vue3 fabricjs自定义鼠标光标样式
fabricjs绘制希望能实现笔刷在绘制中显示为半透明的圆圈光标,并且可以根据笔刷大小动态调整光标大小:
实现过程:
fabricjs中几个常用的光标样式:
// 鼠标在画布上悬停时的默认光标样式
hoverCursor: 'move'
// 在画布上移动对象时使用的默认光标样式
moveCursor: 'move'
// 整个画布的默认光标样式
defaultCursor: 'default'
// 在自由绘图时的光标样式
freeDrawingCursor: 'crosshair'
显然我们需要使用freeDrawingCursor
控制光标样式。
生成svg圆形做为自定义光标样式
由于系统默认样式中没有圆形,css提供了样式属性支持自定义光标dom.style.cursor = url(${imagePath})
,正常填入对应的光标图片路径即可。但由于需求中要求光标可根据画笔大小动态改变,那么可以使用svg图动态控制,如一个20像素圆形的svg源码如下:
<svg height="20" width="20" fill="#c6c6c6" viewBox="0 0 10 10" xmlns="http://www.w3.org/2000/svg">
<circle cx="50%" cy="50%" r="20" opacity="0.5" />
</svg>
设置一个动态变量,将svg用base64的方式嵌入光标样式中
将svg中圆形大小改为动态变量,使用canvas.freeDrawingCursor
修改光标样式:
state.cursor = encodeURIComponent(`
<svg
height="${state.size}"
width="${state.size}"
fill="#c6c6c6"
viewBox="0 0 ${state.size * 2} ${state.size * 2}"
xmlns="http://www.w3.org/2000/svg"
>
<circle
cx="50%"
cy="50%"
r="${state.size}"
opacity="0.5"
/>
</svg>
`)
canvas.freeDrawingCursor = `url('data:image/svg+xml;charset=utf-8,${state.cursor}') ${state.size / 2} ${state.size / 2}, crosshair`
canvas.renderAll()
注:规范要求尽量把svg的内容encode,修改光标样式后,canvas需重新renderAll().
vue页面完整源码:
<template>
<div>
<canvas width="800" height="600" id="canvas" ref="canvasEl"></canvas>
</div>
<button @click="updateConfig">change</button>
<button @click="clear" style="margin-left: 30px;">clear</button>
</template>
<script setup>
import { fabric } from 'fabric'
import { ref, reactive, onMounted } from 'vue'
const canvasEl = ref(null)
const state = reactive({
canvas: null,
cursor: '',
size: 10,
color: '#000'
})
onMounted(() => {
// 初始化canvas
state.canvas = new fabric.Canvas('canvas', {
isDrawingMode: true,
})
updateConfig()
})
function updateConfig() {
state.size = state.size + 10
state.cursor = encodeURIComponent(`
<svg
height="${state.size}"
width="${state.size}"
fill="#c6c6c6"
viewBox="0 0 ${state.size * 2} ${state.size * 2}"
xmlns="http://www.w3.org/2000/svg"
>
<circle
cx="50%"
cy="50%"
r="${state.size}"
opacity="0.5"
/>
</svg>
`)
state.canvas.freeDrawingCursor = `url('data:image/svg+xml;charset=utf-8,${state.cursor}') ${state.size / 2} ${state.size / 2}, crosshair`
state.canvas.freeDrawingBrush = new fabric.PencilBrush(state.canvas)
state.canvas.freeDrawingBrush.width = state.size;
}
function clear() {
state.canvas.clear()
}
</script>
<style>
#app {
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
转载自:https://juejin.cn/post/7361364250608697396