Commit 298d92b8 authored by gijs's avatar gijs

Included looptitles and description in the timeline

parent c78e725b
......@@ -78,4 +78,4 @@ ehthumbs.db
Thumbs.db
contour/static/contour/images/timeline.*
contour/static/contour/images/*.*.*
\ No newline at end of file
contour/static/contour/js/map.*
......@@ -155,7 +155,7 @@ class LoopAdmin(admin.ModelAdmin):
list_display = ('name_nl', 'name_en', 'published')
fieldsets = (
(None, {
'fields': ('published', ('start', 'end'), 'page')
'fields': ('published', ('start', 'end'), ('name_nl', 'name_en'), ('timeline_label_nl', 'timeline_label_en'),'page')
}),
# ('Dutch', {
# 'fields': ('name_nl', 'description_nl')
......
......@@ -11,6 +11,8 @@ import time
import re
import json
from xml.dom import minidom
from django.core.management.base import BaseCommand, CommandError
from django.core.management import call_command
......@@ -36,15 +38,25 @@ timeline = {
'loops': []
}
loopsize = '60mm'
loopsize = 60
def timestampedcopy (path, stamp = None):
if not stamp:
stamp = time.time()
base, ext = os.path.splitext(path)
stampedpath = '{}.{}{}'.format(base, stamp, ext)
shutil.copyfile(path, stampedpath)
return stampedpath
def getloopsize (days):
if len(days) == 1:
return '40mm'
return 40
elif len(days) == 2:
return '60mm'
return 60
else:
return '80mm'
return 80
def daterange(start_date, end_date):
for n in range(int((end_date - start_date).days)):
......@@ -181,11 +193,10 @@ def parralelTrack(loop, daystart, dayend, baseoffset):
return "draw {} dashed evenly scaled 2;".format(' .. '.join("offset(main, {1}mm, {0})".format(t, getLineOffset(baseoffset, i, len(coords))) for i, t in enumerate(coords)))
def generateMP(timeline):
def generateBaseMP(timeline):
mp = """boolean debug;
pad := 0.025;
pad := 0.015;
debug := false;
def offset (expr p, d, t) =
......@@ -226,6 +237,82 @@ beginfig(1);
timelinelength = int((timeline['end'] - timeline['start']).days)
l = 1
for loop in timeline['loops']:
mp += "\n\n\n% ********************* Loop {}\n".format(l)
lt = float((loop['start'] - timeline['start']).days) / float(timelinelength)
# Construct a loop for the loop
mp += "l[0][{0}]t = {1};\n".format(l, lt)
mp += "l[0][{0}]p = loop({1}mm);\n".format(l, getloopsize(loop['days']) + 5)
mp += ""
mp += ""
l += 1
# Insert loops into the main line
mp += "main = insert((0,0) -- (800mm,0mm), l[0], {});\n".format(', '.join([str(l) for l in range(1,l)]))
mp += "pickup pencircle scaled 2;"
mp += """draw main;
% Drawing debug information
if debug:
for s=0 step 1 until length main:
dotlabel.bot(decimal s, point s of main) withcolor red;
endfor
fi
endfig;
end;"""
return mp
def generateMP(timeline):
mp = """boolean debug;
pad := 0.025;
debug := false;
def offset (expr p, d, t) =
(0, d) rotated (angle direction t of p + 180) shifted point t of p
enddef;
def insert (expr bp)(suffix s)(text loops)=
forsuffixes $=loops:
if $=1:
subpath(0, s[$]t * length bp - pad) of bp
fi ..
if length s[$]p = 4:
{direction s[$]t * length bp of bp rotated 180}(point 2 of s[$]p)
else:
subpath(2, length s[$]p-2) of s[$]p
fi rotated angle direction s[$]t * length bp of bp shifted point s[$]t * length bp of bp ..
subpath(s[$]t * length bp + pad, (if known s[$+1]t: s[$+1]t * length bp - pad else: length bp fi)) of bp
endfor
enddef;
def loop(expr height) =
(-.2height,0) .. (0,0) .. {-1,0}(0, height) .. (0,0) .. (.2height,0) enddef;
%%
%% The idea is to draw loops and toinsert them into other shapes at a 'time'.
%% This time lies between 0 and 1
%%
%% The easiest way to modify the drawing is by changing the main shape at te bottom
%% of the file
%%
beginfig(1);
path l[][]p, main, b[][]p, mainbase;
numeric l[][]t, b[][]t;
"""
timelinelength = int((timeline['end'] - timeline['start']).days)
l = 1
for loop in timeline['loops']:
mp += "\n\n\n% ********************* Loop {}\n".format(l)
......@@ -261,7 +348,7 @@ beginfig(1);
# Construct a loop for the loop and fill with the days
mp += "l[0][{0}]t = {1};\n".format(l, lt)
mp += "l[0][{0}]p = insert(loop({2}), l[{0}], {1});\n".format(l, ', '.join([str(i) for i in range(1, days+1)]), getloopsize(loop['days']))
mp += "l[0][{0}]p = insert(loop({2}mm), l[{0}], {1});\n".format(l, ', '.join([str(i) for i in range(1, days+1)]), getloopsize(loop['days']))
mp += ""
mp += ""
# else:
......@@ -272,10 +359,34 @@ beginfig(1);
mp += "main = insert((0,0) -- (800mm,0mm), l[0], {});\n".format(', '.join([str(l) for l in range(1,l)]))
mp += "pickup pencircle scaled 2;"
mp += "pickup pencircle scaled 2;\n"
mp += """draw main;
mp += "draw main;\n"
mp += "pad := 0.011;\n"
l = 1
for loop in timeline['loops']:
mp += "\n\n\n% ********************* Loop {}\n".format(l)
lt = float((loop['start'] - timeline['start']).days) / float(timelinelength)
# Construct a loop for the loop
mp += "b[0][{0}]t = {1};\n".format(l, lt)
mp += "b[0][{0}]p = loop({1}mm);\n".format(l, getloopsize(loop['days']) + 3)
mp += ""
mp += ""
l += 1
# Insert loops into the main line
mp += "mainbase = insert((0,0) -- (800mm,0mm), b[0], {});\n".format(', '.join([str(l) for l in range(1,l)]))
mp += "draw mainbase;\n"
mp += """
% Drawing debug information
if debug:
for s=0 step 1 until length main:
......@@ -311,12 +422,6 @@ def generateSVG(mp):
except subprocess.CalledProcessError as e:
return None
def treatSVG(svg):
svg = svg.replace('stroke-width: 2.000000', 'stroke-width: 3px')
svg = re.sub(r'style="([^"]+)"', 'style="\\1vector-effect: non-scaling-stroke;"', svg)
svg = svg.replace('</svg>','<path></path></svg>')
return svg
class Command(BaseCommand):
args = ''
help = 'Generate a timeline for contour'
......@@ -358,13 +463,55 @@ class Command(BaseCommand):
pp.pprint(timeline)
pp.pprint(eventMap)
mp = generateMP(timeline)
print(mp)
svg = treatSVG(generateSVG(mp))
svg = generateSVG(mp)
print(svg)
# basemp = generateBaseMP(timeline)
# basesvg = generateSVG(basemp)
# # extractPath(basesvg)
# basedom = minidom.parseString(basesvg)
# basepath = basedom.getElementsByTagName('path')[0]
# basepathData = basepath.getAttribute('d')
dom = minidom.parseString(svg)
# basepath = dom.createElement('path')
# basepath.setAttribute('id', 'base')
# basepath.setAttribute('d', basepathData)
# basepath.setAttribute('style', 'fill: none; stroke: none')
timelinepath, basepath = dom.getElementsByTagName('path')
timelinepath.setAttribute('id', 'timeline')
timelinepath.setAttribute('style', 'fill: none; stroke: #000000; stroke-width: 3px; vector-effects: non-scaling-stroke;')
basepath.setAttribute('id', 'base')
basepath.setAttribute('style', 'fill: none; stroke: none')
highlightpath = dom.createElement('path')
highlightpath.setAttribute('id', 'highlight')
dom.documentElement.appendChild(highlightpath)
defs = dom.createElement('defs')
style = dom.createElement('style')
style.setAttribute('type', 'text/css')
style.appendChild(dom.createTextNode('@import url("/static/contour/css/fonts.css"); text { font-family: "Syne"; font-weight: 600; font-size: 14px; }'))
defs.appendChild(style)
dom.documentElement.appendChild(defs)
width = dom.documentElement.getAttribute('width')
height = str(float(dom.documentElement.getAttribute('height')) + 15)
dom.documentElement.setAttribute('height', height)
dom.documentElement.setAttribute('viewBox', '{} {} {} {}'.format(0, -15, width, height))
# dom.
# dom.documentElement.appendChild(basepath)
svgpath = os.path.join(timelinefolder, 'timeline.svg')
with open(svgpath, 'w') as h:
h.write(svg)
h.write(dom.toxml())
h.close()
eventmap = { pk: eventCoordinates(*address) for pk, address in eventMap.items() }
......@@ -387,16 +534,10 @@ class Command(BaseCommand):
""".format(json.dumps(jsonmap)))
h.close()
# Debug snapshot, or keep perhaps?
svgpathtimestamped = os.path.join(timelinefolder, 'timeline.{}.svg'.format(timestamp))
shutil.copyfile(svgpath, svgpathtimestamped)
jsonpathtimestamped = os.path.join(timelinejsonfolder, 'map.{}.json'.format(timestamp))
shutil.copyfile(jsonpath, jsonpathtimestamped)
jspathtimestamped = os.path.join(timelinejsfolder, 'map.{}.js'.format(timestamp))
shutil.copyfile(jspath, jspathtimestamped)
timestampedcopy(svgpath, timestamp)
timestampedcopy(jsonpath, timestamp)
timestampedcopy(jspath, timestamp)
# print(generateSVG(mp))
if not DEBUG:
call_command('collectstatic', interactive=False)
\ No newline at end of file
# Generated by Django 2.1.1 on 2019-03-19 11:16
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('contour', '0046_auto_20190125_0901'),
]
operations = [
migrations.AddField(
model_name='loop',
name='timeline_label_en',
field=models.CharField(default='', max_length=255),
preserve_default=False,
),
migrations.AddField(
model_name='loop',
name='timeline_label_nl',
field=models.CharField(default='', max_length=255),
preserve_default=False,
),
]
......@@ -311,6 +311,8 @@ class Loop(models.Model):
name_nl = models.CharField(max_length=255)
name_en = models.CharField(max_length=255)
timeline_label_nl = models.CharField(max_length=255)
timeline_label_en = models.CharField(max_length=255)
start = models.DateField()
end = models.DateField()
published = models.BooleanField(default=False)
......@@ -322,7 +324,7 @@ class Loop(models.Model):
return '{}'.format(self.name)
def __getattr__ (self, attrname):
if attrname in ['name', 'description']:
if attrname in ['name', 'description', 'timeline_label']:
return getattr(self, attrname + '_' + get_language())
return super().__getattr__(attrname)
......
......@@ -163,31 +163,98 @@ main {
padding: 0 20px;
}
#timeline .full-moon {
text-align: left;
}
#timeline figure {
#timeline-content {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: -1;
/* overflow: hidden; */
top: 0;
transition: left .25s;
z-index: 0;
}
#timeline figure object {
#timeline-drawing {
position: absolute;
/* left: calc(-72vh + 200px);
height: 60vh; */
bottom: 15vh;
bottom: 9em;
height: 45vh;
max-height: 450px;
transition: left .25s;
/* max-width: 6000px */
}
#timeline-annotations {
position: absolute;
bottom: 0;
left: 0;
top: 0;
}
.loop-description {
position: absolute;
bottom: 0;
height: 8em;
width: calc(33vw - 40px);
max-width: 410px;
font-family: 'Latin Modern', serif;
overflow: hidden;
}
.loop-description:after {
content: "";
position: absolute;
bottom: 0;
left: 0;
right: 0;
height: 4em;
background: linear-gradient(to top, rgba(255,255,255,1) 0, rgba(255,255,255,1) 1.3em, rgba(255,255,255,0) 100%);
z-index: 1;
}
.loop-description .toggle {
position: absolute;
bottom: 0;
left: 0;
z-index: 2;
cursor: pointer;
}
.loop-description[data-expanded="true"] .toggle {
display: block;
padding-top: 1em;
background: none;
position: relative;
}
/*
.loop-description[data-expanded="true"] {
height: initial;
top: 0;
overflow-y: auto;
} */
.loop-description[data-expanded="true"]:after {
display: none;
}
.loop-description[data-expanded="true"] {
height: initial;
top: initial;
max-height: 100%;
padding-top: 4em;
background: linear-gradient(to bottom, rgba(255,255,255,0) 0, rgba(255,255,255,.9) 3em);
margin-left: -21px;
padding-left: 21px;
padding-right: 21px;
}
.loop-description .toggle .collapse-label,
.loop-description[data-expanded="true"] .toggle .expand-label {
display: none
}
.loop-description[data-expanded="true"] .toggle .collapse-label,
.loop-description.toggle .expand-label {
display: initial;
}
.full-moon::before {
content: url("/static/contour/images/arrow-bottom-smaller.png");
margin-right: 10px;
......@@ -232,6 +299,8 @@ main {
margin-right: 5px;
}
/**
* Timeline
*/
......@@ -357,9 +426,6 @@ main {
font-family: 'Lack';
}
.contributor {
}
.event .contributor:after {
content: ",";
}
......@@ -397,30 +463,12 @@ main {
/**
* Continuous content
*/
.loop-head {
/* .loop-head {
display: none;
position: absolute;
right: 100%;
width: 300px;
}
.loop-head .loop-description {
font-family: 'Latin Modern', serif;
max-height: 8em;
overflow: hidden;
position: relative;
}
.loop-head .loop-description:after {
content: "";
position: absolute;
bottom: 0;
left: 0;
right: 0;
height: 3em;
background: linear-gradient(to bottom, rgba(255,255,255,0), rgba(255,255,255,1));
z-index: 1;
}
} */
main {
white-space: nowrap;
......
<?xml version="1.0"?>
<!-- Created by MetaPost 2.000 on 2018.10.25:1348 -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="1702.784302" height="172.078430" viewBox="0 0 1702.784302 172.078430">
<!-- Original BoundingBox: -1.000000 -1.000000 1701.784302 171.078430 -->
<path d="M1.000000 171.000000L157.334305 171.000000C257.812958 171.000000,257.312607 62.115295,204.274384 57.792679C163.562103 54.474625,161.933777 114.307190,199.843521 114.307190C237.753265 114.307190,236.124939 54.474625,195.412659 57.792679C142.374435 62.115295,141.874084 171.000000,242.352737 171.000000L395.920868 171.000000C446.354523 171.000000,498.194870 152.411346,510.723923 106.117798C516.578629 84.485275,501.573715 62.916794,479.067734 58.398483C464.256958 55.425064,461.561874 75.972061,473.736847 77.613861C485.916351 79.256302,488.758652 58.731674,473.697006 57.673630C457.528351 56.537827,441.311127 64.749191,436.372894 82.030457C432.156647 96.785126,452.708176 100.935074,455.115036 88.877686C457.521881 76.820404,436.951981 72.761826,435.180359 88.004684C433.105408 105.857330,444.927063 119.665588,460.292511 124.824539C474.606079 129.630310,479.861725 109.587433,467.985092 106.427841C456.112869 103.269424,450.712677 123.276413,465.529953 126.217270C488.031693 130.683289,510.156128 116.545578,513.079300 94.336258C519.068954 48.828735,490.406097 0.921570,438.419418 0.921570C368.348724 0.921570,340.650955 87.955597,383.066467 138.838120C409.110275 170.080795,451.829391 132.868744,429.563568 105.825363C420.179916 94.428268,404.911942 108.781097,413.841812 117.987900C422.771683 127.194702,437.583969 112.372055,426.478699 102.644821C400.179214 79.608810,361.647934 121.162994,392.156525 148.199753C415.846146 169.193527,449.238129 171.000000,480.928635 171.000000L781.354950 171.000000C831.789948 171.000000,883.632294 152.412399,896.161667 106.117798C907.121323 65.623108,849.053726 53.532608,841.942673 89.155136C834.836426 124.753632,893.045212 135.909470,898.517044 94.336258C904.506699 48.828735,875.843842 0.921570,823.857162 0.921570C817.077728 0.921570,810.694946 1.736282,804.733932 3.254135C764.034103 13.617523,782.622803 70.690842,817.535782 58.549683C852.526962 46.381317,831.651123 -9.894989,793.381683 7.194305C746.676941 28.050400,732.928299 96.160477,768.504181 138.838074C795.566971 171.303162,838.819534 130.253799,813.522873 104.173004C788.277603 78.145203,745.895813 120.108566,777.594269 148.199753C801.283905 169.193527,834.675903 171.000000,866.366425 171.000000L1252.423386 171.000000C1302.862320 171.000000,1354.710526 152.415482,1367.240723 106.117798C1378.200378 65.623108,1320.132782 53.532608,1313.021729 89.155136C1305.915482 124.753632,1364.124268 135.909470,1369.596100 94.336258C1375.585754 48.828735,1346.922897 0.921570,1294.936218 0.921570C1288.156784 0.921570,1281.774002 1.736282,1275.812988 3.254135C1235.113159 13.617523,1253.701859 70.690842,1288.614838 58.549683C1323.606018 46.381317,1302.730179 -9.894989,1264.460739 7.194305C1217.755997 28.050400,1204.007355 96.160477,1239.583237 138.838074C1266.646027 171.303162,1309.898590 130.253799,1284.601929 104.173004C1259.356659 78.145203,1216.974869 120.108566,1248.673325 148.199753C1272.362961 169.193512,1305.754929 171.000000,1337.445435 171.000000L1701.784302 171.000000" style="stroke:rgb(0.000000%,0.000000%,0.000000%); stroke-width: 3px;stroke-linecap: round;stroke-linejoin: round;stroke-miterlimit: 10.000000;fill: none;vector-effect: non-scaling-stroke;"></path>
<path></path></svg>
<?xml version="1.0" ?><!-- Created by MetaPost 2.000 on 2019.03.18:1817 --><svg height="252.275162" version="1.1" viewBox="0 -15 2269.712402 252.275162" width="2269.712402" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Original BoundingBox: -1.000000 -1.000000 2268.712402 236.275162 -->
<path d="M1.000000 236.000000L209.445724 236.000000C317.710144 236.000000,321.944031 126.980850,270.555557 122.792679C229.843277 119.474625,228.214951 179.307190,266.124695 179.307190C304.034439 179.307190,302.406113 119.474625,261.693832 122.792679C210.305359 126.980850,214.539246 236.000000,322.803665 236.000000L527.561172 236.000000C594.806046 236.000000,663.926483 211.215134,680.631927 149.490402C687.333344 124.729416,665.489944 101.765762,640.908417 107.648972C626.595001 111.074661,632.641281 130.954117,644.759903 127.157776C656.906555 123.352646,650.496292 103.560944,636.801041 108.936600C628.588516 112.160156,621.968750 118.934128,619.922394 129.185562C617.876038 139.436996,621.387680 148.233368,627.733139 154.362961C638.314896 164.584717,651.832611 148.770981,642.077805 140.593933C632.345505 132.435776,619.130188 148.470291,631.031372 157.128860C651.457764 171.989838,680.427063 159.198425,683.772400 133.781693C691.758621 73.104996,653.541473 9.228760,584.225891 9.228760C575.186646 9.228760,566.676270 10.315033,558.728241 12.338837C533.869537 18.668594,525.013382 49.361786,542.714600 67.740738C552.924286 78.341324,566.993881 63.050858,557.577469 54.529984C548.139282 45.989395,534.329865 61.549103,545.906906 70.628250C552.849197 76.072662,562.044250 78.344147,571.917953 74.910522C581.791656 71.476898,587.593277 63.990265,589.659500 55.413101C593.105164 41.109741,572.621063 37.475754,570.518570 50.029648C568.420944 62.554581,588.942047 65.815994,590.371368 51.167892C592.849701 25.769196,566.940460 7.166077,543.591934 17.592407C481.318924 45.400528,462.987411 136.213959,510.421921 193.117432C538.448929 226.739258,581.226242 185.153458,556.881775 160.054382C532.604858 135.024963,489.694733 176.490356,522.542038 205.599670C554.128204 233.591370,598.650848 236.000000,640.904861 236.000000L1041.473297 236.000000C1108.719971 236.000000,1177.843094 211.216537,1194.548935 149.490402C1205.874725 107.642929,1147.649582 96.204437,1140.788895 130.572800C1133.931808 164.923126,1192.035599 176.737473,1197.689407 133.781693C1205.675629 73.104996,1167.458481 9.228760,1098.142899 9.228760C1089.103653 9.228760,1080.593277 10.315033,1072.645248 12.338837C1030.568176 23.052902,1049.832855 79.927521,1083.507278 68.217087C1117.282227 56.471680,1097.049973 -0.064713,1057.508942 17.592407C995.235931 45.400528,976.904419 136.213959,1024.338928 193.117432C1052.365936 226.739258,1095.143250 185.153458,1070.798782 160.054382C1046.521866 135.024963,1003.611740 176.490356,1036.459045 205.599670C1068.045212 233.591370,1112.567856 236.000000,1154.821869 236.000000L1669.564529 236.000000C1736.816452 236.000000,1805.947388 211.220642,1822.654343 149.490402C1833.980133 107.642929,1775.754990 96.204437,1768.894302 130.572800C1762.037216 164.923126,1820.141006 176.737473,1825.794815 133.781693C1833.781036 73.104996,1795.563889 9.228760,1726.248306 9.228760C1717.209061 9.228760,1708.698685 10.315033,1700.750656 12.338837C1658.673584 23.052902,1677.938263 79.927521,1711.612686 68.217087C1745.387634 56.471680,1725.155380 -0.064713,1685.614349 17.592407C1623.341339 45.400528,1605.009827 136.213959,1652.444336 193.117432C1680.471344 226.739258,1723.248657 185.153458,1698.904190 160.054382C1674.627274 135.024963,1631.717148 176.490356,1664.564453 205.599670C1696.150620 233.591370,1740.673264 236.000000,1782.927277 236.000000L2268.712402 236.000000" id="timeline" style="fill: none; stroke: #000000; stroke-width: 3px; vector-effects: non-scaling-stroke;"/>
<path d="M1.000000 236.000000L241.176285 236.000000C339.316971 236.000000,332.362579 114.110458,266.124695 114.110458C199.886810 114.110458,192.932419 236.000000,291.073120 236.000000L559.280792 236.000000C733.123886 236.000015,725.018692 0.724854,584.225891 0.724838C443.435120 0.724838,435.328964 236.000000,609.174332 236.000000L1073.184570 236.000000C1247.036697 236.000015,1238.927658 0.724854,1098.142899 0.724838C957.352127 0.724838,949.245972 236.000000,1123.091339 236.000000L1701.303436 236.000000C1875.146362 236.000000,1867.041229 0.724838,1726.248306 0.724838C1585.457535 0.724838,1577.351379 236.000000,1751.196747 236.000000L2268.712402 236.000000" id="base" style="fill: none; stroke: none"/>
<path id="highlight"/><defs><style type="text/css">@import url(&quot;/static/contour/css/fonts.css&quot;); text { font-family: &quot;Syne&quot;; font-weight: 600; font-size: 14px; }</style></defs></svg>
\ No newline at end of file
......@@ -17,6 +17,28 @@
return subset.concat(segments.slice(start, end+1));
}
function reversePath (segments) {
var reversed = [],
rest = [],
command = 'M';
for (var i = segments.length-1; i >= 0; i--) {
coords = getSegmentCoords(segments[i]);
reversed.push([command].concat(rest, coords));
if (segments[i][0] === 'C') {
rest = [segments[i][3], segments[i][4], segments[i][1], segments[i][2]];
}
else {
rest = [];
}
command = segments[i][0];
}
return reversed;
}
function makeCoordinateString(x, y) {
return x + ' ' + y;
}
......@@ -54,6 +76,10 @@
window.contour.timeline.highlightpath.setAttribute('d', '');
}
function loopCount () {
return window.contour.timeline.map.loop.length;
}
function getLoopCenter(loop) {
var segments = window.contour.timeline.segmentsAbsolute,
coordinates = window.contour.timeline.map.loop[loop],
......@@ -73,34 +99,29 @@
function updateTimeline() {
window.contour.timeline.paths[0].setAttribute('d', makePathString(window.contour.timeline.segments));
alignAnnotations();
}
function getTimelineDimensions() {
var svg = window.contour.timeline.svg;
var svg = window.contour.timeline.svgElement;
return [parseFloat(svg.getAttribute('width')), parseFloat(svg.getAttribute('height'))];
}
function setTimelineDimensions(width, height) {
var svg = window.contour.timeline.svg;
svg.setAttribute('viewBox', '0 0 ' + width + ' ' + height);
svg.setAttribute('width', width);
svg.setAttribute('height', height);
var svgElement = window.contour.timeline.svgElement;
svgElement.setAttribute('viewBox', '0 -15 ' + width + ' ' + height);
svgElement.setAttribute('width', width);
svgElement.setAttribute('height', height);
}
function toPixels (l) {
return l * window.contour.timeline.scale;
return l * window.contour.timeline.svg.getBoundingClientRect().width / parseFloat(window.contour.timeline.svgElement.getAttribute('width'));;
}
function updateScale () {
var svg = window.contour.timeline.svg;
window.contour.timeline.scale = svg.getBoundingClientRect().height / parseFloat(svg.getAttribute('height'));
}
var makeLoopCoordinates = function () {
var segments = window.contour.timeline.segmentsAbsolute,
loops = [],
function getLoopCoordinates(segments) {
var loops = [],
start = -1;
for (var i=0; i < segments.length; i++) {
if (segments[i][0] == 'L') {
if (start > -1) {
......@@ -112,27 +133,100 @@
}
}
window.contour.timeline.map.loop = loops;
return loops;
}
function makeTextPaths() {
var basepath = window.contour.timeline.svgDocument.getElementById('base'),
segments = Raphael.parsePathString(basepath.getAttribute('d')),
loopCoordinates = getLoopCoordinates(segments),
textAnchors = window.contour.timeline.textAnchors = [];
for (var i = 0; i < loopCoordinates.length;i++) {
var anchorPath = window.contour.timeline.svgDocument.createElementNS('http://www.w3.org/2000/svg', 'path'),
anchorPathSegments = Raphael.pathToRelative(reversePath(getSubpathFromSegments(segments, loopCoordinates[i][0]+1, loopCoordinates[i][1]))),
textElement = window.contour.timeline.svgDocument.createElementNS('http://www.w3.org/2000/svg', 'text'),
textPathElement = window.contour.timeline.svgDocument.createElementNS('http://www.w3.org/2000/svg', 'textPath'),
textNode = window.contour.timeline.svgDocument.createTextNode('');
anchorPath.setAttribute('id', 'loop-' + i.toString());
anchorPath.setAttribute('style', 'fill: none; stroke: none;');
anchorPath.setAttribute('d', makePathString(anchorPathSegments));
window.contour.timeline.svgElement.appendChild(anchorPath);
textPathElement.setAttribute('href', '#loop-' + i.toString());
textPathElement.setAttribute('text-anchor', 'middle');
textPathElement.setAttribute('startOffset', '40%');
textPathElement.appendChild(textNode);