Last active
January 13, 2019 10:07
-
-
Save WolfgangFahl/22361573b05b541ac9799037116aea8d to your computer and use it in GitHub Desktop.
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> | |
<!-- | |
see also https://stackoverflow.com/questions/54151068/d3-multiple-different-graticules | |
--> | |
<html> | |
<head> | |
<meta http-equiv="content-type" | |
content="application/xhtml+xml; charset=utf-8"/> | |
<script src="https://d3js.org/d3.v4.min.js"></script> | |
<script src="https://d3js.org/d3-geo-projection.v1.min.js"></script> | |
<script src="https://d3js.org/d3-array.v1.min.js"></script> | |
<title>IFMMS Logo</title> | |
<style type="text/css"> | |
.leftlabel { | |
color: gray; | |
display: inline-block; | |
text-align: right; | |
width: 100px; | |
} | |
} | |
</style> | |
</head> | |
<body style=font-family:arial> | |
<fieldset> | |
<legend>Logo settings</legend> | |
<label class='leftlabel' for='pickerb'>background:</label> | |
<input id='pickerb' type='color' value='#FFFFFF' | |
onchange='changeColor(this,"background")'> | |
<select onchange='changeColor(this,"background","pickerb")'> | |
<option value="#FFFFFF">white</option> | |
<option value="#E8FFFF">aqua</option> | |
<option value="#F8F8F8">light gray</option> | |
</select> | |
<label class='leftlabel' for='pickers'>stroke:</label> | |
<input id='pickers' type='color' value='#000000' | |
onchange='changeColor(this,"graticule")'><select onchange='changeColor(this,"graticule","pickers")'> | |
<option value="#000000">black</option> | |
<option value="#0000FF">blue</option> | |
<option value="#808080">gray</option> | |
</select> | |
<br> | |
<label class='leftlabel' for='rowsSlider'>rows:</label> | |
<input id="rowsSlider" type="range" min="1" max="5" value="1" | |
onChange="changeSettings(this)"/><label id="rowsLabel"></label> | |
<label class='leftlabel' for='colsSlider'>columns:</label> | |
<input id="colsSlider" type="range" min="1" max="5" value="1" | |
onChange="changeSettings(this)"/><label id="colsLabel"></label> | |
<br> | |
<label class='leftlabel' for='latstepsSlider'>lat steps:</label> | |
<input id="latstepsSlider" type="range" min="4" max="20" value="10" | |
onChange="changeSettings(this)"/><label id="latstepsLabel"></label> | |
<label class='leftlabel' for='lonstepsSlider'>lon steps:</label> | |
<input id="lonstepsSlider" type="range" min="4" max="20" step="2" value="8" | |
onChange="changeSettings(this)"/><label id="lonstepsLabel"></label> | |
<br> | |
<label class='leftlabel' for='scaleSlider'>scale:</label> | |
<input id="scaleSlider" type="range" min="25" max="2000" step="25" value="200" | |
onChange="changeSettings(this)"/><label id="scaleLabel"></label> | |
<label class='leftlabel' for='strokeScaleSlider'>stroke:</label> | |
<input id="strokeScaleSlider" type="range" min="5" max="50" step="1" value="15" | |
onChange="changeSettings(this)"/><label id="strokeScaleLabel"></label> | |
<label class='leftlabel' for='symbolSlider'>symbol:</label> | |
<input id="symbolSlider" type="range" min="50" max="300" step="1" value="100" | |
onChange="changeSettings(this)"/><label id="symbolLabel"></label> | |
<br> | |
<label class='leftlabel' for='dxSlider'>dx:</label> | |
<input id="dxSlider" type="range" min="-500" max="500" step="1" value="0" | |
onChange="changeSettings(this)"/><label id="dxLabel"></label> | |
<label class='leftlabel' for='dySlider'>dy:</label> | |
<input id="dySlider" type="range" min="-500" max="500" step="1" value="0" | |
onChange="changeSettings(this)"/><label id="dyLabel"></label> | |
<br> | |
<label class='leftlabel' for='debugCheckbox'>debug:</label> | |
<input id="debugCheckbox" type=checkbox onclick="changeSettings(this)"/> | |
<label class='leftlabel' for='showSourceCheckbox'>showSource:</label> | |
<input id="showSourceCheckbox" type=checkbox onclick="changeSettings(this)"/> | |
<label class='leftlabel' for='utf8Checkbox'>UTF-8:</label> | |
<input id="utf8Checkbox" type=checkbox onclick="changeSettings(this)"/> | |
<label class='leftlabel' for='mollWeideCheckbox'>mollWeide:</label> | |
<input id="mollWeideCheckbox" type=checkbox onclick="changeSettings(this)"/> | |
</fieldset> | |
<h3>Logo drafts</h3> | |
<div id='container'></div> | |
<h3 id="sourcesTitle"></h3> | |
<div id='source'></div> | |
<script> | |
// global settings | |
var settings = { | |
rows: 1, | |
cols: 1, | |
dx: 0, | |
dy: 0, | |
lonsteps: 6, | |
latsteps: 10, | |
strokeScale: 15, | |
background: "white", | |
graticuleStroke: "black", | |
debug: false | |
}; | |
/** | |
* get the slider value and change the corresponding label | |
* return the value | |
* @param {prefix} - the prefix of the Slider and label | |
*/ | |
function getAndChangeSliderLabel(prefix) { | |
var value=getSliderValue(prefix) | |
setLabelValue(prefix,value) | |
return value; | |
} | |
/** | |
* get the label value | |
* @param {prefix} - the prefix of the Label | |
*/ | |
function setLabelValue(prefix,value) { | |
var label=document.getElementById(prefix+"Label"); | |
label.innerHTML=value; | |
} | |
/** | |
* get the slider value | |
* return the value | |
* @param {prefix} - the prefix of the Slider | |
*/ | |
function getSliderValue(prefix) { | |
var slider=document.getElementById(prefix+"Slider"); | |
var value=slider.value; | |
return parseInt(value); | |
} | |
/** | |
* get the checkBox value | |
* return the value | |
* @param {prefix} - the prefix of the checkBox | |
*/ | |
function getCheckBoxValue(prefix) { | |
var box=document.getElementById(prefix+"Checkbox"); | |
return box.checked | |
} | |
function changeSettings() { | |
dochangeSettings(settings) | |
} | |
/** | |
* modify the rows and columns | |
*/ | |
function dochangeSettings(settings) { | |
settings.rows=getAndChangeSliderLabel("rows"); | |
settings.cols=getAndChangeSliderLabel("cols"); | |
var startScale=getAndChangeSliderLabel("scale"); | |
var symbolScale=getAndChangeSliderLabel("symbol"); | |
settings.strokeScale=getAndChangeSliderLabel("strokeScale"); | |
settings.dx=getAndChangeSliderLabel("dx"); | |
settings.dy=getAndChangeSliderLabel("dy"); | |
settings.lonsteps=getAndChangeSliderLabel("lonsteps"); | |
settings.latsteps=getAndChangeSliderLabel("latsteps"); | |
var debug=getCheckBoxValue("debug") | |
var showSource=getCheckBoxValue("showSource") | |
var mollWeide=getCheckBoxValue("mollWeide"); | |
var utf8=getCheckBoxValue("utf8"); | |
sample(startScale,symbolScale,utf8,mollWeide,debug,showSource); | |
} | |
/** | |
* change the color getting the value from the given picker | |
* using the given attributeName | |
* @param {picker} - the picker for the color | |
* @param {attributeName} - the attribute of the setting to be changed | |
* @param {otherPickerId} - the id of the otherPicker to be changed (if any) | |
*/ | |
function changeColor(picker, attributeName,otherPickerId) { | |
var color=picker.value; | |
if (attributeName==="background") | |
settings.background=color; | |
if (attributeName==="graticule") | |
settings.graticuleStroke=color; | |
if (otherPickerId) { | |
otherPicker=document.getElementById(otherPickerId); | |
otherPicker.value=color; | |
} | |
changeSettings() | |
} | |
/** | |
* use the given svg element | |
* @param {svg} - the svg element in which to use the element | |
* @param {id} - the id of the element to be used | |
*/ | |
function use(svg,id) { | |
return uset(svg,id,1,1,0,0) | |
} | |
/** | |
* use the given element translated and scaled | |
* @param {svg} - the svg element in which to use the element | |
* @param {id} - the id of the element to be used | |
* @param {sx} - scale factor x | |
* @param {sy} - scale factor y | |
* @param {tx} - translation x | |
* @param {ty} - translation y | |
*/ | |
function uset(svg,id,sx,sy,tx,ty) { | |
return svg.append("g").append("use") | |
.attr("xlink:href","#"+id) | |
.attr("transform","translate("+tx+","+ty+") scale("+sx+","+sy+")") | |
} | |
/** | |
* append a rectangle to the given parent | |
* @param {parent} - the parent to append to | |
* @param {id} - the id for the rectangle | |
* @param {x} - the x position in pixels for the rectangle | |
* @param {y} - the y position in pixels for the rectangle | |
* @param {width} - the width in pixels for the rectangle | |
* @param {height} - the height in pixels for the rectangle | |
* @param {stroke} - the stroke color of the rectangle | |
*/ | |
function rect(parent,id,x,y,width,height,stroke) { | |
parent.append("rect") | |
.attr("id",id) | |
.attr("x",x) | |
.attr("y",y) | |
.attr("width",width) | |
.attr("height",height) | |
.attr("fill","#ccc") | |
.attr("opacity",.3) | |
.attr("stroke",stroke) | |
.attr("stroke-width",3); | |
} | |
/** | |
* create an IFMMS logo draft | |
* | |
* @param {title} - the title to use | |
* @param {svgid} - the id of the svg element to insert the logo into | |
* @param {cx} - base x | |
* @param {cy} - base y | |
* @param {scale} - the scale factor of the projection | |
* @param {symbolScale} - the scale of the symbol in percent | |
* @param {lonsteps} - how many steps around the globe from east to west | |
* @param {latsteps} - how many steps around the globe from south to north | |
* @param {utf8} - use UTF-8 symbol | |
* @param {mollWeide} - use MollWeide projection | |
* @param {debug} - show debug information | |
* @returns - the bounding box for the logo | |
*/ | |
function createLogo(title,svgid,cx,cy,scale,symbolScale,lonsteps,latsteps,utf8,mollWeide,debug) { | |
var svg= d3.select("#"+svgid); // context | |
// get a projection | |
var projection=d3.geoAitoff().scale(scale); | |
if (mollWeide) | |
projection=d3.geoMollweide(); | |
//----build svg graticule---- | |
var path = d3.geoPath().projection(projection); | |
var eps=0.01; | |
var lonstep=(360-eps)/lonsteps; | |
var latstep=(360-eps)/latsteps; | |
// create a graticule | |
var graticule = d3.geoGraticule().step([lonstep, latstep]); | |
// set the title of the SVG | |
svg.append("title").text(title); | |
// create a defs node | |
var defs=svg.append("defs"); | |
var ggraticule=defs.append("g") | |
.attr("id","graticule"+svgid) | |
.attr("fill", "none") | |
.attr("stroke", settings.graticuleStroke) | |
.attr("stroke-width",scale/settings.strokeScale); | |
var schlegelUndEisen=defs.append("g") | |
.attr("id","Schlaegel_und_Eisen_nach_DIN_21800"+svgid) | |
.append("path") | |
.attr("fill","black") | |
.attr("d","M83.526 24.3292l5.0006 5.0005 9.8445 19.7439 -19.7439 -9.8445 -4.825 -4.8248 -19.3012 19.9984 31.5273 30.4582c0.7699,0.7437 0.818,1.9607 0.1092,2.7628 -1.3648,1.5446 -2.826,3.0058 -4.3705,4.3705 -0.8021,0.7088 -2.0191,0.6608 -2.7628,-0.1091l-30.3544 -31.4199 -30.3246 31.4186c-0.7436,0.7704 -1.961,0.8188 -2.7634,0.1098 -1.5441,-1.3645 -3.005,-2.8251 -4.3693,-4.3692 -0.709,-0.8023 -0.6607,-2.0199 0.1098,-2.7635l31.5228 -30.425 -20.8788 -21.6126c-3.7644,4.233 -6.9481,8.9965 -9.4369,14.166l-10.8805 -9.4668c6.8998,-12.6804 17.338,-23.1096 30.0058,-30.0183l9.4619 10.879c-5.1582,2.4839 -9.9086,5.6625 -14.1303,9.4194l21.7166 20.9795 20.0988 -19.3983 -11.3677 -11.3679 9.8994 -9.8994 11.5433 11.5435 1.4376 -1.3877 4.6204 4.618 -1.3887 1.4389z") | |
.attr("transform","translate(0,0)"); | |
ggraticule.selectAll("path.feature"+svgid) | |
.data(graticule.lines) | |
.enter().append("path") | |
.attr("class", "feature"+svgid) | |
.attr("d", path); | |
defs.append("path") | |
.attr("id","background"+svgid) | |
.datum(graticule.outline) | |
.attr("fill", settings.background) | |
.attr("d", path); | |
// https://stackoverflow.com/questions/19134995/how-to-display-unicode-in-svg | |
// https://www.utf8icons.com/character/9874/hammer-and-pick | |
// unicode hex 2692 | |
// html ⚒ | |
// http://bl.ocks.org/eweitnauer/7325338 | |
defs.append("text") | |
.attr("id","hammerandpick"+svgid) | |
.attr("font-size",scale*3.3) | |
.attr("text-anchor","middle") | |
.attr("dominant-baseline","central") | |
.attr("x",0) | |
.attr("y",0) | |
.text("⚒"); | |
use(svg,"background"+svgid); | |
var guse=use(svg,"graticule"+svgid); | |
var bbox = guse.node().getBBox(); | |
if (utf8) { | |
uset(svg,"hammerandpick"+svgid,symbolScale/100,symbolScale/100,cx+settings.dx,cy-0.54*scale+settings.dy); | |
} else { | |
uset(svg,"Schlaegel_und_Eisen_nach_DIN_21800"+svgid,scale*symbolScale/3500,scale*symbolScale/3500,cx-1.39*scale+settings.dx,cy-1.56*scale+settings.dy); | |
} | |
if (debug) { | |
rect(svg,"border"+svgid,bbox.x,bbox.y,bbox.width,bbox.height,"#666") | |
} | |
return bbox; | |
} | |
/** | |
* get the id for the given row and column | |
*/ | |
function getId(row,col) { | |
return "logo"+row+col; | |
} | |
/** | |
* create an svg element with the given id, viewbox, width and height | |
* @param {vx} - view box x | |
* @param {vy} - view box y | |
* @param {vw} - view box width | |
* @param {vh} - view box height | |
* @param {width} - the width in pixels for the svg element | |
* @param {height} - the height in pixels for the svg element | |
*/ | |
function createSvg(id,vx,vy,vw,vh,width,height) { | |
var svg=document.createElementNS('http://www.w3.org/2000/svg','svg'); | |
svg.setAttribute('id',id); | |
svg.setAttribute('version','1.1'); | |
svg.setAttribute('xmlns:svg','http://www.w3.org/2000/svg'); | |
svg.setAttribute('xmlns:xlink','http://www.w3.org/1999/xlink'); | |
svg.setAttribute('viewBox',vx+' '+vy+' '+vw+' '+vh); | |
//svg.setAttribute('position','absolute'); | |
//svg.setAttribute('x',x); | |
//svg.setAttribute('y',y); | |
svg.setAttribute('width',width); | |
svg.setAttribute('height',height); | |
svg.setAttribute('overflow','visible'); | |
return svg; | |
} | |
/** | |
* encode the given HMTL string | |
* https://stackoverflow.com/a/48073476/1497139 | |
* @param {str} - the html string to encode | |
*/ | |
function encodeHTML(str){ | |
return str.replace(/[\u00A0-\u9999<>&](?!#)/gim, function(i) { | |
return '&#' + i.charCodeAt(0) + ';'; | |
}); | |
} | |
/** | |
* show the source for the given element | |
* @param {sourceId} - the id of the element to get the HTML source from | |
* @param {targetId} - the id of the element where to insert the code | |
* @param {title} - the title to use | |
*/ | |
function showSource(sourceId,targetId,title) { | |
var h3=document.createElement('h3') | |
h3.innerHTML=title; | |
var pre=document.createElement('pre'); | |
var source=document.getElementById(sourceId); | |
var target=document.getElementById(targetId); | |
pre.innerHTML=encodeHTML(source.outerHTML.replace(/[<]/g,"\n<")); | |
target.appendChild(h3); | |
target.appendChild(pre); | |
} | |
/** | |
* format the given value with the given prefix | |
* @param {prefix} - the prefix to use | |
* @param {value} - the title to use | |
* @returns {String} - the formatted String | |
*/ | |
function format(prefix,value) { | |
return prefix+": "+Math.round(value)+" " | |
} | |
/** | |
* get a formatted bounded Box string | |
*/ | |
function formatBBox(x,y,width,height) { | |
var bboxText=format("x",x)+format("y",y)+format("w",width)+format("h",height) | |
return bboxText; | |
} | |
/** | |
* show the given bounding box values as a pre in the given container | |
*/ | |
function showBox(container,x,y,width,height) { | |
pre=document.createElement("pre") | |
pre.innerHTML=formatBBox(x,y,width,height) | |
container.appendChild(pre) | |
} | |
/** | |
* show a sample of drafts | |
* @param {startScale} - scale to startWith | |
* @param {symbolScale} - the scale of the symbol in percent | |
* @param {utf8} - use UTF-8 symbol | |
* @param {mollWeide} - use MollWeide projection | |
* @param {debug} - show debug information | |
* @param {doShowSource} - show the Sources | |
*/ | |
function sample(startScale,symbolScale,utf8,mollWeide,debug,doShowSource) { | |
var pi=3.1415926 | |
var container=document.getElementById('container'); | |
var source=document.getElementById('source'); | |
// clear the two areas | |
container.innerHTML="" | |
source.innerHTML="" | |
var debug2=false; | |
// loop over the rows and columns | |
for (var row = 0; row <settings.rows; row++) { | |
for (var col = 0; col < settings.cols; col++) { | |
// calculate a unique id for the logo | |
var id=getId(row,col); | |
// base calculation parameters | |
var cx=480; | |
var cy=252; | |
// scale | |
var dScale=row*25; | |
var scale=startScale+dScale; | |
var height=scale; | |
var width=scale*pi/2; | |
var rscale=scale-50; | |
// create an svg element with the calculated id | |
vx=cx-scale*(pi); | |
vy=cy-scale*(pi/2); | |
vw=314+rscale*2*pi; | |
vh=157+rscale*pi; | |
if (debug2) { | |
showBox(container,vx,vy,vw,vh) | |
} | |
var svg=createSvg(id,vx,vy,vw,vh,width,height,scale); | |
container.appendChild(svg); | |
var lonsteps=settings.lonsteps+col*2; | |
var latsteps=settings.latsteps; | |
var title='IFMMS Logo'; | |
title=title+' scale '+scale+' steps '+lonsteps+'/'+latsteps; | |
// create a logo into the svg element with the given id | |
bbox=createLogo(title,id,cx,cy,scale,symbolScale,lonsteps,latsteps,utf8,mollWeide,debug); | |
if (debug2) { | |
showBox(container,bbox.x,bbox.y,bbox.width,bbox.height) | |
} | |
if (doShowSource) { | |
sourcesTitle.innerHTML="Sources" | |
showSource(id,'source',title) | |
} else { | |
sourcesTitle.innerHTML="" | |
} | |
} | |
container.appendChild(document.createElement('br')); | |
} | |
} | |
changeSettings(settings) | |
//sample(1,5,true) | |
</script> | |
</body> | |
</html> |
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
console.log('Hello World!'); |
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
/* todo: add styles */ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment