I have my SVG-based Polymer custom element in happy shape at this point. The
<x-pizza>
element is in nice code shape and, more importantly, building pizzas for hungry customers:It is composed of several different SVG files, each loaded with
<polymer-ajax>
for simplicity and ease of dynamic manipulation. It took some tinkering, but I finally have the drop shadow for the individual toppings animating on mouse over:The drop shadow pain was due to vagaries of SVG, but it proved that the
<polymer-ajax>
solution to loading other SVG assets (pizza toppings in this case) into a primary SVG worked and could still be effectively manipulated. I would like to build on that idea tonight by adding drop shadows to each of my toppings—not just the current pepperonis. I could work through each topping in turn with Inkscape, defining a second layer in each that holds the topping a little higher and with a drop shadow, but that seems like tedious work. Hopefully a little Dart can solve the problem without any Inkscape time.
I start by pulling the drop shadow filter definition out of the only topping SVG that currently has it,
pepperoni.svg
, and placing it in the background SVG of the blank pizza:<?xml version="1.0" encoding="UTF-8" standalone="no"?> <!-- Created with Inkscape (http://www.inkscape.org/) --> <svg xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" version="1.1" width="300" height="300"> <defs> <filter color-interpolation-filters="sRGB" height="2.0" width="1.5" y="-0.2" id="topping-drop-shadow"> <!-- lots and lots of filters... --> </filter> </defs> <path d="m 300,150 a 150,150 0 1 1 -300,0 150,150 0 1 1 300,0 z" id="path3755" style="fill:#c8b7b7;fill-opacity:1;stroke:none" /> <path d="m 280,150 a 130,130 0 1 1 -260,0 130,130 0 1 1 260,0 z" id="path3759" style="fill:#c83737;fill-opacity:1;stroke:none" /> <path d="m 270,150 a 120,120 0 1 1 -240,0 120,120 0 1 1 240,0 z" id="path3761" style="fill:#ffe6d5;fill-opacity:1;stroke:none" /> </svg>The only change that I make to the filter is the ID, which I now call
topping-drop-shadow
for code maintainability and readability. Since I append toppings to this base SVG image, the hope is that the drop shadow filter will continue to work with the topping SVG assets. Starting with pepperoni.svg
, I give it a try:<?xml version="1.0" encoding="UTF-8" standalone="no"?> <!-- Created with Inkscape (http://www.inkscape.org/) --> <svg xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" version="1.1" width="32" height="32"> <g id="down" style="display: inline"> <path d="M 22,12 A 10,10 0 1 1 2,12 10,10 0 1 1 22,12 z" transform="translate(2.8577037,1.6074583)" style="fill:#d40000;fill-opacity:1;stroke:#000000;stroke-width:1.5;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> </g> <g id="up" style="display: none"> <path d="M 22,12 A 10,10 0 1 1 2,12 10,10 0 1 1 22,12 z" style="fill:#d40000;fill-opacity:1;stroke:#000000;stroke-width:1.5;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;filter:url(#topping-drop-shadow)" /> </g> </svg>Happily that does still work.
Since it works on one, the hopefully the filter can work on all of my elements. While I am at it, I would like to switch from hiding/showing layers in my SVG to translating a single layer in each topping SVG. So, I remove the group layers in
pepperoni.svg
which now becomes:<?xml version="1.0" encoding="UTF-8" standalone="no"?> <!-- Created with Inkscape (http://www.inkscape.org/) --> <svg xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" version="1.1" width="32" height="32"> <path d="M 22,12 A 10,10 0 1 1 2,12 10,10 0 1 1 22,12 z" style="fill:#d40000;fill-opacity:1;stroke:#000000;stroke-width:1.5;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> </svg>That is much, much smaller without the filter definition and the layers.
Now I can eliminate the layer code that had supported the pepperoni SVG:
_svgPepperoni() {
var svg = _svgImage('pepperoni');
return svg
..onMouseOver.listen((e){
svg.query('#up').style.display = '';
svg.query('#down').style.display = 'none';
})
..onMouseLeave.listen((e){
svg.query('#up').style.display = 'none';
svg.query('#down').style.display = '';
});
}
Instead, the pepperoni now uses the same function as all of the other toppings: _svgPepperoni() => _svgImage('pepperoni');
_svgSausage() => _svgImage('sausage');
_svgGreenPepper() => _svgImage('green_pepper');
Finally, the _svgImage()
function now does translation and filter application when mouse events occur: _svgImage(basename) {
var svg = new GElement()
..append(new SvgElement.svg(svgContent['$basename.svg']));
var path = svg.query('path');
var style = path.getAttribute('style');
return svg
..onMouseOver.listen((e){
path
..setAttribute('style', '$style;filter:url(#topping-drop-shadow)')
..setAttribute('transform', 'translate(-2.8577037,-1.6074583)');
})
..onMouseLeave.listen((e){
path
..setAttribute('style', style)
..setAttribute('transform', 'translate(0,0)');
});
}
And that does the trick. I now get drop shadows for all of my toppings:Well, that might not be 100% working. I still need to figure out how best to handle the drawing area clipping, but this is getting very close to good enough. I will pick back up with the clipping tomorrow.
Day #74
No comments:
Post a Comment