123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354 |
- <template>
- <div class="chart-container">
- <div id="ring-chart" ref="chart" class="ring-chart"></div>
- <!-- //圆心-->
- <!-- <div id="cc" style="position: absolute;width: 5px;height: 5px;background: #ff0000"></div>-->
- <!--<div id="ring-chart" ref="chart" class="ring-chart"-->
- <!--@mousedown="begin" @mousemove="moving" @mouseup="stopMoving"-->
- <!--></div>-->
- </div>
- </template>
- <script setup>
- import {ref, onMounted, onBeforeUnmount} from 'vue'
- import * as echarts from 'echarts'
- document.body.style.overflow = 'hidden';
- const props = defineProps({
- chartProps: {}
- })
- const isFinish = ref(props.chartProps.isFinish)
- const chart = ref(null)
- let myChart = null
- const currentValue = ref(1) // 初始值
- const isBegin = ref(false)
- // 鼠标状态
- const isDragging = ref(false)
- const startAngle = ref(0)
- const startValue = ref(0)
- const option = ref({})
- // 初始化图表
- const initChart = () => {
- if (!chart.value) return
- myChart = echarts.init(chart.value, null, {width: width, height: height})
- option.value = {
- series: [{
- type: 'pie',
- radius: [radiusMax, radiusMin],
- startAngle: 180,
- endAngle: 360,
- avoidLabelOverlap: false,
- itemStyle: {
- borderRadius: 10,
- borderColor: '#ffff00',
- borderWidth: 2
- },
- label: {
- show: true,
- position: 'center',
- // formatter: '{c}%',
- fontSize: 24,
- fontWeight: 'bold',
- color: '#333'
- },
- emphasis: {
- scale: false,
- itemStyle: {
- shadowBlur: 10,
- shadowOffsetX: 0,
- shadowColor: 'rgba(0, 0, 0, 0.5)'
- }
- },
- data: [
- {value: currentValue.value, name: '', itemStyle: {color: '#5470c6'}},
- {value: 100 - currentValue.value, name: '', itemStyle: {color: '#eee'}}
- ]
- }]
- }
- myChart.setOption(option.value)
- // 添加图表鼠标事件
- // myChart.getZr().on('mousedown', startDrag)
- // myChart.getZr().on('mouseup', endDrag)
- // myChart.getZr().on('mousemove', handleDrag)
- }
- // 更新图表数据
- const updateChart = (newValue) => {
- if (!myChart) return
- currentValue.value = Math.max(0, Math.min(100, newValue)) // 限制在0-100之间
- myChart.setOption({
- series: [{
- data: [
- {value: currentValue.value},
- {value: 100 - currentValue.value}
- ]
- }]
- })
- }
- // 开始拖动
- const startDrag = (e) => {
- if (e.target && e.target.type === 'arc') {
- isDragging.value = true
- startAngle.value = getAngle(e.offsetX, e.offsetY)
- startValue.value = currentValue.value
- }
- }
- // 结束拖动
- const endDrag = () => {
- isDragging.value = false
- }
- // 处理拖动
- const handleDrag = (e) => {
- if (!isDragging.value) return
- const currentAngle = getAngle(e.offsetX, e.offsetY)
- const angleDiff = currentAngle - startAngle.value
- const valueDiff = (angleDiff / 360) * 100
- updateChart(startValue.value + valueDiff)
- }
- // 获取鼠标位置对应的角度
- const getAngle = (x, y) => {
- const rect = chart.value.getBoundingClientRect()
- const centerX = rect.width / 2
- const centerY = rect.height / 2
- const deltaX = x - centerX
- const deltaY = y - centerY
- const angle = Math.atan2(deltaY, deltaX) * 180 / Math.PI
- return (angle + 450) % 360 // 调整为0-360度
- }
- onMounted(() => {
- initChart()
- init()
- })
- onBeforeUnmount(() => {
- // 移除事件监听
- if (myChart) {
- myChart.getZr().off('mousedown', startDrag)
- myChart.getZr().off('mouseup', endDrag)
- myChart.getZr().off('mousemove', handleDrag)
- myChart.dispose()
- }
- })
- //环形相关信息
- const width = props.chartProps.width
- const height = props.chartProps.height
- const left = props.chartProps.left
- const top = props.chartProps.top
- const radiusMax = props.chartProps.radiusMax
- const radiusMin = props.chartProps.radiusMin
- const center_x = left + width / 2
- const center_y = top + height / 2
- function init() {
- //
- // var cc = document.getElementById("cc");
- // console.log("cccccc", "top:", top, "left:", left, "width:", width, "height:", height, "center_y:", center_y, "center_x", center_x)
- // cc.style.top = center_y + "px"
- // cc.style.left = center_x + "px"
- let chartDiv = document.getElementById("ring-chart");
- chartDiv.addEventListener('touchstart', begin)
- chartDiv.addEventListener('touchmove', moving)
- chartDiv.addEventListener('touchend', stopMoving)
- }
- function testMove(e) {
- let x = e.targetTouches[0].pageX;
- let y = e.targetTouches[0].pageY;
- }
- //取点和圆心的角度
- function calculateAngleDegrees(x1, y1, x2, y2) {
- const dx = x2 - x1;
- const dy = y2 - y1;
- const radians = Math.atan2(dy, dx);
- return radians * (180 / Math.PI); // 弧度转角度
- }
- //
- const beginCorner = ref(0)
- const beginPoint = ref({})
- const endCorner = ref(0)
- const endPoint = ref({})
- // function begin(event) {
- //
- // if (!isFinish.value) {
- // if (!event.targetTouches || event.targetTouches.length === 0) return;
- //
- // // 获取触摸点坐标(相对于视口)
- // const touch = event.targetTouches[0];
- // const mouse_x = touch.clientX;
- // const mouse_y = touch.clientY;
- //
- // // 获取图表容器的位置(相对于视口)
- // const chartRect = chart.value.getBoundingClientRect();
- // const center_x = chartRect.left + chartRect.width / 2;
- // const center_y = chartRect.top + chartRect.height / 2;
- //
- // // 计算角度(调整为 ECharts 需要的坐标系)
- // let ang = calculateAngleDegrees(mouse_x, mouse_y, center_x, center_y);
- // console.log("*********************",mouse_x, mouse_y, center_x, center_y)
- // // 将角度转换为 ECharts 的 startAngle 格式:
- // // - 0° 在右侧,顺时针方向
- // // - 调整为 180° 到 360° 的范围(根据你的半圆设计)
- // ang = (360 - ang) % 360; // 反转方向(逆时针 → 顺时针)
- // ang = Math.max(180, Math.min(360, ang)); // 限制在半圆范围内
- //
- // // 更新起始角度
- // beginCorner.value = 360 - ang;
- // option.value.series[0].startAngle = 180 + ang;
- // myChart.setOption(option.value);
- // isBegin.value = true;
- // }
- //
- // }
- function begin(event) {
- console.log("=====", props.chartProps.status)
- if (!event.targetTouches || event.targetTouches.length === 0) return;
- //鼠标按下,取点
- let mouse_x = event.targetTouches[0].pageX;
- let mouse_y = event.targetTouches[0].pageY;
- if (props.chartProps.status == 'edit' && isFinish.value == true) {
- //
- console.log(mouse_x,"11111",mouse_x)
- //
- //计算一下离谁比较近
- let d_begin = Math.pow((beginPoint.value.x - mouse_x),2)+ Math.pow((beginPoint.value.y - mouse_y),2)
- let d_end = Math.pow((endPoint.value.x - mouse_x),2)+ Math.pow((endPoint.value.y - mouse_y),2)
- if(d_begin <= d_end){
- let ang = calculateAngleDegrees(mouse_x, mouse_y, center_x, center_y)
- option.value.series[0].startAngle = 180 - ang
- beginCorner.value = ang
- beginPoint.value ={
- x : mouse_x,
- y : mouse_y
- }
- //
- }else{
- let eang = calculateAngleDegrees(mouse_x, mouse_y, center_x, center_y)
- option.value.series[0].data[0].value = (eang - beginCorner.value) * 5 / 9 + beginCorner.value / 30
- option.value.series[0].data[1].value = 100 - (eang - beginCorner.value) * 5 / 9 - beginCorner.value / 30
- endCorner.value = eang
- endPoint.value ={
- x : mouse_x,
- y : mouse_y
- }
- }
- } else if (props.chartProps.status == 'new') {
- let ang = calculateAngleDegrees(mouse_x, mouse_y, center_x, center_y)
- beginCorner.value = ang
- beginPoint.value = {
- x: mouse_x,
- y: mouse_y
- }
- console.log("ssss",beginPoint.value.x,beginPoint.value.y)
- option.value.series[0].startAngle = 180 - ang
- isBegin.value = true
- }
- myChart.setOption(option.value)
- }
- function stopMoving() {
- nextTick(() => {
- isFinish.value = true
- isBegin.value = false
- myChart.setOption(option.value)
- })
- window.setTimeout(finish, 1000)
- }
- function finish() {
- //alert("绘制完成!")
- }
- function moving(event) {
- let mouse_x = event.targetTouches[0].pageX;
- let mouse_y = event.targetTouches[0].pageY;
- let eang = calculateAngleDegrees(mouse_x, mouse_y, center_x, center_y)
- if (eang >= 0 && eang <= 180) {
- option.value.series[0].data[0].value = (eang - beginCorner.value) * 5 / 9 + beginCorner.value / 30
- option.value.series[0].data[1].value = 100 - (eang - beginCorner.value) * 5 / 9 - beginCorner.value / 30
- }
- endCorner.value = eang
- endPoint.value = {
- x: mouse_x,
- y: mouse_y
- }
- myChart.setOption(option.value)
- }
- // function moving(event) {
- // if (!isFinish.value && isBegin.value == true) {
- // let mouse_x = event.targetTouches[0].pageX;
- // let mouse_y = event.targetTouches[0].pageY;
- // let eang = calculateAngleDegrees(mouse_x, mouse_y, center_x, center_y)
- //
- // eang = (360 - eang) % 360; // 反转方向(逆时针 → 顺时针)
- // eang = Math.max(180, Math.min(360, eang)); // 限制在半圆范围内
- // eang = 360 - eang
- // if (eang >= 0 && eang <= 180) {
- // if (eang >= 0 && eang <= 90) {
- // option.value.series[0].data[0].value = (eang - beginCorner.value) * 5 / 9
- // option.value.series[0].data[1].value = 100 - (eang - beginCorner.value) * 5 / 9
- // } else {
- // option.value.series[0].data[0].value = (eang) * 5 / 9
- // option.value.series[0].data[1].value = 100 - (eang) * 5 / 9
- // }
- // myChart.setOption(option.value)
- // }
- // }
- //
- // }
- </script>
- <style scoped>
- .chart-container {
- position: relative;
- width: 1700px;
- height: 910px;
- display: flex;
- flex-direction: column;
- align-items: center;
- justify-content: center;
- }
- .ring-chart {
- width: 1700px;
- height: 910px;
- cursor: pointer;
- border: 1px solid white;
- margin-top: 219px;
- }
- </style>
|