三年中文在线观看免费大全_三年大片免费高清哔哩哔哩_三年在线观看免费大全哔哩_三年大全免费大片三年大片_三年在线观看免费大全_三年大片观看免费大全哔哩哔哩_三年中文在线观看免费高清第4版_三年中文免费视频大全_三年大片大全免费观看大全_三年大片在线观看哔哩哔哩_三年在线观看中文免费观看_三年成都中文在线观看免费版

微(wēi)信小(xiǎo)程序:使用(yòng)render函數(s €¶×hù)在canvas中布局生(shēng)成海(hǎi)報(bào)圖 £♣÷'- 新聞資訊 - 雲南(nán)小(xiǎo)程序開(kāi)發|雲南(nán)軟件(jiàn)γσ®開(kāi)發|雲南(nán)網站(zhàn)建設-雲南維串信息科技有限公司

159-8711-8523

雲南(nán)網建設/小(xiǎo)程序開(kāi)發/軟件(jiàn)開(kāi)發

知(zhī)識

不(bù)管是(shì)網站(zhàn),軟件(φ₽•δjiàn)還(hái)是(shì)小(xiǎo)程序,都(dōu)要(yà§↓βo)直接或間(jiān)接能(néng)為(wèi)ε•£γ您産生(shēng)價值,我們在追求其視(shì)覺表現(xiàn)的∏★β©(de)同時(shí),更側重于功能(néng)的(de)便>≠捷,營銷的(de)便利,運營的(de)高(gāo)效,讓網站(z₹€↔↕hàn)成為(wèi)營銷工(gōng)具,讓軟件(jiàn)能(nén♣≥∞g)切實提升企業(yè)內(nèi)部管理(lǐ)水(shuǐ)平÷'和(hé)效率。優秀的(de)程序為(wèi)後期升級提供便捷的(de)支持!

微(wēi)信小(xiǎo)程序:使用(yòng)render函數(shù)在c✔★©anvas中布局生(shēng)成海(hǎi)報(bào)圖

發表時(shí)間(jiān):2021-1-5

發布人(rén):葵宇科(kē)技(jì)

浏覽次數(shù):467

背景

一(yī)個(gè)常見(jiàn)的(de)需求,在開(kāi←ε)發微(wēi)信小(xiǎo)程序時(shí),前端需要(yào)€÷生(shēng)成海(hǎi)報(bào)圖分(fēn)享,目前常見(φ•jiàn)解決方案如(rú)下(xià):

  1. 使用(yòng)htmlCanvas庫,利用(yòng)dom來(lái)生(shēng)成圖片
  2. 前端使用(yòng)ctx的(de)api一(yī)個(gλ≠'₩è)一(yī)個(gè)的(de)畫(huà)出來(lái),或者借助一(yδΩπī)些(xiē)繪圖工(gōng)具
  3. 利用(yòng)puppeteer後端服務,打開(kāi)相(xiàng)應界面截圖
痛點:
  1. 這(zhè)個(gè)庫本身(shēn)并不(bù)能(néng)在小"‍(xiǎo)程序使用(yòng),因為(wèi)涉及到(dào)dom,在σ£×≈web端也(yě)有(yǒu)各種兼容性問(wèn)題比如(rú)某個(gè)屬性不(±±£bù)支持
  2. 這(zhè)個(gè)方案,額。。。可(kě)能(néng)這(zhè)就(jiù)是( φshì)程序員(yuán)頭發少(shǎo)的(de)原因吧(ba)。費(fèi)盡千辛萬苦>✔↕畫(huà)好(hǎo),萬一(yī)視(shì)覺調整≠ 一(yī)下(xià)。。這(zhè)個(gè)方案開(kāi)發費(fèi)€>時(shí)費(fèi)力,不(bù)好(hǎo)維護。雖然web端有(yǒu)react-ca♠₹Ω£nvas,小(xiǎo)程序也(yě)有(yǒu)一(yī)些(x₽>iē)工(gōng)具,但(dàn)目前都(dōu)隻是(shì)封裝了(le)♠'$≈繪制(zhì)矩形、文(wén)字等方法,對(duì)于布局來(lá'Ωi)說(shuō)還(hái)是(shì)需要(yào)手動計(jìδ™)算(suàn)寬高(gāo)以及位置,沒有(yǒu)完全解₹π¥決痛點。
  3. 這(zhè)種方案對(duì)前端來(lái)說(shuō)是(shì)最完美(měi)的(d₹≥≠e),也(yě)推薦大(dà)家(jiā)有(yǒu)條件(jiàn)用(yòng>♠★)這(zhè)個(gè)方案,前端寫好(hǎo)頁面放(fàng)到(dào)服務上(shàn×→÷ g),然後再挂一(yī)個(gè)服務訪問(wèn)這(zhè)個(gè)頁面來(láα♥i)截圖,因為(wèi)開(kāi)發和(hé)截圖的(de)都(dōu)是(shì)chr>÷↕omium,基本不(bù)存在兼容性問(wèn)題。但(dàn)是(shì)這(zhè)種方案會σ (huì)非常耗費(fèi)服務器(qì)資源,每次截圖都(dō≈δ‌§u)要(yào)打開(kāi)一(yī)個(gè)新的(de)₩∏浏覽器(qì)tab,并且截圖耗時(shí)比較長(cháng),對(duì)于一€'(yī)些(xiē)公司來(lái)說(shuō)可(kě)→∞™↔能(néng)無法接受。
簡介

easy-canvas實現(xiàn)了(le)在canvas中創建£​文(wén)檔流,api極易上(shàng)手基本沒有(yǒu)學習☆φ(xí)成本,可(kě)以很(hěn)輕松的(de)支持組件(jiàn)化(←Ω↔huà)開(kāi)發,并且沒有(yǒu)第三方依賴,隻要(yào)支持标準的(de)canva♥¶≠s就(jiù)可(kě)以使用(yòng),在實現(xiàn)¥±>★基本功能(néng)的(de)基礎上(shàng)添加了(le)事(shì)✔≤'件(jiàn)、scroll-view等支持。基礎版支持小(xiǎo)¶ ₽←程序、web。

如(rú)果使用(yòng)過render函數(shù)的(de)肯定π✘很(hěn)熟悉使用(yòng)方式了(le),相(xiàng)關屬性"<≠在項目裡(lǐ)以及示例裡(lǐ)都(dōu)有(yǒu)介紹,本篇文(w ∑↑én)章(zhāng)就(jiù)不(bù)過多(duō)介紹,基本使₽'≈用(yòng)如(rú)下(xià):

npm install easy-canvas-layγΩ×out --save
複制(zhì)代碼
    import easyCanvas from 'easy-canvas-layout'

    // 首先綁定圖層
    const layer = easyCanvas.createL§↔¥ayer(ctx, {
      dpr: 2,
      width: 300,
      height: 600,
      canvas   // 小(xiǎo)程序環境必傳
    })

    // 創建node 
    // c(tag,options,children)
    const node = easyCanvas.createElement(×♥λ☆(c) => {
      return c('view', { 
        styles: { backgroundColor:'#000' }, // 樣式
        attrs:{},                           // 屬性 比如(rú)src
        on:{}                               // 事(shì)件(jiàn) 如(rú)click lα≤¥oad 
      }, 
      [
        c('text',{color:'#fff'},'Hello World')
      ])
    })

    // mount
    node.mount(layer)

複制(zhì)代碼
vue中使用(yòng)

另外(wài)在基礎版本上(shàng),封裝了(le)相(xiàngγ‍↔)應的(de)vue組件(jiàn),相(xiàng)比render函數(sh®​ù),要(yào)簡潔易懂(dǒng)很(hěn)多(duō),基本使用(yòng)如(rú•→≤)下(xià):

npm install vue-easy-canvas --save
複制(zhì)代碼
import easyCanvas from 'vue-easy-canvas'
Vue.use(easyCanvas)
複制(zhì)代碼
<ec-canvas :width="300" :height="600">
    <ec-scroll-view :styles="{height:600}">

    <ec-view :styles="styles.imageWrapper">
        <ec-image 
            src="https://tse1-mm.cn.bing.net/th/id/OIP★&♣•.Dkj8fnK1SsPHIBmAN9XnUAHaNK?pid=Api&♦€&amp;rs=1" 
            :styles="styles.image" 
            mode="aspectFill"></ec-image>
        <ec-view :styles="styles.homeTitleWrapper">
        <ec-text>easyCanvas</ec-text>
        </ec-view>
    </ec-view>

    <ec-view :styles="styles.itemWrapper" 
        v-for="(item,index) in examples" 
        :key="index"
        :on="{
        click(e){
            windo‍‍↕←w.location.href = http://www.wxapp-unio'₹§‍n.com/host + item.url
        }
       ​∑≤ }">
        <ec-view :styles="styles.title">
        <ec-text>{{item.title}}</ec-text>
        </ec-view>
        <ec-view :styles="styles.desc">
        <ec-text>{{item.desc}}</ec-text>
        </ec-view>
    </ec-view>

    </ec-scroll-view>
</ec-canvas>
複制(zhì)代碼
支持元素
  • view 基本元素,類似div
  • text 文(wén)本 支持自(zì)動換行(xíng)以及超過省略等功能(néng),目前text實現(← "₽xiàn)為(wèi)inline-block
  • image 圖片 src mode支持aspectFit以及aspectFill,其他(tā)css特性同₽∞web 支持load事(shì)件(jiàn)監聽(tīng)圖片加載并且繪制(zhì)完成
  • scroll-view 滾動容器(qì),需要(yào)在樣式裡(lǐ)設置♣•®αdirection 支持x、y、xy,并且設置具體(tǐ)尺寸 設置renderOnDemand隻繪制(zhì)可(kě)見(jiàn)部分(fēn)
支持屬性

屬性使用(yòng)像素的(de)地(dì)方統一(yī)使用(yòng)¥•♣數(shù)字

  • display block | inline-block | flex, text默認是(sh∞←≥ì)inline-block的(de)
  • width auto 100% Number 這(zhè)裡(lǐ₹≥)盒模型使用(yòng)border-box,不(bù)可(kě≠'$®)修改
  • height
  • flex flex不(bù)支持auto,固定寬度直接使用(yòng)width
  • minWidth maxWidth minHeight maxHeight 如(rú)果設置了(le)具體(tǐ)寬度高(gāo)度不(bù)生( ≤®Ωshēng)效
  • margin marginLeft,marginRight,marginTop,marginBottom margin支持數(shù)組縮寫例如(rú) [10,20][10,20≠±,10,20]
  • paddingLeft,paddingRight,paddingTop,paddingBottom 同上(shàng)
  • backgroundColor
  • borderRadius
  • borderWidth borderTopWidth ... 細邊框直接設置0.5
  • borderColor
  • lineHeight 字體(tǐ)相(xiàng)關的(de)隻在text內(nèi)有(yǒu)效
  • color
  • fontSize
  • textAlign left right center
  • textIndent Number
  • verticalAlign top middle bottom
  • justifyContent flex-start center flex-end flex布局 水(shuǐ)"₹'×平方向對(duì)其
  • alignItems flex-start center flex-end flex布局 垂直方向對™♦σ×(duì)其
  • maxLine 最大(dà)行(xíng)數(shù),超出自(zì)動省略号,隻支持在te&∏©¥xt中使用(yòng)
  • whiteSpace normal nowrap 控制(zhì)換行(xí≈£★∏ng),不(bù)能(néng)控制(zhì)字體(tǐ),φ≤隻能(néng)控制(zhì)inline-block
  • overflow hidden 如(rú)果添加了(le)圓角,會(huì)自(zì)動加上(shàn∑‌♦g) hidden
  • flexDirection
  • borderStyle dash Array 詳見(jiàn)ctx.set↕' LineDash()
  • shadowBlur 設置了(le)陰影(yǐng)會(huì)自(zì)動加上‌λ(shàng) overflow:hidden;
  • shadowColor
  • shadowOffsetX
  • shadowOffsetY
  • position static absolute
  • opacity Number

例如(rú)這(zhè)個(gè)組件(jiàn)庫裡(lǐ)的(de)button組件(¶$<$jiàn)

正常來(lái)說(shuō)我們寫一(yī)個(gè)按鈕

.button{
    display:inline-block;
    background:green;
    color:#fff;
    font-size:14px;
    padding:4px 12px;
    text-align:center;
    border-radius:4px;
}
複制(zhì)代碼

在easyCanvas中的(de)寫法

function Button(c){
    return c('view',{
        styles:{
            display:'inline-block',
            backgroundColor:'green',
            color:'#fff',
            fontSize:14,
            padding:[4,12],
            textAlign:'center',
            borderRadius:4
        }
    },[
        c('text',{},'按鈕')
    ])
}
複制(zhì)代碼

是(shì)不(bù)是(shì)覺得(de)很(hěn)熟悉很(←Ωhěn)簡單,讓我們來(lái)寫一(yī)個(gè)可(kě)以接受參數(shù)的(Ω>‍φde)按鈕

function Button(c, { attrs, styles, on }, content) {
  const size = attrs.size || 'medium'
  const nums = SIZE[size]
  let _styles = Object.assign({
    backgroundColor: THEME[attrs.type.toUpperCase() || 'info'],
    display: 'inline-block',
    borderRadius: 2,
    color: '#fff',
    lineHeight: nums.lineHeight,
    padding: nums.padding,
    fontSize: nums.fontSize
  }, styles |σα₹| {})

  if (attrs.plain) {
    _styles.color = THEME[attr§↔β±s.type.toUpperCase()]
   €  _styles.borderWidth = 0.5
    _styles.borderColor = THEME[attrs.type.t©$©∞oUpperCase()]
    _styles.backgroundColor = PLA§ε≤♣IN_THEME[attrs.type.toUpperCase() || 'info']
  }

  if (attrs.round) {
    _styles£₩≈§.borderRadius = nums.borderRadius
  }

  return c('view', {
    attrs: Object.assign({

    }, attrs |>¶←¶| {}),
    styles: _styles,
    on: on || {},
  }, typeof content === 'string' ? [c('text', {}, content)] : content)
}
複制(zhì)代碼

這(zhè)樣在使用(yòng)的(de)地(dì)方可(kě)以傳入參數(shù),像這(zh蕱φ)樣,也(yě)就(jiù)是(shì)大(dà)家(jiā)在demo裡(lǐ)÷®δ看(kàn)到(dào)的(de)

Button(c, {
    attrs: { type: 'primary', plain: true },
}, '主要(yào)按鈕'),
Button(c, {
    attrs: { type: 'success', plain: true },
}, '成功按鈕'),
Button(c, {
    attrs: { type: 'info', plain: true },
}, '信息按鈕'),
Button(c, {
    attrs: { type: 'warning', plain: true },
}, '警告按鈕'),
Button(c, {
    attrs: { type: 'error', plain: true },
}, '危險按鈕'),
複制(zhì)代碼

并且,easyCanvas支持注冊全局組件(jiàn),方便調用(yòng)• •←,其他(tā)參數(shù)請(qǐng)看(kàn)項₽φ <目使用(yòng)文(wén)檔

// 注冊全局組件(jiàn)
easyCanvas.component('button',Button)

// 使用(yòng)全局組件(jiàn)
function Page(c){
    return c('button',{
        attrs: { type: 'warning', plain: true },
    }, '警告按鈕')
}
複制(zhì)代碼

另外(wài)easyCanvas內(nèi)置了(le)事(shì)件(jiàn)管理(∏$lǐ)器(qì),可(kě)以支持類似web中的(de)事(shì)件(jià↕↓€n),從(cóng)父級向子(zǐ)級執行(xíng)捕獲,子(zǐ)級♥↑φΩ再向父級冒泡。

首先需要(yào)讓canvas元素接管事(shì)件(jiàn)


// canvas元素監聽(tīng)鼠标事(shì)件(jiàn)
canvas.ontouchstart = ontouchstart
canva> ↕αs.ontouchmove = ontouchmove
canvas.ontoucσ ™hend = ontouchend
canvas.onmγ× £ousedown = ontouchstart
canvas.onm‍Ω©♠ousemove = ontouchmove
canvas.onmo‍÷useup = ontouchend
canvas.onmousewheelβ✔∏γ = onmousewheel


// 将事(shì)件(jiàn)交給事(shì)件®←←✘(jiàn)管理(lǐ)器(qì)接管 需要(yào)注意的(de)是(shì),↑×≤•這(zhè)裡(lǐ)的(de)坐(zuò)标是(shì)相(xiàng)對(≥₩≠×duì)于canvas元素的(de)坐(zuò)标,而不(bù)是(shì)屏幕
function ontouchstart(e) {
  e.preventDefault()
  layer.eventManager.tou ©σchstart(e.pageX || e.touches≥₩ [0].pageX || 0, e.pageY || e.touches[0].pageY || 0)
}
function ontouchmove(e) {
  e.preventDefault()
   ₽→layer.eventManager.touchmove(e.pageX÷α÷↓ || e.touches[0].pageX || 0, e.pageY || e.touches[0].pageY || 0)
}
function ontouchend(e) {
  e.preventDefault()
  la>'≤εyer.eventManager.touchend(
    e.pageX || e.ch↕>±✔angedTouches[0].pageX || 0,
    e.pageY || e.changedTouch↕®es[0].pageY || 0
  )
}
function onClick(e) {
  e.preventDefault()
  laye≤εr.eventManager.click(e.pageX, e.pageY↕₹ ↕)
}
function onmousewheel(e){
  e.preventDefault()
  lπφayer.eventManager.mousewheel(e.pageX,e.pageY,-e.∑→<♦deltaX,-e.deltaY)
}
複制(zhì)代碼

接管到(dào)事(shì)件(jiàn)後,我們就(ji✔∏ù)可(kě)以在元素內(nèi)監聽(tīng)事(shì)件(π‍¥jiàn)了(le)

c('button',{
    id:'測試按鈕',
    on:{
        click(e){
            // 阻止冒泡到(dào)父級
            e.stopPropagation()
     $π       alert(e.currentTarget.id) // alert 測試按鈕
        }
    }
},'點我點我')
複制(zhì)代碼

目前支持的(de)鼠标事(shì)件(jiàn)有(yǒu): click、touch•₹ start、touchmove、touchend、mou  →↕sewheel。

圖片支持 load、error事(shì)件(jiàn)

另外(wài),支持在layer中監聽(tīng)所有(yǒu)圖片請(qǐng)求完成,比如←">(rú)我們需要(yào)在圖片加載完成,reflow布局并且重新渲染後立即生(shēng)成圖片‍✘λ:

easyCanvas.createLayer(ctx, {
  ε'©γ  dpr,
    width,
    height,
    lifecycle: {
        onEffectSuccess(res) {
            // 所有(yǒu)圖片加載成功
        },
        onEffectFail(res) {
            // 有(yǒu)圖片加載失敗
        },
        onEffectComplet↓β•e(){
            // 隻要(yào)加載結束就(jiù)會(huì)調用(yòng)
            // 生(shēng)成圖片...
        }
    }
})
複制(zhì)代碼

easyCanvas還(hái)支持在初始渲染後對(duì)元素進行(xíng)操作(zuò)

// 獲取元素 key為(wèi)attrs中定義的(de)
el.getElementBy(key,value)

// 增加元素
el.appendChild(element)
el.prependCh×♦→ild(element)
el.append(element) // 加在當前元素後
el.prepend(element)

// 删除元素
el.removeChild(element)
el.remove(γ®)

// 修改樣式 內(nèi)部會(huì)根據樣式判斷是(shì)否需要(yào)rβΩeflow還(hái)是(shì)僅僅repaint就(jiù)足夠
el.setStyles(styles)
複制(zhì)代碼

demo中點擊左側右側定位代碼

c('view', {
    on: {
        click(e) {
            const target = layer.getElementBy✘£☆ ('id', item.en)[0]
            if (!target || e.currentTarget ===¥​₽× lastSelect) return
            const scrollView = layer.getElementBy('id', 'main')[1]
            scrollView.scrollTo({ y: target.y })
            e.c≠☆≤urrentTarget.setStyles({ backgroundColor: '#f1f1f1', color: '#333' })
            if (lastSelect) lastSelect.se≠↕$™tStyles({ backgroundColor: '' })
            lastSelect = e.cu✔ε₽rrentTarget
        }
    },
    styles: {
        padding: 10,
        color: '#666',
        fontSize: 16
    }
}, [c('text', {}, item.en + ' ' + item.zh)]))
複制(zhì)代碼
Ending

本篇文(wén)章(zhāng)主要(yào)介紹項目背景以及基本使用(yòng),也(yě)是≥✔¥(shì)為(wèi)了(le)給自(zì)己打個(gè)廣告吧(ba):) 後面會≠ ↑(huì)寫實現(xiàn)原理(lǐ)以及一(yī)些(xiē)坑,歡≥‌'π迎各位交流,感謝(xiè)閱讀(dú)!


作(zuò)者:FiyN
來(lái)源:掘金(jīn)
著作(zuò)權歸作(zuò)者所有(yǒu)。商業(yè)轉載請(qǐng)聯系δ♠作(zuò)者獲得(de)授權,非商業(yè)轉載請(qǐng)注₩‍♣明(míng)出處。

相(xiàng)關案例查看(kàn)更多(duō)

相(xiàng)關閱讀(dú)

三年中文在线观看免费大全_三年大片免费高清哔哩哔哩_三年在线观看免费大全哔哩_三年大全免费大片三年大片_三年在线观看免费大全_三年大片观看免费大全哔哩哔哩_三年中文在线观看免费高清第4版_三年中文免费视频大全_三年大片大全免费观看大全_三年大片在线观看哔哩哔哩_三年在线观看中文免费观看_三年成都中文在线观看免费版