使用js如何手搓一个缩放条

使用js如何手搓一个缩放条

先看效果图

前言

可以通过拖动按钮显示不同的进度,如何手搓一个缩放条,这是我们需要用的鼠标事件和鼠标定位。

鼠标事件

click 单击鼠标左键时发生,如果右键也按下则不会发生。当用户的焦点在按钮上并按了 Enter 键时,同样会触发这个事件
dblclick 双击鼠标左键时发生,如果右键也按下则不会发生
mousedown 单击任意一个鼠标按钮时发生
mouseout 鼠标指针位于某个元素上且将要移出元素的边界时发生
mouseover 鼠标指针移出某个元素到另一个元素上时发生
mouseup 松开任意一个鼠标按钮时发生
mousemove 鼠标在某个元素上时持续发生
mouseenter 在鼠标光标位于元素外部时触发,然后移动到元素内部。
mouseleave 在鼠标光标悬停在元素上时触发,然后移动到元素的外部。

鼠标定位

clientX 以浏览器窗口左上顶角为原点,定位 x 轴坐标 所有浏览器,不兼容 Safari
clientY 以浏览器窗口左上顶角为原点,定位 y 轴坐标 所有浏览器,不兼容 Safari
offsetX 以当前事件的目标对象左上顶角为原点,定位 x 轴坐标 所有浏览器,不兼容 Mozilla
offsetY 以当前事件的目标对象左上顶角为原点,定位 y 轴坐标 所有浏览器,不兼容 Mozilla
pageX 以 document 对象(即文档窗口)左上顶角为原点,定位 x 轴坐标 所有浏览器,不兼容 IE
pageY 以 document 对象(即文档窗口)左上顶角为原点,定位 y 轴坐标 所有浏览器,不兼容 IE
screenX 计算机屏幕左上顶角为原点,定位 x 轴坐标 所有浏览器
screenY 计算机屏幕左上顶角为原点,定位 y 轴坐标 所有浏览器
layerX 最近的绝对定位的父元素(如果没有,则为 document 对象)左上顶角为元素,定位 x 轴坐标 Mozilla 和 Safari
layerY 最近的绝对定位的父元素(如果没有,则为 document 对象)左上顶角为元素,定位 y 轴坐标 Mozilla 和 Safari

本文主要用到的事件-----mousemove 事件类型是一个实时响应的事件,当鼠标指针的位置发生变化时(至少移动一个像素),就会触发 mousemove 事件。该事件响应的灵敏度主要参考鼠标指针移动速度的快慢以及浏览器跟踪更新的速度。

代码实现

1.创建所要实现的标签

xml 复制代码
<div>

    <div class="progress-container">

      <!-- 缩放条 -->

      <div class="progress-bar">

        <!-- 缩放条上面的label -->

        <div class="label">

          {{ `${Math.round(scalePercent)}%` }}

        </div>

        <!-- 拖方块图片 -->

        <img src="../../assets/DisplayArea/slider.png" class="slider"/>

        <!-- 滑动的过后的背景条 -->

        <div class="progress" :style="{ width: `${scalePercent}%` }"></div>

      </div>

    </div>

  </div>

2.给缩放条添加样式

css 复制代码
.page{

  width: 100vw;

  height: 100vh;

  background-color: #33CCCC ;

}

.progress-container {

  width: 936px;

  height: 48px;

  position: absolute;

  top: 50%;

  left: calc(50% - 462px);

  background-color: rgba(0, 0, 0, 0);

}

.progress-bar {

  width: 888px;

  height: 8px;

  position: absolute;

  bottom: 20px;

  left: 18px;

  background-color: #a49a9a;

  // background-image: linear-gradient(to right,#AF40FF, #5B42F3 50%,#00DDEB);

  border-radius: 6px;

}

  


.label {

  width: 92px;

  height: 72px;

  text-align: center;

  padding-top: 16px;

  box-sizing: border-box;

  background-image: url('../../assets/DisplayArea/bubble.png');

  background-size: 100%;

  font-size: 16px;

  font-weight: bold;

  color: #00428b;

  position: absolute;

  top: -72px;

}

  


.slider {

  width: 36px;

  height: 24px;

  position: absolute;

  top: -8px;

  z-index: 2;

  cursor: grab;

  box-shadow: 0 6px 12px rgba(0, 128, 232, 0.16);

}

  


.progress {

  height: 100%;

  // background-color: #00428b;

  background: linear-gradient(45deg, #ffbc00, #ff0058);

  border-radius: 6px;

}

3.实现缩放条的拖动同时数值的变化。这就要用到鼠标的事件了,给容器添加事件

xml 复制代码
<div class="page">

    <div

      class="progress-container"

      @mouseleave="onHandlerUnSelected"

      @mousemove="onSettingScale"

      @mouseup="onHandlerUnSelected"
    >

      <!-- 缩放条 -->

      <div class="progress-bar">

        <!-- 缩放条上面的label -->

        <div class="label">

          {{ `${Math.round(scalePercent)}%` }}

        </div>

        <!-- 拖方块图片 -->

        <img

          src="../../assets/DisplayArea/slider.png"

          class="slider"

          @mousedown="onHandlerSelected"

          @mouseup="onHandlerUnSelected"

        />

        <!-- 滑动的过后的背景条 -->

        <div class="progress"></div>

      </div>

    </div>

  </div>

4.书写鼠标事件,通过鼠标定位计算出相差的距离,来更新缩放条的数值。

csharp 复制代码
<script setup lang="ts">

import { ref } from 'vue'

// 进度数值

let scalePercent = ref(50)

// 是否是在选中状态下拖动

let sliderSelected = ref(false)

let start: number = 1

// 鼠标选中缩放条上滑块时触发

function onHandlerSelected(event: MouseEvent): void {

  // 阻止事件冒泡并且阻止该元素上同事件类型的监听器被触发

  // 解决事件的兼容性问题

  event = event || window.event

  event.stopImmediatePropagation()

  //   阻止事件冒泡

  event.stopPropagation()

  //  取消事件的默认动作

  event.preventDefault()

  //   显示鼠标样式

  sliderSelected.value = true

  start = event.clientX

}

// 鼠标松开缩放条滑块时触发

function onHandlerUnSelected(): void {

  sliderSelected.value = false

  start = 1

}

// 鼠标在缩放条上移动时触发

function onSettingScale(event: MouseEvent): void {

  if (!sliderSelected.value) return

  // 解决事件的兼容性问题

  event = event || window.event

  
  updateProgress(event.clientX)

}

//更新进度条和数值
function updateProgress(x: number): void {

  const dis = x - start

  //window.innerWidth 窗口的内部宽度

  // full  计算出缩放条的相对像素

  const full = window.innerWidth * (888 / 1920)

  // 移动的像素除以缩放条总共的像素    在乘以100  计算出百分比

  const per = (dis / full) * 100

  // 默认50%的百分比   加上计算出来的百分比

  scalePercent.value += per

  if (scalePercent.value < 0) {

    scalePercent.value = 1

  }

  if (scalePercent.value > 100) {

    scalePercent.value = 100

  }

  start = x

}

</script>

5.鼠标事件已经写好,需要给缩放条添加缩放的样式效果。

xml 复制代码
<div class="page">

    <div

      class="progress-container"

      @mouseleave="onHandlerUnSelected"

      @mousemove="onSettingScale"

      @mouseup="onHandlerUnSelected"

      :style="{ cursor: sliderSelected ? 'grabbing' : '' }"

    >

      <!-- 缩放条 -->

      <div class="progress-bar">

        <!-- 添加的style -->

        <div class="label" :style="{ left: `calc(${scalePercent}% - 46px)` }">

          {{ `${Math.round(scalePercent)}%` }}

        </div>

        <!-- 拖方块图片 添加的style-->

        <img

          src="../../assets/DisplayArea/slider.png"

          class="slider"

          :style="{

            left: `calc(${scalePercent}% - 18px)`,

            cursor: sliderSelected ? 'grabbing' : ''

          }"

          @mousedown="onHandlerSelected"

          @mouseup="onHandlerUnSelected"

        />

        <!-- 滑动的过后的背景条 添加的style-->

        <div class="progress" :style="{ width: `${scalePercent}%` }"></div>

      </div>

    </div>

  </div>

完整代码和素材

xml 复制代码
<script setup lang="ts">

import { ref } from 'vue'

// 进度数值

let scalePercent = ref(50)

// 是否是在选中状态下拖动

let sliderSelected = ref(false)

let start: number = 1

  


// 鼠标离开缩放条时触发

// function onCursorOutside(): void {

//   // 离开缩放条时让鼠标样式重置

//   sliderSelected.value = false

//   start = 1

// }

// 鼠标选中缩放条上滑块时触发

function onHandlerSelected(event: MouseEvent): void {

  // 阻止事件冒泡并且阻止该元素上同事件类型的监听器被触发

  // 解决事件的兼容性问题

  event = event || window.event

  event.stopImmediatePropagation()

  //   阻止事件冒泡

  event.stopPropagation()

  //  取消事件的默认动作

  event.preventDefault()

  //   显示鼠标样式

  sliderSelected.value = true

  start = event.clientX

}

// 鼠标松开缩放条滑块时触发

function onHandlerUnSelected(): void {

  sliderSelected.value = false

  start = 1

}

// 鼠标在缩放条上移动时触发

function onSettingScale(event: MouseEvent): void {

  if (!sliderSelected.value) return

  // 解决事件的兼容性问题

  event = event || window.event

  


  updateProgress(event.clientX)

}

  


function updateProgress(x: number): void {

  const dis = x - start

  //window.innerWidth 窗口的内部宽度

  // full  计算出缩放条的相对像素

  


  const full = window.innerWidth * (888 / 1920)

  // 移动的像素除以缩放条总共的像素    在乘以100  计算出百分比

  const per = (dis / full) * 100

  // 默认50%的百分比   加上计算出来的百分比

  scalePercent.value += per

  


  if (scalePercent.value < 0) {

    scalePercent.value = 1

  }

  if (scalePercent.value > 100) {

    scalePercent.value = 100

  }

  start = x

}

</script>

  


<template>

  <div class="page">

    <div

      class="progress-container"

      @mouseleave="onHandlerUnSelected"

      @mousemove="onSettingScale"

      @mouseup="onHandlerUnSelected"

      :style="{ cursor: sliderSelected ? 'grabbing' : '' }"

    >

      <!-- 缩放条 -->

      <div class="progress-bar">

        <!-- 缩放条上面的label -->

        <div class="label" :style="{ left: `calc(${scalePercent}% - 46px)` }">

          {{ `${Math.round(scalePercent)}%` }}

        </div>

        <!-- 拖方块图片 -->

        <img

          src="../../assets/DisplayArea/slider.png"

          class="slider"

          :style="{

            left: `calc(${scalePercent}% - 18px)`,

            cursor: sliderSelected ? 'grabbing' : ''

          }"

          @mousedown="onHandlerSelected"

          @mouseup="onHandlerUnSelected"

        />

        <!-- 滑动的过后的背景条 -->

        <div class="progress" :style="{ width: `${scalePercent}%` }"></div>

      </div>

    </div>

  </div>

</template>

  


<style lang="less" scoped>

.page{

  width: 100vw;

  height: 100vh;

  background-color: #33CCCC ;

}

.progress-container {

  width: 936px;

  height: 48px;

  position: absolute;

  top: 50%;

  left: calc(50% - 462px);

  background-color: rgba(0, 0, 0, 0);

}

.progress-bar {

  width: 888px;

  height: 8px;

  position: absolute;

  bottom: 20px;

  left: 18px;

  background-color: #a49a9a;

  // background-image: linear-gradient(to right,#AF40FF, #5B42F3 50%,#00DDEB);

  border-radius: 6px;

}

  


.label {

  width: 92px;

  height: 72px;

  text-align: center;

  padding-top: 16px;

  box-sizing: border-box;

  background-image: url('../../assets//DisplayArea/bubble.png');

  background-size: 100%;

  font-size: 16px;

  font-weight: bold;

  color: #00428b;

  position: absolute;

  top: -72px;

}

  


.slider {

  width: 36px;

  height: 24px;

  position: absolute;

  top: -8px;

  z-index: 2;

  cursor: grab;

  box-shadow: 0 6px 12px rgba(0, 128, 232, 0.16);

}

  


.progress {

  height: 100%;

  // background-color: #00428b;

  background: linear-gradient(45deg, #ffbc00, #ff0058);

  border-radius: 6px;

}

</style>

素材

# JS鼠标事件:c.biancheng.net/view/5944.h...

相关推荐
袁煦丞37 分钟前
OpenKylin 桌面系统,开源自由,跨界协作:cpolar内网穿透实验室第624个成功挑战
前端·程序员·远程工作
excel42 分钟前
JavaScript 尾递归优化详解
前端
lsp-072 小时前
JS 模块化与打包工具
开发语言·javascript·ecmascript
Dontla6 小时前
n8n飞书webhook配置(飞书机器人、飞书bot、feishu bot)Crypto节点、js timestamp代码、Crypto node
javascript·机器人·飞书
tager7 小时前
🔥3行代码搞定全局代理!告别插件依赖的极简方案
前端·fiddler·charles
gnip8 小时前
axios 拦截器实现用户无感刷新 access_token
前端
程序员码歌8 小时前
【零代码AI编程实战】AI灯塔导航-成果展示篇
前端·ai编程·cursor
gnip8 小时前
前端实现即时通讯,常用的技术
前端
烛阴9 小时前
告别 any!用联合类型打造更灵活、更安全的 TS 代码
前端·typescript
excel9 小时前
全面解析 JavaScript 类继承:方式、优缺点与应用场景
前端