canvas.uvue 7.0 KB
Newer Older
X
xty 已提交
1
<template>
2 3
  <view class="page" id="page-canvas">
    <canvas id="canvas" class="canvas-element"></canvas>
4
    <scroll-view class="scroll-view">
5 6
      <!-- #ifdef WEB -->
      <button class="canvas-drawing-button" @click="canvasToBlob">canvasToBlob</button>
7
      <view>
8 9 10 11 12 13 14
        <text>testToBlobResult: {{testToBlobResult}}</text>
      </view>
      <!-- #endif -->
      <button class="canvas-drawing-button" id="toDataURL" @click="canvasToDataURL">canvasToDataURL</button>
      <view class="text-group" v-if="dataBase64.length>0">
        <text>canvasToDataURL:</text>
        <text>{{dataBase64.slice(0,22)}}...</text>
15
      </view>
16
      <button @click="onCreateImage">createImage</button>
H
hdx 已提交
17 18
      <button @click="onCreatePath2D">createPath2D</button>
      <button @click="startAnimationFrame">requestAnimationFrame</button>
19
      <button @click="stopAnimationFrame">cancelAnimationFrame</button>
20 21 22
      <view style="padding: 8px 10px;">CanvasContext API 演示</view>
      <navigator url="./canvas-context">
        <button>CanvasContext API</button>
DCloud-WZF's avatar
DCloud-WZF 已提交
23
      </navigator>
24

25 26 27 28 29 30 31 32
      <view class="text-group">
        <text>获取 CanvasContext 结果:</text>
        <text id="testCanvasContext">{{testCanvasContext}}</text>
      </view>
      <view class="text-group">
        <text>测试 ToDataURL 结果:</text>
        <text id="testToDataURLResult">{{testToDataURLResult}}</text>
      </view>
33

34 35 36 37
      <view class="text-group">
        <text>测试 createImage 结果:</text>
        <text id="testCreateImage">{{testCreateImage}}</text>
      </view>
38

39 40 41 42
      <view class="text-group">
        <text>测试 createPath2D 结果:</text>
        <text id="testCreatePath2D">{{testCreatePath2D}}</text>
      </view>
43 44 45 46 47 48 49
    </scroll-view>
  </view>
</template>

<script>
  function hidpi(canvas : UniCanvasElement) {
    const context = canvas.getContext("2d")!;
H
hdx 已提交
50
    const dpr = uni.getWindowInfo().pixelRatio ?? 1;
51 52 53 54 55 56 57 58
    canvas.width = canvas.offsetWidth * dpr;
    canvas.height = canvas.offsetHeight * dpr;
    context.scale(dpr, dpr);
  }

  export default {
    data() {
      return {
59
        title: 'Context2D',
60
        canvas: null as UniCanvasElement | null,
61 62
        canvasContext: null as CanvasContext | null,
        renderingContext: null as CanvasRenderingContext2D | null,
63
        canvasWidth: 0,
64
        canvasHeight: 0,
65 66 67
        dataBase64: '',
        taskId: 0,
        lastTime: 0,
H
hdx 已提交
68
        frameCount: 0,
69
        // 仅测试
70
        testCanvasContext: false,
71
        testToBlobResult: false,
72 73
        testToDataURLResult: false,
        testCreateCanvasContextAsyncSuccess: false,
74
        testCreateImage: false,
H
hdx 已提交
75 76
        testCreatePath2D: false,
        testFrameCount: 0
77 78
      }
    },
79
    onLoad() {
80 81 82 83 84 85 86 87 88 89 90 91
      // HBuilderX 4.25+
      // 异步调用方式, 跨平台写法
      uni.createCanvasContextAsync({
        id: 'canvas',
        component: this,
        success: (context : CanvasContext) => {
          this.canvasContext = context;
          this.renderingContext = context.getContext('2d')!;
          this.canvas = this.renderingContext!.canvas;

          hidpi(this.canvas!);
          this.canvasWidth = this.canvas!.width;
92
          this.canvasHeight = this.canvas!.height;
93 94 95 96

          // #ifdef WEB
          context.toBlob((blob : Blob) => {
            this.testToBlobResult = (blob.size > 0 && blob.type == 'image/jpeg')
H
hdx 已提交
97 98
          }, 'image/jpeg', 0.95);
          this.testToDataURLResult = this.canvasContext!.toDataURL().startsWith('data:image/png;base64')
99 100 101 102
          // #endif
          this.testCanvasContext = true
        }
      })
103 104
    },
    onReady() {
105
      // TODO app-android 需要延迟调用
H
hdx 已提交
106
      // #ifdef APP
107
      this.testToDataURLResult = this.canvasContext!.toDataURL().startsWith('data:image/png;base64')
H
hdx 已提交
108
      // #endif
109

110 111 112 113 114 115 116
      // 同步调用方式,仅支持 app/web
      // let canvas = uni.getElementById("canvas") as UniCanvasElement
      // this.renderingContext = canvas.getContext("2d")
      // hidpi(canvas);
      // this.canvas = canvas;
      // this.canvasWidth = canvas.width;
      // this.canvasHeight = canvas.height;
117 118 119 120 121
    },
    onUnload() {
      if (this.taskId > 0) {
        this.stopAnimationFrame()
      }
122 123
    },
    methods: {
124
      // #ifdef WEB
125
      canvasToBlob() {
126
        this.canvasContext!.toBlob((blob : Blob) => {
127 128 129
          this.testToBlobResult = (blob.size > 0 && blob.type == 'image/jpeg')
        }, 'image/jpeg', 0.95)
      },
130
      // #endif
131
      canvasToDataURL() {
132
        this.dataBase64 = this.canvasContext!.toDataURL()
133
      },
134
      onCreateImage() {
135 136
        this.renderingContext!.clearRect(0, 0, this.canvasWidth, this.canvasHeight)
        let image = this.canvasContext!.createImage();
H
hdx 已提交
137
        image.src = "../../../static/logo.png"
138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162
        image.onload = () => {
          this.testCreateImage = true
          this.renderingContext?.drawImage(image, 0, 0, 100, 100);
        }
      },
      onCreatePath2D() {
        this.renderingContext!.clearRect(0, 0, this.canvasWidth, this.canvasHeight)
        const context = this.renderingContext!
        let path2D = this.canvasContext!.createPath2D()
        this.testCreatePath2D = true
        const amplitude = 64;
        const wavelength = 64;
        for (let i = 0; i < 5; i++) {
          const x1 = 0 + (i * wavelength);
          const y1 = 128;
          const x2 = x1 + wavelength / 4;
          const y2 = y1 - amplitude;
          const x3 = x1 + 3 * wavelength / 4;
          const y3 = y1 + amplitude;
          const x4 = x1 + wavelength;
          const y4 = y1;
          context.moveTo(x1, y1);
          path2D.bezierCurveTo(x2, y2, x3, y3, x4, y4);
        }
        context.stroke(path2D);
163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183
      },
      startAnimationFrame() {
        this.taskId = this.canvasContext!.requestAnimationFrame((timestamp : number) => {
          this.testFrameCount++
          this.updateFPS(timestamp)
          this.startAnimationFrame()
        })
      },
      stopAnimationFrame() {
        this.canvasContext!.cancelAnimationFrame(this.taskId)
        this.taskId = 0
      },
      updateFPS(timestamp : number) {
        this.frameCount++
        if (timestamp - this.lastTime >= 1000) {
          const timeOfFrame = (1000 / this.frameCount)
          this.renderingContext!.clearRect(0, 0, this.canvasWidth, this.canvasHeight)
          this.renderingContext!.fillText(`${this.frameCount} / ${timeOfFrame.toFixed(3)}ms`, 10, 18)
          this.frameCount = 0
          this.lastTime = timestamp
        }
184 185 186
      }
    }
  }
X
xty 已提交
187 188 189
</script>

<style>
190 191 192 193 194
  .page {
    flex: 1;
    height: 100%;
    overflow: hidden;
  }
X
xty 已提交
195

196 197 198 199 200 201 202 203 204 205
  .scroll-view {
    flex: 1;
  }

  .canvas-element {
    width: 100%;
    height: 250px;
    background-color: #ffffff;
  }

206 207 208 209 210 211 212 213 214 215 216
  .btn-to-image {
    margin: 10px;
  }

  .text-group {
    display: flex;
    flex-flow: row nowrap;
    justify-content: space-between;
    align-items: center;
    padding: 8px 10px;
  }
X
xty 已提交
217
</style>