如何让 xstream 组合鼠标事件?
how do I get xstream to combine mouse events?
我正在 codepen 中使用 cyclejs 进行拖放试验。 HTML 5 支持的标准拖动方法似乎不支持对拖动对象移动的限制,所以我选择了标准 mousedown/mousemove/mouseup。它有效,但不一致。 combine() 操作似乎不会触发,即使 debug() 调用显示已收到 mousedown 和 mousemove 事件,有时会错过 mouseup。也许我对操作的理解不完整或不正确。此 post 底部提供了代码笔的直接 link。感谢任何帮助!
const xs = xstream.default;
const { run } = Cycle;
const { div, svg, makeDOMDriver } = CycleDOM;
function DragBox(sources) {
const COMPONENT_NAME = `DragBox`;
const intent = function({ DOM }) {
return {
mousedown$: DOM.select(`#${COMPONENT_NAME}`)
.events("mousedown")
.map(function(ev) {
return ev;
})
.debug("mousedown"),
mousemove$: DOM.select(`#${COMPONENT_NAME}`)
.events("mousemove")
.map(function(ev) {
return ev;
})
.debug("mousemove"),
mouseup$: DOM.select("#container")
.events("mouseup")
.map(function(ev) {
return ev;
})
.debug("mouseup")
};
};
const between = (first, second) => {
return source => first.mapTo(source.endWhen(second)).flatten();
};
const model = function({ mousedown$, mousemove$, mouseup$ }) {
return xs
.combine(mousedown$, mousemove$)
.debug("combine")
.map(([mousedown, mousemove]) => ({
x: mousemove.pageX - mousedown.layerX,
y: mousemove.pageY - mousedown.layerY
}))
.compose(between(mousedown$, mouseup$))
.startWith({
x: 0,
y: 0
})
.debug("model");
};
const getStyle = left => top => {
return {
style: {
position: "absolute",
left: left + "px",
top: top + "px",
backgroundColor: "#333",
cursor: "move"
}
};
};
const view = function(state$) {
return state$.map(value =>
div("#container", { style: { height: "100vh" } }, [
div(`#${COMPONENT_NAME}`, getStyle(value.x)(value.y), "Move Me!")
])
);
};
const actions = intent(sources);
const state$ = model(actions);
const vTree$ = view(state$);
return {
DOM: vTree$
};
}
function main(sources) {
const dragBox = DragBox(sources);
const sinks = {
DOM: dragBox.DOM
};
return sinks;
}
Cycle.run(main, {
DOM: makeDOMDriver("#app")
});
Testing your code 显示 combine
没有获得第一个 mousedown
事件,显然是由于 between
运算符在第一次 mousedown 之后订阅了 mousedown$
事件。将 remember
添加到 mousedown$
会将第一个 mousedown 事件发送到 between 运算符订阅。
mousedown$: DOM.select(`#${COMPONENT_NAME}`)
.events("mousedown").remember()
Codesandbox.io testing between
这是另一种 CycleJS/xstream 拖放方法(从这个 RxJS Drag and Drop example 中获得灵感)我认为更直接。您代码中的其他所有内容基本相同,但 model
函数是这样的:
const model = function({ mousedown$, mousemove$, mouseup$ }) {
return mousedown$.map(md => {
let startX = md.offsetX, startY = md.offsetY
return mousemove$.map(mm => {
mm.preventDefault()
return {
x: mm.clientX - startX,
y: mm.clientY - startY
}
}).endWhen(mouseup$)
}).flatten().startWith({x:0,y:0})
};
这是一个 Codepen.io example。
我正在 codepen 中使用 cyclejs 进行拖放试验。 HTML 5 支持的标准拖动方法似乎不支持对拖动对象移动的限制,所以我选择了标准 mousedown/mousemove/mouseup。它有效,但不一致。 combine() 操作似乎不会触发,即使 debug() 调用显示已收到 mousedown 和 mousemove 事件,有时会错过 mouseup。也许我对操作的理解不完整或不正确。此 post 底部提供了代码笔的直接 link。感谢任何帮助!
const xs = xstream.default;
const { run } = Cycle;
const { div, svg, makeDOMDriver } = CycleDOM;
function DragBox(sources) {
const COMPONENT_NAME = `DragBox`;
const intent = function({ DOM }) {
return {
mousedown$: DOM.select(`#${COMPONENT_NAME}`)
.events("mousedown")
.map(function(ev) {
return ev;
})
.debug("mousedown"),
mousemove$: DOM.select(`#${COMPONENT_NAME}`)
.events("mousemove")
.map(function(ev) {
return ev;
})
.debug("mousemove"),
mouseup$: DOM.select("#container")
.events("mouseup")
.map(function(ev) {
return ev;
})
.debug("mouseup")
};
};
const between = (first, second) => {
return source => first.mapTo(source.endWhen(second)).flatten();
};
const model = function({ mousedown$, mousemove$, mouseup$ }) {
return xs
.combine(mousedown$, mousemove$)
.debug("combine")
.map(([mousedown, mousemove]) => ({
x: mousemove.pageX - mousedown.layerX,
y: mousemove.pageY - mousedown.layerY
}))
.compose(between(mousedown$, mouseup$))
.startWith({
x: 0,
y: 0
})
.debug("model");
};
const getStyle = left => top => {
return {
style: {
position: "absolute",
left: left + "px",
top: top + "px",
backgroundColor: "#333",
cursor: "move"
}
};
};
const view = function(state$) {
return state$.map(value =>
div("#container", { style: { height: "100vh" } }, [
div(`#${COMPONENT_NAME}`, getStyle(value.x)(value.y), "Move Me!")
])
);
};
const actions = intent(sources);
const state$ = model(actions);
const vTree$ = view(state$);
return {
DOM: vTree$
};
}
function main(sources) {
const dragBox = DragBox(sources);
const sinks = {
DOM: dragBox.DOM
};
return sinks;
}
Cycle.run(main, {
DOM: makeDOMDriver("#app")
});
Testing your code 显示 combine
没有获得第一个 mousedown
事件,显然是由于 between
运算符在第一次 mousedown 之后订阅了 mousedown$
事件。将 remember
添加到 mousedown$
会将第一个 mousedown 事件发送到 between 运算符订阅。
mousedown$: DOM.select(`#${COMPONENT_NAME}`)
.events("mousedown").remember()
Codesandbox.io testing between
这是另一种 CycleJS/xstream 拖放方法(从这个 RxJS Drag and Drop example 中获得灵感)我认为更直接。您代码中的其他所有内容基本相同,但 model
函数是这样的:
const model = function({ mousedown$, mousemove$, mouseup$ }) {
return mousedown$.map(md => {
let startX = md.offsetX, startY = md.offsetY
return mousemove$.map(mm => {
mm.preventDefault()
return {
x: mm.clientX - startX,
y: mm.clientY - startY
}
}).endWhen(mouseup$)
}).flatten().startWith({x:0,y:0})
};
这是一个 Codepen.io example。