使用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...

相关推荐
饺子大魔王的男人3 小时前
【Three.js】机器人管线包模拟
javascript·机器人
知否技术3 小时前
知道这10个npm工具包,开发效率提高好几倍!第2个大家都用过!
前端·npm
希希不嘻嘻~傻希希4 小时前
CSS 字体与文本样式笔记
开发语言·前端·javascript·css·ecmascript
石小石Orz4 小时前
分享10个吊炸天的油猴脚本,2025最新!
前端
爷_5 小时前
Nest.js 最佳实践:异步上下文(Context)实现自动填充
前端·javascript·后端
爱上妖精的尾巴5 小时前
3-19 WPS JS宏调用工作表函数(JS 宏与工作表函数双剑合壁)学习笔记
服务器·前端·javascript·wps·js宏·jsa
草履虫建模5 小时前
Web开发全栈流程 - Spring boot +Vue 前后端分离
java·前端·vue.js·spring boot·阿里云·elementui·mybatis
—Qeyser6 小时前
让 Deepseek 写电器电费计算器(html版本)
前端·javascript·css·html·deepseek
UI设计和前端开发从业者6 小时前
从UI前端到数字孪生:构建数据驱动的智能生态系统
前端·ui
Junerver7 小时前
Kotlin 2.1.0的新改进带来哪些改变
前端·kotlin