<address id="ttjl9"></address>

      <noframes id="ttjl9"><address id="ttjl9"><nobr id="ttjl9"></nobr></address>
      <form id="ttjl9"></form>
        <em id="ttjl9"><span id="ttjl9"></span></em>
        <address id="ttjl9"></address>

          <noframes id="ttjl9"><form id="ttjl9"></form>

          首頁

          有趣的Canvas,你值得擁有!

          seo達人

          Canvas 是 HTML5 提供的一個用于展示繪圖效果的標簽. Canvas 原意為畫布, 在 HTML 頁面中用于展示繪圖效果. 最早 Canvas 是蘋果提出的一個方案, 今天已經在大多數瀏覽器中實現。


          canvas 的使用領域


          游戲

          大數據可視化數據

          banner 廣告

          多媒體

          模擬仿真

          遠程操作

          圖形編輯

          判斷瀏覽器是否支持 canvas 標簽


          var canvas = document.getElementById('canvas')

          if (canvas.getContext) {

          console.log('你的瀏覽器支持Canvas!')

          } else {

          console.log('你的瀏覽器不支持Canvas!')

          }

          canvas 的基本用法

          1、使用 canvas 標簽, 即可在頁面中開辟一格區域,可以設置其寬高,寬高為 300 和 150


          <canvas></canvas>

          2、獲取 dom 元素 canvas


          canvas 本身不能繪圖. 是使用 JavaScript 來完成繪圖. canvas 對象提供了各種繪圖用的 api。


          var cas = document.querySelector('canvas')

          3、通過 cas 獲取上下文對象(畫布對象!)


          var ctx = cas.getContext('2d')

          4、通過 ctx 開始畫畫(設置起點 設置終點 連線-描邊 )


          ctx.moveTo(10, 10)

          ctx.lineTo(100, 100)

          ctx.stroke()

          繪制線條

          設置開始位置: context.moveTo( x, y )

          設置終點位置: context.lineTo( x, y )

          描邊繪制: context.stroke()

          填充繪制: context.fill()

          閉合路徑: context.closePath()

          canvas 還可以設置線條的相關屬性,如下:


          CanvasRenderingContext2D.lineWidth 設置線寬.

          CanvasRenderingContext2D.strokeStyle 設置線條顏色.

          CanvasRenderingContext2D.lineCap 設置線末端類型,'butt'( 默認 ), 'round', 'square'.

          CanvasRenderingContext2D.lineJoin 設置相交線的拐點, 'miter'(默認),'round', 'bevel',

          CanvasRenderingContext2D.getLineDash() 獲得線段樣式數組.

          CanvasRenderingContext2D.setLineDash() 設置線段樣式.

          CanvasRenderingContext2D.lineDashOffset 繪制線段偏移量.

          封裝一個畫矩形的方法


          function myRect(ctxTmp, x, y, w, h) {

          ctxTmp.moveTo(x, y)

          ctxTmp.lineTo(x + w, y)

          ctxTmp.lineTo(x + w, y + h)

          ctxTmp.lineTo(x, y + h)

          ctxTmp.lineTo(x, y)

          ctxTmp.stroke()

          }


          var cas = document.querySelector('canvas')

          var ctx = cas.getContext('2d')

          myRect(ctx, 50, 50, 200, 200)

          繪制矩形

          fillRect( x , y , width , height) 填充以(x,y)為起點寬高分別為 width、height 的矩形 默認為黑色

          stokeRect( x , y , width , height) 繪制一個空心以(x,y)為起點寬高分別為 width、height 的矩形

          clearRect( x, y , width , height ) 清除以(x,y)為起點寬高分別為 width、height 的矩形 為透明

          繪制圓弧

          繪制圓弧的方法有


          CanvasRenderingContext2D.arc()

          CanvasRenderingContext2D.arcTo()

          6 個參數: x,y(圓心的坐標),半徑,起始的弧度(不是角度 deg),結束的弧度,(bool 設置方向 ! )


          var cas = document.querySelector('canvas')

          var ctx = cas.getContext('2d')


          ctx.arc(100, 100, 100, 0, degToArc(360))

          ctx.stroke()


          // 角度轉弧度

          function degToArc(num) {

          return (Math.PI / 180) * num

          }

          繪制扇形


          var cas = document.querySelector('canvas')

          var ctx = cas.getContext('2d')


          ctx.arc(300, 300, 200, degToArc(125), degToArc(300))


          // 自動連回原點

          ctx.closePath()

          ctx.stroke()


          function degToArc(num) {

          return (Math.PI / 180) * num

          }

          制作畫筆

          聲明一個變量作為標識

          鼠標按下的時候,記錄起點位置

          鼠標移動的時候,開始描繪并連線

          鼠標抬起的時候,關閉開關

          點擊查看效果圖


          var cas = document.querySelector('canvas')

          var ctx = cas.getContext('2d')


          var isDraw = false

          // 鼠標按下事件

          cas.addEventListener('mousedown', function () {

          isDraw = true

          ctx.beginPath()

          })


          // 鼠標移動事件

          cas.addEventListener('mousemove', function (e) {

          if (!isDraw) {

          // 沒有按下

          return

          }

          // 獲取相對于容器內的坐標

          var x = e.offsetX

          var y = e.offsetY

          ctx.lineTo(x, y)

          ctx.stroke()

          })


          cas.addEventListener('mouseup', function () {

          // 關閉開關了!

          isDraw = false

          })

          手動涂擦

          原理和畫布相似,只不過用的是clearRect()方法。


          點擊查看效果圖


          var cas = document.querySelector('canvas')

          var ctx = cas.getContext('2d')


          ctx.fillRect(0, 0, 600, 600)


          // 開關

          var isClear = false


          cas.addEventListener('mousedown', function () {

          isClear = true

          })


          cas.addEventListener('mousemove', function (e) {

          if (!isClear) {

          return

          }

          var x = e.offsetX

          var y = e.offsetY

          var w = 20

          var h = 20

          ctx.clearRect(x, y, w, h)

          })


          cas.addEventListener('mouseup', function () {

          isClear = false

          })

          刮刮樂

          首先需要設置獎品和畫布,將畫布置于圖片上方蓋住,

          隨機設置生成獎品。

          當手觸摸移動的時候,可以擦除部分畫布,露出獎品區。

          點擊查看效果圖


          <div>

          <img src="./images/2.jpg" alt="" />

          <canvas width="600" height="600"></canvas>

          </div>

          css


          img {

          width: 600px;

          height: 600px;

          position: absolute;

          top: 10%;

          left: 30%;

          }


          canvas {

          width: 600px;

          height: 600px;

          position: absolute;

          top: 10%;

          left: 30%;

          border: 1px solid #000;

          }

          js


          var cas = document.querySelector('canvas')

          var ctx = cas.getContext('2d')

          var img = document.querySelector('img')

          // 加一個遮罩層

          ctx.fillStyle = '#ccc'

          ctx.fillRect(0, 0, cas.width, cas.height)

          setImgUrl()

          // 開關

          var isClear = false

          cas.addEventListener('mousedown', function () {

          isClear = true

          })

          cas.addEventListener('mousemove', function (e) {

          if (!isClear) {

          return

          }

          var x = e.offsetX

          var y = e.offsetY

          ctx.clearRect(x, y, 30, 30)

          })

          cas.addEventListener('mouseup', function () {

          isClear = false

          })


          function setImgUrl() {

          var arr = ['./images/1.jpg', './images/2.jpg', './images/3.jpg', './images/4.jpg']

          // 0-3

          var random = Math.round(Math.random() * 3)

          img.src = arr[random]

          }

          更多demo,請查看 github.com/Michael-lzg…


          v-if 和 v-show的區別

          前端達人

          簡單來說,v-if 的初始化較快,但切換代價高;v-show 初始化慢,但切換成本低

          1.共同點

          都是動態顯示DOM元素

          2.區別

          (1)手段:
          v-if是動態的向DOM樹內添加或者刪除DOM元素;
          v-show是通過設置DOM元素的display樣式屬性控制顯隱;
          (2)編譯過程:
          v-if切換有一個局部編譯/卸載的過程,切換過程中合適地銷毀和重建內部的事件監聽和子組件;
          v-show只是簡單的基于css切換;
          (3)編譯條件:
          v-if是惰性的,如果初始條件為假,則什么也不做;只有在條件第一次變為真時才開始局部編譯(編譯被緩存?編譯被緩存后,然后再切換的時候進行局部卸載);
          v-show是在任何條件下(首次條件是否為真)都被編譯,然后被緩存,而且DOM元素保留;
          (4)性能消耗:
          v-if有更高的切換消耗;
          v-show有更高的初始渲染消耗;
          (5)使用場景:
          v-if適合運營條件不大可能改變;
          v-show適合頻繁切換。



          新版vue-router的hooks用法

          seo達人

          雖然Vue 3還沒有正式發布,但是熱愛新技術的我早已按捺不住自己的內心,開始嘗試在小項目中使用它了。


          根據這篇《今日凌晨Vue3 beta版震撼發布,竟然公開支持腳手架項目!》我搭建了一個Vue 3的腳手架項目,用這種方式搭建的腳手架項目不僅僅只有vue是新版的,就連vue-router、vuex都是的。


          給大家截一下package.json的圖:




          可以看到vue-router和vuex都已經開啟4.0時代啦!


          不過其實我并沒有去了解過vue-router 4.0的新用法什么的,因為我覺得它不像vue 3.0都已經進行到beta的版本不會有特別大的變動。


          而vue-router 4.0還是alpha的階段,所以我認為現在去學習它有些為時尚早。但卻就是它!差點釀成了一場慘劇。


          舊版vue + vue-router的使用方式

          假如你在路由里面定義了一個動態參數通常都會這么寫:


          {

             path: '/:id'

          }

          然后用編程式導航的時候通常會這樣去寫:


          this.$router.push('/123')

          在組件中是這樣獲取這個參數的:


          this.$route.params.id

          我以為的新版vue + vue-router的使用方式

          由于vue 3.0的Composition API中沒有this了,所以我想到了通過獲取組件實例的方式來獲取$route:


          import { defineComponent, getCurrentInstance } from 'vue'


          export default defineComponent((props, context) => {

             const { ctx } = getCurrentInstance()

             

             console.log(ctx.$route)

          })

          沒想到打印出來的居然是undefined!

          這是咋回事呢?

          于是我又打印了一遍ctx(ctx是當前組件上下文):




          沒有&dollar;的那些字段是我在組件中自己定義的變量,帶&dollar;的這些就是vue內置的了,找了半天發現沒有&dollar;route了,只剩下了一個&dollar;router,估計vue-router 4.0把當前路由信息都轉移到$router里面去了。


          帶著猜想,我點開了&dollar;router:




          currentRoute! 看名字的話感覺應該就是它了!于是乎我:


          import { defineComponent, getCurrentInstance } from 'vue'


          export default defineComponent((props, context) => {

             const { ctx } = getCurrentInstance()

             

             console.log(ctx.$router.currentRoute.value.params.id)

          })

          果然獲取到了!好開心!


          實際的新版vue + vue-router用法

          在接下來的過程中我用ctx.&dollar;router代替了原來的this.&dollar;router、用ctx.&dollar;router.currentRoute.value代替了原先的this.&dollar;route。


          盡管在接下來的進度中并沒有出現任何的bug,程序一直都是按照我所設想的那樣去運行的。


          但在項目打包后卻出現了意想不到的bug:在跳轉路由的時候報了一個在undefined上面沒有push的錯誤。


          奇了怪了,在開發階段程序都沒有任何的報錯怎么一打包就不行了呢?根據我多年的開發經驗,我很快就定位到了是vue-router的錯誤。


          難道這樣寫是錯的嗎?可是我打印了ctx,它里面明明有一個&dollar;router、&dollar;router里面明明就有currentRoute、currentRoute里面明明就有一個value、value里面明明就有params、params里面我一點開明明就看到了傳過來的參數啊:




          估計可能是vue-router的bug,果然alpha階段的產物不靠譜,我開始后悔使用新版的vue腳手架項目了。


          vue-router里的hooks

          不過這時我突然靈光一現,vue 3不是受到了react hooks的啟發才產生了Composition API的嗎?


          那么估計vue-router肯定也會受到react-router的啟發了!


          還好我學過react,果然技多不壓身??!估計里面肯定是有一個useXxx,就像這樣:


          import { useXxx } from 'vue-router'

          那么應該是use什么呢?按理來說應該會盡量的和以前的API保持一定的聯系,我猜應該是useRoute和useRouter吧!


          為了驗證我的想法,我打開了node_modules找到了vue-router的源碼:




          果不其然,在第2454和第2455行我發現它導出了useRoute和useRouter,那么就是它了:


          import { defineComponent } from 'vue'

          import { useRoute, useRouter } from 'vue-router'


          export default defineComponent(_ => {

             const route = useRoute()

             const router = useRouter()


             console.log(route.params.id)

             router.push('/xxx/xxx')

          })

          使用這種方式不但可以成功跳轉路由,也同樣可以獲取到路由傳過來的參數,這次再打包試了一下,果然就沒有之前的那個報錯了。


          結語

          估計以后的vue全家桶要開啟全民hooks的時代了,在翻看源碼的同時我發現他們把一些示例都寫在了vue-router/playground文件夾下了,在里面我發現了一些有趣的用法。


          如果有時間的話我會仔細研究一下然后出一篇更加深入的文章給大家,當然如果已經有小伙伴等不及我出新文章的話可以直接進入vue-router-next的github地址:


          https://github.com/vuejs/vue-router-next

          它的示例都放在了playground這個文件夾下,期待你們研究明白后出一篇更加深入的文章!

          B 端設計師如何做競品分析?

          資深UI設計者

          將要分析的競品排了個期,從最難最不熟悉的開始。為什么從最難的開始,可能是個人習慣吧,吃掉最難的那個,后面就會更上手。突然想起之前讀的一本書「吃掉那只青蛙」,很不錯的一本書,有時間去溫習下。

          一個產品,其實會有很多功能點,有核心的主要功能,也有一些輔助功能,也會有一些讓你忽略,但關鍵時刻很需要的應急功能,而這些點都需要去整理出來。

          分析前-熟悉產品

          這一點很重要,要先熟悉產品。如果對產品都不熟悉,那還是先不要做競品分析。因為很難判斷競品的功能和風格是否也適合當前產品,因為對產品的不熟悉,會產生誤判。

          當然,產品的目標人群,產品定位,適用范圍等等,都會影響產品分析。

          所以,花時間熟悉自己負責的產品,是不能跳過的。

          開始前的準備

          1. 制定時間規劃

          最好事先做好時間規劃,可以有一整塊的時間,這樣分析產品時,思緒也會比較完整和連續,可以更專注。計算大概分析一個產品需要花費的時間,最好不要用零碎時間來做,這樣只會增加時間上的代價,也會增加挫折感;

          2. 確定分析的目的

          在「競品分析」中,想要得到的結論和重點是什么。比如重點可能是產品的報表功能、產品的代碼審核功能等等,目的的確定能讓分析更有針對性,減少干擾。無目的隨意分析,得到的結果也會是零亂不堪,最后只是在浪費時間。

          3. 尋找幫助者

          每個產品,都有其不一樣的特性和產品邏輯,你不一定能夠完全 cover 到,甚至有些點就是比較難理解的,特別是偏技術性的名詞,這時若有技術同學的幫助,就會如虎添翼。所以最好可以事先找一位產品相關的技術同學,詢問這段時間是否有空,幫助你解答一些問題。

          個人建議:能夠在網上查到的資料,就不要先問人,除非時間成本特別高。一方面也是提升自己解決問題的能力,另一方面,也是節省彼此的時間。對方愿意幫你解決問題,不代表你要把所有問題一股腦倒給他,自己了解后再問,也是對對方的尊重,大家的時間都同樣寶貴。

          4. 其他tips

          如果是內部公司產品,提前確認是否需要權限,提前申請好,減少正式開始后,還要等待審批時間。外部產品可以提前找好網站,可以咨詢的客服入口,如果是付費競品,咨詢是否可以向財務申請報銷等等。

          好,現在正式開始吧!

          1. 像個用戶一樣去使用產品

          很多時候,設計師的職業病,會讓我們過多注重視覺享受,而忽略作為用戶,想要的有時候只是功能可用。今天不管你把「掃一掃」功能做得多美,美得像個藝術品一樣,可是當掃碼付款的時候,怎么也掃不出來,那種站在店家前面忐忑不安,怎么也無法完成付款,后面一堆人等你,你仿佛聽見后面其他顧客竊竊私語地討論著發生什么事情。那種場景我相信你不想經歷,同樣我們也不應該讓用戶來經歷。

          我的項目主管,一直都有提醒我,要像個小白來使用和設計我們的產品。這句建議,也一直在提醒著我。如果站在高姿態來俯視用戶,我們就很難真正的「懂」用戶,進而很難設計出真正滿足用戶需要的產品。

          這是競品分析,但是我們也需要轉換自己的角色,變成用戶。這樣能更明白究竟競品帶給用戶是便利,還是麻煩。有時適時抽離「設計師」的角色,會讓你更能去體會用戶的感受。

          所以,先去用這個產品吧,然后才會有然后。

          2. 如何去使用競品

          一個產品的使用,總是有它的使用場景,手機端的就更多樣了,簡直無所不在。B 端產品可能會相對少,一般是在辦公場景或是特定場景。

          可以像個編劇一樣,給自己寫點劇本,加點情節,塑造一個角色,假設競品是電商方向,你可以想像,自己是一個剛畢業的社會新人,你可能沒多少錢,你可能剛拿到你人生第一桶金,你想買件衣服犒勞自己,或許你會是數碼控,你關注已久的佳能單反在雙 11 中有優惠等等,然后再去預想接下去的情節,在購物方面會考慮的問題,或許是好用,或許是有趣等等。

          也可以做任務式去使用產品,比如以電商為例,任務可以是買件喜歡的衣服,從搜索產品,到找到喜歡的衣服,添加購物車,提交訂單,等待發貨,收貨,確認收貨。這一個完整的流程走下來,就會體驗產品功能是否好用,搜索結果是否符合預期等等。

          3. 記錄

          使用產品的過程中,會遇到很多情況,有些是可預期的,有些是不可預期的。有些讓人覺得很好用,有些卻會讓人受挫。將這些情況都記錄下來,有助于分析產品的可用性程度和滿意度。

          • 愉快的:可能是一個友好的提示,減輕你的認知負擔,也可以是一個貼心小 loading 動畫等等
          • 受挫的:點擊沒有反饋,提交后沒反饋,不知道執行成功與否等等
          • 難以理解:產品中專業名詞太多,沒有附帶解釋和幫助文檔,完全不知其所以然
          • 產生誤解:以為是 A,結果是 B
          • 一臉懵:頁面太亂,不知從哪里下手

          上面這些只是舉例說明,在競品當中可能遇到的一些問題,也可以去反思自己的產品是否也會這樣讓用戶感到困惑。有時候,太熟悉自己的產品,會自認為產品很完美,會理所當然認為「大家都這么認為」……

          記錄問題、原因,感受并截圖為證(有必要可錄屏),后期可追溯。寫得越詳細越好,后面整理的時候會更清晰。

          4. 各個擊破-功能了解

          在熟悉整個產品后,就需要對產品的各個功能進行分析了解、梳理。了解競品的核心功能是什么,核心功能在解決用戶什么問題,是否真的解決了用戶的痛點,其他功能又在整個產品當中充當什么樣的角色。

          將競品的功能與本產品功能對比,不只是對比有無,更進一步地去想,為什么有這個功能,為什么沒有這個功能,有或沒有是否會提高用戶的使用效率,用戶的留存,用戶的體驗等等。

          功能多不代表好,如果功能不能給用戶帶來益處,其實它的存在只是增加開發成本而已。

          整體總結

          其實競品分析中,最難的是總結歸納。做了一堆的分析后,結論是什么呢,這個結論如何寫呢?

          可以先從設立分析目的開始,找到中心軸線,然后再慢慢延展開來。在要做總結報告時,你會欣喜地發現最初設立目標是多么的重要。

          文章來源:優設    作者:箴鹽設計

          這10個設計原則,是確保金融類產品體驗優秀的核心要義

          資深UI設計者

          1、

          如何讓郵件體驗設計更加吸引人?

          資深UI設計者

          互聯網時代的人們早就受夠了信息爆炸,我們每天都會經系統推送、應用通知、微信、電話、短信等各類渠道收到大量消息。有多久你沒有查收自己的郵箱?就算打開郵件,又有多少推薦內容讓你有興趣進一步了解?是 EDM 老了沒用了?真正的原因,可能是我們一開始就錯誤地忽視了 EDM 設計。

          對于 95 后以及更年輕的群體來說,EDM 確實是個上了年紀的概念。EDM(Email Direct Marketing)也叫 Email 營銷、電子郵件營銷。企業向目標客戶發送 EDM 郵件,建立同目標客戶的溝通渠道,向其直接傳達相關信息,用來促進銷售轉化。

          這個起源于上世紀 80 年代中期,正式誕生于 90 年代的早期互聯網產物現在已經三十多歲了。時至今日,EDM 早已成為了全球公認的網絡營銷重要方法之一,其卓越效果為互聯網人數十年的實踐所證實。但 EDM 在我國的應用還處于非常低級的水平,不僅沒有系統的理論,在實踐中也存在許多誤區。

          在這樣一個重視審美與強調更新及時的時代,EDM 郵件樸實無華的外表與「一旦發出就固定呈現」的內容特質顯得有些格格不入。作為用戶體驗設計師,我們可以做什么讓 EDM 不落伍呢?

          避免成為垃圾郵件

          首先,我們可以在設計層面上避免 EDM 郵件被郵箱軟件識別為垃圾郵件,不帶敏感詞語或內容、淡化商業廣告色彩、減少數字與附件使用都有助于降低被郵箱系統屏蔽的風險。我們更可以在全量發送前,對指定郵箱進行小范圍測試以確保郵件發送成功率。

          其次,從其歷史來源來看,早期的 EDM 來源于垃圾郵件,這使人們對其本能地缺乏好感,存在排斥心理。因此 EDM 的節奏和時機必須做好控制,對郵件發送的各類數據做好統計,掌握用戶的閱讀習慣,能更好地提升郵件的打開率。

          保持最佳郵件格式

          郵件內容需要設計為一定的格式來發送,常用的郵件格式包括純文本格式、HTML 格式和 Rich Media 格式,或者是這些格式的組合。一般來說,HTML 格式和 Rich Media 格式的電子郵件比純文本格式具有更好的體驗效果。但 Rich Media 格式的電子郵件易造成郵件過大,并且無法確保用戶在客戶端均能夠正常顯示,所以在設計時我們優先選擇 HTML 格式郵件。

          確??缍梭w驗

          與網頁不同,我們無法針對不同設備做郵件內容相應的適配設計,兼顧設備特性的通用模版也就成為了設計時的必要關注點。對用戶來說,一封郵件閱讀體驗很差,那么無論郵件的內容多么精彩、多么吸引人,最終的結果也可能只會被丟棄在一邊。因此,我們通常會按照移動端尺寸對郵件界面進行設計,注意字體大小、最佳尺寸以及鏈接按鈕的大小等。

          除此以外,郵件中鏈接的定義也應得到我們充分的重視。由于郵件中的鏈接我們同樣無法預先針對不同打開設備進行單獨編輯,在有條件的情況下我們可以對鏈接所跳轉的頁面進行響應式設計以確保高質量的跨端瀏覽體驗,或者我們也可以采用默認跳轉路徑而后重定向的傳統方式。

          與「我」緊密相關

          EDM 營銷與一般的營銷方式最大的區別是:EDM 是一對一的溝通,讓用戶感覺到尊重,讓他感覺到這是為他所建立并且是他所獨享的溝通方式。在標題、正文的文案上強調「我」,在內容上也應如此。用戶在意什么,我們就發送什么。把握住用戶關注的信息,幫助用戶收集支持 TA 做決策所需的信息。當我們發送郵件給用戶,給予其操作行為的反饋或提醒時,不要浪費這最好的營銷機會。優先提供給用戶與之行為或特征相關的服務與幫助,其次通過個性化服務或產品推薦促進購買或注冊轉化,有助于我們將營銷機會轉化為實際銷售成果。

          兼顧質量和效率

          做好個性化對 EDM 內容模型要求頗高,但從設計角度講,我們完全可以以原子設計思維實現郵件內容模塊的低成本創建與復用。以通用設計模塊為「殼」,內容與組合規則為「核」,快速響應 EDM 的運營需求。

          以上 5 點就是我結合近期項目經驗所得。EDM 雖老,但設計可以讓 EDM 老而彌新。祝經你精心設計的 EDM 郵件,一經發出,封封有回應

          文章來源:優設    作者:魚子醬聊設計

          用4個經典的重量級產品案例,告訴你什么是標桿式體驗設計

          資深UI設計者

          今天和大家聊一個很多朋友常年卡在 P5/P6 需要關心的命題——如何從業務出發打造具有商業價值還能兼顧用戶體驗的設計,此篇不談理論,就通過 4 個經典的重量級產品案例就給大家安排明白啥是「一拳超人」式體驗設計——就一個字「強」。

          滴滴出行-xpanel

          滴滴出行應該屬于大家的高頻使用 app,但是使用的功能一般還是集中在叫車流程,所以大家可能不太會關注到 CDX 設計團隊一個非常核心的設計成果——xpanel。

          簡單來說 xpanel 就是一個附著于第一信息架構層級上,垂直 Y 軸且支持 X 軸拓展滑動的 Feed 卡片位。內容上分為「消息卡片」「主體卡片」「拓展卡片」三個維度,首屏保障除了「消息」與「主體」外三分之一「拓展卡片1」的露出。

          但在簡單的交互背后蘊藏的是基于業務的 UGD(用戶增長設計)設計思考,這里引用 2018IXDC 會上滴滴主講人的原話來說就是:

          對特定場景垂直領域的深耕和挖掘,尋找「接觸點」,幫助獲取更多的功能、內容、服務、特性、品牌、運營甚至是喜好……進而實現業務的「有效增長」(轉化、變現、留存)。

          通俗一點解釋就是 xpanel 利用主卡與拓展卡之間的信息架構關系,把拓展卡平衡的分為幾類,比如「與產品功能相關的卡片」「與運營相關的卡片」等。

          把本來被 LBS 地圖一屏內搶占的空間通過簡易的交互模式補償回來了,這樣既不打破用戶的核心體驗 focus 在地圖與主卡上,同時又增強了運營、功能的玩法與拓展,可謂雙贏。

          根據這幾年滴滴 xpanel 的線上應用,拓展卡片基本挖掘涵蓋了以下場景的露出:優惠福利、出現卡券、會員體系、安全相關、出行提醒、拉新導流、運營活動等,未來可拓展的價值內容會更多。看著各路出行類 app 又紛紛長期沿用 xpanel 的設計,想必線上的數據反饋應該也是很正向的。

          抖音-TopView

          在上篇文章《多維度解析 | 抖音vs快手的產品設計策略差異》中的商業化模塊里簡要提及過抖音的 Topiew 超級廣告位,這里單獨拿出來和大家解析一下它究竟有多6。

          從功能角度看,它是一個從開屏延續到端內視頻信息流的廣告位,占據了用戶從進入抖音的第一視覺。

          從交互角度看,topview 主要展現以開屏沉浸式視頻 3s 播放→淡出互動轉化組件 3s(完美融入原生視頻信息流),剩余操作手勢與功能等同原生視頻信息流。

          在這樣一個有著 1 億+第一曝光的產品位置,單純只做常規靜態開屏穩當入賬不香嗎?事實是抖音確實讓它不香了,沒有創新就沒有新的收獲?;跇I務和當前產品形態下的交互模式使抖音有一個天時地利的優勢——沉浸式體驗,在這樣的交互模式下給視頻化的開屏提供了很好的承接入口。從開屏開啟到融入信息流,在交互形態的切換中又為廣告內容的播放時長贏得了更多時間。

          更可怕的一點是 3s 播放后融入原生視頻信息流中的 TopView 除了正常收割廣告轉化帶來的單量,還可以通過右側的主頁鏈接輕松引流進行粉絲沉淀(今天就算你不買,先關注我,成為我的潛在用戶,來日我再推一個新商品視頻,你可以第一時間看見也許感興趣就買單了)。

          說完這些大家仔細回憶一下平常我們接觸的有視頻廣告的視頻平臺,別說 60s、30s,15s 我們都嫌長,但為啥 TopView 顯得相對沒那么惹人煩呢(上次留的思考題)?個人認為除了抖音在選擇合作品牌時會傾向符合平臺氣質的品牌合作(細數它合作過的品牌:Mac、寶馬、林肯、vivo 等)保障廣告質量和提供「跳過」外,直接融入信息淡出的互動組件會不僅會給用戶新奇感,還會激發用戶的互動欲望。

          最后看一組數據(與寶馬合作數據),曝光數:1.1 億+;有效播放率:53.82%;點擊率:13.26%。所以你猜一個最長可以展示 60s 的品牌視頻內容、同時進行品牌粉絲沉淀、良好體驗帶來更高有效播放的億級曝光廣告位能值多少錢?

          淘寶-二樓

          2016 年淘寶啟動了一個項目要做一款內容化欄目——以視頻為主,每晚更新一期,類比「一千零一夜」的故事。

          那么在滿滿當當的淘寶運營區里該選擇哪一個來試玩這個有趣的「新欄目」呢?是在頭部的 10 宮格里再擠進去一個圖標呢?還是在熱門推薦里擠出一個 tab 呢?還是做一個懸浮的右下角的運營位?顯然都不太合適。

          根據這款產品每晚 6 點鐘才可以使用,早上 7 點就會消失的游戲規則,最適配它的入口是一個不占界面原生空間,同時又有一定儀式感的位置。于是下拉 loading 的大空區成為了設計師們考慮的陣地。

          △ 不知道這個banner為什么要排擠我

          但地方選好了,又有了新顧慮。因為 iOS 的用戶基本被系統洗腦了下拉手勢,對于他們來說下拉=刷新,貿然在下拉刷新的手勢基礎上再疊加一個無關聯的結果顯然是有風險的。因此從交互上需要界定 2 個維度的指標來保障新欄目的體驗。

          • 下拉速度(速度臨界值:速度多快?→刷新,多慢?→新欄目)——以速度為優先衡量指標(只要速度快,拉的距離再大也是→刷新)
          • 下拉距離(距離臨界值:拉到多少距離進入新欄目?)——兼顧單手用戶操作難度

          反復試錯 2 個指標數據的實際體驗之后,新欄目有了安身之所,賜名「二樓」。進入「二樓」的整體交互和現在的短視頻產品玩法基本雷同,全屏豎滑切換,小圖標帶貨。下拉加載位的開發,從普通 loading 動效到運營位的植入基本被各類電商平臺輕松復刻了,因此這一切看上去更沒什么了得,但對于原創來說那畢竟是 4 年前。

          豆瓣-疊加上滑板

          談到豆瓣我算是半個老用戶了,豆瓣自身是個比較復雜的集合多條業務線分支(「小組」「同城」「閱讀」「音影」……)的多生態產品,這里我們主要拿它 18 年 6.0 大改版中影音模塊的詳情頁大改造來說事兒。

          △ 可能有很多人已經忘記6.0前的豆瓣電影詳情頁長啥樣了,帶你回顧一下。

          看完對比圖,視力正常的朋友乍一看都能看出 6.0 版詳情頁整容得有多成功。但具體成功在哪里,可能不僅僅是好看這么簡單。

          大背景從海報上智能取色雖然不算是什么稀奇的做法,但是加了適度的漸變應用在這里也可以說是非常的恰到好處了。另外深底色和視覺比重加大的外鏈區都突顯了「第三方播放」與「購票選座」的視覺感知。讓用戶沉浸在電影詳情中并引導他們走向「豆瓣的主要收入來源之一——電影票分銷與第三方視頻播放產品引流」正好是 6.0 豆瓣改版一個「小小的目標」——更務實(商業化)。

          從交互層面看,且不說評論頭部吸底這個事情是不是也是因為 6.0 商業化的影響(評論區增加「話題」進行重點運營),這個交互本身我覺得還是很強大的。強大的體現在于良好的空間收納能力與信息拓展能力。我給它起了個好聽的名字叫-疊加上滑板(不好聽也認了吧,畢竟也沒有內部人員告訴我他們是不是起名字了)

          這里可能又會有很多人質疑它與用戶已洗腦的上滑手勢之間的沖突,這點解釋起來和上文淘寶「二樓」有些類似,區別是豆瓣并沒有做上滑速度 or 距離的臨界值,只是把滑動區域做了隔離。而對比它的效仿者 boss 直聘,人家倒是在交互上做了進一步優化,適配自己的產品情況做了上滑疊層卡隱藏和上滑距離臨界值。

          這個故事告訴我們,要抄也要抄得比人家的交互更優秀才不丟人昂。

          文章來源:優設    作者:Nana的設計錦囊

          前端實現生成帶有樣式的excel表格 Node和瀏覽器讀寫Excel文件探究實踐

          seo達人

          最近碰到個需要自動生成表格的任務,作為前端的我,就想在 node 和瀏覽器中生成強大的表格,所以特此研究了很多關于表格的 npm 庫

          支持讀寫 Excel 的 node.js 模塊

          node-xlsx: 基于 Node.js 解析 excel 文件數據及生成 excel 文件,僅支持 xlsx 格式文件

          js-xlsx: 目前 Github 上 star 數量最多的處理 Excel 的庫,支持解析多種格式表格 XLSX / XLSM / XLSB / XLS / CSV,解析采用純 js 實現,寫入需要依賴 nodejs 或者 FileSaver.js 實現生成寫入 Excel,可以生成子表 Excel,功能強大,但上手難度稍大。不提供基礎設置 Excel 表格 api 例單元格寬度,文檔有些亂,不適合快速上手;普通版本不支持定義字體、顏色、背景色等,有這個功能需要的可以使用 pro 版,是要聯系客服收費的,害我照著 API 設置調試了好多次都失敗。好在樣式設置問題有一些教程,通過研究本人已解決,可設置寬度顏色等等,見根目錄本人修改的 xlsx.js

          xlsx-style 基于 xlsx 封裝的樣式庫,可以在 xlsx 的基礎上設置樣式。樣式不全,寬度都設置不了,好多年前作者就不維護了.寬度設置問題本人已解決了,見修改的 xlsx-style.js 文件

          exceljs 在使用此庫之前,本人已花費了很大的精力,用以上庫做好了表格,但是發現不能設置頁眉頁腳,添加圖片,打印選項設置等等,直到發現了這個庫,文檔齊全,功能強大,并且還免費.但是star較少,差一點就錯過了。本教程主要針對這個庫

          代碼庫地址

          https://github.com/lingxiaoyi/excel

          安裝

          npm install


          npm install -g nodemon


          調試使用,替代 node 命令,實現保存文件,node 自動重新啟動執行,必須全局安裝才能運行


          使用

          nodemon app.js


          js-xlsx 具體 api 使用方法請參考 main.js demo 使用,app.js 中修改為 require('./src/main.js');

          exceljs 具體 api 使用方法請參考 main-exceljs.js demo 使用,app.js 中修改為 require('./src/main-exceljs.js');

          因為每次生成完表格,每次都需要打開表格查看樣式,在 windows 電腦中,打開表格之后就鎖定不能生成新文件了,本來想著能導出一個 html 文件對應表格的樣式


          node 調試

          vscode 中打開調試右側設置編輯,將下方代碼復制進去,點 nodemon 啟動就可以進行 debug 調試了


          {

               "type": "node",

               "request": "launch",

               "name": "nodemon",

               "runtimeExecutable": "nodemon",

               "program": "${workspaceFolder}/app.js",

               "restart": true,

               "console": "integratedTerminal",

               "internalConsoleOptions": "neverOpen",

               "skipFiles": ["<node_internals>/**"]

             },

          webpack 目錄的作用

          每次生成完新表格,都需要重新打開表格查看樣式,在 windows 電腦中,打開表格之后就鎖定了,再次生成新表格就會報錯,文件已鎖定,不能寫入,對于想偷懶的我,能不能實現像 webpack 熱更新功能那種,修改樣式 js 頁面自動更新呢?


          wps 自帶另存 html 文件功能,但是沒有提供生成的 api ,網上也搜索不到對應的轉換功能,

          本來以為自己要實現一套表格轉 html 的功能。通過不斷嘗試,偶然間發現手機瀏覽器可以直接打開預覽 xlsx 文件,內心狂喜啊


          使用方法

          進入 webpack 目錄安裝依賴包,安裝好之后執行


          npm run dev


          啟動成功之后,會自動打開帶有 ip 地址的預覽地址,此時在電腦瀏覽器會自動下載 xlsx 文件,忽略不管,用手機直接打開此地址,就能看到 xlsx 表格的內容了,并且每次新修改內容和樣式,都會自動刷新頁面顯示新表格.


          小技巧

          谷歌瀏覽器插件:


          生成二維碼的插件生成二維碼方便手機掃描

          劃詞翻譯 用來翻譯一些看不懂的英文文檔

          browser 目錄

          瀏覽器中實現生成 xlsx 表格方法


          進入 browser 目錄安裝依賴包,安裝好之后執行


          npm run dev


          啟動成功之后,拖動根目錄 src 下的李四表格到頁面上的輸入框里,成功生成表格之后會生成一個下載鏈接地址,右鍵在新標簽頁打開鏈接,即會生成一個新的表格文件出來,完整 api 使用和 demo 文件請參考 index.js


          vue 和 react 用法可以參考此例子,如果有必要也可以此版本庫的例子


          一些概念

          在使用這個庫之前,先介紹庫中的一些概念。


          workbook 對象,指的是整份 Excel 文檔。我們在使用 js-xlsx 讀取 Excel 文檔之后就會獲得 workbook 對象。

          worksheet 對象,指的是 Excel 文檔中的表。我們知道一份 Excel 文檔中可以包含很多張表,而每張表對應的就是 worksheet 對象。

          cell 對象,指的就是 worksheet 中的單元格,一個單元格就是一個 cell 對象。

          xlsx 使用注意事項

          constXLSX = require('xlsx');

          let html = XLSX.utils.sheet_to_html(workbook.Sheets.Sheet1)

          生成 html 的用法,并且不會有任何樣式


          exceljs 使用注意

          讀取文件問題

          因為 exceljs 讀取文件不支持 sync 同步讀取,給的實例也是 await 例子.導致我讀取完遇到一個問題,就是老是生成不成功,最后發現必須要把所有邏輯全部放入函數中,像下方這樣


          (async function (params) {

           let res = await workbook.xlsx.readFile(`${__dirname}/趙六.xlsx`);

           //執行所有數據處理邏輯

           //執行寫的邏輯

           workbook.xlsx.writeFile(path.resolve(__dirname, '../webpack/test222.xlsx'));

          });

          所有邏輯全部要寫入這個函數中,這樣本來是可以的,但是出錯調試幾率較大,并且讀取到的數據龐大還需要額外處理,所以我讀取數據邏輯就用的 node-xlsx,十分簡單方便,如果你用的 exceljs 讀取文件數據出現問題,大概率是異步同步邏輯搞錯了,多加注意即可

          寬度設置

          列寬不知道是以什么為單位,反正不是像素(已測量),例子中是以厘米為單位再乘以 4.7 的結果設置的,4.7 是不斷測試的結果.

          快捷查看列寬的方法,打開 wps 表格,長按列與列字母間的豎線,就能看到列寬,取厘米的單位即可.見下圖




          前景色

          前景色設置必須右鍵單元格選擇設置單元格格式,然后選擇圖案樣式選擇顏色,就可以前景色填充

          worksheet.getCell('A2').fill = { type: 'pattern', pattern:'darkTrellis', fgColor:{argb:'FFFFFF00'}, bgColor:{argb:'FF0000FF'} };


          背景色

          worksheet.getCell('A2').fill = { type: "pattern", pattern: "solid", fgColor: { argb: next.bgColor }, }


          排版不一致的問題

          解決 Mac 下編輯 Microsoft Office Word 文檔與 Windows 排版不一致的問題,,不同的系統用 wps 打開相同的表格,打印預覽的時候,表格寬度顯示不一樣

          問題詳細說明地址


          我的解決辦法就是 mac 下顯示正常,按 mac 下的寬度來設置就可以了


          參考資料

          exceljs

          node-xlsx

          js-xlsx

          日歷

          鏈接

          個人資料

          藍藍設計的小編 http://www.syprn.cn

          存檔

          亚洲va欧美va天堂v国产综合