Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/canvas #15319

Merged
merged 10 commits into from
Mar 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/taro-platform-harmony/src/apis/base/system.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ export const getSystemInfoSync: typeof Taro.getSystemInfoSync = function () {
res.notificationSoundAuthorized = false // 通知带有声音的开关(仅 iOS 有效)boolean
res.phoneCalendarAuthorized = null // 使用日历的开关 boolean
res.wifiEnabled = false // Wi-Fi 的系统开关 boolean
res.pixelRatio = display && (Math.round(display.xDPI / display.width * 100) / 100) // 设备像素比,number
res.pixelRatio = display && display.densityPixels // 设备像素比,number
res.platform = 'harmony' // 客户端平台 string
res.safeArea = safeArea // 在竖屏正方向下的安全区域 General.SafeAreaResult
res.screenHeight = display?.height // 屏幕高度,单位px number
Expand Down
10 changes: 9 additions & 1 deletion packages/taro-platform-harmony/src/apis/canvas/index.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,20 @@
import { eventSource } from '@tarojs/runtime'

import { temporarilyNotSupport } from '../utils'

import type { TaroCanvasElement } from '@tarojs/runtime'
// 画布

/** 创建离屏 canvas 实例 */
export const createOffscreenCanvas = /* @__PURE__ */ temporarilyNotSupport('createOffscreenCanvas')

/** 创建 canvas 的绘图上下文 CanvasContext 对象 */
export const createCanvasContext = /* @__PURE__ */ temporarilyNotSupport('createOffscreenCanvas')
// export const createCanvasContext = /* @__PURE__ */ temporarilyNotSupport('createOffscreenCanvas')
export const createCanvasContext = (canvasId: string) => {
const dom = eventSource.get(`canvasId-${canvasId}`)
// return dom as TaroCanvasElement
if (dom) return (dom as unknown as TaroCanvasElement).context
}

/** 把当前画布指定区域的内容导出生成指定大小的图片 */
export const canvasToTempFilePath = /* @__PURE__ */ temporarilyNotSupport('createOffscreenCanvas')
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import type { TaroCanvasElement } from '@tarojs/runtime'
import { cancelAnimationFrame, requestAnimationFrame } from '@tarojs/runtime'


@Component
export default struct TaroCanvas {
@ObjectLink node: TaroCanvasElement
rafId: number = 0


aboutToDisappear() {
if(this.rafId) {
cancelAnimationFrame(this.rafId)
}
}

build() {
Canvas(this.node._context)
.width('100%')
.height('100%')
.backgroundColor('#ffff00')
.onReady(() => {
const context = this.node._context

const draw = () => {
if (this.node._drawList.length) {
while (this.node._drawList.length) {
const item = this.node._drawList.shift()
if (item) {
if (typeof context[item.key] === 'function') {
context[item.key](...[].concat(item.value))
} else {
context[item.key] = item.value
}
}
}
}
this.rafId = requestAnimationFrame(draw)
}
draw()
})
}
}
5 changes: 5 additions & 0 deletions packages/taro-platform-harmony/src/runtime-ets/bom/window.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import ohosWindow from '@ohos.window'
import { History, Location } from '@tarojs/runtime/dist/runtime.esm'
import { getSystemInfoSync } from '@tarojs/taro'

import { TaroEventTarget } from '../dom/eventTarget'
import { getComputedStyle } from './getComputedStyle'
Expand Down Expand Up @@ -30,6 +31,10 @@ class Window extends TaroEventTarget {
return this._doc
}

get devicePixelRatio () {
return getSystemInfoSync().pixelRatio
}

setTimeout (...args: Parameters<typeof setTimeout>) {
setTimeout(...args)
}
Expand Down
136 changes: 136 additions & 0 deletions packages/taro-platform-harmony/src/runtime-ets/dom/element/canvas.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
import { eventSource, TaroAny, TaroNode } from '@tarojs/runtime'

import { TaroElement } from './element'

import type { CanvasProps, CanvasTouchEvent } from '@tarojs/components/types'

export class CanvasRenderingContext2DWXAdapter extends CanvasRenderingContext2D {
constructor(settings?: RenderingContextSetting) {

Check failure on line 8 in packages/taro-platform-harmony/src/runtime-ets/dom/element/canvas.ts

View workflow job for this annotation

GitHub Actions / Testing on Node.js 16.x (ubuntu-latest)

Useless constructor

Check failure on line 8 in packages/taro-platform-harmony/src/runtime-ets/dom/element/canvas.ts

View workflow job for this annotation

GitHub Actions / Testing on Node.js 18.x (ubuntu-latest)

Useless constructor

Check failure on line 8 in packages/taro-platform-harmony/src/runtime-ets/dom/element/canvas.ts

View workflow job for this annotation

GitHub Actions / Testing on Node.js 20.x (macos-11)

Useless constructor

Check failure on line 8 in packages/taro-platform-harmony/src/runtime-ets/dom/element/canvas.ts

View workflow job for this annotation

GitHub Actions / Testing on Node.js 20.x (windows-latest)

Useless constructor

Check failure on line 8 in packages/taro-platform-harmony/src/runtime-ets/dom/element/canvas.ts

View workflow job for this annotation

GitHub Actions / Testing on Node.js 20.x (ubuntu-latest)

Useless constructor
super(settings)
}

createCircularGradient() {
// Not supported now
}

draw(cb?: (...args: any[]) => any) {
typeof cb === 'function' && cb()
// Not supported now
}

setFillStyle(fillStyle: typeof this.fillStyle) {
this.fillStyle = fillStyle
}

setFontSize(fontSize: number) {
const font = this.font.split(' ')
font[2] = `${fontSize}`
this.font = font.join(' ')
}

setGlobalAlpha(globalAlpha: typeof this.globalAlpha) {
this.globalAlpha = globalAlpha
}

setLineCap(lineCap: typeof this.lineCap) {
this.lineCap = lineCap
}

setLineJoin(lineJoin: typeof this.lineJoin) {
this.lineJoin = lineJoin
}

setLineWidth(lineWidth: typeof this.lineWidth) {
this.lineWidth = lineWidth
}

setMiterLimit(miterLimit: typeof this.miterLimit) {
this.miterLimit = miterLimit
}

setShadow(offsetX: number, offsetY: number, blur: number, color: string) {
this.shadowOffsetX = offsetX
this.shadowOffsetY = offsetY
this.shadowBlur = blur
this.shadowColor = color
}

setStrokeStyle(strokeStyle: typeof this.strokeStyle) {
this.strokeStyle = strokeStyle
}

setTextAlign(textAlign: typeof this.textAlign) {
this.textAlign = textAlign
}

setTextBaseline(textBaseline: typeof this.textBaseline) {
this.textBaseline = textBaseline
}
}
function getContextKey(obj) {
let currentObj = obj
let res = []
while (currentObj) {
if (currentObj instanceof CanvasRenderingContext2D) {
res = [...res, ...Object.getOwnPropertyNames(currentObj)]
}
currentObj = Object.getPrototypeOf(currentObj)
}
return res
}

@Observed
export class TaroCanvasElement extends TaroElement<CanvasProps, CanvasTouchEvent> {
_drawList: {
key: string
value: TaroAny
}[] = []

settings: RenderingContextSettings
_context: CanvasRenderingContext2D
_contextProxy: CanvasRenderingContext2D

constructor() {
super('Canvas')
this.settings = new RenderingContextSettings(true)
const context = new CanvasRenderingContext2DWXAdapter(this.settings) as CanvasRenderingContext2D
this._context = context

const proxyObj = getContextKey(context).reduce((obj, key) => {
if (typeof context[key] === 'function') {
obj[key] = new Proxy(context[key], {
apply: (target, thisArg, argumentsList) => {
this._drawList.push({
key,
value: argumentsList,
})
},
})
} else {
obj[key] = context[key]
}
return obj
}, {})

this._contextProxy = new Proxy(proxyObj, {
set: (_, property, value) => {
this._drawList.push({
key: property,
value,
})
return true
},
})
}

get context() {
return this._contextProxy
}

public setAttribute(name: string, value: TaroAny): void {
if (name === 'canvasId') {
eventSource.set(`canvasId-${value}`, this as TaroNode)
}
super.setAttribute(name, value)
}
}
Loading
Loading