【小程序】类taro语法中小程序端使用f2

前言

  • 最近在类taro框架中小程序端使用最新版f2。(这里我使用rax)并封装了库,特此记录一下。

使用

  • 想直接用的同学直接在你的rax项目中安装rax-my-f2这个包,他依赖@antv/f2@antv/f2-context这2个包。
import {
    
     MyCanvas } from 'rax-my-f2';
  • 导入之后和官方文档一样直接使用:
const LineChart = (props) => (
  <Chart data={
    
    props.data}>
    <Axis
      field="date"
      tickCount={
    
    3}
      style={
    
    {
    
    
        label: {
    
     align: 'between' },
      }}
    />
    <Axis field="value" tickCount={
    
    5} />
    <Line x="date" y="value" />
    <Tooltip />
  </Chart>
);
function Index() {
    
    
  const [datas, setData] = useState(data);
  useEffect(() => {
    
    
    setTimeout(() => {
    
    
      console.log('over');
      setData(data2);
    }, 5000);
  }, []);
  return (
    <view id="aaa">
      <MyCanvas id='ddd' width={
    
    375} height={
    
    260} data={
    
    datas} onRender={
    
    LineChart} />
    </view>
  );
}
export default Index;
  • 如果需要封装taro或者其他类taro框架或者非阿里小程序,需要看一下下面的封装思路自行封装。

封装思路

  • 首先有些背景知识需要知道下。
  • 小程序的canvas和web的canvas有一些区别,不同平台的小程序之间canvas也有区别。f2是基于canvas绘图的,所以需要有个东西抹平canvas的差异。这里f2团队已经做好了使用@antv/f2-context就可以。这个包的用法很简单,你给他个小程序canvas的context做参数,他还你个做过兼容的context。
  • 阿里小程序主要分为支付宝小程序与钉钉小程序。钉钉小程序基础库目前只能使用1版本的,而阿里小程序可以切换1版本或者2版本。而canvas这个在1版本和2版本的使用都不一样,需要做两者的兼容。
  • 阿里小程序中2版本的canvas在加载完成后会触发onReady方法,在onReady方法中可以拿到该canvas的node,从而能获取到context。这个context是已经兼容过的,只需要做一下分辨率然后转给f2渲染即可:
const onCanvasReady = () => {
    
    
    const query = my.createSelectorQuery();
    query
      .select(`#${
      
      id}`)
      .node()
      .exec((res) => {
    
    
        if (!res[0]) {
    
    
          return;
        }
        const canvas = res[0].node;
        const {
    
     width, height } = canvas;
        const pixelRatio = getPixelRatio();
        canvas.width = width * pixelRatio;
        canvas.height = height * pixelRatio;
        const context = canvas.getContext("2d");
        canvasRender({
    
     width, height, pixelRatio, context });
      });
  };
   const canvasRender = ({
     
      width, height, pixelRatio, context }) => {
    
    
    if (!width || !height) {
    
    
      return;
    }
    const children = props.onRender(props);
    const pix = isAppX2CanvasEnv() ? pixelRatio : 1;
    const canvas = new Canvas({
    
    
      pixelRatio: pix,
      width,
      height,
      context,
      children,
    });
    canvas.render();
    setCtx(canvas);
    setEl(canvas.canvas.get("el"));
  };
  • 2版本的判断使用,一个就是onReady用来拿context,一个是return node用来拿canvas的node。
// 判断是否是新版 canvas 所支持的调用方法(AppX 2.7.0 及以上)
const isAppX2CanvasEnv = () =>
  my.canIUse("canvas.onReady") && my.canIUse("createSelectorQuery.return.node");
  • 1版本由于不会触发onReady且也拿不到node,需要使用createSelectorQuery去查找。实测发现这里在useEffect后还需要setTimeout不然很可能找不到。拿到宽高后使用createCanvasContext进行创建context,这个context则是没有兼容的,需要使用@antv/f2-context进行兼容。最后这个传给f2渲染的pixelRatio应该为1,否则这个图像显示会不太正常。
  • 最后对移动端常见的事件进行封装,因为已经拿到element了,直接canvas派发对应事件即可:
  const click = (e) => {
    
    
    if (!el) {
    
    
      return;
    }
    const event = wrapEvent(e);
    const {
    
     detail, target } = e;
    const {
    
     x, y } = detail;
    const {
    
     offsetLeft = 0, offsetTop = 0 } = target;
    // 包装成 touch 对象
    event.touches = [{
    
     x: x - offsetLeft, y: y - offsetTop }];
    el.dispatchEvent("click", event);
  };
  const touchStart = (e) => {
    
    
    if (!el) {
    
    
      return;
    }
    el.dispatchEvent("touchstart", wrapEvent(e));
  };
  const touchMove = (e) => {
    
    
    if (!el) {
    
    
      return;
    }
    el.dispatchEvent("touchmove", wrapEvent(e));
  };
  const touchEnd = (e) => {
    
    
    if (!el) {
    
    
      return;
    }
    el.dispatchEvent("touchend", wrapEvent(e));
  };

faq

1、 按照官网的示例写原生canvas怎么着都出不来效果

  • 官网示例:https://opendocs.alipay.com/mini/api/createimage
    包括onCanvasReady函数不会正常运行。createSelectorQuery没有node方法。
  • 原因:未使用高版本基础库。(低版本基础库也能显示f2,但是不会触发onCanvasReady方法,钉钉小程序只能使用低版本基础库)。
    在这里插入图片描述
    需要在设置里勾上启用2.0构建。
    可以查看下版本号:
    在这里插入图片描述
    错误的版本号1开头的就不会显示。
    在这里插入图片描述
    高版本则正常。

2、rax小程序报找不到jsx

  • 找不到jsx一般有2种情况:
    一种是使用的组件没有保留rax的createElement函数导致。
    还有一种是在该Rax页面中保留了rax的默认导出(这个坑坑了我挺久的)比如:
import Rax, {
    
     createElement, useEffect, useRef, useState } from 'rax';
  • 这个默认导出Rax如果存在,就会报这个错。

猜你喜欢

转载自blog.csdn.net/yehuozhili/article/details/128773578
f2