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

相关推荐
Lefan2 分钟前
一文了解什么是Dart
前端·flutter·dart
Patrick_Wilson7 分钟前
青苔漫染待客迟
前端·设计模式·架构
vvilkim9 分钟前
Nuxt.js 全面测试指南:从单元测试到E2E测试
开发语言·javascript·ecmascript
写不出来就跑路28 分钟前
基于 Vue 3 的智能聊天界面实现:从 UI 到流式响应全解析
前端·vue.js·ui
OpenTiny社区30 分钟前
盘点字体性能优化方案
前端·javascript
FogLetter34 分钟前
深入浅出React Hooks:useEffect那些事儿
前端·javascript
Savior`L35 分钟前
CSS知识复习4
前端·css
0wioiw01 小时前
Flutter基础(前端教程④-组件拼接)
前端·flutter
花生侠1 小时前
记录:前端项目使用pnpm+husky(v9)+commitlint,提交代码格式化校验
前端