i want export and import whole project this is my code "<template>
  <v-app>
    <v-container>
      <v-row justify="center">
        <v-col cols="2">
          <!-- List of Images -->
          <v-list>
            <v-subheader>Images</v-subheader>
            <v-list-item v-for="(img, index) in images" :key="index" @click="selectImage(index)"
              :class="{ 'active': selectedImageIndex === index }" style="cursor: pointer;">
              <v-list-item-content>
                <v-list-item-title>Image {{ index + 1 }}</v-list-item-title>
              </v-list-item-content>
            </v-list-item>
          </v-list>

          <!-- Image Upload -->
          <v-file-input label="Upload Images" accept="image/*" @change="onImageUpload" multiple
            prepend-icon="mdi-upload"></v-file-input>
        </v-col>

        <v-col cols="10">
          <v-row>
            <v-col cols="8" md="8">
              <!-- Button to Log Rectangles -->
              <v-btn color="primary" @click="console.log(images[selectedImageIndex]?.rectangles)"
                :disabled="selectedImageIndex === null">
                Print Rectangles
              </v-btn>
              <v-btn color="primary" @click="console.log(images)" :disabled="selectedImageIndex === null">
                Print All Rectangles
              </v-btn>
            </v-col>
          </v-row>
          <v-row>
            <v-col cols="8">
              <v-card class="my-4">
                <v-card-text>
                  <!-- Canvas for Image Drawing -->
                  <canvas ref="canvas" :width="canvasWidth" :height="canvasHeight" @wheel.prevent="onMouseWheel"
                    @mousedown="onMouseDown" @mouseup="onMouseUp" @mousemove="onMouseMove"
                    style="border: 1px solid black;"></canvas>
                </v-card-text>
              </v-card>
              <!-- Labels Below the Canvas -->

              <v-chip-group v-if="labels.length" mandatory style="cursor: pointer;">
                <v-chip v-for="(label, index) in labels" :key="label.name" @click="selectLabel(label)"
                  :class="{ 'bg-white': selectedLabel === label.name }">
                  <v-badge :color="label.color" :content="index + 1" inline></v-badge>
                  <v-label style="cursor: pointer;">{{ label.name }}</v-label>
                </v-chip>
              </v-chip-group>
            </v-col>

            <v-col cols="4">
              <v-btn v-if="rectangles.length" @click="redrawNormalizedRectangles" color="primary" class="mb-2">
                Redraw Normalized Rectangles
              </v-btn>
              <v-btn v-if="selectedRectangle" @click="copyRectangle" color="secondary" class="mb-2">
                Copy Selected
              </v-btn>
              <v-btn v-if="copiedRectangle" @click="pasteRectangle" color="success" class="mb-2">
                Paste
              </v-btn>

              <v-list v-if="rectangles.length">
                <v-subheader>Rectangles</v-subheader>
                <v-list-item v-for="(rect, index) in rectangles" :key="index" @click="selectRectangle(index)"
                  :class="{ active: rect === selectedRectangle }" style="cursor: pointer;">
                  <template v-slot:prepend>
                    <v-icon :style="{ color: rect.color }">mdi-circle</v-icon>
                  </template>
                  <template v-slot:append>
                    <v-btn icon @click.stop="removeRectangle(index)" color="red" variant="tonal" density="comfortable">
                      <v-icon>mdi-delete</v-icon>
                    </v-btn>
                  </template>
                  <v-list-item-content>
                    <v-list-item-title>
                      {{ rect.label }}
                    </v-list-item-title>
                    <v-list-item-subtitle>
                      [x: {{ rect.x.toFixed(2) }}, y: {{ rect.y.toFixed(2) }}, w:
                      {{ rect.width.toFixed(2) }}, h: {{ rect.height.toFixed(2) }}]
                    </v-list-item-subtitle>
                  </v-list-item-content>
                </v-list-item>
              </v-list>
            </v-col>
          </v-row>
        </v-col>
      </v-row>
    </v-container>
  </v-app>
</template>

<script>
export default {
  data() {
    return {
      canvasWidth: 800,
      canvasHeight: 600,
      context: null,
      scale: 1,
      minScale: 0.1,
      maxScale: 12,
      scaleStep: 0.1,
      originX: 0,
      originY: 0,
      images: [], // Array to store multiple images
      selectedImageIndex: null, // Index of the current image
      rectangles: [], // Rectangles for the current image
      labels: [
        { id: 0, name: "Person", color: "#2200ff", key: "Digit1" },
        { id: 1, name: "Car", color: "#ff0000", key: "Digit2" },
        { id: 2, name: "Dog", color: "#ffdd00", key: "Digit3" }
      ],
      selectedLabel: "Person",
      selectedRectangle: null,
      copiedRectangle: null,
      drawStartX: 0,
      drawStartY: 0,
      drawing: false,
      isDraggingImage: false,
      isDraggingRectangle: false,
      isResizing: false,
      selectedResizeHandle: null,
      resizeHandleSize: 8,
      lastMouseX: 0,
      lastMouseY: 0,
    };
  },
  mounted() {
    this.context = this.$refs.canvas.getContext('2d');
    window.addEventListener('keydown', this.handleKeyDown);
  },
  beforeDestroy() {
    window.removeEventListener('keydown', this.handleKeyDown);
  },
  methods: {
    handleKeyDown(event) {
      if (event.ctrlKey && event.code === 'KeyC') {
        this.copyRectangle();
      }
      if (event.ctrlKey && event.code === 'KeyV') {
        this.pasteRectangle();
      }

      // Check if a label key is pressed
      const label = this.labels.find((label) => label.key === event.code);
      if (label) {
        this.selectLabel(label);
      }
    },
    onImageUpload(event) {
      const files = event.target.files;
      for (let i = 0; i < files.length; i++) {
        const file = files[i];
        const reader = new FileReader();
        reader.onload = (e) => {
          this.images.push({ src: e.target.result, rectangles: [] }); // Add image with its rectangles
          if (this.selectedImageIndex === null) {
            this.selectImage(0);
          }
        };
        reader.readAsDataURL(file);
      }
    },
    selectImage(index) {
      this.selectedImageIndex = index;
      this.rectangles = this.images[index].rectangles;
      this.loadImage(this.images[index].src);
    },
    loadImage(src) {
      const img = new Image();
      img.onload = () => {
        const widthScale = this.canvasWidth / img.width;
        const heightScale = this.canvasHeight / img.height;
        this.scale = Math.min(widthScale, heightScale);

        const width = img.width * this.scale;
        const height = img.height * this.scale;
        this.originX = (this.canvasWidth - width) / 2;
        this.originY = (this.canvasHeight - height) / 2;

        this.currentImage = img; // Save the loaded image
        this.draw();
      };
      img.src = src;
    },
    draw() {
      if (!this.currentImage) return;

      this.context.clearRect(0, 0, this.canvasWidth, this.canvasHeight);
      const width = this.currentImage.width * this.scale;
      const height = this.currentImage.height * this.scale;
      this.context.drawImage(this.currentImage, this.originX, this.originY, width, height);

      this.redrawRectangles();

      if (this.drawing) {
        this.context.strokeStyle = 'green';
        const drawWidth = this.currentMouseX - this.drawStartX;
        const drawHeight = this.currentMouseY - this.drawStartY;
        this.context.strokeRect(this.drawStartX, this.drawStartY, drawWidth, drawHeight);
      }
    },
    redrawRectangles() {
      if (!this.currentImage) return;
      const width = this.currentImage.width * this.scale;
      const height = this.currentImage.height * this.scale;

      this.rectangles.forEach((rect) => {
        const rectX = this.originX + rect.x * width;
        const rectY = this.originY + rect.y * height;
        const rectW = rect.width * width;
        const rectH = rect.height * height;

        this.context.strokeStyle = rect.color;
        this.context.lineWidth = 1;
        this.context.fillStyle = rect.color + "44";

        this.context.fillRect(rectX, rectY, rectW, rectH);


        if (rect === this.selectedRectangle) {
          this.context.fillStyle = 'red';
          this.drawResizeHandles(rectX, rectY, rectW, rectH);
        }
      });
    },
    drawResizeHandles(rectX, rectY, rectW, rectH) {
      const handleSize = this.resizeHandleSize;
      const halfSize = handleSize / 2;
      this.context.fillRect(rectX - halfSize, rectY - halfSize, handleSize, handleSize); // Top-left
      this.context.fillRect(rectX + rectW - halfSize, rectY - halfSize, handleSize, handleSize); // Top-right
      this.context.fillRect(rectX - halfSize, rectY + rectH - halfSize, handleSize, handleSize); // Bottom-left
      this.context.fillRect(rectX + rectW - halfSize, rectY + rectH - halfSize, handleSize, handleSize); // Bottom-right
    },
    onMouseWheel(event) {
      const { offsetX, offsetY } = event;
      const oldScale = this.scale;
      const newScale = event.deltaY > 0
        ? Math.max(this.scale - this.scaleStep, this.minScale)
        : Math.min(this.scale + this.scaleStep, this.maxScale);

      if (newScale !== oldScale) {
        const scaleRatio = newScale / oldScale;
        this.originX = offsetX - (offsetX - this.originX) * scaleRatio;
        this.originY = offsetY - (offsetY - this.originY) * scaleRatio;
        this.scale = newScale;
        this.draw();
      }
    },
    onMouseDown(event) {
      const mouseX = event.offsetX;
      const mouseY = event.offsetY;

      if (event.button === 1) { // Middle mouse button for dragging
        this.isDraggingImage = true;
        this.lastMouseX = mouseX;
        this.lastMouseY = mouseY;
      }
      else if (event.button === 0) { // Left mouse button for actions
        this.selectedResizeHandle = this.getResizeHandle(mouseX, mouseY);
        if (this.selectedResizeHandle) {
          this.isResizing = true;
          this.lastMouseX = mouseX;
          this.lastMouseY = mouseY;
          return;
        }

        this.selectedRectangle = this.rectangles.find(rect =>
          mouseX >= this.originX + rect.x * this.currentImage.width * this.scale &&
          mouseX <= this.originX + (rect.x + rect.width) * this.currentImage.width * this.scale &&
          mouseY >= this.originY + rect.y * this.currentImage.height * this.scale &&
          mouseY <= this.originY + (rect.y + rect.height) * this.currentImage.height * this.scale
        );

        if (this.selectedRectangle) {
          this.isDraggingRectangle = true;
          this.lastMouseX = mouseX;
          this.lastMouseY = mouseY;
        } else {
          this.drawing = true;
          this.drawStartX = mouseX;
          this.drawStartY = mouseY;
          this.currentMouseX = mouseX;
          this.currentMouseY = mouseY;
        }
      }
      this.draw();
    },
    onMouseMove(event) {
      this.currentMouseX = event.offsetX;
      this.currentMouseY = event.offsetY;

      if (this.isDraggingImage) {
        const deltaX = this.currentMouseX - this.lastMouseX;
        const deltaY = this.currentMouseY - this.lastMouseY;
        this.originX += deltaX;
        this.originY += deltaY;
        this.lastMouseX = this.currentMouseX;
        this.lastMouseY = this.currentMouseY;
        this.draw();
      } else if (this.isDraggingRectangle && this.selectedRectangle) {
        const deltaX = (this.currentMouseX - this.lastMouseX) / (this.currentImage.width * this.scale);
        const deltaY = (this.currentMouseY - this.lastMouseY) / (this.currentImage.height * this.scale);
        this.selectedRectangle.x += deltaX;
        this.selectedRectangle.y += deltaY;
        this.lastMouseX = this.currentMouseX;
        this.lastMouseY = this.currentMouseY;
        this.draw();
      } else if (this.isResizing && this.selectedRectangle) {
        const deltaX = this.currentMouseX - this.lastMouseX;
        const deltaY = this.currentMouseY - this.lastMouseY;
        this.resizeRectangle(deltaX, deltaY);
        this.lastMouseX = this.currentMouseX;
        this.lastMouseY = this.currentMouseY;
        this.draw();
      } else if (this.drawing) {
        this.draw();
      }
    },
    onMouseUp(event) {
      if (event.button === 1) {
        this.isDraggingImage = false;
      }
      if (event.button === 0) {
        if (this.drawing) {
          const mouseX = this.currentMouseX;
          const mouseY = this.currentMouseY;

          if (Math.abs(mouseX - this.drawStartX) > 0 && Math.abs(mouseY - this.drawStartY) > 0) {
            this.addRectangle(mouseX, mouseY);
          }
          this.drawing = false;
        }
        this.isDraggingRectangle = false;
        this.isResizing = false;
        this.selectedResizeHandle = null;
        this.draw();
      }
    },
    addRectangle(mouseX, mouseY) {
      const selectedLabelInfo = this.labels.find(
        (label) => label.name === this.selectedLabel
      );

      const rect = {
        x: (Math.min(this.drawStartX, mouseX) - this.originX) / (this.currentImage.width * this.scale),
        y: (Math.min(this.drawStartY, mouseY) - this.originY) / (this.currentImage.height * this.scale),
        width: Math.abs(mouseX - this.drawStartX) / (this.currentImage.width * this.scale),
        height: Math.abs(mouseY - this.drawStartY) / (this.currentImage.height * this.scale),
        labelid: selectedLabelInfo.id,
        label: selectedLabelInfo.name,
        color: selectedLabelInfo.color,

      };
      this.images[this.selectedImageIndex].rectangles.push(rect);
    },
    resizeRectangle(deltaX, deltaY) {
      switch (this.selectedResizeHandle) {
        case 'top-left':
          this.selectedRectangle.x += deltaX / (this.currentImage.width * this.scale);
          this.selectedRectangle.y += deltaY / (this.currentImage.height * this.scale);
          this.selectedRectangle.width -= deltaX / (this.currentImage.width * this.scale);
          this.selectedRectangle.height -= deltaY / (this.currentImage.height * this.scale);
          break;
        case 'top-right':
          this.selectedRectangle.y += deltaY / (this.currentImage.height * this.scale);
          this.selectedRectangle.width += deltaX / (this.currentImage.width * this.scale);
          this.selectedRectangle.height -= deltaY / (this.currentImage.height * this.scale);
          break;
        case 'bottom-left':
          this.selectedRectangle.x += deltaX / (this.currentImage.width * this.scale);
          this.selectedRectangle.width -= deltaX / (this.currentImage.width * this.scale);
          this.selectedRectangle.height += deltaY / (this.currentImage.height * this.scale);
          break;
        case 'bottom-right':
          this.selectedRectangle.width += deltaX / (this.currentImage.width * this.scale);
          this.selectedRectangle.height += deltaY / (this.currentImage.height * this.scale);
          break;
      }
      this.draw();
    },
    getResizeHandle(mouseX, mouseY) {
      if (!this.selectedRectangle) return null;
      const width = this.currentImage.width * this.scale;
      const height = this.currentImage.height * this.scale;
      const rectX = this.originX + this.selectedRectangle.x * width;
      const rectY = this.originY + this.selectedRectangle.y * height;
      const rectW = this.selectedRectangle.width * width;
      const rectH = this.selectedRectangle.height * height;
      const handleSize = this.resizeHandleSize / this.scale;

      if (this.isWithinBounds(mouseX, mouseY, rectX, rectY, handleSize)) return 'top-left';
      if (this.isWithinBounds(mouseX, mouseY, rectX + rectW, rectY, handleSize)) return 'top-right';
      if (this.isWithinBounds(mouseX, mouseY, rectX, rectY + rectH, handleSize)) return 'bottom-left';
      if (this.isWithinBounds(mouseX, mouseY, rectX + rectW, rectY + rectH, handleSize)) return 'bottom-right';

      return null;
    },
    isWithinBounds(mouseX, mouseY, targetX, targetY, size) {
      return (
        mouseX >= targetX - size / 2 &&
        mouseX <= targetX + size / 2 &&
        mouseY >= targetY - size / 2 &&
        mouseY <= targetY + size / 2
      );
    },
    selectRectangle(index) {
      this.selectedRectangle = this.rectangles[index];
      this.draw();
    },
    selectLabel(label) {
      this.selectedLabel = label.name;
      if (this.selectedRectangle) {
        this.selectedRectangle.label = label.name;
        this.selectedRectangle.color = label.color;
        this.selectedRectangle.labelid = label.id;
        this.draw();
      }
    },
    removeRectangle(index) {
      this.rectangles.splice(index, 1);
      if (this.selectedRectangle && this.selectedRectangle === this.rectangles[index]) {
        this.selectedRectangle = null;
      }
      this.draw();
    },
    redrawNormalizedRectangles() {
      if (!this.currentImage) return;

      this.context.clearRect(0, 0, this.canvasWidth, this.canvasHeight);
      this.context.drawImage(this.currentImage, this.originX, this.originY, this.currentImage.width * this.scale, this.currentImage.height * this.scale);

      this.rectangles.forEach((rect) => {
        const rectX = rect.x * this.currentImage.width;
        const rectY = rect.y * this.currentImage.height;
        const rectWidth = rect.width * this.currentImage.width;
        const rectHeight = rect.height * this.currentImage.height;

        this.context.strokeStyle = 'black';
        this.context.strokeRect(
          this.originX + rectX * this.scale,
          this.originY + rectY * this.scale,
          rectWidth * this.scale,
          rectHeight * this.scale
        );
      });
    },
    copyRectangle() {
      if (this.selectedRectangle) {
        this.copiedRectangle = { ...this.selectedRectangle };
      }
    },
    pasteRectangle() {
      if (this.copiedRectangle) {
        const newRect = {
          ...this.copiedRectangle,
          x: this.copiedRectangle.x + 0.05,
          y: this.copiedRectangle.y + 0.05,
        };
        this.images[this.selectedImageIndex].rectangles.push(newRect);
        this.selectedRectangle = newRect;
        this.draw();
      }
    },
  },
};
</script>

<style scoped>
canvas {
  display: block;
  cursor: crosshair;
  margin-bottom: 16px;
}

.active {
  background-color: rgba(0, 0, 255, 0.1);
}

.active-label {
  background-color: rgba(0, 128, 0, 0.1);
}
</style>"