原文链接: rxjs6 简单拖拽
下一篇: rxjs6 拖拽接龙
效果
使用rxjs为dom添加拖拽
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="./rxjs.umd.js"></script>
<style>
.box {
width: 50px;
height: 50px;
background: deepskyblue;
position: relative;
}
.circle {
border-radius: 50%;
}
</style>
</head>
<body>
<div class="box" id="box1"></div>
<div class="box circle" id="box2"></div>
<script>
const {range, fromEvent} = rxjs;
const {map, mapTo, filter, throttleTime, debounceTime, repeat, switchMap, takeUntil} = rxjs.operators;
function setPosition(elem, position) {
elem.style['left'] = position.x + 'px'
elem.style['top'] = position.y + 'px'
}
function getPosition(elem) {
return {
x: +elem.style.left.replace('px', ''),
y: +elem.style.top.replace('px', ''),
}
}
function addDrag(elem, container) {
let mousedown = fromEvent(elem, 'mousedown')
let mouseup = fromEvent(container, 'mouseup')
let mousemove = fromEvent(container, 'mousemove')
mousedown.pipe(
map(e => {
let {x, y} = getPosition(elem)
return {
clickX: e.x,
clickY: e.y,
initX: x,
initY: y,
clickTime: +new Date()
}
}),
switchMap(({clickX, clickY, initX, initY, clickTime}) =>
mousemove.pipe(
throttleTime(40),
map(
e => {
let x = initX + e.x - clickX
let y = initY + e.y - clickY
let time = +new Date() - clickTime
return {
x,
y,
time
}
}
)
)
),
takeUntil(mouseup),
repeat()
).subscribe(position => {
console.log(position)
setPosition(elem, position)
})
}
addDrag(document.getElementById('box1'), document)
addDrag(document.getElementById('box2'), document)
</script>
</body>
</html>
可以看出, rxjs拥有极强的封装能力, 将状态和改变状态的行为隔离, 并且提供统一的流式事件和数据处理能力
添加延迟动画, 在mousedown时, 持续按住一段时间, 触发移动动画, 然后再进行移动, 禁止直接移动
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="./rxjs.umd.js"></script>
<style>
.box {
width: 50px;
height: 50px;
background: deepskyblue;
position: relative;
}
.circle {
/*border-radius: 50%;*/
background: greenyellow;
}
.blink {
animation: .5s linear blinking;
}
@keyframes blinking {
0% {
/*opacity: 1;*/
transform: rotate(0);
}
25% {
/*opacity: 0;*/
transform: rotate(-30grad);
}
50% {
/*opacity: 0;*/
transform: rotate(0);
}
75% {
/*opacity: 0;*/
transform: rotate(30grad);
}
100% {
/*opacity: 1;*/
transform: translateZ(0);
}
}
</style>
</head>
<body>
<div class="box" id="box1"></div>
<div class="box circle" id="box2"></div>
<script>
const {range, fromEvent,of} = rxjs;
const {map, mapTo, filter,delay,tap, throttleTime, debounceTime, repeat, switchMap, takeUntil} = rxjs.operators;
function setPosition(elem, position) {
elem.style['left'] = position.x + 'px'
elem.style['top'] = position.y + 'px'
}
function getPosition(elem) {
return {
x: +elem.style.left.replace('px', ''),
y: +elem.style.top.replace('px', ''),
}
}
function addDrag(elem, container) {
let mousedown = fromEvent(elem, 'mousedown')
let mouseup = fromEvent(container, 'mouseup')
let mousemove = fromEvent(container, 'mousemove')
mousedown.pipe(
switchMap(e => {
let {x, y} = getPosition(elem)
return of({
clickX: e.x,
clickY: e.y,
initX: x,
initY: y,
clickTime: +new Date()
})
}),
delay(200),
tap(() => {
console.log('move start')
elem.classList.add("blink")
}),
takeUntil(mousemove),
repeat(),
switchMap(({clickX, clickY, initX, initY, clickTime}) => {
console.log('tap2', elem.className)
return mousemove.pipe(
throttleTime(40),
map(
e => {
let x = initX + e.x - clickX
let y = initY + e.y - clickY
let time = +new Date() - clickTime
return {
x,
y,
time
}
}
),
)
}
),
takeUntil(mouseup.pipe(
tap(() => {
console.log('move end')
elem.classList.remove("blink")
})
)),
repeat()
).subscribe(position => {
console.log(position)
setPosition(elem, position)
})
}
addDrag(document.getElementById('box1'), document)
addDrag(document.getElementById('box2'), document)
</script>
</body>
</html>
采用combine实现
mousedown.pipe(
switchMap(e => {
let {x, y} = getPosition(box)
return of({
clickX: e.x,
clickY: e.y,
initX: x,
initY: y,
clickTime: +new Date()
})
}),
delay(200),
tap(() => {
console.log('move start')
box.classList.add("blink")
}),
takeUntil(mousemove),
repeat(),
switchMap(({clickX, clickY, initX, initY, clickTime}) => {
console.log('tap2', box.className)
return mousemove.pipe(
throttleTime(40),
map(
e => {
let x = initX + e.x - clickX
let y = initY + e.y - clickY
let time = +new Date() - clickTime
return {
x,
y,
time
}
}
),
)
}
),
takeUntil(mouseup.pipe(
tap(() => {
console.log('move end')
box.classList.remove("blink")
})
)),
repeat()
).subscribe(position => {
console.log(position)
setPosition(box, position)
})