vue 版本 canvas 绘图工具来啦!像写 React Native(RN)一样实现canvas 绘图任务

跟大家分享一下我实现的一个小工具:@sketchjs

小程序使用的话占用包体积比较大,taro主包体积优化插件已经在路上了哈可以等一等

给大家介绍一个我实现的一个小工具 ------@sketchjs。它能实现像写 React Native(RN)一样,相对轻松地完成绘图任务。接下来,就详细跟大家唠唠它。

一、安装轻松上手

  • 要是你习惯 npm,在命令行输入下面这行就行:
shell 复制代码
npm install @sketchjs/vue
  • 喜欢 yarn 的话,就执行:
shell 复制代码
yarn add @sketchjs/vue
  • 用 pnpm 的朋友,输入:
shell 复制代码
pnpm add @sketchjs/vue

二、多平台支持

不管是 H5 页面,还是 Taro 小程序,都能稳稳地发挥作用。

(一)H5环境中

在 codesandbox 中打开

  • 首先,得在vue项目 vite.config.ts 中配置以下内容:
javascript 复制代码
import { defineConfig } from 'vite'
// https://vite.dev/config/
export default defineConfig({
  define:{
    'process.env.SKETCH_PLATFORM': '"WEB"', // 使用小程序端 sketch 实现
    'process.env.YOGA_USE_WASM': 'false' // 不使用 WASM 实现
  },
  optimizeDeps: {
    include: ['@sketchjs/vue'],
  },
})

在 H5 环境里,可以通过以下代码进行简单的Canvas绘制:

js 复制代码
<template>
  <div class="App" @click="handleToDataURL">
    <canvas class="sketch-canvas" ref="canvasRef"/>
    <Sketch.Root :style="style.root" :sketch="sketch" @ready="handleSketchInitialized" @update="handleSketchUpdate">
      <Sketch.View :style="style.view">
        <Sketch.Image :src="logo" :style="style.logo"/>
        <Sketch.Text text="Hello  World!" :style="style.text"/>
      </Sketch.View>
    </Sketch.Root>
  </div>
</template>

<script setup lang="ts">
import logo from '@/assets/logo.svg'
import { onMounted, ref } from 'vue'
import { StyleSheet, Sketch } from '@sketchjs/vue'

Sketch.debug = true

const style = StyleSheet.create({
  root: {
    width: 500,
    height: 500,
    backgroundColor: '#ffffff'
  },
  view: {
    width: 500,
    height: 500,
    justifyContent: 'center',
    alignItems: 'center'
  },
  logo: {
    width: 262,
    height: 227
  },
  text: {
    width: 500,
    marginTop: 20,
    color: '#282c34',
    fontSize: 50,
    fontWeight: 400,
    lineHeight: 50,
    textAlign: 'center'
  }
})

const sketch = Sketch.useSketch()

const canvasRef = ref<HTMLCanvasElement | null>(null)

const initCanvas = () => {
  const canvas = canvasRef.value
  const ctx = canvas?.getContext('2d')
  if (!canvas || !ctx) return
  return sketch.value.init({ canvas, ctx })
}

onMounted(() => initCanvas())

const handleToDataURL = () => {
  const dataUrl = sketch.value.toDataURL('image/png', 1)
  console.log({ dataUrl })
}

const handleSketchUpdate = () => {
  console.log('sketch update')
}

const handleSketchInitialized = () => {
  console.log('sketch initialized')
}
</script>

<style scoped>
.App {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100%;

  .sketch-canvas{
    width: 500px;
    height: 500px;
  }
}
</style>

(二)Taro 小程序中

在 Taro 小程序这边,@sketchjs 同样没让人失望。

  • 首先,得在taro项目 config/index.ts 中配置下环境变量:
ts 复制代码
import { defineConfig } from '@tarojs/cli';

export default defineConfig({
    defineConstants: {
        'process.env.SKETCH_PLATFORM': '"APPLET"',  // 使用小程序端 sketch 实现
        'process.env.YOGA_USE_WASM': 'false',  // 不使用 WASM 实现
    },
});
  • 接着就是具体的示例代码,和 H5 那边有些类似:
js 复制代码
<template>
  <View @tap="handleToDataURL" class='index-view'>
    <Canvas id='sketch-canvas' type='2d' class='sketch-canvas' />
    <Sketch.Root :style="style.root" :sketch="sketch" @ready="handleSketchInitialized" @update="handleSketchUpdate">
      <Sketch.View :style="style.view">
        <Sketch.Image :src="require('@/assets/logo.svg')" :style="style.logo"/>
        <Sketch.Text text="Hello  World!" :style="style.text"/>
      </Sketch.View>
    </Sketch.Root>
  </View>
</template>

<script setup lang="ts">
import { defineComponent, onMounted } from 'vue'
import { View, Canvas } from '@tarojs/components'
import { StyleSheet, Sketch } from '@sketchjs/vue'
import Taro from '@tarojs/taro'
import './index.less'

defineComponent({ name: 'IndexPage' })

Sketch.debug = true

const style = StyleSheet.create({
  root: {
    width: 500,
    height: 500,
    backgroundColor: '#fff'
  },
  view: {
    width: 500,
    height: 500,
    justifyContent: 'center',
    alignItems: 'center'
  },
  logo: {
    width: 262,
    height: 227
  },
  text: {
    width: 500,
    marginTop: 20,
    color: '#282c34',
    fontSize: 50,
    fontWeight: 400,
    lineHeight: 50,
    textAlign: 'center'
  }
})

const sketch = Sketch.useSketch()

const initCanvas = async () => {
  const canvasNode: HTMLCanvasElement = await new Promise((resolve) => {
    const selectorQuery = Taro.createSelectorQuery()
    const callback = (res:any) => resolve(res?.node)
    selectorQuery.select('#sketch-canvas').fields({ node: true }, callback).exec()
  })
  const canvasCtx = canvasNode.getContext('2d')
  if (!canvasNode || !canvasCtx) return
  return sketch.value.init({ canvas: canvasNode, ctx: canvasCtx }).then(() => sketch.value.render())
}

onMounted(() => initCanvas())

const handleToDataURL = () => {
  const dataUrl = sketch.value.toDataURL('image/png', 1)
  console.log({ dataUrl })
}

const handleSketchUpdate = () => {
  console.log('sketch update')
}

const handleSketchInitialized = () => {
  console.log('sketch initialized')
}

</script>

三、关键绘图组件

@sketchjs/react 和 RN 开发模式相似,用起来比较容易上手。

(一)<Sketch.Root> 组件

在代码里,咱们用 StyleSheet.create 来定义样式赋予它宽高。比如说:

js 复制代码
<template>
  <Sketch.Root :style="style.root" />
</template>
<script setup lang="ts">
import { StyleSheet, Sketch } from '@sketchjs/vue'

const style = StyleSheet.create({
    root: {
        width: 500,
        height: 500
    }
});
</script>

(二)<Sketch.View> 组件

<Sketch.View> 在绘图区域内划分出一个个子区域,用于对绘图元素进行分组管理。通过 style 属性,我们能运用熟悉的 CSS 布局技巧对其进行调控。以常见的居中布局为例,在代码中:

js 复制代码
<template>
    <Sketch.Root>
        <Sketch.View :style="style.rootView" >
        {/* 这里面放图片、文本等绘图子组件,它们就能按设定布局展示 */}
        </Sketch.View>
    </Sketch.Root>
</template>
<script setup lang="ts">
import { StyleSheet, Sketch } from '@sketchjs/vue'

const style = StyleSheet.create({
    rootView: {
        width: 500,
        height: 500
    }
});
</script>
  • style.rootView 样式对象定义了子区域的宽度与高度均为 500,justifyContent: 'center' 使得子组件在水平方向上居中对齐,alignItems: 'center' 让子组件在垂直方向上也居中对齐。
  • 这样一来,不管是 <Sketch.Image> 展示的图片,还是 <Sketch.Text> 呈现的文本,都能在这个子区域内找到合适的展示位置,布局整整齐齐的。

(三)<Sketch.Image> 组件

<Sketch.Image> 功能很明确,就是把图片展示在 Canvas 绘图区域里。咱们只要给 src 属性指定图片的路径就行,超级简单。

结合 StyleSheet.create 定义样式来看个例子:

js 复制代码
<template>
    <Sketch.Root>
        <Sketch.View :style="style.rootView" >
            <Sketch.Image src={myImage} style={style.imageStyle} />
        </Sketch.View>
    </Sketch.Root>
</template>

<script setup lang="ts">
import { StyleSheet, Sketch } from '@sketchjs/vue'
import myImage from './myImage.png'; // 这里引入实际的图片资源

const style = StyleSheet.create({
    imageStyle: {
        width: 200,
        height: 200,
        marginLeft: 50, // 还可以设置图片的边距等样式,按需调整
    },
});
</script>
  • 通过 src 属性把 myImage(指向实际图片文件的路径)传给 <Sketch.Image> 组件,
  • 然后用 StyleSheet.create 生成的 style.imageStyle 来设置图片尺寸,像这里设置宽度 200 像素,高度 200 像素,
  • 还可以通过其他属性调整图片位置,这样图片就能以咱们想要的样子出现在绘图区域,给画面添彩。

(四)<Sketch.Text> 组件

<Sketch.Text> 组件负责在绘图区域里显示文字内容。咱们用 text 属性写上要显示的文字,再用 style 属性设置字体、大小、颜色、对齐方式这些,文字就能自然融入绘图。

比如这个例子:

js 复制代码
<template>
    <Sketch.Root>
        <Sketch.View :style="style.rootView" >
           <Sketch.Text text="Hello  World!" style={style.textStyle} />
        </Sketch.View>
    </Sketch.Root>
</template>

<script setup lang="ts">
import { StyleSheet, Sketch } from '@sketchjs/vue'
import myImage from './myImage.png'; // 这里引入实际的图片资源

const style = StyleSheet.create({
    textStyle: {
        width: 500,
        marginTop: 20,
        color: '#ffffff',
        fontSize: 50,
        fontWeight: 400,
        lineHeight: 50,
        textAlign: 'center'
    },
});
</script>
  • 在这个例子里,text 属性写上 "Hello World!"
  • style.textStyle 样式对象里设置了文字颜色为白色、字体大小 50 像素、居中对齐等
  • 这样文字就能在绘图区域里以合适的样子出现,和图片等其他元素搭配起来,共同完成绘图效果。

四、总结

总的来说,@sketchjs/vue 开发体验还不错,能让咱们像写 RN 代码一样相对轻松地搞定 Canvas 2D 绘图。要是你在绘图开发上也遇到难题,不妨试试它,说不定能帮你省不少事儿,让你的项目绘图功能实现得更顺利。希望对大家的Canvas绘图开发有点帮助。

目前@sketchjs/vue还是alpha版本。要是在使用的过程中有什么问题,欢迎提issues随时交流。

如果这个库在canvas开发中帮到了你,请给个赞或者github的star吧

本文由豆包AI生成如有错漏,辛苦指正。

链接地址

npm 地址

github 仓库地址

相关推荐
计算机魔术师2 小时前
管谷歌的不是Pichai一个人,是一整层AI智能体
前端
米米商聊2 小时前
图标能点,按钮就可用了吗?键盘、名称与收藏状态
前端·javascript
Younglina3 小时前
三个晚上,我和 WorkBuddy 做了个生图网站
前端·后端·ai编程
xy34533 小时前
Axure 9.0 内联框架加载方式
前端·ui·html·axure·原型·产品设计
陈随易4 小时前
副业搞钱点子之收入查看器
前端·后端
Profile排查笔记4 小时前
浏览器指纹逆向怎么分析:从网络请求追踪到 JavaScript 采集链
前端·人工智能·后端·自动化
hudie7655 小时前
LikeShop 二开最常改的 5 个文件(附改前改后对比)
前端·uni-app·php·个人开发
qetfw5 小时前
Bash 函数与流程控制:read、if、for、case 验证
linux·前端·javascript·bash
鬼手点金6 小时前
从 API 消息到模型 Token:Chat Template
java·前端·javascript·数据库·人工智能·深度学习·1024程序员节
Shadow(⊙o⊙)6 小时前
LangChain 自定义工具全解析:从 @tool 到 bind_tools 的完整调用链路
java·服务器·前端·1024程序员节