K 线图桌面端拖动适配

项目仓库:
Gitee:https://gitee.com/yyt363045841/klinechart
Github:https://github.com/363045841/klinechart
NPM:https://www.npmjs.com/package/@363045841yyt/klinechart
安装:npm i @363045841yyt/klinechart
项目持续更新中!欢迎提出宝贵建议!如果对您有帮助可以给个 Star!

正常情况下组件内的拖动是通过 overflow-x: auto 来实现的,但是 K 线图通常采用左右拖动的形式浏览,这就要求桌面端和移动端的操作逻辑一致。

视觉层

首先隐藏掉 x 轴滚动条(虽然滚动条看不见也点不到了,但这个 div 依然具备滚动的能力,比如你用触控板双指滑动,或者通过 JS 代码修改 scrollLeft,它依然会滚动):

/* Firefox */
scrollbar-width: none; 
/* Chrome/Safari */
::-webkit-scrollbar { display: none; }

逻辑层

mouseDown 事件

当按下左键时,响应事件并记录当前鼠标位置:

function onMouseDown(e: MouseEvent) {
  // 只响应左键
  if (e.button !== 0) return

  const container = containerRef.value
  if (!container) return

  isDragging.value = true
  dragStartX = e.clientX
  scrollStartX = container.scrollLeft

  // 防止选中文字
  e.preventDefault()
}

通过 MouseEvent.button 可以获取鼠标哪个键被按下:

0:主按键,通常指鼠标左键或默认值
1:辅助按键,通常指鼠标滚轮中键
2:次按键,通常指鼠标右键
3:第四个按钮,通常指浏览器后退按钮
4:第五个按钮,通常指浏览器的前进按钮

设置 isDragging 表明开始拖拽。记录鼠标按下时的 X 坐标位置 dragStartX
保存容器当前的滚动位置 scrollStartX

mouseMove 事件

function onMouseMove(e: MouseEvent) {
  if (!isDragging.value) return

  const container = containerRef.value
  if (!container) return

  const deltaX = dragStartX - e.clientX
  container.scrollLeft = scrollStartX + deltaX
}

当鼠标移动时,不断进行以下计算:
计算鼠标动了多少:

位移 = 刚按下时的鼠标 X − 现在的鼠标 X    ( 1 ) 位移 = 刚按下时的鼠标 X - 现在的鼠标 X\;(1) 位移=刚按下时的鼠标X现在的鼠标X(1)

更新卷轴位置:

新的卷轴位置 = 刚按下时的卷轴位置 + 位移 新的卷轴位置 = 刚按下时的卷轴位置 + 位移 新的卷轴位置=刚按下时的卷轴位置+位移

这里的核心问题是要理解当鼠标向左拖动的时候,实际上的 scrollLeft 是应该增加的,因为视觉上用户其实是在向右移动。因此 (1) 式也是向左移动为正,向右移动为负。

mouseUp 事件

function onMouseUp() {
  isDragging.value = false
}

取消拖动标记。

渲染层

由于鼠标事件动态修改了 container.scrollLeft,因此 @scroll 事件被照常触发,无缝接入原先的重绘逻辑,实现鼠标拖动和重绘的解耦。

样式交互

为了提供更好的用户体验(UX),我们需要在视觉上告知用户该区域是“可拖拽”的。这通常通过 CSS 的 cursor 属性来实现,模拟真实物理世界中“抓取”和“拖动”的动作反馈。

  • 默认状态: 当鼠标悬停在图表区域时,光标应变为张开的手掌(grab),暗示用户“此处可以抓取”。
  • 激活状态: 当用户按下鼠标进行拖拽时,光标应变为握紧的拳头(grabbing),给予用户“正在拖动中”的反馈。
.chart-container {
  /* 提示用户可以抓取 */
  cursor: grab; 
}

/* 当元素被按下(激活)时 */
.chart-container:active {
  /* 提示用户正在抓取移动中 */
  cursor: grabbing;
}

这个 active 伪类在元素被激活(鼠标按下且未松开)时触发。
注意为了防止出现 CSS 规则不生效的情况,应该遵循LVHA原则

  1. Link(没点过)
  2. Visited(点过)
  3. Hover(鼠标放上去)
  4. Active(按下去)
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

yyt363045841

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值