CSS
背景和边框 | Backgrounds & Borders

框阴影生成 | CSS Background and Borders: Box-shadow generator

CSS Background and Borders: Box-shadow generator

这个工具可以让你构造CSS box-shadow效果,为你的CSS对象添加阴影效果。

盒子阴影发生器

HTML内容

<div id="container">     <div class="group section">         <div id="layer_manager">             <div class="group section">                 <div class="button" data-type="add"> </div>                 <div class="button" data-type="move-up"> </div>                 <div class="button" data-type="move-down"> </div>             </div>             <div id="stack_container"></div>         </div>         <div id="preview_zone">             <div id="layer_menu" class="col span_12">                 <div class="button" id="element" data-type="subject" data-title="element"> element </div>                 <div class="button" id="before" data-type="subject" data-title=":before">                     :before                     <span class="delete" data-type="disable"></span>                 </div>                 <div class="button" id="after" data-type="subject" data-title=":after">                     :after                     <span class="delete" data-type="disable"></span>                 </div>                 <div class="ui-checkbox" data-topic='before' data-label=":before"></div>                 <div class="ui-checkbox" data-topic='after' data-label=":after"></div>             </div>             <div id="preview">                 <div id="obj-element">                     <div class="content"> </div>                     <div id="obj-before"> </div>                     <div id="obj-after"> </div>                 </div>             </div>         </div>     </div>     <div id="controls" class="group section">         <div class="wrap-left">             <div class="colorpicker category">                 <div class="title"> </div>                 <div id="colorpicker" class="group">                     <div id="gradient" class="gradient">                         <div id="gradient_picker"> </div>                     </div>                     <div id="hue" data-topic="hue" class="hue">                         <div id="hue_selector"> </div>                     </div>                     <div class="info">                         <div class="input" data-topic="hue" data-title='H:' data-action="HSV"></div>                         <div class="input" data-topic="saturation" data-title='S:' data-action="HSV"></div>                         <div class="input" data-topic="value" data-title='V:' data-action="HSV"></div>                     </div>                     <div class="alpha">                         <div id="alpha" data-topic="alpha">                             <div id="alpha_selector"> </div>                         </div>                     </div>                     <div class="info">                         <div class="input" data-topic="r" data-title='R:' data-action="RGB"></div>                         <div class="input" data-topic="g" data-title='G:' data-action="RGB"></div>                         <div class="input" data-topic="b" data-title='B:' data-action="RGB"></div>                     </div>                     <div class="preview block">                         <div id="output_color"> </div>                     </div>                     <div class="block info">                         <div class="input" data-topic="a" data-title='alpha:' data-action="alpha"></div>                         <div class="input" data-topic="hexa" data-title='' data-action="hexa"></div>                     </div>                 </div>             </div>         </div>         <div class="wrap-right">             <div id="shadow_properties" class="category">                 <div class="title"> Shadow properties </div>                 <div class="group">                     <div class="group property">                         <div class="ui-slider-name"> inset </div>                         <div class="ui-checkbox" data-topic='inset'></div>                     </div>                     <div class="slidergroup">                         <div class="ui-slider-name"> Position x </div>                         <div class="ui-slider-btn-set" data-topic="posX" data-type="sub"></div>                         <div class="ui-slider" data-topic="posX"                             data-min="-500" data-max="500" data-step="1"> </div>                         <div class="ui-slider-btn-set" data-topic="posX" data-type="add"></div>                         <div class="ui-slider-input" data-topic="posX" data-unit="px"></div>                     </div>                     <div class="slidergroup">                         <div class="ui-slider-name"> Position y </div>                         <div class="ui-slider-btn-set" data-topic="posY" data-type="sub"></div>                         <div class="ui-slider" data-topic="posY"                             data-min="-500" data-max="500" data-step="1"> </div>                         <div class="ui-slider-btn-set" data-topic="posY" data-type="add"></div>                         <div class="ui-slider-input" data-topic="posY" data-unit="px"></div>                     </div>                     <div class="slidergroup">                         <div class="ui-slider-name"> Blur </div>                         <div class="ui-slider-btn-set" data-topic="blur" data-type="sub"></div>                         <div class="ui-slider" data-topic="blur"                             data-min="0" data-max="200" data-step="1"> </div>                         <div class="ui-slider-btn-set" data-topic="blur" data-type="add"></div>                         <div class="ui-slider-input" data-topic="blur" data-unit="px"></div>                     </div>                     <div class="slidergroup">                         <div class="ui-slider-name"> Spread </div>                         <div class="ui-slider-btn-set" data-topic="spread" data-type="sub"></div>                         <div class="ui-slider" data-topic="spread"                             data-min="-100"    data-max="100" data-step="1" data-value="50">                         </div>                         <div class="ui-slider-btn-set" data-topic="spread" data-type="add"></div>                         <div class="ui-slider-input" data-topic="spread" data-unit="px"></div>                     </div>                 </div>             </div>             <div id="element_properties" class="category">                 <div class="title"> Class element properties </div>                 <div class="group">                     <div class="group property">                         <div class="ui-slider-name"> border </div>                         <div class="ui-checkbox" data-topic='border-state' data-state="true"></div>                     </div>                     <div id="z-index" class="slidergroup">                         <div class="ui-slider-name"> z-index </div>                         <div class="ui-slider-btn-set" data-topic="z-index" data-type="sub"></div>                         <div class="ui-slider" data-topic="z-index"                             data-min="-10" data-max="10" data-step="1"></div>                         <div class="ui-slider-btn-set" data-topic="z-index" data-type="add"></div>                         <div class="ui-slider-input" data-topic="z-index"></div>                     </div>                     <div class="slidergroup">                         <div class="ui-slider-name"> top </div>                         <div class="ui-slider-btn-set" data-topic="top" data-type="sub"></div>                         <div class="ui-slider" data-topic="top"                             data-min="-500" data-max="500" data-step="1"> </div>                         <div class="ui-slider-btn-set" data-topic="top" data-type="add"></div>                         <div class="ui-slider-input" data-topic="top" data-unit="px"></div>                     </div>                     <div class="slidergroup">                         <div class="ui-slider-name"> left </div>                         <div class="ui-slider-btn-set" data-topic="left" data-type="sub"></div>                         <div class="ui-slider" data-topic="left"                             data-min="-300" data-max="700" data-step="1"> </div>                         <div class="ui-slider-btn-set" data-topic="left" data-type="add"></div>                         <div class="ui-slider-input" data-topic="left" data-unit="px"></div>                     </div>                     <div id="transform_rotate" class="slidergroup">                         <div class="ui-slider-name"> Rotate </div>                         <div class="ui-slider-btn-set" data-topic="rotate" data-type="sub"></div>                         <div class="ui-slider" data-topic="rotate"                             data-min="-360" data-max="360" data-step="1" data-value="0">                         </div>                         <div class="ui-slider-btn-set" data-topic="rotate" data-type="add"></div>                         <div class="ui-slider-input" data-topic="rotate" data-unit="deg"></div>                     </div>                     <div class="slidergroup">                         <div class="ui-slider-name"> Width </div>                         <div class="ui-slider-btn-set" data-topic="width" data-type="sub"></div>                         <div class="ui-slider" data-topic="width"                             data-min="0" data-max="1000" data-step="1" data-value="200">                         </div>                         <div class="ui-slider-btn-set" data-topic="width" data-type="add"></div>                         <div class="ui-slider-input" data-topic="width"  data-unit="px"></div>                     </div>                     <div class="slidergroup">                         <div class="ui-slider-name"> Height </div>                         <div class="ui-slider-btn-set" data-topic="height" data-type="sub"></div>                         <div class="ui-slider" data-topic="height"                             data-min="0" data-max="400" data-step="1" data-value="200">                         </div>                         <div class="ui-slider-btn-set" data-topic="height" data-type="add"></div>                         <div class="ui-slider-input" data-topic="height" data-unit="px"></div>                     </div>                 </div>             </div>             <div id="output" class="category">                 <div id="menu" class="menu"></div>                 <div class="title">    CSS Code </div>                 <div class="group" style="border-top-left-radius: 0;">                     <div class="output" data-topic="element" data-name="element"                         data-prop="width height background-color position=[relative] box-shadow">                     </div>                     <div class="output" data-topic="before" data-name="element:before"                         data-prop="content=[&quot;&quot;] position=[absolute] width height top left z-index background-color box-shadow transform -webkit-transform -ms-transform">                     </div>                     <div class="output" data-topic="after" data-name="element:after"                         data-prop="content=[&quot;&quot;] position=[absolute] width height top left z-index background-color box-shadow transform -webkit-transform -ms-transform">                     </div>                 </div>             </div>         </div>     </div> </div>

CSS内容

/* GRID OF TWELVE * ========================================================================== */ .span_12 { width: 100%; } .span_11 { width: 91.46%; } .span_10 { width: 83%; } .span_9 { width: 74.54%; } .span_8 { width: 66.08%; } .span_7 { width: 57.62%; } .span_6 { width: 49.16%; } .span_5 { width: 40.7%; } .span_4 { width: 32.24%; } .span_3 { width: 23.78%; } .span_2 { width: 15.32%; } .span_1 { width: 6.86%; } /* SECTIONS * ========================================================================== */ .section { clear: both; padding: 0px; margin: 0px; } /* GROUPING * ========================================================================== */ .group:before, .group:after { content: ""; display: table; } .group:after { clear:both; } .group { zoom: 1; /* For IE 6/7 (trigger hasLayout) */ } /* GRID COLUMN SETUP * ========================================================================== */ .col { display: block; float:left; margin: 1% 0 1% 1.6%; } .col:first-child { margin-left: 0; } /* all browsers except IE6 and lower */ /* * UI Slider */ .slidergroup { height: 20px; margin: 10px 0; font-family: "Segoe UI", Arial, Helvetica, sans-serif; -moz-user-select: none; user-select: none; } .slidergroup * { float: left; height: 100%; line-height: 100%; } /* Slider */ .ui-slider { height: 10px; width: 200px; margin: 4px 10px; display: block; border: 1px solid #999; border-radius: 3px; background: #EEE; } .ui-slider:hover { cursor: pointer; } .ui-slider-name { width: 90px; padding: 0 10px 0 0; text-align: right; text-transform: lowercase; } .ui-slider-pointer { width: 13px; height: 13px; background-color: #EEE; border: 1px solid #2C9FC9; border-radius: 3px; position: relative; top: -3px; left: 0%; } .ui-slider-btn-set { width: 25px; background-color: #2C9FC9; border-radius: 3px; color: #FFF; font-weight: bold; text-align: center; } .ui-slider-btn-set:hover { background-color: #379B4A; cursor: pointer; } .ui-slider-input > input { margin: 0 10px; padding: 0; width: 50px; text-align: center; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; } /* * UI Button */ /* Checkbox */ .ui-checkbox { text-align: center; font-size: 16px; font-family: "Segoe UI", Arial, Helvetica, sans-serif; line-height: 1.5em; color: #FFF; -moz-user-select: none; -webkit-user-select: none; -ms-user-select: none; user-select: none; } .ui-checkbox > input { display: none; } .ui-checkbox > label { font-size: 12px; padding: 0.333em 1.666em 0.5em; height: 1em; line-height: 1em; background-color: #888; background-image: url("https://mdn.mozillademos.org/files/5683/disabled.png" background-position: center center; background-repeat: no-repeat; color: #FFF; border-radius: 3px; font-weight: bold; float: left; } .ui-checkbox .text { padding-left: 34px; background-position: center left 10px; } .ui-checkbox .left { padding-right: 34px; padding-left: 1.666em; background-position: center right 10px; } .ui-checkbox > label:hover { cursor: pointer; } .ui-checkbox > input:checked + label { background-image: url("https://mdn.mozillademos.org/files/5681/checked.png" background-color: #379B4A; } /* * BOX SHADOW GENERATOR TOOL */ body { max-width: 1000px; height: 800px; margin: 20px auto 0; font-family: "Segoe UI", Arial, Helvetica, sans-serif; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; -moz-user-select: none; -webkit-user-select: none; -ms-user-select: none; } #container { width: 100%; padding: 2px; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; } /* container with shadows stacks */ #stack_container { height: 400px; overflow: hidden; position: relative; border: 1px solid #CCC; border-radius: 3px; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; } #stack_container .container { height: 100%; width: 100%; position: absolute; left: 100%; transition-property: left; transition-duration: 0.5s; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; } #stack_container .title { text-align: center; font-weight: bold; line-height: 2em; border-bottom: 1px solid #43A6E1; color: #666; } /* * Stack of Layers for shadow */ #layer_manager { width: 17%; background-color: #FEFEFE; margin: 0 1% 0 0; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; float: left; } #layer_manager .button { width: 30%; height: 25px; margin:0 0 10px; color: #333; background-color: #EEE; text-align: center; font-size: 0.75em; line-height: 1.5em; border: 1px solid #CCC; border-radius: 3px; display: block; background-position: center center; background-repeat: no-repeat; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; float: left; } #layer_manager .button:hover { background-color: #3380C4; border: 1px solid #3380C4; cursor: pointer; } #layer_manager [data-type='add'] { background-image: url("https://mdn.mozillademos.org/files/5685/add-black.png" } #layer_manager [data-type='add']:hover { background-image: url("https://mdn.mozillademos.org/files/5687/add-white.png" } #layer_manager [data-type='move-up'] { background-image: url("https://mdn.mozillademos.org/files/5697/up-black.png" margin-left: 5%; margin-right: 5%; } #layer_manager [data-type='move-up']:hover { background-image: url("https://mdn.mozillademos.org/files/5709/up-white.png" } #layer_manager [data-type='move-down'] { background-image: url("https://mdn.mozillademos.org/files/5693/down-black.png" } #layer_manager [data-type='move-down']:hover { background-image: url("https://mdn.mozillademos.org/files/5695/down-white.png" } /* shadows classes */ #layer_manager .node { width: 100%; margin: 5px 0; padding: 5px; text-align: center; background-color: #EEE; border: 1px solid #DDD; font-size: 0.75em; line-height: 1.5em; color: #333; border-radius: 3px; position: relative; display: block; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; } #layer_manager .node:hover { color: #FFF; background-color: #3380C4; cursor: pointer; } /* active element styling */ #layer_manager [data-active='layer'] { color: #FFF; border: none; background-color: #379B4A; } #layer_manager [data-active='subject'] { color: #FFF; background-color: #467FC9; } /* delete button */ #layer_manager .delete { width: 1.5em; height: 100%; float: right; border-radius: 3px; background-image: url("https://mdn.mozillademos.org/files/5689/delete-white.png" background-position: center center; background-repeat: no-repeat; position: absolute; top: 0; right: 10px; display: none; } #layer_manager .delete:hover { background-image: url("https://mdn.mozillademos.org/files/5691/delete-yellow.png" } #layer_manager .node:hover .delete { display: block; } #layer_manager .stack { padding: 0 5px; max-height: 90%; overflow: auto; overflow-x: hidden; } /* * Layer Menu */ #layer_menu { margin: 0 0 10px 0; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; } #layer_menu .button { width: 100px; margin: 0 5px 0 0; padding: 2.5px; color: #333; background-color: #EEE; border: 1px solid #CCC; border-radius: 3px; text-align: center; font-size: 0.75em; line-height: 1.5em; position: relative; display: block; float: left; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; } #layer_menu .button:hover { color: #FFF; background-color: #3380C4; border: 1px solid #3380C4; cursor: pointer; } #layer_menu .delete { width: 1.5em; height: 100%; float: right; border-radius: 3px; background-image: url("https://mdn.mozillademos.org/files/5689/delete-white.png" background-position: center center; background-repeat: no-repeat; position: absolute; top: 0; right: 5px; display: none; } #layer_menu .delete:hover { background-image: url("https://mdn.mozillademos.org/files/5691/delete-yellow.png" } #layer_menu .button:hover .delete { display: block; } /* * active element styling */ #layer_menu [data-active='subject'] { color: #FFF; background-color: #379B4A; border: 1px solid #379B4A; } /* Checkbox */ #layer_menu .ui-checkbox > label { height: 15px; line-height: 17px; font-weight: normal; width: 46px; margin: 0 5px 0 0; } #layer_menu .ui-checkbox > input:checked + label { display: none; } /******************************************************************************/ /******************************************************************************/ /* * Preview Area */ #preview_zone { width: 82%; float: left; } #preview { width: 100%; height: 400px; border: 1px solid #CCC; border-radius: 3px; text-align: center; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; cursor: move; float: left; } #preview .content { width: 100%; height: 100%; display: block; } #obj-element { width: 300px; height: 100px; border: 1px solid #CCC; background: #FFF; position: relative; } #obj-before { height: 100%; width: 100%; background: #999; border: 1px solid #CCC; text-align: left; display : block; position: absolute; z-index: -1; } #obj-after { height: 100%; width: 100%; background: #DDD; border: 1px solid #CCC; text-align: right; display : block; position: absolute; z-index: -1; } /******************************************************************************/ /******************************************************************************/ /** * Controls */ .wrap-left { float: left; overflow: hidden; } .wrap-right { float: right; overflow: hidden; } .wrap-left > * { float: left; } .wrap-right > * { float: right; } @media (min-width: 960px) { .wrap-left { width: 45%; } .wrap-right { width: 55%; } } @media (max-width: 959px) { .wrap-left { width: 30%; } .wrap-right { width: 70%; } } #controls { color: #444; margin: 10px 0 0 0; } #controls .category { width: 500px; margin: 0 auto 20px; padding: 0; } #controls .category .title { width: 100%; height: 1.5em; line-height: 1.5em; color: #AAA; text-align: right; } #controls .category > .group { border: 1px solid #CCC; border-radius: 3px; } /** * Color Picker */ @media (min-width: 960px) { #controls .colorpicker { width: 420px; } } @media (max-width: 959px) { #controls .colorpicker { width: 210px; } } #colorpicker { width: 100%; margin: 0 auto; } #colorpicker .gradient { width: 200px; height: 200px; margin: 5px; background: url("https://mdn.mozillademos.org/files/5707/picker_mask_200.png" background: -moz-linear-gradient(bottom, #000 0%, rgba(0, 0, 0, 0) 100%), -moz-linear-gradient(left, #FFF 0%, rgba(255, 255, 255, 0) 100% background: -webkit-linear-gradient(bottom, #000 0%, rgba(0, 0, 0, 0) 100%), -webkit-linear-gradient(left, #FFF 0%, rgba(255, 255, 255, 0) 100% background-color: #F00; float: left; } #colorpicker .hue { width: 200px; height: 30px; margin: 5px; background: url("https://mdn.mozillademos.org/files/5701/hue.png" background: -moz-linear-gradient(left, #F00 0%, #FF0 16.66%, #0F0 33.33%, #0FF 50%, #00F 66.66%, #F0F 83.33%, #F00 100% background: -webkit-linear-gradient(left, #F00 0%, #FF0 16.66%, #0F0 33.33%, #0FF 50%, #00F 66.66%, #F0F 83.33%, #F00 100% float: left; } #colorpicker .alpha { width: 200px; height: 30px; margin: 5px; border: 1px solid #CCC; float: left; background: url("https://mdn.mozillademos.org/files/5705/alpha.png" -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; } #colorpicker #alpha { width: 100%; height: 100%; background: url("https://mdn.mozillademos.org/files/5703/alpha_mask.png" background: -moz-linear-gradient(left, rgba(255, 0, 0, 0) 0%, rgba(255, 0, 0, 1) 100% } #colorpicker #gradient_picker { width: 0.5em; height: 0.5em; border-radius: 0.4em; border: 2px solid #CCC; position: relative; top: 20%; left: 20%; } #colorpicker #hue_selector, #colorpicker #alpha_selector { width: 3px; height: 100%; border: 1px solid #777; background-color: #FFF; position: relative; top: -1px; left: 0%; } /* input HSV and RGB */ #colorpicker .info { width: 200px; margin: 5px; float: left; } #colorpicker .info * { float: left; } #colorpicker .info input { margin: 0; text-align: center; width: 30px; -moz-user-select: text; -webkit-user-select: text; -ms-user-select: text; } #colorpicker .info span { height: 20px; width: 30px; text-align: center; line-height: 20px; display: block; } /* Preview color */ #colorpicker .block { width: 95px; height: 54px; float: left; position: relative; } #colorpicker .preview { margin: 5px; border: 1px solid #CCC; background-image: url("https://mdn.mozillademos.org/files/5705/alpha.png" -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; } #colorpicker .preview:before { height: 100%; width: 50%; left: 50%; content: ""; background: #FFF; position: absolute; z-index: 1; } #colorpicker .preview > * { width: 50%; height: 100%; } #colorpicker #output_color { width: 100%; height: 100%; position: absolute; z-index: 2; } #colorpicker .block .input { float: right; } #colorpicker [data-topic="a"] > span { width: 50px; } #colorpicker [data-topic="hexa"] { float: right; margin: 10px 0 0 0; } #colorpicker [data-topic="hexa"] > span { display: none; } #colorpicker [data-topic="hexa"] > input { width: 85px; padding: 2px 0; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; } /* * UI Components */ /* Property */ .property { height: 20px; margin: 10px 0; } .property * { float: left; height: 100%; line-height: 100%; } /* Slider */ #controls .ui-slider-name { margin: 0 10px 0 0; } /* * Output code styling */ #output { position: relative; } #output .menu { max-width: 70%; height: 20px; position: absolute; top: 2px; } #output .button { width: 90px; height: 22px; margin: 0 5px 0 0; text-align: center; line-height: 20px; font-size: 14px; color: #FFF; background-color: #999; border-top-left-radius: 3px; border-top-right-radius: 3px; bottom: -5px; float:left; } #output .button:hover { color: #FFF; background-color: #666; cursor: pointer; } #output .menu [data-active="true"] { color: #777; background-color: #FFF; border: 1px solid #CCC; border-bottom: none; } #output .menu [data-topic="before"] { left: 100px; } #output .menu [data-topic="after"] { left: 200px; } #output .output { width: 480px; margin: 10px; padding: 10px; overflow: hidden; color: #555; font-size: 14px; border: 1px dashed #CCC; border-radius: 3px; display: none; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; -moz-user-select: text; -webkit-user-select: text; -ms-user-select: text; } #output .css-property { width: 100%; float: left; white-space: pre; } #output .name { width: 35%; float: left; } #output .value { width: 65%; float: left; }

JavaScript内容

'use strict'; /** * UI-SlidersManager */ var SliderManager = (function SliderManager() { var subscribers = {}; var sliders = []; var Slider = function(node) { var min = node.getAttribute('data-min') | 0; var max = node.getAttribute('data-max') | 0; var step = node.getAttribute('data-step') | 0; var value = node.getAttribute('data-value') | 0; var snap = node.getAttribute('data-snap' var topic = node.getAttribute('data-topic' this.min = min; this.max = max > 0 ? max : 100; this.step = step === 0 ? 1 : step; this.value = value <= max && value >= min ? value : (min + max) / 2 | 0; this.snap = snap === "true" ? true : false; this.topic = topic; this.node = node; var pointer = document.createElement('div' pointer.className = 'ui-slider-pointer'; node.appendChild(pointer this.pointer = pointer; setMouseTracking(node, updateSlider.bind(this) sliders[topic] = this; setValue(topic, this.value } var setButtonComponent = function setButtonComponent(node) { var type = node.getAttribute('data-type' var topic = node.getAttribute('data-topic' if (type === "sub") { node.textContent = '-'; node.addEventListener("click", function() { decrement(topic } } if (type === "add") { node.textContent = '+'; node.addEventListener("click", function() { increment(topic } } } var setInputComponent = function setInputComponent(node) { var topic = node.getAttribute('data-topic' var unit_type = node.getAttribute('data-unit' var input = document.createElement('input' var unit = document.createElement('span' unit.textContent = unit_type; input.setAttribute('type', 'text' node.appendChild(input node.appendChild(unit input.addEventListener('click', function(e) { this.select( } input.addEventListener('change', function(e) { setValue(topic, e.target.value | 0 } subscribe(topic, function(value) { node.children[0].value = value; } } var increment = function increment(topic) { var slider = sliders[topic]; if (slider === null || slider === undefined) return; if (slider.value + slider.step <= slider.max) { slider.value += slider.step; setValue(slider.topic, slider.value) notify.call(slider } }; var decrement = function decrement(topic) { var slider = sliders[topic]; if (slider === null || slider === undefined) return; if (slider.value - slider.step >= slider.min) { slider.value -= slider.step; setValue(topic, slider.value) notify.call(slider } } // this = Slider object var updateSlider = function updateSlider(e) { var node = this.node; var pos = e.pageX - node.offsetLeft; var width = node.clientWidth; var delta = this.max - this.min; var offset = this.pointer.clientWidth + 4; // border width * 2 if (pos < 0) pos = 0; if (pos > width) pos = width; var value = pos * delta / width | 0; var precision = value % this.step; value = value - precision + this.min; if (precision > this.step / 2) value = value + this.step; if (this.snap) pos = (value - this.min) * width / delta; this.pointer.style.left = pos - offset/2 + "px"; this.value = value; node.setAttribute('data-value', value notify.call(this } var setValue = function setValue(topic, value) { var slider = sliders[topic]; if (value > slider.max || value < slider.min) return; var delta = slider.max - slider.min; var width = slider.node.clientWidth; var offset = slider.pointer.clientWidth; var pos = (value - slider.min) * width / delta; slider.value = value; slider.pointer.style.left = pos - offset / 2 + "px"; slider.node.setAttribute('data-value', value notify.call(slider } var setMouseTracking = function setMouseTracking(elem, callback) { elem.addEventListener("mousedown", function(e) { callback(e document.addEventListener("mousemove", callback } document.addEventListener("mouseup", function(e) { document.removeEventListener("mousemove", callback } } var subscribe = function subscribe(topic, callback) { if (subscribers[topic] === undefined) subscribers[topic] = []; subscribers[topic].push(callback } var unsubscribe = function unsubscribe(topic, callback) { subscribers[topic].indexOf(callback subscribers[topic].splice(index, 1 } var notify = function notify() { if (subscribers[this.topic] === undefined) return; for (var i in subscribers[this.topic]) { subscribers[this.topic][i](this.value } } var init = function init() { var elem, size; elem = document.querySelectorAll('.ui-slider-btn-set' size = elem.length; for (var i = 0; i < size; i++) setButtonComponent(elem[i] elem = document.querySelectorAll('.ui-slider-input' size = elem.length; for (var i = 0; i < size; i++) setInputComponent(elem[i] elem = document.querySelectorAll('.ui-slider' size = elem.length; for (var i = 0; i < size; i++) new Slider(elem[i] } return { init : init, setValue : setValue, subscribe : subscribe, unsubscribe : unsubscribe } })( /** * UI-ButtonManager */ var ButtonManager = (function CheckBoxManager() { var subscribers = []; var buttons = []; var CheckBox = function CheckBox(node) { var topic = node.getAttribute('data-topic' var state = node.getAttribute('data-state' var name = node.getAttribute('data-label' var align = node.getAttribute('data-text-on' state = (state === "true" var checkbox = document.createElement("input" var label = document.createElement("label" var id = 'checkbox-' + topic; checkbox.id = id; checkbox.setAttribute('type', 'checkbox' checkbox.checked = state; label.setAttribute('for', id if (name) { label.className = 'text'; if (align) label.className += ' ' + align; label.textContent = name; } node.appendChild(checkbox node.appendChild(label this.node = node; this.topic = topic; this.checkbox = checkbox; checkbox.addEventListener('change', function(e) { notify.call(this }.bind(this) buttons[topic] = this; } var getNode = function getNode(topic) { return buttons[topic].node; } var setValue = function setValue(topic, value) { try { buttons[topic].checkbox.checked = value; notify.call(buttons[topic] } catch(error) { console.log(error, topic, value } } var subscribe = function subscribe(topic, callback) { if (subscribers[topic] === undefined) subscribers[topic] = []; subscribers[topic].push(callback } var unsubscribe = function unsubscribe(topic, callback) { subscribers[topic].indexOf(callback subscribers[topic].splice(index, 1 } var notify = function notify() { if (subscribers[this.topic] === undefined) return; for (var i = 0; i < subscribers[this.topic].length; i++) subscribers[this.topic][i](this.checkbox.checked } var init = function init() { var elem = document.querySelectorAll('.ui-checkbox' var size = elem.length; for (var i = 0; i < size; i++) new CheckBox(elem[i] } return { init : init, setValue : setValue, subscribe : subscribe, unsubscribe : unsubscribe } })( window.addEventListener("load", function(){ BoxShadow.init( } var BoxShadow = (function BoxShadow() { function getElemById(id) { return document.getElementById(id } /** * RGBA Color class */ function Color() { this.r = 0; this.g = 0; this.b = 0; this.a = 1; this.hue = 0; this.saturation = 0; this.value = 0; } Color.prototype.copy = function copy(obj) { if(obj instanceof Color !== true) { console.log("Typeof instance not Color" return; } this.r = obj.r; this.g = obj.g; this.b = obj.b; this.a = obj.a; this.hue = obj.hue; this.saturation = obj.saturation; this.value = obj.value; } Color.prototype.setRGBA = function setRGBA(red, green, blue, alpha) { if (red != undefined) this.r = red | 0; if (green != undefined) this.g = green | 0; if (blue != undefined) this.b = blue | 0; if (alpha != undefined) this.a = alpha | 0; } /** * HSV/HSB (hue, saturation, value / brightness) * @param hue 0-360 * @param saturation 0-100 * @param value 0-100 */ Color.prototype.setHSV = function setHSV(hue, saturation, value) { this.hue = hue; this.saturation = saturation; this.value = value; this.updateRGB( } Color.prototype.updateRGB = function updateRGB() { var sat = this.saturation / 100; var value = this.value / 100; var C = sat * value; var H = this.hue / 60; var X = C * (1 - Math.abs(H % 2 - 1) var m = value - C; var precision = 255; C = (C + m) * precision; X = (X + m) * precision; m = m * precision; if (H >= 0 && H < 1) { this.setRGBA(C, X, m return; } if (H >= 1 && H < 2) { this.setRGBA(X, C, m return; } if (H >= 2 && H < 3) { this.setRGBA(m, C, X return; } if (H >= 3 && H < 4) { this.setRGBA(m, X, C return; } if (H >= 4 && H < 5) { this.setRGBA(X, m, C return; } if (H >= 5 && H < 6) { this.setRGBA(C, m, X return; } } Color.prototype.updateHSV = function updateHSV() { var red = this.r / 255; var green = this.g / 255; var blue = this.b / 255; var cmax = Math.max(red, green, blue var cmin = Math.min(red, green, blue var delta = cmax - cmin; var hue = 0; var saturation = 0; if (delta) { if (cmax === red ) { hue = ((green - blue) / delta } if (cmax === green ) { hue = 2 + (blue - red) / delta; } if (cmax === blue ) { hue = 4 + (red - green) / delta; } if (cmax) saturation = delta / cmax; } this.hue = 60 * hue | 0; if (this.hue < 0) this.hue += 360; this.saturation = (saturation * 100) | 0; this.value = (cmax * 100) | 0; } Color.prototype.setHexa = function setHexa(value) { var valid = /(^#{0,1}[0-9A-F]{6}$)|(^#{0,1}[0-9A-F]{3}$)/i.test(value) if (valid !== true) return; if (value[0] === '#') value = value.slice(1, value.length if (value.length === 3) value = value.replace(/([0-9A-F])([0-9A-F])([0-9A-F])/i,"$1$1$2$2$3$3" this.r = parseInt(value.substr(0, 2), 16 this.g = parseInt(value.substr(2, 2), 16 this.b = parseInt(value.substr(4, 2), 16 this.alpha = 1; } Color.prototype.getHexa = function getHexa() { var r = this.r.toString(16 var g = this.g.toString(16 var b = this.b.toString(16 if (this.r < 16) r = '0' + r; if (this.g < 16) g = '0' + g; if (this.b < 16) b = '0' + b; var value = '#' + r + g + b; return value.toUpperCase( } Color.prototype.getRGBA = function getRGBA() { var rgb = "(" + this.r + ", " + this.g + ", " + this.b; var a = ''; var v = ''; if (this.a !== 1) { a = 'a'; v = ', ' + this.a; } var value = "rgb" + a + rgb + v + ")"; return value; } Color.prototype.getColor = function getColor() { if (this.a | 0 === 1) return this.getHexa( return this.getRGBA( } /** * Shadow Object */ function Shadow() { this.inset = false; this.posX = 5; this.posY = -5; this.blur = 5; this.spread = 0; this.color = new Color( var hue = (Math.random() * 360) | 0; var saturation = (Math.random() * 75) | 0; var value = (Math.random() * 50 + 50) | 0; this.color.setHSV(hue, saturation, value, 1 } Shadow.prototype.computeCSS = function computeCSS() { var value = ""; if (this.inset === true) value += "inset "; value += this.posX + "px "; value += this.posY + "px "; value += this.blur + "px "; value += this.spread + "px "; value += this.color.getColor( return value; } Shadow.prototype.toggleInset = function toggleInset(value) { if (value !== undefined || typeof value === "boolean") this.inset = value; else this.inset = this.inset === true ? false : true; } Shadow.prototype.copy = function copy(obj) { if(obj instanceof Shadow !== true) { console.log("Typeof instance not Shadow" return; } this.inset = obj.inset; this.posX = obj.posX; this.posY = obj.posY; this.blur = obj.blur; this.spread = obj.spread; this.color.copy(obj.color } /** * Color Picker */ var ColoPicker = (function ColoPicker() { var colorpicker; var hue_area; var gradient_area; var alpha_area; var gradient_picker; var hue_selector; var alpha_selector; var pick_object; var info_rgb; var info_hsv; var info_hexa; var output_color; var color = new Color( var subscribers = []; var updateColor = function updateColor(e) { var x = e.pageX - gradient_area.offsetLeft; var y = e.pageY - gradient_area.offsetTop; // width and height should be the same var size = gradient_area.clientWidth; if (x > size) x = size; if (y > size) y = size; if (x < 0) x = 0; if (y < 0) y = 0; var value = 100 - (y * 100 / size) | 0; var saturation = x * 100 / size | 0; color.setHSV(color.hue, saturation, value // should update just // color pointer location updateUI( notify("color", color } var updateHue = function updateHue(e) { var x = e.pageX - hue_area.offsetLeft; var width = hue_area.clientWidth; if (x < 0) x = 0; if (x > width) x = width; var hue = ((360 * x) / width) | 0; if (hue === 360) hue = 359; color.setHSV(hue, color.saturation, color.value // should update just // hue pointer location // picker area background // alpha area background updateUI( notify("color", color } var updateAlpha = function updateAlpha(e) { var x = e.pageX - alpha_area.offsetLeft; var width = alpha_area.clientWidth; if (x < 0) x = 0; if (x > width) x = width; color.a = (x / width).toFixed(2 // should update just // alpha pointer location updateUI( notify("color", color } var setHueGfx = function setHueGfx(hue) { var sat = color.saturation; var val = color.value; var alpha = color.a; color.setHSV(hue, 100, 100 gradient_area.style.backgroundColor = color.getHexa( color.a = 0; var start = color.getRGBA( color.a = 1; var end = color.getRGBA( color.a = alpha; var gradient = '-moz-linear-gradient(left, ' + start + '0%, ' + end + ' 100%)'; alpha_area.style.background = gradient; } var updateUI = function updateUI() { var x, y; // coordinates var size; // size of the area var offset; // pointer graphic selector offset // Set color pointer location size = gradient_area.clientWidth; offset = gradient_picker.clientWidth / 2 + 2; x = (color.saturation * size / 100) | 0; y = size - (color.value * size / 100) | 0; gradient_picker.style.left = x - offset + "px"; gradient_picker.style.top = y - offset + "px"; // Set hue pointer location size = hue_area.clientWidth; offset = hue_selector.clientWidth/2; x = (color.hue * size / 360 ) | 0; hue_selector.style.left = x - offset + "px"; // Set alpha pointer location size = alpha_area.clientWidth; offset = alpha_selector.clientWidth/2; x = (color.a * size) | 0; alpha_selector.style.left = x - offset + "px"; // Set picker area background var nc = new Color( nc.copy(color if (nc.hue === 360) nc.hue = 0; nc.setHSV(nc.hue, 100, 100 gradient_area.style.backgroundColor = nc.getHexa( // Set alpha area background nc.copy(color nc.a = 0; var start = nc.getRGBA( nc.a = 1; var end = nc.getRGBA( var gradient = '-moz-linear-gradient(left, ' + start + '0%, ' + end + ' 100%)'; alpha_area.style.background = gradient; // Update color info notify("color", color notify("hue", color.hue notify("saturation", color.saturation notify("value", color.value notify("r", color.r notify("g", color.g notify("b", color.b notify("a", color.a notify("hexa", color.getHexa() output_color.style.backgroundColor = color.getRGBA( } var setInputComponent = function setInputComponent(node) { var topic = node.getAttribute('data-topic' var title = node.getAttribute('data-title' var action = node.getAttribute('data-action' title = title === null ? '' : title; var input = document.createElement('input' var info = document.createElement('span' info.textContent = title; input.setAttribute('type', 'text' input.setAttribute('data-action', 'set-' + action + '-' + topic node.appendChild(info node.appendChild(input input.addEventListener('click', function(e) { this.select( } input.addEventListener('change', function(e) { if (action === 'HSV') inputChangeHSV(topic if (action === 'RGB') inputChangeRGB(topic if (action === 'alpha') inputChangeAlpha(topic if (action === 'hexa') inputChangeHexa(topic } subscribe(topic, function(value) { node.children[1].value = value; } } var inputChangeHSV = function actionHSV(topic) { var selector = "[data-action='set-HSV-" + topic + "']"; var node = document.querySelector("#colorpicker " + selector var value = parseInt(node.value if (typeof value === 'number' && isNaN(value) === false && value >= 0 && value < 360) color[topic] = value; color.updateRGB( updateUI( } var inputChangeRGB = function inputChangeRGB(topic) { var selector = "[data-action='set-RGB-" + topic + "']"; var node = document.querySelector("#colorpicker " + selector var value = parseInt(node.value if (typeof value === 'number' && isNaN(value) === false && value >= 0 && value <= 255) color[topic] = value; color.updateHSV( updateUI( } var inputChangeAlpha = function inputChangeAlpha(topic) { var selector = "[data-action='set-alpha-" + topic + "']"; var node = document.querySelector("#colorpicker " + selector var value = parseFloat(node.value if (typeof value === 'number' && isNaN(value) === false && value >= 0 && value <= 1) color.a = value.toFixed(2 updateUI( } var inputChangeHexa = function inputChangeHexa(topic) { var selector = "[data-action='set-hexa-" + topic + "']"; var node = document.querySelector("#colorpicker " + selector var value = node.value; color.setHexa(value color.updateHSV( updateUI( } var setMouseTracking = function setMouseTracking(elem, callback) { elem.addEventListener("mousedown", function(e) { callback(e document.addEventListener("mousemove", callback } document.addEventListener("mouseup", function(e) { document.removeEventListener("mousemove", callback } } /* * Observer */ var setColor = function setColor(obj) { if(obj instanceof Color !== true) { console.log("Typeof instance not Color" return; } color.copy(obj updateUI( } var subscribe = function subscribe(topic, callback) { if (subscribers[topic] === undefined) subscribers[topic] = []; subscribers[topic].push(callback } var unsubscribe = function unsubscribe(callback) { subscribers.indexOf(callback subscribers.splice(index, 1 } var notify = function notify(topic, value) { for (var i in subscribers[topic]) subscribers[topic][i](value } var init = function init() { colorpicker = getElemById("colorpicker" hue_area = getElemById("hue" gradient_area = getElemById("gradient" alpha_area = getElemById("alpha" gradient_picker = getElemById("gradient_picker" hue_selector = getElemById("hue_selector" alpha_selector = getElemById("alpha_selector" output_color = getElemById("output_color" var elem = document.querySelectorAll('#colorpicker .input' var size = elem.length; for (var i = 0; i < size; i++) setInputComponent(elem[i] setMouseTracking(gradient_area, updateColor setMouseTracking(hue_area, updateHue setMouseTracking(alpha_area, updateAlpha } return { init : init, setColor : setColor, subscribe : subscribe, unsubscribe : unsubscribe } })( /** * Shadow dragging */ var PreviewMouseTracking = (function Drag() { var active = false; var lastX = 0; var lastY = 0; var subscribers = []; var init = function init(id) { var elem = getElemById(id elem.addEventListener('mousedown', dragStart, false document.addEventListener('mouseup', dragEnd, false } var dragStart = function dragStart(e) { if (e.button !== 0) return; active = true; lastX = e.clientX; lastY = e.clientY; document.addEventListener('mousemove', mouseDrag, false } var dragEnd = function dragEnd(e) { if (e.button !== 0) return; if (active === true) { active = false; document.removeEventListener('mousemove', mouseDrag, false } } var mouseDrag = function mouseDrag(e) { notify(e.clientX - lastX, e.clientY - lastY lastX = e.clientX; lastY = e.clientY; } var subscribe = function subscribe(callback) { subscribers.push(callback } var unsubscribe = function unsubscribe(callback) { var index = subscribers.indexOf(callback subscribers.splice(index, 1 } var notify = function notify(deltaX, deltaY) { for (var i in subscribers) subscribers[i](deltaX, deltaY } return { init : init, subscribe : subscribe, unsubscribe : unsubscribe } })( /* * Element Class */ var CssClass = function CssClass(id) { this.left = 0; this.top = 0; this.rotate = 0; this.width = 300; this.height = 100; this.display = true; this.border = true; this.zIndex = -1; this.bgcolor = new Color( this.id = id; this.node = getElemById('obj-' + id this.object = getElemById(id this.shadowID = null; this.shadows = [] this.render = []; this.init( } CssClass.prototype.init = function init() { this.left = ((this.node.parentNode.clientWidth - this.node.clientWidth) / 2) | 0; this.top = ((this.node.parentNode.clientHeight - this.node.clientHeight) / 2) | 0; this.setTop(this.top this.setLeft(this.left this.setHeight(this.height this.setWidth(this.width this.bgcolor.setHSV(0, 0, 100 this.updateBgColor(this.bgcolor } CssClass.prototype.updatePos = function updatePos(deltaX, deltaY) { this.left += deltaX; this.top += deltaY; this.node.style.top = this.top + "px"; this.node.style.left = this.left + "px"; SliderManager.setValue("left", this.left SliderManager.setValue("top", this.top } CssClass.prototype.setLeft = function setLeft(value) { this.left = value; this.node.style.left = this.left + "px"; OutputManager.updateProperty(this.id, 'left', this.left + 'px' } CssClass.prototype.setTop = function setTop(value) { this.top = value; this.node.style.top = this.top + 'px'; OutputManager.updateProperty(this.id, 'top', this.top + 'px' } CssClass.prototype.setWidth = function setWidth(value) { this.width = value; this.node.style.width = this.width + 'px'; OutputManager.updateProperty(this.id, 'width', this.width + 'px' } CssClass.prototype.setHeight = function setHeight(value) { this.height = value; this.node.style.height = this.height + 'px'; OutputManager.updateProperty(this.id, 'height', this.height + 'px' } // Browser support CssClass.prototype.setRotate = function setRotate(value) { var cssvalue = 'rotate(' + value +'deg)'; this.node.style.transform = cssvalue; this.node.style.webkitTransform = cssvalue; this.node.style.msTransform = cssvalue; if (value !== 0) { if (this.rotate === 0) { OutputManager.toggleProperty(this.id, 'transform', true OutputManager.toggleProperty(this.id, '-webkit-transform', true OutputManager.toggleProperty(this.id, '-ms-transform', true } } else { OutputManager.toggleProperty(this.id, 'transform', false OutputManager.toggleProperty(this.id, '-webkit-transform', false OutputManager.toggleProperty(this.id, '-ms-transform', false } OutputManager.updateProperty(this.id, 'transform', cssvalue OutputManager.updateProperty(this.id, '-webkit-transform', cssvalue OutputManager.updateProperty(this.id, '-ms-transform', cssvalue this.rotate = value; } CssClass.prototype.setzIndex = function setzIndex(value) { this.node.style.zIndex = value; OutputManager.updateProperty(this.id, 'z-index', value this.zIndex = value; } CssClass.prototype.toggleDisplay = function toggleDisplay(value) { if (typeof value !== "boolean" || this.display === value) return; this.display = value; var display = this.display === true ? "block" : "none"; this.node.style.display = display; this.object.style.display = display; } CssClass.prototype.toggleBorder = function toggleBorder(value) { if (typeof value !== "boolean" || this.border === value) return; this.border = value; var border = this.border === true ? "1px solid #CCC" : "none"; this.node.style.border = border; } CssClass.prototype.updateBgColor = function updateBgColor(color) { this.bgcolor.copy(color this.node.style.backgroundColor = color.getColor( OutputManager.updateProperty(this.id, 'background-color', color.getColor() } CssClass.prototype.updateShadows = function updateShadows() { if (this.render.length === 0) OutputManager.toggleProperty(this.id, 'box-shadow', false if (this.render.length === 1) OutputManager.toggleProperty(this.id, 'box-shadow', true this.node.style.boxShadow = this.render.join(", " OutputManager.updateProperty(this.id, 'box-shadow', this.render.join(", \n") } /** * Tool Manager */ var Tool = (function Tool() { var preview; var classes = []; var active = null; var animate = false; /* * Toll actions */ var addCssClass = function addCssClass(id) { classes[id] = new CssClass(id } var setActiveClass = function setActiveClass(id) { active = classes[id]; active.shadowID = null; ColoPicker.setColor(classes[id].bgcolor SliderManager.setValue("top", active.top SliderManager.setValue("left", active.left SliderManager.setValue("rotate", active.rotate SliderManager.setValue("z-index", active.zIndex SliderManager.setValue("width", active.width SliderManager.setValue("height", active.height ButtonManager.setValue("border-state", active.border active.updateShadows( } var disableClass = function disableClass(topic) { classes[topic].toggleDisplay(false ButtonManager.setValue(topic, false } var addShadow = function addShadow(position) { if (animate === true) return -1; active.shadows.splice(position, 0, new Shadow() active.render.splice(position, 0, null } var swapShadow = function swapShadow(id1, id2) { var x = active.shadows[id1]; active.shadows[id1] = active.shadows[id2]; active.shadows[id2] = x; updateShadowCSS(id1 updateShadowCSS(id2 } var deleteShadow = function deleteShadow(position) { active.shadows.splice(position, 1 active.render.splice(position, 1 active.updateShadows( } var setActiveShadow = function setActiveShadow(id, glow) { active.shadowID = id; ColoPicker.setColor(active.shadows[id].color ButtonManager.setValue("inset", active.shadows[id].inset SliderManager.setValue("blur", active.shadows[id].blur SliderManager.setValue("spread", active.shadows[id].spread SliderManager.setValue("posX", active.shadows[id].posX SliderManager.setValue("posY", active.shadows[id].posY if (glow === true) addGlowEffect(id } var addGlowEffect = function addGlowEffect(id) { if (animate === true) return; animate = true; var store = new Shadow( var shadow = active.shadows[id]; store.copy(shadow shadow.color.setRGBA(40, 125, 200, 1 shadow.blur = 10; shadow.spread = 10; active.node.style.transition = "box-shadow 0.2s"; updateShadowCSS(id setTimeout(function() { shadow.copy(store updateShadowCSS(id setTimeout(function() { active.node.style.removeProperty("transition" animate = false; }, 100 }, 200 } var updateActivePos = function updateActivePos(deltaX, deltaY) { if (active.shadowID === null) active.updatePos(deltaX, deltaY else updateShadowPos(deltaX, deltaY } /* * Shadow properties */ var updateShadowCSS = function updateShadowCSS(id) { active.render[id] = active.shadows[id].computeCSS( active.updateShadows( } var toggleShadowInset = function toggleShadowInset(value) { if (active.shadowID === null) return; active.shadows[active.shadowID].toggleInset(value updateShadowCSS(active.shadowID } var updateShadowPos = function updateShadowPos(deltaX, deltaY) { var shadow = active.shadows[active.shadowID]; shadow.posX += deltaX; shadow.posY += deltaY; SliderManager.setValue("posX", shadow.posX SliderManager.setValue("posY", shadow.posY updateShadowCSS(active.shadowID } var setShadowPosX = function setShadowPosX(value) { if (active.shadowID === null) return; active.shadows[active.shadowID].posX = value; updateShadowCSS(active.shadowID } var setShadowPosY = function setShadowPosY(value) { if (active.shadowID === null) return; active.shadows[active.shadowID].posY = value; updateShadowCSS(active.shadowID } var setShadowBlur = function setShadowBlur(value) { if (active.shadowID === null) return; active.shadows[active.shadowID].blur = value; updateShadowCSS(active.shadowID } var setShadowSpread = function setShadowSpread(value) { if (active.shadowID === null) return; active.shadows[active.shadowID].spread = value; updateShadowCSS(active.shadowID } var updateShadowColor = function updateShadowColor(color) { active.shadows[active.shadowID].color.copy(color updateShadowCSS(active.shadowID } /* * Element Properties */ var updateColor = function updateColor(color) { if (active.shadowID === null) active.updateBgColor(color else updateShadowColor(color } var init = function init() { preview = getElemById("preview" ColoPicker.subscribe("color", updateColor PreviewMouseTracking.subscribe(updateActivePos // Affects shadows ButtonManager.subscribe("inset", toggleShadowInset SliderManager.subscribe("posX", setShadowPosX SliderManager.subscribe("posY", setShadowPosY SliderManager.subscribe("blur", setShadowBlur SliderManager.subscribe("spread", setShadowSpread // Affects element SliderManager.subscribe("top", function(value){ active.setTop(value } SliderManager.subscribe("left", function(value){ active.setLeft(value } SliderManager.subscribe("rotate", function(value) { if (active == classes["element"]) return; active.setRotate(value } SliderManager.subscribe("z-index", function(value) { if (active == classes["element"]) return; active.setzIndex(value } SliderManager.subscribe("width", function(value) { active.setWidth(value) } SliderManager.subscribe("height", function(value) { active.setHeight(value) } // Actions classes['before'].top = -30; classes['before'].left = -30; classes['after'].top = 30; classes['after'].left = 30; classes['before'].toggleDisplay(false classes['after'].toggleDisplay(false ButtonManager.setValue('before', false ButtonManager.setValue('after', false ButtonManager.subscribe("before", classes['before'].toggleDisplay.bind(classes['before']) ButtonManager.subscribe("after", classes['after'].toggleDisplay.bind(classes['after']) ButtonManager.subscribe("border-state", function(value) { active.toggleBorder(value } } return { init : init, addShadow : addShadow, swapShadow : swapShadow, addCssClass : addCssClass, disableClass : disableClass, deleteShadow : deleteShadow, setActiveClass : setActiveClass, setActiveShadow : setActiveShadow } })( /** * Layer Manager */ var LayerManager = (function LayerManager() { var stacks = []; var active = { node : null, stack : null } var elements = {}; var mouseEvents = function mouseEvents(e) { var node = e.target; var type = node.getAttribute('data-type' if (type === 'subject') setActiveStack(stacks[node.id] if (type === 'disable') { Tool.disableClass(node.parentNode.id setActiveStack(stacks['element'] } if (type === 'add') active.stack.addLayer( if (type === 'layer') active.stack.setActiveLayer(node if (type === 'delete') active.stack.deleteLayer(node.parentNode if (type === 'move-up') active.stack.moveLayer(1 if (type === 'move-down') active.stack.moveLayer(-1 } var setActiveStack = function setActiveStack(stackObj) { active.stack.hide( active.stack = stackObj; active.stack.show( } /* * Stack object */ var Stack = function Stack(subject) { var S = document.createElement('div' var title = document.createElement('div' var stack = document.createElement('div' S.className = 'container'; stack.className = 'stack'; title.className = 'title'; title.textContent = subject.getAttribute('data-title' S.appendChild(title S.appendChild(stack this.id = subject.id; this.container = S; this.stack = stack; this.subject = subject; this.order = []; this.uid = 0; this.count = 0; this.layer = null; this.layerID = 0; } Stack.prototype.addLayer = function addLayer() { if (Tool.addShadow(this.layerID) == -1) return; var uid = this.getUID( var layer = this.createLayer(uid if (this.layer === null && this.stack.children.length >= 1) this.layer = this.stack.children[0]; this.stack.insertBefore(layer, this.layer this.order.splice(this.layerID, 0, uid this.count++; this.setActiveLayer(layer } Stack.prototype.createLayer = function createLayer(uid) { var layer = document.createElement('div' var del = document.createElement('span' layer.className = 'node'; layer.setAttribute('data-shid', uid layer.setAttribute('data-type', 'layer' layer.textContent = 'shadow ' + uid; del.className = 'delete'; del.setAttribute('data-type', 'delete' layer.appendChild(del return layer; } Stack.prototype.getUID = function getUID() { return this.uid++; } // SOLVE IE BUG Stack.prototype.moveLayer = function moveLayer(direction) { if (this.count <= 1 || this.layer === null) return; if (direction === -1 && this.layerID === (this.count - 1) ) return; if (direction === 1 && this.layerID === 0 ) return; if (direction === -1) { var before = null; Tool.swapShadow(this.layerID, this.layerID + 1 this.swapOrder(this.layerID, this.layerID + 1 this.layerID += 1; if (this.layerID + 1 !== this.count) before = this.stack.children[this.layerID + 1]; this.stack.insertBefore(this.layer, before Tool.setActiveShadow(this.layerID, false } if (direction === 1) { Tool.swapShadow(this.layerID, this.layerID - 1 this.swapOrder(this.layerID, this.layerID - 1 this.layerID -= 1; this.stack.insertBefore(this.layer, this.stack.children[this.layerID] Tool.setActiveShadow(this.layerID, false } } Stack.prototype.swapOrder = function swapOrder(pos1, pos2) { var x = this.order[pos1]; this.order[pos1] = this.order[pos2]; this.order[pos2] = x; } Stack.prototype.deleteLayer = function deleteLayer(node) { var shadowID = node.getAttribute('data-shid') | 0; var index = this.order.indexOf(shadowID this.stack.removeChild(this.stack.children[index] this.order.splice(index, 1 this.count--; Tool.deleteShadow(index if (index > this.layerID) return; if (index == this.layerID) { if (this.count >= 1) { this.layerID = 0; this.setActiveLayer(this.stack.children[0], true } else { this.layer = null; this.show( } } if (index < this.layerID) { this.layerID--; Tool.setActiveShadow(this.layerID, true } } Stack.prototype.setActiveLayer = function setActiveLayer(node) { elements.shadow_properties.style.display = 'block'; elements.element_properties.style.display = 'none'; if (this.layer) this.layer.removeAttribute('data-active' this.layer = node; this.layer.setAttribute('data-active', 'layer' var shadowID = node.getAttribute('data-shid') | 0; this.layerID = this.order.indexOf(shadowID Tool.setActiveShadow(this.layerID, true } Stack.prototype.unsetActiveLayer = function unsetActiveLayer() { if (this.layer) this.layer.removeAttribute('data-active' this.layer = null; this.layerID = 0; } Stack.prototype.hide = function hide() { this.unsetActiveLayer( this.subject.removeAttribute('data-active' var style = this.container.style; style.left = '100%'; style.zIndex = '0'; } Stack.prototype.show = function show() { elements.shadow_properties.style.display = 'none'; elements.element_properties.style.display = 'block'; if (this.id === 'element') { elements.zIndex.style.display = 'none'; elements.transform_rotate.style.display = 'none'; } else { elements.zIndex.style.display = 'block'; elements.transform_rotate.style.display = 'block'; } this.subject.setAttribute('data-active', 'subject' var style = this.container.style; style.left = '0'; style.zIndex = '10'; Tool.setActiveClass(this.id } function init() { var elem, size; var layerManager = getElemById("layer_manager" var layerMenu = getElemById("layer_menu" var container = getElemById("stack_container" elements.shadow_properties = getElemById('shadow_properties' elements.element_properties = getElemById('element_properties' elements.transform_rotate = getElemById('transform_rotate' elements.zIndex = getElemById('z-index' elem = document.querySelectorAll('#layer_menu [data-type="subject"]' size = elem.length; for (var i = 0; i < size; i++) { var S = new Stack(elem[i] stacks[elem[i].id] = S; container.appendChild(S.container Tool.addCssClass(elem[i].id } active.stack = stacks['element']; stacks['element'].show( layerManager.addEventListener("click", mouseEvents layerMenu.addEventListener("click", mouseEvents ButtonManager.subscribe("before", function(value) { if (value === false && active.stack === stacks['before']) setActiveStack(stacks['element']) if (value === true && active.stack !== stacks['before']) setActiveStack(stacks['before']) } ButtonManager.subscribe("after", function(value) { if (value === false && active.stack === stacks['after']) setActiveStack(stacks['element']) if (value === true && active.stack !== stacks['after']) setActiveStack(stacks['after']) } } return { init : init } })( /* * OutputManager */ var OutputManager = (function OutputManager() { var classes = []; var buttons = []; var active = null; var menu = null; var button_offset = 0; var crateOutputNode = function(topic, property) { var prop = document.createElement('div' var name = document.createElement('span' var value = document.createElement('span' var pmatch = property.match(/(^([a-z0-9\-]*)=\[([a-z0-9\-\"]*)\])|^([a-z0-9\-]*)/i name.textContent = '\t' + pmatch[4]; if (pmatch[3] !== undefined) { name.textContent = '\t' + pmatch[2]; value.textContent = pmatch[3] + ';'; } name.textContent += ': '; prop.className = 'css-property'; name.className = 'name'; value.className = 'value'; prop.appendChild(name prop.appendChild(value classes[topic].node.appendChild(prop classes[topic].line[property] = prop; classes[topic].prop[property] = value; } var OutputClass = function OutputClass(node) { var topic = node.getAttribute('data-topic' var prop = node.getAttribute('data-prop' var name = node.getAttribute('data-name' var properties = prop.split(' ' classes[topic] = {}; classes[topic].node = node; classes[topic].prop = []; classes[topic].line = []; classes[topic].button = new Button(topic var open_decl = document.createElement('div' var end_decl = document.createElement('div' open_decl.textContent = name + ' {'; end_decl.textContent = '}'; node.appendChild(open_decl for (var i in properties) crateOutputNode(topic, properties[i] node.appendChild(end_decl } var Button = function Button(topic) { var button = document.createElement('div' button.className = 'button'; button.textContent = topic; button.style.left = button_offset + 'px'; button_offset += 100; button.addEventListener("click", function() { toggleDisplay(topic }) menu.appendChild(button return button; } var toggleDisplay = function toggleDisplay(topic) { active.button.removeAttribute('data-active' active.node.style.display = 'none'; active = classes[topic]; active.node.style.display = 'block'; active.button.setAttribute('data-active', 'true' } var toggleButton = function toggleButton(topic, value) { var display = (value === true) ? 'block' : 'none'; classes[topic].button.style.display = display; if (value === true) toggleDisplay(topic else toggleDisplay('element' } var updateProperty = function updateProperty(topic, property, data) { try { classes[topic].prop[property].textContent = data + ';'; } catch(error) { // console.log("ERROR undefined : ", topic, property, data } } var toggleProperty = function toggleProperty(topic, property, value) { var display = (value === true) ? 'block' : 'none'; try { classes[topic].line[property].style.display = display; } catch(error) { // console.log("ERROR undefined : ",classes, topic, property, value } } var init = function init() { menu = getElemById('menu' var elem = document.querySelectorAll('#output .output' var size = elem.length; for (var i = 0; i < size; i++) OutputClass(elem[i] active = classes['element']; toggleDisplay('element' ButtonManager.subscribe("before", function(value) { toggleButton('before', value } ButtonManager.subscribe("after", function(value) { toggleButton('after', value } } return { init : init, updateProperty : updateProperty, toggleProperty : toggleProperty } })( /** * Init Tool */ var init = function init() { ButtonManager.init( OutputManager.init( ColoPicker.init( SliderManager.init( LayerManager.init( PreviewMouseTracking.init("preview" Tool.init( } return { init : init } })(

相关工具: Box Shadow CSS Generator