Implement refreshed customiser
Add select indicator Animate selector circle Support for selecting 2 colors Make marker all nice and pretty Show selector numbers Add shadows to selected fields Don't allow reselection of secondary color Fix font baseline issue Avoid some white lines in wheel Add overlap to tiles New SVG filter for shadow Incorporate code into MaterialCustomizer prototype Revert "New SVG filter for shadow" This reverts commit bc23f0d2ba36e6181b527fb87f7b41eb3333cea2. Stronger shadow Refactor init procedure into subroutines First steps of customizer logic recycling Actually call template generation Implement forbidden accents Remove dead code Clean up CSS Make wheel scale Implement new customizer preview Cross browser check Remove slashes Give max-width to customizer Make jshint behavemaster
parent
fc9310d712
commit
786db4d3e9
|
@ -1,175 +1,97 @@
|
|||
.mdl-gen {
|
||||
padding: 24px;
|
||||
display: -webkit-flex;
|
||||
display: flex;
|
||||
-webkit-flex-direction: column;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
body {
|
||||
overflow: scroll !important;
|
||||
}
|
||||
|
||||
.mdl-gen--light-text {
|
||||
color: white;
|
||||
}
|
||||
|
||||
.mdl-gen--dark-text {
|
||||
color: rgb(66,66,66);
|
||||
}
|
||||
|
||||
.mdl-gen-preview {
|
||||
#wheel {
|
||||
position: relative;
|
||||
}
|
||||
#wheel svg {
|
||||
width: 100%;
|
||||
max-width: 600px;
|
||||
height: 350px;
|
||||
margin: 16px auto 16px auto;
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
.mdl-gen-preview__content {
|
||||
padding: 24px;
|
||||
@media (min-width: 840px) {
|
||||
#wheel svg {
|
||||
max-width: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.mdl-gen-color-row {
|
||||
display: -webkit-flex;
|
||||
display: flex;
|
||||
width: 100%;
|
||||
max-width: 800px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.mdl-gen-color {
|
||||
-webkit-flex: 1;
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
height: 80px;
|
||||
cursor: pointer;
|
||||
padding: 8px;
|
||||
box-sizing: border-box;
|
||||
position: relative;
|
||||
text-align: center;
|
||||
-webkit-transition: -webkit-transform 0.2s cubic-bezier(0.4, 0, 0.2, 1),
|
||||
opacity 0.2s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
transition: transform 0.2s cubic-bezier(0.4, 0, 0.2, 1),
|
||||
opacity 0.2s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
}
|
||||
|
||||
.mdl-gen-nocolor {
|
||||
-webkit-flex: 1;
|
||||
flex: 1;
|
||||
height: 80px;
|
||||
padding: 8px;
|
||||
box-sizing: border-box;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.mdl-gen-textinput {
|
||||
display: -webkit-flex;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.mdl-gen-textinput__input {
|
||||
-webkit-flex-grow: 1;
|
||||
-webkit-flex-shrink: 1;
|
||||
flex-grow: 1;
|
||||
flex-shrink: 1;
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
|
||||
.mdl-gen:not(.mdl-gen--selecting-primary) .mdl-gen-color.is-primary {
|
||||
box-shadow: 0 10px 10px 0 rgba(0,0,0,0.19), 0 6px 3px 0 rgba(0,0,0,0.23);
|
||||
z-index: 3;
|
||||
-webkit-transform: scale(1.1);
|
||||
transform: scale(1.1);
|
||||
}
|
||||
|
||||
.mdl-gen:not(.mdl-gen--selecting-primary) .mdl-gen-color.is-primary:after {
|
||||
content: 'Primary';
|
||||
display: block;
|
||||
#wheel .mdl-gen-download {
|
||||
position: absolute;
|
||||
line-height: 100px;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
top: 0;
|
||||
left: 0;
|
||||
font-size: 30px;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
}
|
||||
|
||||
.mdl-gen:not(.mdl-gen--selecting-accent) .mdl-gen-color.is-accent {
|
||||
box-shadow: 0 10px 10px 0 rgba(0,0,0,0.19), 0 6px 3px 0 rgba(0,0,0,0.23);
|
||||
z-index: 4;
|
||||
-webkit-transform: scale(1.1);
|
||||
transform: scale(1.1);
|
||||
#wheel .mdl-gen-download .mdl-button {
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
|
||||
.mdl-gen:not(.mdl-gen--selecting-accent) .mdl-gen-color.is-accent:after {
|
||||
content: 'Accent';
|
||||
display: block;
|
||||
position: absolute;
|
||||
line-height: 100px;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
top: 0;
|
||||
left: 0;
|
||||
font-size: 30px;
|
||||
#wheel g[data-color] {
|
||||
opacity: 1;
|
||||
transition: opacity 0.2s cubic-bezier(0.4, 0.0, 1, 1);
|
||||
}
|
||||
|
||||
.mdl-gen--selecting-accent .mdl-gen-color--muted:not(.is-primary) {
|
||||
pointer-events: none;
|
||||
cursor: auto;
|
||||
color: white;
|
||||
#wheel .selector {
|
||||
opacity: 0;
|
||||
transition: opacity 0.4s cubic-bezier(0.4, 0.0, 1, 1);
|
||||
fill: #BDBDBD;
|
||||
}
|
||||
#wheel .selected .selector {
|
||||
opacity: 1;
|
||||
}
|
||||
#wheel .label {
|
||||
text-anchor: middle;
|
||||
opacity: 0;
|
||||
transition: opacity 0.4s cubic-bezier(0.4, 0.0, 1, 1);
|
||||
fill: white;
|
||||
font-size: 24px;
|
||||
}
|
||||
#wheel .selected--1 .label--1,
|
||||
#wheel .selected--2 .label--2 {
|
||||
opacity: 1;
|
||||
}
|
||||
#wheel svg.hide-nonaccents g[data-color="Blue Grey"]:not(.selected),
|
||||
#wheel svg.hide-nonaccents g[data-color="Brown"]:not(.selected),
|
||||
#wheel svg.hide-nonaccents g[data-color="Grey"]:not(.selected) {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.mdl-gen-download {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
max-width: 800px;
|
||||
margin: 24px auto 0 auto;
|
||||
text-align: right;
|
||||
#wheel .selected {
|
||||
opacity: 1 !important;
|
||||
}
|
||||
|
||||
.mdl-gen-download .mdl-button {
|
||||
.mdl-gen > .mdl-grid {
|
||||
max-width: 1280px;
|
||||
}
|
||||
.mdl-gen__preview {
|
||||
position: relative;
|
||||
height: 350px;
|
||||
}
|
||||
.mdl-gen__preview .mdl-layout__container {
|
||||
height: auto;
|
||||
}
|
||||
.mdl-gen__preview .mdl-layout__content {
|
||||
padding: 32px;
|
||||
background-color: #EFEFEF;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-start;
|
||||
align-items: flex-start;
|
||||
}
|
||||
.mdl-gen__preview .mdl-layout__content .mdl-button {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.mdl-gen-fab {
|
||||
position: absolute !important;
|
||||
right: 24px;
|
||||
.mdl-gen__preview .mdl-layout__content .mdl-button--fab {
|
||||
align-self: flex-end;
|
||||
}
|
||||
|
||||
.mdl-gen--hidden {
|
||||
display: none;
|
||||
.mdl-gen__preview .mdl-layout__content h3 {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
|
||||
@media (max-width: 400px) {
|
||||
.mdl-gen {
|
||||
padding: 16px 16px 24px 16px;
|
||||
}
|
||||
|
||||
.mdl-gen-color {
|
||||
height: 90px;
|
||||
}
|
||||
|
||||
.mdl-gen-preview {
|
||||
order: 4;
|
||||
margin-top: 16px;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.mdl-gen-download {
|
||||
order: 5;
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
.mdl-gen:not(.mdl-gen--selecting-primary) .mdl-gen-color.is-primary:after {
|
||||
content: 'P';
|
||||
line-height: 130px;
|
||||
}
|
||||
|
||||
.mdl-gen:not(.mdl-gen--selecting-accent) .mdl-gen-color.is-accent:after {
|
||||
content: 'A';
|
||||
line-height: 130px;
|
||||
}
|
||||
.mdl-gen__panel {
|
||||
padding: 32px;
|
||||
}
|
||||
.mdl-gen__panel--right {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
justify-content: center;
|
||||
}
|
||||
.mdl-gen__desc strong,
|
||||
.mdl-gen__desc p {
|
||||
display: block;
|
||||
margin-bottom: 32px;
|
||||
color: rgba(0, 0, 0, 0.54);
|
||||
}
|
||||
|
|
|
@ -1,60 +1,30 @@
|
|||
/*global MaterialCustomizer:true*/
|
||||
|
||||
/* exported init */
|
||||
function init() {
|
||||
'use strict';
|
||||
|
||||
new MaterialCustomizer(document.getElementById('mdl-gen-body'));
|
||||
var wheel = document.querySelector('#wheel > svg');
|
||||
new MaterialCustomizer(wheel);
|
||||
}
|
||||
|
||||
function MaterialCustomizer(page) {
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
this.page = page;
|
||||
this.colors = null;
|
||||
this.selectedPrimary = null;
|
||||
this.selectedAccent = null;
|
||||
this.selectingPrimary = true;
|
||||
this.blob = null;
|
||||
|
||||
this.init();
|
||||
}
|
||||
|
||||
MaterialCustomizer.prototype.init = function() {
|
||||
'use strict';
|
||||
|
||||
if (!this.page.getAttribute('initialized')) {
|
||||
this.changeColor();
|
||||
|
||||
this.colors = this.page.querySelectorAll('.mdl-gen-color');
|
||||
|
||||
for (var i = 0; i < this.colors.length; i++) {
|
||||
this.colors[i].addEventListener('click', this.selectColor.bind(this));
|
||||
|
||||
if (this.colors[i].classList.contains('is-primary')) {
|
||||
this.selectedPrimary = i;
|
||||
}
|
||||
|
||||
if (this.colors[i].classList.contains('is-accent')) {
|
||||
this.selectedAccent = i;
|
||||
}
|
||||
}
|
||||
|
||||
document.getElementById('download').addEventListener('click',
|
||||
this.download.bind(this));
|
||||
|
||||
var isSafari = /constructor/i.test(window.HTMLElement);
|
||||
if (isSafari) {
|
||||
document.getElementById('download').innerHTML = 'Get CSS';
|
||||
} else {
|
||||
document.getElementById('warning').classList.add('mdl-gen--hidden');
|
||||
}
|
||||
|
||||
this.page.setAttribute('initialized', true);
|
||||
function parentWrapper(p) {
|
||||
return p.parentElement || p.parentNode;
|
||||
}
|
||||
};
|
||||
|
||||
MaterialCustomizer.prototype.processTemplate = function(response) {
|
||||
'use strict';
|
||||
|
||||
var palettes = [
|
||||
window.MaterialCustomizer = function(wheel) {
|
||||
this.wheel = wheel;
|
||||
this.paletteIndices = ['Red', 'Pink', 'Purple', 'Deep Purple', 'Indigo',
|
||||
'Blue', 'Light Blue', 'Cyan', 'Teal', 'Green',
|
||||
'Light Green', 'Lime', 'Yellow', 'Amber', 'Orange',
|
||||
'Deep Orange', 'Brown', 'Grey', 'Blue Grey'];
|
||||
this.lightnessIndices = ['50', '100', '200', '300', '400',
|
||||
'500', '600', '700', '800', '900',
|
||||
'A100', 'A200', 'A400', 'A700'];
|
||||
this.palettes = [
|
||||
['255,235,238', '255,205,210', '239,154,154', '229,115,115', '239,83,80',
|
||||
'244,67,54', '229,57,53', '211,47,47', '198,40,40', '183,28,28',
|
||||
'255,138,128', '255,82,82', '255,23,68', '213,0,0'],
|
||||
|
@ -109,152 +79,357 @@ MaterialCustomizer.prototype.processTemplate = function(response) {
|
|||
'158,158,158', '117,117,117', '97,97,97', '66,66,66', '33,33,33'],
|
||||
['236,239,241', '207,216,220', '176,190,197', '144,164,174', '120,144,156',
|
||||
'96,125,139', '84,110,122', '69,90,100', '55,71,79', '38,50,56']
|
||||
];
|
||||
];
|
||||
|
||||
var generated = response;
|
||||
|
||||
var primary = palettes[this.selectedPrimary][5];
|
||||
var primaryDark = palettes[this.selectedPrimary][7];
|
||||
var accent = palettes[this.selectedAccent][11];
|
||||
|
||||
generated = this.replaceKeyword(
|
||||
generated, '\\$color-primary-dark', primaryDark);
|
||||
|
||||
generated = this.replaceKeyword(
|
||||
generated, '\\$color-primary-contrast', this.calculateTextColor(primary));
|
||||
|
||||
generated = this.replaceKeyword(
|
||||
generated, '\\$color-accent-contrast', this.calculateTextColor(accent));
|
||||
|
||||
generated = this.replaceKeyword(generated, '\\$color-primary', primary);
|
||||
|
||||
generated = this.replaceKeyword(generated, '\\$color-accent', accent);
|
||||
|
||||
window.generated = generated;
|
||||
return generated;
|
||||
};
|
||||
|
||||
MaterialCustomizer.prototype.calculateChannel = function(component) {
|
||||
'use strict';
|
||||
|
||||
component = component / 255;
|
||||
|
||||
return component < 0.03928 ?
|
||||
component / 12.92 : Math.pow((component + 0.055) / 1.055, 2.4);
|
||||
};
|
||||
|
||||
MaterialCustomizer.prototype.calculateLuminance = function(color) {
|
||||
'use strict';
|
||||
|
||||
var components = color.split(',');
|
||||
var red = this.calculateChannel(parseInt(components[0]));
|
||||
var green = this.calculateChannel(parseInt(components[1]));
|
||||
var blue = this.calculateChannel(parseInt(components[2]));
|
||||
|
||||
return (0.2126 * red) + (0.7152 * green) + (0.0722 * blue);
|
||||
};
|
||||
|
||||
MaterialCustomizer.prototype.calculateContrast =
|
||||
function(background, foreground) {
|
||||
'use strict';
|
||||
|
||||
var backLum = this.calculateLuminance(background) + 0.05;
|
||||
var foreLum = this.calculateLuminance(foreground) + 0.05;
|
||||
|
||||
return Math.max(backLum, foreLum) / Math.min(backLum, foreLum);
|
||||
};
|
||||
|
||||
MaterialCustomizer.prototype.calculateTextColor = function(background) {
|
||||
'use strict';
|
||||
|
||||
var minimumContrast = 3.1;
|
||||
var light = '255,255,255';
|
||||
var dark = '66,66,66';
|
||||
|
||||
// Most colors will be dark, so check light text color first.
|
||||
var whiteContrast = this.calculateContrast(background, light);
|
||||
|
||||
if (whiteContrast >= minimumContrast) {
|
||||
return light;
|
||||
} else {
|
||||
var blackContrast = this.calculateContrast(background, dark);
|
||||
return blackContrast > whiteContrast ? dark : light;
|
||||
}
|
||||
};
|
||||
|
||||
MaterialCustomizer.prototype.replaceKeyword = function(str, key, val) {
|
||||
'use strict';
|
||||
|
||||
return str.replace(new RegExp(key, 'g'), val);
|
||||
};
|
||||
|
||||
MaterialCustomizer.prototype.changeColor = function() {
|
||||
'use strict';
|
||||
|
||||
var oldStyle = document.getElementById('main-stylesheet');
|
||||
|
||||
var req = new XMLHttpRequest();
|
||||
var self = this;
|
||||
req.onload = function() {
|
||||
var style = document.createElement('style');
|
||||
style.id = 'main-stylesheet';
|
||||
style.textContent = self.processTemplate(this.responseText);
|
||||
if (oldStyle && oldStyle.parentNode) {
|
||||
oldStyle.parentNode.removeChild(oldStyle);
|
||||
}
|
||||
document.head.appendChild(style);
|
||||
self.prepareDownload();
|
||||
this.init_();
|
||||
};
|
||||
req.open('get', '../material.min.css.template', true);
|
||||
req.send();
|
||||
};
|
||||
|
||||
MaterialCustomizer.prototype.download = function() {
|
||||
'use strict';
|
||||
MaterialCustomizer.prototype.init_ = function() {
|
||||
this.config = {
|
||||
width: 650, // width of the SVG panel
|
||||
height: 650, // height of the SVG panel
|
||||
r: 250, // radius of the wheel
|
||||
ri: 100, // radius of the inner hole
|
||||
hd: 40, // height of the dark section
|
||||
c: 40, // Distance(center of selector circle, border of wheel)
|
||||
mrs: 0.5, // Percent of available width to use as radius for selector circle
|
||||
alphaIncr: 0.005, // Value to add to alpha to make tiles overlap slightly
|
||||
colors: [
|
||||
'Cyan',
|
||||
'Teal',
|
||||
'Green',
|
||||
'Light Green',
|
||||
'Lime',
|
||||
'Yellow',
|
||||
'Amber',
|
||||
'Orange',
|
||||
'Brown',
|
||||
'Blue Grey',
|
||||
'Grey',
|
||||
'Deep Orange',
|
||||
'Red',
|
||||
'Pink',
|
||||
'Purple',
|
||||
'Deep Purple',
|
||||
'Indigo',
|
||||
'Blue',
|
||||
'Light Blue',
|
||||
]
|
||||
};
|
||||
this.forbiddenAccents = ['Blue Grey', 'Brown', 'Grey'];
|
||||
this.numSelected = 0;
|
||||
|
||||
// Workaround for IE.
|
||||
if (window.navigator.msSaveBlob) {
|
||||
window.navigator.msSaveBlob(this.blob, 'material.min.css');
|
||||
}
|
||||
};
|
||||
this.calculateValues_();
|
||||
this.buildWheel_();
|
||||
|
||||
MaterialCustomizer.prototype.prepareDownload = function() {
|
||||
'use strict';
|
||||
return;
|
||||
};
|
||||
|
||||
var link = document.getElementById('download');
|
||||
var blob = new Blob([window.generated], {type: 'text/css'});
|
||||
this.blob = blob;
|
||||
var url = URL.createObjectURL(blob);
|
||||
link.setAttribute('href', url);
|
||||
link.setAttribute('download', 'material.min.css');
|
||||
};
|
||||
MaterialCustomizer.prototype.calculateValues_ = function() {
|
||||
var config = this.config;
|
||||
// Calculated values
|
||||
// Angle of each piece of the wheel
|
||||
config.alphaDeg = 360.0 / config.colors.length;
|
||||
config.alphaRad = config.alphaDeg * Math.PI / 180;
|
||||
// Radius of selector circle
|
||||
config.rs = (config.c + config.r) * Math.sin(config.alphaRad / 2);
|
||||
config.rs *= config.mrs;
|
||||
// Angle of selector cone
|
||||
config.selectorAlphaRad = Math.atan(config.rs / config.c) * 2;
|
||||
// Angles of cone tangetial point
|
||||
config.gamma1 = config.alphaRad / 2 - config.selectorAlphaRad / 2;
|
||||
config.gamma2 = config.alphaRad / 2 + config.selectorAlphaRad / 2;
|
||||
// Center of selector circle
|
||||
config.cx = (config.c + config.r) * Math.sin(config.alphaRad) / 2;
|
||||
config.cy = -(config.c + config.r) * (1 + Math.cos(config.alphaRad)) / 2;
|
||||
|
||||
MaterialCustomizer.prototype.selectColor = function(event) {
|
||||
'use strict';
|
||||
this.config = config;
|
||||
};
|
||||
|
||||
var index = event.target.getAttribute('index');
|
||||
MaterialCustomizer.prototype.buildWheel_ = function() {
|
||||
var config = this.config;
|
||||
var mainG = this.wheel.querySelector('g.wheel--maing');
|
||||
|
||||
if (!this.selectingPrimary && this.selectedPrimary === index) {
|
||||
this.colors[this.selectedPrimary].classList.remove('is-primary');
|
||||
this.colors[this.selectedAccent].classList.remove('is-accent');
|
||||
this.selectingPrimary = true;
|
||||
this.page.classList.add('mdl-gen--selecting-primary');
|
||||
this.page.classList.remove('mdl-gen--selecting-accent');
|
||||
} else if (this.selectingPrimary) {
|
||||
this.page.classList.remove('mdl-gen--selecting-primary');
|
||||
this.colors[this.selectedPrimary].classList.remove('is-primary');
|
||||
this.selectedPrimary = index;
|
||||
this.colors[index].classList.add('is-primary');
|
||||
this.selectingPrimary = false;
|
||||
this.page.classList.add('mdl-gen--selecting-accent');
|
||||
} else {
|
||||
this.page.classList.remove('mdl-gen--selecting-primary');
|
||||
this.colors[this.selectedAccent].classList.remove('is-accent');
|
||||
this.selectedAccent = index;
|
||||
this.colors[index].classList.add('is-accent');
|
||||
this.selectingPrimary = true;
|
||||
this.page.classList.remove('mdl-gen--selecting-accent');
|
||||
}
|
||||
this.wheel.setAttribute('viewBox', '0 0 ' +
|
||||
this.config.width + ' ' + this.config.height);
|
||||
this.wheel.setAttribute('preserveAspectRatio', 'xMidYMid meet');
|
||||
this.wheel.setAttribute('width', this.config.width);
|
||||
this.wheel.setAttribute('height', this.config.height);
|
||||
|
||||
this.changeColor();
|
||||
};
|
||||
var fieldTpl = this.generateFieldTemplate_();
|
||||
|
||||
var svgNS = 'http://www.w3.org/2000/svg';
|
||||
config.colors.forEach(function(color, idx) {
|
||||
var field = fieldTpl.cloneNode(true);
|
||||
|
||||
for (var i = 1; i <= 2; i++) {
|
||||
var g = document.createElementNS(svgNS, 'g');
|
||||
var label = document.createElementNS(svgNS, 'text');
|
||||
label.setAttribute('class', 'label label--' + i);
|
||||
label.setAttribute('transform',
|
||||
'rotate(' + (-config.alphaDeg * idx) + ')');
|
||||
label.setAttribute('dy', '0.5ex');
|
||||
label.textContent = '' + i;
|
||||
g.appendChild(label);
|
||||
g.setAttribute('transform',
|
||||
'translate(' + config.cx + ',' + config.cy + ')');
|
||||
field.appendChild(g);
|
||||
}
|
||||
field.setAttribute('data-color', color);
|
||||
field.querySelector('.polygons > *:nth-child(1)').style.fill =
|
||||
'rgb(' + this.getColor(color, '500') + ')';
|
||||
field.querySelector('.polygons > *:nth-child(2)').style.fill =
|
||||
'rgb(' + this.getColor(color, '700') + ')';
|
||||
field.querySelector('.polygons').
|
||||
addEventListener('click', this.fieldClicked_.bind(this));
|
||||
field.setAttribute('transform', 'rotate(' + config.alphaDeg * idx + ')');
|
||||
mainG.appendChild(field);
|
||||
}.bind(this));
|
||||
|
||||
mainG.setAttribute('transform',
|
||||
'translate(' + config.width / 2 + ',' + config.height / 2 + ')');
|
||||
};
|
||||
|
||||
MaterialCustomizer.prototype.generateFieldTemplate_ = function() {
|
||||
var svgNS = 'http://www.w3.org/2000/svg';
|
||||
var config = this.config;
|
||||
var fieldTpl = document.createElementNS(svgNS, 'g');
|
||||
var polygons = document.createElementNS(svgNS, 'g');
|
||||
var lightField = document.createElementNS(svgNS, 'polygon');
|
||||
lightField.setAttribute('points', [
|
||||
[
|
||||
config.ri * Math.sin(config.alphaRad + config.alphaIncr),
|
||||
-config.ri * Math.cos(config.alphaRad + config.alphaIncr)
|
||||
].join(','),
|
||||
[
|
||||
config.r * Math.sin(config.alphaRad + config.alphaIncr),
|
||||
-config.r * Math.cos(config.alphaRad + config.alphaIncr)
|
||||
].join(','),
|
||||
[0, -config.r].join(','),
|
||||
[0, -(config.ri + config.hd)].join(','),
|
||||
].join(' '));
|
||||
var darkField = document.createElementNS(svgNS, 'polygon');
|
||||
darkField.setAttribute('points', [
|
||||
[
|
||||
config.ri * Math.sin(config.alphaRad + config.alphaIncr),
|
||||
-config.ri * Math.cos(config.alphaRad + config.alphaIncr)
|
||||
].join(','),
|
||||
[
|
||||
(config.ri + config.hd) * Math.sin(config.alphaRad + config.alphaIncr),
|
||||
-(config.ri + config.hd) * Math.cos(config.alphaRad + config.alphaIncr)
|
||||
].join(','),
|
||||
[0, -(config.ri + config.hd)].join(','),
|
||||
[0, -config.ri].join(','),
|
||||
].join(' '));
|
||||
polygons.appendChild(lightField);
|
||||
polygons.appendChild(darkField);
|
||||
polygons.setAttribute('class', 'polygons');
|
||||
fieldTpl.appendChild(polygons);
|
||||
|
||||
var selector = document.createElementNS(svgNS, 'path');
|
||||
selector.setAttribute('class', 'selector');
|
||||
selector.setAttribute('d',
|
||||
' M ' +
|
||||
(config.r * Math.sin(config.alphaRad) / 2) +
|
||||
' ' +
|
||||
-(config.r * (1 + Math.cos(config.alphaRad)) / 2) +
|
||||
' L ' +
|
||||
(config.cx - config.rs * Math.cos(config.gamma1)) +
|
||||
' ' +
|
||||
(config.cy - config.rs * Math.sin(config.gamma1)) +
|
||||
' A ' +
|
||||
config.rs +
|
||||
' ' +
|
||||
config.rs +
|
||||
' ' +
|
||||
config.alphaDeg +
|
||||
' 1 1 ' +
|
||||
(config.cx + config.rs * Math.cos(config.gamma2)) +
|
||||
' ' +
|
||||
(config.cy + config.rs * Math.sin(config.gamma2)) +
|
||||
' z '
|
||||
);
|
||||
fieldTpl.appendChild(selector);
|
||||
|
||||
return fieldTpl;
|
||||
};
|
||||
|
||||
MaterialCustomizer.prototype.fieldClicked_ = function (ev) {
|
||||
var g = parentWrapper(parentWrapper(ev.target));
|
||||
var selectedColor = g.getAttribute('data-color');
|
||||
// Ignore clicks on already selected fields
|
||||
if ((g.getAttribute('class') || '').indexOf('selected') !== -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.numSelected++;
|
||||
switch (this.numSelected) {
|
||||
case 2:
|
||||
if (this.forbiddenAccents.indexOf(selectedColor) !== -1) {
|
||||
this.numSelected--;
|
||||
return;
|
||||
}
|
||||
this.highlightField_(g);
|
||||
this.wheel.setAttribute('class', '');
|
||||
window.requestAnimationFrame(this.changeColor.bind(this));
|
||||
break;
|
||||
case 3:
|
||||
Array.prototype.forEach.call(
|
||||
this.wheel.querySelector('g.wheel--maing').childNodes,
|
||||
function(f) {
|
||||
f.setAttribute('class', '');
|
||||
f.querySelector('.polygons').setAttribute('filter', '');
|
||||
}
|
||||
);
|
||||
this.numSelected = 1;
|
||||
/* falls through */
|
||||
case 1:
|
||||
this.highlightField_(g);
|
||||
window.requestAnimationFrame(function() {
|
||||
this.wheel.setAttribute('class', 'hide-nonaccents');
|
||||
}.bind(this));
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
MaterialCustomizer.prototype.highlightField_ = function(g) {
|
||||
var parent = parentWrapper(g);
|
||||
|
||||
// Make the current polygon the last child of its parent
|
||||
// so shadows are visible.
|
||||
parent.removeChild(g);
|
||||
parent.appendChild(g);
|
||||
|
||||
// We changed the DOM hierarchy, CSS animations might not show until
|
||||
// DOM has updated internally.
|
||||
var isIE = window.navigator.msPointerEnabled;
|
||||
window.requestAnimationFrame(function() {
|
||||
g.setAttribute('class', 'selected selected--' + this);
|
||||
// FIXME: Shadows in IE10 don't disappear, for now they are disabled
|
||||
if (!isIE) {
|
||||
g.querySelector('.polygons')
|
||||
.setAttribute('filter', 'url(#drop-shadow)');
|
||||
}
|
||||
}.bind(this.numSelected));
|
||||
};
|
||||
|
||||
MaterialCustomizer.prototype.getColor = function(name, lightness) {
|
||||
var r = this.palettes[this.paletteIndices.indexOf(name)];
|
||||
if (!r) {
|
||||
return null;
|
||||
}
|
||||
return r[this.lightnessIndices.indexOf(lightness)];
|
||||
};
|
||||
|
||||
MaterialCustomizer.prototype.processTemplate = function(response) {
|
||||
var generated = response;
|
||||
|
||||
var primaryColor = this.wheel.querySelector('.selected--1')
|
||||
.getAttribute('data-color');
|
||||
var secondaryColor = this.wheel.querySelector('.selected--2')
|
||||
.getAttribute('data-color');
|
||||
|
||||
var primary = this.getColor(primaryColor, '500');
|
||||
var primaryDark = this.getColor(primaryColor, '700');
|
||||
var accent = this.getColor(secondaryColor, 'A200');
|
||||
|
||||
generated = this.replaceKeyword(
|
||||
generated,
|
||||
'\\$color-primary-dark', primaryDark);
|
||||
|
||||
generated = this.replaceKeyword(
|
||||
generated,
|
||||
'\\$color-primary-contrast', this.calculateTextColor(primary));
|
||||
|
||||
generated = this.replaceKeyword(
|
||||
generated,
|
||||
'\\$color-accent-contrast', this.calculateTextColor(accent));
|
||||
|
||||
generated = this.replaceKeyword(generated, '\\$color-primary', primary);
|
||||
|
||||
generated = this.replaceKeyword(generated, '\\$color-accent', accent);
|
||||
|
||||
window.generated = generated;
|
||||
return generated;
|
||||
};
|
||||
|
||||
MaterialCustomizer.prototype.calculateChannel = function(component) {
|
||||
component = component / 255;
|
||||
|
||||
return component < 0.03928 ?
|
||||
component / 12.92 : Math.pow((component + 0.055) / 1.055, 2.4);
|
||||
};
|
||||
|
||||
MaterialCustomizer.prototype.calculateLuminance = function(color) {
|
||||
var components = color.split(',');
|
||||
var red = this.calculateChannel(parseInt(components[0]));
|
||||
var green = this.calculateChannel(parseInt(components[1]));
|
||||
var blue = this.calculateChannel(parseInt(components[2]));
|
||||
|
||||
return (0.2126 * red) + (0.7152 * green) + (0.0722 * blue);
|
||||
};
|
||||
|
||||
MaterialCustomizer.prototype.calculateContrast =
|
||||
function(background, foreground) {
|
||||
var backLum = this.calculateLuminance(background) + 0.05;
|
||||
var foreLum = this.calculateLuminance(foreground) + 0.05;
|
||||
|
||||
return Math.max(backLum, foreLum) / Math.min(backLum, foreLum);
|
||||
};
|
||||
|
||||
MaterialCustomizer.prototype.calculateTextColor = function(background) {
|
||||
var minimumContrast = 3.1;
|
||||
var light = '255,255,255';
|
||||
var dark = '66,66,66';
|
||||
|
||||
// Most colors will be dark, so check light text color first.
|
||||
var whiteContrast = this.calculateContrast(background, light);
|
||||
|
||||
if (whiteContrast >= minimumContrast) {
|
||||
return light;
|
||||
} else {
|
||||
var blackContrast = this.calculateContrast(background, dark);
|
||||
return blackContrast > whiteContrast ? dark : light;
|
||||
}
|
||||
};
|
||||
|
||||
MaterialCustomizer.prototype.replaceKeyword = function(str, key, val) {
|
||||
return str.replace(new RegExp(key, 'g'), val);
|
||||
};
|
||||
|
||||
MaterialCustomizer.prototype.changeColor = function() {
|
||||
var oldStyle = document.getElementById('main-stylesheet');
|
||||
|
||||
var req = new XMLHttpRequest();
|
||||
var self = this;
|
||||
req.onload = function() {
|
||||
var style = document.createElement('style');
|
||||
style.id = 'main-stylesheet';
|
||||
style.textContent = self.processTemplate(this.responseText);
|
||||
if (oldStyle && oldStyle.parentNode) {
|
||||
oldStyle.parentNode.removeChild(oldStyle);
|
||||
}
|
||||
document.head.appendChild(style);
|
||||
self.prepareDownload();
|
||||
};
|
||||
req.open('get', '../material.min.css.template', true);
|
||||
req.send();
|
||||
};
|
||||
|
||||
MaterialCustomizer.prototype.download = function() {
|
||||
// Workaround for IE.
|
||||
if (window.navigator.msSaveBlob) {
|
||||
window.navigator.msSaveBlob(this.blob, 'material.min.css');
|
||||
}
|
||||
};
|
||||
|
||||
MaterialCustomizer.prototype.prepareDownload = function() {
|
||||
var link = document.getElementById('download');
|
||||
var blob = new Blob([window.generated], {type: 'text/css'});
|
||||
this.blob = blob;
|
||||
var url = URL.createObjectURL(blob);
|
||||
link.setAttribute('href', url);
|
||||
link.setAttribute('download', 'material.min.css');
|
||||
};
|
||||
|
||||
})();
|
||||
|
|
|
@ -4,10 +4,4 @@ title: Customize & Download
|
|||
bodyclass: customize
|
||||
include_prefix: ../
|
||||
---
|
||||
|
||||
|
||||
Pick a primary and accent color for your theme. When you're
|
||||
ready, click the `Download CSS` button to get your
|
||||
customised version of Material Design Lite.
|
||||
|
||||
<iframe src="../embedded_customizer/index.html" height="800px"/>
|
||||
|
|
|
@ -2,10 +2,6 @@
|
|||
|
||||
{% block content %}
|
||||
|
||||
<span class="docs-text-styling">
|
||||
<h1>{{page.title}}</h1>
|
||||
|
||||
{{content|safe}}
|
||||
</span>
|
||||
|
||||
{% endblock %}
|
||||
|
|
|
@ -13,105 +13,73 @@
|
|||
|
||||
<link rel="stylesheet" href="{{page.include_prefix}}material.min.css" id="main-stylesheet">
|
||||
<link rel="stylesheet" href="{{page.include_prefix}}assets/customizer.css">
|
||||
<script src="{{page.include_prefix}}assets/customizer.js"></script>
|
||||
</head>
|
||||
<body class="mdl-gen mdl-color--grey-200" onload="init();" id="mdl-gen-body">
|
||||
<div class="mdl-gen-color-row">
|
||||
<div class="mdl-gen-color mdl-color--red mdl-gen--light-text" index="0">Red</div>
|
||||
<div class="mdl-gen-color mdl-color--pink mdl-gen--light-text is-accent" index="1">Pink</div>
|
||||
<div class="mdl-gen-color mdl-color--purple mdl-gen--light-text" index="2">Purple</div>
|
||||
<div class="mdl-gen-color mdl-color--deep-purple mdl-gen--light-text" index="3">Deep Purple</div>
|
||||
<div class="mdl-gen-color mdl-color--indigo mdl-gen--light-text is-primary" index="4">Indigo</div>
|
||||
</div>
|
||||
<div class="mdl-gen-color-row">
|
||||
<div class="mdl-gen-color mdl-color--blue mdl-gen--light-text" index="5">Blue</div>
|
||||
<div class="mdl-gen-color mdl-color--light-blue mdl-gen--dark-text" index="6">Light Blue</div>
|
||||
<div class="mdl-gen-color mdl-color--cyan mdl-gen--dark-text" index="7">Cyan</div>
|
||||
<div class="mdl-gen-color mdl-color--teal mdl-gen--light-text" index="8">Teal</div>
|
||||
<div class="mdl-gen-color mdl-color--green mdl-gen--dark-text" index="9">Green</div>
|
||||
</div>
|
||||
<div class="mdl-gen-preview mdl-shadow--3dp">
|
||||
<div class="mdl-layout mdl-js-layout mdl-layout--fixed-header">
|
||||
<header class="mdl-layout__header">
|
||||
<svg class="mdl-layout-icon" width="411px" height="406px" viewBox="0 0 411 406" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g transform="translate(-51.000000, -54.000000)" fill="currentColor">
|
||||
<path d="M253.532807,381.627 L205.905373,459.1512 L75.2987939,365.2047 L137.208794,290.0547 L51,265.8834 L100.217083,116.7498 L183.176447,150.0543 L176.402456,54 L337.901996,54 L331.203531,149.0202 L409.306732,116.4465 L461.243662,265.7448 L371.760263,290.7036 L429.826513,365.6628 L302.333596,459.2493 L253.532807,381.627 Z M222.176831,106.2 L291.098533,106.2 L282.729084,224.796484 L383.182429,182.939488 L404.947387,245.446521 L297.795289,275.304737 L368.114228,365.995226 L313.701833,405.9 L252.592681,308.789934 L192.876775,405.9 L137.348587,365.995226 L212.130699,275.304737 L105.539492,245.446521 L126.18666,182.939488 L230.548276,224.796484 L222.176831,106.2 Z"></path>
|
||||
</g>
|
||||
</g>
|
||||
<body class="mdl-gen" onload="init();">
|
||||
<div class="mdl-grid">
|
||||
<div class="mdl-gen__panel mdl-gen__panel--left mdl-cell mdl-cell--6-col-desktop mdl-cell--8-col">
|
||||
<div id="wheel">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<defs>
|
||||
<filter id="drop-shadow">
|
||||
<feGaussianBlur in="SourceAlpha" stdDeviation="3.2"/>
|
||||
<feOffset dx="0" dy="0" result="offsetblur"/>
|
||||
<feFlood flood-color="rgba(0,0,0,1)"/>
|
||||
<feComposite in2="offsetblur" operator="in"/>
|
||||
<feMerge>
|
||||
<feMergeNode/>
|
||||
<feMergeNode in="SourceGraphic"/>
|
||||
</feMerge>
|
||||
</filter>
|
||||
</defs>
|
||||
<g class="wheel--maing"></g>
|
||||
</svg>
|
||||
<div class="mdl-layout__header-row">
|
||||
<span class="mdl-layout-title">Theme Preview</span>
|
||||
<div class="mdl-layout-spacer"></div>
|
||||
<div class="mdl-textfield mdl-js-textfield mdl-textfield--expandable mdl-textfield--floating-label mdl-textfield--align-right">
|
||||
<label class="mdl-button mdl-js-button mdl-button--icon" for="sample-expclean">
|
||||
<i class="material-icons">search</i>
|
||||
</label>
|
||||
<div class="mdl-textfield__expandable-holder">
|
||||
<input class="mdl-textfield__input" type="text" name="sample" id="sample-expclean" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="mdl-gen-download">
|
||||
<a href="#" id="download" class="mdl-button mdl-js-button mdl-button--raised mdl-js-ripple-effect mdl-button--fab"><i class="material-icons">file_download</i></a>
|
||||
</div>
|
||||
</header>
|
||||
<div class="mdl-layout__drawer">
|
||||
<span class="mdl-layout-title">Theme Preview</span>
|
||||
<nav class="mdl-navigation">
|
||||
<a class="mdl-navigation__link" href="#">Some</a>
|
||||
<a class="mdl-navigation__link" href="#">Links</a>
|
||||
<a class="mdl-navigation__link" href="#">Here</a>
|
||||
</nav>
|
||||
</div>
|
||||
<main class="mdl-gen-preview__content mdl-layout__content">
|
||||
<p>
|
||||
<div class="mdl-gen-textinput">
|
||||
<div class="mdl-gen-textinput__input">
|
||||
<div class="mdl-textfield mdl-textfield--full-width mdl-js-textfield">
|
||||
<input class="mdl-textfield__input" type="text" id="sample1" />
|
||||
<label class="mdl-textfield__label" for="sample1">Type Something...</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mdl-gen__panel--right mdl-gen__panel mdl-cell mdl-cell--6-col-desktop mdl-cell--8-col">
|
||||
<div class="mdl-gen__desc">
|
||||
<strong>Custom CSS theme builder</strong>
|
||||
<p>Click on the color wheel to choose a primary (1) and accent (2) color to preview the theme below. When you’ve selected a color combination you like, download the CSS by clicking the white button in the middle.</p>
|
||||
</div>
|
||||
<div class="mdl-gen__preview">
|
||||
<div class="mdl-layout mdl-js-layout mdl-layout--fixed-header">
|
||||
<header class="mdl-layout__header">
|
||||
<svg class="mdl-layout-icon" width="411px" height="406px" viewBox="0 0 411 406" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g transform="translate(-51.000000, -54.000000)" fill="currentColor">
|
||||
<path d="M253.532807,381.627 L205.905373,459.1512 L75.2987939,365.2047 L137.208794,290.0547 L51,265.8834 L100.217083,116.7498 L183.176447,150.0543 L176.402456,54 L337.901996,54 L331.203531,149.0202 L409.306732,116.4465 L461.243662,265.7448 L371.760263,290.7036 L429.826513,365.6628 L302.333596,459.2493 L253.532807,381.627 Z M222.176831,106.2 L291.098533,106.2 L282.729084,224.796484 L383.182429,182.939488 L404.947387,245.446521 L297.795289,275.304737 L368.114228,365.995226 L313.701833,405.9 L252.592681,308.789934 L192.876775,405.9 L137.348587,365.995226 L212.130699,275.304737 L105.539492,245.446521 L126.18666,182.939488 L230.548276,224.796484 L222.176831,106.2 Z"></path>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
<div class="mdl-layout__header-row">
|
||||
<span class="mdl-layout-title">Theme Preview</span>
|
||||
</div>
|
||||
<button class="mdl-button mdl-js-button mdl-button--raised mdl-button--colored mdl-js-ripple-effect">Button</button>
|
||||
</header>
|
||||
<div class="mdl-layout__drawer">
|
||||
<span class="mdl-layout-title">Theme Preview</span>
|
||||
<nav class="mdl-navigation">
|
||||
<a class="mdl-navigation__link" href="#">Some</a>
|
||||
<a class="mdl-navigation__link" href="#">Links</a>
|
||||
<a class="mdl-navigation__link" href="#">Here</a>
|
||||
</nav>
|
||||
</div>
|
||||
</p>
|
||||
<br>
|
||||
<p>
|
||||
<input class="mdl-slider mdl-js-slider" type="range"
|
||||
min="0" max="100" value="50" tabindex="0"/>
|
||||
</p>
|
||||
<br>
|
||||
<p>
|
||||
<button class="mdl-gen-fab mdl-button mdl-js-button mdl-button--fab mdl-button--colored mdl-js-ripple-effect">
|
||||
<i class="material-icons">add</i>
|
||||
</button>
|
||||
</p>
|
||||
|
||||
</main>
|
||||
<main class="mdl-layout__content">
|
||||
<h3>Try it out</h3>
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet.
|
||||
</p>
|
||||
<button class="mdl-button mdl-button--colored mdl-button--raised">BUTTON</button>
|
||||
<button class="mdl-button mdl-js-button mdl-button--fab mdl-button--colored mdl-js-ripple-effect">
|
||||
<i class="material-icons">email</i>
|
||||
</button>
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mdl-gen-color-row">
|
||||
<div class="mdl-gen-color mdl-color--light-green mdl-gen--dark-text" index="10">Light Green</div>
|
||||
<div class="mdl-gen-color mdl-color--lime mdl-gen--dark-text" index="11">Lime</div>
|
||||
<div class="mdl-gen-color mdl-color--yellow mdl-gen--dark-text" index="12">Yellow</div>
|
||||
<div class="mdl-gen-color mdl-color--amber mdl-gen--dark-text" index="13">Amber</div>
|
||||
<div class="mdl-gen-color mdl-color--orange mdl-gen--dark-text" index="14">Orange</div>
|
||||
</div>
|
||||
<div class="mdl-gen-color-row">
|
||||
<div class="mdl-gen-color mdl-color--deep-orange mdl-gen--light-text" index="15">Deep Orange</div>
|
||||
<div class="mdl-gen-color mdl-gen-color--muted mdl-color--brown mdl-gen--light-text" index="16">Brown</div>
|
||||
<div class="mdl-gen-nocolor"></div>
|
||||
<div class="mdl-gen-color mdl-gen-color--muted mdl-color--grey mdl-gen--dark-text" index="17">Grey</div>
|
||||
<div class="mdl-gen-color mdl-gen-color--muted mdl-color--blue-grey mdl-gen--light-text" index="18">Blue Grey</div>
|
||||
</div>
|
||||
|
||||
<div class="mdl-gen-download">
|
||||
<a href="" id="download" class="mdl-button mdl-js-button mdl-button--raised mdl-js-ripple-effect">Download CSS</a>
|
||||
</div>
|
||||
<div id="warning">
|
||||
<div class="mdl-tooltip mdl-tooltip--large" for="download">
|
||||
Due to browser issues, clicking this may open a page that you will need to manually save.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="{{page.include_prefix}}assets/customizer.js"></script>
|
||||
<script src="{{page.include_prefix}}material.min.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
Loading…
Reference in New Issue