Created
November 24, 2016 06:50
-
-
Save appsforartists/39b83156dee562636d5ddcec200569eb to your computer and use it in GitHub Desktop.
Attempting drag in Cycle.js
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** @license | |
* Copyright 2016 - present The Material Motion Authors. All Rights Reserved. | |
* | |
* Licensed under the Apache License, Version 2.0 (the "License"); you may not | |
* use this file except in compliance with the License. You may obtain a copy | |
* of the License at | |
* | |
* http://www.apache.org/licenses/LICENSE-2.0 | |
* | |
* Unless required by applicable law or agreed to in writing, software | |
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | |
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | |
* License for the specific language governing permissions and limitations | |
* under the License. | |
*/ | |
import pairwise from 'xstream/extra/pairwise' | |
import sampleCombine from 'xstream/extra/sampleCombine' | |
import { DOMSource } from '@cycle/dom/rxjs-typings'; | |
import xs, { Stream } from 'xstream' | |
import { VNode } from '@cycle/dom'; | |
import { html } from 'snabbdom-jsx'; | |
export type Sources = { | |
DOM: DOMSource | |
} | |
export type Sinks = { | |
DOM: Stream<VNode> | |
} | |
// helpers moved to bottom of file for brevity | |
export function App(sources: Sources): Sinks { | |
const drag$ = getDrag$FromDOMSource( | |
sources.DOM.select('.draggable') | |
); | |
// This looks like the right way to implement mutual observation according to | |
// http://staltz.com/xstream/#imitate but it isn't working. Moreover, if I | |
// even subscribe to location$Proxy, vtree$ stops dispatching. | |
const location$Proxy = xs.create(); | |
const location$ = xs.merge( | |
xs.of( | |
{ | |
x: 0, | |
y: 0, | |
} | |
), | |
drag$.compose( | |
sampleCombine(location$Proxy) | |
).map( | |
addPoints | |
) | |
); | |
location$Proxy.imitate(location$); | |
const vtree$ = location$.map( | |
location => ( | |
<div | |
className = 'draggable' | |
style = { | |
{ | |
backgroundColor: '#8BC34A', | |
width: '56px', | |
height: '56px', | |
borderRadius: '28px', | |
boxShadow: ` | |
0 3px 1px -2px rgba(0, 0, 0, 0.2), | |
0 2px 2px 0 rgba(0, 0, 0, 0.14), | |
0 1px 5px 0 rgba(0, 0, 0, 0.12) | |
`, | |
willChange: 'transform', | |
transform: `translate(${ location.x }px, ${ location.y }px)`, | |
} | |
} | |
/> | |
) | |
); | |
const sinks = { | |
DOM: vtree$ | |
}; | |
return sinks; | |
} | |
function getPointerLocationFromEvent(event: PointerEvent) { | |
return { | |
x: event.pageX, | |
y: event.pageY, | |
}; | |
} | |
function getDistanceBetweenPoints([prev, next]) { | |
if (!prev || !next) { | |
return { | |
x: 0, | |
y: 0, | |
}; | |
} | |
return { | |
x: next.x - prev.x, | |
y: next.y - prev.y, | |
}; | |
} | |
function addPoints([prev, next]) { | |
if (!prev || !next) { | |
return { | |
x: 0, | |
y: 0, | |
}; | |
} | |
return { | |
x: next.x + prev.x, | |
y: next.y + prev.y, | |
}; | |
} | |
function getDrag$FromDOMSource(domSource) { | |
return domSource.events('pointerdown').map( | |
downEvent => { | |
downEvent.target.setPointerCapture(downEvent.pointerId); | |
return domSource.events('pointermove').endWhen( | |
domSource.events('pointerup').take() | |
).startWith( | |
downEvent | |
).map( | |
getPointerLocationFromEvent | |
).compose(pairwise).map( | |
getDistanceBetweenPoints | |
) | |
} | |
).flatten(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
And the cleaner solution: