onMouseDown
事件,即当鼠标点下,再触发onMouseMove
事件,监听鼠标滑动距离来修改初始宽度为0小盒子的动态宽度。(命名:index.js
)
import React, { Component } from 'react';
import './style.css';
import unSelect from './assets/drag_line.svg';
import onSelect from './assets/drag_line_hover.svg';
class SwipeScan extends Component {
constructor(props) {
super(props);
// 初始化state
this.state = {
// 滑动条初始左偏移
initX: 0,
// 滑动条动态左偏移 即默认显示位置
needX: -28,
// 滑动条的宽度
SliderW: 0,
// 扫描盒子宽度和高度
boxW: 0,
boxH: 0,
// 滑动条选中状态
isSelect: false,
};
}
componentDidMount = () => {
// 封装设置元素高宽的函数
this.setWidHei();
// 监听 当窗口大小发生变化触发
window.addEventListener('resize', this.onResize);
};
// 销毁监听
componentWillUnmount = () => {
document.body.removeEventListener('mousemove', this.onMouseMove);
document.body.removeEventListener('mouseup', this.onMouseUp);
window.removeEventListener('resize', this.onResize);
};
// 封装设置元素高宽的函数
setWidHei = () => {
// 获取扫描盒子的宽度 即右边图片的大小宽度
this.setState({
boxW: document.getElementsByClassName('scanBox')[0].clientWidth,
boxH: document.getElementsByClassName('scanBox')[0].clientHeight,
SliderW: document.getElementsByClassName('slider')[0].clientWidth,
});
};
// 当窗口大小发生变化触发
onResize = () => {
this.setWidHei();
// eslint-disable-next-line no-restricted-globals
location.reload();
};
// 当鼠标点下触发事件
onMouseDown = (e) => {
let { initX } = this.state;
// 当前鼠标点下的页面位置-当前元素的左偏移=滑动条初始左偏移
initX = e.clientX - e.target.offsetLeft;
this.setState({ initX, isSelect: true });
// 给body绑定鼠标移动监听事件
document.body.addEventListener('mousemove', this.onMouseMove);
// 给body绑定鼠标弹起监听事件
document.body.addEventListener('mouseup', this.onMouseUp);
};
// 当鼠标移动触发事件
onMouseMove = (e) => {
const { boxW, SliderW } = this.state;
// 动态滑动距离
let resultX = 0;
// 鼠标移动距离
const MoveX = e.clientX - this.state.initX;
if (MoveX <= -28) {
resultX = -28;
} else if (MoveX >= boxW - SliderW + 27) {
resultX = boxW - SliderW + 27;
} else {
resultX = MoveX;
}
this.setState({
needX: resultX,
});
};
// 当鼠标弹起触发事件
onMouseUp = () => {
this.setState({ isSelect: false });
document.body.removeEventListener('mousemove', this.onMouseMove);
document.body.removeEventListener('mouseup', this.onMouseUp);
};
render() {
const { needX, isSelect, boxW, boxH } = this.state;
const { leftImg, rightImg } = this.props;
// 滑动条的左边偏移量
const sliderStyle = {
left: needX,
// 如果滑动条是选中状态则选择第一个背景图片,否则第二个
backgroundImage: isSelect ? `url(${onSelect})` : `url(${unSelect})`,
};
// 修改左边盒子的宽度和高度,避免页面大小变化时出现不对齐的情况
const rightBoxStyle = {
width: needX + 28,
height: boxH,
};
// 固定左边图片的高宽,避免页面大小变化时出现不对齐的情况
const rightImgStyle = {
width: boxW,
height: boxH,
};
return (
<div className='scanBox noSelect' onMouseUp={this.onMouseUp}>
{/* 左边盒子 */}
<div className='left noSelect' style={rightBoxStyle}>
{/* 左边图片 */}
<img
alt='after'
src={leftImg}
className='noDrag'
style={rightImgStyle}
/>
</div>
{/* 滑动条 */}
<div
onMouseDown={this.onMouseDown}
className='slider'
style={sliderStyle}
></div>
{/* 右边盒子 */}
<div className='right noSelect'>
{/* 右边盒子 */}
<img alt='before' src={rightImg} className='rightPic noDrag' />
</div>
</div>
);
}
}
export default SwipeScan;
(命名:style.css
)
/* 图片不可拖动 */
.noDrag {
-webkit-user-drag: none;
}
/* div不可选中 */
.noSelect {
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
/* 扫描盒子 */
.scanBox {
position: relative;
margin: 100px auto;
/* 高度宽度可根据实际情况配置 */
width: 800px;
height: 500px;
overflow: hidden;
}
/* 解译按钮 */
.scanBox .scanBtn {
position: absolute;
top: 50%;
left: 50%;
z-index: 5;
padding: 0px 20px;
font-size: 18px;
transform: translate(-50%, -50%);
}
/* 滑动条 */
.scanBox .slider {
position: absolute;
top: 0px;
z-index: 3;
width: 56px;
height: 100%;
background-image: url(assets/drag_line.svg);
background-repeat: no-repeat;
background-size: 100% 100%;
}
/* 左盒子 */
.scanBox .left {
position: absolute;
top: 0;
left: 0;
z-index: 2;
width: 100%;
height: 100%;
overflow: hidden;
}
/* 左图片 */
.scanBox .left .leftPic {
width: 100%;
height: 100%;
}
/* 右盒子 */
.scanBox .right {
position: absolute;
top: 0;
left: 0px;
z-index: 1;
width: 100%;
height: 100%;
overflow: hidden;
}
/* 右图片 */
.scanBox .right .rightPic {
width: 100%;
height: 100%;
}
可以按需求更改svg代码,或者直接用上喜欢的图片
未点中状态(命名:drag_line.svg
):
<svg xmlns="http://www.w3.org/2000/svg" width="58" height="1019.5" viewBox="0 0 58 1019.5">
<g id="组_30" data-name="组 30" transform="translate(-999 -127.5)">
<line id="直线_21" data-name="直线 21" y2="480.5" transform="translate(1028.5 666.5)" fill="none" stroke="#adadad" stroke-width="2"/>
<line id="直线_22" data-name="直线 22" y2="481" transform="translate(1028.5 127.5)" fill="none" stroke="#adadad" stroke-width="2"/>
<g id="椭圆_12" data-name="椭圆 12" transform="translate(999 608)" fill="none" stroke="#adadad" stroke-width="2">
<circle cx="29" cy="29" r="29" stroke="none"/>
<circle cx="29" cy="29" r="28" fill="none"/>
g>
<g id="组_29" data-name="组 29" transform="translate(1010 627.295)">
<path id="多边形_1" data-name="多边形 1" d="M10.5,0,21,11H0Z" transform="translate(0 20.705) rotate(-90)" fill="#adadad"/>
<path id="多边形_2" data-name="多边形 2" d="M10.5,0,21,11H0Z" transform="translate(36 -0.295) rotate(90)" fill="#adadad"/>
g>
g>
svg>
点中状态(命名:drag_line_hover.svg
):
<svg xmlns="http://www.w3.org/2000/svg" width="58" height="1019.5" viewBox="0 0 58 1019.5">
<g id="组_30" data-name="组 30" transform="translate(-999 -127.5)">
<line id="直线_21" data-name="直线 21" y2="480.5" transform="translate(1028.5 666.5)" fill="none" stroke="#1890ff" stroke-width="2"/>
<line id="直线_22" data-name="直线 22" y2="481" transform="translate(1028.5 127.5)" fill="none" stroke="#1890ff" stroke-width="2"/>
<g id="椭圆_12" data-name="椭圆 12" transform="translate(999 608)" fill="none" stroke="#1890ff" stroke-width="2">
<circle cx="29" cy="29" r="29" stroke="none"/>
<circle cx="29" cy="29" r="28" fill="none"/>
g>
<g id="组_29" data-name="组 29" transform="translate(1010 627.295)">
<path id="多边形_1" data-name="多边形 1" d="M10.5,0,21,11H0Z" transform="translate(0 20.705) rotate(-90)" fill="#1890ff"/>
<path id="多边形_2" data-name="多边形 2" d="M10.5,0,21,11H0Z" transform="translate(36 -0.295) rotate(90)" fill="#1890ff"/>
g>
g>
svg>
这个具体要看你怎么使用了,我是直接导入在项目里的index.js
。(组件命名:SwipeScan
)
// 导入组件
import SwipeScan from './SwipeScan';
// 导入图片
import leftImg from './assets/leftImg.png';
import rightImg from './assets/rightImg.png';
// 渲染
ReactDOM.render(
<div>
// 使用组件,传递图片
<SwipeScan leftImg={leftImg} rightImg={rightImg} />
</div>,
document.getElementById('root')
);