diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..6347583 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +*.html linguist-language=javascript diff --git a/.github/issue_template.md b/.github/issue_template.md new file mode 100644 index 0000000..5834ef8 --- /dev/null +++ b/.github/issue_template.md @@ -0,0 +1,12 @@ +Title: 标号-题目-类型 问题简述 + +例子: + +``` +11 - Custom Video Player - readme: LocalStorage 補充 +11 - Custom Video Player - js: const 写法错误 +``` + +说明中最好提供问题所在的具体位置链接,链接获取方法: +1. Markdown 文档下,鼠标移动至你有问题的小标题,点击其左侧的链接图标,复制地址栏的地址即可。如:https://github.com/soyaine/JavaScript30/tree/master/11%20-%20Custom%20Video%20Player#图标切换 +2. 代码文档下,点击某一行左侧标号,复制地址栏地址即可,如 https://github.com/soyaine/JavaScript30/blob/master/11%20-%20Custom%20Video%20Player/index.html#L20 diff --git a/01 - JavaScript Drum Kit/README.md b/01 - JavaScript Drum Kit/README.md index 7fe38a8..1b02d30 100644 --- a/01 - JavaScript Drum Kit/README.md +++ b/01 - JavaScript Drum Kit/README.md @@ -1,6 +1,6 @@ -# 01 JavaScript Dump Kit 中文指南 +# 01 JavaScript Drum Kit 中文指南 -> 作者:©[缉熙Soyaine](https://github.com/soyaine) +> 作者:©[未枝丫](https://github.com/soyaine) > 简介:[JavaScript30](https://javascript30.com) 是 [Wes Bos](https://github.com/wesbos) 推出的一个 30 天挑战。项目免费提供了 30 个视频教程、30 个挑战的起始文档和 30 个挑战解决方案源代码。目的是帮助人们用纯 JavaScript 来写东西,不借助框架和库,也不使用编译器和引用。现在你看到的是这系列指南的第 1 篇。完整指南在 [GitHub](https://github.com/soyaine/JavaScript30),喜欢请 Star 哦♪(^∇^*) ## 实现效果 @@ -92,7 +92,7 @@ audio.play(); ### 如何使页面按钮恢复原状? -利用一个叫 [`transitionened`](https://developer.mozilla.org/zh-CN/docs/Web/Events/transitionend) 的事件,它在 CSS transition 结束后会被触发。我们就可以利用这个事件,在每次打鼓的效果(尺寸变大、颜色变化)完成之后,去除相应样式。 +利用一个叫 [`transitionend`](https://developer.mozilla.org/zh-CN/docs/Web/Events/transitionend) 的事件,它在 CSS transition 结束后会被触发。我们就可以利用这个事件,在每次打鼓的效果(尺寸变大、颜色变化)完成之后,去除相应样式。 在这个页面中,发生 `transition` 的样式属性不止一个(`box-shadow`, `transform`, `border-color`),所以需要添加一个判断语句,使每发生一次按键事件时,只去除一次样式。 @@ -102,4 +102,4 @@ funciton remove(event) { this.classList.remove('playing'); // event.target.classList.remove('playing'); } -```` \ No newline at end of file +```` diff --git a/01 - JavaScript Drum Kit/index-draft.html b/01 - JavaScript Drum Kit/index-draft.html index 1e4bfab..903fcc3 100644 --- a/01 - JavaScript Drum Kit/index-draft.html +++ b/01 - JavaScript Drum Kit/index-draft.html @@ -69,7 +69,7 @@ } function removeTransition(e) { - if(e.propertyName != 'border-left-color') return; + if(e.propertyName !== 'border-left-color') return; this.classList.remove('playing'); } @@ -85,31 +85,30 @@ const keyCode = event.key; if ( keyCode === '76') { - alert("76"); + alert('76'); } else { - alert("false"); + alert('false'); } } - window.addEventListener("keydown", function(e){ + window.addEventListener('keydown', function(e){ const audio = document.querySelector(`audio[data-key="${ e.keyCode }"]`); const key = document.querySelector(`div[data-key="${ e.keyCode }"]`); -// console.log(video); -// console.log(key); + console.log(video); + console.log(key); if(!audio) return; audio.currentTime = 0; audio.play(); - key.classList.add("playing"); -// key.classList.remove("playing"); + key.classList.add('playing'); + // key.classList.remove("playing"); }, false); function removeTransition(e){ -// if(e.propertyName !== "border-left-color") return; + // if(e.propertyName !== "border-left-color") return; console.log(e.propertyName); -// e.target.classList.remove("playing"); + // e.target.classList.remove("playing"); } - const keys = document.querySelectorAll('.key'); keys.forEach( keyin => keyin.addEventListener('transitionend', removeTransition)); diff --git a/02 - JS + CSS Clock/README.md b/02 - JS + CSS Clock/README.md index fa56a74..0ca0415 100644 --- a/02 - JS + CSS Clock/README.md +++ b/02 - JS + CSS Clock/README.md @@ -1,8 +1,11 @@ # 02 纯 JS、CSS 时钟 中文指南 -> 作者:©[缉熙Soyaine](https://github.com/soyaine) +> 作者:©[未枝丫](https://github.com/soyaine) > 简介:[JavaScript30](https://javascript30.com) 是 [Wes Bos](https://github.com/wesbos) 推出的一个 30 天挑战。项目免费提供了 30 个视频教程、30 个挑战的起始文档和 30 个挑战解决方案源代码。目的是帮助人们用纯 JavaScript 来写东西,不借助框架和库,也不使用编译器和引用。现在你看到的是这系列指南的第 2 篇。完整指南在 [GitHub](https://github.com/soyaine/JavaScript30),喜欢请 Star 哦♪(^∇^*) +> 创建时间:2016-12-21 +最后更新:2017-01-06 + ## 实现效果 ![实现效果 by soyaine](https://cl.ly/0y1C2T1z3p2R/Screen%20recording%202016-12-23%20at%2012.30.25%20PM.gif) @@ -18,7 +21,7 @@ 3. 每一秒改变一次指针状态 **涉及到的特性:** -- `transform-oragin` +- `transform-origin` - `transform: rotate()` - `transition` - `transition-timing-function: cubic-bezier(x, x, x, x)` @@ -30,10 +33,10 @@ ### CSS 部分 1. 调整指针的初始位置以及旋转的轴点 - [transform-oragin](https://developer.mozilla.org/en-US/docs/Web/CSS/transform-origin) + [transform-origin](https://developer.mozilla.org/en-US/docs/Web/CSS/transform-origin) ```css - transform-oragin: 100%; // 或者可以用 right + transform-origin: 100%; // 或者可以用 right ``` 2. 调整时钟指针跳动时的过渡效果 @@ -101,5 +104,58 @@ ``` 4. 将角度值赋值给 HTML 元素的 `style` 中的 `transform` 属性 + +## 延伸思考 + +> 2017-01-06 更新完善,感谢 [@cody1991 提的 issue](https://github.com/soyaine/JavaScript30/issues/1) + +此处存在一个小瑕疵,当秒针旋转一圈之后回到初始位置,开始第二圈旋转,角度值的变化时 444° → 90° → 96° .... 这个过程中,指针会先逆时针从 444° 旋转至 90°,再继续我们期望的顺时针旋转,由于秒针变换时间只有 0.05s,所以呈现的效果就是秒针闪了一下,如果想要观察细节,可以将 `.second` 设为 `transition: all 1s`。要解决这个问题,目前找到了两种解决办法: + +#### 方法一 + +在这个特殊点将指针的 `transition` 属性去掉,由于距离短、时间短,将逆时针回旋的过程瞬间完成。 + +```js +if (secondDeg === 90) secHand.style.transition = 'all 0s'; +else secHand.style.transition = 'all 0.05s'; + +if (minDeg === 90) minHand.style.transition = 'all 0s'; +else minHand.style.transition = 'all 0.1s'; +``` + +#### 方法二 + +既然引发问题的是角度的大小变化,那就可以对这个值进行处理。此前的代码中,每秒都会重新 new 一个 Date 对象,用来计算角度值,但如果让这个角度值一直保持增长,也就不会出现逆时针回旋的问题了。 + +这是 @cody1991 提供的思路。只在页面第一次加载时 new 一次 Date 对象,此后每秒直接更新角度值。 + +```js +let secondDeg = 0, +minDeg = 0, +hourDeg = 0; + +function initDate() { + const date = new Date(); + const second = date.getSeconds(); + secondDeg = 90 + (second / 60) * 360; + const min = date.getMinutes(); + minDeg = 90 + (min / 60) * 360 + ((second / 60) / 60) * 360; + const hour = date.getHours(); + hourDeg = 90 + (hour / 12) * 360 + ((min / 60) / 12) * 360 + (((second / 60) / 60) / 12) * 360; +} + +function updateDate() { + secondDeg += (1 / 60) * 360; + minDeg += ((1 / 60) / 60) * 360; + hourDeg += (((1 / 60) / 60) / 12); -大功告成! \ No newline at end of file + secHand.style.transform = `rotate(${ secondDeg}deg)`; + minHand.style.transform = `rotate(${ minDeg }deg)`; + hourHand.style.transform = `rotate(${ hourDeg }deg)`; +} + +initDate(); +setInterval(updateDate, 1000); +``` + +问题解决。大功告成! \ No newline at end of file diff --git a/02 - JS + CSS Clock/index-SOYAINE.html b/02 - JS + CSS Clock/index-SOYAINE.html index d7539e4..af02706 100644 --- a/02 - JS + CSS Clock/index-SOYAINE.html +++ b/02 - JS + CSS Clock/index-SOYAINE.html @@ -53,7 +53,8 @@ position: relative; width: 100%; height: 100%; - transform: translateY(-3px); /* account for the height of the clock hands */ + /* transform: translateY(-3px); /* account for the height of the clock hands */ + /* canceled according to https://github.com/soyaine/JavaScript30/issues/55 */ } .hand { @@ -87,8 +88,6 @@ 0 0 0 2px rgba(0,0,0,0.1), 0 0 10px rgba(0,0,0,0.2); transform: translate(-50%, -50%); - /*transition: all .05s;*/ - } .hour-hand { @@ -104,7 +103,7 @@ width: 45%; height:5px; margin-top: -2.5px; - transition: all .1s; + transition: all .1s cubic-bezier(0.9, 0.54, 0.26, 1.68); } .second-hand { @@ -112,7 +111,7 @@ margin-top: -1px; border-bottom-left-radius: 100%; border-top-left-radius: 100%; - transition: all .05s; + transition: all .05s cubic-bezier(0.9, 0.54, 0.26, 1.68); background-color: red; } @@ -124,28 +123,76 @@ const secHand = document.querySelector('.second-hand'); const minHand = document.querySelector('.min-hand'); const hourHand = document.querySelector('.hour-hand'); - + function setDate() { const date = new Date(); - + const second = date.getSeconds(); - const secondDeg = (90 + (second / 60) * 360) % 360; + const secondDeg = (90 + (second / 60) * 360); const min = date.getMinutes(); - const minDeg = (90 + (min / 60) * 360) % 360; + const minDeg = (90 + (min / 60) * 360); const hour = date.getHours(); const hourDeg = (90 + (hour / 12) * 360 + (min / 12 / 60) * 360);// 加入分钟所占的时间,使时针可以缓慢地移动 + +// 解决指针跳顿问题【第一种方法】 +// 在发生跳顿的角度值处,将 CSS 的 `transition` 属性去掉 + if (secondDeg === 90) secHand.style.transition = 'all 0s'; + else secHand.style.transition = 'all 0.05s cubic-bezier(0.9, 0.54, 0.26, 1.68)'; + + if (minDeg === 90) minHand.style.transition = 'all 0s'; + else minHand.style.transition = 'all 0.1s cubic-bezier(0.9, 0.54, 0.26, 1.68)'; + +// 时针间距过大不做处理 +// if (hourDeg === 116.5) hourHand.style.transition = 'all 0s'; +// else hourHand.style.transition = 'all 3s'; + secHand.style.transform = `rotate(${ secondDeg }deg)`; minHand.style.transform = `rotate(${ minDeg }deg)`; hourHand.style.transform = `rotate(${ hourDeg }deg)`; -// console.log(`${hour}:${min}:${second} - ${hourDeg}:${minDeg}:${secondDeg}` ); + console.log(`${hour}:${min}:${second} - ${hourDeg}:${minDeg}:${secondDeg}` ); } // setDate(); setInterval(setDate, 1000); + + diff --git a/03 - CSS Variables/README.md b/03 - CSS Variables/README.md index 5948bec..e28b206 100644 --- a/03 - CSS Variables/README.md +++ b/03 - CSS Variables/README.md @@ -1,6 +1,6 @@ # 03 CSS Variable -> 作者:©[缉熙Soyaine](https://github.com/soyaine) +> 作者:©[未枝丫](https://github.com/soyaine) > 简介:[JavaScript30](https://javascript30.com) 是 [Wes Bos](https://github.com/wesbos) 推出的一个 30 天挑战。项目免费提供了 30 个视频教程、30 个挑战的起始文档和 30 个挑战解决方案源代码。目的是帮助人们用纯 JavaScript 来写东西,不借助框架和库,也不使用编译器和引用。现在你看到的是这系列指南的第 3 篇。完整指南在 [GitHub](https://github.com/soyaine/JavaScript30),喜欢请 Star 哦♪(^∇^*) ## 实现效果 @@ -98,17 +98,4 @@ ```js document.documentElement.style.setProperty('--base', '#fff'); - ``` - - - - - - - - - - - - - \ No newline at end of file + ``` \ No newline at end of file diff --git a/04 - Array Cardio Day 1/README.md b/04 - Array Cardio Day 1/README.md index 1974b62..ffff200 100644 --- a/04 - Array Cardio Day 1/README.md +++ b/04 - Array Cardio Day 1/README.md @@ -1,6 +1,6 @@ -# 04 Array Cardio 💪 指南 +# 04 Array Cardio 💪 指南一 -> 作者:©[缉熙Soyaine](https://github.com/soyaine) +> 作者:©[Soyaine](https://github.com/soyaine) > 简介:[JavaScript30](https://javascript30.com) 是 [Wes Bos](https://github.com/wesbos) 推出的一个 30 天挑战。项目免费提供了 30 个视频教程、30 个挑战的起始文档和 30 个挑战解决方案源代码。目的是帮助人们用纯 JavaScript 来写东西,不借助框架和库,也不使用编译器和引用。现在你看到的是这系列指南的第 4 篇。完整指南在 [GitHub](https://github.com/soyaine/JavaScript30),喜欢请 Star 哦♪(^∇^*) ## 实现效果 @@ -23,11 +23,11 @@ console.table(thing) 1. 筛选 16 世纪出生的发明家 2. 展示他们的姓和名 -3. 把他们按照年龄从大到小进行排序 +3. 把他们按照出生日期从大到小进行排序 4. 计算所有的发明家加起来一共活了多少岁 5. 按照他们活了多久来进行排序 6. 筛选出一个网页里含有某个词语的标题 -7. 按照姓氏来对发明家进行排序 +7. 按照姓氏来进行排序 8. 统计给出数组中各个物品的数量 ## 相关知识 diff --git a/04 - Array Cardio Day 1/index-FINISHED.html b/04 - Array Cardio Day 1/index-FINISHED.html index e61b94c..7e3c68f 100644 --- a/04 - Array Cardio Day 1/index-FINISHED.html +++ b/04 - Array Cardio Day 1/index-FINISHED.html @@ -27,7 +27,7 @@ { first: 'Hanna', last: 'Hammarström', year: 1829, passed: 1909 } ]; - const people = ['Beck, Glenn', 'Becker, Carl', 'Beckett, Samuel', 'Beddoes, Mick', 'Beecher, Henry', 'Beethoven, Ludwig', 'Begin, Menachem', 'Belloc, Hilaire', 'Bellow, Saul', 'Benchley, Robert', 'Benenson, Peter', 'Ben-Gurion, David', 'Benjamin, Walter', 'Benn, Tony', 'Bennington, Chester', 'Benson, Leana', 'Bent, Silas', 'Bentsen, Lloyd', 'Berger, Ric', 'Bergman, Ingmar', 'Berio, Luciano', 'Berle, Milton', 'Berlin, Irving', 'Berne, Eric', 'Bernhard, Sandra', 'Berra, Yogi', 'Berry, Halle', 'Berry, Wendell', 'Bethea, Erin', 'Bevan, Aneurin', 'Bevel, Ken', 'Biden, Joseph', 'Bierce, Ambrose', 'Biko, Steve', 'Billings, Josh', 'Biondo, Frank', 'Birrell, Augustine', 'Black Elk', 'Blair, Robert', 'Blair, Tony', 'Blake, William']; + const people = ['Beck, Glenn', 'Becker, Carl', 'Beckett, Samuel', 'Beddoes, Mick', 'Beecher, Henry', 'Beethoven, Ludwig', 'Begin, Menachem', 'Belloc, Hilaire', 'Bellow, Saul', 'Benchley, Robert', 'Benenson, Peter', 'Ben-Gurion, David', 'Benjamin, Walter', 'Benn, Tony', 'Bennington, Chester', 'Benson, Leana', 'Bent, Silas', 'Bentsen, Lloyd', 'Berger, Ric', 'Bergman, Ingmar', 'Berio, Luciano', 'Berle, Milton', 'Berlin, Irving', 'Berne, Eric', 'Bernhard, Sandra', 'Berra, Yogi', 'Berry, Halle', 'Berry, Wendell', 'Bethea, Erin', 'Bevan, Aneurin', 'Bevel, Ken', 'Biden, Joseph', 'Bierce, Ambrose', 'Biko, Steve', 'Billings, Josh', 'Biondo, Frank', 'Birrell, Augustine', 'Black, Elk', 'Blair, Robert', 'Blair, Tony', 'Blake, William']; // Array.prototype.filter() // 1. Filter the list of inventors for those who were born in the 1500's diff --git a/04 - Array Cardio Day 1/index-SOYAINE.html b/04 - Array Cardio Day 1/index-SOYAINE.html index 6de312b..e56eb6a 100644 --- a/04 - Array Cardio Day 1/index-SOYAINE.html +++ b/04 - Array Cardio Day 1/index-SOYAINE.html @@ -6,11 +6,9 @@

请按 F12 查看 Console 面板 💁

-

若无结果请刷新试试

+

若无结果请刷新试试

diff --git a/05 - Flex Panel Gallery/README.md b/05 - Flex Panel Gallery/README.md new file mode 100644 index 0000000..90a1a04 --- /dev/null +++ b/05 - Flex Panel Gallery/README.md @@ -0,0 +1,132 @@ +# 05 Flex 实现可伸缩的图片墙 中文指南 + +> 作者:©[未枝丫](https://github.com/soyaine) +> 简介:[JavaScript30](https://javascript30.com) 是 [Wes Bos](https://github.com/wesbos) 推出的一个 30 天挑战。项目免费提供了 30 个视频教程、30 个挑战的起始文档和 30 个挑战解决方案源代码。目的是帮助人们用纯 JavaScript 来写东西,不借助框架和库,也不使用编译器和引用。现在你看到的是这系列指南的第 5 篇。完整指南在 [GitHub](https://github.com/soyaine/JavaScript30),喜欢请 Star 哦♪(^∇^*) + +## 实现效果 + +![可伸缩的图片墙演示](https://cl.ly/1X1A320o0x1T/Screen%20recording%202016-12-31%20at%2010.06.10%20AM.gif) + +点击任意一张图片,图片展开,同时从图片上下两方分别移入文字。点击已经展开的图片后,图片被压缩,同时该图片上下两端的文字被挤走。若图片加载不出来,[请点链接看更完整的演示图片](https://d17oy1vhnax1f7.cloudfront.net/items/3J2r2G0p0C0h0q2c3R3p/Screen%20recording%202016-12-30%20at%2005.33.01%20PM.gif),在线效果[请点这里。](http://soyaine.cn/JavaScript30/05%20-%20Flex%20Panel%20Gallery/index-SOYAINE2.html) + +初始文档的 DOM 结构:以 `.panels` 为父 `div` 之下,有 5 个类名为 `.panel` 的 `div`,这 5 个各含有 3 个子 `p` 标签。而相应的 CSS 样式中,动画时间等特性已经设定好,只需要完成不同状态下的页面布局以及事件监听即可。 + +## 涉及特性 + +- display: flex + - flex-direction + - justify-content + - align-items +- transform: translateX/translateY +- element.classList.toggle() +- transitionend 事件 + +## 过程指南 + +### CSS 部分 + +CSS 在这个过程中占了重点,运用 `flex` 可以使各个元素按一定比例占据页面。在调试的时候,可以把边框显示出来方便查看效果。(`border: 1px solid #f00;`) + +1. 将 `.panels` 设置为 `display:flex` +2. 设定每个子 panel 的 `flex` 值为 1 +3. 针对每个子 panel,设为 `display:flex`,设置其 flex 主轴方向 +4. 控制 `.panle` 的子元素 `

` 中的文字垂直、水平居中(单独看每个 panel,其中的文字也可以用 flex 的思路来使其三等分后居中) + 1. 设置为 `display:flex` + 2. 设置 `flex` 值 + 2. 设置其子元素的布局方式:垂直水平居中(沿主轴、侧轴居中) +4. 设定点击图片后文字移动的样式 +5. 设定点击图片展开后的图片的 `flex` 值 + +### JS 部分 + +1. 获取所有类名为 `panel` 的元素 +2. 为其添加 `click` 事件监听,编写触发事件调用的函数(给触发的 DOM 元素添加/去掉样式,实现拉伸/压缩的效果) +3. 为其添加 `transitionend` 事件监听,编写调用的函数(添加/去掉样式,实现文字的飞入/飞出效果) + +## 相关知识 + +### [Flexbox](https://developer.mozilla.org/zh-CN/docs/Web/CSS/CSS_Flexible_Box_Layout/Using_CSS_flexible_boxes) + +![MDN flexbox 图示](https://mdn.mozillademos.org/files/12998/flexbox.png) + +这一个挑战的关键部分就在于理解如何使用 Flexbox,挑战的文档里嵌套了三个 flex 容器,作为弹性盒子,它们各自的作用是: + +- `.panels`:使其中的 `.panel` 按横向的 flex 等分排布(此处为五等分) +- `.panel`:使其中的 `

` 按纵向的 flex 等分排布(此处为三等分) +- `p` :借用 flex 相对于主轴及侧轴的对齐方式,使其中的文字垂直水平居中 + +这里容易混淆的是不同 CSS 属性的应用对象,想区分很简单,只需记住针对容器内子元素的特性较少(只有 5 个),可以这样联想:针对某一个具体的小元素进行设置,可供发挥的空间比较少,而针对 Flex 容器本身,有统筹大局的责任,故特性多一些。下面简单介绍一些基本的特性(没有完全列出)。 + +#### 针对 Flex items 的特性(Children) + +- `flex-growth`:伸展值 +- `flex-shrink`:可接受的压缩值 +- `flex-basis`:元素默认的尺寸值 +- `flex`:以上三个值按顺序的缩写 + +#### 针对 Flex container 的特性(Parent) + +- `display: flex`:将这个元素设置成弹性盒子 +- `flex-direction`:主轴方向 + - `row`:横向 + - `column`:纵向 +- `justify-content`:沿主轴的的对齐方式 +- `align-items`:沿侧轴的对齐方式 +- `align-content`:子元素中文本沿侧轴的对齐方式(只有一行时无效) + +可以在下面几个地方试一下 Flex 的各种特性: + +- [http://demo.agektmr.com/flexbox/](http://demo.agektmr.com/flexbox/) +- [http://the-echoplex.net/flexyboxes/](http://the-echoplex.net/flexyboxes/) +- [http://codepen.io/justd/pen/yydezN](http://codepen.io/justd/pen/yydezN) + +## 延伸思考 + +在 index-FINISHED.html 的解决方案中,用了两种 `class` 值来分别控制 `div` 元素和 `p` 元素的动画,这就会造成一个问题,当快速点击两下时,会出现相反的组合(图片缩小 + 上下文字出现)。 + +那为什么还要将文字的移动动画用 `.open-actived` 这个类来控制,同时还多加上了一个 `transitionend` 的事件监听,而不是直接用 `.open` 控制文字的移动,并且只采用一个 `click` 事件监听呢? + +我试了一下,发现如果将要触发的文字移动(`transform`)用 `.open` 来控制,那么会出现有点不协调的状况。 + +要找到问题所在,可以先研究一下动画效果,由于录 GIF 很容易掉帧,最好打开网页来看细节。 + +当拉伸图片时,首先往里压缩(阶段①),然后再展开(阶段②),而文字是阶段②出现的;而当压缩图片时,也是同样的道理,先微微拉开一点(阶段①),然后再往里缩(阶段②),文字也是在阶段②才往上移动的,这样就形成了一种被 pia 飞的效果。 + +这样也就可以回答我最开始的疑问,为何要多添加一个 [`transitioned` 的事件监听](https://developer.mozilla.org/zh-CN/docs/Web/Events/transitionend),这个事件会在 `transition` 结束之后被触发,所以目的是先让图片的压缩拉伸完成,再移动文字。 + +也就是说,如果除去字体大小的变化,具体的动画细节其实是这样的: +- 图片展开:微微压缩一段距离 -> 展开图片 -> 文字向中心移动 +- 图片压缩:微微展开一段距离 -> 压缩图片 -> 文字向上下移动 + +这就解释了为什么我改动之后出现了不协调,此时看到的动画,像是文字主导了图片的压缩伸展,原因就是文字动画的时机不太对,找到了这个原因,就很好解决了。(见 [index-SOYAINE2.html](https://github.com/soyaine/JavaScript30/blob/master/05%20-%20Flex%20Panel%20Gallery/index-SOYAINE2.html)) + +```css +.panel > * { + /* ... */ + transition:transform 0.5s 0.7s; +} + +/* 修改 .open-actived -> .open*/ +.panel.open p:first-child { + transform: translateY(0); +} + +.panel.open p:last-child { + transform: translateY(0); +} +``` + +```js +const panels = document.querySelectorAll('.panel'); + +function toggleOpen(e) { + this.classList.toggle('open'); +} + +panels.forEach( panel => panel.addEventListener('click', toggleOpen, false)); +// 去掉对于 transitionend 的事件监听 +``` + +解决思路是让 `p` 标签的文字动画效果延迟一下,添加 `transition` 属性的 `delay` 值,使其到图片变换的阶段②再发生,此处我选用了图片的动画最长时间 0.7s,圆满解决。 + +**挑战 5 Pass ~\(≧▽≦)/~** \ No newline at end of file diff --git a/05 - Flex Panel Gallery/index-FINISHED.html b/05 - Flex Panel Gallery/index-FINISHED.html new file mode 100644 index 0000000..243f8a2 --- /dev/null +++ b/05 - Flex Panel Gallery/index-FINISHED.html @@ -0,0 +1,145 @@ + + + + + Flex Panels 💪 + + + + + + +

+
+

Hey

+

Let's

+

Dance

+
+
+

Give

+

Take

+

Receive

+
+
+

Experience

+

It

+

Today

+
+
+

Give

+

All

+

You can

+
+
+

Life

+

In

+

Motion

+
+
+ + + + + diff --git a/05 - Flex Panel Gallery/index-SOYAINE.html b/05 - Flex Panel Gallery/index-SOYAINE.html new file mode 100644 index 0000000..4606f8f --- /dev/null +++ b/05 - Flex Panel Gallery/index-SOYAINE.html @@ -0,0 +1,158 @@ + + + + + Flex Panels 💪 + + + + + + +
+
+

Hey

+

Let's

+

Dance

+
+
+

Give

+

Take

+

Receive

+
+
+

Experience

+

It

+

Today

+
+
+

Give

+

All

+

You can

+
+
+

Life

+

In

+

Motion

+
+
+ + + + + \ No newline at end of file diff --git a/05 - Flex Panel Gallery/index-SOYAINE2.html b/05 - Flex Panel Gallery/index-SOYAINE2.html new file mode 100644 index 0000000..11a778f --- /dev/null +++ b/05 - Flex Panel Gallery/index-SOYAINE2.html @@ -0,0 +1,147 @@ + + + + + 改进后 - Flex Panels 💪 + + + + +
+
+

Hey

+

Let's

+

Dance

+
+
+

Give

+

Take

+

Receive

+
+
+

Experience

+

It

+

Today

+
+
+

Give

+

All

+

You can

+
+
+

Life

+

In

+

Motion

+
+
+ + + + + diff --git a/05 - Flex Panel Gallery/index-START.html b/05 - Flex Panel Gallery/index-START.html new file mode 100644 index 0000000..04e974b --- /dev/null +++ b/05 - Flex Panel Gallery/index-START.html @@ -0,0 +1,119 @@ + + + + + Flex Panels 💪 + + + + + + +
+
+

Hey

+

Let's

+

Dance

+
+
+

Give

+

Take

+

Receive

+
+
+

Experience

+

It

+

Today

+
+
+

Give

+

All

+

You can

+
+
+

Life

+

In

+

Motion

+
+
+ + + + + + + + + + diff --git a/06 - Type Ahead/README.md b/06 - Type Ahead/README.md new file mode 100644 index 0000000..8a1f093 --- /dev/null +++ b/06 - Type Ahead/README.md @@ -0,0 +1,141 @@ +# 06 Fetch 结合 filter 实现快速匹配古诗 + +> 作者:©[未枝丫](https://github.com/soyaine) +> 简介:[JavaScript30](https://javascript30.com) 是 [Wes Bos](https://github.com/wesbos) 推出的一个 30 天挑战。项目免费提供了 30 个视频教程、30 个挑战的起始文档和 30 个挑战解决方案源代码。目的是帮助人们用纯 JavaScript 来写东西,不借助框架和库,也不使用编译器和引用。现在你看到的是这系列指南的第 6 篇。完整指南在 [GitHub](https://github.com/soyaine/JavaScript30),喜欢请 Star 哦♪(^∇^*) + +## 实现效果 + +![仿即时搜索诗句效果](https://cl.ly/0b360y270s0f/Screen%20recording%202016-12-31%20at%2010.05.23%20PM.gif) + +在输入框中输入一个词,迅速匹配,展示含有这个词的诗句,诗句的来源 json 数据是加载页面时从网络中异步获得。[在线效果请查看。](http://soyaine.cn/JavaScript30/06%20-%20Type%20Ahead/index-SOYAINE.html) + +初始文档中提供了 HTML 和 CSS,我们需要补全 JS 代码。这个挑战是 Ajax 的预热练习,在异步方面用到了一些目前还未被完全支持的新特性,但很好用。 + +原文档中选的内容是英文城市名,我将其换成了唐诗,构造了一个含有 70 多首唐诗的 JSON 数据,访问地址是 [https://gist.githubusercontent.com/soyaine/81399bb2b24ca1bb5313e1985533c640/raw/bdf7df2cbcf70706c4a5e51a7dfb8c933ed78878/TangPoetry.json](https://gist.githubusercontent.com/soyaine/81399bb2b24ca1bb5313e1985533c640/raw/bdf7df2cbcf70706c4a5e51a7dfb8c933ed78878/TangPoetry.json),请自由取用。 + +## 涉及特性 + +- Promise + - `fetch()` + - `then()` + - `json()` +- Array + - `filter()` + - `map()` + - `push()` + - `join()` + - Spread syntax 扩展语句 +- RegExp + - `match()` + - `replace()` + +## 过程指南 + +1. 声明一个空数组,用于存放解析 json 后的数据 +2. 运用 `fetch()` 发送 HTTP 请求 + 1. 获取返回的 Promise 对象 + 2. 解析 JSON 数据 + 3. 存入数组 +3. 获取两个主要 HTML 元素(``,`