【可视化工具】二维矩形装箱可视化 + JS-Canvas实现

简介: 【可视化工具】二维矩形装箱可视化 + JS-Canvas实现

@[toc]


一、说明

本代码文件为.vue文件,其中使用了Element-UI组件。可视化代码主要用了JS的Canvas画布。

如果需要可视化,需要在程序中按照一定格式输出如下信息,data表示了每个矩形的坐标和长、宽(注意:这里的l是指矩形的高,w是指矩形的宽)。

data:[{x:0.0,y:0.0,l:116.0,w:113.0}, {x:113.0,y:0.0,l:116.0,w:99.0}, {x:212.0,y:0.0,l:116.0,w:111.0}, {x:323.0,y:0.0,l:116.0,w:20.0}, {x:343.0,y:0.0,l:89.0,w:57.0}, {x:343.0,y:89.0,l:95.0,w:57.0}, {x:0.0,y:116.0,l:100.0,w:113.0}, {x:113.0,y:116.0,l:88.0,w:99.0}, {x:212.0,y:116.0,l:79.0,w:111.0}, {x:323.0,y:116.0,l:58.0,w:20.0}, {x:332.0,y:184.0,l:42.0,w:68.0}, {x:230.0,y:195.0,l:31.0,w:102.0}, {x:113.0,y:204.0,l:71.0,w:117.0}, {x:0.0,y:216.0,l:88.0,w:113.0}, {x:230.0,y:226.0,l:81.0,w:102.0}, {x:332.0,y:226.0,l:97.0,w:68.0}, {x:113.0,y:275.0,l:29.0,w:117.0}, {x:0.0,y:304.0,l:96.0,w:98.0}, {x:98.0,y:304.0,l:96.0,w:84.0}, {x:182.0,y:304.0,l:50.0,w:48.0}, {x:230.0,y:307.0,l:53.0,w:102.0}, {x:332.0,y:323.0,l:37.0,w:68.0}, {x:182.0,y:354.0,l:46.0,w:30.0}, {x:212.0,y:360.0,l:40.0,w:106.0}, {x:318.0,y:360.0,l:40.0,w:82.0}],
isRotate:[0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1],

然后将上面的信息复制到前端代码对应位置即可进行可视化展示。

在这里插入图片描述

二、可视化效果展示

可以看到下面的矩形有两种颜色。其中蓝色代表没有旋转,粉色代表进行了90度旋转。

在这里插入图片描述

BACK按钮:往后一步

在这里插入图片描述
NEXT按钮:往前一步

在这里插入图片描述

NUM输入框:展示前n个矩形

在这里插入图片描述

REFRESH按钮:刷新页面

在这里插入图片描述

三、代码

<template>
  <div style="margin: 20px;display: flex">
    <div style="margin-right: 20px">
      <el-card style="text-align: center;width: 180px;height: 83vh">
        <div slot="header" class="clearfix">
          <el-image src="https://picgo-wskh.oss-cn-guangzhou.aliyuncs.com/公文包,工具箱,手提包,行李包.svg"></el-image>
        </div>
        <div>
          <el-button icon="el-icon-d-arrow-left" type="danger" @click="diff()" style="margin-top: 10px">BACK</el-button>
          <el-input v-model="n" style="margin-top: 10px;" @change="draw()">
            <template slot="prepend">NUM<b>:</b></template>
          </el-input>
          <el-button icon="el-icon-d-arrow-right" type="success" @click="add()" style="margin-top: 10px">NEXT
          </el-button>
          <el-button icon="el-icon-refresh" type="primary" @click="refresh()" style="margin-top: 10px">REFRESH
          </el-button>
        </div>
      </el-card>
    </div>
    <div style="width:100%">
      <el-card style="text-align: center;height: 83vh;overflow: auto">
        <h1>矩形绘制:</h1>
        <div ref="cardCanvas" id="canvasDiv">
          <canvas id="canvas" style="border: 2px solid #409EFF;background-color: #f6f6fd;" ref="canvas"
                  :width="canvasWidth" :height="canvasHeight"
          ></canvas>
        </div>
        <h3>信息:{{ data }}</h3>
      </el-card>
    </div>
  </div>
</template>

<script>
export default {
  name: 'index',
  data() {
    return {
      n: 0,
      stander: 500,
      canvas: {},
      context: {},
      canvasWidth: 400,
      canvasHeight: 400,
      data:[{x:0.0,y:0.0,l:115.0,w:59.0}, {x:59.0,y:0.0,l:115.0,w:21.0}, {x:80.0,y:0.0,l:115.0,w:46.0}, {x:374.0,y:0.0,l:99.0,w:26.0}, {x:258.0,y:0.0,l:99.0,w:116.0}, {x:179.0,y:0.0,l:99.0,w:79.0}, {x:126.0,y:0.0,l:102.0,w:53.0}, {x:179.0,y:99.0,l:118.0,w:79.0}, {x:258.0,y:99.0,l:111.0,w:116.0}, {x:374.0,y:99.0,l:102.0,w:26.0}, {x:138.0,y:102.0,l:63.0,w:41.0}, {x:0.0,y:115.0,l:39.0,w:59.0}, {x:59.0,y:115.0,l:60.0,w:21.0}, {x:90.0,y:115.0,l:50.0,w:48.0}, {x:0.0,y:154.0,l:86.0,w:55.0}, {x:80.0,y:165.0,l:33.0,w:58.0}, {x:146.0,y:165.0,l:114.0,w:33.0}, {x:55.0,y:175.0,l:97.0,w:25.0}, {x:80.0,y:198.0,l:82.0,w:66.0}, {x:379.0,y:201.0,l:108.0,w:21.0}, {x:291.0,y:210.0,l:99.0,w:88.0}, {x:258.0,y:210.0,l:66.0,w:33.0}, {x:179.0,y:217.0,l:111.0,w:79.0}, {x:0.0,y:240.0,l:87.0,w:55.0}, {x:55.0,y:272.0,l:55.0,w:24.0}, {x:258.0,y:276.0,l:47.0,w:27.0}, {x:149.0,y:279.0,l:46.0,w:30.0}, {x:79.0,y:280.0,l:76.0,w:70.0}, {x:285.0,y:309.0,l:44.0,w:94.0}, {x:380.0,y:309.0,l:58.0,w:20.0}, {x:258.0,y:323.0,l:56.0,w:27.0}, {x:149.0,y:325.0,l:73.0,w:30.0}, {x:0.0,y:327.0,l:73.0,w:55.0}, {x:55.0,y:327.0,l:61.0,w:24.0}, {x:196.0,y:328.0,l:51.0,w:62.0}, {x:285.0,y:353.0,l:44.0,w:49.0}, {x:334.0,y:353.0,l:47.0,w:34.0}, {x:81.0,y:356.0,l:42.0,w:68.0}, {x:179.0,y:379.0,l:21.0,w:103.0}],
      isRotate:[0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 0, 0],
    }
  },
  created() {
    let max = Math.max(this.canvasWidth, this.canvasHeight)
    this.r = this.stander / max
    this.canvasWidth = this.canvasWidth * this.r
    this.canvasHeight = this.canvasHeight * this.r
  },
  mounted() {
    this.canvas = document.getElementById('canvas')
    // 坐标矫正
    this.context = this.canvas.getContext('2d')
    this.context.translate(0, this.canvasHeight)
    this.context.rotate(this.getRad(180))
    this.context.scale(-1, 1)
    this.n = this.data.length
    this.draw()
  },
  methods: {
    refresh() {
      location.reload()
    },
    clearCanvas() {
      this.context.clearRect(0, 0, this.canvasWidth, this.canvasHeight)
    },
    diff() {
      this.n = -1 + parseInt(this.n)
      this.draw()
    },
    add() {
      this.n = 1 + parseInt(this.n)
      this.draw()
    },
    draw() {
      if (this.judgeN()) {
        this.clearCanvas()
        for (let i = 0; i < this.n; i++) {
          let tube = this.data[i]
          this.drawRect(tube.x, tube.y, tube.l, tube.w, this.isRotate[i])
        }
      }
    },
    judgeN() {
      if (this.n < 0) {
        this.n = 0
        this.$message.warning('矩形数量已经为0了!')
        return false
      } else if (this.n > this.data.length) {
        this.n = this.data.length
        this.$message.warning('所有的矩形已经放置完毕!')
        return false
      }
      return true
    },
    drawRect(x, y, l, w, isRotate) {

      let r = this.r

      w = w * r
      l = l * r
      x = x * r
      y = y * r

      this.context.strokeStyle = '#5190da'
      this.context.lineWidth = 2
      this.context.beginPath()
      this.context.rect(x, y, w, l)
      this.context.stroke()

      // this.context.fillStyle = '#d1e4f9';
      if(isRotate === 1){
        this.context.fillStyle = 'rgba(212,152,218,0.29)'
      }else{
        this.context.fillStyle = 'rgba(123,159,199,0.29)'
      }
      this.context.beginPath()
      this.context.rect(x, y, w, l)
      this.context.fill()

    },
    getRad(degree) {
      return degree / 180 * Math.PI
    }
  }
}
</script>

<style scoped>

</style>
目录
相关文章
|
2月前
|
JavaScript 前端开发 网络安全
【网络安全 | 信息收集】JS文件信息收集工具LinkFinder安装使用教程
【网络安全 | 信息收集】JS文件信息收集工具LinkFinder安装使用教程
79 4
|
2月前
|
JavaScript 前端开发 UED
在 JavaScript 中,异步编程和回调函数是处理非阻塞操作(如网络请求、文件读写等)的重要工具
【5月更文挑战第10天】JavaScript中的异步编程和回调函数用于处理非阻塞操作,提高应用响应性和吞吐量。异步编程通过回调函数、Promises和async/await等方式实现,避免程序因等待操作完成而阻塞。回调函数是异步操作完成后调用的函数,常用于处理网络请求等。然而,回调函数存在嵌套问题和错误处理困难,因此出现了Promises和async/await等更优解决方案。
22 3
|
2月前
|
数据可视化 JavaScript 前端开发
【专栏】D3.js 和 Tableau 是两种流行的数据可视化工具
【4月更文挑战第27天】D3.js 和 Tableau 是两种流行的数据可视化工具。D3.js,一个JavaScript库,以其灵活性和定制性著称,适合创建复杂、个性化的可视化效果,但需要编程技能。Tableau,一款用户友好的分析软件,提供直观界面和强大分析功能,适合快速生成常见图表。在选择时,应考虑项目需求、团队技术能力、数据规模和性能要求。两者可单独使用,也可结合发挥各自优点。随着数据可视化需求的增长,这些工具将持续发展并提供更好的解决方案。
|
16天前
|
JavaScript 前端开发 Java
装箱和拆箱(JS)
装箱和拆箱(JS)
|
17天前
|
JavaScript Java 测试技术
基于springboot+vue.js+uniapp小程序的社区医疗服务可视化系统附带文章源码部署视频讲解等
基于springboot+vue.js+uniapp小程序的社区医疗服务可视化系统附带文章源码部署视频讲解等
21 4
|
17天前
|
存储 JavaScript 前端开发
Node.js 常用工具
Node.js 常用工具
10 1
|
19天前
|
JavaScript Java 测试技术
基于ssm+vue.js+uniapp小程序的短视频流量数据分析与可视化附带文章和源代码部署视频讲解等
基于ssm+vue.js+uniapp小程序的短视频流量数据分析与可视化附带文章和源代码部署视频讲解等
18 0
基于ssm+vue.js+uniapp小程序的短视频流量数据分析与可视化附带文章和源代码部署视频讲解等
|
14天前
|
JavaScript 网络协议
Node.js 工具模块
Node.js 工具模块
16 0
|
2月前
|
数据可视化 JavaScript 定位技术
Cesium第1篇,CesiumJS第1篇,CesiumJS使用详细,在vue中使用Cesium.js(WebGIS中的Cesium地图可视化应用)
Cesium是一种基于WebGL开源的虚拟地球技术,可以用于构建高性能、跨平台的三维地球应用程序,它支持多种数据格式和地图服务,可以实现地球表面的高精度渲染、地形分析、数据可视化等功能。Cesium还提供了丰富的API和插件,方便开发者进行二次开发和定制化,且可免费商用,在航空航天、国防、城市规划、教育等领域得到了广泛应用。
98 0
Cesium第1篇,CesiumJS第1篇,CesiumJS使用详细,在vue中使用Cesium.js(WebGIS中的Cesium地图可视化应用)
|
2月前
|
前端开发 JavaScript 开发者
在JavaScript中,回调函数是一种非常强大的工具
【5月更文挑战第10天】JavaScript中的回调函数是异步编程的核心,常用于处理异步操作结果、事件监听、定时任务、数组遍历和转换以及递归调用。例如,`fetchData`函数使用回调处理网络请求的结果,`addEventListener`用于监听事件,`setTimeout`执行延迟任务,`map`则对数组元素进行操作。尽管回调函数可能导致回调地狱和错误处理复杂,但它们依然是理解和掌握JavaScript的关键技能,而Promise和async/await提供了更优的异步解决方案。
22 2