当前位置: 代码网 > it编程>编程语言>Javascript > JavaScript前端实现拼图分割效果

JavaScript前端实现拼图分割效果

2024年11月26日 Javascript 我要评论
第一步找到一张模板图,如下:这是一张通过rgba的b通道区分的模板图,每个碎片的b通道,对应序号分别是0,10,20,30,40,……即序号的10倍等于b通道的值。第二步找

第一步

找到一张模板图,如下:

这是一张通过rgba的b通道区分的模板图,每个碎片的b通道,对应序号分别是0,10,20,30,40,……

即序号的10倍等于b通道的值。

第二步

找到一张需要切分的图,如下:

确保两张图的尺寸一致,不一致会导致压缩变形既。

第三步

上代码,微信小程序: ts代码:

// components/cut-img/index.ts
component({

  /**
   * 组件的属性列表
   */
  properties: {
    temp: {
      type: string,
      value: getapp().imgprefix('/model/test/temp5-3.png')
    },
    img: {
      type: string,
      value: getapp().imgprefix('/model/test/test.jpg')
    },
    size: {
      type: number,
      value: 15
    },
  },

  /**
   * 组件的初始数据
   */
  data: {

  },

  lifetimes: {
    ready() {
      // 通过 selectorquery 获取 canvas 节点
      settimeout(() => {
        const query = wx.createselectorquery().in(this)
        query.select('#canvas')
          .fields({
            node: true,
            size: true,
          })
          .exec(this.init.bind(this))
      }, 1000);
    },
  },

  /**
   * 组件的方法列表
   */
  methods: {
    /**
     * 初始化
     */
    init(res: any) {
      const canvas = this.canvas = res[0]?.node
      if (!canvas) {
        return false
      }
      this.ctx = canvas.getcontext('2d')

      this.settemp()

      return false
    },
    /**
     * 设置temp 图片上图
     */
    settemp() {
      const ctx = this.ctx
      const canvas = this.canvas

      const img = canvas.createimage()
      ctx.clearrect(0, 0, canvas.width, canvas.height)
      img.onload = () => {
        this.width = canvas.width = img.width
        this.height = canvas.height = img.height
        ctx.drawimage(img, 0, 0, canvas.width, canvas.height)

        this.tempdata = ctx.getimagedata(0, 0, canvas.width, canvas.height);
        this.setimg()
      }
      img.src = this.data.temp
    },
    /**
     * 设置img 图片上图
     */
    setimg() {
      const ctx = this.ctx
      const canvas = this.canvas
      const img = canvas.createimage()
      ctx.clearrect(0, 0, canvas.width, canvas.height)
      img.onload = () => {
        ctx.drawimage(img, 0, 0, canvas.width, canvas.height)

        this.imgdata = ctx.getimagedata(0, 0, canvas.width, canvas.height);
  
        const size = this.data.size
        const list: any[] = []
        for(let i = 0; i < size; i++) {
          this.cut(i, list)
        }
        console.log('>>> list', list)
        // this.triggerevent('success', list)
      }
      img.src = this.data.img
    },
    /**
     * 裁剪
     * @param index 序号
     * @param list 存储列表
     */
    cut(index: number, list: any[]) {
      const ctx = this.ctx
      const canvas = this.canvas
      const newdata = ctx.createimagedata(this.width, this.height);
      for (let i = 0; i < newdata.data.length; i += 4) {
        const temp = this.tempdata.data.slice(i, i + 4)
        if (math.abs(temp[2] - index * 10) < 2 && temp[3] > 10) {
          newdata.data[i + 0] = this.imgdata.data[i + 0]
          newdata.data[i + 1] = this.imgdata.data[i + 1]
          newdata.data[i + 2] = this.imgdata.data[i + 2]
          newdata.data[i + 3] = this.imgdata.data[i + 3]
        } else {
          newdata.data[i + 0] = 0
          newdata.data[i + 1] = 0
          newdata.data[i + 2] = 0
          newdata.data[i + 3] = 0
        }
      }
      // ctx.putimagedata(newdata, 0, 0)

      let minx = newdata.width;
      let miny = newdata.height;
      let maxx = -1;
      let maxy = -1;

      // 遍历所有像素,查找非透明像素的位置
      for (let y = 0; y < newdata.height; y++) {
        for (let x = 0; x < newdata.width; x++) {
          const pixelindex = (y * newdata.width + x) * 4;
          if (newdata.data[pixelindex + 3] > 0) { // alpha通道大于0表示非透明
            minx = math.min(minx, x);
            maxx = math.max(maxx, x);
            miny = math.min(miny, y);
            maxy = math.max(maxy, y);
          }
        }
      }
      const width = maxx - minx + 1
      const height = maxy - miny + 1
      canvas.width = width
      canvas.height = height
      // 创建新的图像数据对象用于裁剪后的图像
      const croppedimage = ctx.createimagedata(width, height);

      // 复制非透明像素到新的图像数据中
      for (let y = miny; y <= maxy; y++) {
        for (let x = minx; x <= maxx; x++) {
          const srcindex = ((y * newdata.width) + x) * 4;
          const destindex = ((y - miny) * (maxx - minx + 1) + (x - minx)) * 4;
          croppedimage.data.set(newdata.data.subarray(srcindex, srcindex + 4), destindex);
        }
      }

      // 清除画布并绘制裁剪后的图像
      ctx.clearrect(0, 0, width, height);
      ctx.putimagedata(croppedimage, 0, 0);
      const dataurl = canvas.todataurl('image/png');
      list.push({
        x: minx,
        y: miny,
        width,
        height,
        dataurl
      })
    },
  }
})

wxml代码:

<!--components/cut-img/index.wxml-->
<view style="display: none;">
  <canvas type="2d" id="canvas"></canvas>
</view>

步骤总结

1、获取canvas

2、先渲染模板,拿到模板图的imgdata

3、再渲染需要切换的目标图,拿到目标图的imgdata

4、根据切分的数量,循环切分

4.1、创建一个空的imgdata,根据序号对应的b通道,把对应的切片数据存入imgdata

4.2、计算非空白区域的位置和尺寸,裁剪图片数据

4.3、裁剪后的数据放回canvas,导出dataurl

4.4、保存对应的x、y、width、height、dataurl

5、返回list

到此这篇关于javascript前端实现拼图分割效果的文章就介绍到这了,更多相关javascript拼图分割内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com