vue实现多种形式的色卡选择效果代码
代码语言:html
所属分类:选择器
代码描述:vue实现多种形式的色卡选择效果代码
下面为部分代码预览,完整代码请点击下载或在bfwstudio webide中打开
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <link type="text/css" rel="stylesheet" href="//repo.bfw.wiki/bfwrepo/css/reset.min.css"> <style> @charset "UTF-8"; :root { --c-black: #212121; --c-white: #fff; --c-background: var(--c-black); --c-background-contrast: var(--c-white); --s-toggler-button-height: 4rem; --s-bezel: 2rem; --font: "Inter", sans-serif; font-size: calc(.6rem + .4vw); } @supports (font-variation-settings: normal) { :root { --font: "Inter var", sans-serif; } } :root { font-family: var(--font); font-feature-settings: "dlig" 0, "numr" 0, "dnom" 0, "tnum", "case" 0, "zero" 0, "frac", "sups" 0, "subs" 0, "cpsp" 0, "salt" 0, "ss01", "ss02" 0, "cv01" 0, "cv02" 0, "cv03" 0, "cv04" 0, "cv05" 0, "cv06" 0, "cv07" 0, "cv08" 0, "cv09" 0, "cv10" 0, "calt", "liga", "kern"; } .palette { transition: background-color 300ms 440ms ease-out; } a { color: currentColor; font-weight: 700; text-decoration: none; } a:hover { text-decoration: underline; } a[href*="//"]:not([href*="color.pizza"])::after { display: inline-block; content: "↓"; font-size: 0.8em; font-weight: 300; transform: translate(10%, -25%) rotate(-135deg); transition: 300ms transform cubic-bezier(0.8, 0.3, 0.25, 1.75); } a[href*="//"]:not([href*="color.pizza"]):hover::after { transform: translate(20%, -35%) rotate(-135deg) scale(0.7); } .palette--header { z-index: 1; position: fixed; color: var(--c-background-contrast); padding: 3.5rem 4rem; width: 40%; } .palette--header h1 { font-size: 6rem; font-weight: 700; text-shadow: 0 0 0 transparent; transition: 600ms text-shadow; } .palette--header h1:hover { text-shadow: var(--text-shadow); } .palette--header h2 { font-size: 2.5rem; font-weight: 100; margin-top: 0.75rem; } .button-row { display: flex; width: 100%; } .button-row > input[type=color] { width: calc(100% - .25em); margin-left: 0.7em; border-radius: 1em; overflow: hidden; cursor: pointer; } .button { display: inline-block; border: none; background: transparent; font-weight: 700; font-size: 1.2rem; color: var(--c-background); padding: 0; text-decoration: underline; cursor: pointer; margin-bottom: 0.25em; } .button + .button { margin-left: 0.75em; } .button--color { position: relative; } .button--color i { display: inline-block; width: 0.75em; height: 0.75em; border-radius: 50%; box-shadow: 0 0 0 2px var(--c-black); } .button--color strong { display: none; position: absolute; left: 1em; } .settings-wrap { z-index: 2; position: fixed; height: var(--s-toggler-button-height); min-width: 10.75rem; right: var(--s-bezel); top: calc(2.3 * var(--s-bezel)); transition: min-width 337ms cubic-bezier(0.13, 1, 0.4, 1) 800ms, height 337ms cubic-bezier(0.13, 1, 0.4, 1) 500ms, color 200ms linear 300ms, background-color 200ms linear 300ms; } .palette---visible-settings .settings-wrap { min-width: 24rem; height: calc(100% - calc(3 * var(--s-bezel))); box-shadow: 0 0 0 0 var(--c-white); color: var(--c-black); transition: min-width 337ms cubic-bezier(0.13, 1, 0.4, 1), height 337ms cubic-bezier(0.13, 1, 0.4, 1) 220ms, color 200ms linear 300ms, background-color 200ms linear 300ms; } .settings-toggler { z-index: 2; position: absolute; right: 0; top: 0; left: 0; width: 100%; text-align: center; height: 0; padding: var(--s-toggler-button-height)0 0; font-weight: 200; border: none; background: none; font-size: 1.5rem; border-radius: 0; color: var(--c-background-contrast); cursor: pointer; outline: none; } .palette---visible-settings .settings-toggler:hover { box-shadow: none; } .settings-toggler__label { z-index: 1; text-align: left; position: absolute; display: block; right: 2.7rem; top: 50%; transform: translate(0, -50%); margin-top: -0.12ex; padding-left: var(--s-bezel); width: 8rem; transition: 400ms width 300ms; } .palette---visible-settings .settings-toggler__label { width: 19.3rem; } .settings-toggler__label .dotsnav { position: absolute; top: 0; right: -1.5rem; fill: var(--c-background-contrast); width: 2rem; height: 2rem; } .settings-toggler__label .dots { transition: 222ms transform 100ms; } .palette---visible-settings .settings-toggler__label .dots { fill: var(--c-black); transition: 222ms transform 0ms; } .palette---visible-settings .settings-toggler__label .dots--bottom { transform: translate(12px, 12px) rotate(45deg) translate(-12px, -12px); } .palette---visible-settings .settings-toggler__label .dots--top { transform: translate(12px, 12px) rotate(-45deg) translate(-12px, -12px); } .settings-toggler::after { content: ""; position: absolute; top: 0; right: 0; bottom: 0; left: 0; background: hotpink; transform-origin: 100% 50%; transform: scaleX(0); background-color: var(--c-white); } .palette---visible-settings .settings-toggler::after { transform: scaleX(1); transition: transform 337ms cubic-bezier(0.13, 1, 0.4, 1) 200ms; } .palette---visible-settings .settings-toggler { color: currentColor; } .settings { opacity: 0; pointer-events: none; position: absolute; right: 0; top: var(--s-toggler-button-height,0); bottom: 0; left: 0; font-size: 1.2rem; box-sizing: border-box; padding: 0 var(--s-bezel); color: currentColor; transition: opacity 200ms linear 500ms; overflow: hidden; } .palette---visible-settings .settings { opacity: 1; pointer-events: auto; overflow-y: auto; } .settings > * { transform: translateY(-50%) translateX(50%) scale(0.5); opacity: 0; transition: opacity 350ms cubic-bezier(0.88, 0, 0, 1), transform 450ms cubic-bezier(0.88, 0, 0, 1); background-color: var(--c-white); margin: 0 calc(var(--s-bezel) * -1); padding: 0 var(--s-bezel); /*backdrop-filter: blur(5px); background-color: rgba(255,255,255,.7); */ } .settings > *:last-child { padding-bottom: var(--s-bezel); } .palette---visible-settings .settings > * { transform: scale(1); opacity: 1; } .palette---visible-settings .settings > *:nth-child(1) { transition-delay: 200ms, 175ms; } .palette---visible-settings .settings > *:nth-child(2) { transition-delay: 250ms, 250ms; } .palette---visible-settings .settings > *:nth-child(3) { transition-delay: 300ms, 325ms; } .palette---visible-settings .settings > *:nth-child(4) { transition-delay: 350ms, 400ms; } .palette---visible-settings .settings > *:nth-child(5) { transition-delay: 400ms, 475ms; } .palette---visible-settings .settings > *:nth-child(6) { transition-delay: 450ms, 550ms; } .palette---visible-settings .settings > *:nth-child(7) { transition-delay: 500ms, 625ms; } .palette---visible-settings .settings > *:nth-child(8) { transition-delay: 550ms, 700ms; } .palette---visible-settings .settings > *:nth-child(9) { transition-delay: 600ms, 775ms; } .palette---visible-settings .settings > *:nth-child(10) { transition-delay: 650ms, 850ms; } .palette---visible-settings .settings > *:nth-child(11) { transition-delay: 700ms, 925ms; } .palette---visible-settings .settings > *:nth-child(12) { transition-delay: 750ms, 1000ms; } .palette---visible-settings .settings > *:nth-child(13) { transition-delay: 800ms, 1075ms; } .palette---visible-settings .settings > *:nth-child(14) { transition-delay: 850ms, 1150ms; } .palette---visible-settings .settings > *:nth-child(15) { transition-delay: 900ms, 1225ms; } .setting { display: flex; align-items: center; flex-wrap: wrap; padding-bottom: 1.2em; } .setting button { border: none; background: transparent; font-weight: 700; font-size: 1.2rem; color: var(--c-black); padding: 0; text-decoration: underline; } .setting__label { text-transform: capitalize; flex-grow: 1; flex-basis: 1 1 80%; font-weight: 700; font-size: 0.8em; margin-bottom: 0.5em; margin-top: 0.75em; } .setting__input { width: 70%; } .setting__value { font-size: 0.6em; text-align: right; flex: 1 1 20%; } .setting__colors { width: 100%; } .setting__colors > button { margin-top: 0.5rem; } .setting__color { color: currentColor; width: 100%; display: flex; flex-wrap: wrap; font-size: 0.75rem; margin-bottom: 0.5rem; } .setting__color input, .setting__color button { color: currentColor; border: none; box-sizing: border-box; padding: 0; } .setting__color input { flex: 0 0 calc(100% - 1.25rem); } .setting__color button { flex: 0 0 1.25rem; background: none; cursor: pointer; font-size: 1rem; color: currentColor; } input { background-color: transparent; } input[type=range], input[type=color] { -webkit-appearance: none; width: 100%; } input[type=color]::-webkit-color-swatch-wrapper { padding: 0; } input[type=color]::-webkit-color-swatch { border: none; } input[type=color] { border: 2px solid var(--c-black); padding: 0; height: 1.1rem; } input[type=range] { margin: 0; } input[type=range]:focus { outline: none; } input[type=range]:focus::-webkit-slider-thumb { -webkit-clip-path: polygon(100% 0%, 0% 0%, 50% 100%, 50% 100%); clip-path: polygon(100% 0%, 0% 0%, 50% 100%, 50% 100%); } input[type=range]::-webkit-slider-runnable-track { width: 100%; height: 1rem; cursor: pointer; animate: 0.2s; background: transparent; color: var(--c-black); border-radius: 0; border: solid var(--c-black); border-width: 0 0 1px; } input[type=range]::-webkit-slider-thumb { border: 2px solid transparent; height: 0.75rem; width: 0.5rem; border-radius: 0; background: var(--c-black); cursor: pointer; -webkit-appearance: none; margin-top: 0.25rem; transition: 150ms background-color, 200ms clip-path, 200ms -webkit-clip-path; -webkit-clip-path: polygon(0 0, 100% 0, 100% 100%, 0% 100%); clip-path: polygon(0 0, 100% 0, 100% 100%, 0% 100%); } input[type=range]::-moz-range-track { width: 100%; height: 1rem; cursor: pointer; animate: 0.2s; background: transparent; color: var(--c-black); border-radius: 0; border: solid var(--c-black); border-width: 0 0 1px; } input[type=range]::-moz-range-thumb { border: 2px solid transparent; height: 0.75rem; width: 0.5rem; border-radius: 0; background: var(--c-black); cursor: pointer; -webkit-appearance: none; margin-top: 0.25rem; transition: 150ms background-color, 200ms clip-path, 200ms -webkit-clip-path; clip-path: polygon(0 0, 100% 0, 100% 100%, 0% 100%); } input[type=range]::-ms-track { width: 100%; height: 1rem; cursor: pointer; animate: 0.2s; background: transparent; color: var(--c-black); border-radius: 0; border: solid var(--c-black); border-width: 0 0 1px; } input[type=range]::-ms-fill-lower { background: currentColor; border: none; border-radius: 100%; } input[type=range]::-ms-fill-upper { background: currentColor; border-radius: 100%; box-shadow: none; } input[type=range]::-ms-thumb { border: 2px solid transparent; height: 0.75rem; width: 0.5rem; border-radius: 0; background: var(--c-black); cursor: pointer; -webkit-appearance: none; margin-top: 0.25rem; transition: 150ms background-color, 200ms clip-path, 200ms -webkit-clip-path; clip-path: polygon(0 0, 100% 0, 100% 100%, 0% 100%); } select, .multiselect { color: var(--c-black); font-family: var(--font); width: 100%; box-sizing: border-box; font-size: 1rem; -webkit-appearance: none; border: 0; box-shadow: 0 1px 0 0 currentColor; border-radius: 0; padding: 0.25rem 1rem 0.25rem 0rem; background-color: transparent; transition: 150ms background-color; } select:focus, .multiselect:focus { outline: none; background-color: transparent; } .multiselect { padding: 0.25rem 0; } .multiselect__content-wrapper { background: var(--white); overflow: auto; } .multiselect__content { overflow: hidden; width: 100%; padding: 0.5rem 0; } .multiselect__option { position: relative; display: block; padding: 0.25rem 0; cursor: pointer; overflow: hidden; } .multiselect__single { display: block; } .option__title, .option__preview { display: block; } .option__title { position: relative; z-index: 1; font-size: 0.9em; padding: 0.25rem 0; text-shadow: 1px 1px #fff, -1px -1px #fff, -1px 1px #fff, 1px -1px #fff; } .option__preview { position: absolute; bottom: 0; left: 0; right: 0; height: 100%; transform-origin: 100% 50%; transform: scaleY(0.2) scaleX(0.4); transition: 400ms transform cubic-bezier(0.3, 0.7, 0, 1) 400ms; } .multiselect__option:hover .option__preview { transform: scaleY(1) scaleX(0.4); } .select-wrap { width: 100%; position: relative; } .select-wrap::after { pointer-events: none; position: absolute; top: 0; right: 0; content: "↓"; font-size: 0.9rem; line-height: 1.6; } .blade { position: absolute; cursor: pointer; display: flex; flex-direction: column; height: 40vh; width: 10vh; top: -40vh; left: 0; box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.1), 0 0 15px rgba(0, 0, 0, 0.1); transform: translate3d(0, 0, 0) rotate(0deg); transform-origin: 1vh 39vh; border-radius: 0.5vh; overflow: hidden; transition: 200ms 200ms transform ease-in-out; transition: 200ms 200ms transform cubic-bezier(0.25, 0.25, 0.275, 1.265); } .blade__label, .blade__value { display: flex; flex-direction: column; justify-content: center; padding: 1vh; line-height: 1.2; } .blade__label { color: var(--c-white); font-size: 0.8rem; padding-top: 0.75vh; font-weight: 300; line-height: 1.5; } .blade__label--inner { display: block; overflow: hidden; text-overflow: ellipsis; } .blade__value { font-size: calc(0.6rem + .3vmin); line-height: 1.5; font-weight: 500; line-height: 0.75; text-transform: uppercase; background: var(--c-white); color: currentColor; } .view { position: relative; height: 100vh; overflow: auto; margin: var(--s-bezel); } .view--wheel { z-index: 1; margin-top: 0; overflow: hidden; } .fan { position: absolute; top: 50%; left: 50%; perspective: 600px; transition: 666ms transform cubic-bezier(0.88, 0, 0, 1); transition: 666ms transform cubic-bezier(0.4, 0, 0.25, 1); } .view--cube { position: relative; overflow: hidden; } .view--cube .select-wrap { z-index: 1; position: absolute; bottom: 1rem; left: 1rem; width: auto; min-width: 4rem; background-position: 90% 50%; color: var(--c-background-contrast); } .view--cube .select-wrap select { text-transform: uppercase; } .view--cube .select-wrap:focus { color: var(--c-background); } .view--radialgradient { overflow: hidden; } .radialgradient { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); width: 75vmin; height: 75vmin; background: #212121; border-radius: 100%; cursor: pointer; } .view--list { display: flex; align-items: center; justify-content: space-around; } .color-list { min-width: 60%; } .color-list__item { display: flex; justify-content: space-between; position: relative; padding: 0.5rem 1rem; transition: transform 300ms cubic-bezier(0.7, 0.3, 0, 1); will-change: transform; } .color-list__item > * { color: var(--c-black); opacity: 0.5; transition: transform 300ms cubic-bezier(0.7, 0.3, 0, 1); } .color-list__item:hover { transform: scaleY(2) scaleX(1.05); z-index: 2; } .color-list__item:hover > * { opacity: 1; transform: scaleY(0.5) scaleX(0.95); } .color-list__item::after { z-index: -1; opacity: 0.5; content: ""; position: absolute; left: 0; right: 0; bottom: 0; top: 0; box-shadow: 0 0 2rem rgba(0, 0, 0, 0.3), 0 0 3rem currentColor; } .color-watch { display: flex; flex-direction: column; width: 14.8%; max-width: 9rem; flex: 0 0 14.8%; margin: 0.5rem; perspective: 600px; border-bottom: 2.7vmin solid #fff; } .color-watch__wrap { padding-top: 100%; } .color-watch__inner { position: absolute; left: 50%; top: 50%; width: 14rem; height: 17rem; transform: translate(-50%, -50%); } .color-watch__inner::after { display: none; border-radius: 50%; content: ""; box-shadow: 0 0 5rem currentColor; position: absolute; top: 0; right: 0; left: 0; bottom: 0; } .color-watch__swatch { position: relative; padding-top: 100%; z-index: 1; } .color-watch__swatch__shade { position: absolute; top: 0; right: 0; bottom: 0; left: 0; transform-origin: 50% 100%; background: currentColor; } .color-watch__swatch__shade::after { content: ""; position: absolute; top: 0; right: 0; bottom: 0; left: 0; } .color-watch__label { position: absolute; bottom: 0; left: 0; right: 0; z-index: 2; flex-grow: 1; background: #fff; padding: 0.6rem 0.75rem; color: #212121; transform-origin: 50% 0; box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.05); } .color-watch__title { font-weight: 700; font-size: 1.2em; margin-bottom: 0.25em; text-transform: capitalize; } .color-watch__subtitle { font-size: 0.85em; text-transform: uppercase; } .color-watch__title, .color-watch__subtitle { display: block; transform-origin: 50% 100%; } .color-watch { overflow: hidden; box-shadow: 0 0 15px rgba(0, 0, 0, 0.1); } .color-watch__inner { pointer-events: none; opacity: 0; transition: opacity 133.2ms linear 199.8ms; } .color-watch__label { transform: scaleY(0); transition: 133.2ms transform cubic-bezier(0.7, 0.3, 0, 1); transition-delay: 199.8ms; } .color-watch__title, .color-watch__subtitle { opacity: 0; transform: scaleY(0); transition: 66.6ms opacity linear, 133.2ms transform cubic-bezier(0.7, 0.3, 0, 1); } .color-watch__swatch { transform: translate3d(0, 150%, 0); transition: 443.556ms transform cubic-bezier(0.8, 0.3, 0.25, 1.75); will-change: transform; transform-origin: 50% 0; } .color-watch__swatch__shade:nth-child(1) { transform: scaleY(0); transition-delay: 133.2ms; opacity: 0.3; } .color-watch__swatch__shade:nth-child(2) { transform: scaleY(0); transition-delay: 66.6ms; opacity: 0.5; } .color-watch__swatch__shade:nth-child(3) { transform: scaleY(0); transition-delay: 0ms; } .color-watch:hover { overflow: initial; z-index: 1; } .color-watch:hover .color-watch__inner { opacity: 1; transition: opacity 66.6ms linear; overflow: hidden; } .color-watch:hover .color-watch__label { transform: scaleY(1); transition: 133.2ms transform cubic-bezier(0.7, 0.3, 0, 1); transition-delay: 133.2ms; } .color-watch:hover .color-watch__title, .color-watch:hover .color-watch__subtitle { opacity: 1; transform: scaleY(1); transition: 66.6ms opacity linear, 133.2ms transform cubic-bezier(0.7, 0.3, 0, 1); transition-delay: 266.4ms; } .color-watch:hover .color-watch__subtitle { transition-delay: 299.7ms; } .color-watch:hover .color-watch__swatch { transform: translate3d(0, 0, 0); transition: 376.956ms transform cubic-bezier(0.8, 0.3, 0.25, 1); will-change: transform; transform-origin: 50% 0; } .color-watch:hover .color-watch__swatch__shade { transition: 443.556ms transform cubic-bezier(0.7, 0.3, 0, 1); transform: scaleY(1); } .color-watch:hover .color-watch__swatch__shade:nth-child(1) { transition-delay: 0ms; } .color-watch:hover .color-watch__swatch__shade:nth-child(2) { transition-delay: 66.6ms; } .color-watch:hover .color-watch__swatch__shade:nth-child(3) { transition-delay: 133.2ms; } .view--watches { overflow: hidden; display: flex; align-items: center; justify-content: space-around; } .view__watch__list { display: flex; width: 80%; flex-wrap: wrap; align-items: center; } .view--pie { overflow: hidden; cursor: pointer; } .view--pie svg { position: absolute; top: 50%; left: 50%; } .pie { transition: 400ms transform cubic-bezier(0.7, 0.3, 0, 1); transform: translate(-50%, -50%) rotate(-90deg) scale3d(0.8, 0.8, 0.8); } .pie--zoomed { transform: translate(-50%, -50%) rotate(-90deg) scale3d(5, 5, 5); } .pie__wrap { position: absolute; top: 0; left: 0; right: 0; bottom: 0; } .view--rows__list { position: absolute; height: 100%; width: 100%; top: 0; left: 0; display: flex; align-items: stretch; box-sizing: border-box; overflow: hidden; } .color__row { position: relative; flex-grow: 1; transition: flex-grow 444ms cubic-bezier(0.7, 0.3, 0, 1); overflow: hidden; margin: 0 -1px; } .color__row:hover { flex-grow: 4; } .color__row:hover .color__row__label { transform: translateY(0%); } .color__row:hover .color__row__title, .color__row:hover .color__row__subtitle { opacity: 1; transform: scaleY(1); } .color__row:hover .color__row__title { transition-delay: 233.1ms; } .color__row:hover .color__row__subtitle { transition-delay: 266.4ms; } .color__row__label { position: absolute; bottom: 0; left: 0; right: 0; z-index: 2; flex-grow: 1; background: #fff; padding: 0.6rem 0.75rem; color: #212121; transform-origin: 50% 0; box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.05); white-space: nowrap; transform: translateY(100%); transition: 200ms transform cubic-bezier(0.7, 0.3, 0, 1) 300ms; } .color__row__title { font-weight: 700; font-size: 1.2em; margin-bottom: 0.25em; text-transform: uppercase; } .color__row__subtitle { font-size: 0.85em; text-transform: capitalize; } .color__row__title, .color__row__subtitle { display: block; transform-origin: 50% 100%; opacity: 0; transform: scaleY(0); transition: 66.6ms opacity linear, 133.2ms transform cubic-bezier(0.7, 0.3, 0, 1); transition-delay: 266.4ms; } .view--export { display: none; } .view--export textarea { position: absolute; left: 0; top: 0; width: 100%; height: 100%; background: transparent; border: none; color: var(--c-background); font-size: 0.8rem; } .view--itten { height: auto; min-height: 100vh; display: flex; align-items: center; justify-content: space-around; flex-wrap: wrap; } .view--itten button { color: var(--c-background-contrast); background: none; font-size: 1.2rem; border: none; padding: 0.5em 0.5em; cursor: pointer; outline: none; } .itten__list { display: flex; align-items: center; justify-content: space-around; flex-wrap: wrap; padding-bottom: 2rem; } .color__itten { position: relative; width: 10rem; height: 10rem; } .itten--ball .color__itten { border-radius: 100%; background-image: linear-gradient(-45deg, transparent, currentColor); overflow: hidden; transition: 200ms border-radius linear; } .itten--ball .color__itten::after { opacity: 0; content: ""; position: absolute; top: 0; left: 0; right: 0; bottom: 0; background-image: linear-gradient(-45deg, transparent 50%, currentColor calc(50% + 1px)); } .itten--ball .color__itten:hover { background-image: none; } .itten--ball .color__itten:hover::after { opacity: 1; transform: scale(1.01); } .itten--cube .color__itten { box-shadow: inset 0 0 0 4rem currentColor; transition: 200ms box-shadow cubic-bezier(0.5, 0, 0.15, 1), 333ms border-radius cubic-bezier(0.7, 0.3, 0, 1); } .itten--cube .color__itten:hover { box-shadow: inset 0 0 10rem 0 currentColor, 0 0 6rem currentColor; } .itten--triangle .color__itten { -webkit-clip-path: polygon(50% 0, 0 100%, 100% 100%); clip-path: polygon(50% 0, 0 100%, 100% 100%); background-image: linear-gradient(0deg, transparent 20%, currentColor); } .itten--triangle .color__itten:hover { background-image: linear-gradient(34deg, transparent 40%, currentColor calc(40% + 1px)); } .itten__item { flex: 0 0 10rem; margin: 5%; } .ittem-vues { position: absolute; left: 1rem; bottom: 1rem; } .itten__name { display: block; display: none; color: var(--c-background-contrast); font-size: 0.8em; text-align: center; line-height: 1.4; padding-top: 1em; } .itten__name em { font-size: 0.75em; } /* .expand { &::after { animation: 500ms expand cubic-bezier(0, 0.8, 0.6, 1.8); animation-fill-mode: forwards; transition: 100ms opacity linear 400ms; transform: rotate(180deg); will-change: clip-path, opacity; } &:hover::after { animation: 500ms expand-out cubic-bezier(0, .8, .6, 1); animation-fill-mode: forwards; transition: 200ms opacity linear; transform: rotate(0deg); } } //animation-timing-function: cubic-bezier(.7, .3, 0, 1); @keyframes expand { 0% { clip-path: polygon(45% 45%, 85% 45%, 70% 70%, 45% 85%); } 20% { clip-path: polygon(30% 30%, 70% 30%, 70% 70%, 30% 70%); } 30% { clip-path: polygon(30% 30%, 80% 20%, 70% 70%, 30% 70%); } 45% { clip-path: polygon(18% 18%, 100% 0, 80% 80%, 30% 70%); } 55% { clip-path: polygon(0% 0%, 100% 0, 100% 100%, 20% 80%); } 90% { clip-path: polygon(0% 0%, 100% 0, 100% 100%, 0% 100%); } 100% { clip-path: polygon(0 0, 100% 0, 100% 100%, 0 100%); } } @keyframes expand-out { 0% { clip-path: polygon(0 0, 100% 0, 100% 100%, 0 100%); } 20% { clip-path: polygon(0 0, 100% 0, 100% 100%, 0 100%); } 30% { clip-path: polygon(0% 0%, 100% 0, 100% 100%, 0% 100%); } 40% { clip-path: polygon(0% 0%, 100% 0, 100% 100%, 20% 80%); } 50% { clip-path: polygon(18% 18%, 100% 0, 80% 80%, 30% 70%); } 70% { clip-path: polygon(20% 20%, 80% 20%, 70% 70%, 30% 70%); } 80% { clip-path: polygon(30% 30%, 70% 30%, 70% 70%, 30% 70%); } 100% { clip-path: polygon(30% 30%, 70% 30%, 70% 70%, 30% 70%); } } */ .view--text { position: relative; z-index: 1; height: auto; background: var(--c-background); color: var(--c-background-contrast); padding: 3.5em 2rem; line-height: 1.4; } .view--text h1, .view--text h2 { font-weight: 700; } .view--text h1 { font-size: 4rem; } .view--text h2 { font-size: 1.8rem; margin-top: 1.25em; } .view--text p { font-weight: 300; margin-top: 0.8em; font-size: 1.2rem; max-width: 40rem; } .view--text p strong { font-weight: 400; } .text { display: flex; justify-content: space-between; } .text__sample { padding-right: 2rem; } .text__contrast { font-size: 0.5em; } .text__customizer { text-align: right; flex: 0 0 25%; } .text__customizer .text-customizer-bg__button, .text__customizer .text-customizer__button { cursor: pointer; border: 0.25rem solid currentColor; font-size: 2rem; margin-bottom: 0.2em; margin-right: 0.2em; } .text__customizer .text-customizer-bg__button { background: currentColor; } .text__customizer .text-customizer__button { background: none; } .footer { position: relative; z-index: 1; padding: calc(2 * var(--s-bezel)) calc(2 * var(--s-bezel)) var(--s-bezel); font-size: 1.2rem; line-height: 1.4; color: var(--c-background); background-color: var(--c-background-contrast); font-weight: 300; } .footer h2 { font-size: 1em; font-weight: 700; margin-bottom: 1.5em; } .footer__title { position: relative; font-size: 2em; font-weight: 700; margin-bottom: 1.25em; } .footer__title sub { font-size: 0.4em; font-weight: 300; transform: translateY(10%); margin-left: 0.25em; } .footer__subline { display: block; margin-top: 2em; font-weight: 700; } .footer__subline a { position: relative; } .footer__subline a::after { opacity: 0; } .footer__subline a svg { position: absolute; bottom: 50%; transform: translate(-2rem, 50%); } .footer__list { font-size: 1em; display: flex; } .footer__section { flex: 0 0 calc(33.33% - 2em); } .footer__section + .footer__section { margin-left: 2em; } .footer__section li { margin-top: 0.5em; } .elastiq-logo { display: inline-block; width: 12rem; height: auto; } .elastiq-logo .font { fill: currentColor; } .elastiq-logo .elastiq { fill: none; stroke: var(--c-background); stroke-linecap: round; stroke-linejoin: round; stroke-width: 11.4px; } .view--abstract { overflow: hidden; } .view--abstract::after { content: ""; position: absolute; background: linear-gradient(180deg, transparent, var(--c-background) 60%); bottom: 0; left: 0; right: 0; height: 50%; } .view--abstract div { position: absolute; top: 75%; left: 50%; width: 75%; height: 75%; background: linear-gradient(45deg, var(--gradient)); transform: translate(-50%, -50%) rotate(30deg) scale(0.8); } .view--abstract div::before { opacity: 0.7; content: ""; position: absolute; top: -4rem; right: 0; bottom: 0; left: -4rem; background: linear-gradient(45deg, var(--gradient)); filter: blur(4rem); } .view--abstract div::after { content: ""; position: absolute; top: 1rem; right: 0; bottom: 0; left: 1rem; background: radial-gradient(circle at 0% 0%, transparent 20%, var(--c-background) 70%); transform: scale(1.2); filter: blur(1rem); } .view--fattext { padding: 3rem 2rem; min-height: 100vh; height: auto; position: relative; z-index: 1; font-size: 4rem; font-weight: 700; text-align: left; background: var(--c-background); } .view--fattext h3 { text-align: left; line-height: 1.5; } </style> </head> <body> <div id="palette" class="palette" v-bind:style="{'background-color': bgcolor, '--c-background': bgcolor, '--c-background-contrast': bgcolorcontrast}" v-bind:class="{'palette---visible-settings': settingsVisible}"> <hhead v-bind:color="bgcolor" v-bind:colors="currentColors"></hhead> <div class="settings-wrap"> <button class="settings-toggler" v-on:click="toggleSettings"> <span class="settings-toggler__label"> customize <svg viewBox="0 0 24 24" class="dotsnav" xmlns="http://www.w3.org/2000/svg"> <g class="dots dots--bottom" transform="translate(12 12) rotate(0) translate(-12 -12)"> <circle cx="12" cy="6" r="1.5" /> <circle cx="12" cy="12" r="1.5" /> <circle cx="12" cy="18" r="1.5" /> </g> <g class="dots dots--top" transform="translate(12 12) rotate(0) translate(-12 -12)"> <circle cx="12" cy="6" r="1.5" /> <circle cx="12" cy="18" r="1.5" /> </g> </svg> </span> </button> <div class="settings"> <label class="setting"> <h3 class="setting__label">Method</h3> <div class="select-wrap"> <vue-multiselect :max-height="1200" :value="currentSpace" @select="selectCurrentSpace" v-bind:selected="name === currentSpace" :options="names" :searchable="false" :close-on-select="true" :show-labels="false" placeholder="Pick a space"> <template slot="option" slot-scope="{ option }"> <strong class="option__title">{{ option }}</strong> <span class="option__preview" v-bind:style="{'background': 'linear-gradient(to left,' + colorsBySpace(option).join(',') + ')' }"></span> <ol> </ol> </template> </vue-multiselect> <!--select @change="selectCurrentSpace"> <option v-for="name in names" @value="name" v-bind:selected="name === currentSpace">{{name}}</option> </select--> </div> </label> <div> <setting label="Colors" v-bind:value="colorCount"> <input type="range" v-bind:min="minColorCount" v-bind:max="maxColorCount" v-model="colorCount" step="1"> </setting> </div> <div> <setting multifield="true" label="Background Color"> <div class="button-row"> <button class="button button--color" v-on:click="bgcolor = '#212121'"><i style="background: #212121"></i><strong>Black</strong></button><button class="button button--color" v-on:click="bgcolor = '#5e5e5e'"><i style="background: #5e5e5e"></i><strong>Grey</strong></button><button class="button button--color" v-on:click="bgcolor = '#fffcec'"><i style="background: #fffcec"></i><strong>Ivory</strong></button><button class="button button--color" v-on:click="bgcolor = '#fcfcfc'"><i style="background: #fcfcfc"></i><strong>White</strong></button> <input type="color" v-model="bgcolor" /> </div> </setting> </div> <div v-for="prop in space.attr"> <setting v-if="(space.attr.find(e => (e.name === 'gradient space')) && prop.name != space.attr.find(e => (e.name === 'gradient space'))['value']) || !space.attr.find(e => (e.name === 'gradient space'))" v-bind:label="prop.name" multifield="prop.type === 'colorlist'" v-bind:value="typeof(prop.value) != 'array' && typeof(prop.value) != 'object' ? prop.value : null" > <input v-if="prop.type === 'range'" type="range" v-bind:min="prop.min" v-bind:max="prop.max" v-model="prop.value" v-bind:step="prop.step" /> <input v-if="prop.type === 'color'" type="color" v-model="prop.value" /> <div v-if="prop.type === 'list'" class="select-wrap"> <select v-model="prop.value"> <option v-for="val in prop.values" v-bind:value="val">{{val}}</option> <select /> </div> <colorlistinput v-if="prop.type === 'colorlist'" v-bind:colors="prop.value" v-on:change="(colors) => { prop.value = [...colors] }" /> </setting> </div> </div> </div> <colorwheel v-on:setcolor="setColorByIndex" v-bind:colors="currentColors" v-bind:names="colorNames"></colorwheel> <colorgradient v-bind:colors="currentColors" v-bind:names="colorNames"></colorgradient> <colorball v-bind:colors="currentColors" v-bind:names="colorNames"></colorball> <colorlist v-bind:colors="currentColors" v-bind:names="colorNames"></colorlist> <cube v-bind:bgcolorcontrast="bgcolorcontrast" v-bind:colors="currentColors" v-bind:names="colorNames"></cube> <!--colorabstract v-bind:bgcolorcontrast="bgcolorcontrast" v-bind:colors="currentColors" v-bind:names="colorNames"></colorabstract--> <colorwatches v-on:setcolor="setColorByIndex" v-bind:colors="currentColors" v-bind:names="colorNames"></colorwatches> <colorpie v-bind:colors="currentColors" v-bind:names="colorNames"></colorpie> <fattext v-bind:colors="currentColors" v-bind:names="colorNames"></fattext> <colorrows v-bind:colors="currentColors" v-bind:names="colorNames"></colorrows> <itten v-bind:colors="currentColors" v-bind:names="colorNames"></itten> <colortext v-bind:colors="currentColors" v-bind:bgcolorcontrast="bgcolorcontrast" v-bind:bgcolor="bgcolor"> <article> <p> WCAG 2 level AA requires a contrast ratio of at least 4.5:1 for normal text and 3:1 for large text, and a contrast ratio of at least 3:1 for graphics and user interface components (such as form input borders). Level AAA requires a contrast ratio of at least 7:1 for normal text and 4.5:1 for large text. Large text is defined either as bold and at least 14 point (typically 18.66px) or regular and at least 18 point (typically 24px). </p> <p> Large text is defined as 14 point (typically 18.66px) and bold or larger, or 18 point (typically 24px) or larger. </p> </article> <article> <h2>Brewer</h2> <p> Color schemes based on the research of <a href="https://twitter.com/ColorBrewer">Dr. Cynthia Brewer</a>, are excellent for qualitative, sequential, diverging <strong>data and map visualisation</strong>. <a href="http://www.personal.psu.edu/cab38/ColorBrewer/ColorBrewer_updates.html">Read more</a> </p> </article> <article> <h2>Interpolate</h2> <p> Gradually mixing one color with another to create pleasing gradients. Changing the color space changes the way those colors are mixed together and will greatly affect the result. </p> </article> <article> <h2>CIE L*a*b*</h2> <p> CIELAB was designed to be perceptually uniform with respect to human color vision, meaning that the same amount of numerical change in these values corresponds to about the same amount of visually perceived change. This is especially visible when the gradient space is set to lightness. <a href="https://en.wikipedia.org/wiki/CIELAB_color_space">Read more</a> </p> </article> <article> <h2>RGB</h2> <p> Is a mix of red green and blue as natively produced by the screen you are reading this on. By choosing the gradient space ‘red’, the color red will gradually be mixed to the amount of ‘blue’ and ‘green’ that you have chosen on the corresponding sliders. </p> </article> <article> <h2>Cubehelix</h2> <p> Those colors are generated by a helix (spiral) traversing the RGB color space. Looking at the 3-D view should explain this visually pretty nicely. Cubehelix was designed to provide a color mapping that would degrade gracefully to grayscale without losing information. Also meaning that there is a clear hierarchy in lightness. <a href="https://www.mrao.cam.ac.uk/~dag/CUBEHELIX/">Read more</a> </p> </article> <article> <h2>HSL</h2> <p> HSL stands for Hue Saturation and light. The palette is generated by rotating on the hue parameter. </p> </article> <article> <h2>HULuv & HPLuv</h2> <p> The input in <strong>HULuv</strong> and <strong>HPLuv</strong> is the same as in HSL. The generated colors are corrected for perceptual uniformity using the findings from CIE. On top of that HPLuv aims to correct the chroma, meaning that not all the colors from the RGB space can be represented. <a href="http://www.hsluv.org/comparison/">Read more</a> </p> </article> </colortext> <aside class="footer"> <h1 class="footer__title">color.pizza<sub>{{version}}</sub></h1> <div class="footer__list"> <aside class="footer__section"> <h2>Color Temple</h2> <p> Over the years I have coded multiple tools to help me understand and play with ideas sourrounding color. In an effort to make my findings accessible to a broader audience and to simply have fun, I designed and developed this tool. — <a href="https://twitter.com/meodai">David</a> </p> </aside> <aside class="footer__section"> <h2>Technology</h2> <ul> <li><a href="https://vuejs.org/">vue.js</a> general application</li> <li><a href="https://github.com/gka/chroma.js">chroma.js</a> color math heavy lifting</li> <li><a href="http://www.hsluv.org/">HSL<sub>uv</sub></a> HSL but with corrected chroma and luminosity</li> <li><a href="https://github.com/meodai/color-names">color-names</a> API providing the 17530 color-names used</li> <li><a href="https://threejs.org/">three.js</a> used for the 3d color space</li> <li><a href="https://rsms.me/inter/">Inter typeface family</a> perfectly hinted font</li> </ul> </aside> <aside class="footer__section"> <h2>Thanks</h2> <ul> <li><a href="http://www.florianschulz.info/portfolio/">Florian Schulz</a> for letting me bounce my ideas and endless discussions about design systems</li> <li><a href="http://www.daviddarx.com/">David Darx</a> for the visual direction and being an awesome person</li> <li><a href="http://z43.network/">z43.network</a> and all the designers, illustrators and pixelartists involved in my hallway tests: <a href="https://twitter.com/rilemtwit">Richard Lems</a>, <a href="https://twitter.com/ENDESGA">ENDESGA</a></li> </ul> </aside> </div> <strong class="footer__subline">brought to you by <a href="http://elastiq.ch/"><ellogo v-bind:colors="currentColors" /></a></strong> <exportjson v-bind:names="colorNames"></exportjson> </aside> </div> <script type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/vue@2.6.1.js"></script> <script type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/chroma.min.js"></script> <script type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/hsluv.min.js"></script> <script type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/vuex.min.js"></script> <script type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/three.110.js"></script> <script type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/vue-multiselect.2.1.0.js"></script> <link type="text/css" rel="stylesheet" href="//repo.bfw.wiki/bfwrepo/css/vue-multiselect.2.1.0.css"> <script type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/OrbitControls.min.js"></script> <script> /** * # todo: * ## [ ] Status / Benefit:Complxity / "Description" * [ ] 3:1 "Think about patreon / monetizing / sponsoring" * [ ] 3:1 "Make a SVG/Image export" * [x] 3:1 "Add Close ICON to customize pannel" * [ ] 3:1 "Add a section with simple text. (Possibly the color space descriptions" * [x] 3:1 "Make colors clickable (Change Context color on click)" * [ ] 3:2 "Add some kind of nav (dots or something for the different views)" * [ ] 3:3 "Save settings" * [ ] 3:3 "FF & Safari testing" * [X] 2:1 "Add HWB" * [ ] 2:1 "Add CIELCHuv" * [x] 2:1 "More padding in pannel" * [x] 2:1 "Have a default background color per mode" * [x] 2:1 "Write a short paragraph for each color space" * [ ] 2:2 "overlay preview gradients over sliders" * [ ] 2:2 "Only render views when they are close the the scrollable area" * [ ] 2:2 "Add stats (metrics: I what to know if people scroll, and what they interact with)" * [ ] 2:2 "Make values inputable on sliders (text input)" * [ ] 2:2 "Add starting color" * [x] 2:3 "Make it possible to add colors manually (black / white)" * [ ] 2:3 "Make a draggable view to be able to compose colors manually" https://github.com/catc/displace * [x] 1:1 "Automatically close the sidepannel when scrolling a bit" * [ ] 1:1 "Collabsible Footer" * [x] 1:1 "Add HCL color space (no need is the same as LCH)" * [ ] 1:1 "Make UI hideable" * [ ] 1:1 "Replace chroma.js with culori" * [~] 1:2 "Font weight / leight height tuning" * [x] 1:2 "Wheel over font" **/ Vue.component('vue-multiselect', window.VueMultiselect.default); const contrastMinimums = { aa: 4.5, aaLarge: 3, aaa: 7, aaaLarge: 4.5 }; const ypbprToRGB = (y, pb, pr, kb = 0.0722, kr = 0.2126) => { const r = y + 2 * pr * (1 - kr); const b = y + 2 * pb * (1 - kb); const g = (y - kr * r - kb * b) / (1 - kr - kb); return [r * 255, g * 255, b * 255]; }; const ucsToxyz = function (ucs) { const u = ucs[0], v = ucs[1], w = ucs[2]; return [ 1.5 * u, v, 1.5 * u - 3 * v + 2 * w]; }; function ryb2rgb(color) { var r = color[0], y = color[1], b = color[2]; // Remove the whiteness from the color. var w = Math.min(r, y, b); r -= w; y -= w; b -= w; var my = Math.max(r, y, b); // Get the green out of the yellow and blue var g = Math.min(y, b); y -= g; b -= g; if (b && g) { b *= 2.0; g *= 2.0; } // Redistribute the remaining yellow. r += y; g += y; // Normalize to values. var mg = Math.max(r, g, b); if (mg) { var n = my / mg; r *= n; g *= n; b *= n; } // Add the white back in. r += w; g += w; b += w; // And return back the ryb typed accordingly. return [r, g, b]; } const xyzToRGB = function (_xyz, white = [100, 100, 100]) { const x = _xyz[0] / white[0], y = _xyz[1] / white[1], z = _xyz[2] / white[2]; // assume sRGB // http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html let r = x * 3.240969941904521 + y * -1.537383177570093 + z * -0.498610760293; let g = x * -0.96924363628087 + y * 1.87596750150772 + z * 0.041555057407175; let b = x * 0.055630079696993 + y * -0.20397695888897 + z * 1.056971514242878; r = r > 0.0031308 ? 1.055 * Math.pow(r, 1.0 / 2.4) - 0.055: r = r * 12.92; g = g > 0.0031308 ? 1.055 * Math.pow(g, 1.0 / 2.4) - 0.055: g = g * 12.92; b = b > 0.0031308 ? 1.055 * Math.pow(b, 1.0 / 2.4) - 0.055: b = b * 12.92; r = Math.min(Math.max(0, r), 1); g = Math.min(Math.max(0, g), 1); b = Math.min(Math.max(0, b), 1); return [r * 255, g * 255, b * 255]; }; const colorSpaces = [{ name: ['EDG-RGB-Hue'], hasStart: false, bg: '#212121', attr: [{ name: 'stops', type: 'colorlist', value: [ '#72ffd7', '#f03b50', '#0f0b50'] }, { name: 'edg-mix', min: .2, max: .8, step: .001, value: .5, type: 'range' }, { name: 'space-a', value: 'rgb', values: ['lab', 'hsl', 'hsv', 'hsi', 'lch', 'rgb', 'lrgb'], type: 'list' }, { name: 'space-b', value: 'hsv', values: ['lab', 'hsl', 'hsv', 'hsi', 'lch', 'rgb', 'lrgb'], type: 'list' }], palette: (mode, attrs, options = { correctLightness: false, colors: 32 }) => { let scaleRGB = chroma.scale(attrs['stops'].value).mode(attrs['space-a'].value).colors(options.colors); let scaleHSV = chroma.scale(attrs['stops'].value).mode(attrs['space-b'].value).colors(options.colors); /*let padding = parseFloat(attrs.padding.value); if (padding !== 0) { scale.padding(padding); }*/ return scaleRGB.map((color, i) => { return chroma.mix(color, scaleHSV[i], attrs['edg-mix'].value, 'rgb').hex(); }); } }, { name: ['HSL', 'HSLuv', 'HPLuv'], bg: '#212121', hasStart: true, attr: [{ name: 'gradient space', value: 'hue', values: ['light', 'saturation', 'hue'], type: 'list', excludeValue: true }, { name: 'hue', min: 0, max: 360, step: 1, value: 0, type: 'range' }, { name: 'saturation', min: 0, max: 1, step: 0.01, value: 1, type: 'range' }, { name: 'light', min: 0, max: 1, step: 0.01, value: .8, type: 'range' }], palette: (mode, attrs, options = { correctLightness: false, colors: 32 }) => { let colors = []; let space = ['hue', 'saturation', 'light']; let iterate = attrs['gradient space'].value; for (let i = 0; i < options.colors; i++) { let color; let componentPercent = i / options.colors; if (mode.toLowerCase() === 'hsluv') { color = hsluv.hsluvToHex([ iterate === space[0] ? componentPercent * 360: parseFloat(attrs[space[0]].value), iterate === space[1] ? componentPercent * 100: parseFloat(attrs[space[1]].value) * 100, iterate === space[2] ? componentPercent * 100: parseFloat(attrs[space[2]].value) * 100]); } else if (mode.toLowerCase() === 'hpluv') { color = hsluv.hpluvToHex([ iterate === space[0] ? componentPercent * 360: parseFloat(attrs[space[0]].value), iterate === space[1] ? componentPercent * 100: parseFloat(attrs[space[1]].value) * 100, iterate === space[2] ? componentPercent * 100: parseFloat(attrs[space[2]].value) * 100]); } else { color = chroma.hsl([ iterate === space[0] ? componentPercent * 360: parseFloat(attrs[space[0]].value), iterate === space[1] ? componentPercent: parseFloat(attrs[space[1]].value), iterate === space[2] ? componentPercent: parseFloat(attrs[space[2]].value)]). get('hex'); } colors.push(color); } return colors; } }, { name: ['HWB'], bg: '#212121', hasStart: true, attr: [{ name: 'gradient space', value: 'blackness', values: ['hue', 'blackness', 'whiteness'], type: 'list', excludeValue: true }, { name: 'hue', min: 0, max: 360, step: 1, value: 24, type: 'range' }, { name: 'whiteness', min: 0, max: 1, step: 0.01, value: 0.7, type: 'range' }, { name: 'blackness', min: 0, max: 1, step: 0.01, value: .8, type: 'range' }], palette: (mode, attrs, options = { correctLightness: false, colors: 32 }) => { let colors = []; let space = ['hue', 'whiteness', 'blackness']; let iterate = attrs['gradient space'].value; for (let i = 0; i < options.colors; i++) { let color; let componentPercent = i / options.colors; let h = iterate === space[0] ? componentPercent * 360: parseFloat(attrs[space[0]].value); let b = iterate === space[1] ? componentPercent: parseFloat(attrs[space[1]].value); let w = iterate === space[2] ? componentPercent: parseFloat(attrs[space[2]].value); let [hsvH, hsvS, hsvV] = [ h, b === 1 ? 0: 1 - w / (1 - b) * 1, 1 - w]; color = chroma.hsv([ hsvH, hsvS, hsvV]). get('hex'); colors.push(color); } return colors; } }, { name: ['XYZ'], bg: '#212121', hasStart: true, attr: [{ name: 'gradient space', value: 'y', values: ['x', 'y', 'z'], type: 'list', excludeValue: true }, { name: 'x', min: 0, max: 95.045592705167, step: 0.01, value: 29, type: 'range' }, { name: 'y', min: 0, max: 100, step: 0.01, value: 20, type: 'range' }, { name: 'z', min: 0, max: 108.9057750759878, step: 0.01, value: 70, type: 'range' }], palette: (mode, attrs, options = { correctLightness: false, colors: 32 }) => { let colors = []; let space = ['x', 'y', 'z']; let iterate = attrs['gradient space'].value; let max = attrs[iterate].max; for (let i = 0; i < options.colors; i++) { let color; let componentPercent = i / options.colors * max; let x = iterate === space[0] ? componentPercent: parseFloat(attrs[space[0]].value); let y = iterate === space[1] ? componentPercent: parseFloat(attrs[space[1]].value); let z = iterate === space[2] ? componentPercent: parseFloat(attrs[space[2]].value); let rgb = xyzToRGB([x, y, z]); color = chroma.rgb(rgb).get('hex'); colors.push(color); } return colors; } }, { name: ['ucs'], bg: '#212121', hasStart: true, attr: [{ name: 'gradient space', value: 'u', values: ['u', 'v', 'w'], type: 'list', excludeValue: true }, { name: 'u', min: 0, max: 100, step: 0.01, value: 29, type: 'range' }, { name: 'v', min: 0, max: 100, step: 0.01, value: 20, type: 'range' }, { name: 'w', min: 0, max: 100, step: 0.01, value: 70, type: 'range' }], palette: (mode, attrs, options = { correctLightness: false, colors: 32 }) => { let colors = []; let space = ['u', 'v', 'w']; let iterate = attrs['gradient space'].value; let max = attrs[iterate].max; for (let i = 0; i < options.colors; i++) { let color; let componentPercent = i / options.colors * max; let u = iterate === space[0] ? componentPercent: parseFloat(attrs[space[0]].value); let v = iterate === space[1] ? componentPercent: parseFloat(attrs[space[1]].value); let w = iterate === space[2] ? componentPercent: parseFloat(attrs[space[2]].value); let rgb = xyzToRGB(ucsToxyz([u, v, w])); color = chroma.rgb(rgb).get('hex'); colors.push(color); } return colors; } }, { name: ['Harmonies'], hasStart: false, bg: '#212121', attr: [{ name: 'color', type: 'color', value: '#72ffd7' }, { name: 'scheme', value: 'splitcomplementary', values: ['complementary', 'splitcomplementary', 'triadic', 'tetradic', 'analogous', 'square'], type: 'list', harmonies: { complementary: { h: [0, 180] }, splitcomplementary: { h: [0, 150, 210] }, triadic: { h: [0, 120, 240] }, tetradic: { h: [0, 60, 180, 240] }, analogous: { h: [-30, 0, 30] }, square: { h: [0, 90, 180, 270] } } }, { name: 'space', value: 'lab', values: ['lab', 'hsl', 'hsv', 'hsi', 'lch', 'rgb', 'lrgb', 'num'], type: 'list' }], palette: (mode, attrs, options = { correctLightness: false, colors: 32 }) => { const harmonies = attrs['scheme'].harmonies; const harmonyModel = harmonies[attrs['scheme'].value]; const color = attrs['color'].value; const colors = []; for (let componentKey in harmonyModel) { let currentColor = chroma(color); for (let val in harmonyModel[componentKey]) { let value = harmonyModel[componentKey][val]; let operator = Math.sign(value) < 0 ? '-': '+'; colors.push(currentColor.set('hsl.' + componentKey, operator + Math.abs(value)).hex()); } } return chroma.scale(colors).mode(attrs['space'].value).colors(options.colors); } }, { name: ['cubehelix'], hasStart: false, bg: '#212121', attr: [{ name: 'start', min: 0, max: 360, step: 1, value: 0, type: 'range' }, { name: 'rotations', min: -2, max: 2, step: 0.01, value: -0.65, type: 'range' }, { name: 'hue', min: 0, max: 1, step: 0.01, value: 1, type: 'range' }, { name: 'gamma', min: 0, max: 1, step: 0.01, value: 1, type: 'range' }, { name: 'lightness min', min: 0, max: 0.9, step: 0.01, value: 0.2, type: 'range' }, { name: 'lightness max', min: 0.1, max: 1, step: 0.01, value: 0.8, type: 'range' }, { name: 'padding', min: -.49, max: .49, step: 0.001, value: 0, type: 'range' }], palette: (mode, attrs, options = { correctLightness: false, colors: 32 }) => { let colors = chroma.cubehelix(). start(parseFloat(attrs['start'].value)). rotations(parseFloat(attrs['rotations'].value)). hue( parseFloat(attrs['hue'].value)). gamma( parseFloat(attrs['gamma'].value)). lightness([ parseFloat(attrs['lightness min'].value), parseFloat(attrs['lightness max'].value)]). scale(); let padding = parseFloat(attrs.padding.value); if (padding !== 0) { colors.padding(padding); } return colors.colors(options.colors); } }, { name: ['RGB'], hasStart: true, bg: '#212121', attr: [{ name: 'gradient space', value: 'red', values: ['red', 'green', 'blue'], type: 'list', excludeValue: true }, { name: 'red', min: 0, max: 255, step: 1, value: 20, type: 'range' }, { name: 'green', min: 0, max: 255, step: 1, value: 88, type: 'range' }, { name: 'blue', min: 0, max: 255, step: 1, value: 100, type: 'range' }], palette: (mode, attrs, options = { correctLightness: false, colors: 32 }) => { let colors = []; let space = ['red', 'green', 'blue']; let iterate = attrs['gradient space'].value; for (let i = 0; i < options.colors; i++) { let componentPercent = Math.ceil(i / (options.colors - 1) * 255); let color = chroma.rgb([ iterate === space[0] ? componentPercent: parseFloat(attrs[space[0]].value), iterate === space[1] ? componentPercent: parseFloat(attrs[space[1]].value), iterate === space[2] ? componentPercent: parseFloat(attrs[space[2]].value)]). get('hex'); colors.push(color); } return colors; } }, { name: ['RYB'], hasStart: true, bg: '#212121', attr: [{ name: 'gradient space', value: 'yellow', values: ['red', 'yellow', 'blue'], type: 'list', excludeValue: true }, { name: 'red', min: 0, max: 255, step: 1, value: 255, type: 'range' }, { name: 'yellow', min: 0, max: 255, step: 1, value: 88, type: 'range' }, { name: 'blue', min: 0, max: 255, step: 1, value: 125, type: 'range' }], palette: (mode, attrs, options = { correctLightness: false, colors: 32 }) => { let colors = []; let space = ['red', 'yellow', 'blue']; let iterate = attrs['gradient space'].value; for (let i = 0; i < options.colors; i++) { let componentPercent = Math.ceil(i / (options.colors - 1) * 255); let rgb = ryb2rgb([ iterate === space[0] ? componentPercent: parseFloat(attrs[space[0]].value), iterate === space[1] ? componentPercent: parseFloat(attrs[space[1]].value), iterate === space[2] ? componentPercent: parseFloat(attrs[space[2]].value)]); let color = chroma.rgb(rgb).get('hex'); colors.push(color); } return colors; } }, { name: ['YPbPr'], hasStart: true, bg: '#212121', attr: [{ name: 'gradient space', value: 'Y', values: ['Y', 'Pb', 'Pr'], type: 'list', excludeValue: true }, { name: 'Y', min: 0, max: 1, step: 0.0001, value: 0, type: 'range' }, { name: 'Pb', min: -0.5, max: 0.5, step: 0.0001, value: -0.5, type: 'range' }, { name: 'Pr', min: -0.5, max: 0.5, step: 0.0001, value: 0.5, type: 'range' }], palette: (mode, attrs, options = { correctLightness: false, colors: 32 }) => { let colors = []; let space = ['Y', 'Pb', 'Pr']; let iterate = attrs['gradient space'].value; for (let i = 0; i < options.colors; i++) { let componentPercent = i / (options.colors - 1); let color = chroma( ypbprToRGB( iterate === space[0] ? componentPercent: parseFloat(attrs[space[0]].value), iterate === space[1] ? -0.5 + componentPercent: parseFloat(attrs[space[1]].value), iterate === space[2] ? -0.5 + componentPercent: parseFloat(attrs[space[2]].value)), 'rgb'). get('hex'); colors.push(color); } return colors; } }, { name: ['lch' /*, 'hcl'*/], hasStart: true, bg: '#fffcec', attr: [{ name: 'gradient space', value: 'h', values: ['l', 'c', 'h'], type: 'list', excludeValue: true }, { name: 'h', min: 0, max: 360, step: 1, value: 20, type: 'range' }, { name: 'l', min: 0, max: 100, step: 1, value: 75, type: 'range' }, { name: 'c', min: 0, max: 140, step: 1, value: 100, type: 'range' }], palette: (mode, attrs, options = { correctLightness: false, colors: 32 }) => { let colors = []; let space = ['l', 'c', 'h']; let iterate = attrs['gradient space'].value; //color = chroma.hcl(h, s, l).get('hex'); for (let i = 0; i < options.colors; i++) { let color = chroma[mode]([ iterate === space[0] ? Math.ceil(i / options.colors * 100): parseFloat(attrs[space[0]].value), iterate === space[1] ? Math.ceil(i / options.colors * 140): parseFloat(attrs[space[1]].value), iterate === space[2] ? Math.ceil(i / options.colors * 360): parseFloat(attrs[space[2]].value)]). get('hex'); colors.push(color); } return colors; } }, { name: ['lab'], hasStart: true, bg: '#f5f5f5', attr: [{ name: 'lightness', min: 0, max: 100, step: 1, value: 74, type: 'range' }, { name: 'green–red', min: -100, max: 100, step: 1, value: 67, type: 'range' }, { name: 'blue–yellow', min: -100, max: 100, step: 1, value: 8, type: 'range' }, { name: 'gradient space', value: 'blue–yellow', values: ['lightness', 'green–red', 'blue–yellow'], type: 'list', excludeValue: true }], palette: (mode, attrs, options = { correctLightness: false, colors: 32 }) => { let colors = []; let space = ['lightness', 'green–red', 'blue–yellow']; let iterate = attrs['gradient space'].value; for (let i = 0; i < options.colors; i++) { let color = chroma.lch([ iterate === space[0] ? Math.ceil(i / options.colors * 100): parseFloat(attrs[space[0]].value), iterate === space[1] ? -100 + Math.ceil(i / options.colors * 200): parseFloat(attrs[space[1]].value), iterate === space[2] ? -100 + Math.ceil(i / options.colors * 200): parseFloat(attrs[space[2]].value)]). get('hex'); colors.push(color); } return colors; } }, { name: ['interpolate'], hasStart: false, bg: '#212121', attr: [{ name: 'stops', type: 'colorlist', value: [ '#72ffd7', '#f03b50', '#0f0b50'] }, { name: 'space', value: 'lab', values: ['lab', 'hsl', 'hsv', 'hsi', 'lch', 'rgb', 'lrgb', 'num'], type: 'list' }, { name: 'padding', min: -.49, max: .49, step: 0.001, value: 0, type: 'range' }], palette: (mode, attrs, options = { correctLightness: false, colors: 32 }) => { let scale = chroma.scale(attrs['stops'].value).mode(attrs['space'].value); let padding = parseFloat(attrs.padding.value); if (padding !== 0) { scale.padding(padding); } let colors = scale.colors(options.colors); /*colors = colors.map(c => { return chroma(c).set('hsl.h', '+20').hex(); })*/ return colors; } }, { name: ['matplotlib'], hasStart: false, bg: '#fdfdfd', attr: [{ name: 'scheme', value: 'plasma', values: ['plasma', 'inferno', 'magma', 'viridis'], type: 'list' }, { name: 'padding', min: -.49, max: .49, step: 0.001, value: 0, type: 'range' }], palette: (mode, attrs, options = { correctLightness: false, colors: 32 }) => { const schemes = { 'inferno': ["#000004", "#010005", "#010106", "#010108", "#02010a", "#02020c", "#02020e", "#030210", "#040312", "#040314", "#050417", "#060419", "#07051b", "#08051d", "#09061f", "#0a0722", "#0b0724", "#0c0826", "#0d0829", "#0e092b", "#10092d", "#110a30", "#120a32", "#140b34", "#150b37", "#160b39", "#180c3c", "#190c3e", "#.........完整代码请登录后点击上方下载按钮下载查看
网友评论0