文档反馈
文档反馈

自定义图形

云信互动白板支持用户插入自定义图形插件。目前暂时只开放基于一次鼠标按下,鼠标移动,鼠标松开的完整动作绘制图形。这样的图形也被成为OneMotion图形插件。后续计划将根据用户需求定制开放更多的自定义图形插件模式。

OneMotion

插件定义

自定义图形插件的接口定义如下:

type Point = [number, number]

pluginDefinition: {
    /**
     * 插件类型。不能和已有教具类型,以及工具栏的图标名称冲突
     */
    type: string,
    /**
     * 自定义图形的绘制函数
     */
    draw: (opt: {
        ctx: CanvasRenderingContext2D,
        sp: Point,
        ep: Point,
        color: string,
        lineWidth: number,
        opacity: number
    }) => void
    /**
     * 判断鼠标是否悬浮在自定义图形上方
     */
    ifMouseOnOp: (mx, my, opt: {
        ctx: CanvasRenderingContext2D,
        sp: Point,
        ep: Point,
        color: string,
        lineWidth: number,
        opacity: number
    }) => boolean
    /**
     * 可选函数。如果自定义图形的boundary范围和鼠标拖动起始点,终点的范围不同,用户应该实现该函数,用于告诉SDK如何确定图形的包含盒
     */
    getBoundary?: (opt: {
        sp: Point,
        ep: Point
    }) => {
        sx: number,
        sy: number,
        w: number,
        h:number
    }
}

我们以下面的三角形为例,讲解如何实现一个自定义图形插件:

等腰三角形

//Triangle.js

type Point = [number, number]

export default {
    type: 'triangle',
    draw: (opt: {
        ctx: CanvasRenderingContext2D,
        sp: Point,
        ep: Point,
        color: string,
        lineWidth: number,
        opacity: number
    }) => {
        const {ctx, lineWidth, color} = opt
        _drawPath(opt)
        ctx.lineWidth = lineWidth
        ctx.strokeStyle = color
        ctx.globalAlpha = opt.opacity
        ctx.stroke()
    },
    ifMouseOnOp: (mx: number, my: number, opt: {
        ctx: CanvasRenderingContext2D,
        sp: Point,
        ep: Point,
        color: string,
        lineWidth: number,
        opacity: number
    }) => {
        const {ctx, lineWidth} = opt
        _drawPath(opt)
        ctx.lineWidth = lineWidth
        ctx.stroke()
        return ctx.isPointInPath(mx, my)
    }
}

const _drawPath = (opt: {
    ctx: CanvasRenderingContext2D,
    sp: Point,
    ep: Point,
    color: string,
    lineWidth: number,
    opacity: number
}) => {
    const {ctx, sp, ep} = opt
    ctx.beginPath()
    ctx.moveTo(sp[0], ep[1])
    ctx.lineTo(sp[0]/2 + ep[0]/2, sp[1])
    ctx.lineTo(ep[0], ep[1])
    ctx.closePath()
}

添加插件

定义好插件之后,首先需要在drawPlugin中添加插件:

import Triangle from './Triangle'

drawPlugin.addPlugin(drawPlugin.PluginType.OneMotion, Triangle)

然后,为了选中该教具,可以在工具栏的图形集合中加入该图标:

toolCollection.addOrSetSubItem({
    baseTool: 'shapeSelect',
    subItem: {
        /**
         * tool必须和插件的type名称一致
         */
        tool: 'triangle',
        hint: '等腰三角形',
        backgroundImage: triangleSVG
    }, 
    insertAfterTool: 'ellipse-fill'
})

或者,如果你有自定义的工具栏按钮,需要点击该按钮时,选中三角形教具,则可以通过setTool选择:

/**
 * 参数名必须和插件的type名称一致
 */
drawPlugin.setTool('triangle')

录像回放

如果在教学阶段使用了自定义图形,在录像回放阶段也必须在drawPlugin中注入自定义图形, 否则回放模块不知道如何绘制自定义图形

import Triangle from './Triangle'

RecordPlayer.getInstance({
    whiteboardParams: {
        urlArr: replayUrls,
        container: document.getElementById('wb') as HTMLDivElement
    }
})
.then(({player, drawPlugin}) => {
    drawPlugin.addPlugin(drawPlugin.PluginType.OneMotion, Triangle)
})
×

反馈成功

非常感谢您的反馈,我们会继续努力做得更好。