Vue

by Vladimir

HTML

<div id="app">
  <svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="500px" height="400px" @mousedown="startDrag" @mouseup="endDrag" @mousemove="mouseMove">
    <defs>
      <pattern id="bg-grid" patternUnits="userSpaceOnUse" width="100" height="100">
      <rect width="100" height="100" fill="gray"></rect>
      <g fill="silver" style="fillOpacity: 0.4">
          <rect width="100" height="1" y="20"></rect>
          <rect width="100" height="1" y="40"></rect>
          <rect width="100" height="1" y="60"></rect>
          <rect width="100" height="1" y="80"></rect>
          <rect width="1" height="100" x="20"></rect>
          <rect width="1" height="100" x="40"></rect>
          <rect width="1" height="100" x="60"></rect>
          <rect width="1" height="100" x="80"></rect>
      </g>
      <rect width="100" height="100" fill="none" strokeWidth="2" stroke="white"></rect>
  </pattern>
    </defs>
    <rect x=0 y=0 width="500px" height="400px" style="fill: url(#bg-grid);"/>
    <g>
      <g v-for="(obj, ind) in objects" @mousedown="selectObject(ind)" :key="ind">
        <rect :stroke="selectedIndex === ind ? 'white' : ''" :x="obj.x" :y="obj.y" :width="obj.width" :height="obj.height" :fill="obj.fill" />
      </g>
    </g>
  </svg>
</div>

Vue

function random(min,max) {
    return Math.floor(Math.random()*(max-min+1)+min);
}
function randColor() { return "#"+((1<<24)*Math.random()|0).toString(16) };

const COUNT_OBJECTS = 1000;

let objects = [...new Array(COUNT_OBJECTS)].map(x => ({ x: random(0, 400), y: random(0, 400), width: random(2, 50), height: random(20, 50), fill: randColor() }));


new Vue({
  el: "#app",
  data: {
    objects: objects,
    selectedIndex: -1
  },
  methods: {
  	selectObject: function(ind) {
    	this.selectedIndex = ind;
    },
    startDrag: function() {
    	this.isDragging = true;
    },
    endDrag: function() {
    	this.isDragging = false;
    },
    moveObject: function(ind, addX, addY) {
    	let obj = this.objects[this.selectedIndex];
      obj.x += addX;
      obj.y += addY;
      Vue.set(this.objects, ind, obj);
    },
    mouseMove: function(e) {
    	if (this.isDragging) {
        let diffX = e.clientX - this.mouseX;
        let diffY = e.clientY - this.mouseY;
        if (this.selectedIndex >= 0) {
          this.moveObject(this.selectedIndex, diffX, diffY);
        }
      }
    	this.mouseX = e.clientX;
      this.mouseY = e.clientY;
    }
  }
})