Js实现椭圆绘制

在一些项目中,可能会需要对一些内容模块通过框选随时进行一个标记,以下实现了在页面中通过鼠标拖动进行椭圆的绘制(当然 如果有其他标记样式需求换个样式即可)

首先,要熟悉一下具体实现流程,当鼠标按下需要创建一个元素标签用来作为存放椭圆的容器,因为可能绘制多个椭圆,这里通过circlelist数组存放每个椭圆的信息(以便后期与后端交互永久存储,下次直接获取数据展示)

const circlelist = reactive([
  {
    id: 1,
    width: 100,//椭圆的宽
    height: 50,//椭圆的高
    left: 50,//椭圆距离父元素左侧距离
    top: 10,//椭圆距离父元素顶部距离
  },
]);

当鼠标按下设置isdragging状态值,用来在鼠标移动时判断是否需要去绘制;获取当前鼠标的位置(offsetX:距离容器左侧的距离;offsetY:距离容器顶部的距离),用来设置椭圆在容器中的位置;设置椭圆起始宽高为0,将新建的一个椭圆信息插入到circlelist中,并且创建元素标签

const currentid = ref(1);//当前绘制的椭圆id
const onmousedowns = (e) => {
  isdragging.value = true;
  let { offsetX, offsetY } = e;
  startX.value = offsetX;
  startY.value = offsetY;
  currentid.value++;
  const ele = {
    id: currentid.value,
    width: 0,
    height: 0,
    left: offsetX,
    top: offsetY,
    status:false,
  };
  circlelist.push(ele);
  let span = document.createElement("span");
  span.id=ele.id.toString()
  span.style.cssText = `position:absolute;left:${ele.left}px;top:${ele.top}px;display:inline-block;width:${ele.width}px;height:${ele.height}px;border:2px solid red;border-radius: 50%;`;
  showcontainer.value?.appendChild(span);
};

当鼠标移动并且鼠标处于按下状态中,也就是isdragging值为true时,根据当前的id获取绘制的椭圆标签,计算出移动后新的椭圆宽高,位置信息对标签样式属性进行改变,以便实时获取椭圆信息 

const onmousemoves = (e) => {
  if (isdragging.value) {
    let span = document.getElementById(currentid.value.toString());
    const rect = e.currentTarget.getBoundingClientRect();
    let offsetX = e.clientX - rect.left;
    let offsetY = e.clientY - rect.top;
    let width = Math.abs(offsetX - startX.value);
    let height = Math.abs(offsetY - startY.value);
    // 判断当前鼠标和起始鼠标位置,用于反向绘制
    let left = startX.value > offsetX ? offsetX : startX.value;
    let top = startY.value > offsetY ? offsetY : startY.value;
    span.style.width = width + "px";
    span.style.height = height + "px";
    span.style.left = left + "px";
    span.style.top = top + "px";
  }
};

鼠标抬起,设置isdragging值为false,停止椭圆的绘制

完整代码:

<template>
  <h1 style="text-align: center">绘制椭圆</h1>
  <div
    ref="showcontainer"
    class="container"
    @mousedown="onmousedowns($event)"
    @mousemove="onmousemoves($event)"
    @mouseup="onmouseups($event)"
  ></div>
</template>
<script setup lang="ts">
import { ref, reactive, onMounted } from "vue";
const showcontainer = ref();
// 是否处于绘制状态
const isdragging = ref(false);
//开始绘制的起始位置
let startX = ref();
let startY = ref();
const circlelist = reactive([
  {
    id: 1,
    width: 100, //椭圆的宽
    height: 50, //椭圆的高
    left: 50, //椭圆距离父元素左侧距离
    top: 10, //椭圆距离父元素顶部距离
  },
]);
const currentid = ref(1); //当前绘制的椭圆id
const onmousedowns = (e) => {
  isdragging.value = true;
  let { offsetX, offsetY } = e;
  startX.value = offsetX;
  startY.value = offsetY;
  currentid.value++;
  const ele = {
    id: currentid.value,
    width: 0,
    height: 0,
    left: offsetX,
    top: offsetY,
  };
  circlelist.push(ele);
  // 创建标签元素
  let span = document.createElement("span");
  span.id = ele.id.toString();
  span.style.cssText = `position:absolute;left:${ele.left}px;top:${ele.top}px;display:inline-block;width:${ele.width}px;height:${ele.height}px;border:2px solid red;border-radius: 50%;`;
  showcontainer.value?.appendChild(span);
};
const onmousemoves = (e) => {
  if (isdragging.value) {
    let span = document.getElementById(currentid.value.toString());
    const rect = e.currentTarget.getBoundingClientRect();
    let offsetX = e.clientX - rect.left;
    let offsetY = e.clientY - rect.top;
    let width = Math.abs(offsetX - startX.value);
    let height = Math.abs(offsetY - startY.value);
    // 判断当前鼠标和起始鼠标位置,用于反向绘制
    let left = startX.value > offsetX ? offsetX : startX.value;
    let top = startY.value > offsetY ? offsetY : startY.value;
    span.style.width = width + "px";
    span.style.height = height + "px";
    span.style.left = left + "px";
    span.style.top = top + "px";
  }
};
const onmouseups = (e) => {
  isdragging.value = false;
};
const initcircle = () => {
  if (circlelist.length != 0) {
    circlelist.forEach((item) => {
      let span = document.createElement("span");
      span.id = item.id.toString();
      span.style.cssText = `position:absolute;left:${item.left}px;top:${item.top}px;display:inline-block;width:${item.width}px;height:${item.height}px;border:2px solid red;border-radius: 50%;`;
      showcontainer.value?.appendChild(span);
    });
  }
};
onMounted(() => {
  initcircle();
});
</script>
<style scoped lang="scss">
.container {
  position: relative;
  width: 100%;
  height: 400px;
  background-color: antiquewhite;
}
</style>

  • 8
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值