Add subtractions and auto updating
This commit is contained in:
parent
74470e61b3
commit
ce7dfc28ea
5 changed files with 486 additions and 319 deletions
|
@ -4,6 +4,7 @@ import tornado.ioloop
|
|||
import os
|
||||
|
||||
web_dir = os.path.join(os.path.split(__file__)[0], 'www')
|
||||
output_dir = os.path.join(os.path.split(__file__)[0], 'output')
|
||||
|
||||
# This is our WebSocketHandler - it handles the messages
|
||||
# from the tornado server
|
||||
|
@ -27,6 +28,7 @@ class WebSocketHandler(tornado.websocket.WebSocketHandler):
|
|||
|
||||
application = tornado.web.Application([
|
||||
(r"/ws", WebSocketHandler),
|
||||
(r"/output/(.*)", tornado.web.StaticFileHandler, {"path": output_dir}),
|
||||
(r"/(.*)", tornado.web.StaticFileHandler, {"path": web_dir, "default_filename": 'index.html'}),
|
||||
],debug=True)
|
||||
|
||||
|
|
|
@ -13,6 +13,9 @@ from websocket import create_connection
|
|||
import logging
|
||||
import json
|
||||
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
logger = logging.getLogger('portraits')
|
||||
|
||||
camera = picamera.PiCamera()
|
||||
camera.rotation = 180
|
||||
camera.resolution = (1920, 1080)
|
||||
|
@ -24,6 +27,8 @@ outputResolution = (1000, 1000)
|
|||
genders = ['male', 'female', 'unknown']
|
||||
perspectives = ['side', 'front']
|
||||
gender_perspectives = [g+"_"+p for p in perspectives for g in genders]
|
||||
# we also want dedicated composites for the perspectives
|
||||
gender_perspectives.extend(perspectives)
|
||||
|
||||
curdir = os.path.dirname(os.path.abspath(__file__))
|
||||
tmpimage = '/tmp/piimage.jpg'
|
||||
|
@ -42,6 +47,8 @@ environment = {
|
|||
'LD_PRELOAD': '/usr/lib/arm-linux-gnueabihf/libopencv_core.so.2.4',
|
||||
}
|
||||
|
||||
updateGoesOk = True;
|
||||
|
||||
def updateStats(type, name, count, image_filename):
|
||||
params = {
|
||||
'type': type,
|
||||
|
@ -49,35 +56,41 @@ def updateStats(type, name, count, image_filename):
|
|||
'time': int(time.time()),
|
||||
'case_count': int(count),
|
||||
}
|
||||
try:
|
||||
ws = create_connection("ws://localhost:8888/ws")
|
||||
js = json.dumps({
|
||||
'type': type,
|
||||
'name': name,
|
||||
'img_src': os.path.basename(image_filename),
|
||||
'case_count': int(count),
|
||||
})
|
||||
ws.send(js)
|
||||
except Exception as e:
|
||||
raise
|
||||
# try:
|
||||
# ws = create_connection("ws://localhost:8888/ws")
|
||||
# js = json.dumps({
|
||||
# 'type': type,
|
||||
# 'name': name,
|
||||
# 'img_src': os.path.basename(image_filename),
|
||||
# 'case_count': int(count),
|
||||
# })
|
||||
# ws.send(js)
|
||||
# except Exception as e:
|
||||
# raise
|
||||
|
||||
url = 'https://artstats.rubenvandeven.com/composites/views.php'
|
||||
try:
|
||||
if count % 10 == 0:
|
||||
# only send every one in x image, so that the server never can
|
||||
# retrace _exact_ faces by comparing the sent frames.
|
||||
with open(image_filename) as fp:
|
||||
print('send request including image')
|
||||
logger.info('send request including image')
|
||||
r = requests.post(
|
||||
url ,
|
||||
files={'image': fp},
|
||||
params=params
|
||||
)
|
||||
else:
|
||||
print('send request')
|
||||
logger.info('send request')
|
||||
r = requests.post(
|
||||
url,
|
||||
params=params
|
||||
)
|
||||
updateGoesOk = True
|
||||
except Exception as e:
|
||||
updateGoesOk = False
|
||||
logger.critical("Error when updating statistics")
|
||||
logger.exception(e)
|
||||
|
||||
class CompositeImage:
|
||||
def __init__(self, name, resolution):
|
||||
|
@ -102,7 +115,7 @@ class CompositeImage:
|
|||
self.count = i
|
||||
name = self.get_frame_filename(self.count)
|
||||
img_file = os.path.join(dir, name)
|
||||
print("\trestore {}".format(img_file))
|
||||
logger.info("\trestore {}".format(img_file))
|
||||
self.image = np.array(Image.open(img_file)).astype('float64')
|
||||
self.state_dirty = False
|
||||
|
||||
|
@ -112,12 +125,15 @@ class CompositeImage:
|
|||
def get_frame_filename(self, i):
|
||||
return "{}-{}x{}-{}.png".format(self.name, self.resolution[0], self.resolution[1], i)
|
||||
|
||||
def get_current_filename(self):
|
||||
return self.get_frame_filename(self.count)
|
||||
|
||||
def save_image(self, dir):
|
||||
if self.state_dirty is False:
|
||||
# don't save if no changes are made since last save
|
||||
return
|
||||
|
||||
name = self.get_frame_filename(self.count)
|
||||
name = self.get_current_filename()
|
||||
filename = os.path.join(dir, name)
|
||||
self.get_image().save(filename)
|
||||
|
||||
|
@ -140,6 +156,9 @@ class CompositeCollection:
|
|||
def get_pickle_filename(self):
|
||||
return os.path.join(self.target_dir, self.id + ".p")
|
||||
|
||||
def get_json_filename(self):
|
||||
return os.path.join(self.target_dir, "composites.json")
|
||||
|
||||
def load(self):
|
||||
pickle_file_name = self.get_pickle_filename()
|
||||
# if os.path.exists(pickle_file_name):
|
||||
|
@ -151,7 +170,7 @@ class CompositeCollection:
|
|||
composites[name] = CompositeImage(name, self.size)
|
||||
composites[name].restore( data['c'][name], self.target_dir)
|
||||
except Exception as e:
|
||||
print("Create new composite", e)
|
||||
logger.info("Create new composite", e)
|
||||
for name in self.names:
|
||||
composites[name] = CompositeImage(name, self.size)
|
||||
|
||||
|
@ -163,9 +182,31 @@ class CompositeCollection:
|
|||
data['c'][name] = self.composites[name].count
|
||||
|
||||
with open( self.get_pickle_filename(), "wb" ) as fp:
|
||||
print("Save", data)
|
||||
logger.info("Save", data)
|
||||
pickle.dump( data, fp )
|
||||
|
||||
self.save_json()
|
||||
|
||||
def save_json(self):
|
||||
"""
|
||||
Save statistics as json
|
||||
"""
|
||||
data = {}
|
||||
for name in self.composites:
|
||||
data[name] = {
|
||||
'count': self.composites[name].count,
|
||||
'img': self.composites[name].get_current_filename()
|
||||
}
|
||||
|
||||
with open( self.get_json_filename(), "w" ) as fp:
|
||||
logger.debug("Json to {}".format(self.get_json_filename()))
|
||||
json.dump(data, fp)
|
||||
|
||||
ws = create_connection("ws://localhost:8888/ws")
|
||||
ws.send("update")
|
||||
|
||||
|
||||
|
||||
def save_img(self, name):
|
||||
self.get(name).save_image(self.target_dir)
|
||||
|
||||
|
@ -192,19 +233,22 @@ class CompositeCollection:
|
|||
for i in range(start, end):
|
||||
filename = os.path.join(self.target_dir, c.get_frame_filename(i))
|
||||
if os.path.exists(filename):
|
||||
print("Clean {}".format(filename))
|
||||
logger.info("Clean {}".format(filename))
|
||||
os.unlink(filename)
|
||||
|
||||
|
||||
|
||||
def append_face(row, image, composites):
|
||||
# degrees to distinguish side (as we will never be able to use 90 :-( )
|
||||
suffix = 'side' if abs(float(row['yaw'])) > 20 else 'front'
|
||||
# print('yaw:', float(row['yaw']))
|
||||
name = "{}_{}".format(row['gender'], suffix)
|
||||
# Plus, we now have a wide angle lens.
|
||||
suffix = 'side' if abs(float(row['yaw'])) > 12 else 'front'
|
||||
names = [suffix, "{}_{}".format(row['gender'], suffix)]
|
||||
|
||||
compositesToUse = []
|
||||
for name in names:
|
||||
if name not in composites.names:
|
||||
return
|
||||
composite = composites.get(name)
|
||||
compositesToUse.append(composites.get(name))
|
||||
|
||||
# TODO: matrix transform the image, to skew the face into being a flat-ish surface
|
||||
# This might yield less blurry composites
|
||||
|
@ -228,16 +272,17 @@ def append_face(row, image, composites):
|
|||
# PIL.Image handles cropping outside the canvas by filling with black/transparent
|
||||
x = face_x + dx
|
||||
y = face_y + dy
|
||||
print('crop')
|
||||
logger.debug('crop')
|
||||
i = image.crop((x,y, x + size_x, y + size_y))
|
||||
|
||||
if suffix == 'side' and float(row['yaw']) < 0:
|
||||
print('\tflip')
|
||||
logger.debug('\tflip')
|
||||
i = i.transpose(Image.FLIP_LEFT_RIGHT)
|
||||
|
||||
print('add')
|
||||
for composite in compositesToUse:
|
||||
logger.debug('add')
|
||||
composite.addFace(i)
|
||||
print('added')
|
||||
logger.debug('added')
|
||||
|
||||
composites = CompositeCollection(gender_perspectives, outputResolution, os.path.join(curdir, 'output'))
|
||||
|
||||
|
@ -250,7 +295,7 @@ while True:
|
|||
img = Image.open(tmpimage)
|
||||
os.unlink(tmpimage)
|
||||
with open(tmpimageResults) as csvfile:
|
||||
print("open csv")
|
||||
logger.debug("open csv")
|
||||
data = csv.DictReader(csvfile)
|
||||
faces = 0
|
||||
for row in data:
|
||||
|
@ -258,15 +303,14 @@ while True:
|
|||
# not a valid face
|
||||
continue
|
||||
faces += 1
|
||||
print("append face")
|
||||
logger.info("append face")
|
||||
append_face(row, img, composites)
|
||||
|
||||
if faces > 0:
|
||||
print("save :-)")
|
||||
logger.info("save :-)")
|
||||
for name in composites.names:
|
||||
print("\tsave img '{}'".format(name))
|
||||
logger.info("\tsave img '{}'".format(name))
|
||||
c = composites.save_img(name)
|
||||
# save pickle after images, so they can be restored
|
||||
composites.save()
|
||||
composites.clean()
|
||||
# TODO: trigger output update
|
||||
|
|
100
www/composite_loader.js
Normal file
100
www/composite_loader.js
Normal file
|
@ -0,0 +1,100 @@
|
|||
class Face {
|
||||
constructor(id) {
|
||||
this.id = id;
|
||||
this.value = 0;
|
||||
// this.name = name;
|
||||
this.imgEls = [];
|
||||
this.valueEls = [];
|
||||
|
||||
let els = document.querySelectorAll(`[data-face='${this.id}']`);
|
||||
for(let el of els) {
|
||||
if(el.tagName == 'IMG') {
|
||||
this.imgEls.push(el);
|
||||
} else {
|
||||
this.valueEls.push(el);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
addImgEl(el) {
|
||||
this.imgEls.push(el)
|
||||
}
|
||||
|
||||
addValueEl(el) {
|
||||
this.valueEls.push(el)
|
||||
}
|
||||
|
||||
update(imgUrl, value) {
|
||||
for(let el of this.valueEls) {
|
||||
el.textContent = new Intl.NumberFormat("nl").format(value);
|
||||
}
|
||||
for(let el of this.imgEls) {
|
||||
el.src = imgUrl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class Bar {
|
||||
constructor(el) {
|
||||
this.el = el;
|
||||
this.values = {};
|
||||
}
|
||||
|
||||
setValue(id, value) {
|
||||
this.values[id] = value;
|
||||
this.update();
|
||||
}
|
||||
|
||||
update() {
|
||||
for(let id in this.values) {
|
||||
let el = document.getElementById('graph--' + id);
|
||||
if(!el) continue;
|
||||
|
||||
let nrEls = el.getElementsByClassName('nr');
|
||||
for(let nrEl of nrEls) {
|
||||
nrEl.textContent = new Intl.NumberFormat("nl").format(this.values[id]);
|
||||
}
|
||||
|
||||
el.style.flex = parseInt(this.values[id]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
var bar = new Bar(document.getElementById('graph'));
|
||||
|
||||
var faces = {
|
||||
'front': new Face('front'),
|
||||
'side': new Face('side'),
|
||||
'male_front': new Face('male_front'),
|
||||
'female_front': new Face('female_front'),
|
||||
'unknown_front': new Face('unknown_front'),
|
||||
'male_side': new Face('male_side'),
|
||||
'female_side': new Face('female_side'),
|
||||
'unknown_side': new Face('unknown_side')
|
||||
}
|
||||
|
||||
var update = function() {
|
||||
let req = new XMLHttpRequest();
|
||||
req.addEventListener("load", function(e){
|
||||
let data = JSON.parse(this.responseText);
|
||||
console.log(data);
|
||||
for(let name in data){
|
||||
faces[name].update('/output/'+data[name]['img'], data[name]['count']);
|
||||
}
|
||||
|
||||
bar.setValue('male', data['male_front']['count'] + data['male_side']['count'])
|
||||
bar.setValue('female', data['female_front']['count'] + data['female_side']['count'])
|
||||
bar.setValue('unknown', data['unknown_front']['count'] + data['unknown_side']['count'])
|
||||
});
|
||||
req.open("GET", "/output/composites.json?v=" + Date.now());
|
||||
req.send();
|
||||
}
|
||||
|
||||
var socket = new ReconnectingWebSocket("ws://"+window.location.hostname+":"+window.location.port+"/ws")
|
||||
socket.addEventListener('message', function (event) {
|
||||
//trigger update
|
||||
update();
|
||||
});
|
||||
|
||||
update();
|
353
www/index.html
353
www/index.html
|
@ -9,291 +9,164 @@
|
|||
<h1>Specimens <span class='of'>of</span> Discriminatory Composite Portraiture</h1>
|
||||
<section id='gender'>
|
||||
<h2>Gender Differentiation<span class='star'>*</span></h2>
|
||||
<div class='gender-wrap'>
|
||||
<div class='genders'>
|
||||
<div id="front">
|
||||
<div class='composite' id="front--f">
|
||||
<img data-face="female_front" src="unknown_side-1000x1000-3.png">
|
||||
<div class='cases'><span class='type'>female</span> <span class='cases--nr' data-face="female_front">12.320</span> cases</div>
|
||||
</div>
|
||||
<div class='composite' id="front--u">
|
||||
<img data-face="unknown_front" src="unknown_side-1000x1000-3.png">
|
||||
<div class='cases'><span class='type'>unknown</span> <span class='cases--nr' data-face="unknown_front">100</span> cases</div>
|
||||
</div>
|
||||
<div class='composite' id="front--m">
|
||||
<img data-face="male_front" src="unknown_side-1000x1000-3.png">
|
||||
<div class='cases'><span class='type'>male</span> <span class='cases--nr' data-face="male_front">120</span> cases</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="general">
|
||||
<div class='composite' id="side--composite">
|
||||
<img data-face="side" src="unknown_side-1000x1000-3.png">
|
||||
<div class='cases'><span class='cases--nr' data-face="side">100</span> side faces</div>
|
||||
</div>
|
||||
<div class='composite' id="front--composite">
|
||||
<img data-face="front" src="unknown_side-1000x1000-3.png">
|
||||
<div class='cases'><span class='cases--nr' data-face="front">100</span> front faces</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="side">
|
||||
<div class='composite' id="side--m">
|
||||
<img data-face="male_side" src="unknown_side-1000x1000-3.png">
|
||||
<div class='cases'><span class='type'>male</span> <span class='cases--nr' data-face="male_side">120</span> cases</div>
|
||||
</div>
|
||||
<div class='composite' id="side--u">
|
||||
<img data-face="unknown_side" src="unknown_side-1000x1000-3.png">
|
||||
<div class='cases'><span class='type'>unknown</span> <span class='cases--nr' data-face="unknown_side">100</span> cases</div>
|
||||
</div>
|
||||
<div class='composite' id="side--f">
|
||||
<img data-face="female_side" src="unknown_side-1000x1000-3.png">
|
||||
<div class='cases'><span class='type'>female</span> <span class='cases--nr' data-face="female_side">12.320</span> cases</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<svg
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
id="svg954"
|
||||
id="lines--front"
|
||||
version="1.1"
|
||||
viewBox="0 0 269.68921 171.03902"
|
||||
height="171.03902mm"
|
||||
width="249.68921mm">
|
||||
<defs
|
||||
id="defs948" />
|
||||
viewBox="0 0 59.548019 116.38292"
|
||||
height="116.38292mm"
|
||||
width="59.548019mm">
|
||||
<g
|
||||
transform="translate(-479.74467,99.971886)"
|
||||
transform="translate(679.89306,124.0486)"
|
||||
id="layer1">
|
||||
<path
|
||||
style="fill:none;stroke:var(--primary-color);stroke-width:1.02617979;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 707.56274,47.386401 c -39.08004,0 -26.35353,-98.175942 -59.54802,-98.175942"
|
||||
id="path919" />
|
||||
<path
|
||||
id="path921"
|
||||
d="m 707.56274,-67.970339 c -39.08004,0 -26.35353,17.180798 -59.54802,17.180798"
|
||||
style="fill:none;stroke:var(--primary-color);stroke-width:1.02617979;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<path
|
||||
style="fill:none;stroke:var(--primary-color);stroke-width:1.02617979;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 707.56274,-8.6440273 c -39.08004,0 -26.35353,-42.1455137 -59.54802,-42.1455137"
|
||||
id="path923" />
|
||||
<path
|
||||
id="path836"
|
||||
d="m 540.57238,-79.730199 c 70.83004,0 26.35353,98.17594 59.54801,98.17594"
|
||||
d="m -679.89306,-123.53551 c 70.83005,0 26.35353,98.175937 59.54802,98.175937"
|
||||
style="fill:none;stroke:var(--primary-color);stroke-width:1.02617979;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<path
|
||||
style="fill:none;stroke:var(--primary-color);stroke-width:1.02617979;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 540.57238,35.626541 c 39.08004,0 26.35352,-17.1808 59.54801,-17.1808"
|
||||
d="m -679.89306,-8.1787728 c 39.08005,0 26.35353,-17.1808002 59.54802,-17.1808002"
|
||||
id="path838" />
|
||||
<path
|
||||
id="path840"
|
||||
d="m 540.57238,-23.699793 c 39.08004,0 26.35352,42.145534 59.54801,42.145534"
|
||||
d="m -679.89306,-67.505107 c 39.08005,0 26.35353,42.145534 59.54802,42.145534"
|
||||
style="fill:none;stroke:var(--primary-color);stroke-width:1.02617979;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<image
|
||||
y="-98.78492"
|
||||
x="488.05942"
|
||||
id="image826"
|
||||
xlink:href="unknown_side-1000x1000-3.png"
|
||||
preserveAspectRatio="none"
|
||||
height="51.730377"
|
||||
width="51.730377" />
|
||||
<use
|
||||
height="100%"
|
||||
width="100%"
|
||||
transform="translate(-4.5528998e-7,57.022051)"
|
||||
id="use828"
|
||||
xlink:href="#image826"
|
||||
y="0"
|
||||
x="0" />
|
||||
<use
|
||||
height="100%"
|
||||
width="100%"
|
||||
transform="translate(-4.5528998e-7,58.005791)"
|
||||
id="use830"
|
||||
xlink:href="#use828"
|
||||
y="0"
|
||||
x="0" />
|
||||
<image
|
||||
width="49.769428"
|
||||
height="49.769428"
|
||||
preserveAspectRatio="none"
|
||||
xlink:href="unknown_side-1000x1000-3.png"
|
||||
id="use834"
|
||||
x="597.66241"
|
||||
y="-20.339062" />
|
||||
<image
|
||||
width="53.440414"
|
||||
height="53.440414"
|
||||
preserveAspectRatio="none"
|
||||
xlink:href="unknown_side-1000x1000-3.png"
|
||||
id="image910"
|
||||
x="687.51868"
|
||||
y="-99.971886" />
|
||||
<image
|
||||
y="-41.172611"
|
||||
x="687.51868"
|
||||
id="image913"
|
||||
xlink:href="unknown_side-1000x1000-3.png"
|
||||
preserveAspectRatio="none"
|
||||
height="53.440414"
|
||||
width="53.440414" />
|
||||
<image
|
||||
width="53.440414"
|
||||
height="53.440414"
|
||||
preserveAspectRatio="none"
|
||||
xlink:href="unknown_side-1000x1000-3.png"
|
||||
id="image915"
|
||||
x="687.51868"
|
||||
y="17.626713" />
|
||||
<image
|
||||
width="49.769428"
|
||||
height="51.32375"
|
||||
preserveAspectRatio="none"
|
||||
xlink:href="unknown_side-1000x1000-3.png"
|
||||
id="image917"
|
||||
x="597.66241"
|
||||
y="-82.246162" />
|
||||
<text
|
||||
id="text927"
|
||||
y="63.765812"
|
||||
x="542.91345"
|
||||
style="font-style:normal;font-variant:normal;font-weight:500;font-stretch:normal;font-size:5.96850729px;line-height:1.25;font-family:'CMU Serif';-inkscape-font-specification:'CMU Serif, Medium';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:var(--primary-color);fill-opacity:1;stroke:none;stroke-width:0.14921269"
|
||||
xml:space="preserve"><tspan
|
||||
style="font-style:normal;font-variant:normal;font-weight:500;font-stretch:normal;font-size:5.96850729px;font-family:'CMU Serif';-inkscape-font-specification:'CMU Serif, Medium';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.14921269"
|
||||
y="63.765812"
|
||||
x="542.91345"
|
||||
id="tspan925">20 cases</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:500;font-stretch:normal;font-size:7.32276964px;line-height:0.80000001;font-family:'CMU Serif';-inkscape-font-specification:'CMU Serif, Medium';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:var(--primary-color);fill-opacity:1;stroke:none;stroke-width:0.18306924"
|
||||
x="541.38544"
|
||||
y="1.2943537"
|
||||
id="text931"><tspan
|
||||
id="tspan929"
|
||||
x="541.38544"
|
||||
y="1.2943537"
|
||||
style="font-style:normal;font-variant:normal;font-weight:500;font-stretch:normal;font-size:7.32276964px;line-height:0.80000001;font-family:'CMU Serif';-inkscape-font-specification:'CMU Serif, Medium';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.18306924">1.200</tspan><tspan
|
||||
id="tspan939"
|
||||
x="541.38544"
|
||||
y="7.1525693"
|
||||
style="font-style:normal;font-variant:normal;font-weight:500;font-stretch:normal;font-size:7.32276964px;line-height:0.80000001;font-family:'CMU Serif';-inkscape-font-specification:'CMU Serif, Medium';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.18306924">cases</tspan></text>
|
||||
<text
|
||||
id="text935"
|
||||
y="-48.44733"
|
||||
x="540.32709"
|
||||
style="font-style:normal;font-variant:normal;font-weight:500;font-stretch:normal;font-size:7.32276964px;line-height:1.25;font-family:'CMU Serif';-inkscape-font-specification:'CMU Serif, Medium';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:var(--primary-color);fill-opacity:1;stroke:none;stroke-width:0.18306924"
|
||||
xml:space="preserve"><tspan
|
||||
style="font-style:normal;font-variant:normal;font-weight:500;font-stretch:normal;font-size:7.32276964px;font-family:'CMU Serif';-inkscape-font-specification:'CMU Serif, Medium';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.18306924"
|
||||
y="-48.44733"
|
||||
x="540.32709"
|
||||
id="tspan933">120 cases</tspan></text>
|
||||
<path
|
||||
id="path937"
|
||||
d="M 540.57238,-79.730199 Z"
|
||||
style="fill:none;stroke:var(--primary-color);stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:500;font-stretch:normal;font-size:7.32276964px;line-height:1.25;font-family:'CMU Serif';-inkscape-font-specification:'CMU Serif, Medium';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:var(--primary-color);fill-opacity:1;stroke:none;stroke-width:0.18306924"
|
||||
x="603.58911"
|
||||
y="37.606449"
|
||||
id="text972"><tspan
|
||||
id="tspan970"
|
||||
x="603.58911"
|
||||
y="37.606449"
|
||||
style="font-style:normal;font-variant:normal;font-weight:500;font-stretch:normal;font-size:7.32276964px;font-family:'CMU Serif';-inkscape-font-specification:'CMU Serif, Medium';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.18306924">1.340 cases</tspan></text>
|
||||
<text
|
||||
id="text976"
|
||||
y="-24.546719"
|
||||
x="608.34381"
|
||||
style="font-style:normal;font-variant:normal;font-weight:500;font-stretch:normal;font-size:7.32276964px;line-height:1.25;font-family:'CMU Serif';-inkscape-font-specification:'CMU Serif, Medium';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:var(--primary-color);fill-opacity:1;stroke:none;stroke-width:0.18306924"
|
||||
xml:space="preserve"><tspan
|
||||
style="font-style:normal;font-variant:normal;font-weight:500;font-stretch:normal;font-size:7.32276964px;font-family:'CMU Serif';-inkscape-font-specification:'CMU Serif, Medium';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.18306924"
|
||||
y="-24.546719"
|
||||
x="608.34381"
|
||||
id="tspan974">800 cases</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:500;font-stretch:normal;font-size:7.32276964px;line-height:1.25;font-family:'CMU Serif';-inkscape-font-specification:'CMU Serif, Medium';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:var(--primary-color);fill-opacity:1;stroke:none;stroke-width:0.18306924"
|
||||
x="479.47293"
|
||||
y="-66.438972"
|
||||
id="text1006"><tspan
|
||||
id="tspan1004"
|
||||
x="479.47293"
|
||||
y="-66.438972"
|
||||
style="font-style:normal;font-variant:normal;font-weight:500;font-stretch:normal;font-size:7.32276964px;font-family:'CMU Serif';-inkscape-font-specification:'CMU Serif, Medium';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.18306924">M</tspan></text>
|
||||
<text
|
||||
id="text1010"
|
||||
y="-13.522312"
|
||||
x="480.53125"
|
||||
style="font-style:normal;font-variant:normal;font-weight:500;font-stretch:normal;font-size:7.32276964px;line-height:1.25;font-family:'CMU Serif';-inkscape-font-specification:'CMU Serif, Medium';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:var(--primary-color);fill-opacity:1;stroke:none;stroke-width:0.18306924"
|
||||
xml:space="preserve"><tspan
|
||||
style="font-style:normal;font-variant:normal;font-weight:500;font-stretch:normal;font-size:7.32276964px;font-family:'CMU Serif';-inkscape-font-specification:'CMU Serif, Medium';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.18306924"
|
||||
y="-13.522312"
|
||||
x="480.53125"
|
||||
id="tspan1008">F</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:500;font-stretch:normal;font-size:7.32276964px;line-height:1.25;font-family:'CMU Serif';-inkscape-font-specification:'CMU Serif, Medium';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:var(--primary-color);fill-opacity:1;stroke:none;stroke-width:0.18306924"
|
||||
x="481.06042"
|
||||
y="44.686024"
|
||||
id="text1014"><tspan
|
||||
id="tspan1012"
|
||||
x="481.06042"
|
||||
y="44.686024"
|
||||
style="font-style:normal;font-variant:normal;font-weight:500;font-stretch:normal;font-size:7.32276964px;font-family:'CMU Serif';-inkscape-font-specification:'CMU Serif, Medium';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.18306924">?</tspan></text>
|
||||
<text
|
||||
id="text1018"
|
||||
y="-66.438972"
|
||||
x="742.99786"
|
||||
style="font-style:normal;font-variant:normal;font-weight:500;font-stretch:normal;font-size:7.32276964px;line-height:1.25;font-family:'CMU Serif';-inkscape-font-specification:'CMU Serif, Medium';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:var(--primary-color);fill-opacity:1;stroke:none;stroke-width:0.18306924"
|
||||
xml:space="preserve"><tspan
|
||||
style="font-style:normal;font-variant:normal;font-weight:500;font-stretch:normal;font-size:7.32276964px;font-family:'CMU Serif';-inkscape-font-specification:'CMU Serif, Medium';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.18306924"
|
||||
y="-66.438972"
|
||||
x="742.99786"
|
||||
id="tspan1016">M</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:500;font-stretch:normal;font-size:7.32276964px;line-height:1.25;font-family:'CMU Serif';-inkscape-font-specification:'CMU Serif, Medium';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:var(--primary-color);fill-opacity:1;stroke:none;stroke-width:0.18306924"
|
||||
x="744.05621"
|
||||
y="-13.522312"
|
||||
id="text1022"><tspan
|
||||
id="tspan1020"
|
||||
x="744.05621"
|
||||
y="-13.522312"
|
||||
style="font-style:normal;font-variant:normal;font-weight:500;font-stretch:normal;font-size:7.32276964px;font-family:'CMU Serif';-inkscape-font-specification:'CMU Serif, Medium';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.18306924">F</tspan></text>
|
||||
<text
|
||||
id="text1026"
|
||||
y="44.686024"
|
||||
x="744.58539"
|
||||
style="font-style:normal;font-variant:normal;font-weight:500;font-stretch:normal;font-size:7.32276964px;line-height:1.25;font-family:'CMU Serif';-inkscape-font-specification:'CMU Serif, Medium';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:var(--primary-color);fill-opacity:1;stroke:none;stroke-width:0.18306924"
|
||||
xml:space="preserve"><tspan
|
||||
style="font-style:normal;font-variant:normal;font-weight:500;font-stretch:normal;font-size:7.32276964px;font-family:'CMU Serif';-inkscape-font-specification:'CMU Serif, Medium';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.18306924"
|
||||
y="44.686024"
|
||||
x="744.58539"
|
||||
id="tspan1024">?</tspan></text>
|
||||
</g>
|
||||
</svg>
|
||||
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
id="lines--side"
|
||||
version="1.1"
|
||||
viewBox="0 0 59.548019 116.38292"
|
||||
height="116.38292mm"
|
||||
width="59.548019mm">
|
||||
<g
|
||||
transform="translate(679.89306,124.0486)"
|
||||
id="layer1">
|
||||
<path
|
||||
id="path836"
|
||||
d="m -679.89306,-123.53551 c 70.83005,0 26.35353,98.175937 59.54802,98.175937"
|
||||
style="fill:none;stroke:var(--primary-color);stroke-width:1.02617979;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<path
|
||||
style="fill:none;stroke:var(--primary-color);stroke-width:1.02617979;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m -679.89306,-8.1787728 c 39.08005,0 26.35353,-17.1808002 59.54802,-17.1808002"
|
||||
id="path838" />
|
||||
<path
|
||||
id="path840"
|
||||
d="m -679.89306,-67.505107 c 39.08005,0 26.35353,42.145534 59.54802,42.145534"
|
||||
style="fill:none;stroke:var(--primary-color);stroke-width:1.02617979;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
</g>
|
||||
</svg>
|
||||
</div>
|
||||
</section>
|
||||
<section id='differences'>
|
||||
<div class='gender'>
|
||||
<h2>Distinctive traits</h2>
|
||||
<div>
|
||||
<div class='gender explanation'>
|
||||
<!-- <p>Distinctive traits</p> -->
|
||||
<h3>composite subtraction</h3>
|
||||
<p>An examination of discriminatory traits in gender differentation.</p>
|
||||
</div>
|
||||
<div class='gender'>
|
||||
<img src="unknown_side-1000x1000-3.png"><img src="unknown_side-1000x1000-3.png">
|
||||
<div class='diff-layer'>
|
||||
<img data-face="male_front" src="unknown_side-1000x1000-3.png"><img data-face="male_side" src="unknown_side-1000x1000-3.png">
|
||||
</div>
|
||||
<div class='original-layer'>
|
||||
<img data-face="front" src="unknown_side-1000x1000-3.png"><img data-face="side" src="unknown_side-1000x1000-3.png">
|
||||
</div>
|
||||
<div class='label'>Male</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class='gender'>
|
||||
<div class='diff-layer'>
|
||||
<img data-face="unknown_front" src="unknown_side-1000x1000-3.png"><img data-face="unknown_side" src="unknown_side-1000x1000-3.png">
|
||||
</div>
|
||||
<div class='original-layer'>
|
||||
<img data-face="front" src="unknown_side-1000x1000-3.png"><img data-face="side" src="unknown_side-1000x1000-3.png">
|
||||
</div>
|
||||
<div class='label'>Unknown</div>
|
||||
</div>
|
||||
<div class='gender'>
|
||||
<img src="unknown_side-1000x1000-3.png"><img src="unknown_side-1000x1000-3.png">
|
||||
<div class='diff-layer'>
|
||||
<img data-face="female_front" src="unknown_side-1000x1000-3.png"><img data-face="female_side" src="unknown_side-1000x1000-3.png">
|
||||
</div>
|
||||
<div class='gender'>
|
||||
<img src="unknown_side-1000x1000-3.png"><img src="unknown_side-1000x1000-3.png">
|
||||
<div class='original-layer'>
|
||||
<img data-face="front" src="unknown_side-1000x1000-3.png"><img data-face="side" src="unknown_side-1000x1000-3.png">
|
||||
</div>
|
||||
|
||||
<div class='label'>Female</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<div id='bar-wrap'>
|
||||
<section id='legend'>
|
||||
<div class='legend legend--female'>Female</div>
|
||||
<div class='legend legend--unknown'>Unknown</div>
|
||||
<div class='legend legend--male'>Male</div>
|
||||
</section>
|
||||
<section id='graph'>
|
||||
<div id='graph--male' data-width="30%">
|
||||
<div id='graph--female'>
|
||||
<div class='wrap'><div class='background'></div></div>
|
||||
<div class='cases'><span class='nr'>0</span> <span class='txt'>cases</span></div>
|
||||
</div>
|
||||
<div id='graph--female' data-width="30%">
|
||||
<div id='graph--unknown'>
|
||||
<div class='wrap'><div class='background'></div></div>
|
||||
<div class='cases'><span class='nr'>0</span> <span class='txt'>cases</span></div>
|
||||
</div>
|
||||
<div id='graph--unknown' data-width="30%">
|
||||
<div id='graph--male'>
|
||||
<div class='wrap'><div class='background'></div></div>
|
||||
<div class='cases'><span class='nr'>0</span> <span class='txt'>cases</span></div>
|
||||
</div>
|
||||
</section>
|
||||
<!-- <section id='ethnicity'>
|
||||
<h2>Reinforced Ethnical Stereotypes</h2>
|
||||
<div id='graph'>
|
||||
<div id='graph--black-african'>
|
||||
<div class='background'></div>
|
||||
<div class='cases'><span class='nr'>0</span> <span class='txt'>cases</span></div>
|
||||
</div>
|
||||
<div id='graph--caucasian'>
|
||||
<div class='background'></div>
|
||||
<div class='cases'><span class='nr'>0</span> <span class='txt'>cases</span></div>
|
||||
</div>
|
||||
<div id='graph--east-asian'>
|
||||
<div class='background'></div>
|
||||
<div class='cases'><span class='nr'>0</span> <span class='txt'>cases</span></div>
|
||||
</div>
|
||||
<div id='graph--hispanic'>
|
||||
<div class='background'></div>
|
||||
<div class='cases'><span class='nr'>0</span> <span class='txt'>cases</span></div>
|
||||
</div>
|
||||
<div id='graph--south-asian'>
|
||||
<div class='background'></div>
|
||||
<div class='cases'><span class='nr'>0</span> <span class='txt'>cases</span></div>
|
||||
</div>
|
||||
</div>
|
||||
</section> -->
|
||||
<div id='affdex'>* according to the 2018 edition of Affectiva's gender detection toolkit</div>
|
||||
<div id='signature'>
|
||||
<!-- — -->
|
||||
Ruben van de Ven
|
||||
<!-- — -->
|
||||
</div>
|
||||
<script type="text/javascript" src="reconnecting-websocket.min.js"></script>
|
||||
<script type="text/javascript" src="composite_loader.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
178
www/styles.css
178
www/styles.css
|
@ -6,6 +6,7 @@
|
|||
html{
|
||||
/* filter: invert(1); */
|
||||
background: var(--secundary-color);
|
||||
/* background-color: darkred; */
|
||||
}
|
||||
body{
|
||||
font-family: "CMU Serif";
|
||||
|
@ -34,7 +35,7 @@ html{
|
|||
padding: 20px 0 20px 0;
|
||||
}
|
||||
section#gender{
|
||||
height: 44%;
|
||||
height: 47%;
|
||||
border-bottom: solid 4px var(--primary-color);
|
||||
}
|
||||
|
||||
|
@ -53,7 +54,7 @@ html{
|
|||
font-size: 40%;
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
top: -12px;
|
||||
top: -27px;
|
||||
}
|
||||
|
||||
.genders{
|
||||
|
@ -63,11 +64,6 @@ html{
|
|||
#gender h2{
|
||||
letter-spacing: 2px;
|
||||
}
|
||||
|
||||
#ethnicity h2{
|
||||
/* letter-spacing: 2px; */
|
||||
}
|
||||
|
||||
#affdex{
|
||||
position: absolute;
|
||||
top: calc(100% - 18px);
|
||||
|
@ -85,15 +81,68 @@ html{
|
|||
text-align: right;
|
||||
}
|
||||
|
||||
.genders {
|
||||
display: flex;
|
||||
/* flex-direction: row; */
|
||||
justify-content: space-between;
|
||||
/* vertical align: */
|
||||
align-items: center;
|
||||
margin: 30px;
|
||||
|
||||
}
|
||||
|
||||
.gender-wrap{
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.genders > div{
|
||||
font-size: 20pt;
|
||||
width: 195px;
|
||||
}
|
||||
|
||||
.genders .composite img{
|
||||
width: 100%;
|
||||
/* height: 180px; */
|
||||
}
|
||||
|
||||
/* .genders #front--composite{
|
||||
margin-top: 10px;
|
||||
} */
|
||||
|
||||
.genders #front--composite{
|
||||
margin-top: 30px;
|
||||
}
|
||||
|
||||
.genders .type{
|
||||
text-transform: uppercase;;
|
||||
display:block;
|
||||
margin-top: -45px;
|
||||
}
|
||||
|
||||
#graph{
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
margin: 0 20px;
|
||||
padding-top: 50px;
|
||||
clear:both;
|
||||
font-size: 22pt;
|
||||
}
|
||||
#graph > div{
|
||||
width: 33%;
|
||||
flex: 1;
|
||||
min-width: 5%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#lines--side, #lines--front{
|
||||
position: absolute;
|
||||
top: 100px;
|
||||
left: 200px;
|
||||
z-index: -1;
|
||||
}
|
||||
#lines--side{
|
||||
top: 120px;
|
||||
left: 580px;
|
||||
transform: scale(-1);
|
||||
}
|
||||
|
||||
|
||||
|
@ -127,28 +176,73 @@ html{
|
|||
|
||||
#graph .cases{
|
||||
text-align: center;
|
||||
text-wrap: wrap;
|
||||
height: 1.2em;;
|
||||
}
|
||||
|
||||
#differences{
|
||||
border-bottom: solid 4px var(--primary-color);
|
||||
padding-bottom: 50px;
|
||||
padding-bottom: 10px;
|
||||
display:flex;
|
||||
height: 497px;
|
||||
}
|
||||
#differences::after{
|
||||
content: '';
|
||||
clear:both;
|
||||
display: block;
|
||||
}
|
||||
|
||||
#differences .gender {
|
||||
width: 50%;
|
||||
margin: 50px 0 0 0;
|
||||
float:left;
|
||||
font-size: 18pt;
|
||||
}
|
||||
#differences > div{
|
||||
flex: 1;
|
||||
}
|
||||
#differences .gender {
|
||||
width: 100%;
|
||||
margin: 40px 0 0 0;
|
||||
/* float:left; */
|
||||
text-align: center;
|
||||
position: relative;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
#differences .gender + .gender{
|
||||
margin-top: 20px;
|
||||
}
|
||||
#differences .gender.explanation {
|
||||
text-align: left;
|
||||
text-transform: none;
|
||||
padding-left: 85px;
|
||||
padding-right: 50px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
#differences .gender.explanation h3{
|
||||
margin: 60px 0 0 0;
|
||||
padding:0;
|
||||
}
|
||||
#differences .gender.explanation p{
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#differences .gender.explanation + .gender{
|
||||
margin-top: 40px;
|
||||
}
|
||||
|
||||
#differences .gender .diff-layer{
|
||||
position: absolute;
|
||||
top:0;
|
||||
right:0;
|
||||
left:0;
|
||||
mix-blend-mode: difference;
|
||||
}
|
||||
|
||||
#differences .gender .original-layer img{
|
||||
/* black yields no difference for blend-mode */
|
||||
border-color: black;
|
||||
}
|
||||
|
||||
#differences .gender img{
|
||||
width: 180px;
|
||||
height: 180px;
|
||||
width: 170px;
|
||||
height: 170px;
|
||||
border: solid 2px var(--primary-color);
|
||||
}
|
||||
|
||||
|
@ -156,3 +250,57 @@ html{
|
|||
border-bottom: none;
|
||||
margin-top: 40px;
|
||||
}
|
||||
|
||||
#bar-wrap{
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#legend{
|
||||
position: absolute;
|
||||
border-top: solid 4px var(--primary-color);
|
||||
border-right: solid 4px var(--primary-color);
|
||||
border-bottom: solid 1px var(--secundary-color);
|
||||
background-color: var(--secundary-color);
|
||||
bottom: calc(100%);
|
||||
left:0;
|
||||
width: 46%;
|
||||
padding: 20px 22px 0 22px;
|
||||
font-size: 20pt;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
|
||||
}
|
||||
|
||||
#legend div{
|
||||
display: inline-block;
|
||||
text-transform: uppercase;
|
||||
position: relative;
|
||||
top: 15px;
|
||||
font-size: 18pt;
|
||||
}
|
||||
#legend div::before{
|
||||
content: '';
|
||||
display: inline-block;
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
border: solid 2px var(--primary-color);
|
||||
outline: 2px solid var(--secundary-color);
|
||||
margin-right: 10px;
|
||||
background-image:url('texture-cross.png');
|
||||
background-size: 12px;
|
||||
filter:invert(1);
|
||||
font-size: 15pt;
|
||||
/* vertical-align: baseline; */
|
||||
position: relative;
|
||||
top: 2px;
|
||||
|
||||
}
|
||||
#legend div:nth-child(2)::before{
|
||||
background-image:url('texture-diagonal.png');
|
||||
background-size: 12px;
|
||||
}
|
||||
#legend div:nth-child(3)::before{
|
||||
background-image:url('texture-ball.png');
|
||||
background-size: 12px;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue