Canvas、SVG实现鼠标滑过某个区域高亮显示的方案说明

这篇具有很好参考价值的文章主要介绍了Canvas、SVG实现鼠标滑过某个区域高亮显示的方案说明。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1、需求背景:

用户提供了某个厂区的底图(就一张静态图片),在底图中,划分了10个不规则区域,给了10个区域的高亮、开灯效果图片(切好了图),鼠标滑过每个区域的时候,要高亮显示,开灯的时候,显示开灯效果;看到这个需求的时候,挺懵的,有点不知从何下手,但是分析后,有2种可以实现的方案,具体方案如下:

2、方案说明

方案1:传统的div去定位,绝对定位,用css实现hover效果,click的时候设置active效果。

这种方案会存在问题。首先,划分的区域是不规则的,如果强行用div去定位,可能会导致区域重叠的问题;其次鼠标划过,鼠标高亮效果要完全和底图贴合,这一点其实不容易实现。而且浏览器全屏后,可能会导致位置出现偏差的问题,基于以上的考虑,我放弃了此方案。

方案2:用Canvas和SVG的方式实现。不规则的区域,手动取点,绘制路径,鼠标划过或鼠标点击的时候,判断鼠标坐标点是否在Path路径内,如果在某个区域内,就显示对应效果。但是要考虑一个问题,因为Path的点,我们是在某个分辨率基准下取点的,这就导致在不同屏幕分辨率下,会导致,无法取到点的问题,所以要重新计算鼠标坐标点。这种方案,全屏后,也不会说出现位置偏差,后面采用了此种方案,具体实现过程如下:

1、找一个容器,放背景图

<template>
  <div ref="container" class="canvas-container">
    <canvas
      ref="canvas"
      width="980px"
      height="675px"
      @mousemove.stop="handleMouseEnter"
      @click.stop="handleCanvasClick"
      @mouseout.stop="renderCanvas"
    ></canvas>
  </div>
</template>

2、 绘制canvas区域,并且在每个区域写上文字标识,绘制10个区域

    drawImage(cb) {
      const that = this
      const img = new Image()
      img.src = backImg
      img.onload = function() {
        // 在Canvas中绘制图像
        ctx.drawImage(img, 0, 0, canvas.width, canvas.height)
        for (let i = 0; i < that.svgShapeList.length; i++) {
          const shape = that.svgShapeList[i]
          ctx.fillStyle = '#ffff33' // 设置填充颜色
          ctx.font = 'bold 14px Arial'
          ctx.textBaseline = 'middle'     
          ctx.fillText(shape.name, shape.textX, shape.textY) // 绘制文本
        }
        if (cb) {
          cb()
        }
      }
    }
 /**
     * @description 鼠标移出,移除效果,如果存在开灯效果继续显示开灯效果
     */
    renderCanvas() {
      this.drawImage(() => {
        for (let i = 0; i < this.svgShapeList.length; i++) {
          // 保存绘图状态
          ctx.save()
          const shape = this.svgShapeList[i]
          if (shape.switchState) {
            this.fetchFile(shape)
          }
          // 恢复到之前保存的绘图状态
          ctx.restore()
        }
      })
    },
    /**
     * @description 获取外部文件
     */
    fetchFile(shape) {
      // ctx.fillStyle = 'rgb(255, 255, 0,0.2)'
      // ctx.fill(shape.path)
      var image = new Image()
      image.src = baseImg
      image.onload = async () => {
        var pattern = await ctx.createPattern(image, 'repeat')
        ctx.fillStyle = pattern
        ctx.fill(shape.path)
      }
    },

问题点:通过mousemove实现图片渲染的时候,由于会不断的onload图片,导致页面闪烁的问题

解决方法:把pattern 缓存起来,不要一致onload,可以在给ctx赋值后,同时给pattern赋值,那么fetchFile函数中,只需要做以下的操作即可:

/**
     * @description 获取外部文件
     */
    fetchFile(shape) {
        ctx.fillStyle = pattern
        ctx.fill(shape.path)
    },

 完美!!

3、接下来就是处理鼠标滑过、鼠标点击的问题了

判断坐标点位置的核心代码

const isInArea = ctx.isPointInPath(shape.path, mouseX, mouseY)

4、重新计算坐标点位:

  setRatio() {
      const initialWidth = 1920  
      const initialHeight = 937
      const targetWidth = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth
      const targetHeight = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight
      this.ratioX = initialWidth / targetWidth
      this.ratioY = initialHeight / targetHeight
    },

说明1920,937为绘制路径时,屏幕可视区域的基准值,这个根据自己的情况来定

然后再鼠标划过,鼠标点击的时候,要注意用当前坐标点乘以一个系数ratioX,ratioY

基本上就这样子了

反正就是要注意导入图片时,不要用路径,否则会出现闪烁的问题,因为一直从服务器请求资源,建议用base64。

完整代码就不粘了,有疑问或者有更好的方案,欢迎留言!文章来源地址https://www.toymoban.com/news/detail-590884.html

到了这里,关于Canvas、SVG实现鼠标滑过某个区域高亮显示的方案说明的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包