# Javascript and Animation Studies ## Community Statement * It's less about Crafts but more about Creativty. * Less about Coding but more about Thinking. * Inspiration & Personal Heros * https://taliacotton.com/ * https://compform.net/introduction/ * http://www.thegreeneyl.com/ * http://yhsong.com/ * https://yuinchien.com/ * https://antonandirene.com/ * https://studiodumbar.com/ * https://www.joycenho.com/ * http://zz-is.it/ * http://www.generative-gestaltung.de/2/ ## Resources https://developers.google.com/web ## JS libraries * CSS Animation * Anime.js * JQuery * Scroll Reveal * Physical Engine * Matter.js - tutorial - 欣葶 * https://www.youtube.com/watch?v=urR596FsU68&list=PLRqwX-V7Uu6bLh3T_4wtrmVHOrOEM1ig_&index=1 * 2D (HTML Canvas) * Paper.js * Pts.js – Creative Coding * P5.js * Sound * Tone.js - 靜儀 * Data Viz * D3.js - tutorial - 璦翎 * https://www.coursera.org/learn/information-visualization-programming-d3js * 3D/WebGL * Three.js - 怡萱 * http://test.domojyun.net/MEMO/3D/threejs.html * https://ithelp.ithome.com.tw/articles/10192566 * Aframe.io (VR/AR) * Machine Learning * Ml5js # Week1: HTML+CSS+JS ### HTML, CSS, JS http://m105.nthu.edu.tw/~s105011127/spin/ ### Environment * Code: VSCode * FileZilla: mxxx.nthu.edu.tw ### 進行方式 * 分周次講不同的js * Care 設計的部分 * 不Care 程式太複雜的地方:資料結構或優化效能(除非電腦會燒起來) * 不會因為你沒研究出來就生氣 ### Hello Website ```html= <!DOCTYPE html> <html> <head> <title>Page Title</title> </head> <body> <h1>This is a Heading</h1> <p>This is a paragraph.</p> </body> </html> ``` ### CSS 進來! ```css= <link rel="stylesheet" href="styles.css"> ``` ### 編碼 ```css= @charset "utf-8"; <meta charset="utf-8"> ``` ### 字體 https://fonts.google.com/specimenTab?standard-styles ```css= <link rel="preconnect" href="https://fonts.gstatic.com"> <link href="https://fonts.googleapis.com/css2?family=Oswald:wght@335;432&display=swap" rel="stylesheet"> font-family: 'Oswald', sans-serif; ``` ### CSS https://www.w3schools.com/css/default.asp ### CSS Animation ```css= animation: animaionName 1s infinite; @keyframe{ 0%{} 100%{} } ``` ### nth-child() ```css= p:nth-child(odd){}; P:nth-child(even){}; ``` ### hover() ```css= p:hover{}; ``` ### Jquery Library ```html= <script src="https://code.jquery.com/jquery-1.12.4.js"></script> <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script> <script src="???.js"></script> ``` ### p5.js ```html= <script src="https://cdn.jsdelivr.net/npm/p5@1.3.1/lib/p5.js"></script> <script src="???.js"></script> ``` ### 今天的code連結 > https://drive.google.com/file/d/1nxGW08DQHclUkEUemtYhCmSe7SmKGucX/view?usp=sharing # Week2: CSS Advanced ### CSS Advanced #### Box ![](https://i.imgur.com/61llFpM.png) https://www.w3schools.com/css/css_border.asp Intro * CSS Borders * CSS Lists * CSS Position * CSS z-index * CSS Overflow * CSS Float * CSS Pseudo-classes (before, after) https://w3c.hexschool.com/blog/5667df85 * CSS Navigation Bar * CSS Dropdown * CSS Website Layout Advanced * Rounded Corners * Gradients * Shadows * Text Effects * 2D Transforms * 3D Transforms * RWD Intro vs AWD https://medium.com/@282714/%E4%B8%8D%E6%9C%83%E5%AF%ABcss%E4%B9%9F%E8%83%BD%E6%87%82-%E5%A6%82%E4%BD%95%E9%81%B8%E6%93%87rwd%E9%82%84%E6%98%AFawd-2b4057e92d4 * RWD Viewport * RWD Grid View * RWD Media Queries * RWD Framework ## Sass Sass syntax / Scss ![](https://i.imgur.com/TQGrJjt.png) 在VScode內有我們的好朋友:Live Sass Compiler https://sass-lang.com/documentation/at-rules/function #### Hello World **css** ```css= .nav{ background: #ccc; } .nav li { display: inline-block; } .nav li a{ display: block; padding: 15px; text-decoration: none; color: #000; } .nav li img{ width: 100%; } ``` **sass** ```sass= .nav background: #ccc li display: inline-block a display: block padding: 15px text-decoration: none color: #000 img width: 100% ``` **scss** ```sass= .nav{ background: #ccc; li { display: inline; a { display: block; padding: 15px; text-decoration: none; color: #000; } img { width: 100%; } } } ``` # Week3: SCSS + JS Intro SCSS is our good friend, who is a close neighbor to CSS, who is an annoying shit. ## Variable **css** ```css= body { font: 100% Helvetica, sans-serif; color: #333; } ``` **sass** ```sass= $font-stack: Helvetica, sans-serif $primary-color: #333 body font: 100% $font-stack color: $primary-color ``` **scss** ```sass= $font-stack: Helvetica, sans-serif; $primary-color: #333; body { font: 100% $font-stack; color: $primary-color; } ``` ## Function 除了變數之外,讓開發 Sass 更像在寫程式的特性就是 function 了,可以將重複使用的長度、大小計算等邏輯,抽象化成 function 的形式,如下面例子是使用 function 的 SCSS:‍ 語法: `@function $var(args){ @return }` `$var`為自定義變數,後綴加上一個以上的參數`args`,通常作為計算用途。 **scss** ```sass= @function pow($base, $exponent) { $result: 1; @for $_ from 1 through $exponent { $result: $result * $base; } @return $result; } .sidebar { float: left; margin-left: pow(4, 3) * 1px; } ``` ### for loop 語法: `@for` $var `from` Num1 `through/to` Num2 `$var` 可以自定義變數,每次回傳數字類型的結果。 `through` 包含Num2在內的範圍 `to` 不包含Num2在內,例如1 `to` 24只會回傳到23為止 ```sass= @for $i from 0 through 24 { .flex_#{$i} { flex: $i; } } ``` ### each 語法: `@each` $var `in` Array `$var`可以自定義變數,每次回傳Array對應的值。 Array 陣列,可以直接在`in`的後面接'icon_1', 'icon_2'... 或者直接另外定義變數存放: ```sass= $iconSet: ['icon_1', 'icon_2', 'icon_3']; ``` **scss** ```sass= $iconSet: ['icon_1', 'icon_2', 'icon_3']; @each $currentIcon in $iconSet { .icon_#{$currentIcon} { background: url('../img/#{$currentIcon}.svg') no-repeat center; } } ``` **css** ```css= /* 編譯後的結果 */ .icon_icon_1 { background: url("../img/icon_1.svg") no-repeat center; } .icon_icon_2 { background: url("../img/icon_2.svg") no-repeat center; } .icon_icon_3 { background: url("../img/icon_3.svg") no-repeat center; } ``` ### if 語法: `@if` $var `==` value `(and, or)`(value2) `==` 等於 `>` 大於 `>=` 大於或等於 `<` 小於 `<=` 小於或等於 `!=` 不等於 `and` 以及 `or` 或者 ```sass= @for $i from 0 through 3 { .flex_#{$i} { flex: $i; @if $i == 0 { height: 100%; } @else if $i >= 2 { color: #fff; } @else if $i != 3 { color: #333; } } } ``` **css** ```css= /* 編譯後的結果 */ .flex_0 { flex: 0; height: 100%; /* $i = 0 時加入的條件 */ color: #333; /* $i 不等於 3 時加入的條件 */ } .flex_1 { flex: 1; color: #333; /* $i 不等於 3 時加入的條件 */ } .flex_2 { flex: 2; color: #fff; /* $i 符合大於或等於 2 的條件 */ color: #333; /* $i 符合不等於 3 的條件 */ } .flex_3 { flex: 3; color: #fff; } ``` 看得出來$i = 2時color被編譯了兩次結果對吧? 而瀏覽器會以最後一個結果為主,這就可能造成不是我們要的樣式覆蓋了正確的樣式,也會讓編譯資源佔據不少垃圾影響效能。 ## Nesting **scss** ```sass= nav { ul { margin: 0; padding: 0; list-style: none; } li { display: inline-block; } a { display: block; padding: 6px 12px; text-decoration: none; } } ``` **css** ```css= nav ul { margin: 0; padding: 0; list-style: none; } nav li { display: inline-block; } nav a { display: block; padding: 6px 12px; text-decoration: none; } ``` ## Mixins 當有一段 CSS 設定經常性地被重複使用,甚至可以根據不同「參數」對應出相似的樣式,就可以將這段設定獨立寫成一個 mixin 方便取用,參考下面的例子: **scss** ```sass= @mixin square($size, $radius: 0) { width: $size; height: $size; @if $radius != 0 { border-radius: $radius; } } .avatar { @include square(100px, $radius: 4px); } .card { @include square(300px, $radius: 2px); } ``` **css** ```css= .avatar { width: 100px; height: 100px; border-radius: 4px; } .card { width: 300px; height: 300px; border-radius: 2px; } ``` ## Extends 有一種狀況是當有一個選擇器需要包含另一個選擇器中的所有樣式,或是許多選擇器具有相同樣式時,為了避免要一直重寫同一組相同的 CSS 樣式,在 Sass 中我們可以使用 Extends 的寫法。 上面這段話稍微有點抽象,換句話說就是 Extends 可以將所有相同樣式的內容合併,直接舉個例子: **scss** ```sass= %message-shared { border: 1px solid #ccc; padding: 10px; color: #333; } %equal-heights { display: flex; flex-wrap: wrap; } .message { @extend %message-shared; } .success { @extend %message-shared; border-color: green; } .error { @extend %message-shared; border-color: red; } .warning { @extend %message-shared; border-color: yellow; } ``` **css** ```css= .warning, .error, .success, .message { border: 1px solid #ccc; padding: 10px; color: #333; } .success { border-color: green; } .error { border-color: red; } .warning { border-color: yellow; } ``` ## Flexbox ```css= .container { display: flex; flex-direction: row; /* 預設值是row,代表橫向排列,column則是垂直 */ } ``` ![](https://i.imgur.com/JSB4TiR.png) ### 利用mixin和extend的flexbox **scss** ```sass= .container { width: 100%; height: auto; } @mixin flexBox($direction) { display: flex; flex-direction: $direction; } @mixin flexAlign($alignItems, $justifyContent) { align-items: $alignItems; justify-content: $justifyContent; } .new-container { @include flexBox(column); @include flexAlign(flex-start, flex-start); @extend .container; } ``` **css** ```css= .container, .new-container { width: 100%; height: auto; } .new-container { display: flex; flex-direction: column; align-items: flex-start; justify-content: flex-start; } ``` ## data-attribute **html** ```html= <div class="tab__container" data-panel-count="1">...</div> ``` 而且你還試圖去Google了程式碼中的data-panel-count卻發現根本找不到任何解答對吧?正常,因為「data-」之後那串字都是我們工程師自己命名的你當然找不到! data-attribute原意是HTML5中提供給開發人員做選擇器之類的用途,不僅是Javascript可以任意調用,CSS也一樣可以: **CSS** ```css= .container[data-width="10rem"] { width: 10rem; } .container[data-inset="0.5rem"] { box-sizing: border-box; padding: 0.5rem; } ``` **SASS: Function** ```sass= @for $i form 0 through 20 { /* #{} 的字符代表連接變數使用,{}中可以有運算式 */ [data-inset="#{$i * 0.1}rem"] { padding: #{$i * 0.1}rem; } } ``` ## CSS Grid https://kanboo.github.io/2018/06/27/CSS-Grid/ ## Interactivity ### DOM 文件物件模型 (DOM) 文件物件模型(Document Object Model, DOM)是 HTML、XML 和 SVG 文件的程式介面。它提供了一個文件(樹)的結構化表示法,並定義讓程式可以存取並改變文件架構、風格和內容的方法。DOM 提供了文件以擁有屬性與函式的節點與物件組成的結構化表示。節點也可以附加事件處理程序,一旦觸發事件就會執行處理程序。 本質上,它將網頁與腳本或程式語言連結在一起。 ### Library ```html= <script src="https://code.jquery.com/jquery-1.12.4.js"></script> <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script> <script src="???.js"></script> ``` ### Mouse X, Mouse Y in JS/CSS ### Variable & Constants: ```javascript= var name= "John"; ///很爛不要用它 let lastName = 'Doe'; ///可以改動的值 const version= '1.3'; ///cannot be changed ``` ### Mouse-x, Mouse-y **HTML** ```html= <div class="mover"></div> ``` **JS** ```javascript= let root = document.documentElement; root.addEventListener("mousemove", e => { root.style.setProperty('--mouse-x', e.clientX + "px"); root.style.setProperty('--mouse-y', e.clientY + "px"); }); ``` **SCSS** ```sass= .mover { width: 50px; height: 50px; background: red; position: absolute; left: var(--mouse-x); top: var(--mouse-y); } ``` ### Mouse Background **HTML** ```html= <div class="module" id="module"> </div> ``` **SCSS** ```sass= .module { width: 300px; height: 300px; border: 1px solid white; background-image: url(https://images.unsplash.com/photo-1499162526249-f5b8b9ba9923?ixlib=rb-0.3.5&q=85&fm=jpg&crop=entropy&cs=srgb&ixid=eyJhcHBfaWQiOjE0NTg5fQ&s=865bf5c0b77ceb22e88de9fd41c5a671); background-size: 1000px; } body { height: 100vh; margin: 0; display: flex; justify-content: center; align-items: center; background: #000; } ``` **JS** ```javascript= $(document).ready(function(){ const el = document.querySelector("#module"); el.addEventListener("mousemove", (e) => { el.style.backgroundPositionX = -e.offsetX + "px"; el.style.backgroundPositionY = -e.offsetY + "px"; }); }); ``` ![](https://i.imgur.com/tvvEHkO.png) ### 上傳FileZilla ### Further Studies https://css-tricks.com/lets-make-one-of-those-fancy-scrolling-animations-used-on-apple-product-pages/?fbclid=IwAR38t8JjS-qL4gHKuEyYTiKLjNFhSulale6XJliH5LpW1Z9ky8AGRBlcnBA https://css-tricks.com/adding-particle-effects-to-dom-elements-with-canvas/?fbclid=IwAR3kbVZ99KEl_eYqCkSFL8jsUFgTJQEApgN0mZbuOPAJ-QZfUx9uPSxnjis ### Next Week http://www.generative-gestaltung.de/ # Week4: Animation Magic! http://m105.nthu.edu.tw/~s105011127/FreeFridayForum/ We will review several ways to acheive the effect we want using CSS, JS and extended libraries. ## CSS vs JS vs Jquery vs JS libraries HTML Boilerplate ```html= <link rel="stylesheet" href="main.css"> <script src="script.js"></script> ``` ### CSS Transition +JS **html** ```html= <div class="box"></div> ``` **scss** ```scss= .box{ width:100px; height: 100px; background: #00FF00; transform: translate(0,0); transition: transform 500ms; } .move{ transform:translate(100px, 100px); } ``` **js** ```javascript= var box = document.querySelector('.box'); box.addEventListener('click', function() { box.classList.toggle('move'); }); ``` **import** ```html= <script src="https://code.jquery.com/jquery-1.12.4.js"></script> <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script> ``` ### CSS Animation **SASS** ```CSS= animation: movingBox 1300ms infinite alternate; @keyframes movingBox { 0% { transform: translate(0, 0); opacity: 0.3;} 25% { opacity: 0.9;} 50% { transform: translate(100px, 100px); opacity: 0.2;} 100% { transform: translate(30px, 30px); opacity: 0.8;} } ``` ## JS Manipulating CSS ```javascript= var target = document.querySelector('.box'); var player = target.animate([ {transform: 'translate(0)'}, {transform: 'translate(100px, 100px)'} ], 500); player.addEventListener('finish', function() { target.style.transform = 'translate(100px, 100px)'; }); ``` ## Only JS ```javascript= var id = null; var box = document.querySelector('.box'); box.addEventListener('click', function () { myMove(); }); function myMove() { var elem = document.querySelector(".box"); var pos = 0; clearInterval(id); id = setInterval(frame, 10); function frame() { if (pos == 100) { clearInterval(id); } else { pos++; elem.style.top = pos + 'px'; elem.style.left = pos + 'px'; } } } ``` :::success 以下是我們真正的好朋友! ::: ## Best Friends 1: CSS library https://animate.style/ import ```html= <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css"/> ``` easy use **HTML** ```html= <div class="animate__animated animate__bounce"></div> ``` **CSS** ```css= .box{ animation: bounce 2s; } ``` ```javascript= const animateCSS = (element, animation, prefix = 'animate__') => // We create a Promise and return it new Promise((resolve, reject) => { const animationName = `${prefix}${animation}`; const node = document.querySelector(element); node.classList.add(`${prefix}animated`, animationName); // When the animation ends, we clean the classes and resolve the Promise function handleAnimationEnd(event) { event.stopPropagation(); node.classList.remove(`${prefix}animated`, animationName); resolve('Animation ended'); } node.addEventListener('animationend', handleAnimationEnd, { once: true }); }); ``` ```javascript= animateCSS('.box', 'bounce'); ``` |屬性 |說明| |---|---| |animation-name| 動畫名稱| |animation-duration| 動畫持續時間,預設 0,單位 s 或 ms。| |animation-delay| 動畫延遲播放時間,預設 0,單位 s 或 ms。| |animation-iteration-count| 動畫播放次數,預設 1。其他還有 infinite...| |animation-timing-function| 動畫加速度函式,預設 ease。其他還有: linear、ease-in、ease-out、ease-in-out、step-start、step-end、steps(int,start/end)、cubic-bezier(n,n,n,n)。| |animation-direction| 動畫播放方向,預設 normal。其他還有 reverse、alternate、alternate-reverse。| |animation-fill-mode| 動畫播放前後模式,預設 none。其他還有 forwards、backwards、both。| animation-play-state| 動畫播放或暫停狀態,預設 running。其他還有 paused。| ## Best Friend 2: AOJ 除了滑鼠觸發(上周我們有做過)之外,另一個網頁常見的觸發方式,就是Scroll,想不想做出這種效果:https://www.youtube.com/watch?v=ptfUwPJbGlQ https://michalsnik.github.io/aos/ ## Visualization Options SVG * https://codepen.io/aurer/pen/jEGbA * https://codepen.io/ghepting/pen/xnezB 教學 * https://blog.techbridge.cc/2019/11/06/svg-animation-in-10mins/?fbclid=IwAR3n3WQ3bO1LkbjXWgI2LHo_bS1iB_tNnZJhxl3n2t19JaSfrGE2ahsHDfw Canvas * https://codepen.io/ge1doot/details/vOYOVz * https://codepen.io/soulwire/details/Ffvlo WebGL * https://epok.tech/work/tendrils/ * https://codepen.io/shubniggurath/pen/XWpYpON ## P5 is your best CANVAS friend ```html= <script src="https://cdn.jsdelivr.net/npm/p5@1.3.1/lib/p5.js"></script> ``` ## SVG and Friends # Week5: Animation & Your Friend Javascript ## JS Intros ## Statement & Variable ```javascript= let quantity = 3; let number = 0.75; let string = 'Hi, Ivy!'; let boolean = true; ``` ## Change Content **html** ```html= <h1>Elderflower</h1> <div id="content"> <h2>Custom Signage</h2> <div id="cost">Cost: $5 per tile</div> </div> ``` **scss** ```scss= h1{ color: red; } #cost{ color: blue; } ``` **js** ```javascript= let price; let quantity; let total; price = 5; quantity = 14; total = price*quantity; let el = document.getElementById('cost'); el.textContent = '$' + total; ``` ## Change Content with HTML **js** ```javascript= let message = "<p>I don't know what this is<p>" el.innerHTML = message; ``` ## 關於變數的規則 * 需要是字母、$或_開始,絕對不能是數字開始 * 可以包含_但不能包含-或. * 不能是keywords or reversed words * 有大小寫之分 * 通常follow Camal Case (firstName, lastNameIs) ## Change Content with Array **js** ```javascript= let message; message = ['dog', 'cat', 'shit'] el.textContent = message[0]; let message = new Array('dog', 'cat', 'shit'); ``` **js** ```javascript= let message = ['dog', 'cat', 'shit']; message[2] = 'cow' + 'piggy'; ``` ## Function ```javascript= function updateMessage(){ el.textContent = message[2]; } updateMessage(); ``` ## Object ```javascript= let hotel={ name: 'Royal', rooms: 40, booked: 25, gym: true, roomTypes: ['twin', 'double', 'suite']; } ``` --- https://happycoding.io/tutorials/p5js/web-dev?fbclid=IwAR2EHEsXwpHmZZsB9Q3Mqi5QZEYyMB_sgnssFMQJFgmkSqztzll2YyZ4q2I Some of the tutorials are from coursera NYU: Information Visualization Programming with D3.js ### Operators ```javascript= let result = 3+2; ///+*/- result+=4; ///result=result+4; let name = firstName + lastName; let result = 3>=2; let isEqual = months === 4; ``` ### Function ```javascript= function add(v1,v2){ return v1+v2 } const add = (v1, v2) => v1+v2; let result = add(5,3); ``` ### Conditional ```javascript= let color; if(v1===10){ color="blue" }else{ color="red" } let color=v1===10?"blue":"red"; ``` ### Loop ```javascript= for(let i=1; i<21; i+=1){ console.log(i) } let i=1 while(i<21){ console.log(i) i+=1; if(i>=21) break; } ``` ### Intro to Java ```javascript= const KG_PER_KILO = 0.45; const INCH_TO_METER = 0.0254; let Name = 'John'; let Weight = 196; let Height = 90; let client = { Name : 'Jane', Weight : 196, Height : 90 } function getBMI(client){ let weightInKg = client.Weight * KG_PER_KILO; let heightInMt = client.Height * INCH_TO_METER; let BMI = weightInKg / heightInMt / heightInMt; return BMI } function getBMI(client){ let weightInKg = Weight * KG_PER_KILO; let heightInMt = Height * INCH_TO_METER; let BMI = weightInKg / heightInMt / heightInMt; return BMI } document.write(client.Name + ":" + getBMI(client)); ``` ### Control Structures ```javascript= let clients =[ { Name : 'John', Weight : 196, Height : 90 }, { Name : 'Jane', Weight : 186, Height : 70 }, { Name : 'James', Weight : 206, Height : 60 } ] for(let i=0; i<clients.length; i++){ let client = clients[i]; let bmi = getBMI(client) if(bmi> 25){ document.write(client.Name + ":" + bmi + "</br>") } } ``` # Week6: D3.js ### 流程 1. D3簡介 2. 案例分享 3. 視覺化步驟 4. Select介紹 5. 內容更改介紹 7. 新增/移除元素介紹 9. 屬性更改介紹 (恭喜你已經學完D3基本操作了!) 11. 長條圖實作 ### D3簡介 * [程式前沿](https://codertw.com/%E7%A8%8B%E5%BC%8F%E8%AA%9E%E8%A8%80/635116/) ### 實作案例 * [Best D3 Websites](https://www.awwwards.com/sites/daesk) * [Globalance World (私心喜歡的應用)](https://fe.globalanceworld.com/) 吃D3! ```html= <script src="https://d3js.org/d3.v4.min.js"></script> ``` ### Visualization Steps & D3 APIs ##### **1. Transform Data** `d3.cross`: cross- multiplication over two collctions `d3.max`: maximum value in a field ##### **2. Map Data to Image Space** `d3.scaleLinear`: maps linearly between the two values `d3.scaleTime`: helps you to work with time values ##### **3. Compute Layouts and Paths** `d3.path`: drawing maps, line chart `d3.treemap`: treemap ##### **4. Draw the chart** `d3.select`: select things `d3.append`: add new elements ### D3 Selection D3 selection is a API that we're going to use, to select elements on our HTML page. ```html= <body> <div> <h1>Title</h1> <button></button> <button></button> </div> </body> ``` **Select first element** ```javascript= d3.select(selector) d3.select("p") d3.select("#dog") d3.select("p") .select(".main") let selection = d3 .select("p") .select(".main") ``` **Select All elements** ```javascript= let selection = d3 .selectAll("p") .selectAll(".main") ``` Return with D3 wrapper, able to use other APIs of the three on top of it ### D3 Changing Content #### Get vs Set ```javascript= .select("") .method() ///get .method(value) ///set ``` #### Get ```javascript= let x = d3.select("p").text() ``` #### Set ```javascript= d3.select("p").text("this is the content") d3.select("p").html("This <b>contetn</b>") ``` #### Onclick **html** ```html= <p class="paragraph">This is an example paragraph></p> <button onclick="change1()">Change First</button> <button onclick="change2()">Change All</button> <button onclick="change3()">Change html</button> <button onclick="change4()">Change All</button> ``` **javascript** ```javascript= function change1(){ let d = d3.select(".paragraph") d.text("New Text") } function change2(){ d3.selectAll("p").text("New Text 2") } function change3(){ d3.selectAll("p").html("<b>bold</b> normal") } function change4(){ d3.select("p").text("<b>bold</b> normal") } ``` ### Adding and Removing Elements #### API|selection.append (Add Elements) ###### Syntax: 獲得空元素 ```html= selection .append(tag) ``` ###### Syntax: 利用.text .html 對內容進行更動 ```html= d3.select('ul') .append('li') .text('Item4') ``` ###### result ```html= <ul> <li>Item 1<li> <li>Item 2<li> <li>Item 3<li> <li>Item 4<li> #新增項 </ul> ``` #### API|selection.remove (Remove Elements) select element you want to remove directly 否則會把整個 < ul > 刪掉,使得其他 button 失效 ###### Syntax ```html= selection .remove() ``` ###### example: selectAll ```html= d3.selectAll('li') .remove() ``` ```html= <ul> </ul> ``` ###### example: select ```html= d3.select('li') .remove() ``` ```html= <ul> <li>Item 2<li> <li>Item 3<li> <li>Item 4<li> </ul> ``` #### css小複習 ```html= Attributes <img src='logo.png' /> Style <p style='color:red' /> ``` #### API|selection.attr ###### Syntax ```html= selection .attr(attribute, value) ``` ###### example ```html= d3.select('img') .attr('src', 'newLogo.png') ``` #### API|selection.style ###### Syntax ```html= selection .style(property, value) ``` ###### example ```html= d3.select('p') .style('color', 'red') #可以直接改動 property ``` ### 長條圖實作 ###### index.html ```html= <!DOCTYPE html> <html> <head> <title>D3 Pratice</title> <meta charset="utf-8"> <link rel="stylesheet" href="style.css"> </head> <body> </body> <script src="https://d3js.org/d3.v5.min.js"></script> <script> var title = "Comments on Posts"; d3.select("body") .append("h3") .text(title); d3.csv('https://raw.githubusercontent.com/sdaityari/my_git_project/master/posts.csv', d3.autoType).then(function (data) { d3.select("body") .selectAll("div") .data(data) .enter() .append("div") .style("width", function(d) { return d.amount * 40 + "px"; }) .style("height", "15px"); }); </script> </html> ``` ###### css吃進來 ```css= body { background-color: #3c3c3c; color: #cfcfcf; } div { line-height: 15px; margin-bottom: 3px; background-color: grey; text-align: right; padding-right: 5px; font-size: 10px; color: #cfcfcf; } ``` # Week7: Three.js ### 首先 先測試自己的瀏覽器可不可以跑WebGl https://get.webgl.org/ ### 用法 要在螢幕上顯示 3D 圖形,在 Three.js 中需要以下的基本元素: * 場景(Scene):供其他元素設置的空間。 * 攝影機(Camera):在場景中建立觀察點,並確定觀察方向、角度。 * 物體(Objects):在場景中添加被觀察的物體。 * 光源(Light):在場景中用來照亮物體的光。 * 渲染器(Renderer):將所要呈現的場景渲染到畫面上。 ## 實作一 ##### 1. 建立場景、攝影機、渲染器 ```html= var scene = new THREE.Scene(); var camera = new THREE.PerspectiveCamera( 75, window.innerWidth/window.innerHeight, 0.1, 1000 ); var renderer = new THREE.WebGLRenderer(); // 設定渲染器渲染範圍以及背景顏色 renderer.setSize(window.innerWidth, window.innerHeight) renderer.setClearColor(new THREE.Color('rgb(255, 255, 255)')) //將渲染器append到body裡 document.body.appendChild( renderer.domElement ); ``` ##### 2. 建立物件(mesh) Object根據構成方式分成Mesh、Points 而Object具有Geometry、Material等特質可以操作 ```html= var geometry = new THREE.BoxGeometry( 1, 1, 1 ); var cube = new THREE.Mesh( geometry, material ); scene.add( cube ); ``` ##### 3. 建立材質 可調整像是顏色(color)、紋理(texture)、透明度(opacity)等數值。其中有些材質屬性能對光源產生反應,像是發光度(shininess)、鏡面反射程度(specular)等等,會決定物體會像金屬或像塑膠。 ```html= //方法1:指定內建的材質 var material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } ); //方法2:把材質貼圖mapping到物件上 const texture = new THREE.TextureLoader().load( 'textures/crate.gif' ); const geometry = new THREE.BoxGeometry( 200, 200, 200 ); const material = new THREE.MeshBasicMaterial( { map: texture } ); ``` ##### 4. 調整攝影機 ```html= camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 0.1, 100 ) camera.position.set(10, 10, 10) // 相機位置 camera.lookAt(scene.position) // 相機焦點 ```` 相機可以當作是一個觀察點,決定了我們從哪個位置、方向、角度來觀察場景中的畫面,在 Three.js 中主要有兩種比較常用的[相機](https://dezchuang.github.io/ironman-three.js/day02_threeBasic/bothCamera/index.html)。(可點進去按右上角的switchCamera來切換相機體驗差異。) ![](https://i.imgur.com/9tdL8HY.png) * 透視投影相機(PerspectiveCamera) THREE.PerspectiveCamera(fov, aspect, near, far); * 正交投影相機(OrthographicCamera) THREE.OrthographicCamera(left, right, top, bottom, near, far); 關於攝影機的補充名詞 * 視角(fov, field of view):又稱為視野、視場,指的是我們能從畫面上看到的視野範圍,一般在遊戲中會設定在 60 ~ 90 度。 * 畫面寬高比(aspect):渲染結果的畫面比例,一般都是使用 window.innerWidth / window.innerHeight 。 * 近面距離(near):從距離相機多近的地方開始渲染,一般推薦使用 0.1。 * 遠面距離(far):相機能看得多遠,一般推薦使用 1000,可視需求調整,設置過大會影響效能。 * camera.lookAt:指相機會盯著何處,一般靜止觀察的相機都是設定為 camera.lookAt(scene.position),就是觀察場景固定的位置。但若今天你要讓相機動態追蹤某個物體,那你可以在渲染時改變 camera.lookeAt 中的參數為特定物體的某個基準座標,可以參考[官網範例](https://threejs.org/examples/?q=lookat#misc_lookat)。 ##### 5. 加入燈光 打光在3D世界中是個超超超重要的大學問! 不需光源就被渲染在畫面上的材質:MeshBasicMaterial、MeshNormalMaterial 能與光源互動的材質:MeshLambertMaterial、MeshPhongMaterial 。 在 Three.js 中提供了包括環境光(AmbientLight)、點光源(PointLight)、 聚光燈 (SpotLight)、方向光(DirectionalLight)、半球光(HemisphereLight)等多種光源。 ```html= let pointLight = new THREE.PointLight(0xffffff) pointLight.position.set(10, 10, -10) scene.add(pointLight) ``` ##### 6. 呼叫 renderer.render 繪製場景。 在 Three.js 中多種渲染器可以選擇(WebGLRender、CanvasRenderer、SVGRenderer 等等),但一般而言都是使用 WebGLRenderer,因為它支援較多功能,像是材質、陰影等等,在後面的程式碼中會看到常透過渲染器來設定預設背景顏色、場景尺寸、陰影效果等。 小補充:three.js也是使用**[requestAnimationFrame](https://docs.microsoft.com/en-us/previous-versions/windows/internet-explorer/ie-developer/dev-guides/hh920765(v=vs.85)?redirectedfrom=MSDN)** 來進行動畫幀數的配置 完整的程式碼: ```htmlembedded= //html <script src="https://threejs.org/build/three.js"></script> //js var scene = new THREE.Scene(); var camera = new THREE.PerspectiveCamera( 75, window.innerWidth/window.innerHeight, 0.1, 1000 ); var renderer = new THREE.WebGLRenderer(); renderer.setSize( window.innerWidth, window.innerHeight ); renderer.setClearColor(new THREE.Color('rgb(255, 255, 255)')); document.body.appendChild( renderer.domElement ); var geometry = new THREE.BoxGeometry( 1, 1, 1 ); var material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } ); var cube = new THREE.Mesh( geometry, material ); scene.add( cube ); camera.position.z = 5; let pointLight = new THREE.PointLight(0xffffff) pointLight.position.set(20, 10, 10) scene.add(pointLight) var animate = function () { requestAnimationFrame( animate ); cube.rotation.x += 0.01; cube.rotation.y += 0.01; renderer.render( scene, camera ); }; animate(); ``` ## 實作二 ### 滑鼠控制3D物件 ```html= document.addEventListener( 'mousemove', onDocumentMouseMove ); ``` # Week8: Matter.js 因為筆記長度限制,開了新筆記在[這裡](https://hackmd.io/ti1kH6o3THCH8d-iLukNuQ?view)