diff --git a/README.md b/README.md index 9235528..2c1cbc5 100644 --- a/README.md +++ b/README.md @@ -1,24 +1,21 @@ # taro-f2-react -> 支持在使用 Taro React 开发小程序中,按 React 组件书写方式使用 F2 。 ->
使用 [@antv/f2](https://f2.antv.antgroup.com/tutorial/getting-started) ->
taro-f2-react 1.1.x 支持 4.x <= @antv/f2 < 5.x ->
taro-f2-react 1.2.x 支持 @antv/f2 >= 5.x +> 在 Taro React 中使用 @antv/f2 。 # Demo -Demo +Demo # Install ```bash #via pnpm -$ pnpm add taro-f2-react @antv/f2 +$ pnpm add taro-f2-react @antv/f2@4.0.51 # via npm -$ npm i taro-f2-react @antv/f2 +$ npm i taro-f2-react # via yarn -$ yarn add taro-f2-react @antv/f2 +$ yarn add taro-f2-react ``` # Usage @@ -28,30 +25,30 @@ $ yarn add taro-f2-react @antv/f2
接下来就可以愉快的在 Taro 中使用 F2 了 ```javascript -import React from 'react'; -import ReactDOM from 'react-dom'; -import { View } from '@tarojs/components'; -import F2Canvas from 'taro-f2-react'; -import { Chart, Interval } from '@antv/f2'; +import React from "react"; +import { View } from "@tarojs/components"; +import F2Canvas from "taro-f2-react"; +import { Chart, Interval } from "@antv/f2"; const data = [ - { genre: 'Sports', sold: 275 }, - { genre: 'Strategy', sold: 115 }, - { genre: 'Action', sold: 120 }, - { genre: 'Shooter', sold: 350 }, - { genre: 'Other', sold: 150 }, + { genre: "Sports", sold: 275 }, + { genre: "Strategy", sold: 115 }, + { genre: "Action", sold: 120 }, + { genre: "Shooter", sold: 350 }, + { genre: "Other", sold: 150 }, ]; -ReactDOM.render( - - - - - - - , - document.getElementById('root') -); +function Index() { + return ( + + + + + + + + ); +} ``` ## 多图表 @@ -94,11 +91,14 @@ Taro 在 >= 3.6.0 版本中 Dev 模式下新增了 split chunks,导致加载 } ``` +# 关于 @antv/f2 5.x +* 由于开发者反馈 @antv/f2 5.x 版本的问题较多,最新版本修改为支持 4.x 版本 +* 如果想体验 @antv/f2 5.x 版本,可以安装 taro-f2-react 1.2.0 版本 + # Support Taro >= 3.x -
taro-f2-react 1.1.x 支持 4.x <= @antv/f2 < 5.x -
taro-f2-react 1.2.x 支持 @antv/f2 >= 5.x +
@antv/f2@4.x ## LICENSE [MIT](LICENSE) diff --git a/components/f2-canvas/index.tsx b/components/f2-canvas/index.tsx index 47c9640..e26d9fd 100644 --- a/components/f2-canvas/index.tsx +++ b/components/f2-canvas/index.tsx @@ -1,10 +1,6 @@ -import { ReactNode, useCallback, useEffect, useRef } from 'react'; -import { - createOffscreenCanvas, - createSelectorQuery, - getSystemInfoSync, -} from '@tarojs/taro'; -import { Canvas } from '@tarojs/components'; +import { ReactNode, useEffect, useRef } from 'react'; +import { createSelectorQuery, getSystemInfoSync } from '@tarojs/taro'; +import { ITouchEvent, CanvasTouchEvent, Canvas } from '@tarojs/components'; import { Canvas as FFCanvas } from '@antv/f2'; interface F2CanvasProps { @@ -12,47 +8,38 @@ interface F2CanvasProps { children?: ReactNode; } -function convertTouches(touches) { - if (!touches) return touches; - touches.forEach((touch) => { - touch.pageX = 0; - touch.pageY = 0; - touch.clientX = touch.x; - touch.clientY = touch.y; - }); - return touches; +type CanvasEvent = ITouchEvent | CanvasTouchEvent; + +interface CanvasElement { + dispatchEvent: (type: string, event: CanvasEvent) => void; } -function dispatchEvent(el, event, type) { - if (!el || !event) return; - if (!event.preventDefault) { - event.preventDefault = function () {}; - } - const mergedEvent = { - ...event, - type, - target: el, - }; - const { touches, changedTouches, detail } = mergedEvent; - mergedEvent.touches = convertTouches(touches); - mergedEvent.changedTouches = convertTouches(changedTouches); - if (detail) { - mergedEvent.clientX = detail.x; - mergedEvent.clientY = detail.y; +function wrapEvent(e: CanvasEvent) { + if (e && !e.preventDefault) { + e.preventDefault = function () {}; } - el.dispatchEvent(mergedEvent); + return e; } const F2Canvas = (props: F2CanvasProps) => { const { id, children } = props; - const idRef = useRef(id || 'f-canvas'); + const idRef = useRef(id || 'f2Canvas'); const canvasRef = useRef(); const ffCanvasRef = useRef(); - const canvasElRef = useRef(); - // const childrenRef = useRef(); + const canvasElRef = useRef(); + const childrenRef = useRef(); - const renderCanvas = useCallback(() => { + useEffect(() => { + childrenRef.current = children; + ffCanvasRef.current?.update({ children }); + }, [children]); + + useEffect(() => { + return () => ffCanvasRef.current?.destroy(); + }, []); + + const renderCanvas = () => { const query = createSelectorQuery(); query .select(`#${idRef.current}`) @@ -62,8 +49,6 @@ const F2Canvas = (props: F2CanvasProps) => { }) .exec((res) => { const { node, width, height } = res[0]; - const { requestAnimationFrame, cancelAnimationFrame } = node; - const pixelRatio = getSystemInfoSync().pixelRatio; // 高清设置 node.width = width * pixelRatio; @@ -74,20 +59,14 @@ const F2Canvas = (props: F2CanvasProps) => { width, height, context, - children, - // @ts-ignore - offscreenCanvas: createOffscreenCanvas({ type: '2d' }), + children: childrenRef.current, createImage: () => node.createImage(), // fix: 解决图片元素不渲染的问题 - requestAnimationFrame, - cancelAnimationFrame, - isTouchEvent: (e) => e.type.startsWith('touch'), - isMouseEvent: (e) => e.type.startsWith('mouse'), }); - ffCanvasRef.current = canvas; - canvasElRef.current = canvas.getCanvasEl(); canvas.render(); + ffCanvasRef.current = canvas; + canvasElRef.current = canvas.canvas.get('el'); }); - }, []); + }; useEffect(() => { if (canvasRef.current) { @@ -95,13 +74,41 @@ const F2Canvas = (props: F2CanvasProps) => { } }, [canvasRef]); - useEffect(() => { - ffCanvasRef.current?.update({ children }); - }, [children]); + const handleClick = (e: ITouchEvent) => { + const canvasEl = canvasElRef.current; + if (!canvasEl) { + return; + } - useEffect(() => { - return () => ffCanvasRef.current?.destroy(); - }, []); + const event = wrapEvent(e); + // 包装成 touch 对象 + event.touches = [e.detail]; + canvasEl.dispatchEvent('click', event); + }; + + const handleTouchStart = (e: CanvasTouchEvent) => { + const canvasEl = canvasElRef.current; + if (!canvasEl) { + return; + } + canvasEl.dispatchEvent('touchstart', wrapEvent(e)); + }; + + const handleTouchMove = (e: CanvasTouchEvent) => { + const canvasEl = canvasElRef.current; + if (!canvasEl) { + return; + } + canvasEl.dispatchEvent('touchmove', wrapEvent(e)); + }; + + const handleTouchEnd = (e: CanvasTouchEvent) => { + const canvasEl = canvasElRef.current; + if (!canvasEl) { + return; + } + canvasEl.dispatchEvent('touchend', wrapEvent(e)); + }; return ( { ref={canvasRef} type="2d" style="width:100%;height:100%;display:block;padding: 0;margin: 0;" - onClick={(e) => dispatchEvent(canvasElRef.current, e, 'click')} - onTouchStart={(e) => dispatchEvent(canvasElRef.current, e, 'touchstart')} - onTouchMove={(e) => dispatchEvent(canvasElRef.current, e, 'touchmove')} - onTouchEnd={(e) => dispatchEvent(canvasElRef.current, e, 'touchend')} + onClick={handleClick} + onTouchStart={handleTouchStart} + onTouchMove={handleTouchMove} + onTouchEnd={handleTouchEnd} /> ); }; diff --git a/package.json b/package.json index 26c3d5f..ada46ae 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "taro-f2-react", - "version": "1.2.0", - "description": "支持在使用 Taro React 开发小程序中,按 React 组件书写方式使用 F2", + "version": "1.3.0", + "description": "在 Taro React 中使用 @antv/f2", "main": "lib/index.js", "module": "es/index.js", "types": "es/index.d.ts", @@ -16,7 +16,7 @@ }, "repository": { "type": "git", - "url": "git+https://github.com/daniel-zd/taro-f2-react.git" + "url": "git+https://github.com/domisolo/taro-f2-react.git" }, "keywords": [ "taro", @@ -29,14 +29,16 @@ "author": "Daniel Zhao", "license": "MIT", "bugs": { - "url": "https://github.com/daniel-zd/taro-f2-react/issues" + "url": "https://github.com/domisolo/taro-f2-react/issues" + }, + "homepage": "https://github.com/domisolo/taro-f2-react#readme", + "dependencies": { + "@antv/f2": "^4.0.51" }, - "homepage": "https://github.com/daniel-zd/taro-f2-react#readme", "devDependencies": { - "@antv/f2": "^5.4.2", - "@tarojs/components": "^3.6.24", - "@tarojs/taro": "^3.6.24", - "@types/react": "^18.2.66", - "typescript": "^5.4.2" + "@tarojs/components": "^3.6.35", + "@tarojs/taro": "^3.6.35", + "@types/react": "^18.3.4", + "typescript": "^5.5.4" } }