Skip to content

Instantly share code, notes, and snippets.

@mohhasbias mohhasbias/.block
Created Feb 26, 2017

Embed
What would you like to do?
multi line drawing
license: mit
height: 300
border: no

Implementasi line drawing (multiple lines)

<!DOCTYPE html>
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]-->
<!--[if IE 7]> <html class="no-js lt-ie9 lt-ie8"> <![endif]-->
<!--[if IE 8]> <html class="no-js lt-ie9"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js"> <!--<![endif]-->
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Multi Line Drawing</title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<!--[if lt IE 7]>
<p class="browsehappy">You are using an <strong>outdated</strong> browser. Please <a href="#">upgrade your browser</a> to improve your experience.</p>
<![endif]-->
<div id="d3-drawing-area"></div>
<script src="//cdnjs.cloudflare.com/ajax/libs/d3/4.6.0/d3.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/redux/3.6.0/redux.min.js"></script>
<script>
/* ======================
* definitions
* ======================*/
// reducers
function drag(state = false, action) {
switch(action.type) {
case 'DRAG_START':
return true;
case 'DRAG_STOP':
return false;
default:
return state;
}
}
function dragStart() {
return {
type: 'DRAG_START'
};
}
function dragStop() {
return {
type: 'DRAG_STOP'
};
}
function selectDrag(state) {
return state.drag;
}
function lines(state = [], action) {
switch(action.type) {
case 'LINE_START':
return [
...state,
{
p1: action.payload.position
}
];
case 'LINE_EXTEND':
var lastLine = state.slice(-1)[0];
return [
...state.slice(0, -1),
Object.assign({}, lastLine, {
p2: action.payload.position
})
];
case 'LINE_STOP':
var lastLine = state.slice(-1)[0];
if(lastLine.hasOwnProperty('p2')) {
return state;
} else {
return state.slice(0, -1);
}
default:
return state;
}
}
function lineStart(position) {
return {
type: 'LINE_START',
payload: {
position: position
}
};
}
function lineExtend(position) {
return {
type: 'LINE_EXTEND',
payload: {
position: position
}
};
}
function lineStop(position) {
return {
type: 'LINE_STOP',
payload: {
position: position
}
};
}
function selectLines(state) {
return state.lines;
}
// middleware
function logger() {
return function(next) {
return function(action) {
console.log(action.type);
return next(action);
}
}
}
// draw lines
function drawLines(linesData) {
// console.log(linesData)
var lines = svg.selectAll('.line')
.data(linesData, (d,i) => i); // update
lines.exit().remove(); // exit
lines.enter() // enter
.append('line')
.merge(lines) // enter + update
.attr('class', 'line')
.attr('x1', d => d.p1[0])
.attr('y1', d => d.p1[1])
.attr('x2', d => d.p2[0])
.attr('y2', d => d.p2[1])
.style('stroke', 'blue')
.style('stroke-width', 2);
}
/* ======================
* main
* ======================*/
// global store
var reducer = Redux.combineReducers({
drag: drag,
lines: lines
});
var store = Redux.createStore(reducer, {}, Redux.applyMiddleware(logger));
// d3 visualizer
var svg = d3.select('#d3-drawing-area').append('svg')
.attr('width', 300)
.attr('height', 300)
.style('background', 'lightblue');
// attach event
svg.on('mousedown', function() {
store.dispatch(lineStart(d3.mouse(this)));
store.dispatch(dragStart());
});
svg.on('mousemove', function() {
if(selectDrag(store.getState())) {
store.dispatch(lineExtend(d3.mouse(this)));
}
});
svg.on('mouseup', function() {
store.dispatch(dragStop());
store.dispatch(lineStop(d3.mouse(this)));
});
// update d3 on state change
store.subscribe(function() {
console.log('state changed');
console.log(selectLines(store.getState()));
drawLines(
selectLines(store.getState())
.filter(line => line.hasOwnProperty('p2'))
);
});
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.