整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          聽說過CSS in JS,還有JS in CSS?


          說過CSS in JS,還有JS in CSS?

          CSS in JS

          CSS in JS是一種解決css問題想法的集合,而不是一個指定的庫。從CSS in JS的字面意思可以看出,它是將css樣式寫在JavaScript文件中,而不需要獨立出.css.less之類的文件。將css放在js中使我們更方便的使用js的變量模塊化tree-shaking。還解決了css中的一些問題,譬如:更方便解決基于狀態的樣式更容易追溯依賴關系生成唯一的選擇器來鎖定作用域。盡管CSS in JS不是一個很新的技術,但國內的普及程度并不高。由于Vue和Angular都有屬于他們自己的一套定義樣式的方案,React本身也沒有管用戶怎樣定義組件的樣式,所以CSS in JS在React社區的熱度比較高。

          目前為止實現CSS in JS的第三方庫有很多:點擊這里。像JSS、styled-components等。在這里我們就不展開贅述了,這篇文章的重點是JS in CSS

          JS in CSS又是什么

          在上面我們提到CSS in JS就是把CSS寫在JavaScript中,那么JS in CSS我們可以推斷出就是可以在CSS中使用JavaScript腳本,如下所示。可以在CSS中編寫Paint API的功能。還可以訪問:ctx,geom。甚至我們還可以編寫自己的css自定義屬性等。這些功能的實現都基于CSS Houdini。

          .el {
            --color: cyan;
            --multiplier: 0.24;
            --pad: 30;
            --slant: 20;
            --background-canvas: (ctx, geom) => {
              let multiplier = var(--multiplier);
              let c = `var(--color)`;
              let pad = var(--pad);
              let slant = var(--slant);
          
              ctx.moveTo(0, 0);
              ctx.lineTo(pad + (geom.width - slant - pad) * multiplier, 0);
              ctx.lineTo(pad + (geom.width - slant - pad) * multiplier + slant, geom.height);
              ctx.lineTo(0, geom.height);
              ctx.fillStyle = c;
              ctx.fill();
            };
            background: paint(background-canvas);
            transition: --multiplier .4s;
          }
          .el:hover {
            --multiplier: 1;
          }

          Houdini 解決了什么問題

          CSS 與 JS的標準制定流程對比

          在如今的Web開發中,JavaScript幾乎占據了項目代碼的大部分。我們可以在項目開發中使用ES 2020、ES2021、甚至提案中的新特性(如:Decorator),即使瀏覽器尚未支持,也可以編寫Polyfill或使用Babel之類的工具進行轉譯,讓我們可以將最新的特性應用到生產環境中(如下圖所示)。



          而CSS就不同了,除了制定CSS標準規范所需的時間外,各家瀏覽器的版本、實戰進度差異更是曠日持久(如下圖所示),最多利用PostCSS、Sass等工具來幫我們轉譯出瀏覽器能接受的CSS。開發者們能操作的就是通過JS去控制DOMCSSOM來影響頁面的變化,但是對于接下來的LayoutPaintComposite就幾乎沒有控制權了。為了解決上述問題,為了讓CSS的魔力不再受到瀏覽器的限制,Houdini就此誕生。

          CSS Polyfill

          我們上文中提到JavaScript中進入提案中的特性我們可以編寫Polyfill,只需要很短的時間就可以講新特性投入到生產環境中。這時,腦海中閃現出的第一個想法就是CSS Polyfill,只要CSS的Polyfill 足夠強大,CSS或許也能有JavaScript一樣的發展速度,令人可悲的是編寫CSS Polyfill異常的困難,并且大多數情況下無法在不破壞性能的情況下進行。這是因為JavaScript是一門動態腳本語言。它帶來了極強的擴展性,正是因為這樣,我們可以很輕松使用JavaScript做出JavaScript的Polyfill。但是CSS不是動態的,在某些場景下,我們可以在編譯時將一種形式的CSS的轉換成另一種(如PostCSS)。如果你的Polyfill依賴于DOM結構或者某一個元素的布局、定位等,那么我們的Polyfill就無法編譯時執行,而需要在瀏覽器中運行了。不幸的是,在瀏覽器中實現這種方案非常不容易。

          如上圖所示,是從瀏覽器獲取到HTML到渲染在屏幕上的全過程,我們可以看到只有帶顏色(粉色、藍色)的部分是JavaScript可以控制的環節。首先我們根本無法控制瀏覽器解析HTML與CSS并將其轉化為DOMCSSOM的過程,以及Cascade,Layout,Paint,Composite我們也無能為力。整個過程中我們唯一完全可控制的就是DOM,另外CSSOM部分可控。

          CSS Houdini草案中提到,這種程度的暴露是不確定的、兼容性不穩定的以及缺乏對關鍵特性的支持的。比如,在瀏覽器中的 CSSOM 是不會告訴我們它是如何處理跨域的樣式表,而且對于瀏覽器無法解析的 CSS 語句它的處理方式就是不解析了,也就是說——如果我們要用 CSS polyfill 讓瀏覽器去支持它尚且不支持的屬性,那就不能在 CSSOM 這個環節做,我們只能遍歷一遍DOM,找到 <style><link rel="stylesheet"> 標簽,獲取其中的 CSS 樣式、解析、重寫,最后再加回 DOM 樹中。令人尷尬的是,這樣DOM樹全部刷新了,會導致頁面的重新渲染(如下如所示)。

          即便如此,有的人可能會說:“除了這種方法,我們也別無選擇,更何況對網站的性能也不會造成很大的影響”。那么對于部分網站是這樣的。但如果我們的Polyfill是需要對可交互的頁面呢?例如scrollresizemousemovekeyup等等,這些事件隨時會被觸發,那么意味著隨時都會導致頁面的重新渲染,交互不會像原本那樣絲滑,甚至導致頁面崩潰,對用戶的體驗也極其不好。

          綜上所述,如果我們想讓瀏覽器解析它不認識的樣式(低版本瀏覽器使用grid布局),然而渲染流程我們無法介入,我們也只能通過手動更新DOM的方式,這樣會帶來很多問題,Houdini的出現正是致力于解決他們。

          Houdini API

          Houdini是一組底層API,它公開了CSS引擎的各個部分,如下圖所示展示了每個環節對應的新API(灰色部分各大瀏覽器還未實現),從而使開發人員能夠通過加入瀏覽器渲染引擎的樣式和布局過程來擴展CSS。Houdini是一群來自Mozilla,Apple,Opera,Microsoft,HP,Intel和Google的工程師組成的工作小組設計而成的。它們使開發者可以直接訪問CSS對象模型(CSSOM),使開發人員可以編寫瀏覽器可以解析為CSS的代碼,從而創建新的CSS功能,而無需等待它們在瀏覽器中本地實現。

          Properties & Values API

          盡管當前已經有了CSS變量,可以讓開發者控制屬性值,但是無法約束類型或者更嚴格的定義,CSS Houdini新的API,我們可以擴展css的變量,我們可以定義CSS變量的類型,初始值,繼承。它是css變量更強大靈活。

          CSS變量現狀:

          .dom {
            --my-color: green;
            --my-color: url('not-a-color'); // 它并不知道當前的變量類型
            color: var(--my-color);
          }

          Houdini提供了兩種自定義屬性的注冊方式,分別是在js和css中。

          CSS.registerProperty({
            name: '--my-prop', // String 自定義屬性名
            syntax: '<color>', // String 如何去解析當前的屬性,即屬性類型,默認 *
            inherits: false, // Boolean 如果是true,子節點將會繼承
            initialValue: '#c0ffee', // String 屬性點初始值
          });

          我們還可以在css中注冊,也可以達到上面的效果

          @property --my-prop {
            syntax: '<color>';
            inherits: false;
            initial-value: #c0ffee;
          }

          這個API中最令人振奮人心的功能是自定義屬性上添加動畫,像這樣:transition: --multiplier 0.4s;,這個功能我們在前面介紹什么是js in css那個demo用使用過。我們還可以使用+使syntax屬性支持一個或多個類型,也可以使用|來分割。更多syntax屬性值:

          屬性值

          描述

          <length>

          長度值

          <number>

          數字

          <percentage>

          百分比

          <length-percentage>

          長度或百分比,calc將長度和百分比組成的表達式

          <color>

          顏色

          <image>

          圖像

          <url>

          網址

          <integer>

          整數

          <angle>

          角度

          <time>

          時間

          <resolution>

          分辨率

          <transform-list>

          轉換函數

          <custom-ident>

          ident

          Worklets

          Worklets是渲染引擎的擴展,從概念上來講它類似于Web Workers,但有幾個重要的區別:

          1. 設計為并行,每個Worklets必須始終有兩個或更多的實例,它們中的任何一個都可以在被調用時運行
          2. 作用域較小,限制不能訪問全局作用域的API(Worklet的函數除外)
          3. 渲染引擎會在需要的時候調用他們,而不是我們手動調用

          Worklet是一個JavaScript模塊,通過調用worklet的addModule方法(它是個Promise)來添加。比如registerLayout, registerPaint, registerAnimator 我們都需要放在Worklet中

          //加載單個
          await demoWorklet.addModule('path/to/script.js');
          
          // 一次性加載多個worklet
          Promise.all([
            demoWorklet1.addModule('script1.js'),
            demoWorklet2.addModule('script2.js'),
          ]).then(results => {});
          
          registerDemoWorklet('name', class {
          
            // 每個Worklet可以定義要使用的不同函數
            // 他們將由渲染引擎在需要時調用
            process(arg) {
              return !arg;
            }
          });
          

          Worklets的生命周期


          1. Worklet的生命周期從渲染引擎內開始
          2. 對于JavaScript,渲染引擎啟動JavaScript主線程
          3. 然后他將啟動多個worklet進程,并且可以運行。這些進程理想情況下是獨立于主線程的線程,這樣就不會阻塞主線程(但它們也不需要阻塞)
          4. 然后在主線程中加載我們瀏覽器的JavaScript
          5. 該JavaScript調用 worklet.addModule 并異步加載一個worklet
          6. 加載后,將worklet加載到兩個或多個可用的worklet流程中
          7. 當需要時,渲染引擎將通過從加載的Worklet中調用適當的處理函數來執行Worklet。該調用可以針對任何并行的Worklet實例。

          Typed OM

          Typed OM是對現有的CSSOM的擴展,并實現 Parsing APIProperties & Values API相關的特性。它將css值轉化為有意義類型的JavaScript的對象,而不是像現在的字符串。如果我們嘗試將字符串類型的值轉化為有意義的類型并返回可能會有很大的性能開銷,因此這個API可以讓我們更高效的使用CSS的值。

          現在讀取CSS值增加了新的基類CSSStyleValue,他有許多的子類可以更加精準的描述css值的類型:

          子類

          描述

          CSSKeywordValue

          CSS關鍵字和其他標識符(如inherit或grid)

          CSSPositionValue

          位置信息 (x,y)

          CSSImageValue

          表示圖像的值屬性的對象

          CSSUnitValue

          表示為具有單個單位的單個值(例如50px),也可以表示為沒有單位的單個值或百分比

          CSSMathValue

          比較復雜的數值,比如有calc,min和max。這包括子類 CSSMathSum, CSSMathProduct, CSSMathMin, CSSMathMax, CSSMathNegateCSSMathInvert

          CSSTransformValue

          CSS transforms組成的CSSTransformComponent列表,其中包括CSSTranslate, CSSRotate, CSSScale, CSSSkew, CSSSkewX, CSSSkewY, CSSPerspectiveCSSMatrixComponent

          使用Typed OM主要有兩種方法:

          1. 通過attributeStyleMap設置和獲取有類型的行間樣式
          2. 通過computedStyleMap獲取元素完整的Typed OM樣式

          使用attributeStyleMap設置并獲取

          myElement.attributeStyleMap.set('font-size', CSS.em(2));
          myElement.attributeStyleMap.get('font-size'); // CSSUnitValue { value: 2, unit: 'em' }
          
          myElement.attributeStyleMap.set('opacity', CSS.number(.5));
          myElement.attributeStyleMap.get('opacity'); // CSSUnitValue { value: 0.5, unit: 'number' };

          在線demo

          使用computedStyleMap

          .foo {
            transform: translateX(1em) rotate(50deg) skewX(10deg);
            vertical-align: baseline;
            width: calc(100% - 3em);
          }
          const cs = document.querySelector('.foo').computedStyleMap();
          
          cs.get('vertical-align');
          // CSSKeywordValue {
          //  value: 'baseline',
          // }
          
          cs.get('width');
          // CSSMathSum {
          //   operator: 'sum',
          //   length: 2,
          //   values: CSSNumericArray {
          //     0: CSSUnitValue { value: -90, unit: 'px' },
          //     1: CSSUnitValue { value: 100, unit: 'percent' },
          //   },
          // }
          
          cs.get('transform');
          // CSSTransformValue {
          //   is2d: true,
          //   length: 3,
          //   0: CSSTranslate {
          //     is2d: true,
          //     x: CSSUnitValue { value: 20, unit: 'px' },
          //     y: CSSUnitValue { value: 0, unit: 'px' },
          //     z: CSSUnitValue { value: 0, unit: 'px' },
          //   },
          //   1: CSSRotate {...},
          //   2: CSSSkewX {...},
          // }
          復制代碼

          在線demo

          Layout API

          開發者可以通過這個API實現自己的布局算法,我們可以像原生css一樣使用我們自定義的布局(像display:flex, display:table)。在 Masonry layout library 上我們可以看到開發者們是有多想實現各種各樣的復雜布局,其中一些布局光靠 CSS 是不行的。雖然這些布局會讓人耳目一新印象深刻,但是它們的頁面性能往往都很差,在一些低端設備上性能問題猶為明顯。

          CSS Layout API 暴露了一個registerLayout方法給開發者,接收一個布局名(layout name)作為后面在 CSS中使用的屬性值,還有一個包含有這個布局邏輯的JavaScript類。

          my-div {
            display: layout(my-layout);
          }
          // layout-worklet.js
          registerLayout('my-layout', class {
            static get inputProperties() { return ['--foo']; }
            
            static get childrenInputProperties() { return ['--bar']; }
            
            async intrinsicSizes(children, edges, styleMap) {}
          
            async layout(children, edges, constraints, styleMap) {}
          });
          await CSS.layoutWorklet.addModule('layout-worklet.js');

          在線demo 目前瀏覽器大部分還不支持

          Painting API

          我們可以在CSS background-image中使用它,我們可以使用Canvas 2d上下文,根據元素的大小控制圖像,還可以使用自定義屬性。

          await CSS.paintWorklet.addModule('paint-worklet.js');
          registerPaint('sample-paint', class {
            static get inputProperties() { return ['--foo']; }
          
            static get inputArguments() { return ['<color>']; }
          
            static get contextOptions() { return {alpha: true}; }
          
            paint(ctx, size, props, args) { }
          });

          在線demo

          Animation API

          這個API讓我們可以控制基于用戶輸入的關鍵幀動畫,并且以非阻塞的方式。還能更改一個 DOM 元素的屬性,不過是不會引起渲染引擎重新計算布局或者樣式的屬性,比如 transform、opacity 或者滾動條位置(scroll offset)。Animation API的使用方式與 Paint APILayout API略有不同我們還需要通過new一個WorkletAnimation來注冊worklet。

          // animation-worklet.js
          registerAnimator('sample-animator', class {
            constructor(options) {
            }
            animate(currentTime, effect) {
              effect.localTime = currentTime;
            }
          });
          await CSS.animationWorklet.addModule('animation-worklet.js');
          
          // 需要添加動畫的元素
          const elem = document.querySelector('#my-elem');
          const scrollSource = document.scrollingElement;
          const timeRange = 1000;
          const scrollTimeline = new ScrollTimeline({
            scrollSource,
            timeRange,
          });
          
          const effectKeyframes = new KeyframeEffect(
            elem,
            // 動畫需要綁定的關鍵幀
            [
              {transform: 'scale(1)'},
              {transform: 'scale(.25)'},
              {transform: 'scale(1)'}
            ],
            {
              duration: timeRange,
            },
          );
          new WorkletAnimation(
            'sample-animator',
            effectKeyframes,
            scrollTimeline,
            {},
          ).play();

          關于此API的更多內容點擊這里

          Parser API

          允許開發者自由擴展 CSS 詞法分析器。

          解析規則:

          const background = window.cssParse.rule("background: green");
          console.log(background.styleMap.get("background").value) // "green"
          
          const styles = window.cssParse.ruleSet(".foo { background: green; margin: 5px; }");
          console.log(styles.length) // 5
          console.log(styles[0].styleMap.get("margin-top").value) // 5
          console.log(styles[0].styleMap.get("margin-top").type) // "px"

          解析CSS:

          const style = fetch("style.css")
                  .then(response => CSS.parseStylesheet(response.body));
          style.then(console.log);

          Font Metrics API

          它將提供一些方法來測量在屏幕上呈現的文本元素的尺寸,將允許開發者控制文本元素在屏幕上呈現的方式。使用當前功能很難或無法測量這些值,因此該API將使開發者可以更輕松地創建與文本和字體相關的CSS特性。例如:

          • flex布局: align-items baseline特性。需要知道每一個flex盒子中第一個元素的基線位置。
          • 首字母: 需要知道每個字母的基線高度和字母最大的高度,以及換行內容的基線長度。
          • 單個字形的前進和后退。
          • 換行: 需要訪問字體數據,文本的所有樣式輸入以及布局信息(可用的段落長度等)。
          • 元素中的每一個line boxes都需要一個基線。(line boxes代表包含眾多inline boxes的這行)

          Houdini 目前進展

          Houdini 的藍圖

          了解到這里,部分開發者可能會說:“我不需要這些花里胡哨的技術,并不能帶收益。我只想簡簡單單地寫幾個頁面,做做普通的Web App,并不想試圖干預瀏覽器的渲染過程從而實現一些實驗性或炫酷的功能。”如果這樣想的話,我們不妨退一步再去思考。回憶下最近做過的項目,用于實現頁面效果所使用到的技術,grid布局方式在考慮兼容老版本瀏覽器時也不得不放棄。我們想控制瀏覽器渲染頁面的過程并不是僅僅為了炫技,更多的是為了幫助開發者們解決以下兩個問題:

          1. 統一各大瀏覽器的行為
          2. JavaScript一樣,在推出新的特性時,我們可以通過Polyfill的形式快速地投入生產環境中。

          幾年過后再回眸,當主流瀏覽器完全支持Houdini的時候。我們可以在瀏覽器上隨心所欲的使用任何CSS屬性,并且他們都能完美支持。像今天的grid布局在舊版本瀏覽器支持的并不友好的這類問題,那時我們只需要安裝對應的Polyfill就能解決類似的問題。

          如在文中發現有誤之處,歡迎反饋、糾正。

          寫CSS的常用套路(下篇)...

          點擊觀看——我寫CSS的常用套路(上篇)...

          box-shadow

          為盒子添加陰影,增加盒子的立體感,可以多層疊加,并且會使陰影更加絲滑

          本demo地址:Pagination

          內發光

          注意到box-shadow還有個inset,用于盒子內部發光

          利用這個特性我們可以在盒子內部的某個范圍內設定顏色,做出一個新月形

          再加點動畫和濾鏡效果,“猩紅之月”閃亮登場!

          注意到它散發著淡淡的紅光,其實就是2個偽元素應用了模糊濾鏡所產生的效果

          本demo地址:Crimson Crescent Loading

          text-shadow

          文本陰影,本質上和box-shadow相同,只不過是相對于文本而言,常用于文本發光,也可通過多層疊加來制作霓虹文本和偽3D文本等效果

          發光文本

          本demo地址:Staggered GlowIn Text

          霓虹文本

          本demo地址:Neon Text

          偽3D文本

          本demo地址:Staggered Bouncing 3D Loading

          background-clip:text

          能將背景裁剪成文字的前景色,常用來和color: transparent配合生成漸變文本

          本demo地址:Menu Hover Fill Text

          gradient

          漸變可以作為背景圖片的一種,具有很強的色彩效果,甚至可以用來模擬光

          linear-gradient

          線性漸變是筆者最常用的漸變

          這個作品用到了HTML的dialog標簽,線性漸變背景,動畫以及overflow障眼法,細心的你看出來了嗎:)

          本demo地址:Confirm Modal

          radial-gradient

          徑向漸變常用于生成圓形背景,上面例子中Snow的背景就是一個橢圓形的徑向漸變

          此外,由于背景可以疊加,我們可以疊加多個不同位置大小的徑向漸變來生成圓點群,再加上動畫就產生了一種微粒效果,無需多余的div元素

          本demo地址:Particle Button

          conic-gradient

          圓錐漸變可以用于制作餅圖

          用一個偽元素疊在餅圖上面,并將content設為某個值(這個值通過CSS變量計算出來),就能制作出度量計的效果,障眼法又一次完成了它的使命

          本demo地址:Gauge (No SVG)

          filter

          PS里的濾鏡,blur最常用

          融合效果

          當blur濾鏡和contrast濾鏡一起使用時,會產生一種融合(gooey)的奇特效果

          本demo地址:Snow Scratch

          backdrop-filter

          對背景應用濾鏡,產生毛玻璃的效果

          本demo地址:Frosted Glass

          mix-blend-mode

          PS里的混合模式,常用于文本在背景下的特殊效果

          以下利用濾色模式(screen)實現文本視頻蒙版效果

          本demo地址:Video Mask Text

          clip-path

          PS里的裁切,可以制作各種不規則形狀。如果和動畫結合也會相當有意思

          本demo地址:Name Card Hover Expand

          故障效果

          由于clip-path有裁切功能,因此可以將多個文字疊在一起,并按比例裁切成多分,再應用交錯動畫,就能制作出酷炫的故障效果(glitch)。

          本demo地址:Cross Bar Glitch Text

          mask

          PS里的遮罩。所謂遮罩,就是原始圖片只顯示遮罩圖片非透明的部分

          鏤空效果

          雖然clip-path能裁切出形狀,但它無法鏤空,因為形狀的里面它管不著

          可能有人(包括我)會用偽元素來“模擬”鏤空(通過設置同樣的背景色),但這樣并非真的鏤空,換了個背景或浮在圖片上就會暴露出來,這時我們就要求助于遮罩了

          假設,你想制作一個空心的圓環,那么你只需將一個徑向漸變作為元素的遮罩,并且第一個color-stop設置為透明,其他的color-stop設置為其他顏色即可,因為遮罩的定義就是只顯示遮罩圖片非透明的部分

          注意:為了消除鋸齒,這個徑向漸變的中間需要有一個額外的color-stop用于緩沖,長度設置為原長度加0.5px即可

          本demo地址:Circle Arrow Nav

          -webkit-box-reflect

          投影效果,不怎么常用,適合立體感強的作品

          本demo地址:Card Flip Reflection

          web animations

          雖然這并不是一個CSS特性,但是它經常用于完成那些CSS所做不到的事情

          那么何時用它呢?當CSS動畫中有屬性無法從CSS中獲取時,自然就會使用到它了

          跟蹤鼠標的位置

          目前CSS還尚未有獲取鼠標位置的API,因此考慮用JS來進行

          通過查閱相關的DOM API,發現在監聽鼠標事件的API中,可通過e.clientX和e.clientY來獲得鼠標當前的位置

          既然能夠獲取鼠標的位置,那么跟蹤鼠標的位置也就不是什么難事了:通過監聽mouseenter和mouseleave事件,來獲取鼠標出入一個元素時的位置,并用此坐標來當作鼠標的位移距離,監聽mousemove事件,來獲取鼠標在元素上移動時的位置,同樣地用此坐標來當作鼠標的位移距離,這樣一個跟蹤鼠標的效果就實現了

          本demo地址:Menu Hover Image

          CSS Houdini

          CSS Houdini是CSS的底層API,它使我們能夠通過這套接口來擴展CSS的功能

          讓漸變動起來

          目前來說,我們無法直接給漸變添加動畫,因為瀏覽器不理解要改變的值是什么類型

          這時,我們就可以利用CSS.registerProperty()來注冊我們的自定義變量,并聲明其語法類型(syntax)為顏色類型<color>,這樣瀏覽器就能理解并對顏色應用插值方法來進行動畫

          還記得上文提到的圓錐漸變conic-gradient()嗎?既然它可以用來制作餅圖,那么我們能不能讓餅圖動起來呢?答案是肯定的,定義三個變量:--color1、--color2和--pos,其中--pos的語法類型為長度百分比<length-percentage>,將其從0變為100%,餅圖就會順時針旋轉出現

          利用絕對定位和層疊上下文,我們可以疊加多個從小到大的餅圖,再給它們設置不同的顏色,應用交錯動畫,就有了下面這個炫麗的效果

          本demo地址:Mawaru

          彩蛋

          將交錯動畫和偽類偽元素結合起來寫出來的慎重勇者風格的菜單

          本demo地址:Shinchou Menu

          具的選擇不是越多人用越好。像Axure這類專業的原型制作軟件,在標尺、對齊上面,是iH5遠比不上的。但后者在與人溝通以及查看時有著優勢。

          最近支付寶進行了一次比較大的版本更新,引起了很多人的關注,無論從視覺還是交互體驗上都有了很大的改變,但是從原型制作來說,其實比之前更加簡單了。

          通過臨摹這些知名廠商的產品,是快速進步的一種方式,可以更好的借鑒他們的交互與邏輯,比體驗觀看,更能深刻的理解,從而更好的改進自己的產品。

          說到原型,很多人就會想到Axure,這類常用的原型工具,他們使用的都是HTML規范,動效以及交互大部分引入的jQuery庫或者封裝的JS庫,其效果可以在軟件預覽以及導出HTML文件在瀏覽器預覽,同樣類別的還有Justinmind等等。

          與其原理類似的也有很多,如定位于開發工具的Animate,其動畫效果比Axure要強大的多,以及谷歌的web design,還有向國內線上制作平臺的iH5,他們面向的是基礎交互,可自由編輯度高,不僅可以做出H5實例,同樣也可以用于原型。

          這些工具可以分為線上與離線兩種制作方式,我個人偏向使用線上的制作工具,因為離線工具生成的原型不方便發給別人那看,而且制作嚴重依賴于軟件安裝,不便與即時查看與他人溝通。

          對于臨摹來說,事先無需過多分析,了解一下大致交互,直接上手就可以。

          工具:iH5

          材料準備:用手機把新版支付截屏,調到PS用切片把其分為各個模塊,如導航欄,對話框等等。

          Step1:頁面切換

          描述:底部導航的切換交互,跳轉頁面并且圖標變為藍色。可以用點擊事件控制兩種狀態,一是遮罩的移動,二是頁面的跳轉。

          新建時間軸,在其下面新建一個畫布,將藍色與灰色兩個底部導航欄,以及一個與圖標大小的白色矩形,放入其中,在藍色導航圖片的屬性——遮罩,選擇白色矩形。然后在矩形下建立軌跡,四個關鍵幀分別對應四個圖標。

          在舞臺上建四個頁面用來存放導航里的內容。

          在圖標位置添加透明按鈕,在其下方添加事件,當輕觸時跳轉頁面,以及跳轉到該時間軸的某一幀。

          Step2:浮動導航

          描述:當頁面滑動一段距離,頂部導航欄發生變換。通過監測時間軸滑動的時間,來觸發菜單欄的更換。

          在頁面一,新建滑動時間軸,所有素材放入其中,將兩個頂部導航疊放在一起,為內容添加軌跡,讓其讓下滑動,一秒時滑動到底部,為初始默認的導航添加兩個事件,當滑動時間軸滑動0.1秒時,置于底層,當時間為0時,至于頂層。

          Step3:滑動切換

          描述:類似圖片的輪播效果,將未顯示的圖片放在屏幕之外或者隱藏,通過手指的左右滑動來控制圖片的進出。

          在頁面二,把準備好三張輪播的圖,帶有三個鏤空圓點的PNG圖片,以及一個大小與圓點差不多的矩形,都放入滑動時間軸下面,新建軌跡,創建三個關鍵幀,通過調整圖片坐標來控制在每一幀上顯示的圖片,當你滑動時,就會出現圖片的輪播效果,如果需要在圖片上加入鏈接,直接在該圖片添加點擊事件,動作設置為跳轉頁面即可。

          Step4:彈框

          描述:點擊按鈕時彈框出現,然后點擊其周圍彈框消失。為彈框設置好動畫之后,利用事件,來控制其正向與反向播放即可。

          在頁面三上,準備一張黑背景圖片以及設計好的彈框,將其放入時間軸下,利用軌跡制作出想要的效果,在背景上的“+”添加一個透明按鈕,增加一個事件,當點擊時讓該時間軸從頭播放,然后在黑色背景下添加同樣的事件,把動作改為反向播放。

          其他的一些交互無外乎都是頁面的跳轉,原型制作上并沒有多少壓力。

          制作完成之后,就可發布了,會生成一個網址鏈接與二維碼,可以在線編輯與查看。

          總結:

          工欲善其事,必先利其器,工具的選擇不是越多人用越好。像Axure這類專業的原型制作軟件,在標尺、對齊上面,是上面所使用的iH5遠比不上的(后者得通過x|y坐標等精確控制),而且其還擁有眾多有手機圖標等模板,可以大大加快原型制作,但后者在與人溝通以及查看時有著優勢,并且隨著H5營銷的流行,其也可以快速制作出相關的營銷案例,并迅速在網上傳播,不用再依靠別人,或者重新學習其他制作工具,擁有更多的可操作性。

          本文由 @iood 原創發布于人人都是產品經理。未經許可,禁止轉載。


          主站蜘蛛池模板: 麻豆一区二区三区蜜桃免费| 精品理论片一区二区三区| 理论亚洲区美一区二区三区| 激情爆乳一区二区三区| 国产精品无码一区二区三区电影 | 亚洲AV无码一区二区三区性色| 成人在线观看一区| 中文字幕在线观看一区二区| 中文字幕日韩一区二区三区不卡| 国产成人一区二区三区高清| 无码AV天堂一区二区三区| 无码精品一区二区三区| 在线视频一区二区三区三区不卡| 日本在线视频一区二区| 成人精品一区二区三区中文字幕| 亚洲日本久久一区二区va| 亚洲第一区精品观看| 亚洲色精品VR一区区三区| 久久精品无码一区二区日韩AV| 国产精品一区二区久久| 一区二区三区内射美女毛片| 国产福利91精品一区二区| 国产一区二区精品尤物| 国产伦精品一区二区三区女| 一区二区三区免费在线视频| 亚洲av无码成人影院一区| 亚洲av一综合av一区| 精品国产不卡一区二区三区| 人妻精品无码一区二区三区| 无码欧精品亚洲日韩一区| 一区二区三区国模大胆| 国产一区二区在线观看麻豆| 濑亚美莉在线视频一区| 国产在线精品一区二区在线看| 成人区人妻精品一区二区三区 | 在线中文字幕一区| 亚洲欧洲日韩国产一区二区三区| 国产福利91精品一区二区三区| AV无码精品一区二区三区| 亚洲日韩一区二区三区| 在线观看一区二区三区视频|