Skip to content

Commit

Permalink
feat: support canvas universal api (#104)
Browse files Browse the repository at this point in the history
* feat: support canvas universal api

* chore: typo

* chore: typo

* chore: supplement types

* chore: supplement types

* chore: typo
  • Loading branch information
SoloJiang authored Jun 30, 2020
1 parent 7111814 commit 0e262bb
Show file tree
Hide file tree
Showing 28 changed files with 425 additions and 28 deletions.
49 changes: 49 additions & 0 deletions packages/canvas/README-zh_CN.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# universal-canvas [![npm](https://img.shields.io/npm/v/universal-canvas.svg)](https://www.npmjs.com/package/universal-canvas)

一个适配多端的 canvas api。

## 支持

**icon_miniapp_mp** **icon_miniapp_wx** **icon_web**

## 安装

```bash
$ npm install universal-canvas --save
```

## 使用

```js
import { createElement, useEffect, Fragment } from 'rax';
import { createContext } from 'universal-canvas';

function App() {
useEffect(() => {
createContext('canvasId', '2d').then(context => {
context.fillStyle = 'red';
context.fillRect(0, 0, 100, 100);
context.draw();
});
}, []);

return (<>
<canvas id='canvasId'></canvas>
</>)
}
```

## 方法

### `createContext(canvasId, type, options)`

只有在阿里系小程序中,返回的 `context` 中才含有有实际作用的 `draw` 方法。

```js
createContext("canvasId").then((context) => {
context.fillStyle = 'red';
context.fillRect(0, 0, 100, 100);
// 在除了阿里小程序的其它容器中,draw 方法是一个空函数
context.draw();
});
```
49 changes: 49 additions & 0 deletions packages/canvas/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# universal-canvas [![npm](https://img.shields.io/npm/v/universal-canvas.svg)](https://www.npmjs.com/package/universal-canvas)

Universal canvas api.

## Support

**icon_miniapp_mp** **icon_miniapp_wx** **icon_web**

## Install

```bash
$ npm install universal-canvas --save
```

## Usage

```js
import { createElement, useEffect, Fragment } from 'rax';
import { createContext } from 'universal-canvas';

function App() {
useEffect(() => {
createContext('canvasId', '2d').then(context => {
context.fillStyle = 'red';
context.fillRect(0, 0, 100, 100);
context.draw();
});
}, []);

return (<>
<canvas id='canvasId'></canvas>
</>)
}
```

## Methods

### `createContext(canvasId, type, options)`

Only in MiniApp, the return `context` has valid `draw` method.

```js
createContext("canvasId").then((context) => {
context.fillStyle = 'red';
context.fillRect(0, 0, 100, 100);
// Only in alibaba miniapp, draw isn't an empty function
context.draw();
});
```
11 changes: 11 additions & 0 deletions packages/canvas/build.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"plugins": [
[
"build-plugin-rax-component",
{
"type": "rax",
"targets": ["web"]
}
]
]
}
22 changes: 22 additions & 0 deletions packages/canvas/demo/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { createElement, useEffect, render } from 'rax';
import UniversalDriver from 'driver-universal';
import View from 'rax-view';
import { createContext } from '../src/index';

function App() {
useEffect(() => {
createContext('canvas', '2d').then((canvasContext) => {
canvasContext.fillStyle = 'red';
canvasContext.fillRect(0, 0, 100, 100);
// Only valid in miniapp
canvasContext.draw();
});
}, []);
return (
<View>
<canvas id="canvas" width="400" height="400" />
</View>
);
}

render(<App />, document.body, { driver: UniversalDriver });
49 changes: 49 additions & 0 deletions packages/canvas/docs-template/README-zh_CN.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# universal-canvas [![npm](https://img.shields.io/npm/v/universal-canvas.svg)](https://www.npmjs.com/package/universal-canvas)

一个适配多端的 canvas api。

## 支持

**icon_miniapp_mp** **icon_miniapp_wx** **icon_web**

## 安装

```bash
$ npm install universal-canvas --save
```

## 使用

```js
import { createElement, useEffect, Fragment } from 'rax';
import { createContext } from 'universal-canvas';

function App() {
useEffect(() => {
createContext('canvasId', '2d').then(context => {
context.fillStyle = 'red';
context.fillRect(0, 0, 100, 100);
context.draw();
});
}, []);

return (<>
<canvas id='canvasId'></canvas>
</>)
}
```

## 方法

### `createContext(canvasId, type, options)`

只有在阿里系小程序中,返回的 `context` 中才含有有实际作用的 `draw` 方法。

```js
createContext("canvasId").then((context) => {
context.fillStyle = 'red';
context.fillRect(0, 0, 100, 100);
// 在除了阿里小程序的其它容器中,draw 方法是一个空函数
context.draw();
});
```
49 changes: 49 additions & 0 deletions packages/canvas/docs-template/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# universal-canvas [![npm](https://img.shields.io/npm/v/universal-canvas.svg)](https://www.npmjs.com/package/universal-canvas)

Universal canvas api.

## Support

**icon_miniapp_mp** **icon_miniapp_wx** **icon_web**

## Install

```bash
$ npm install universal-canvas --save
```

## Usage

```js
import { createElement, useEffect, Fragment } from 'rax';
import { createContext } from 'universal-canvas';

function App() {
useEffect(() => {
createContext('canvasId', '2d').then(context => {
context.fillStyle = 'red';
context.fillRect(0, 0, 100, 100);
context.draw();
});
}, []);

return (<>
<canvas id='canvasId'></canvas>
</>)
}
```

## Methods

### `createContext(canvasId, type, options)`

Only in MiniApp, the return `context` has valid `draw` method.

```js
createContext("canvasId").then((context) => {
context.fillStyle = 'red';
context.fillRect(0, 0, 100, 100);
// Only in alibaba miniapp, draw isn't an empty function
context.draw();
});
```
33 changes: 33 additions & 0 deletions packages/canvas/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
{
"name": "universal-canvas",
"author": "Rax Team",
"version": "1.0.0",
"description": "Universal canvas api",
"main": "lib/index.js",
"files": [
"src",
"lib",
"dist"
],
"scripts": {
"start": "build-scripts start",
"build": "build-scripts build"
},
"pre-commit": ["lint"],
"keywords": [
"Rax",
"canvas"
],
"engines": {
"npm": ">=3.0.0"
},
"devDependencies": {
"typescript": "^3.7.5",
"driver-universal": "^3.0.0",
"rax": "^1.1.0",
"rax-text": "^1.0.1",
"rax-view": "^1.0.2",
"build-plugin-rax-component": "^0.2.0",
"@alib/build-scripts": "^0.1.0"
}
}
22 changes: 22 additions & 0 deletions packages/canvas/src/ali-miniapp/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { CanvasContext } from '../types'

declare const my: any;

function createContext(selector: string): Promise<CanvasContext> {
return new Promise((resolve) => {
const context = my.createCanvasContext(selector);
Object.defineProperty(context, 'fillStyle', {
get() {
return context.setFillStyle;
},
set(value) {
context.setFillStyle(value);
},
});
resolve(context);
});
}

export default {
createContext,
};
24 changes: 24 additions & 0 deletions packages/canvas/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// eslint-disable-next-line import/no-extraneous-dependencies
import { isWeb, isMiniApp, isWeChatMiniProgram } from 'universal-env';
import aliMiniApp from './ali-miniapp';
import wechatMiniProgram from './wechat-miniprogram';
import web from './web';
import { Canvas } from './types';

let canvas: Canvas;

if (isMiniApp && !isWeb) {
// For cased that import wechat or miniapp sdk in web
canvas = aliMiniApp;
} else if (isWeChatMiniProgram && !isWeb) {
canvas = wechatMiniProgram;
} else {
// Web as default
canvas = web;
}

const createContext = canvas.createContext;

export {
createContext
};
21 changes: 21 additions & 0 deletions packages/canvas/src/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
export type CanvasContext = { draw?: () => void } & RenderingContext;
export interface Canvas {
createContext: (
selector: string,
type: string,
options: object
) => Promise<CanvasContext>;
}

export interface ContextAttributes {
antialias?: boolean,
depth?: boolean,
alpha?: boolean,
willReadFrequently?: boolean,
storage?: string,
failIfMajorPerformanceCaveat?: boolean,
powerPreference?: string,
premultipliedAlpha?: boolean,
preserveDrawingBuffer?: boolean,
stencil?: boolean
}
22 changes: 22 additions & 0 deletions packages/canvas/src/web/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { CanvasContext, ContextAttributes } from '../types'

function createContext(
selector: string,
type: string = '2d',
options: ContextAttributes = {}
): Promise<CanvasContext> {
return new Promise((resolve, reject) => {
const canvasNode: HTMLCanvasElement = document.getElementById(
selector
) as HTMLCanvasElement;
if (!canvasNode) reject('The canvas node may not exist.');
const context :CanvasContext = canvasNode.getContext(type, options);
// For fallback
context.draw = function() {};
resolve(context);
});
}

export default {
createContext,
};
28 changes: 28 additions & 0 deletions packages/canvas/src/wechat-miniprogram/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { CanvasContext, ContextAttributes } from '../types'

declare const wx: any;

function createContext(
selector: string,
type: string = '2d',
options: ContextAttributes = {}
): Promise<CanvasContext> {
return new Promise((resolve, reject) => {
const query = wx.createSelectorQuery();
query
.select(`#${selector}`)
.fields({ node: true, size: true })
.exec((res) => {
if (!res[0] || !res[0].node) reject('The canvas node may not exist.');
const canvasNode :HTMLCanvasElement = res[0].node;
const context :CanvasContext = canvasNode.getContext(type, options);
// For fallback
context.draw = function() {};
resolve(context);
});
});
}

export default {
createContext,
};
Loading

0 comments on commit 0e262bb

Please sign in to comment.