javascript-svg-在圆环上拖动并选中区域

目录

  • 问题描述
  • 解决思路
  • 代码结构

问题描述

假设我某个页面上使用了<svg>,其中包括一个<circle>。我希望实现的是:在circle上点击某个位置后,拖动,出现圆弧状阴影。实现效果为:
在这里插入图片描述

解决思路

要实现这个效果,需要考虑3个问题:

  1. 如何绘制圆弧阴影?
  2. 何时添加圆弧阴影?
  3. 在拖动时如何修改圆弧阴影的范围?

对于第1个问题,很明显我们需要使用<path>,并且通过设置fillstrokestroke-widthopacity等属性定制圆弧阴影的外观,通过设置d属性修改其位置和大小。

对于第2个问题,思路是这样的:首先,鼠标按下(mousedown事件)时为<svg>添加<path>元素,同时设置外观参数,并将初始为falseisDragging属性设置为true;当鼠标开始移动(mousemove事件)时,如果isDragging == true,那么说明是在拖动,此时计算d属性的值(即第3个问题),并进行更新;当鼠标抬起(mouseup事件)时,如果isDragging == true,说明拖动已经结束,此时将isDragging重新设置为false,并做一些清理(如果需要的话)。

对于第3个问题,实际是绘制如图所示的图像(从(x0, y0)顺时针连线,r1r2是不同的半径):
在这里插入图片描述

此时<path>d属性的值应该是这样的结构:

M x0 y0
L x1 y1
A r2 r2 a1 isLargeArc isOuterClockwise x2 y2
L x3 y3
A r1 r1 a2 isLargeArc isInnerClockwise x0 y0
Z

其中:
a 1 = θ 2 − θ 1 , a 2 = 360 − a 1 a1 = θ_2 - θ_1, a2 = 360 - a1 a1=θ2θ1,a2=360a1
isLargeArc表示是大弧(1)还是小弧(0),isOuterClockwise和isInnerClockwise表示外层圆弧和内侧圆弧是否为顺时针。

这里需要考虑的问题有:

3.1 如何获取θ1和当前θ2?如何通过θ计算圆弧上点的坐标?
这个在上一篇已经写过,此处不再赘述。javascript-svg-在圆环上加入闪烁光标-CSDN博客

3.2 如何判断圆弧阴影区域是大弧还是小弧?
由于绘制时可能出现跨越0点的情况,如下图所示:
在这里插入图片描述
所以考虑先判断绘制方向是顺时针还是逆时针。首先默认都是小弧,如果满足以下条件之一则为大弧:
a) θ1 > θ2、绘制方向为顺时针、(θ2 + 360 - θ1) > 180
b) θ1 < θ2、绘制方向为逆时针、(θ1 + 360 - θ2) > 180
c) 如不满足a和b,同时满足abs(θ2 - θ1) > 180

3.3 如何判断绘制方向是顺时针还是逆时针?
此时需要考虑最近两个θ的大小关系。假设有两个全局变量startAnglelastAngle,以及一个标记方向的变量angleDirection。在mousedown事件中,先计算初始位置的θ,并赋值给startAnglelastAngle;在mousemove事件中,获得当前的θ(记作currentAngle),并通过这个函数来判断方向:

function determineDirection(currentAngle) {if (lastAngle != null) {const diff = currentAngle - lastAngle;if (diff > 0 && Math.abs(diff) < 180 || diff < -180) {angleDirection = 1; // Clockwise} else if (diff < 0 && Math.abs(diff) < 180 || diff > 180) {angleDirection = 0; // Counterclockwise}}lastAngle = currentAngle;console.log(angleDirection > 0 ? "Clockwise" : "Counterclockwise");
}

最后在mouseup事件中重置lastAngleangleDirection

3.4 如何计算isOuterClockwise和isInnerClockwise?
首先,由于绘制方向的问题,这俩一定是相反的。直接使用绘制方向是否为顺时针作为isOuterClockwise的值,isInnerClockwise只要与之相反即可。

代码结构

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
</head>
<body><div><svg width="100%" height="1000" xmlns="http://www.w3.org/2000/svg"><circle id="myCircle1" cx="600" cy="480" r="285" fill="#fff" stroke="#ccc" stroke-width="1" /><!-- 先隐藏line --><line x1="1" y1="11" x2="2" y2="2" id="cursor" stroke="#1F2744" stroke-width="1" style="display:none;"></line></svg></div>
<script>// 获取svg和circleconst svg = document.querySelector('svg');const circle = document.getElementById('myCircle1');let isDragging = false;let arcPath = null;let startAngle, lastAngle;// 1 for clockwise, 0 for counterclockwise, -1 for none. 这是方便写svg// 其实可以自定义let angleDirection = 1; // 添加监听circle.addEventListener('mousedown', (e) => {isDragging = true;// 使用窗口中的圆心和点击点计算夹角,省略函数的实现// 计算细节可看:https://blog.csdn.net/pxy7896/article/details/144256701let angle = calculateCircleInfo(centerX, centerY, radius, clickX, clickY);startAngle = angle;lastAngle = startAngle;// do something// 添加path元素,并做一些设置arcPath = document.createElementNS("http://www.w3.org/2000/svg", "path");arcPath.setAttribute("opacity", 0.3);arcPath.setAttribute("fill", "blue");arcPath.setAttribute("stroke", "blue");arcPath.setAttribute("stroke-width", 1);svg.appendChild(arcPath);});svg.addEventListener('mousemove', (e) => {if (isDragging) {// 使用窗口中的圆心和点击点计算夹角,省略函数的实现// 判断绘制方向并计算darcPath.setAttribute("d", d);}});svg.addEventListener('mouseup', (e) => {if(isDragging) {// 重置isDragging = false;lastAngle = null;angleDirection = 1;}
});</script>
</body>
</html>	

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/34923.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

Android 使用 Canvas 和 Paint 实现圆形图片

学习笔记 效果展示: 全部代码: public class YuanActivity extends AppCompatActivity {private ActivityYuanBinding binding;Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);// 通过 DataBinding 获取布局文件binding …

python怎么将字母大写

Python中有三种将字母转换为大写的方法&#xff1a;upper()、capitalize()、title()。 下面通过实例给大家介绍具体用法&#xff1a; str "www.php.com" print(str.upper()) # 把所有字符中的小写字母转换成大写字母 print(str.lower()) # 把所有字…

鸿蒙Next星河版高级用例之网络请求和自适应布局以及响应式布局

目录&#xff1a; 1、发起网络请求的两种方式第一种使用httpRequest发送http的请求&#xff1a;1.1、在进行网络请求前&#xff0c;您需要在module.json5文件中申明网络访问权限1.2、GET 请求1.3、POST请求1.4、处理响应的结果第二种使用axios发送http的请求&#xff1a;1.1、在…

ClouderaManager 集群搭建

前提&#xff1a;服务器之前做过域名映射、免密登录 ClouderaManager 集群 1. 组件分布规划 服务器服务器h1zk、hdfs(dn)、yarn(nm)、spark、kafka、flumeh2hdfs(nn-standy)、yarn(rm-active)、sparkh3hdfs(nn-active)、yarn(rm-standy)、hive、sparkh4zk、hdfs(dn)、yarn(n…

如何获取谷歌新闻API密钥?

在信息获取和新闻传播领域&#xff0c;快速获取最新的新闻动态至关重要。谷歌新闻API为开发者提供了强大的工具&#xff0c;能够方便地集成全球各类新闻内容。通过使用该API&#xff0c;开发者可以实现对新闻的实时访问和管理&#xff0c;为用户提供丰富的信息服务。本文将指导…

IP 协议

IP协议 一、介绍1、IP协议2、IPv43、IPv6 二、主要功能三、协议格式1、示意图2、说明 四、网段划分1、介绍2、目的3、方法4、步骤 五、基于类别的IP地址分配方式1、示意图2、范围 六、CIDR1、介绍2、组成3、优点4、示意图 七、子网掩码1、介绍2、功能3、表示方法4、CIDR表示法5…

数据结构 (23)并查集与等价类划分

一、并查集 并查集&#xff08;Union-Find Set或Disjoint Set&#xff09;是一种数据结构&#xff0c;用于处理一些不相交集合&#xff08;disjoint sets&#xff09;的合并及查询问题。它通常表示为森林&#xff0c;并用数组来实现&#xff08;类似于二叉堆&#xff09;。在并…

Java 【数据结构】 哈希(Hash超详解)HashSetHashMap【神装】

登神长阶 第十神装 HashSet 第十一神装 HashMap 目录 &#x1f454;一.哈希 &#x1f9e5;1.概念 &#x1fa73;2.Object类的hashCode()方法: &#x1f45a;3.String类的哈希码: &#x1f460;4.注意事项: &#x1f3b7;二.哈希桶 &#x1fa97;1.哈希桶原理 &#x…

lyapunov指数的绘制

有如下方程&#xff1a; %% 方程式 % x(n1)1y(n)-a*x(n)^2 % y(n1)b*x(n)绘制其对应的lyapunov指数。 MATLAB实现方式&#xff1a; clc; clearvars; close all;%% 方程式 % x(n1)1y(n)-a*x(n)^2 % y(n1)b*x(n)%% 代码 N 1000; a (0:0.001:1.4); b 0.3; na length(a…

LearnOpenGL学习(高级OpenGL -- 深度测试,模板测试,)

深度测试 深度缓冲用来防止被阻挡的面渲染到其他面的前面&#xff0c;深度缓冲就像颜色缓冲&#xff0c;在每个片段中储存了信息&#xff0c; 当深度测试(Depth Testing)被启用的时候&#xff0c;OpenGL会将一个片段的深度值与深度缓冲的内容进行对比。OpenGL会执行一个深度测…

【CSP CCF记录】202305-2第30次认证 矩阵运算

题目 样例输入 3 2 1 2 3 4 5 6 10 10 -20 -20 30 30 6 5 4 3 2 1 4 0 -5 样例输出 480 240 0 0 -2200 -1100 思路 我的初步想法是按照题目所给计算顺序&#xff0c;分为三步计算&#xff0c;即&#xff1a; 1. &#xff0c;时间复杂度为 2. &#xff0c;时间复杂度为 3.&a…

Tomcat,javaweb, servlet , springBoot

在server.xml里配置服务器 <scope>provided</scope>打包的时候&#xff0c;这个jar包不会被打进去&#xff0c;因为tomcat已将封装了这个jar包&#xff0c;没必要要这个

书生实战营第四期-进阶岛第一关-探索 InternLM 模型能力边界

任务一: InternThinker 挑战 Leetcode Leetcode题目链接 Prompt InternThinker 回答截图 Q1 仅含置位位的最小整数 - 力扣&#xff08;LeetCode&#xff09; 给你一个正整数 n。 返回 大于等于 n 且二进制表示仅包含 置位 位…

[SAP ABAP] ALV基础开发

ALV全称为SAP List Viewer&#xff0c;是SAP中常用的报表输出格式&#xff0c;输出结果以行和列展示&#xff0c;集成的功能有排序&#xff0c;求和&#xff0c;过滤&#xff0c;隐藏&#xff0c;筛选等功能 ALV格式的数据是以单元格为单位显示&#xff0c;这种方式便于数据导…

360全向触觉型灵巧手 Allegro Hand V5 亮相,Wonik 机器人助推前沿科技前行

在机器人技术持续演进的当下&#xff0c;Wonik Robotics 依靠自身技术实力&#xff0c;推出了新一代机器人手 Allegro Hand V5&#xff0c;为工业与科研领域带来新机遇。 Allegro Hand V5 具备诸多出色特性。 Allegro Hand V5 指尖配备的全方位触觉传感器是一大亮点&#xff0…

python 装饰器学习与实践

目录 装饰器学习1、最基本装饰器2、函数带参数的装饰器3、装饰器带参数4、类中函数的装饰器5、装饰器实践6、pyqt5类中方法的装饰器实现时遇到的问题 装饰器学习 先假定一个场景 在之前的一篇文章中&#xff0c;分享了一个pyqt5将日志实时展示在gui界面上的功能python在pyqt5l…

12.4深度学习_模型优化和迁移_awanb、tb

一、数据获取方法 1. 开源数据集 ​ 免费&#xff0c;成本低 PyTorch&#xff1a; https://pytorch.org/vision/stable/datasets.html 开源数据集imagenet&#xff1a;https://image-net.org/ Hugging Face数据集&#xff1a;https://huggingface.co/datasets kaggle数据集…

网络基础知识

172.16.24.100这个是ip地址&#xff0c;讲师机的IP地址。IP地址&#xff08;Internet Protocol Address&#xff09;是指互联网协议地址&#xff0c;又译为网际协议地址。每台电脑只要联网都会有ip地址。ip地址数量有限&#xff0c;不够给世界上每一台电脑分配ip地址&#xff0…

漫画之家系统:Spring Boot技术下的漫画发现引擎

4 系统设计 4.1系统设计主要功能 通过市场调研及咨询研究&#xff0c;了解了用户及管理者的使用需求&#xff0c;于是制定了管理员和用户等模块。功能结构图如下所示&#xff1a; 图4-1系统功能结构图 4.2数据库设计 4.2.1数据库设计规范 数据可设计要遵循职责分离原则&#…

漫画之家系统:Spring Boot框架下的漫画版权保护

摘 要 随着信息技术和网络技术的飞速发展&#xff0c;人类已进入全新信息化时代&#xff0c;传统管理技术已无法高效&#xff0c;便捷地管理信息。为了迎合时代需求&#xff0c;优化管理效率&#xff0c;各种各样的管理系统应运而生&#xff0c;各行各业相继进入信息管理时代&a…