wallside poast
This commit is contained in:
parent
8e64a09f01
commit
61d04f2321
5 changed files with 519 additions and 0 deletions
109
content/posts/WALL-side/index.md
Normal file
109
content/posts/WALL-side/index.md
Normal file
|
|
@ -0,0 +1,109 @@
|
||||||
|
+++
|
||||||
|
date = "2022-05-29"
|
||||||
|
draft = false
|
||||||
|
path = "/blog/WALL-side"
|
||||||
|
tags = ["art"]
|
||||||
|
title = "WALL side"
|
||||||
|
+++
|
||||||
|
|
||||||
|
{% image(name="wallside.png", colocated=true) %}
|
||||||
|
poster with diagonal WALL side text in four different
|
||||||
|
languages
|
||||||
|
{% end %}
|
||||||
|
|
||||||
|
My partner has a brilliant poster they made of the backing of 3M command strips
|
||||||
|
in their apartment, which I wanted to recreate as a vector image to make
|
||||||
|
another. I initially tried inkscape, where I ran into issues with the tiled
|
||||||
|
clone tool not supporting dragging to set spacing and more crucially not
|
||||||
|
supporting absolute distances, which meant that it could not maintain proper
|
||||||
|
spacing of things of different height (I later realized it could probably be
|
||||||
|
done with a group, but there were unrelated factors of fiddliness at play such
|
||||||
|
as difficulty working in a transformed coordinate system that made Inkscape
|
||||||
|
infeasible to use).
|
||||||
|
|
||||||
|
I conceded and did this project as a simple Python SVG generator. First, I took
|
||||||
|
a picture as reference, then included it in the SVG as an `<image>`. SVG is fun
|
||||||
|
because it is *not* HTML, and is also strict XML. For instance, one difference
|
||||||
|
is that the image tag is called `image` rather than `img` and uses an `href`,
|
||||||
|
not a `src` (or indeed, `xlink:href` if you are using an older implementation
|
||||||
|
such as inkscape).
|
||||||
|
|
||||||
|
With that out of the way, I made a `<g>` group that's rotated 45 degrees and
|
||||||
|
translated some amount (`transform="rotate(-45) translate(-1000, 100)"`), then
|
||||||
|
I created the four languages of `<text>` text elements inside. Regarding how to
|
||||||
|
get the actual text to put in there, there are various ways to do this; I typed
|
||||||
|
it in on my phone (including the Japanese! there's a drawing keyboard for
|
||||||
|
Japanese in Google Keyboard, so even my dubious-quality non-Japanese-speaker
|
||||||
|
scrawls got turned into characters pretty easily).
|
||||||
|
|
||||||
|
To get each text fragment into position easily,
|
||||||
|
I nicked [some code to make them draggable][draggable],
|
||||||
|
then noted down the transformation after dragging them into position. Next, I
|
||||||
|
duplicated each language's element and moved the new one into the next
|
||||||
|
horizontal position to figure out the horizontal (along the line) period and
|
||||||
|
the next vertical position to figure out the cross-line period.
|
||||||
|
|
||||||
|
Then, I made these definitions reusable by giving them an `id` property and
|
||||||
|
putting them in a `<defs>` block. This makes the original definition invisible,
|
||||||
|
so you have to reference them as something like `<use xlink:href="#someId" />`.
|
||||||
|
|
||||||
|
Since I knew the spacings, I got Python out in earnest. To make my workflow
|
||||||
|
more pleasant, I wanted to rebuild the image on every editor save. I found a
|
||||||
|
tool [`entr`][entr] that can do this: `ls *.py | entr -r python wallside.py`.
|
||||||
|
It takes a list of files to watch on standard input, and a command to run when
|
||||||
|
any of them change.
|
||||||
|
|
||||||
|
With my setup sufficiently pleasant, I wrote some Python to generate a series
|
||||||
|
of instances of the definition with the horizontal spacing for every language,
|
||||||
|
with each looking like this:
|
||||||
|
`<use x="{idx * SPACING[language]}" xlink:href="#{language}" />`.
|
||||||
|
This forms one line of several copies of each of English, French, Spanish, and
|
||||||
|
Japanese. I put this into a `<defs>` block as a group, then referenced it in
|
||||||
|
the body of the document with a `<use>` to check my work.
|
||||||
|
|
||||||
|
After I was satisfied this worked, I then started generating that `<use>`
|
||||||
|
automatically, with the `y` offset set to some multiple of the line spacing,
|
||||||
|
and with some tweaks, that was that.
|
||||||
|
|
||||||
|
Next was the job of getting it to work on Inkscape since I was prototyping
|
||||||
|
against Firefox, which, being a web browser, has a very advanced SVG renderer
|
||||||
|
compared to non-browser programs. One thing I was doing that was not ideal for
|
||||||
|
Inkscape was that I was rendering a bunch of text off-page. I fixed this with a
|
||||||
|
clip path the size of the document like so:
|
||||||
|
|
||||||
|
```xml
|
||||||
|
<clipPath id="viewRect">
|
||||||
|
<rect height="100%" width="100%" />
|
||||||
|
</clipPath>
|
||||||
|
<!-- ... -->
|
||||||
|
<g clip-path="url(#viewRect)">
|
||||||
|
<g transform="..."><!-- all the text goes in here --></g>
|
||||||
|
</g>
|
||||||
|
```
|
||||||
|
|
||||||
|
Another thing that Inkscape disliked (to the point of not rendering anything)
|
||||||
|
was the use of `href="..."` in my document. Its predecessor, `xlink:href`, was
|
||||||
|
[noted on MDN][mdn xlink] as being deprecated, replaced in the SVG 2 standard
|
||||||
|
by unprefixed `href`. I just had to switch to the older one and add
|
||||||
|
`xmlns:xlink="http://www.w3.org/1999/xlink"` to my `<svg>` element to fix this.
|
||||||
|
|
||||||
|
The last bit of trouble I got from Inkscape was that it does not support the
|
||||||
|
CSS `transform` property, so I had to convert to the `transform="..."` property
|
||||||
|
directly on tags. Oh well, so much for the shiny features. But it works now and
|
||||||
|
is more portable!
|
||||||
|
|
||||||
|
Finally, I have a SVG file that is exactly what I want and was not that painful
|
||||||
|
to create. That was fun!
|
||||||
|
|
||||||
|
I've included the sources and SVG file below (note: it requires Source Han Sans
|
||||||
|
installed on your computer, which is a nice open source sans-serif font with
|
||||||
|
Chinese/Japanese/Korean support).
|
||||||
|
|
||||||
|
* [SVG file here](./wallside.svg)
|
||||||
|
* [PDF for printing here (11x17 inch tabloid size)](./wallside.svg.pdf)
|
||||||
|
|
||||||
|
{{ codefile(path="wallside.py", colocated=true, code_lang="python", hide=true) }}
|
||||||
|
|
||||||
|
[draggable]: https://github.com/petercollingridge/code-for-blog/blob/master/svg-interaction/draggable/draggable_groups.svg
|
||||||
|
[mdn xlink]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/xlink:href
|
||||||
|
[entr]: https://github.com/eradman/entr
|
||||||
BIN
content/posts/WALL-side/wallside.png
Normal file
BIN
content/posts/WALL-side/wallside.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 881 KiB |
174
content/posts/WALL-side/wallside.py
Normal file
174
content/posts/WALL-side/wallside.py
Normal file
|
|
@ -0,0 +1,174 @@
|
||||||
|
import contextlib
|
||||||
|
|
||||||
|
|
||||||
|
class Periods:
|
||||||
|
y = 106
|
||||||
|
x = {
|
||||||
|
'en': 106,
|
||||||
|
'fr': 106,
|
||||||
|
'es': 146,
|
||||||
|
'jp': 82,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DEFS = """
|
||||||
|
"""
|
||||||
|
|
||||||
|
HEADER = """
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" height="17in" width="11in" onload="makeDraggable(evt)">
|
||||||
|
<style>
|
||||||
|
.text {
|
||||||
|
font-family: "Source Han Sans";
|
||||||
|
font-size: 14pt;
|
||||||
|
font-weight: bolder;
|
||||||
|
letter-spacing: -1.5px;
|
||||||
|
}
|
||||||
|
.text.japanese {
|
||||||
|
font-size: 16pt;
|
||||||
|
letter-spacing: -0.8px;
|
||||||
|
}
|
||||||
|
.wallside {
|
||||||
|
transform: rotate(-45deg)translate(-13in, 1.2in);
|
||||||
|
}
|
||||||
|
.draggable, .draggable-group {
|
||||||
|
cursor: move;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<!--<image href="./wallsideref.jpg" x="0" y="0" transform="scale(0.4, 0.4)" /> -->
|
||||||
|
<clipPath id="viewRect">
|
||||||
|
<rect height="17in" width="11in" />
|
||||||
|
</clipPath>
|
||||||
|
<rect height="17in" width="11in" stroke="black" fill="none" />
|
||||||
|
"""
|
||||||
|
|
||||||
|
FOOTER = """
|
||||||
|
<script type="text/javascript"><![CDATA[
|
||||||
|
function makeDraggable(evt) {
|
||||||
|
var svg = evt.target;
|
||||||
|
|
||||||
|
svg.addEventListener('mousedown', startDrag);
|
||||||
|
svg.addEventListener('mousemove', drag);
|
||||||
|
svg.addEventListener('mouseup', endDrag);
|
||||||
|
svg.addEventListener('mouseleave', endDrag);
|
||||||
|
svg.addEventListener('touchstart', startDrag);
|
||||||
|
svg.addEventListener('touchmove', drag);
|
||||||
|
svg.addEventListener('touchend', endDrag);
|
||||||
|
svg.addEventListener('touchleave', endDrag);
|
||||||
|
svg.addEventListener('touchcancel', endDrag);
|
||||||
|
|
||||||
|
function getMousePosition(evt) {
|
||||||
|
var CTM = svg.getScreenCTM();
|
||||||
|
if (evt.touches) { evt = evt.touches[0]; }
|
||||||
|
return {
|
||||||
|
x: (evt.clientX - CTM.e) / CTM.a,
|
||||||
|
y: (evt.clientY - CTM.f) / CTM.d
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
var selectedElement, offset, transform;
|
||||||
|
|
||||||
|
function initialiseDragging(evt) {
|
||||||
|
offset = getMousePosition(evt);
|
||||||
|
|
||||||
|
// Make sure the first transform on the element is a translate transform
|
||||||
|
var transforms = selectedElement.transform.baseVal;
|
||||||
|
|
||||||
|
if (transforms.length === 0 || transforms.getItem(0).type !== SVGTransform.SVG_TRANSFORM_TRANSLATE) {
|
||||||
|
// Create an transform that translates by (0, 0)
|
||||||
|
var translate = svg.createSVGTransform();
|
||||||
|
translate.setTranslate(0, 0);
|
||||||
|
selectedElement.transform.baseVal.insertItemBefore(translate, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get initial translation
|
||||||
|
transform = transforms.getItem(0);
|
||||||
|
offset.x -= transform.matrix.e;
|
||||||
|
offset.y -= transform.matrix.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
function startDrag(evt) {
|
||||||
|
if (evt.target.classList.contains('draggable')) {
|
||||||
|
selectedElement = evt.target;
|
||||||
|
initialiseDragging(evt);
|
||||||
|
} else if (evt.target.parentNode.classList.contains('draggable-group')) {
|
||||||
|
selectedElement = evt.target.parentNode;
|
||||||
|
initialiseDragging(evt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function drag(evt) {
|
||||||
|
if (selectedElement) {
|
||||||
|
evt.preventDefault();
|
||||||
|
var coord = getMousePosition(evt);
|
||||||
|
transform.setTranslate(coord.x - offset.x, coord.y - offset.y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function endDrag(evt) {
|
||||||
|
selectedElement = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
]]></script>
|
||||||
|
|
||||||
|
</svg>
|
||||||
|
"""
|
||||||
|
|
||||||
|
BODY = """
|
||||||
|
<defs>
|
||||||
|
<text id="en" x="0" y="0" transform="translate(0, -80)" class="text">WALL side</text>
|
||||||
|
<text id="fr" x="0" y="0" transform="translate(-25, -56)" class="text">Côté MUR</text>
|
||||||
|
<text id="es" x="0" y="0" transform="translate(-28, 0)" class="text">lado de la PARED</text>
|
||||||
|
<text id="jp" x="0" y="0" transform="translate(-20, -27)" class="text japanese">かベ面</text>
|
||||||
|
</defs>
|
||||||
|
|
||||||
|
<g class="wallside">
|
||||||
|
<!--
|
||||||
|
<use href="#en" />
|
||||||
|
<use href="#en" x="106" class="draggable" />
|
||||||
|
<use href="#en" y="106" class="draggable" />
|
||||||
|
<use href="#fr" />
|
||||||
|
<use href="#fr" x="106" class="draggable" />
|
||||||
|
<use href="#es" />
|
||||||
|
<use href="#es" x="146" class="draggable" />
|
||||||
|
<use href="#jp" />
|
||||||
|
<use href="#jp" x="82" class="draggable" />
|
||||||
|
-->
|
||||||
|
</g>
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
def make_line_def(id):
|
||||||
|
print(f'<defs><g id="{id}">')
|
||||||
|
for (lang, per) in Periods.x.items():
|
||||||
|
for i in range(30 if lang == 'jp' else 20):
|
||||||
|
print(f'<use x="{i * per}" xlink:href="#{lang}" />')
|
||||||
|
print('</g></defs>')
|
||||||
|
|
||||||
|
|
||||||
|
def make_wallside():
|
||||||
|
# 96px/in * {13in, 1.2in}
|
||||||
|
print('<g clip-path="url(#viewRect)"><g transform="rotate(-45) translate(-1248, 115)">')
|
||||||
|
for i in range(20):
|
||||||
|
print(f'<use xlink:href="#line-10" y="{Periods.y * i}" />')
|
||||||
|
print('</g></g>')
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
f = open('./wallside.svg', 'w')
|
||||||
|
with contextlib.redirect_stdout(f):
|
||||||
|
build()
|
||||||
|
print('built svg')
|
||||||
|
|
||||||
|
|
||||||
|
def build():
|
||||||
|
print(HEADER)
|
||||||
|
print(DEFS)
|
||||||
|
make_line_def('line-10')
|
||||||
|
make_wallside()
|
||||||
|
print(BODY)
|
||||||
|
print(FOOTER)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
236
content/posts/WALL-side/wallside.svg
Normal file
236
content/posts/WALL-side/wallside.svg
Normal file
|
|
@ -0,0 +1,236 @@
|
||||||
|
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" height="17in" width="11in" onload="makeDraggable(evt)">
|
||||||
|
<style>
|
||||||
|
.text {
|
||||||
|
font-family: "Source Han Sans";
|
||||||
|
font-size: 14pt;
|
||||||
|
font-weight: bolder;
|
||||||
|
letter-spacing: -1.5px;
|
||||||
|
}
|
||||||
|
.text.japanese {
|
||||||
|
font-size: 16pt;
|
||||||
|
letter-spacing: -0.8px;
|
||||||
|
}
|
||||||
|
.wallside {
|
||||||
|
transform: rotate(-45deg)translate(-13in, 1.2in);
|
||||||
|
}
|
||||||
|
.draggable, .draggable-group {
|
||||||
|
cursor: move;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<!--<image href="./wallsideref.jpg" x="0" y="0" transform="scale(0.4, 0.4)" /> -->
|
||||||
|
<clipPath id="viewRect">
|
||||||
|
<rect height="100%" width="100%" />
|
||||||
|
</clipPath>
|
||||||
|
<rect height="17in" width="11in" stroke="black" fill="none" />
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<defs><g id="line-10">
|
||||||
|
<use x="0" xlink:href="#en" />
|
||||||
|
<use x="106" xlink:href="#en" />
|
||||||
|
<use x="212" xlink:href="#en" />
|
||||||
|
<use x="318" xlink:href="#en" />
|
||||||
|
<use x="424" xlink:href="#en" />
|
||||||
|
<use x="530" xlink:href="#en" />
|
||||||
|
<use x="636" xlink:href="#en" />
|
||||||
|
<use x="742" xlink:href="#en" />
|
||||||
|
<use x="848" xlink:href="#en" />
|
||||||
|
<use x="954" xlink:href="#en" />
|
||||||
|
<use x="1060" xlink:href="#en" />
|
||||||
|
<use x="1166" xlink:href="#en" />
|
||||||
|
<use x="1272" xlink:href="#en" />
|
||||||
|
<use x="1378" xlink:href="#en" />
|
||||||
|
<use x="1484" xlink:href="#en" />
|
||||||
|
<use x="1590" xlink:href="#en" />
|
||||||
|
<use x="1696" xlink:href="#en" />
|
||||||
|
<use x="1802" xlink:href="#en" />
|
||||||
|
<use x="1908" xlink:href="#en" />
|
||||||
|
<use x="2014" xlink:href="#en" />
|
||||||
|
<use x="0" xlink:href="#fr" />
|
||||||
|
<use x="106" xlink:href="#fr" />
|
||||||
|
<use x="212" xlink:href="#fr" />
|
||||||
|
<use x="318" xlink:href="#fr" />
|
||||||
|
<use x="424" xlink:href="#fr" />
|
||||||
|
<use x="530" xlink:href="#fr" />
|
||||||
|
<use x="636" xlink:href="#fr" />
|
||||||
|
<use x="742" xlink:href="#fr" />
|
||||||
|
<use x="848" xlink:href="#fr" />
|
||||||
|
<use x="954" xlink:href="#fr" />
|
||||||
|
<use x="1060" xlink:href="#fr" />
|
||||||
|
<use x="1166" xlink:href="#fr" />
|
||||||
|
<use x="1272" xlink:href="#fr" />
|
||||||
|
<use x="1378" xlink:href="#fr" />
|
||||||
|
<use x="1484" xlink:href="#fr" />
|
||||||
|
<use x="1590" xlink:href="#fr" />
|
||||||
|
<use x="1696" xlink:href="#fr" />
|
||||||
|
<use x="1802" xlink:href="#fr" />
|
||||||
|
<use x="1908" xlink:href="#fr" />
|
||||||
|
<use x="2014" xlink:href="#fr" />
|
||||||
|
<use x="0" xlink:href="#es" />
|
||||||
|
<use x="146" xlink:href="#es" />
|
||||||
|
<use x="292" xlink:href="#es" />
|
||||||
|
<use x="438" xlink:href="#es" />
|
||||||
|
<use x="584" xlink:href="#es" />
|
||||||
|
<use x="730" xlink:href="#es" />
|
||||||
|
<use x="876" xlink:href="#es" />
|
||||||
|
<use x="1022" xlink:href="#es" />
|
||||||
|
<use x="1168" xlink:href="#es" />
|
||||||
|
<use x="1314" xlink:href="#es" />
|
||||||
|
<use x="1460" xlink:href="#es" />
|
||||||
|
<use x="1606" xlink:href="#es" />
|
||||||
|
<use x="1752" xlink:href="#es" />
|
||||||
|
<use x="1898" xlink:href="#es" />
|
||||||
|
<use x="2044" xlink:href="#es" />
|
||||||
|
<use x="2190" xlink:href="#es" />
|
||||||
|
<use x="2336" xlink:href="#es" />
|
||||||
|
<use x="2482" xlink:href="#es" />
|
||||||
|
<use x="2628" xlink:href="#es" />
|
||||||
|
<use x="2774" xlink:href="#es" />
|
||||||
|
<use x="0" xlink:href="#jp" />
|
||||||
|
<use x="82" xlink:href="#jp" />
|
||||||
|
<use x="164" xlink:href="#jp" />
|
||||||
|
<use x="246" xlink:href="#jp" />
|
||||||
|
<use x="328" xlink:href="#jp" />
|
||||||
|
<use x="410" xlink:href="#jp" />
|
||||||
|
<use x="492" xlink:href="#jp" />
|
||||||
|
<use x="574" xlink:href="#jp" />
|
||||||
|
<use x="656" xlink:href="#jp" />
|
||||||
|
<use x="738" xlink:href="#jp" />
|
||||||
|
<use x="820" xlink:href="#jp" />
|
||||||
|
<use x="902" xlink:href="#jp" />
|
||||||
|
<use x="984" xlink:href="#jp" />
|
||||||
|
<use x="1066" xlink:href="#jp" />
|
||||||
|
<use x="1148" xlink:href="#jp" />
|
||||||
|
<use x="1230" xlink:href="#jp" />
|
||||||
|
<use x="1312" xlink:href="#jp" />
|
||||||
|
<use x="1394" xlink:href="#jp" />
|
||||||
|
<use x="1476" xlink:href="#jp" />
|
||||||
|
<use x="1558" xlink:href="#jp" />
|
||||||
|
<use x="1640" xlink:href="#jp" />
|
||||||
|
<use x="1722" xlink:href="#jp" />
|
||||||
|
<use x="1804" xlink:href="#jp" />
|
||||||
|
<use x="1886" xlink:href="#jp" />
|
||||||
|
<use x="1968" xlink:href="#jp" />
|
||||||
|
<use x="2050" xlink:href="#jp" />
|
||||||
|
<use x="2132" xlink:href="#jp" />
|
||||||
|
<use x="2214" xlink:href="#jp" />
|
||||||
|
<use x="2296" xlink:href="#jp" />
|
||||||
|
<use x="2378" xlink:href="#jp" />
|
||||||
|
</g></defs>
|
||||||
|
<g clip-path="url(#viewRect)"><g transform="rotate(-45) translate(-1248, 115)">
|
||||||
|
<use xlink:href="#line-10" y="0" />
|
||||||
|
<use xlink:href="#line-10" y="106" />
|
||||||
|
<use xlink:href="#line-10" y="212" />
|
||||||
|
<use xlink:href="#line-10" y="318" />
|
||||||
|
<use xlink:href="#line-10" y="424" />
|
||||||
|
<use xlink:href="#line-10" y="530" />
|
||||||
|
<use xlink:href="#line-10" y="636" />
|
||||||
|
<use xlink:href="#line-10" y="742" />
|
||||||
|
<use xlink:href="#line-10" y="848" />
|
||||||
|
<use xlink:href="#line-10" y="954" />
|
||||||
|
<use xlink:href="#line-10" y="1060" />
|
||||||
|
<use xlink:href="#line-10" y="1166" />
|
||||||
|
<use xlink:href="#line-10" y="1272" />
|
||||||
|
<use xlink:href="#line-10" y="1378" />
|
||||||
|
<use xlink:href="#line-10" y="1484" />
|
||||||
|
<use xlink:href="#line-10" y="1590" />
|
||||||
|
<use xlink:href="#line-10" y="1696" />
|
||||||
|
<use xlink:href="#line-10" y="1802" />
|
||||||
|
<use xlink:href="#line-10" y="1908" />
|
||||||
|
<use xlink:href="#line-10" y="2014" />
|
||||||
|
</g></g>
|
||||||
|
|
||||||
|
<defs>
|
||||||
|
<text id="en" x="0" y="0" transform="translate(0, -80)" class="text">WALL side</text>
|
||||||
|
<text id="fr" x="0" y="0" transform="translate(-25, -56)" class="text">Côté MUR</text>
|
||||||
|
<text id="es" x="0" y="0" transform="translate(-28, 0)" class="text">lado de la PARED</text>
|
||||||
|
<text id="jp" x="0" y="0" transform="translate(-20, -27)" class="text japanese">かベ面</text>
|
||||||
|
</defs>
|
||||||
|
|
||||||
|
<g class="wallside">
|
||||||
|
<!--
|
||||||
|
<use href="#en" />
|
||||||
|
<use href="#en" x="106" class="draggable" />
|
||||||
|
<use href="#en" y="106" class="draggable" />
|
||||||
|
<use href="#fr" />
|
||||||
|
<use href="#fr" x="106" class="draggable" />
|
||||||
|
<use href="#es" />
|
||||||
|
<use href="#es" x="146" class="draggable" />
|
||||||
|
<use href="#jp" />
|
||||||
|
<use href="#jp" x="82" class="draggable" />
|
||||||
|
-->
|
||||||
|
</g>
|
||||||
|
|
||||||
|
|
||||||
|
<script type="text/javascript"><![CDATA[
|
||||||
|
function makeDraggable(evt) {
|
||||||
|
var svg = evt.target;
|
||||||
|
|
||||||
|
svg.addEventListener('mousedown', startDrag);
|
||||||
|
svg.addEventListener('mousemove', drag);
|
||||||
|
svg.addEventListener('mouseup', endDrag);
|
||||||
|
svg.addEventListener('mouseleave', endDrag);
|
||||||
|
svg.addEventListener('touchstart', startDrag);
|
||||||
|
svg.addEventListener('touchmove', drag);
|
||||||
|
svg.addEventListener('touchend', endDrag);
|
||||||
|
svg.addEventListener('touchleave', endDrag);
|
||||||
|
svg.addEventListener('touchcancel', endDrag);
|
||||||
|
|
||||||
|
function getMousePosition(evt) {
|
||||||
|
var CTM = svg.getScreenCTM();
|
||||||
|
if (evt.touches) { evt = evt.touches[0]; }
|
||||||
|
return {
|
||||||
|
x: (evt.clientX - CTM.e) / CTM.a,
|
||||||
|
y: (evt.clientY - CTM.f) / CTM.d
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
var selectedElement, offset, transform;
|
||||||
|
|
||||||
|
function initialiseDragging(evt) {
|
||||||
|
offset = getMousePosition(evt);
|
||||||
|
|
||||||
|
// Make sure the first transform on the element is a translate transform
|
||||||
|
var transforms = selectedElement.transform.baseVal;
|
||||||
|
|
||||||
|
if (transforms.length === 0 || transforms.getItem(0).type !== SVGTransform.SVG_TRANSFORM_TRANSLATE) {
|
||||||
|
// Create an transform that translates by (0, 0)
|
||||||
|
var translate = svg.createSVGTransform();
|
||||||
|
translate.setTranslate(0, 0);
|
||||||
|
selectedElement.transform.baseVal.insertItemBefore(translate, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get initial translation
|
||||||
|
transform = transforms.getItem(0);
|
||||||
|
offset.x -= transform.matrix.e;
|
||||||
|
offset.y -= transform.matrix.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
function startDrag(evt) {
|
||||||
|
if (evt.target.classList.contains('draggable')) {
|
||||||
|
selectedElement = evt.target;
|
||||||
|
initialiseDragging(evt);
|
||||||
|
} else if (evt.target.parentNode.classList.contains('draggable-group')) {
|
||||||
|
selectedElement = evt.target.parentNode;
|
||||||
|
initialiseDragging(evt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function drag(evt) {
|
||||||
|
if (selectedElement) {
|
||||||
|
evt.preventDefault();
|
||||||
|
var coord = getMousePosition(evt);
|
||||||
|
transform.setTranslate(coord.x - offset.x, coord.y - offset.y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function endDrag(evt) {
|
||||||
|
selectedElement = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
]]></script>
|
||||||
|
|
||||||
|
</svg>
|
||||||
|
|
||||||
|
After Width: | Height: | Size: 7.7 KiB |
BIN
content/posts/WALL-side/wallside.svg.pdf
Normal file
BIN
content/posts/WALL-side/wallside.svg.pdf
Normal file
Binary file not shown.
Loading…
Add table
Add a link
Reference in a new issue