Implementasi line drawing (multiple lines)
Created
February 26, 2017 16:48
-
-
Save mohhasbias/7d02d15d15b29b723a752f435d5e52bc to your computer and use it in GitHub Desktop.
multi line drawing
This file contains 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: mit | |
height: 300 | |
border: no |
This file contains 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
<!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