Создание веб-иконки умнее
() translation by (you can also view the original English article)
Эта статья является первой в серии из трех частей, показаны новые подходы к иконографии знаковых будут доставлять. Если вам нравится, что вы видите в этой статье, пожалуйста, рассмотреть вопрос о поддержке знаменитого на Kickstarter.
Этот контент был заказан знаковых и написал и/или отредактировал команда туц+. Наша цель с авторами контента, чтобы публиковать актуальные и объективные учебники, кейс-стади, и вдохновляющие интервью, что предложение подлинное воспитательное значение для наших читателей и позволит финансировать создание более полезного контента.
Что такое умный значок?
Умный значок разработан таким образом, что элементы внутри него подстраиваться ввода, взаимодействия и связанные с ними данные. Короче говоря, он динамичный. Умные иконки в SVG-основано и управляется с комбинацией JavaScript и CSS.
Почему это актуально
Веб-иконки до этого момента были статические—в первую очередь из-за ограничений в технологии. Различных государств или вариации значок может быть создан просто путем предоставления отдельных файлов каждой перестановки. Например, значок батареи будет в четырех различных версиях: зарядки, полной зарядки, половину заряда и не заряжать. Не совсем оптимальный подход.
Целый ряд новых возможностей теперь возможен с массового применения браузера для SVG 1.1. Из-за семантической структуры СВГ, а умный значок может отображать полный диапазон состояний и вариаций. Это устраняет необходимость замены изображения и позволяет переходы между состояниями происходят плавно.
Умные иконки также дают дизайнерам возможность отображать соответствующую контекстную информацию в икону. Хорошо разработанный значок уже относительно пиков плотный объект. Добавление контекстной информации к иконе, его информационную плотность еще больше, если бы не значительное увеличение когнитивной нагрузки. В теории, эти типы икон будет способен взять на себя тяжелую коммуникации, таким образом, уменьшая количество другие элементы на экране.
Примеры использования для смарт-иконы
Существует множество различных направлений умные иконки могут пойти—некоторые из них проще в реализации, чем другие. Мы все еще в процессе поиска, но пока мы придумали три основных варианта использования:
Предоставление контекстной информации
Есть много икон, которые могли бы обеспечить другой слой информации, но просто не до этого момента, из-за их статического метода отображения. Примеры включают значки, такие как часы, термометр, диафрагма, WiFi сигнала и заряда батареи.



Действуя как простые данные-ВИС элементов (при d3.js это слишком много)
Один из лучших использования-чехлы для смарт-значки прост визуализации данных. Иконки, которые вписываются в эту категорию, звукового спектра, датчик/метр и индикатор загрузки. Умные иконки могут значительно упростить процесс создания панели отображает—думаю, просто добавив четыре или пять иконок в HTML и регулировки значения датчика с атрибутом данных.



Отображение различных государств
Много икон, часто попадают в серию вариаций, чтобы передать все их разных государств. Примеры включают батареи, беспроводной доступ в интернет, воспроизведения медиа-файлов (например, воспроизведение, пауза и т. д.) и мощности (например, включение, выключение, режим ожидания). Еще одна возможность применения смарт-иконки свернуть все государства-икона в единую СВГ. Поэтому вместо замены активов изображение, когда предмет государственного меняется, вы просто изменить атрибут данных в соответствующее состояние.



Гайки и болты
Примечание: перед вдаваясь в подробности, важно отметить, что в примерах мы просто доказательство концепции прототипов. Эти прототипы предназначены для передачи функциональности, которую мы будем создавать. Ни один из следующий код является окончательной, не говоря уже бета. Мы все еще в стадии разработки этого метода и мы знаем, что есть много вопросов, которые еще предстоит решить. Мы будем работать над более конкретное направление на этот метод после того, как кампания на Kickstarter завершится.
Умные иконки состоят из формата SVG, JavaScript и CSS. Наше нынешнее мышление к каждому значок как небольшие автономные приложения с помощью простого API для настройки элементов внутри значка. Для достижения такой надежной, такой подход требует разметки SVG, которые должны быть включены в дом.
Имейте в виду, что СВГ размечаем должен быть соответствующим образом структурирован для такого подхода к работе. Это то, что мы чувствуем, делает знаковые уникальные. Значки были спроектированы и изготовлены новые концепции в уме. Эти концепции опираются на четкую семантику и хорошо продуманная структура разметки для правильной работы. Это ничем не отличается от правильно структурированный HTML—если ваша разметка gobbleygoop, это будет сложно сделать, ничего сложного.
Много убедительных вещи могут случиться один раз хорошо структурированной разметки SVG в дом. Проблема в том, что при добавлении разметки SVG в HTML-это боль. Разметки SVG может добавить значительное количество наворотов в ваш код, и это становится труднее различать между структурными HTML и векторных изображений. Для того, чтобы убрать это трение, мы предлагаем инъекционных разметки SVG в DOM во время выполнения.
Мы сделали простой прототип инжектора СВГ, который заменяет все указанные теги img с разметки из ссылочного файла SVG. Так это...
1 |
<div class="image-container"> |
2 |
<img src="images/circle.svg" class="svg-inject" width="300" /> |
3 |
</div>
|
Превращается в это:
1 |
<div class="image-container"> |
2 |
<svg version="1.1" xmlns="https://www.w3.org/2000/svg" x="0px" y="0px" width="100px" height="100px"> |
3 |
<circle cx="50" cy="50" r="50"/> |
4 |
</svg>
|
5 |
</div>
|
Примечание: имейте в виду, это форсунки подход, безусловно, чувствует, как временная мера и мы надеемся, что наша работа поможет подтолкнуть браузер-родной стандарт. До тех пор, наше нынешнее мышление заключается в том, что это лучший подход.
После того, как СВГ вводят в DOM, JavaScript-код инкапсулирован в ее выполнении и готов к использованию. Некоторые иконки будут работать самостоятельно (как часы), тогда как другие требуют ввода для регулировки.
Значок работающей в автоматическом режиме
Часы-это прекрасный пример значок, который работает на своей собственной. После инъекции, он будет просто идти. Увидеть его в действии
HTML-код
1 |
<img src="clock.svg" class="svg-inject" alt="clock" /> |
Яш
1 |
$('.svg-inject').svgInject(); |
СВГ: часы.СВГ
1 |
<svg version="1.1" class="iconic-clock" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="384px" height="384px" viewBox="0 0 384 384" enable-background="new 0 0 384 384" xml:space="preserve"> |
2 |
<path class="iconic-clock-frame" d="M192,0C85.961,0,0,85.961,0,192s85.961,192,192,192s192-85.961,192-192S298.039,0,192,0zM315.037,315.037c-9.454,9.454-19.809,17.679-30.864,24.609l-14.976-25.939l-10.396,6l14.989,25.964c-23.156,12.363-48.947,19.312-75.792,20.216V336h-12v29.887c-26.845-0.903-52.636-7.854-75.793-20.217l14.989-25.963l-10.393-6l-14.976,25.938c-11.055-6.931-21.41-15.154-30.864-24.608s-17.679-19.809-24.61-30.864l25.939-14.976l-6-10.396l-25.961,14.99C25.966,250.637,19.017,224.846,18.113,198H48v-12H18.113c0.904-26.844,7.853-52.634,20.216-75.791l25.96,14.988l6.004-10.395L44.354,99.827c6.931-11.055,15.156-21.41,24.61-30.864s19.809-17.679,30.864-24.61l14.976,25.939l10.395-6L110.208,38.33C133.365,25.966,159.155,19.017,186,18.113V48h12V18.113c26.846,0.904,52.635,7.853,75.792,20.216l-14.991,25.965l10.395,6l14.978-25.942c11.056,6.931,21.41,15.156,30.865,24.611c9.454,9.454,17.679,19.808,24.608,30.863l-25.94,14.976l6,10.396l25.965-14.99c12.363,23.157,19.312,48.948,20.218,75.792H336v12h29.887c-0.904,26.845-7.853,52.636-20.216,75.792l-25.964-14.989l-6.002,10.396l25.941,14.978C332.715,295.229,324.491,305.583,315.037,315.037z" /> |
3 |
<line class="iconic-clock-hour-hand" id="foo" fill="none" stroke="#000000" stroke-width="18" stroke-miterlimit="10" x1="192" y1="192" x2="192" y2="87.5"/> |
4 |
<line class="iconic-clock-minute-hand" id="iconic-anim-clock-minute-hand" fill="none" stroke="#000000" stroke-width="12" stroke-miterlimit="10" x1="192" y1="192" x2="192" y2="54"/> |
5 |
<circle class="iconic-clock-axis" cx="192" cy="192" r="9"/> |
6 |
<g class="iconic-clock-second-hand" id="iconic-anim-clock-second-hand"> |
7 |
<line class="iconic-clock-second-hand-arm" fill="none" stroke="#D53A1F" stroke-width="4" stroke-miterlimit="10" x1="192" y1="192" x2="192" y2="28.5"/> |
8 |
<circle class="iconic-clock-second-hand-axis" fill="#D53A1F" cx="192" cy="192" r="4.5"/> |
9 |
</g>
|
10 |
<defs>
|
11 |
<animateTransform
|
12 |
type="rotate" |
13 |
fill="remove" |
14 |
restart="always" |
15 |
calcMode="linear" |
16 |
accumulate="none" |
17 |
additive="sum" |
18 |
xlink:href="#iconic-anim-clock-hour-hand" |
19 |
repeatCount="indefinite" |
20 |
dur="43200s" |
21 |
to="360 192 192" |
22 |
from="0 192 192" |
23 |
attributeName="transform" |
24 |
attributeType="xml"> |
25 |
</animateTransform>
|
26 |
|
27 |
<animateTransform
|
28 |
type="rotate" |
29 |
fill="remove" |
30 |
restart="always" |
31 |
calcMode="linear" |
32 |
accumulate="none" |
33 |
additive="sum" |
34 |
xlink:href="#iconic-anim-clock-minute-hand" |
35 |
repeatCount="indefinite" |
36 |
dur="3600s" |
37 |
to="360 192 192" |
38 |
from="0 192 192" |
39 |
attributeName="transform" |
40 |
attributeType="xml"> |
41 |
</animateTransform>
|
42 |
|
43 |
<animateTransform
|
44 |
type="rotate" |
45 |
fill="remove" |
46 |
restart="always" |
47 |
calcMode="linear" |
48 |
accumulate="none" |
49 |
additive="sum" |
50 |
xlink:href="#iconic-anim-clock-second-hand" |
51 |
repeatCount="indefinite" |
52 |
dur="60s" |
53 |
to="360 192 192" |
54 |
from="0 192 192" |
55 |
attributeName="transform" |
56 |
attributeType="xml"> |
57 |
</animateTransform>
|
58 |
</defs>
|
59 |
<script type="text/javascript"> |
60 |
<![CDATA[
|
61 |
var date = new Date;
|
62 |
var seconds = date.getSeconds();
|
63 |
var minutes = date.getMinutes();
|
64 |
var hours = date.getHours();
|
65 |
hours = (hours > 12) ? hours - 12 : hours;
|
66 |
|
67 |
minutes = (minutes * 60) + seconds; |
68 |
hours = (hours * 3600) + minutes; |
69 |
|
70 |
document.querySelector('.iconic-clock-second-hand').setAttribute('transform', 'rotate('+360*(seconds/60)+',192,192)'); |
71 |
document.querySelector('.iconic-clock-minute-hand').setAttribute('transform', 'rotate('+360*(minutes/3600)+',192,192)'); |
72 |
document.querySelector('.iconic-clock-hour-hand').setAttribute('transform', 'rotate('+360*(hours/43200)+',192,192)'); |
73 |
]]> |
74 |
</script>
|
75 |
</svg>
|
Значок ввода на основе
Когда значок откликается на ввод данных, она требует немного больше работы, но основы остаются неизменными. Увидеть его в действии
HTML-код
1 |
<img src="audio-spectrum-analyzer.svg" class="svg-inject" alt="audio spectrum analyzer" /> |
Яш
1 |
$('.svg-inject').svgInject(); |
СВГ: аудио спектр-анализатор.СВГ
1 |
<svg id="audio-spectrum-analyzer" xmlns="http://www.w3.org/2000/svg" xml:space="preserve" height="320px" width="210px" version="1.1" y="0px" x="0px" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 210 320" onclick="toggleAudio()"> |
2 |
<g id="eq-bars" height="320px" width="210px" fill="#010101" transform=""> |
3 |
<rect x="00" y="150" height="20" width="10" /> |
4 |
<rect x="20" y="140" height="40" width="10" /> |
5 |
<rect x="40" y="100" height="120" width="10" /> |
6 |
<rect x="60" y="120" height="80" width="10" /> |
7 |
<rect x="80" y="60" height="200" width="10" /> |
8 |
<rect x="100" y="20" height="280" width="10" /> |
9 |
<rect x="120" y="70" height="180" width="10" /> |
10 |
<rect x="140" y="120" height="80" width="10" /> |
11 |
<rect x="160" y="140" height="40" width="10" /> |
12 |
<rect x="180" y="150" height="20" width="10" /> |
13 |
<rect x="200" y="155" height="10" width="10" /> |
14 |
</g>
|
15 |
|
16 |
<defs>
|
17 |
<style type="text/css"><![CDATA[ |
18 |
svg#audio-spectrum-analyzer {
|
19 |
margin: 0 auto;
|
20 |
}
|
21 |
]]></style> |
22 |
</defs>
|
23 |
|
24 |
<script type="application/javascript"><![CDATA[ |
25 |
var context;
|
26 |
if (typeof AudioContext !== "undefined") {
|
27 |
context = new AudioContext();
|
28 |
}
|
29 |
else if (typeof webkitAudioContext !== "undefined") {
|
30 |
context = new webkitAudioContext();
|
31 |
}
|
32 |
else {
|
33 |
throw new Error('AudioContext not supported. :(');
|
34 |
}
|
35 |
|
36 |
var eqHeight = document.querySelector('svg#audio-spectrum-analyzer > g#eq-bars').getAttribute('height').replace('px', '');
|
37 |
var bars = document.querySelectorAll('svg#audio-spectrum-analyzer rect'); |
38 |
|
39 |
var playing = false; |
40 |
|
41 |
var audioFileUrl = document.querySelector('svg#audio-spectrum-analyzer').getAttribute('data-audiofile'); |
42 |
if (audioFileUrl === undefined) { |
43 |
throw new Error('Audio File not defined'); |
44 |
} |
45 |
|
46 |
var soundSource; |
47 |
var fft; |
48 |
var fftSmoothing = 0.6; |
49 |
var fftMaxValue = 256; |
50 |
var samples = 128; |
51 |
var sampleIntervalID; |
52 |
var ampFactor = 1.25; |
53 |
var numBars = bars.length; |
54 |
var soundBuffer; |
55 |
|
56 |
|
57 |
var request = new XMLHttpRequest(); |
58 |
request.open("GET", audioFileUrl, true); |
59 |
request.responseType = "arraybuffer"; |
60 |
|
61 |
// Our asynchronous callback |
62 |
request.onload = function () { |
63 |
var audioData = request.response; |
64 |
|
65 |
// The Audio Context handles creating source |
66 |
// buffers from raw binary data |
67 |
soundBuffer = context.createBuffer(audioData, true /*make mono*/ ); |
68 |
|
69 |
}; |
70 |
request.send(); |
71 |
|
72 |
function sampleAudio() { |
73 |
var data = new Uint8Array(fft.frequencyBinCount); |
74 |
fft.getByteFrequencyData(data); |
75 |
|
76 |
// Calc bin size to sum freqs into. |
77 |
// Carve off some of the high-end, lower energy bars (+2) |
78 |
var bin_size = Math.floor(data.length / (numBars + 2)); |
79 |
|
80 |
// Sum up and average the samples into their bins |
81 |
for (var i = 0; i < numBars; ++i) { |
82 |
|
83 |
// Sum this bin |
84 |
var sum = 0; |
85 |
for (var j = 0; j < bin_size; ++j) { |
86 |
sum += data[(i * bin_size) + j]; |
87 |
}
|
88 |
|
89 |
// Duck some of the low-end power |
90 |
if (i === 0) { |
91 |
sum = sum * 0.75; |
92 |
}
|
93 |
|
94 |
// Calculate the average frequency of the samples in the bin |
95 |
var average = sum / bin_size; |
96 |
var scaled_average = Math.max(10, ((average / fftMaxValue) * eqHeight) * ampFactor); |
97 |
|
98 |
// Update eq bar height |
99 |
bars[i].setAttribute('height', scaled_average); |
100 |
|
101 |
// Center bar |
102 |
bars[i].setAttribute('y', (eqHeight - scaled_average) / 2); |
103 |
}
|
104 |
}
|
105 |
|
106 |
function playSound() { |
107 |
// create a sound source |
108 |
soundSource = context.createBufferSource(); |
109 |
|
110 |
// Add the buffered data to our object |
111 |
soundSource.buffer = soundBuffer; |
112 |
|
113 |
// Create the FFT |
114 |
fft = context.createAnalyser(); |
115 |
fft.smoothingTimeConstant = fftSmoothing; |
116 |
fft.fftSize = samples; |
117 |
|
118 |
soundSource.connect(fft);
|
119 |
fft.connect(context.destination);
|
120 |
|
121 |
soundSource.noteOn(context.currentTime);
|
122 |
|
123 |
// Start the FFT sampler |
124 |
sampleIntervalID = setInterval(sampleAudio, 30); |
125 |
|
126 |
playing = true; |
127 |
}
|
128 |
|
129 |
function stopSound() { |
130 |
// Stop the FFT sampler |
131 |
clearInterval(sampleIntervalID);
|
132 |
|
133 |
if (soundSource) { |
134 |
soundSource.noteOff(context.currentTime);
|
135 |
}
|
136 |
playing = false; |
137 |
}
|
138 |
|
139 |
var toggleAudio = function () { |
140 |
if (!playing) { |
141 |
playing = true; |
142 |
playSound();
|
143 |
}
|
144 |
else { |
145 |
stopSound();
|
146 |
playing = false; |
147 |
}
|
148 |
}
|
149 |
|
150 |
window.addEventListener('load', function () { |
151 |
window.toggleAudio = toggleAudio; |
152 |
}, false); |
153 |
|
154 |
]]></script> |
155 |
|
156 |
</svg>
|
Добавление движения (вишенка на торте)
Умный значок становится еще лучше с движением. Есть много способов сделать это. В настоящее время мы используем элементы анимации SVG, так как это позволяет значительно функциональность встроена прямо в браузере—меньше кода в SVG. Поддержка еще не восстановилось (мы столкнулись с вопросами в Safari 6), но он становится лучше день ото дня. Увидеть его в действии
HTML-код
1 |
<img src="thermometer.svg" class="svg-inject" alt="thermometer" /> |
2 |
<ul class="menu"> |
3 |
<li><a href="#1">Hot</a></li> |
4 |
<li><a href="#0.66">Warm</a></li> |
5 |
<li><a href="#0.33">Chilly</a></li> |
6 |
<li><a href="#0">Cold</a></li> |
7 |
</ul>
|
Яш
1 |
$('.svg-inject').svgInject(); |
СВГ: термометр.СВГ
1 |
<svg version="1.0" class="iconic-thermometer" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="40px" |
2 |
height="128px" viewBox="0 0 40 128" enable-background="new 0 0 40 128" xml:space="preserve"> |
3 |
<path class="iconic-thermometer-container" d="M20,6c2.757,0,5,2.243,5,5v80.305v3.234l2.701,1.777C31.646,98.912,34,103.279,34,108c0,7.72-6.28,14-14,14 |
4 |
s-14-6.28-14-14c0-4.721,2.354-9.088,6.298-11.684L15,94.539v-3.234V11C15,8.243,17.243,6,20,6 M20,0C13.935,0,9,4.935,9,11
|
5 |
v80.305c-5.501,3.62-9,9.829-9,16.695c0,11.028,8.972,20,20,20c11.028,0,20-8.972,20-20c0-6.865-3.499-13.075-9-16.695V11
|
6 |
C31,4.935,26.065,0,20,0L20,0z"/> |
7 |
<line class="iconic-thermometer-shaft iconic-thermometer-hot" id="iconic-anim-thermometer-shaft" fill="none" stroke="#000000" stroke-width="6" stroke-linecap="round" stroke-miterlimit="10" x1="20" y1="108" x2="20" y2="11" /> |
8 |
<circle class="iconic-thermometer-well iconic-thermometer-hot" cx="20" cy="108" r="12" /> |
9 |
|
10 |
<animate
|
11 |
id="shaft-animate" |
12 |
attributeName= "y2" |
13 |
begin= "indefinite" |
14 |
dur="1s" |
15 |
xlink:href="#iconic-anim-thermometer-shaft" |
16 |
fill="freeze" |
17 |
calcMode="spline" |
18 |
keySplines="0.42 0 0.58 1" |
19 |
keyTimes="0;1" |
20 |
restart="whenNotActive" |
21 |
/>
|
22 |
|
23 |
<script type="text/ecmascript"> |
24 |
<![CDATA[
|
25 |
|
26 |
var shaft = document.querySelector('#iconic-anim-thermometer-shaft');
|
27 |
var well = document.querySelector('.iconic-thermometer-well');
|
28 |
var yOrigin2 = parseFloat(shaft.getAttribute('y2'));
|
29 |
var yOrigin1 = parseFloat(shaft.getAttribute('y1'));
|
30 |
var yPos = yOrigin2;
|
31 |
var tempClass;
|
32 |
|
33 |
window.addEventListener('hashchange', function() {
|
34 |
var hash = window.location.hash.substr(1);
|
35 |
goto(hash);
|
36 |
}, false);
|
37 |
|
38 |
function goto(amount) {
|
39 |
var shaftAnim = document.querySelector('#shaft-animate');
|
40 |
|
41 |
shaft.setAttribute('y2', yPos)
|
42 |
|
43 |
amount = parseFloat(amount)
|
44 |
if( isNaN( amount ) ) return;
|
45 |
|
46 |
if(amount>.9) {
|
47 |
tempClass="iconic-thermometer-hot"; |
48 |
} else if(amount>.5) { |
49 |
tempClass="iconic-thermometer-warm"; |
50 |
} else if(amount>.2) { |
51 |
tempClass="iconic-thermometer-chilly"; |
52 |
} else { |
53 |
tempClass="iconic-thermometer-cold"; |
54 |
} |
55 |
|
56 |
amount = 1 - amount; |
57 |
amount = Math.min(Math.max(0, amount), 1); |
58 |
|
59 |
var ry = ( amount * ( yOrigin1-yOrigin2 ) ) + yOrigin2; |
60 |
|
61 |
/* |
62 |
* Unfortunately, Safari doesn't make life easy on us. We need to remove and re-initialize |
63 |
* the animation element for animations to start from the last end point. |
64 |
*/ |
65 |
var ns = shaftAnim.cloneNode(true); |
66 |
ns.setAttribute( 'from', yPos ) |
67 |
ns.setAttribute( 'to', ry ); |
68 |
|
69 |
shaftAnim.parentNode.replaceChild(ns, shaftAnim); |
70 |
|
71 |
well.setAttribute('class', 'iconic-thermometer-well ' + tempClass); |
72 |
shaft.setAttribute('class', 'iconic-thermometer-shaft ' + tempClass); |
73 |
ns.beginElement(); |
74 |
yPos = ry; |
75 |
|
76 |
} |
77 |
]]> |
78 |
</script>
|
79 |
</svg>
|
Заключение
Иконография имеет важную роль в дизайн интерфейса. Более актуальную информацию на наших иконах, тем более могущественными они становятся. Мы искренне верим, что умная иконография может быть незаменимым инструментом для дизайнеров, чтобы добавить еще один слой смысла в их иконах. Не каждая икона подходит для такого подхода—как и все хорошие вещи, он требует умеренности. Однако, когда используется должным образом, это может быть огромный новый инструмент.
Обратно знаковых на Kickstarter
Цель знаковых для обеспечения новых подходов к иконографии. Есть много более известных, чем просто умные иконки и мы рады поделиться еще одной интересной особенностью с вами на следующей неделе.



Пожалуйста, рассмотреть вопрос о поддержке знаменитого на Kickstarter.