diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..485dee64 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.idea diff --git a/.idea/misc.xml b/.idea/misc.xml deleted file mode 100644 index 28a804d8..00000000 --- a/.idea/misc.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - \ No newline at end of file diff --git a/.idea/php.xml b/.idea/php.xml new file mode 100644 index 00000000..f324872a --- /dev/null +++ b/.idea/php.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml index 94a25f7f..35eb1ddf 100644 --- a/.idea/vcs.xml +++ b/.idea/vcs.xml @@ -1,6 +1,6 @@ - + \ No newline at end of file diff --git a/.idea/workspace.xml b/.idea/workspace.xml index 76733042..ef267ca1 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -1,27 +1,13 @@ - - - - - - - - - - - - - - - - - + +
+ + +
+
+ + +
+
+ + +
+
+ + +
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ + +
+
+ +
+
+ +
+
+ +
+
+ + +
+
+ +
+
+
+
+ +
+
+ +
+
+ +
+
+ + +
+
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git "a/web/112 \350\214\266\345\217\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/css/bootstrap-3.3.4.css" "b/web/112 \350\214\266\345\217\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/css/bootstrap-3.3.4.css" new file mode 100644 index 00000000..85b74019 --- /dev/null +++ "b/web/112 \350\214\266\345\217\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/css/bootstrap-3.3.4.css" @@ -0,0 +1,3 @@ +/*-防止各大cdn公共库加载地址失效问题,此地址我们会时时监控,及调整-www.jq22.com为您服务*/ +/*当前为百度 cdn公共库提供的bootstrap-3.3.4 Css样式文件*/ +@import url("bootstrap.css"); diff --git "a/web/112 \350\214\266\345\217\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/css/bootstrap.css" "b/web/112 \350\214\266\345\217\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/css/bootstrap.css" new file mode 100644 index 00000000..15179b7f --- /dev/null +++ "b/web/112 \350\214\266\345\217\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/css/bootstrap.css" @@ -0,0 +1,6584 @@ +/*! + * Bootstrap v3.3.4 (http://getbootstrap.com) + * Copyright 2011-2015 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + */ + +/*! normalize.css v3.0.2 | MIT License | git.io/normalize */ +html { + font-family: sans-serif; + -webkit-text-size-adjust: 100%; + -ms-text-size-adjust: 100%; +} +body { + margin: 0; +} +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +main, +menu, +nav, +section, +summary { + display: block; +} +audio, +canvas, +progress, +video { + display: inline-block; + vertical-align: baseline; +} +audio:not([controls]) { + display: none; + height: 0; +} +[hidden], +template { + display: none; +} +a { + background-color: transparent; +} +a:active, +a:hover { + outline: 0; +} +abbr[title] { + border-bottom: 1px dotted; +} +b, +strong { + font-weight: bold; +} +dfn { + font-style: italic; +} +h1 { + margin: .67em 0; + font-size: 2em; +} +mark { + color: #000; + background: #ff0; +} +small { + font-size: 80%; +} +sub, +sup { + position: relative; + font-size: 75%; + line-height: 0; + vertical-align: baseline; +} +sup { + top: -.5em; +} +sub { + bottom: -.25em; +} +img { + border: 0; +} +svg:not(:root) { + overflow: hidden; +} +figure { + margin: 1em 40px; +} +hr { + height: 0; + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; +} +pre { + overflow: auto; +} +code, +kbd, +pre, +samp { + font-family: monospace, monospace; + font-size: 1em; +} +button, +input, +optgroup, +select, +textarea { + margin: 0; + font: inherit; + color: inherit; +} +button { + overflow: visible; +} +button, +select { + text-transform: none; +} +button, +html input[type="button"], +input[type="reset"], +input[type="submit"] { + -webkit-appearance: button; + cursor: pointer; +} +button[disabled], +html input[disabled] { + cursor: default; +} +button::-moz-focus-inner, +input::-moz-focus-inner { + padding: 0; + border: 0; +} +input { + line-height: normal; +} +input[type="checkbox"], +input[type="radio"] { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + padding: 0; +} +input[type="number"]::-webkit-inner-spin-button, +input[type="number"]::-webkit-outer-spin-button { + height: auto; +} +input[type="search"] { + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; + -webkit-appearance: textfield; +} +input[type="search"]::-webkit-search-cancel-button, +input[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; +} +fieldset { + padding: .35em .625em .75em; + margin: 0 2px; + border: 1px solid #c0c0c0; +} +legend { + padding: 0; + border: 0; +} +textarea { + overflow: auto; +} +optgroup { + font-weight: bold; +} +table { + border-spacing: 0; + border-collapse: collapse; +} +td, +th { + padding: 0; +} +/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */ +@media print { + *, + *:before, + *:after { + color: #000 !important; + text-shadow: none !important; + background: transparent !important; + -webkit-box-shadow: none !important; + box-shadow: none !important; + } + a, + a:visited { + text-decoration: underline; + } + a[href]:after { + content: " (" attr(href) ")"; + } + abbr[title]:after { + content: " (" attr(title) ")"; + } + a[href^="#"]:after, + a[href^="javascript:"]:after { + content: ""; + } + pre, + blockquote { + border: 1px solid #999; + + page-break-inside: avoid; + } + thead { + display: table-header-group; + } + tr, + img { + page-break-inside: avoid; + } + img { + max-width: 100% !important; + } + p, + h2, + h3 { + orphans: 3; + widows: 3; + } + h2, + h3 { + page-break-after: avoid; + } + select { + background: #fff !important; + } + .navbar { + display: none; + } + .btn > .caret, + .dropup > .btn > .caret { + border-top-color: #000 !important; + } + .label { + border: 1px solid #000; + } + .table { + border-collapse: collapse !important; + } + .table td, + .table th { + background-color: #fff !important; + } + .table-bordered th, + .table-bordered td { + border: 1px solid #ddd !important; + } +} +@font-face { + font-family: 'Glyphicons Halflings'; + + src: url('../fonts/glyphicons-halflings-regular.eot'); + src: url('../fonts/glyphicons-halflings-regular.eot') format('embedded-opentype'), url('../fonts/glyphicons-halflings-regular.woff2') format('woff2'), url('../fonts/glyphicons-halflings-regular.woff') format('woff'), url('../fonts/glyphicons-halflings-regular.ttf') format('truetype'), url('../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg'); +} +.glyphicon { + position: relative; + top: 1px; + display: inline-block; + font-family: 'Glyphicons Halflings'; + font-style: normal; + font-weight: normal; + line-height: 1; + + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} +.glyphicon-asterisk:before { + content: "\2a"; +} +.glyphicon-plus:before { + content: "\2b"; +} +.glyphicon-euro:before, +.glyphicon-eur:before { + content: "\20ac"; +} +.glyphicon-minus:before { + content: "\2212"; +} +.glyphicon-cloud:before { + content: "\2601"; +} +.glyphicon-envelope:before { + content: "\2709"; +} +.glyphicon-pencil:before { + content: "\270f"; +} +.glyphicon-glass:before { + content: "\e001"; +} +.glyphicon-music:before { + content: "\e002"; +} +.glyphicon-search:before { + content: "\e003"; +} +.glyphicon-heart:before { + content: "\e005"; +} +.glyphicon-star:before { + content: "\e006"; +} +.glyphicon-star-empty:before { + content: "\e007"; +} +.glyphicon-user:before { + content: "\e008"; +} +.glyphicon-film:before { + content: "\e009"; +} +.glyphicon-th-large:before { + content: "\e010"; +} +.glyphicon-th:before { + content: "\e011"; +} +.glyphicon-th-list:before { + content: "\e012"; +} +.glyphicon-ok:before { + content: "\e013"; +} +.glyphicon-remove:before { + content: "\e014"; +} +.glyphicon-zoom-in:before { + content: "\e015"; +} +.glyphicon-zoom-out:before { + content: "\e016"; +} +.glyphicon-off:before { + content: "\e017"; +} +.glyphicon-signal:before { + content: "\e018"; +} +.glyphicon-cog:before { + content: "\e019"; +} +.glyphicon-trash:before { + content: "\e020"; +} +.glyphicon-home:before { + content: "\e021"; +} +.glyphicon-file:before { + content: "\e022"; +} +.glyphicon-time:before { + content: "\e023"; +} +.glyphicon-road:before { + content: "\e024"; +} +.glyphicon-download-alt:before { + content: "\e025"; +} +.glyphicon-download:before { + content: "\e026"; +} +.glyphicon-upload:before { + content: "\e027"; +} +.glyphicon-inbox:before { + content: "\e028"; +} +.glyphicon-play-circle:before { + content: "\e029"; +} +.glyphicon-repeat:before { + content: "\e030"; +} +.glyphicon-refresh:before { + content: "\e031"; +} +.glyphicon-list-alt:before { + content: "\e032"; +} +.glyphicon-lock:before { + content: "\e033"; +} +.glyphicon-flag:before { + content: "\e034"; +} +.glyphicon-headphones:before { + content: "\e035"; +} +.glyphicon-volume-off:before { + content: "\e036"; +} +.glyphicon-volume-down:before { + content: "\e037"; +} +.glyphicon-volume-up:before { + content: "\e038"; +} +.glyphicon-qrcode:before { + content: "\e039"; +} +.glyphicon-barcode:before { + content: "\e040"; +} +.glyphicon-tag:before { + content: "\e041"; +} +.glyphicon-tags:before { + content: "\e042"; +} +.glyphicon-book:before { + content: "\e043"; +} +.glyphicon-bookmark:before { + content: "\e044"; +} +.glyphicon-print:before { + content: "\e045"; +} +.glyphicon-camera:before { + content: "\e046"; +} +.glyphicon-font:before { + content: "\e047"; +} +.glyphicon-bold:before { + content: "\e048"; +} +.glyphicon-italic:before { + content: "\e049"; +} +.glyphicon-text-height:before { + content: "\e050"; +} +.glyphicon-text-width:before { + content: "\e051"; +} +.glyphicon-align-left:before { + content: "\e052"; +} +.glyphicon-align-center:before { + content: "\e053"; +} +.glyphicon-align-right:before { + content: "\e054"; +} +.glyphicon-align-justify:before { + content: "\e055"; +} +.glyphicon-list:before { + content: "\e056"; +} +.glyphicon-indent-left:before { + content: "\e057"; +} +.glyphicon-indent-right:before { + content: "\e058"; +} +.glyphicon-facetime-video:before { + content: "\e059"; +} +.glyphicon-picture:before { + content: "\e060"; +} +.glyphicon-map-marker:before { + content: "\e062"; +} +.glyphicon-adjust:before { + content: "\e063"; +} +.glyphicon-tint:before { + content: "\e064"; +} +.glyphicon-edit:before { + content: "\e065"; +} +.glyphicon-share:before { + content: "\e066"; +} +.glyphicon-check:before { + content: "\e067"; +} +.glyphicon-move:before { + content: "\e068"; +} +.glyphicon-step-backward:before { + content: "\e069"; +} +.glyphicon-fast-backward:before { + content: "\e070"; +} +.glyphicon-backward:before { + content: "\e071"; +} +.glyphicon-play:before { + content: "\e072"; +} +.glyphicon-pause:before { + content: "\e073"; +} +.glyphicon-stop:before { + content: "\e074"; +} +.glyphicon-forward:before { + content: "\e075"; +} +.glyphicon-fast-forward:before { + content: "\e076"; +} +.glyphicon-step-forward:before { + content: "\e077"; +} +.glyphicon-eject:before { + content: "\e078"; +} +.glyphicon-chevron-left:before { + content: "\e079"; +} +.glyphicon-chevron-right:before { + content: "\e080"; +} +.glyphicon-plus-sign:before { + content: "\e081"; +} +.glyphicon-minus-sign:before { + content: "\e082"; +} +.glyphicon-remove-sign:before { + content: "\e083"; +} +.glyphicon-ok-sign:before { + content: "\e084"; +} +.glyphicon-question-sign:before { + content: "\e085"; +} +.glyphicon-info-sign:before { + content: "\e086"; +} +.glyphicon-screenshot:before { + content: "\e087"; +} +.glyphicon-remove-circle:before { + content: "\e088"; +} +.glyphicon-ok-circle:before { + content: "\e089"; +} +.glyphicon-ban-circle:before { + content: "\e090"; +} +.glyphicon-arrow-left:before { + content: "\e091"; +} +.glyphicon-arrow-right:before { + content: "\e092"; +} +.glyphicon-arrow-up:before { + content: "\e093"; +} +.glyphicon-arrow-down:before { + content: "\e094"; +} +.glyphicon-share-alt:before { + content: "\e095"; +} +.glyphicon-resize-full:before { + content: "\e096"; +} +.glyphicon-resize-small:before { + content: "\e097"; +} +.glyphicon-exclamation-sign:before { + content: "\e101"; +} +.glyphicon-gift:before { + content: "\e102"; +} +.glyphicon-leaf:before { + content: "\e103"; +} +.glyphicon-fire:before { + content: "\e104"; +} +.glyphicon-eye-open:before { + content: "\e105"; +} +.glyphicon-eye-close:before { + content: "\e106"; +} +.glyphicon-warning-sign:before { + content: "\e107"; +} +.glyphicon-plane:before { + content: "\e108"; +} +.glyphicon-calendar:before { + content: "\e109"; +} +.glyphicon-random:before { + content: "\e110"; +} +.glyphicon-comment:before { + content: "\e111"; +} +.glyphicon-magnet:before { + content: "\e112"; +} +.glyphicon-chevron-up:before { + content: "\e113"; +} +.glyphicon-chevron-down:before { + content: "\e114"; +} +.glyphicon-retweet:before { + content: "\e115"; +} +.glyphicon-shopping-cart:before { + content: "\e116"; +} +.glyphicon-folder-close:before { + content: "\e117"; +} +.glyphicon-folder-open:before { + content: "\e118"; +} +.glyphicon-resize-vertical:before { + content: "\e119"; +} +.glyphicon-resize-horizontal:before { + content: "\e120"; +} +.glyphicon-hdd:before { + content: "\e121"; +} +.glyphicon-bullhorn:before { + content: "\e122"; +} +.glyphicon-bell:before { + content: "\e123"; +} +.glyphicon-certificate:before { + content: "\e124"; +} +.glyphicon-thumbs-up:before { + content: "\e125"; +} +.glyphicon-thumbs-down:before { + content: "\e126"; +} +.glyphicon-hand-right:before { + content: "\e127"; +} +.glyphicon-hand-left:before { + content: "\e128"; +} +.glyphicon-hand-up:before { + content: "\e129"; +} +.glyphicon-hand-down:before { + content: "\e130"; +} +.glyphicon-circle-arrow-right:before { + content: "\e131"; +} +.glyphicon-circle-arrow-left:before { + content: "\e132"; +} +.glyphicon-circle-arrow-up:before { + content: "\e133"; +} +.glyphicon-circle-arrow-down:before { + content: "\e134"; +} +.glyphicon-globe:before { + content: "\e135"; +} +.glyphicon-wrench:before { + content: "\e136"; +} +.glyphicon-tasks:before { + content: "\e137"; +} +.glyphicon-filter:before { + content: "\e138"; +} +.glyphicon-briefcase:before { + content: "\e139"; +} +.glyphicon-fullscreen:before { + content: "\e140"; +} +.glyphicon-dashboard:before { + content: "\e141"; +} +.glyphicon-paperclip:before { + content: "\e142"; +} +.glyphicon-heart-empty:before { + content: "\e143"; +} +.glyphicon-link:before { + content: "\e144"; +} +.glyphicon-phone:before { + content: "\e145"; +} +.glyphicon-pushpin:before { + content: "\e146"; +} +.glyphicon-usd:before { + content: "\e148"; +} +.glyphicon-gbp:before { + content: "\e149"; +} +.glyphicon-sort:before { + content: "\e150"; +} +.glyphicon-sort-by-alphabet:before { + content: "\e151"; +} +.glyphicon-sort-by-alphabet-alt:before { + content: "\e152"; +} +.glyphicon-sort-by-order:before { + content: "\e153"; +} +.glyphicon-sort-by-order-alt:before { + content: "\e154"; +} +.glyphicon-sort-by-attributes:before { + content: "\e155"; +} +.glyphicon-sort-by-attributes-alt:before { + content: "\e156"; +} +.glyphicon-unchecked:before { + content: "\e157"; +} +.glyphicon-expand:before { + content: "\e158"; +} +.glyphicon-collapse-down:before { + content: "\e159"; +} +.glyphicon-collapse-up:before { + content: "\e160"; +} +.glyphicon-log-in:before { + content: "\e161"; +} +.glyphicon-flash:before { + content: "\e162"; +} +.glyphicon-log-out:before { + content: "\e163"; +} +.glyphicon-new-window:before { + content: "\e164"; +} +.glyphicon-record:before { + content: "\e165"; +} +.glyphicon-save:before { + content: "\e166"; +} +.glyphicon-open:before { + content: "\e167"; +} +.glyphicon-saved:before { + content: "\e168"; +} +.glyphicon-import:before { + content: "\e169"; +} +.glyphicon-export:before { + content: "\e170"; +} +.glyphicon-send:before { + content: "\e171"; +} +.glyphicon-floppy-disk:before { + content: "\e172"; +} +.glyphicon-floppy-saved:before { + content: "\e173"; +} +.glyphicon-floppy-remove:before { + content: "\e174"; +} +.glyphicon-floppy-save:before { + content: "\e175"; +} +.glyphicon-floppy-open:before { + content: "\e176"; +} +.glyphicon-credit-card:before { + content: "\e177"; +} +.glyphicon-transfer:before { + content: "\e178"; +} +.glyphicon-cutlery:before { + content: "\e179"; +} +.glyphicon-header:before { + content: "\e180"; +} +.glyphicon-compressed:before { + content: "\e181"; +} +.glyphicon-earphone:before { + content: "\e182"; +} +.glyphicon-phone-alt:before { + content: "\e183"; +} +.glyphicon-tower:before { + content: "\e184"; +} +.glyphicon-stats:before { + content: "\e185"; +} +.glyphicon-sd-video:before { + content: "\e186"; +} +.glyphicon-hd-video:before { + content: "\e187"; +} +.glyphicon-subtitles:before { + content: "\e188"; +} +.glyphicon-sound-stereo:before { + content: "\e189"; +} +.glyphicon-sound-dolby:before { + content: "\e190"; +} +.glyphicon-sound-5-1:before { + content: "\e191"; +} +.glyphicon-sound-6-1:before { + content: "\e192"; +} +.glyphicon-sound-7-1:before { + content: "\e193"; +} +.glyphicon-copyright-mark:before { + content: "\e194"; +} +.glyphicon-registration-mark:before { + content: "\e195"; +} +.glyphicon-cloud-download:before { + content: "\e197"; +} +.glyphicon-cloud-upload:before { + content: "\e198"; +} +.glyphicon-tree-conifer:before { + content: "\e199"; +} +.glyphicon-tree-deciduous:before { + content: "\e200"; +} +.glyphicon-cd:before { + content: "\e201"; +} +.glyphicon-save-file:before { + content: "\e202"; +} +.glyphicon-open-file:before { + content: "\e203"; +} +.glyphicon-level-up:before { + content: "\e204"; +} +.glyphicon-copy:before { + content: "\e205"; +} +.glyphicon-paste:before { + content: "\e206"; +} +.glyphicon-alert:before { + content: "\e209"; +} +.glyphicon-equalizer:before { + content: "\e210"; +} +.glyphicon-king:before { + content: "\e211"; +} +.glyphicon-queen:before { + content: "\e212"; +} +.glyphicon-pawn:before { + content: "\e213"; +} +.glyphicon-bishop:before { + content: "\e214"; +} +.glyphicon-knight:before { + content: "\e215"; +} +.glyphicon-baby-formula:before { + content: "\e216"; +} +.glyphicon-tent:before { + content: "\26fa"; +} +.glyphicon-blackboard:before { + content: "\e218"; +} +.glyphicon-bed:before { + content: "\e219"; +} +.glyphicon-apple:before { + content: "\f8ff"; +} +.glyphicon-erase:before { + content: "\e221"; +} +.glyphicon-hourglass:before { + content: "\231b"; +} +.glyphicon-lamp:before { + content: "\e223"; +} +.glyphicon-duplicate:before { + content: "\e224"; +} +.glyphicon-piggy-bank:before { + content: "\e225"; +} +.glyphicon-scissors:before { + content: "\e226"; +} +.glyphicon-bitcoin:before { + content: "\e227"; +} +.glyphicon-btc:before { + content: "\e227"; +} +.glyphicon-xbt:before { + content: "\e227"; +} +.glyphicon-yen:before { + content: "\00a5"; +} +.glyphicon-jpy:before { + content: "\00a5"; +} +.glyphicon-ruble:before { + content: "\20bd"; +} +.glyphicon-rub:before { + content: "\20bd"; +} +.glyphicon-scale:before { + content: "\e230"; +} +.glyphicon-ice-lolly:before { + content: "\e231"; +} +.glyphicon-ice-lolly-tasted:before { + content: "\e232"; +} +.glyphicon-education:before { + content: "\e233"; +} +.glyphicon-option-horizontal:before { + content: "\e234"; +} +.glyphicon-option-vertical:before { + content: "\e235"; +} +.glyphicon-menu-hamburger:before { + content: "\e236"; +} +.glyphicon-modal-window:before { + content: "\e237"; +} +.glyphicon-oil:before { + content: "\e238"; +} +.glyphicon-grain:before { + content: "\e239"; +} +.glyphicon-sunglasses:before { + content: "\e240"; +} +.glyphicon-text-size:before { + content: "\e241"; +} +.glyphicon-text-color:before { + content: "\e242"; +} +.glyphicon-text-background:before { + content: "\e243"; +} +.glyphicon-object-align-top:before { + content: "\e244"; +} +.glyphicon-object-align-bottom:before { + content: "\e245"; +} +.glyphicon-object-align-horizontal:before { + content: "\e246"; +} +.glyphicon-object-align-left:before { + content: "\e247"; +} +.glyphicon-object-align-vertical:before { + content: "\e248"; +} +.glyphicon-object-align-right:before { + content: "\e249"; +} +.glyphicon-triangle-right:before { + content: "\e250"; +} +.glyphicon-triangle-left:before { + content: "\e251"; +} +.glyphicon-triangle-bottom:before { + content: "\e252"; +} +.glyphicon-triangle-top:before { + content: "\e253"; +} +.glyphicon-console:before { + content: "\e254"; +} +.glyphicon-superscript:before { + content: "\e255"; +} +.glyphicon-subscript:before { + content: "\e256"; +} +.glyphicon-menu-left:before { + content: "\e257"; +} +.glyphicon-menu-right:before { + content: "\e258"; +} +.glyphicon-menu-down:before { + content: "\e259"; +} +.glyphicon-menu-up:before { + content: "\e260"; +} +* { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +*:before, +*:after { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +html { + font-size: 10px; + + -webkit-tap-highlight-color: rgba(0, 0, 0, 0); +} +body { + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 14px; + line-height: 1.42857143; + color: #333; + background-color: #fff; +} +input, +button, +select, +textarea { + font-family: inherit; + font-size: inherit; + line-height: inherit; +} +a { + color: #337ab7; + text-decoration: none; +} +a:hover, +a:focus { + color: #23527c; + text-decoration: underline; +} +a:focus { + outline: thin dotted; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} +figure { + margin: 0; +} +img { + vertical-align: middle; +} +.img-responsive, +.thumbnail > img, +.thumbnail a > img, +.carousel-inner > .item > img, +.carousel-inner > .item > a > img { + display: block; + max-width: 100%; + height: auto; +} +.img-rounded { + border-radius: 6px; +} +.img-thumbnail { + display: inline-block; + max-width: 100%; + height: auto; + padding: 4px; + line-height: 1.42857143; + background-color: #fff; + border: 1px solid #ddd; + border-radius: 4px; + -webkit-transition: all .2s ease-in-out; + -o-transition: all .2s ease-in-out; + transition: all .2s ease-in-out; +} +.img-circle { + border-radius: 50%; +} +hr { + margin-top: 20px; + margin-bottom: 20px; + border: 0; + border-top: 1px solid #eee; +} +.sr-only { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; +} +.sr-only-focusable:active, +.sr-only-focusable:focus { + position: static; + width: auto; + height: auto; + margin: 0; + overflow: visible; + clip: auto; +} +[role="button"] { + cursor: pointer; +} +h1, +h2, +h3, +h4, +h5, +h6, +.h1, +.h2, +.h3, +.h4, +.h5, +.h6 { + font-family: inherit; + font-weight: 500; + line-height: 1.1; + color: inherit; +} +h1 small, +h2 small, +h3 small, +h4 small, +h5 small, +h6 small, +.h1 small, +.h2 small, +.h3 small, +.h4 small, +.h5 small, +.h6 small, +h1 .small, +h2 .small, +h3 .small, +h4 .small, +h5 .small, +h6 .small, +.h1 .small, +.h2 .small, +.h3 .small, +.h4 .small, +.h5 .small, +.h6 .small { + font-weight: normal; + line-height: 1; + color: #777; +} +h1, +.h1, +h2, +.h2, +h3, +.h3 { + margin-top: 20px; + margin-bottom: 10px; +} +h1 small, +.h1 small, +h2 small, +.h2 small, +h3 small, +.h3 small, +h1 .small, +.h1 .small, +h2 .small, +.h2 .small, +h3 .small, +.h3 .small { + font-size: 65%; +} +h4, +.h4, +h5, +.h5, +h6, +.h6 { + margin-top: 10px; + margin-bottom: 10px; +} +h4 small, +.h4 small, +h5 small, +.h5 small, +h6 small, +.h6 small, +h4 .small, +.h4 .small, +h5 .small, +.h5 .small, +h6 .small, +.h6 .small { + font-size: 75%; +} +h1, +.h1 { + font-size: 36px; +} +h2, +.h2 { + font-size: 30px; +} +h3, +.h3 { + font-size: 24px; +} +h4, +.h4 { + font-size: 18px; +} +h5, +.h5 { + font-size: 14px; +} +h6, +.h6 { + font-size: 12px; +} +p { + margin: 0 0 10px; +} +.lead { + margin-bottom: 20px; + font-size: 16px; + font-weight: 300; + line-height: 1.4; +} +@media (min-width: 768px) { + .lead { + font-size: 21px; + } +} +small, +.small { + font-size: 85%; +} +mark, +.mark { + padding: .2em; + background-color: #fcf8e3; +} +.text-left { + text-align: left; +} +.text-right { + text-align: right; +} +.text-center { + text-align: center; +} +.text-justify { + text-align: justify; +} +.text-nowrap { + white-space: nowrap; +} +.text-lowercase { + text-transform: lowercase; +} +.text-uppercase { + text-transform: uppercase; +} +.text-capitalize { + text-transform: capitalize; +} +.text-muted { + color: #777; +} +.text-primary { + color: #337ab7; +} +a.text-primary:hover { + color: #286090; +} +.text-success { + color: #3c763d; +} +a.text-success:hover { + color: #2b542c; +} +.text-info { + color: #31708f; +} +a.text-info:hover { + color: #245269; +} +.text-warning { + color: #8a6d3b; +} +a.text-warning:hover { + color: #66512c; +} +.text-danger { + color: #a94442; +} +a.text-danger:hover { + color: #843534; +} +.bg-primary { + color: #fff; + background-color: #337ab7; +} +a.bg-primary:hover { + background-color: #286090; +} +.bg-success { + background-color: #dff0d8; +} +a.bg-success:hover { + background-color: #c1e2b3; +} +.bg-info { + background-color: #d9edf7; +} +a.bg-info:hover { + background-color: #afd9ee; +} +.bg-warning { + background-color: #fcf8e3; +} +a.bg-warning:hover { + background-color: #f7ecb5; +} +.bg-danger { + background-color: #f2dede; +} +a.bg-danger:hover { + background-color: #e4b9b9; +} +.page-header { + padding-bottom: 9px; + margin: 40px 0 20px; + border-bottom: 1px solid #eee; +} +ul, +ol { + margin-top: 0; + margin-bottom: 10px; +} +ul ul, +ol ul, +ul ol, +ol ol { + margin-bottom: 0; +} +.list-unstyled { + padding-left: 0; + list-style: none; +} +.list-inline { + padding-left: 0; + margin-left: -5px; + list-style: none; +} +.list-inline > li { + display: inline-block; + padding-right: 5px; + padding-left: 5px; +} +dl { + margin-top: 0; + margin-bottom: 20px; +} +dt, +dd { + line-height: 1.42857143; +} +dt { + font-weight: bold; +} +dd { + margin-left: 0; +} +@media (min-width: 768px) { + .dl-horizontal dt { + float: left; + width: 160px; + overflow: hidden; + clear: left; + text-align: right; + text-overflow: ellipsis; + white-space: nowrap; + } + .dl-horizontal dd { + margin-left: 180px; + } +} +abbr[title], +abbr[data-original-title] { + cursor: help; + border-bottom: 1px dotted #777; +} +.initialism { + font-size: 90%; + text-transform: uppercase; +} +blockquote { + padding: 10px 20px; + margin: 0 0 20px; + font-size: 17.5px; + border-left: 5px solid #eee; +} +blockquote p:last-child, +blockquote ul:last-child, +blockquote ol:last-child { + margin-bottom: 0; +} +blockquote footer, +blockquote small, +blockquote .small { + display: block; + font-size: 80%; + line-height: 1.42857143; + color: #777; +} +blockquote footer:before, +blockquote small:before, +blockquote .small:before { + content: '\2014 \00A0'; +} +.blockquote-reverse, +blockquote.pull-right { + padding-right: 15px; + padding-left: 0; + text-align: right; + border-right: 5px solid #eee; + border-left: 0; +} +.blockquote-reverse footer:before, +blockquote.pull-right footer:before, +.blockquote-reverse small:before, +blockquote.pull-right small:before, +.blockquote-reverse .small:before, +blockquote.pull-right .small:before { + content: ''; +} +.blockquote-reverse footer:after, +blockquote.pull-right footer:after, +.blockquote-reverse small:after, +blockquote.pull-right small:after, +.blockquote-reverse .small:after, +blockquote.pull-right .small:after { + content: '\00A0 \2014'; +} +address { + margin-bottom: 20px; + font-style: normal; + line-height: 1.42857143; +} +code, +kbd, +pre, +samp { + font-family: Menlo, Monaco, Consolas, "Courier New", monospace; +} +code { + padding: 2px 4px; + font-size: 90%; + color: #c7254e; + background-color: #f9f2f4; + border-radius: 4px; +} +kbd { + padding: 2px 4px; + font-size: 90%; + color: #fff; + background-color: #333; + border-radius: 3px; + -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .25); + box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .25); +} +kbd kbd { + padding: 0; + font-size: 100%; + font-weight: bold; + -webkit-box-shadow: none; + box-shadow: none; +} +pre { + display: block; + padding: 9.5px; + margin: 0 0 10px; + font-size: 13px; + line-height: 1.42857143; + color: #333; + word-break: break-all; + word-wrap: break-word; + background-color: #f5f5f5; + border: 1px solid #ccc; + border-radius: 4px; +} +pre code { + padding: 0; + font-size: inherit; + color: inherit; + white-space: pre-wrap; + background-color: transparent; + border-radius: 0; +} +.pre-scrollable { + max-height: 340px; + overflow-y: scroll; +} +.container { + padding-right: 15px; + padding-left: 15px; + margin-right: auto; + margin-left: auto; +} +@media (min-width: 768px) { + .container { + width: 750px; + } +} +@media (min-width: 992px) { + .container { + width: 970px; + } +} +@media (min-width: 1200px) { + .container { + width: 1170px; + } +} +.container-fluid { + padding-right: 15px; + padding-left: 15px; + margin-right: auto; + margin-left: auto; +} +.row { + margin-right: -15px; + margin-left: -15px; +} +.col-xs-1, .col-sm-1, .col-md-1, .col-lg-1, .col-xs-2, .col-sm-2, .col-md-2, .col-lg-2, .col-xs-3, .col-sm-3, .col-md-3, .col-lg-3, .col-xs-4, .col-sm-4, .col-md-4, .col-lg-4, .col-xs-5, .col-sm-5, .col-md-5, .col-lg-5, .col-xs-6, .col-sm-6, .col-md-6, .col-lg-6, .col-xs-7, .col-sm-7, .col-md-7, .col-lg-7, .col-xs-8, .col-sm-8, .col-md-8, .col-lg-8, .col-xs-9, .col-sm-9, .col-md-9, .col-lg-9, .col-xs-10, .col-sm-10, .col-md-10, .col-lg-10, .col-xs-11, .col-sm-11, .col-md-11, .col-lg-11, .col-xs-12, .col-sm-12, .col-md-12, .col-lg-12 { + position: relative; + min-height: 1px; + padding-right: 15px; + padding-left: 15px; +} +.col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12 { + float: left; +} +.col-xs-12 { + width: 100%; +} +.col-xs-11 { + width: 91.66666667%; +} +.col-xs-10 { + width: 83.33333333%; +} +.col-xs-9 { + width: 75%; +} +.col-xs-8 { + width: 66.66666667%; +} +.col-xs-7 { + width: 58.33333333%; +} +.col-xs-6 { + width: 50%; +} +.col-xs-5 { + width: 41.66666667%; +} +.col-xs-4 { + width: 33.33333333%; +} +.col-xs-3 { + width: 25%; +} +.col-xs-2 { + width: 16.66666667%; +} +.col-xs-1 { + width: 8.33333333%; +} +.col-xs-pull-12 { + right: 100%; +} +.col-xs-pull-11 { + right: 91.66666667%; +} +.col-xs-pull-10 { + right: 83.33333333%; +} +.col-xs-pull-9 { + right: 75%; +} +.col-xs-pull-8 { + right: 66.66666667%; +} +.col-xs-pull-7 { + right: 58.33333333%; +} +.col-xs-pull-6 { + right: 50%; +} +.col-xs-pull-5 { + right: 41.66666667%; +} +.col-xs-pull-4 { + right: 33.33333333%; +} +.col-xs-pull-3 { + right: 25%; +} +.col-xs-pull-2 { + right: 16.66666667%; +} +.col-xs-pull-1 { + right: 8.33333333%; +} +.col-xs-pull-0 { + right: auto; +} +.col-xs-push-12 { + left: 100%; +} +.col-xs-push-11 { + left: 91.66666667%; +} +.col-xs-push-10 { + left: 83.33333333%; +} +.col-xs-push-9 { + left: 75%; +} +.col-xs-push-8 { + left: 66.66666667%; +} +.col-xs-push-7 { + left: 58.33333333%; +} +.col-xs-push-6 { + left: 50%; +} +.col-xs-push-5 { + left: 41.66666667%; +} +.col-xs-push-4 { + left: 33.33333333%; +} +.col-xs-push-3 { + left: 25%; +} +.col-xs-push-2 { + left: 16.66666667%; +} +.col-xs-push-1 { + left: 8.33333333%; +} +.col-xs-push-0 { + left: auto; +} +.col-xs-offset-12 { + margin-left: 100%; +} +.col-xs-offset-11 { + margin-left: 91.66666667%; +} +.col-xs-offset-10 { + margin-left: 83.33333333%; +} +.col-xs-offset-9 { + margin-left: 75%; +} +.col-xs-offset-8 { + margin-left: 66.66666667%; +} +.col-xs-offset-7 { + margin-left: 58.33333333%; +} +.col-xs-offset-6 { + margin-left: 50%; +} +.col-xs-offset-5 { + margin-left: 41.66666667%; +} +.col-xs-offset-4 { + margin-left: 33.33333333%; +} +.col-xs-offset-3 { + margin-left: 25%; +} +.col-xs-offset-2 { + margin-left: 16.66666667%; +} +.col-xs-offset-1 { + margin-left: 8.33333333%; +} +.col-xs-offset-0 { + margin-left: 0; +} +@media (min-width: 768px) { + .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12 { + float: left; + } + .col-sm-12 { + width: 100%; + } + .col-sm-11 { + width: 91.66666667%; + } + .col-sm-10 { + width: 83.33333333%; + } + .col-sm-9 { + width: 75%; + } + .col-sm-8 { + width: 66.66666667%; + } + .col-sm-7 { + width: 58.33333333%; + } + .col-sm-6 { + width: 50%; + } + .col-sm-5 { + width: 41.66666667%; + } + .col-sm-4 { + width: 33.33333333%; + } + .col-sm-3 { + width: 25%; + } + .col-sm-2 { + width: 16.66666667%; + } + .col-sm-1 { + width: 8.33333333%; + } + .col-sm-pull-12 { + right: 100%; + } + .col-sm-pull-11 { + right: 91.66666667%; + } + .col-sm-pull-10 { + right: 83.33333333%; + } + .col-sm-pull-9 { + right: 75%; + } + .col-sm-pull-8 { + right: 66.66666667%; + } + .col-sm-pull-7 { + right: 58.33333333%; + } + .col-sm-pull-6 { + right: 50%; + } + .col-sm-pull-5 { + right: 41.66666667%; + } + .col-sm-pull-4 { + right: 33.33333333%; + } + .col-sm-pull-3 { + right: 25%; + } + .col-sm-pull-2 { + right: 16.66666667%; + } + .col-sm-pull-1 { + right: 8.33333333%; + } + .col-sm-pull-0 { + right: auto; + } + .col-sm-push-12 { + left: 100%; + } + .col-sm-push-11 { + left: 91.66666667%; + } + .col-sm-push-10 { + left: 83.33333333%; + } + .col-sm-push-9 { + left: 75%; + } + .col-sm-push-8 { + left: 66.66666667%; + } + .col-sm-push-7 { + left: 58.33333333%; + } + .col-sm-push-6 { + left: 50%; + } + .col-sm-push-5 { + left: 41.66666667%; + } + .col-sm-push-4 { + left: 33.33333333%; + } + .col-sm-push-3 { + left: 25%; + } + .col-sm-push-2 { + left: 16.66666667%; + } + .col-sm-push-1 { + left: 8.33333333%; + } + .col-sm-push-0 { + left: auto; + } + .col-sm-offset-12 { + margin-left: 100%; + } + .col-sm-offset-11 { + margin-left: 91.66666667%; + } + .col-sm-offset-10 { + margin-left: 83.33333333%; + } + .col-sm-offset-9 { + margin-left: 75%; + } + .col-sm-offset-8 { + margin-left: 66.66666667%; + } + .col-sm-offset-7 { + margin-left: 58.33333333%; + } + .col-sm-offset-6 { + margin-left: 50%; + } + .col-sm-offset-5 { + margin-left: 41.66666667%; + } + .col-sm-offset-4 { + margin-left: 33.33333333%; + } + .col-sm-offset-3 { + margin-left: 25%; + } + .col-sm-offset-2 { + margin-left: 16.66666667%; + } + .col-sm-offset-1 { + margin-left: 8.33333333%; + } + .col-sm-offset-0 { + margin-left: 0; + } +} +@media (min-width: 992px) { + .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12 { + float: left; + } + .col-md-12 { + width: 100%; + } + .col-md-11 { + width: 91.66666667%; + } + .col-md-10 { + width: 83.33333333%; + } + .col-md-9 { + width: 75%; + } + .col-md-8 { + width: 66.66666667%; + } + .col-md-7 { + width: 58.33333333%; + } + .col-md-6 { + width: 50%; + } + .col-md-5 { + width: 41.66666667%; + } + .col-md-4 { + width: 33.33333333%; + } + .col-md-3 { + width: 25%; + } + .col-md-2 { + width: 16.66666667%; + } + .col-md-1 { + width: 8.33333333%; + } + .col-md-pull-12 { + right: 100%; + } + .col-md-pull-11 { + right: 91.66666667%; + } + .col-md-pull-10 { + right: 83.33333333%; + } + .col-md-pull-9 { + right: 75%; + } + .col-md-pull-8 { + right: 66.66666667%; + } + .col-md-pull-7 { + right: 58.33333333%; + } + .col-md-pull-6 { + right: 50%; + } + .col-md-pull-5 { + right: 41.66666667%; + } + .col-md-pull-4 { + right: 33.33333333%; + } + .col-md-pull-3 { + right: 25%; + } + .col-md-pull-2 { + right: 16.66666667%; + } + .col-md-pull-1 { + right: 8.33333333%; + } + .col-md-pull-0 { + right: auto; + } + .col-md-push-12 { + left: 100%; + } + .col-md-push-11 { + left: 91.66666667%; + } + .col-md-push-10 { + left: 83.33333333%; + } + .col-md-push-9 { + left: 75%; + } + .col-md-push-8 { + left: 66.66666667%; + } + .col-md-push-7 { + left: 58.33333333%; + } + .col-md-push-6 { + left: 50%; + } + .col-md-push-5 { + left: 41.66666667%; + } + .col-md-push-4 { + left: 33.33333333%; + } + .col-md-push-3 { + left: 25%; + } + .col-md-push-2 { + left: 16.66666667%; + } + .col-md-push-1 { + left: 8.33333333%; + } + .col-md-push-0 { + left: auto; + } + .col-md-offset-12 { + margin-left: 100%; + } + .col-md-offset-11 { + margin-left: 91.66666667%; + } + .col-md-offset-10 { + margin-left: 83.33333333%; + } + .col-md-offset-9 { + margin-left: 75%; + } + .col-md-offset-8 { + margin-left: 66.66666667%; + } + .col-md-offset-7 { + margin-left: 58.33333333%; + } + .col-md-offset-6 { + margin-left: 50%; + } + .col-md-offset-5 { + margin-left: 41.66666667%; + } + .col-md-offset-4 { + margin-left: 33.33333333%; + } + .col-md-offset-3 { + margin-left: 25%; + } + .col-md-offset-2 { + margin-left: 16.66666667%; + } + .col-md-offset-1 { + margin-left: 8.33333333%; + } + .col-md-offset-0 { + margin-left: 0; + } +} +@media (min-width: 1200px) { + .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12 { + float: left; + } + .col-lg-12 { + width: 100%; + } + .col-lg-11 { + width: 91.66666667%; + } + .col-lg-10 { + width: 83.33333333%; + } + .col-lg-9 { + width: 75%; + } + .col-lg-8 { + width: 66.66666667%; + } + .col-lg-7 { + width: 58.33333333%; + } + .col-lg-6 { + width: 50%; + } + .col-lg-5 { + width: 41.66666667%; + } + .col-lg-4 { + width: 33.33333333%; + } + .col-lg-3 { + width: 25%; + } + .col-lg-2 { + width: 16.66666667%; + } + .col-lg-1 { + width: 8.33333333%; + } + .col-lg-pull-12 { + right: 100%; + } + .col-lg-pull-11 { + right: 91.66666667%; + } + .col-lg-pull-10 { + right: 83.33333333%; + } + .col-lg-pull-9 { + right: 75%; + } + .col-lg-pull-8 { + right: 66.66666667%; + } + .col-lg-pull-7 { + right: 58.33333333%; + } + .col-lg-pull-6 { + right: 50%; + } + .col-lg-pull-5 { + right: 41.66666667%; + } + .col-lg-pull-4 { + right: 33.33333333%; + } + .col-lg-pull-3 { + right: 25%; + } + .col-lg-pull-2 { + right: 16.66666667%; + } + .col-lg-pull-1 { + right: 8.33333333%; + } + .col-lg-pull-0 { + right: auto; + } + .col-lg-push-12 { + left: 100%; + } + .col-lg-push-11 { + left: 91.66666667%; + } + .col-lg-push-10 { + left: 83.33333333%; + } + .col-lg-push-9 { + left: 75%; + } + .col-lg-push-8 { + left: 66.66666667%; + } + .col-lg-push-7 { + left: 58.33333333%; + } + .col-lg-push-6 { + left: 50%; + } + .col-lg-push-5 { + left: 41.66666667%; + } + .col-lg-push-4 { + left: 33.33333333%; + } + .col-lg-push-3 { + left: 25%; + } + .col-lg-push-2 { + left: 16.66666667%; + } + .col-lg-push-1 { + left: 8.33333333%; + } + .col-lg-push-0 { + left: auto; + } + .col-lg-offset-12 { + margin-left: 100%; + } + .col-lg-offset-11 { + margin-left: 91.66666667%; + } + .col-lg-offset-10 { + margin-left: 83.33333333%; + } + .col-lg-offset-9 { + margin-left: 75%; + } + .col-lg-offset-8 { + margin-left: 66.66666667%; + } + .col-lg-offset-7 { + margin-left: 58.33333333%; + } + .col-lg-offset-6 { + margin-left: 50%; + } + .col-lg-offset-5 { + margin-left: 41.66666667%; + } + .col-lg-offset-4 { + margin-left: 33.33333333%; + } + .col-lg-offset-3 { + margin-left: 25%; + } + .col-lg-offset-2 { + margin-left: 16.66666667%; + } + .col-lg-offset-1 { + margin-left: 8.33333333%; + } + .col-lg-offset-0 { + margin-left: 0; + } +} +table { + background-color: transparent; +} +caption { + padding-top: 8px; + padding-bottom: 8px; + color: #777; + text-align: left; +} +th { + text-align: left; +} +.table { + width: 100%; + max-width: 100%; + margin-bottom: 20px; +} +.table > thead > tr > th, +.table > tbody > tr > th, +.table > tfoot > tr > th, +.table > thead > tr > td, +.table > tbody > tr > td, +.table > tfoot > tr > td { + padding: 8px; + line-height: 1.42857143; + vertical-align: top; + border-top: 1px solid #ddd; +} +.table > thead > tr > th { + vertical-align: bottom; + border-bottom: 2px solid #ddd; +} +.table > caption + thead > tr:first-child > th, +.table > colgroup + thead > tr:first-child > th, +.table > thead:first-child > tr:first-child > th, +.table > caption + thead > tr:first-child > td, +.table > colgroup + thead > tr:first-child > td, +.table > thead:first-child > tr:first-child > td { + border-top: 0; +} +.table > tbody + tbody { + border-top: 2px solid #ddd; +} +.table .table { + background-color: #fff; +} +.table-condensed > thead > tr > th, +.table-condensed > tbody > tr > th, +.table-condensed > tfoot > tr > th, +.table-condensed > thead > tr > td, +.table-condensed > tbody > tr > td, +.table-condensed > tfoot > tr > td { + padding: 5px; +} +.table-bordered { + border: 1px solid #ddd; +} +.table-bordered > thead > tr > th, +.table-bordered > tbody > tr > th, +.table-bordered > tfoot > tr > th, +.table-bordered > thead > tr > td, +.table-bordered > tbody > tr > td, +.table-bordered > tfoot > tr > td { + border: 1px solid #ddd; +} +.table-bordered > thead > tr > th, +.table-bordered > thead > tr > td { + border-bottom-width: 2px; +} +.table-striped > tbody > tr:nth-of-type(odd) { + background-color: #f9f9f9; +} +.table-hover > tbody > tr:hover { + background-color: #f5f5f5; +} +table col[class*="col-"] { + position: static; + display: table-column; + float: none; +} +table td[class*="col-"], +table th[class*="col-"] { + position: static; + display: table-cell; + float: none; +} +.table > thead > tr > td.active, +.table > tbody > tr > td.active, +.table > tfoot > tr > td.active, +.table > thead > tr > th.active, +.table > tbody > tr > th.active, +.table > tfoot > tr > th.active, +.table > thead > tr.active > td, +.table > tbody > tr.active > td, +.table > tfoot > tr.active > td, +.table > thead > tr.active > th, +.table > tbody > tr.active > th, +.table > tfoot > tr.active > th { + background-color: #f5f5f5; +} +.table-hover > tbody > tr > td.active:hover, +.table-hover > tbody > tr > th.active:hover, +.table-hover > tbody > tr.active:hover > td, +.table-hover > tbody > tr:hover > .active, +.table-hover > tbody > tr.active:hover > th { + background-color: #e8e8e8; +} +.table > thead > tr > td.success, +.table > tbody > tr > td.success, +.table > tfoot > tr > td.success, +.table > thead > tr > th.success, +.table > tbody > tr > th.success, +.table > tfoot > tr > th.success, +.table > thead > tr.success > td, +.table > tbody > tr.success > td, +.table > tfoot > tr.success > td, +.table > thead > tr.success > th, +.table > tbody > tr.success > th, +.table > tfoot > tr.success > th { + background-color: #dff0d8; +} +.table-hover > tbody > tr > td.success:hover, +.table-hover > tbody > tr > th.success:hover, +.table-hover > tbody > tr.success:hover > td, +.table-hover > tbody > tr:hover > .success, +.table-hover > tbody > tr.success:hover > th { + background-color: #d0e9c6; +} +.table > thead > tr > td.info, +.table > tbody > tr > td.info, +.table > tfoot > tr > td.info, +.table > thead > tr > th.info, +.table > tbody > tr > th.info, +.table > tfoot > tr > th.info, +.table > thead > tr.info > td, +.table > tbody > tr.info > td, +.table > tfoot > tr.info > td, +.table > thead > tr.info > th, +.table > tbody > tr.info > th, +.table > tfoot > tr.info > th { + background-color: #d9edf7; +} +.table-hover > tbody > tr > td.info:hover, +.table-hover > tbody > tr > th.info:hover, +.table-hover > tbody > tr.info:hover > td, +.table-hover > tbody > tr:hover > .info, +.table-hover > tbody > tr.info:hover > th { + background-color: #c4e3f3; +} +.table > thead > tr > td.warning, +.table > tbody > tr > td.warning, +.table > tfoot > tr > td.warning, +.table > thead > tr > th.warning, +.table > tbody > tr > th.warning, +.table > tfoot > tr > th.warning, +.table > thead > tr.warning > td, +.table > tbody > tr.warning > td, +.table > tfoot > tr.warning > td, +.table > thead > tr.warning > th, +.table > tbody > tr.warning > th, +.table > tfoot > tr.warning > th { + background-color: #fcf8e3; +} +.table-hover > tbody > tr > td.warning:hover, +.table-hover > tbody > tr > th.warning:hover, +.table-hover > tbody > tr.warning:hover > td, +.table-hover > tbody > tr:hover > .warning, +.table-hover > tbody > tr.warning:hover > th { + background-color: #faf2cc; +} +.table > thead > tr > td.danger, +.table > tbody > tr > td.danger, +.table > tfoot > tr > td.danger, +.table > thead > tr > th.danger, +.table > tbody > tr > th.danger, +.table > tfoot > tr > th.danger, +.table > thead > tr.danger > td, +.table > tbody > tr.danger > td, +.table > tfoot > tr.danger > td, +.table > thead > tr.danger > th, +.table > tbody > tr.danger > th, +.table > tfoot > tr.danger > th { + background-color: #f2dede; +} +.table-hover > tbody > tr > td.danger:hover, +.table-hover > tbody > tr > th.danger:hover, +.table-hover > tbody > tr.danger:hover > td, +.table-hover > tbody > tr:hover > .danger, +.table-hover > tbody > tr.danger:hover > th { + background-color: #ebcccc; +} +.table-responsive { + min-height: .01%; + overflow-x: auto; +} +@media screen and (max-width: 767px) { + .table-responsive { + width: 100%; + margin-bottom: 15px; + overflow-y: hidden; + -ms-overflow-style: -ms-autohiding-scrollbar; + border: 1px solid #ddd; + } + .table-responsive > .table { + margin-bottom: 0; + } + .table-responsive > .table > thead > tr > th, + .table-responsive > .table > tbody > tr > th, + .table-responsive > .table > tfoot > tr > th, + .table-responsive > .table > thead > tr > td, + .table-responsive > .table > tbody > tr > td, + .table-responsive > .table > tfoot > tr > td { + white-space: nowrap; + } + .table-responsive > .table-bordered { + border: 0; + } + .table-responsive > .table-bordered > thead > tr > th:first-child, + .table-responsive > .table-bordered > tbody > tr > th:first-child, + .table-responsive > .table-bordered > tfoot > tr > th:first-child, + .table-responsive > .table-bordered > thead > tr > td:first-child, + .table-responsive > .table-bordered > tbody > tr > td:first-child, + .table-responsive > .table-bordered > tfoot > tr > td:first-child { + border-left: 0; + } + .table-responsive > .table-bordered > thead > tr > th:last-child, + .table-responsive > .table-bordered > tbody > tr > th:last-child, + .table-responsive > .table-bordered > tfoot > tr > th:last-child, + .table-responsive > .table-bordered > thead > tr > td:last-child, + .table-responsive > .table-bordered > tbody > tr > td:last-child, + .table-responsive > .table-bordered > tfoot > tr > td:last-child { + border-right: 0; + } + .table-responsive > .table-bordered > tbody > tr:last-child > th, + .table-responsive > .table-bordered > tfoot > tr:last-child > th, + .table-responsive > .table-bordered > tbody > tr:last-child > td, + .table-responsive > .table-bordered > tfoot > tr:last-child > td { + border-bottom: 0; + } +} +fieldset { + min-width: 0; + padding: 0; + margin: 0; + border: 0; +} +legend { + display: block; + width: 100%; + padding: 0; + margin-bottom: 20px; + font-size: 21px; + line-height: inherit; + color: #333; + border: 0; + border-bottom: 1px solid #e5e5e5; +} +label { + display: inline-block; + max-width: 100%; + margin-bottom: 5px; + font-weight: bold; +} +input[type="search"] { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +input[type="radio"], +input[type="checkbox"] { + margin: 4px 0 0; + margin-top: 1px \9; + line-height: normal; +} +input[type="file"] { + display: block; +} +input[type="range"] { + display: block; + width: 100%; +} +select[multiple], +select[size] { + height: auto; +} +input[type="file"]:focus, +input[type="radio"]:focus, +input[type="checkbox"]:focus { + outline: thin dotted; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} +output { + display: block; + padding-top: 7px; + font-size: 14px; + line-height: 1.42857143; + color: #555; +} +.form-control { + display: block; + width: 100%; + height: 34px; + padding: 6px 12px; + font-size: 14px; + line-height: 1.42857143; + color: #555; + background-color: #fff; + background-image: none; + border: 1px solid #ccc; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); + -webkit-transition: border-color ease-in-out .15s, -webkit-box-shadow ease-in-out .15s; + -o-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; + transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; +} +.form-control:focus { + border-color: #66afe9; + outline: 0; + -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, .6); + box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, .6); +} +.form-control::-moz-placeholder { + color: #999; + opacity: 1; +} +.form-control:-ms-input-placeholder { + color: #999; +} +.form-control::-webkit-input-placeholder { + color: #999; +} +.form-control[disabled], +.form-control[readonly], +fieldset[disabled] .form-control { + background-color: #eee; + opacity: 1; +} +.form-control[disabled], +fieldset[disabled] .form-control { + cursor: not-allowed; +} +textarea.form-control { + height: auto; +} +input[type="search"] { + -webkit-appearance: none; +} +@media screen and (-webkit-min-device-pixel-ratio: 0) { + input[type="date"], + input[type="time"], + input[type="datetime-local"], + input[type="month"] { + line-height: 34px; + } + input[type="date"].input-sm, + input[type="time"].input-sm, + input[type="datetime-local"].input-sm, + input[type="month"].input-sm, + .input-group-sm input[type="date"], + .input-group-sm input[type="time"], + .input-group-sm input[type="datetime-local"], + .input-group-sm input[type="month"] { + line-height: 30px; + } + input[type="date"].input-lg, + input[type="time"].input-lg, + input[type="datetime-local"].input-lg, + input[type="month"].input-lg, + .input-group-lg input[type="date"], + .input-group-lg input[type="time"], + .input-group-lg input[type="datetime-local"], + .input-group-lg input[type="month"] { + line-height: 46px; + } +} +.form-group { + margin-bottom: 15px; +} +.radio, +.checkbox { + position: relative; + display: block; + margin-top: 10px; + margin-bottom: 10px; +} +.radio label, +.checkbox label { + min-height: 20px; + padding-left: 20px; + margin-bottom: 0; + font-weight: normal; + cursor: pointer; +} +.radio input[type="radio"], +.radio-inline input[type="radio"], +.checkbox input[type="checkbox"], +.checkbox-inline input[type="checkbox"] { + position: absolute; + margin-top: 4px \9; + margin-left: -20px; +} +.radio + .radio, +.checkbox + .checkbox { + margin-top: -5px; +} +.radio-inline, +.checkbox-inline { + position: relative; + display: inline-block; + padding-left: 20px; + margin-bottom: 0; + font-weight: normal; + vertical-align: middle; + cursor: pointer; +} +.radio-inline + .radio-inline, +.checkbox-inline + .checkbox-inline { + margin-top: 0; + margin-left: 10px; +} +input[type="radio"][disabled], +input[type="checkbox"][disabled], +input[type="radio"].disabled, +input[type="checkbox"].disabled, +fieldset[disabled] input[type="radio"], +fieldset[disabled] input[type="checkbox"] { + cursor: not-allowed; +} +.radio-inline.disabled, +.checkbox-inline.disabled, +fieldset[disabled] .radio-inline, +fieldset[disabled] .checkbox-inline { + cursor: not-allowed; +} +.radio.disabled label, +.checkbox.disabled label, +fieldset[disabled] .radio label, +fieldset[disabled] .checkbox label { + cursor: not-allowed; +} +.form-control-static { + min-height: 34px; + padding-top: 7px; + padding-bottom: 7px; + margin-bottom: 0; +} +.form-control-static.input-lg, +.form-control-static.input-sm { + padding-right: 0; + padding-left: 0; +} +.input-sm { + height: 30px; + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +select.input-sm { + height: 30px; + line-height: 30px; +} +textarea.input-sm, +select[multiple].input-sm { + height: auto; +} +.form-group-sm .form-control { + height: 30px; + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +select.form-group-sm .form-control { + height: 30px; + line-height: 30px; +} +textarea.form-group-sm .form-control, +select[multiple].form-group-sm .form-control { + height: auto; +} +.form-group-sm .form-control-static { + height: 30px; + min-height: 32px; + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; +} +.input-lg { + height: 46px; + padding: 10px 16px; + font-size: 18px; + line-height: 1.3333333; + border-radius: 6px; +} +select.input-lg { + height: 46px; + line-height: 46px; +} +textarea.input-lg, +select[multiple].input-lg { + height: auto; +} +.form-group-lg .form-control { + height: 46px; + padding: 10px 16px; + font-size: 18px; + line-height: 1.3333333; + border-radius: 6px; +} +select.form-group-lg .form-control { + height: 46px; + line-height: 46px; +} +textarea.form-group-lg .form-control, +select[multiple].form-group-lg .form-control { + height: auto; +} +.form-group-lg .form-control-static { + height: 46px; + min-height: 38px; + padding: 10px 16px; + font-size: 18px; + line-height: 1.3333333; +} +.has-feedback { + position: relative; +} +.has-feedback .form-control { + padding-right: 42.5px; +} +.form-control-feedback { + position: absolute; + top: 0; + right: 0; + z-index: 2; + display: block; + width: 34px; + height: 34px; + line-height: 34px; + text-align: center; + pointer-events: none; +} +.input-lg + .form-control-feedback { + width: 46px; + height: 46px; + line-height: 46px; +} +.input-sm + .form-control-feedback { + width: 30px; + height: 30px; + line-height: 30px; +} +.has-success .help-block, +.has-success .control-label, +.has-success .radio, +.has-success .checkbox, +.has-success .radio-inline, +.has-success .checkbox-inline, +.has-success.radio label, +.has-success.checkbox label, +.has-success.radio-inline label, +.has-success.checkbox-inline label { + color: #3c763d; +} +.has-success .form-control { + border-color: #3c763d; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); +} +.has-success .form-control:focus { + border-color: #2b542c; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #67b168; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #67b168; +} +.has-success .input-group-addon { + color: #3c763d; + background-color: #dff0d8; + border-color: #3c763d; +} +.has-success .form-control-feedback { + color: #3c763d; +} +.has-warning .help-block, +.has-warning .control-label, +.has-warning .radio, +.has-warning .checkbox, +.has-warning .radio-inline, +.has-warning .checkbox-inline, +.has-warning.radio label, +.has-warning.checkbox label, +.has-warning.radio-inline label, +.has-warning.checkbox-inline label { + color: #8a6d3b; +} +.has-warning .form-control { + border-color: #8a6d3b; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); +} +.has-warning .form-control:focus { + border-color: #66512c; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #c0a16b; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #c0a16b; +} +.has-warning .input-group-addon { + color: #8a6d3b; + background-color: #fcf8e3; + border-color: #8a6d3b; +} +.has-warning .form-control-feedback { + color: #8a6d3b; +} +.has-error .help-block, +.has-error .control-label, +.has-error .radio, +.has-error .checkbox, +.has-error .radio-inline, +.has-error .checkbox-inline, +.has-error.radio label, +.has-error.checkbox label, +.has-error.radio-inline label, +.has-error.checkbox-inline label { + color: #a94442; +} +.has-error .form-control { + border-color: #a94442; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); +} +.has-error .form-control:focus { + border-color: #843534; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #ce8483; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #ce8483; +} +.has-error .input-group-addon { + color: #a94442; + background-color: #f2dede; + border-color: #a94442; +} +.has-error .form-control-feedback { + color: #a94442; +} +.has-feedback label ~ .form-control-feedback { + top: 25px; +} +.has-feedback label.sr-only ~ .form-control-feedback { + top: 0; +} +.help-block { + display: block; + margin-top: 5px; + margin-bottom: 10px; + color: #737373; +} +@media (min-width: 768px) { + .form-inline .form-group { + display: inline-block; + margin-bottom: 0; + vertical-align: middle; + } + .form-inline .form-control { + display: inline-block; + width: auto; + vertical-align: middle; + } + .form-inline .form-control-static { + display: inline-block; + } + .form-inline .input-group { + display: inline-table; + vertical-align: middle; + } + .form-inline .input-group .input-group-addon, + .form-inline .input-group .input-group-btn, + .form-inline .input-group .form-control { + width: auto; + } + .form-inline .input-group > .form-control { + width: 100%; + } + .form-inline .control-label { + margin-bottom: 0; + vertical-align: middle; + } + .form-inline .radio, + .form-inline .checkbox { + display: inline-block; + margin-top: 0; + margin-bottom: 0; + vertical-align: middle; + } + .form-inline .radio label, + .form-inline .checkbox label { + padding-left: 0; + } + .form-inline .radio input[type="radio"], + .form-inline .checkbox input[type="checkbox"] { + position: relative; + margin-left: 0; + } + .form-inline .has-feedback .form-control-feedback { + top: 0; + } +} +.form-horizontal .radio, +.form-horizontal .checkbox, +.form-horizontal .radio-inline, +.form-horizontal .checkbox-inline { + padding-top: 7px; + margin-top: 0; + margin-bottom: 0; +} +.form-horizontal .radio, +.form-horizontal .checkbox { + min-height: 27px; +} +.form-horizontal .form-group { + margin-right: -15px; + margin-left: -15px; +} +@media (min-width: 768px) { + .form-horizontal .control-label { + padding-top: 7px; + margin-bottom: 0; + text-align: right; + } +} +.form-horizontal .has-feedback .form-control-feedback { + right: 15px; +} +@media (min-width: 768px) { + .form-horizontal .form-group-lg .control-label { + padding-top: 14.333333px; + } +} +@media (min-width: 768px) { + .form-horizontal .form-group-sm .control-label { + padding-top: 6px; + } +} +.btn { + display: inline-block; + padding: 6px 12px; + margin-bottom: 0; + font-size: 14px; + font-weight: normal; + line-height: 1.42857143; + text-align: center; + white-space: nowrap; + vertical-align: middle; + -ms-touch-action: manipulation; + touch-action: manipulation; + cursor: pointer; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + background-image: none; + border: 1px solid transparent; + border-radius: 4px; +} +.btn:focus, +.btn:active:focus, +.btn.active:focus, +.btn.focus, +.btn:active.focus, +.btn.active.focus { + outline: thin dotted; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} +.btn:hover, +.btn:focus, +.btn.focus { + color: #333; + text-decoration: none; +} +.btn:active, +.btn.active { + background-image: none; + outline: 0; + -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); + box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); +} +.btn.disabled, +.btn[disabled], +fieldset[disabled] .btn { + pointer-events: none; + cursor: not-allowed; + filter: alpha(opacity=65); + -webkit-box-shadow: none; + box-shadow: none; + opacity: .65; +} +.btn-default { + color: #333; + background-color: #fff; + border-color: #ccc; +} +.btn-default:hover, +.btn-default:focus, +.btn-default.focus, +.btn-default:active, +.btn-default.active, +.open > .dropdown-toggle.btn-default { + color: #333; + background-color: #e6e6e6; + border-color: #adadad; +} +.btn-default:active, +.btn-default.active, +.open > .dropdown-toggle.btn-default { + background-image: none; +} +.btn-default.disabled, +.btn-default[disabled], +fieldset[disabled] .btn-default, +.btn-default.disabled:hover, +.btn-default[disabled]:hover, +fieldset[disabled] .btn-default:hover, +.btn-default.disabled:focus, +.btn-default[disabled]:focus, +fieldset[disabled] .btn-default:focus, +.btn-default.disabled.focus, +.btn-default[disabled].focus, +fieldset[disabled] .btn-default.focus, +.btn-default.disabled:active, +.btn-default[disabled]:active, +fieldset[disabled] .btn-default:active, +.btn-default.disabled.active, +.btn-default[disabled].active, +fieldset[disabled] .btn-default.active { + background-color: #fff; + border-color: #ccc; +} +.btn-default .badge { + color: #fff; + background-color: #333; +} +.btn-primary { + color: #fff; + background-color: #337ab7; + border-color: #2e6da4; +} +.btn-primary:hover, +.btn-primary:focus, +.btn-primary.focus, +.btn-primary:active, +.btn-primary.active, +.open > .dropdown-toggle.btn-primary { + color: #fff; + background-color: #286090; + border-color: #204d74; +} +.btn-primary:active, +.btn-primary.active, +.open > .dropdown-toggle.btn-primary { + background-image: none; +} +.btn-primary.disabled, +.btn-primary[disabled], +fieldset[disabled] .btn-primary, +.btn-primary.disabled:hover, +.btn-primary[disabled]:hover, +fieldset[disabled] .btn-primary:hover, +.btn-primary.disabled:focus, +.btn-primary[disabled]:focus, +fieldset[disabled] .btn-primary:focus, +.btn-primary.disabled.focus, +.btn-primary[disabled].focus, +fieldset[disabled] .btn-primary.focus, +.btn-primary.disabled:active, +.btn-primary[disabled]:active, +fieldset[disabled] .btn-primary:active, +.btn-primary.disabled.active, +.btn-primary[disabled].active, +fieldset[disabled] .btn-primary.active { + background-color: #337ab7; + border-color: #2e6da4; +} +.btn-primary .badge { + color: #337ab7; + background-color: #fff; +} +.btn-success { + color: #fff; + background-color: #5cb85c; + border-color: #4cae4c; +} +.btn-success:hover, +.btn-success:focus, +.btn-success.focus, +.btn-success:active, +.btn-success.active, +.open > .dropdown-toggle.btn-success { + color: #fff; + background-color: #449d44; + border-color: #398439; +} +.btn-success:active, +.btn-success.active, +.open > .dropdown-toggle.btn-success { + background-image: none; +} +.btn-success.disabled, +.btn-success[disabled], +fieldset[disabled] .btn-success, +.btn-success.disabled:hover, +.btn-success[disabled]:hover, +fieldset[disabled] .btn-success:hover, +.btn-success.disabled:focus, +.btn-success[disabled]:focus, +fieldset[disabled] .btn-success:focus, +.btn-success.disabled.focus, +.btn-success[disabled].focus, +fieldset[disabled] .btn-success.focus, +.btn-success.disabled:active, +.btn-success[disabled]:active, +fieldset[disabled] .btn-success:active, +.btn-success.disabled.active, +.btn-success[disabled].active, +fieldset[disabled] .btn-success.active { + background-color: #5cb85c; + border-color: #4cae4c; +} +.btn-success .badge { + color: #5cb85c; + background-color: #fff; +} +.btn-info { + color: #fff; + background-color: #5bc0de; + border-color: #46b8da; +} +.btn-info:hover, +.btn-info:focus, +.btn-info.focus, +.btn-info:active, +.btn-info.active, +.open > .dropdown-toggle.btn-info { + color: #fff; + background-color: #31b0d5; + border-color: #269abc; +} +.btn-info:active, +.btn-info.active, +.open > .dropdown-toggle.btn-info { + background-image: none; +} +.btn-info.disabled, +.btn-info[disabled], +fieldset[disabled] .btn-info, +.btn-info.disabled:hover, +.btn-info[disabled]:hover, +fieldset[disabled] .btn-info:hover, +.btn-info.disabled:focus, +.btn-info[disabled]:focus, +fieldset[disabled] .btn-info:focus, +.btn-info.disabled.focus, +.btn-info[disabled].focus, +fieldset[disabled] .btn-info.focus, +.btn-info.disabled:active, +.btn-info[disabled]:active, +fieldset[disabled] .btn-info:active, +.btn-info.disabled.active, +.btn-info[disabled].active, +fieldset[disabled] .btn-info.active { + background-color: #5bc0de; + border-color: #46b8da; +} +.btn-info .badge { + color: #5bc0de; + background-color: #fff; +} +.btn-warning { + color: #fff; + background-color: #f0ad4e; + border-color: #eea236; +} +.btn-warning:hover, +.btn-warning:focus, +.btn-warning.focus, +.btn-warning:active, +.btn-warning.active, +.open > .dropdown-toggle.btn-warning { + color: #fff; + background-color: #ec971f; + border-color: #d58512; +} +.btn-warning:active, +.btn-warning.active, +.open > .dropdown-toggle.btn-warning { + background-image: none; +} +.btn-warning.disabled, +.btn-warning[disabled], +fieldset[disabled] .btn-warning, +.btn-warning.disabled:hover, +.btn-warning[disabled]:hover, +fieldset[disabled] .btn-warning:hover, +.btn-warning.disabled:focus, +.btn-warning[disabled]:focus, +fieldset[disabled] .btn-warning:focus, +.btn-warning.disabled.focus, +.btn-warning[disabled].focus, +fieldset[disabled] .btn-warning.focus, +.btn-warning.disabled:active, +.btn-warning[disabled]:active, +fieldset[disabled] .btn-warning:active, +.btn-warning.disabled.active, +.btn-warning[disabled].active, +fieldset[disabled] .btn-warning.active { + background-color: #f0ad4e; + border-color: #eea236; +} +.btn-warning .badge { + color: #f0ad4e; + background-color: #fff; +} +.btn-danger { + color: #fff; + background-color: #d9534f; + border-color: #d43f3a; +} +.btn-danger:hover, +.btn-danger:focus, +.btn-danger.focus, +.btn-danger:active, +.btn-danger.active, +.open > .dropdown-toggle.btn-danger { + color: #fff; + background-color: #c9302c; + border-color: #ac2925; +} +.btn-danger:active, +.btn-danger.active, +.open > .dropdown-toggle.btn-danger { + background-image: none; +} +.btn-danger.disabled, +.btn-danger[disabled], +fieldset[disabled] .btn-danger, +.btn-danger.disabled:hover, +.btn-danger[disabled]:hover, +fieldset[disabled] .btn-danger:hover, +.btn-danger.disabled:focus, +.btn-danger[disabled]:focus, +fieldset[disabled] .btn-danger:focus, +.btn-danger.disabled.focus, +.btn-danger[disabled].focus, +fieldset[disabled] .btn-danger.focus, +.btn-danger.disabled:active, +.btn-danger[disabled]:active, +fieldset[disabled] .btn-danger:active, +.btn-danger.disabled.active, +.btn-danger[disabled].active, +fieldset[disabled] .btn-danger.active { + background-color: #d9534f; + border-color: #d43f3a; +} +.btn-danger .badge { + color: #d9534f; + background-color: #fff; +} +.btn-link { + font-weight: normal; + color: #337ab7; + border-radius: 0; +} +.btn-link, +.btn-link:active, +.btn-link.active, +.btn-link[disabled], +fieldset[disabled] .btn-link { + background-color: transparent; + -webkit-box-shadow: none; + box-shadow: none; +} +.btn-link, +.btn-link:hover, +.btn-link:focus, +.btn-link:active { + border-color: transparent; +} +.btn-link:hover, +.btn-link:focus { + color: #23527c; + text-decoration: underline; + background-color: transparent; +} +.btn-link[disabled]:hover, +fieldset[disabled] .btn-link:hover, +.btn-link[disabled]:focus, +fieldset[disabled] .btn-link:focus { + color: #777; + text-decoration: none; +} +.btn-lg, +.btn-group-lg > .btn { + padding: 10px 16px; + font-size: 18px; + line-height: 1.3333333; + border-radius: 6px; +} +.btn-sm, +.btn-group-sm > .btn { + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +.btn-xs, +.btn-group-xs > .btn { + padding: 1px 5px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +.btn-block { + display: block; + width: 100%; +} +.btn-block + .btn-block { + margin-top: 5px; +} +input[type="submit"].btn-block, +input[type="reset"].btn-block, +input[type="button"].btn-block { + width: 100%; +} +.fade { + opacity: 0; + -webkit-transition: opacity .15s linear; + -o-transition: opacity .15s linear; + transition: opacity .15s linear; +} +.fade.in { + opacity: 1; +} +.collapse { + display: none; +} +.collapse.in { + display: block; +} +tr.collapse.in { + display: table-row; +} +tbody.collapse.in { + display: table-row-group; +} +.collapsing { + position: relative; + height: 0; + overflow: hidden; + -webkit-transition-timing-function: ease; + -o-transition-timing-function: ease; + transition-timing-function: ease; + -webkit-transition-duration: .35s; + -o-transition-duration: .35s; + transition-duration: .35s; + -webkit-transition-property: height, visibility; + -o-transition-property: height, visibility; + transition-property: height, visibility; +} +.caret { + display: inline-block; + width: 0; + height: 0; + margin-left: 2px; + vertical-align: middle; + border-top: 4px dashed; + border-right: 4px solid transparent; + border-left: 4px solid transparent; +} +.dropup, +.dropdown { + position: relative; +} +.dropdown-toggle:focus { + outline: 0; +} +.dropdown-menu { + position: absolute; + top: 100%; + left: 0; + z-index: 1000; + display: none; + float: left; + min-width: 160px; + padding: 5px 0; + margin: 2px 0 0; + font-size: 14px; + text-align: left; + list-style: none; + background-color: #fff; + -webkit-background-clip: padding-box; + background-clip: padding-box; + border: 1px solid #ccc; + border: 1px solid rgba(0, 0, 0, .15); + border-radius: 4px; + -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, .175); + box-shadow: 0 6px 12px rgba(0, 0, 0, .175); +} +.dropdown-menu.pull-right { + right: 0; + left: auto; +} +.dropdown-menu .divider { + height: 1px; + margin: 9px 0; + overflow: hidden; + background-color: #e5e5e5; +} +.dropdown-menu > li > a { + display: block; + padding: 3px 20px; + clear: both; + font-weight: normal; + line-height: 1.42857143; + color: #333; + white-space: nowrap; +} +.dropdown-menu > li > a:hover, +.dropdown-menu > li > a:focus { + color: #262626; + text-decoration: none; + background-color: #f5f5f5; +} +.dropdown-menu > .active > a, +.dropdown-menu > .active > a:hover, +.dropdown-menu > .active > a:focus { + color: #fff; + text-decoration: none; + background-color: #337ab7; + outline: 0; +} +.dropdown-menu > .disabled > a, +.dropdown-menu > .disabled > a:hover, +.dropdown-menu > .disabled > a:focus { + color: #777; +} +.dropdown-menu > .disabled > a:hover, +.dropdown-menu > .disabled > a:focus { + text-decoration: none; + cursor: not-allowed; + background-color: transparent; + background-image: none; + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); +} +.open > .dropdown-menu { + display: block; +} +.open > a { + outline: 0; +} +.dropdown-menu-right { + right: 0; + left: auto; +} +.dropdown-menu-left { + right: auto; + left: 0; +} +.dropdown-header { + display: block; + padding: 3px 20px; + font-size: 12px; + line-height: 1.42857143; + color: #777; + white-space: nowrap; +} +.dropdown-backdrop { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 990; +} +.pull-right > .dropdown-menu { + right: 0; + left: auto; +} +.dropup .caret, +.navbar-fixed-bottom .dropdown .caret { + content: ""; + border-top: 0; + border-bottom: 4px solid; +} +.dropup .dropdown-menu, +.navbar-fixed-bottom .dropdown .dropdown-menu { + top: auto; + bottom: 100%; + margin-bottom: 2px; +} +@media (min-width: 768px) { + .navbar-right .dropdown-menu { + right: 0; + left: auto; + } + .navbar-right .dropdown-menu-left { + right: auto; + left: 0; + } +} +.btn-group, +.btn-group-vertical { + position: relative; + display: inline-block; + vertical-align: middle; +} +.btn-group > .btn, +.btn-group-vertical > .btn { + position: relative; + float: left; +} +.btn-group > .btn:hover, +.btn-group-vertical > .btn:hover, +.btn-group > .btn:focus, +.btn-group-vertical > .btn:focus, +.btn-group > .btn:active, +.btn-group-vertical > .btn:active, +.btn-group > .btn.active, +.btn-group-vertical > .btn.active { + z-index: 2; +} +.btn-group .btn + .btn, +.btn-group .btn + .btn-group, +.btn-group .btn-group + .btn, +.btn-group .btn-group + .btn-group { + margin-left: -1px; +} +.btn-toolbar { + margin-left: -5px; +} +.btn-toolbar .btn-group, +.btn-toolbar .input-group { + float: left; +} +.btn-toolbar > .btn, +.btn-toolbar > .btn-group, +.btn-toolbar > .input-group { + margin-left: 5px; +} +.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) { + border-radius: 0; +} +.btn-group > .btn:first-child { + margin-left: 0; +} +.btn-group > .btn:first-child:not(:last-child):not(.dropdown-toggle) { + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} +.btn-group > .btn:last-child:not(:first-child), +.btn-group > .dropdown-toggle:not(:first-child) { + border-top-left-radius: 0; + border-bottom-left-radius: 0; +} +.btn-group > .btn-group { + float: left; +} +.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn { + border-radius: 0; +} +.btn-group > .btn-group:first-child:not(:last-child) > .btn:last-child, +.btn-group > .btn-group:first-child:not(:last-child) > .dropdown-toggle { + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} +.btn-group > .btn-group:last-child:not(:first-child) > .btn:first-child { + border-top-left-radius: 0; + border-bottom-left-radius: 0; +} +.btn-group .dropdown-toggle:active, +.btn-group.open .dropdown-toggle { + outline: 0; +} +.btn-group > .btn + .dropdown-toggle { + padding-right: 8px; + padding-left: 8px; +} +.btn-group > .btn-lg + .dropdown-toggle { + padding-right: 12px; + padding-left: 12px; +} +.btn-group.open .dropdown-toggle { + -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); + box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); +} +.btn-group.open .dropdown-toggle.btn-link { + -webkit-box-shadow: none; + box-shadow: none; +} +.btn .caret { + margin-left: 0; +} +.btn-lg .caret { + border-width: 5px 5px 0; + border-bottom-width: 0; +} +.dropup .btn-lg .caret { + border-width: 0 5px 5px; +} +.btn-group-vertical > .btn, +.btn-group-vertical > .btn-group, +.btn-group-vertical > .btn-group > .btn { + display: block; + float: none; + width: 100%; + max-width: 100%; +} +.btn-group-vertical > .btn-group > .btn { + float: none; +} +.btn-group-vertical > .btn + .btn, +.btn-group-vertical > .btn + .btn-group, +.btn-group-vertical > .btn-group + .btn, +.btn-group-vertical > .btn-group + .btn-group { + margin-top: -1px; + margin-left: 0; +} +.btn-group-vertical > .btn:not(:first-child):not(:last-child) { + border-radius: 0; +} +.btn-group-vertical > .btn:first-child:not(:last-child) { + border-top-right-radius: 4px; + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} +.btn-group-vertical > .btn:last-child:not(:first-child) { + border-top-left-radius: 0; + border-top-right-radius: 0; + border-bottom-left-radius: 4px; +} +.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn { + border-radius: 0; +} +.btn-group-vertical > .btn-group:first-child:not(:last-child) > .btn:last-child, +.btn-group-vertical > .btn-group:first-child:not(:last-child) > .dropdown-toggle { + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} +.btn-group-vertical > .btn-group:last-child:not(:first-child) > .btn:first-child { + border-top-left-radius: 0; + border-top-right-radius: 0; +} +.btn-group-justified { + display: table; + width: 100%; + table-layout: fixed; + border-collapse: separate; +} +.btn-group-justified > .btn, +.btn-group-justified > .btn-group { + display: table-cell; + float: none; + width: 1%; +} +.btn-group-justified > .btn-group .btn { + width: 100%; +} +.btn-group-justified > .btn-group .dropdown-menu { + left: auto; +} +[data-toggle="buttons"] > .btn input[type="radio"], +[data-toggle="buttons"] > .btn-group > .btn input[type="radio"], +[data-toggle="buttons"] > .btn input[type="checkbox"], +[data-toggle="buttons"] > .btn-group > .btn input[type="checkbox"] { + position: absolute; + clip: rect(0, 0, 0, 0); + pointer-events: none; +} +.input-group { + position: relative; + display: table; + border-collapse: separate; +} +.input-group[class*="col-"] { + float: none; + padding-right: 0; + padding-left: 0; +} +.input-group .form-control { + position: relative; + z-index: 2; + float: left; + width: 100%; + margin-bottom: 0; +} +.input-group-lg > .form-control, +.input-group-lg > .input-group-addon, +.input-group-lg > .input-group-btn > .btn { + height: 46px; + padding: 10px 16px; + font-size: 18px; + line-height: 1.3333333; + border-radius: 6px; +} +select.input-group-lg > .form-control, +select.input-group-lg > .input-group-addon, +select.input-group-lg > .input-group-btn > .btn { + height: 46px; + line-height: 46px; +} +textarea.input-group-lg > .form-control, +textarea.input-group-lg > .input-group-addon, +textarea.input-group-lg > .input-group-btn > .btn, +select[multiple].input-group-lg > .form-control, +select[multiple].input-group-lg > .input-group-addon, +select[multiple].input-group-lg > .input-group-btn > .btn { + height: auto; +} +.input-group-sm > .form-control, +.input-group-sm > .input-group-addon, +.input-group-sm > .input-group-btn > .btn { + height: 30px; + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +select.input-group-sm > .form-control, +select.input-group-sm > .input-group-addon, +select.input-group-sm > .input-group-btn > .btn { + height: 30px; + line-height: 30px; +} +textarea.input-group-sm > .form-control, +textarea.input-group-sm > .input-group-addon, +textarea.input-group-sm > .input-group-btn > .btn, +select[multiple].input-group-sm > .form-control, +select[multiple].input-group-sm > .input-group-addon, +select[multiple].input-group-sm > .input-group-btn > .btn { + height: auto; +} +.input-group-addon, +.input-group-btn, +.input-group .form-control { + display: table-cell; +} +.input-group-addon:not(:first-child):not(:last-child), +.input-group-btn:not(:first-child):not(:last-child), +.input-group .form-control:not(:first-child):not(:last-child) { + border-radius: 0; +} +.input-group-addon, +.input-group-btn { + width: 1%; + white-space: nowrap; + vertical-align: middle; +} +.input-group-addon { + padding: 6px 12px; + font-size: 14px; + font-weight: normal; + line-height: 1; + color: #555; + text-align: center; + background-color: #eee; + border: 1px solid #ccc; + border-radius: 4px; +} +.input-group-addon.input-sm { + padding: 5px 10px; + font-size: 12px; + border-radius: 3px; +} +.input-group-addon.input-lg { + padding: 10px 16px; + font-size: 18px; + border-radius: 6px; +} +.input-group-addon input[type="radio"], +.input-group-addon input[type="checkbox"] { + margin-top: 0; +} +.input-group .form-control:first-child, +.input-group-addon:first-child, +.input-group-btn:first-child > .btn, +.input-group-btn:first-child > .btn-group > .btn, +.input-group-btn:first-child > .dropdown-toggle, +.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle), +.input-group-btn:last-child > .btn-group:not(:last-child) > .btn { + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} +.input-group-addon:first-child { + border-right: 0; +} +.input-group .form-control:last-child, +.input-group-addon:last-child, +.input-group-btn:last-child > .btn, +.input-group-btn:last-child > .btn-group > .btn, +.input-group-btn:last-child > .dropdown-toggle, +.input-group-btn:first-child > .btn:not(:first-child), +.input-group-btn:first-child > .btn-group:not(:first-child) > .btn { + border-top-left-radius: 0; + border-bottom-left-radius: 0; +} +.input-group-addon:last-child { + border-left: 0; +} +.input-group-btn { + position: relative; + font-size: 0; + white-space: nowrap; +} +.input-group-btn > .btn { + position: relative; +} +.input-group-btn > .btn + .btn { + margin-left: -1px; +} +.input-group-btn > .btn:hover, +.input-group-btn > .btn:focus, +.input-group-btn > .btn:active { + z-index: 2; +} +.input-group-btn:first-child > .btn, +.input-group-btn:first-child > .btn-group { + margin-right: -1px; +} +.input-group-btn:last-child > .btn, +.input-group-btn:last-child > .btn-group { + margin-left: -1px; +} +.nav { + padding-left: 0; + margin-bottom: 0; + list-style: none; +} +.nav > li { + position: relative; + display: block; +} +.nav > li > a { + position: relative; + display: block; + padding: 10px 15px; +} +.nav > li > a:hover, +.nav > li > a:focus { + text-decoration: none; + background-color: #eee; +} +.nav > li.disabled > a { + color: #777; +} +.nav > li.disabled > a:hover, +.nav > li.disabled > a:focus { + color: #777; + text-decoration: none; + cursor: not-allowed; + background-color: transparent; +} +.nav .open > a, +.nav .open > a:hover, +.nav .open > a:focus { + background-color: #eee; + border-color: #337ab7; +} +.nav .nav-divider { + height: 1px; + margin: 9px 0; + overflow: hidden; + background-color: #e5e5e5; +} +.nav > li > a > img { + max-width: none; +} +.nav-tabs { + border-bottom: 1px solid #ddd; +} +.nav-tabs > li { + float: left; + margin-bottom: -1px; +} +.nav-tabs > li > a { + margin-right: 2px; + line-height: 1.42857143; + border: 1px solid transparent; + border-radius: 4px 4px 0 0; +} +.nav-tabs > li > a:hover { + border-color: #eee #eee #ddd; +} +.nav-tabs > li.active > a, +.nav-tabs > li.active > a:hover, +.nav-tabs > li.active > a:focus { + color: #555; + cursor: default; + background-color: #fff; + border: 1px solid #ddd; + border-bottom-color: transparent; +} +.nav-tabs.nav-justified { + width: 100%; + border-bottom: 0; +} +.nav-tabs.nav-justified > li { + float: none; +} +.nav-tabs.nav-justified > li > a { + margin-bottom: 5px; + text-align: center; +} +.nav-tabs.nav-justified > .dropdown .dropdown-menu { + top: auto; + left: auto; +} +@media (min-width: 768px) { + .nav-tabs.nav-justified > li { + display: table-cell; + width: 1%; + } + .nav-tabs.nav-justified > li > a { + margin-bottom: 0; + } +} +.nav-tabs.nav-justified > li > a { + margin-right: 0; + border-radius: 4px; +} +.nav-tabs.nav-justified > .active > a, +.nav-tabs.nav-justified > .active > a:hover, +.nav-tabs.nav-justified > .active > a:focus { + border: 1px solid #ddd; +} +@media (min-width: 768px) { + .nav-tabs.nav-justified > li > a { + border-bottom: 1px solid #ddd; + border-radius: 4px 4px 0 0; + } + .nav-tabs.nav-justified > .active > a, + .nav-tabs.nav-justified > .active > a:hover, + .nav-tabs.nav-justified > .active > a:focus { + border-bottom-color: #fff; + } +} +.nav-pills > li { + float: left; +} +.nav-pills > li > a { + border-radius: 4px; +} +.nav-pills > li + li { + margin-left: 2px; +} +.nav-pills > li.active > a, +.nav-pills > li.active > a:hover, +.nav-pills > li.active > a:focus { + color: #fff; + background-color: #337ab7; +} +.nav-stacked > li { + float: none; +} +.nav-stacked > li + li { + margin-top: 2px; + margin-left: 0; +} +.nav-justified { + width: 100%; +} +.nav-justified > li { + float: none; +} +.nav-justified > li > a { + margin-bottom: 5px; + text-align: center; +} +.nav-justified > .dropdown .dropdown-menu { + top: auto; + left: auto; +} +@media (min-width: 768px) { + .nav-justified > li { + display: table-cell; + width: 1%; + } + .nav-justified > li > a { + margin-bottom: 0; + } +} +.nav-tabs-justified { + border-bottom: 0; +} +.nav-tabs-justified > li > a { + margin-right: 0; + border-radius: 4px; +} +.nav-tabs-justified > .active > a, +.nav-tabs-justified > .active > a:hover, +.nav-tabs-justified > .active > a:focus { + border: 1px solid #ddd; +} +@media (min-width: 768px) { + .nav-tabs-justified > li > a { + border-bottom: 1px solid #ddd; + border-radius: 4px 4px 0 0; + } + .nav-tabs-justified > .active > a, + .nav-tabs-justified > .active > a:hover, + .nav-tabs-justified > .active > a:focus { + border-bottom-color: #fff; + } +} +.tab-content > .tab-pane { + display: none; +} +.tab-content > .active { + display: block; +} +.nav-tabs .dropdown-menu { + margin-top: -1px; + border-top-left-radius: 0; + border-top-right-radius: 0; +} +.navbar { + position: relative; + min-height: 50px; + margin-bottom: 20px; + border: 1px solid transparent; +} +@media (min-width: 768px) { + .navbar { + border-radius: 4px; + } +} +@media (min-width: 768px) { + .navbar-header { + float: left; + } +} +.navbar-collapse { + padding-right: 15px; + padding-left: 15px; + overflow-x: visible; + -webkit-overflow-scrolling: touch; + border-top: 1px solid transparent; + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1); +} +.navbar-collapse.in { + overflow-y: auto; +} +@media (min-width: 768px) { + .navbar-collapse { + width: auto; + border-top: 0; + -webkit-box-shadow: none; + box-shadow: none; + } + .navbar-collapse.collapse { + display: block !important; + height: auto !important; + padding-bottom: 0; + overflow: visible !important; + } + .navbar-collapse.in { + overflow-y: visible; + } + .navbar-fixed-top .navbar-collapse, + .navbar-static-top .navbar-collapse, + .navbar-fixed-bottom .navbar-collapse { + padding-right: 0; + padding-left: 0; + } +} +.navbar-fixed-top .navbar-collapse, +.navbar-fixed-bottom .navbar-collapse { + max-height: 340px; +} +@media (max-device-width: 480px) and (orientation: landscape) { + .navbar-fixed-top .navbar-collapse, + .navbar-fixed-bottom .navbar-collapse { + max-height: 200px; + } +} +.container > .navbar-header, +.container-fluid > .navbar-header, +.container > .navbar-collapse, +.container-fluid > .navbar-collapse { + margin-right: -15px; + margin-left: -15px; +} +@media (min-width: 768px) { + .container > .navbar-header, + .container-fluid > .navbar-header, + .container > .navbar-collapse, + .container-fluid > .navbar-collapse { + margin-right: 0; + margin-left: 0; + } +} +.navbar-static-top { + z-index: 1000; + border-width: 0 0 1px; +} +@media (min-width: 768px) { + .navbar-static-top { + border-radius: 0; + } +} +.navbar-fixed-top, +.navbar-fixed-bottom { + position: fixed; + right: 0; + left: 0; + z-index: 1030; +} +@media (min-width: 768px) { + .navbar-fixed-top, + .navbar-fixed-bottom { + border-radius: 0; + } +} +.navbar-fixed-top { + top: 0; + border-width: 0 0 1px; +} +.navbar-fixed-bottom { + bottom: 0; + margin-bottom: 0; + border-width: 1px 0 0; +} +.navbar-brand { + float: left; + height: 50px; + padding: 15px 15px; + font-size: 18px; + line-height: 20px; +} +.navbar-brand:hover, +.navbar-brand:focus { + text-decoration: none; +} +.navbar-brand > img { + display: block; +} +@media (min-width: 768px) { + .navbar > .container .navbar-brand, + .navbar > .container-fluid .navbar-brand { + margin-left: -15px; + } +} +.navbar-toggle { + position: relative; + float: right; + padding: 9px 10px; + margin-top: 8px; + margin-right: 15px; + margin-bottom: 8px; + background-color: transparent; + background-image: none; + border: 1px solid transparent; + border-radius: 4px; +} +.navbar-toggle:focus { + outline: 0; +} +.navbar-toggle .icon-bar { + display: block; + width: 22px; + height: 2px; + border-radius: 1px; +} +.navbar-toggle .icon-bar + .icon-bar { + margin-top: 4px; +} +@media (min-width: 768px) { + .navbar-toggle { + display: none; + } +} +.navbar-nav { + margin: 7.5px -15px; +} +.navbar-nav > li > a { + padding-top: 10px; + padding-bottom: 10px; + line-height: 20px; +} +@media (max-width: 767px) { + .navbar-nav .open .dropdown-menu { + position: static; + float: none; + width: auto; + margin-top: 0; + background-color: transparent; + border: 0; + -webkit-box-shadow: none; + box-shadow: none; + } + .navbar-nav .open .dropdown-menu > li > a, + .navbar-nav .open .dropdown-menu .dropdown-header { + padding: 5px 15px 5px 25px; + } + .navbar-nav .open .dropdown-menu > li > a { + line-height: 20px; + } + .navbar-nav .open .dropdown-menu > li > a:hover, + .navbar-nav .open .dropdown-menu > li > a:focus { + background-image: none; + } +} +@media (min-width: 768px) { + .navbar-nav { + float: left; + margin: 0; + } + .navbar-nav > li { + float: left; + } + .navbar-nav > li > a { + padding-top: 15px; + padding-bottom: 15px; + } +} +.navbar-form { + padding: 10px 15px; + margin-top: 8px; + margin-right: -15px; + margin-bottom: 8px; + margin-left: -15px; + border-top: 1px solid transparent; + border-bottom: 1px solid transparent; + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1), 0 1px 0 rgba(255, 255, 255, .1); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1), 0 1px 0 rgba(255, 255, 255, .1); +} +@media (min-width: 768px) { + .navbar-form .form-group { + display: inline-block; + margin-bottom: 0; + vertical-align: middle; + } + .navbar-form .form-control { + display: inline-block; + width: auto; + vertical-align: middle; + } + .navbar-form .form-control-static { + display: inline-block; + } + .navbar-form .input-group { + display: inline-table; + vertical-align: middle; + } + .navbar-form .input-group .input-group-addon, + .navbar-form .input-group .input-group-btn, + .navbar-form .input-group .form-control { + width: auto; + } + .navbar-form .input-group > .form-control { + width: 100%; + } + .navbar-form .control-label { + margin-bottom: 0; + vertical-align: middle; + } + .navbar-form .radio, + .navbar-form .checkbox { + display: inline-block; + margin-top: 0; + margin-bottom: 0; + vertical-align: middle; + } + .navbar-form .radio label, + .navbar-form .checkbox label { + padding-left: 0; + } + .navbar-form .radio input[type="radio"], + .navbar-form .checkbox input[type="checkbox"] { + position: relative; + margin-left: 0; + } + .navbar-form .has-feedback .form-control-feedback { + top: 0; + } +} +@media (max-width: 767px) { + .navbar-form .form-group { + margin-bottom: 5px; + } + .navbar-form .form-group:last-child { + margin-bottom: 0; + } +} +@media (min-width: 768px) { + .navbar-form { + width: auto; + padding-top: 0; + padding-bottom: 0; + margin-right: 0; + margin-left: 0; + border: 0; + -webkit-box-shadow: none; + box-shadow: none; + } +} +.navbar-nav > li > .dropdown-menu { + margin-top: 0; + border-top-left-radius: 0; + border-top-right-radius: 0; +} +.navbar-fixed-bottom .navbar-nav > li > .dropdown-menu { + margin-bottom: 0; + border-top-left-radius: 4px; + border-top-right-radius: 4px; + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} +.navbar-btn { + margin-top: 8px; + margin-bottom: 8px; +} +.navbar-btn.btn-sm { + margin-top: 10px; + margin-bottom: 10px; +} +.navbar-btn.btn-xs { + margin-top: 14px; + margin-bottom: 14px; +} +.navbar-text { + margin-top: 15px; + margin-bottom: 15px; +} +@media (min-width: 768px) { + .navbar-text { + float: left; + margin-right: 15px; + margin-left: 15px; + } +} +@media (min-width: 768px) { + .navbar-left { + float: left !important; + } + .navbar-right { + float: right !important; + margin-right: -15px; + } + .navbar-right ~ .navbar-right { + margin-right: 0; + } +} +.navbar-default { + background-color: #f8f8f8; + border-color: #e7e7e7; +} +.navbar-default .navbar-brand { + color: #777; +} +.navbar-default .navbar-brand:hover, +.navbar-default .navbar-brand:focus { + color: #5e5e5e; + background-color: transparent; +} +.navbar-default .navbar-text { + color: #777; +} +.navbar-default .navbar-nav > li > a { + color: #777; +} +.navbar-default .navbar-nav > li > a:hover, +.navbar-default .navbar-nav > li > a:focus { + color: #333; + background-color: transparent; +} +.navbar-default .navbar-nav > .active > a, +.navbar-default .navbar-nav > .active > a:hover, +.navbar-default .navbar-nav > .active > a:focus { + color: #555; + background-color: #e7e7e7; +} +.navbar-default .navbar-nav > .disabled > a, +.navbar-default .navbar-nav > .disabled > a:hover, +.navbar-default .navbar-nav > .disabled > a:focus { + color: #ccc; + background-color: transparent; +} +.navbar-default .navbar-toggle { + border-color: #ddd; +} +.navbar-default .navbar-toggle:hover, +.navbar-default .navbar-toggle:focus { + background-color: #ddd; +} +.navbar-default .navbar-toggle .icon-bar { + background-color: #888; +} +.navbar-default .navbar-collapse, +.navbar-default .navbar-form { + border-color: #e7e7e7; +} +.navbar-default .navbar-nav > .open > a, +.navbar-default .navbar-nav > .open > a:hover, +.navbar-default .navbar-nav > .open > a:focus { + color: #555; + background-color: #e7e7e7; +} +@media (max-width: 767px) { + .navbar-default .navbar-nav .open .dropdown-menu > li > a { + color: #777; + } + .navbar-default .navbar-nav .open .dropdown-menu > li > a:hover, + .navbar-default .navbar-nav .open .dropdown-menu > li > a:focus { + color: #333; + background-color: transparent; + } + .navbar-default .navbar-nav .open .dropdown-menu > .active > a, + .navbar-default .navbar-nav .open .dropdown-menu > .active > a:hover, + .navbar-default .navbar-nav .open .dropdown-menu > .active > a:focus { + color: #555; + background-color: #e7e7e7; + } + .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a, + .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:hover, + .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:focus { + color: #ccc; + background-color: transparent; + } +} +.navbar-default .navbar-link { + color: #777; +} +.navbar-default .navbar-link:hover { + color: #333; +} +.navbar-default .btn-link { + color: #777; +} +.navbar-default .btn-link:hover, +.navbar-default .btn-link:focus { + color: #333; +} +.navbar-default .btn-link[disabled]:hover, +fieldset[disabled] .navbar-default .btn-link:hover, +.navbar-default .btn-link[disabled]:focus, +fieldset[disabled] .navbar-default .btn-link:focus { + color: #ccc; +} +.navbar-inverse { + background-color: #222; + border-color: #080808; +} +.navbar-inverse .navbar-brand { + color: #9d9d9d; +} +.navbar-inverse .navbar-brand:hover, +.navbar-inverse .navbar-brand:focus { + color: #fff; + background-color: transparent; +} +.navbar-inverse .navbar-text { + color: #9d9d9d; +} +.navbar-inverse .navbar-nav > li > a { + color: #9d9d9d; +} +.navbar-inverse .navbar-nav > li > a:hover, +.navbar-inverse .navbar-nav > li > a:focus { + color: #fff; + background-color: transparent; +} +.navbar-inverse .navbar-nav > .active > a, +.navbar-inverse .navbar-nav > .active > a:hover, +.navbar-inverse .navbar-nav > .active > a:focus { + color: #fff; + background-color: #080808; +} +.navbar-inverse .navbar-nav > .disabled > a, +.navbar-inverse .navbar-nav > .disabled > a:hover, +.navbar-inverse .navbar-nav > .disabled > a:focus { + color: #444; + background-color: transparent; +} +.navbar-inverse .navbar-toggle { + border-color: #333; +} +.navbar-inverse .navbar-toggle:hover, +.navbar-inverse .navbar-toggle:focus { + background-color: #333; +} +.navbar-inverse .navbar-toggle .icon-bar { + background-color: #fff; +} +.navbar-inverse .navbar-collapse, +.navbar-inverse .navbar-form { + border-color: #101010; +} +.navbar-inverse .navbar-nav > .open > a, +.navbar-inverse .navbar-nav > .open > a:hover, +.navbar-inverse .navbar-nav > .open > a:focus { + color: #fff; + background-color: #080808; +} +@media (max-width: 767px) { + .navbar-inverse .navbar-nav .open .dropdown-menu > .dropdown-header { + border-color: #080808; + } + .navbar-inverse .navbar-nav .open .dropdown-menu .divider { + background-color: #080808; + } + .navbar-inverse .navbar-nav .open .dropdown-menu > li > a { + color: #9d9d9d; + } + .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:hover, + .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:focus { + color: #fff; + background-color: transparent; + } + .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a, + .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:hover, + .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:focus { + color: #fff; + background-color: #080808; + } + .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a, + .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:hover, + .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:focus { + color: #444; + background-color: transparent; + } +} +.navbar-inverse .navbar-link { + color: #9d9d9d; +} +.navbar-inverse .navbar-link:hover { + color: #fff; +} +.navbar-inverse .btn-link { + color: #9d9d9d; +} +.navbar-inverse .btn-link:hover, +.navbar-inverse .btn-link:focus { + color: #fff; +} +.navbar-inverse .btn-link[disabled]:hover, +fieldset[disabled] .navbar-inverse .btn-link:hover, +.navbar-inverse .btn-link[disabled]:focus, +fieldset[disabled] .navbar-inverse .btn-link:focus { + color: #444; +} +.breadcrumb { + padding: 8px 15px; + margin-bottom: 20px; + list-style: none; + background-color: #f5f5f5; + border-radius: 4px; +} +.breadcrumb > li { + display: inline-block; +} +.breadcrumb > li + li:before { + padding: 0 5px; + color: #ccc; + content: "/\00a0"; +} +.breadcrumb > .active { + color: #777; +} +.pagination { + display: inline-block; + padding-left: 0; + margin: 20px 0; + border-radius: 4px; +} +.pagination > li { + display: inline; +} +.pagination > li > a, +.pagination > li > span { + position: relative; + float: left; + padding: 6px 12px; + margin-left: -1px; + line-height: 1.42857143; + color: #337ab7; + text-decoration: none; + background-color: #fff; + border: 1px solid #ddd; +} +.pagination > li:first-child > a, +.pagination > li:first-child > span { + margin-left: 0; + border-top-left-radius: 4px; + border-bottom-left-radius: 4px; +} +.pagination > li:last-child > a, +.pagination > li:last-child > span { + border-top-right-radius: 4px; + border-bottom-right-radius: 4px; +} +.pagination > li > a:hover, +.pagination > li > span:hover, +.pagination > li > a:focus, +.pagination > li > span:focus { + color: #23527c; + background-color: #eee; + border-color: #ddd; +} +.pagination > .active > a, +.pagination > .active > span, +.pagination > .active > a:hover, +.pagination > .active > span:hover, +.pagination > .active > a:focus, +.pagination > .active > span:focus { + z-index: 2; + color: #fff; + cursor: default; + background-color: #337ab7; + border-color: #337ab7; +} +.pagination > .disabled > span, +.pagination > .disabled > span:hover, +.pagination > .disabled > span:focus, +.pagination > .disabled > a, +.pagination > .disabled > a:hover, +.pagination > .disabled > a:focus { + color: #777; + cursor: not-allowed; + background-color: #fff; + border-color: #ddd; +} +.pagination-lg > li > a, +.pagination-lg > li > span { + padding: 10px 16px; + font-size: 18px; +} +.pagination-lg > li:first-child > a, +.pagination-lg > li:first-child > span { + border-top-left-radius: 6px; + border-bottom-left-radius: 6px; +} +.pagination-lg > li:last-child > a, +.pagination-lg > li:last-child > span { + border-top-right-radius: 6px; + border-bottom-right-radius: 6px; +} +.pagination-sm > li > a, +.pagination-sm > li > span { + padding: 5px 10px; + font-size: 12px; +} +.pagination-sm > li:first-child > a, +.pagination-sm > li:first-child > span { + border-top-left-radius: 3px; + border-bottom-left-radius: 3px; +} +.pagination-sm > li:last-child > a, +.pagination-sm > li:last-child > span { + border-top-right-radius: 3px; + border-bottom-right-radius: 3px; +} +.pager { + padding-left: 0; + margin: 20px 0; + text-align: center; + list-style: none; +} +.pager li { + display: inline; +} +.pager li > a, +.pager li > span { + display: inline-block; + padding: 5px 14px; + background-color: #fff; + border: 1px solid #ddd; + border-radius: 15px; +} +.pager li > a:hover, +.pager li > a:focus { + text-decoration: none; + background-color: #eee; +} +.pager .next > a, +.pager .next > span { + float: right; +} +.pager .previous > a, +.pager .previous > span { + float: left; +} +.pager .disabled > a, +.pager .disabled > a:hover, +.pager .disabled > a:focus, +.pager .disabled > span { + color: #777; + cursor: not-allowed; + background-color: #fff; +} +.label { + display: inline; + padding: .2em .6em .3em; + font-size: 75%; + font-weight: bold; + line-height: 1; + color: #fff; + text-align: center; + white-space: nowrap; + vertical-align: baseline; + border-radius: .25em; +} +a.label:hover, +a.label:focus { + color: #fff; + text-decoration: none; + cursor: pointer; +} +.label:empty { + display: none; +} +.btn .label { + position: relative; + top: -1px; +} +.label-default { + background-color: #777; +} +.label-default[href]:hover, +.label-default[href]:focus { + background-color: #5e5e5e; +} +.label-primary { + background-color: #337ab7; +} +.label-primary[href]:hover, +.label-primary[href]:focus { + background-color: #286090; +} +.label-success { + background-color: #5cb85c; +} +.label-success[href]:hover, +.label-success[href]:focus { + background-color: #449d44; +} +.label-info { + background-color: #5bc0de; +} +.label-info[href]:hover, +.label-info[href]:focus { + background-color: #31b0d5; +} +.label-warning { + background-color: #f0ad4e; +} +.label-warning[href]:hover, +.label-warning[href]:focus { + background-color: #ec971f; +} +.label-danger { + background-color: #d9534f; +} +.label-danger[href]:hover, +.label-danger[href]:focus { + background-color: #c9302c; +} +.badge { + display: inline-block; + min-width: 10px; + padding: 3px 7px; + font-size: 12px; + font-weight: bold; + line-height: 1; + color: #fff; + text-align: center; + white-space: nowrap; + vertical-align: baseline; + background-color: #777; + border-radius: 10px; +} +.badge:empty { + display: none; +} +.btn .badge { + position: relative; + top: -1px; +} +.btn-xs .badge, +.btn-group-xs > .btn .badge { + top: 0; + padding: 1px 5px; +} +a.badge:hover, +a.badge:focus { + color: #fff; + text-decoration: none; + cursor: pointer; +} +.list-group-item.active > .badge, +.nav-pills > .active > a > .badge { + color: #337ab7; + background-color: #fff; +} +.list-group-item > .badge { + float: right; +} +.list-group-item > .badge + .badge { + margin-right: 5px; +} +.nav-pills > li > a > .badge { + margin-left: 3px; +} +.jumbotron { + padding: 30px 15px; + margin-bottom: 30px; + color: inherit; + background-color: #eee; +} +.jumbotron h1, +.jumbotron .h1 { + color: inherit; +} +.jumbotron p { + margin-bottom: 15px; + font-size: 21px; + font-weight: 200; +} +.jumbotron > hr { + border-top-color: #d5d5d5; +} +.container .jumbotron, +.container-fluid .jumbotron { + border-radius: 6px; +} +.jumbotron .container { + max-width: 100%; +} +@media screen and (min-width: 768px) { + .jumbotron { + padding: 48px 0; + } + .container .jumbotron, + .container-fluid .jumbotron { + padding-right: 60px; + padding-left: 60px; + } + .jumbotron h1, + .jumbotron .h1 { + font-size: 63px; + } +} +.thumbnail { + display: block; + padding: 4px; + margin-bottom: 20px; + line-height: 1.42857143; + background-color: #fff; + border: 1px solid #ddd; + border-radius: 4px; + -webkit-transition: border .2s ease-in-out; + -o-transition: border .2s ease-in-out; + transition: border .2s ease-in-out; +} +.thumbnail > img, +.thumbnail a > img { + margin-right: auto; + margin-left: auto; +} +a.thumbnail:hover, +a.thumbnail:focus, +a.thumbnail.active { + border-color: #337ab7; +} +.thumbnail .caption { + padding: 9px; + color: #333; +} +.alert { + padding: 15px; + margin-bottom: 20px; + border: 1px solid transparent; + border-radius: 4px; +} +.alert h4 { + margin-top: 0; + color: inherit; +} +.alert .alert-link { + font-weight: bold; +} +.alert > p, +.alert > ul { + margin-bottom: 0; +} +.alert > p + p { + margin-top: 5px; +} +.alert-dismissable, +.alert-dismissible { + padding-right: 35px; +} +.alert-dismissable .close, +.alert-dismissible .close { + position: relative; + top: -2px; + right: -21px; + color: inherit; +} +.alert-success { + color: #3c763d; + background-color: #dff0d8; + border-color: #d6e9c6; +} +.alert-success hr { + border-top-color: #c9e2b3; +} +.alert-success .alert-link { + color: #2b542c; +} +.alert-info { + color: #31708f; + background-color: #d9edf7; + border-color: #bce8f1; +} +.alert-info hr { + border-top-color: #a6e1ec; +} +.alert-info .alert-link { + color: #245269; +} +.alert-warning { + color: #8a6d3b; + background-color: #fcf8e3; + border-color: #faebcc; +} +.alert-warning hr { + border-top-color: #f7e1b5; +} +.alert-warning .alert-link { + color: #66512c; +} +.alert-danger { + color: #a94442; + background-color: #f2dede; + border-color: #ebccd1; +} +.alert-danger hr { + border-top-color: #e4b9c0; +} +.alert-danger .alert-link { + color: #843534; +} +@-webkit-keyframes progress-bar-stripes { + from { + background-position: 40px 0; + } + to { + background-position: 0 0; + } +} +@-o-keyframes progress-bar-stripes { + from { + background-position: 40px 0; + } + to { + background-position: 0 0; + } +} +@keyframes progress-bar-stripes { + from { + background-position: 40px 0; + } + to { + background-position: 0 0; + } +} +.progress { + height: 20px; + margin-bottom: 20px; + overflow: hidden; + background-color: #f5f5f5; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, .1); + box-shadow: inset 0 1px 2px rgba(0, 0, 0, .1); +} +.progress-bar { + float: left; + width: 0; + height: 100%; + font-size: 12px; + line-height: 20px; + color: #fff; + text-align: center; + background-color: #337ab7; + -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .15); + box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .15); + -webkit-transition: width .6s ease; + -o-transition: width .6s ease; + transition: width .6s ease; +} +.progress-striped .progress-bar, +.progress-bar-striped { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + -webkit-background-size: 40px 40px; + background-size: 40px 40px; +} +.progress.active .progress-bar, +.progress-bar.active { + -webkit-animation: progress-bar-stripes 2s linear infinite; + -o-animation: progress-bar-stripes 2s linear infinite; + animation: progress-bar-stripes 2s linear infinite; +} +.progress-bar-success { + background-color: #5cb85c; +} +.progress-striped .progress-bar-success { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); +} +.progress-bar-info { + background-color: #5bc0de; +} +.progress-striped .progress-bar-info { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); +} +.progress-bar-warning { + background-color: #f0ad4e; +} +.progress-striped .progress-bar-warning { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); +} +.progress-bar-danger { + background-color: #d9534f; +} +.progress-striped .progress-bar-danger { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); +} +.media { + margin-top: 15px; +} +.media:first-child { + margin-top: 0; +} +.media, +.media-body { + overflow: hidden; + zoom: 1; +} +.media-body { + width: 10000px; +} +.media-object { + display: block; +} +.media-right, +.media > .pull-right { + padding-left: 10px; +} +.media-left, +.media > .pull-left { + padding-right: 10px; +} +.media-left, +.media-right, +.media-body { + display: table-cell; + vertical-align: top; +} +.media-middle { + vertical-align: middle; +} +.media-bottom { + vertical-align: bottom; +} +.media-heading { + margin-top: 0; + margin-bottom: 5px; +} +.media-list { + padding-left: 0; + list-style: none; +} +.list-group { + padding-left: 0; + margin-bottom: 20px; +} +.list-group-item { + position: relative; + display: block; + padding: 10px 15px; + margin-bottom: -1px; + background-color: #fff; + border: 1px solid #ddd; +} +.list-group-item:first-child { + border-top-left-radius: 4px; + border-top-right-radius: 4px; +} +.list-group-item:last-child { + margin-bottom: 0; + border-bottom-right-radius: 4px; + border-bottom-left-radius: 4px; +} +a.list-group-item { + color: #555; +} +a.list-group-item .list-group-item-heading { + color: #333; +} +a.list-group-item:hover, +a.list-group-item:focus { + color: #555; + text-decoration: none; + background-color: #f5f5f5; +} +.list-group-item.disabled, +.list-group-item.disabled:hover, +.list-group-item.disabled:focus { + color: #777; + cursor: not-allowed; + background-color: #eee; +} +.list-group-item.disabled .list-group-item-heading, +.list-group-item.disabled:hover .list-group-item-heading, +.list-group-item.disabled:focus .list-group-item-heading { + color: inherit; +} +.list-group-item.disabled .list-group-item-text, +.list-group-item.disabled:hover .list-group-item-text, +.list-group-item.disabled:focus .list-group-item-text { + color: #777; +} +.list-group-item.active, +.list-group-item.active:hover, +.list-group-item.active:focus { + z-index: 2; + color: #fff; + background-color: #337ab7; + border-color: #337ab7; +} +.list-group-item.active .list-group-item-heading, +.list-group-item.active:hover .list-group-item-heading, +.list-group-item.active:focus .list-group-item-heading, +.list-group-item.active .list-group-item-heading > small, +.list-group-item.active:hover .list-group-item-heading > small, +.list-group-item.active:focus .list-group-item-heading > small, +.list-group-item.active .list-group-item-heading > .small, +.list-group-item.active:hover .list-group-item-heading > .small, +.list-group-item.active:focus .list-group-item-heading > .small { + color: inherit; +} +.list-group-item.active .list-group-item-text, +.list-group-item.active:hover .list-group-item-text, +.list-group-item.active:focus .list-group-item-text { + color: #c7ddef; +} +.list-group-item-success { + color: #3c763d; + background-color: #dff0d8; +} +a.list-group-item-success { + color: #3c763d; +} +a.list-group-item-success .list-group-item-heading { + color: inherit; +} +a.list-group-item-success:hover, +a.list-group-item-success:focus { + color: #3c763d; + background-color: #d0e9c6; +} +a.list-group-item-success.active, +a.list-group-item-success.active:hover, +a.list-group-item-success.active:focus { + color: #fff; + background-color: #3c763d; + border-color: #3c763d; +} +.list-group-item-info { + color: #31708f; + background-color: #d9edf7; +} +a.list-group-item-info { + color: #31708f; +} +a.list-group-item-info .list-group-item-heading { + color: inherit; +} +a.list-group-item-info:hover, +a.list-group-item-info:focus { + color: #31708f; + background-color: #c4e3f3; +} +a.list-group-item-info.active, +a.list-group-item-info.active:hover, +a.list-group-item-info.active:focus { + color: #fff; + background-color: #31708f; + border-color: #31708f; +} +.list-group-item-warning { + color: #8a6d3b; + background-color: #fcf8e3; +} +a.list-group-item-warning { + color: #8a6d3b; +} +a.list-group-item-warning .list-group-item-heading { + color: inherit; +} +a.list-group-item-warning:hover, +a.list-group-item-warning:focus { + color: #8a6d3b; + background-color: #faf2cc; +} +a.list-group-item-warning.active, +a.list-group-item-warning.active:hover, +a.list-group-item-warning.active:focus { + color: #fff; + background-color: #8a6d3b; + border-color: #8a6d3b; +} +.list-group-item-danger { + color: #a94442; + background-color: #f2dede; +} +a.list-group-item-danger { + color: #a94442; +} +a.list-group-item-danger .list-group-item-heading { + color: inherit; +} +a.list-group-item-danger:hover, +a.list-group-item-danger:focus { + color: #a94442; + background-color: #ebcccc; +} +a.list-group-item-danger.active, +a.list-group-item-danger.active:hover, +a.list-group-item-danger.active:focus { + color: #fff; + background-color: #a94442; + border-color: #a94442; +} +.list-group-item-heading { + margin-top: 0; + margin-bottom: 5px; +} +.list-group-item-text { + margin-bottom: 0; + line-height: 1.3; +} +.panel { + margin-bottom: 20px; + background-color: #fff; + border: 1px solid transparent; + border-radius: 4px; + -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, .05); + box-shadow: 0 1px 1px rgba(0, 0, 0, .05); +} +.panel-body { + padding: 15px; +} +.panel-heading { + padding: 10px 15px; + border-bottom: 1px solid transparent; + border-top-left-radius: 3px; + border-top-right-radius: 3px; +} +.panel-heading > .dropdown .dropdown-toggle { + color: inherit; +} +.panel-title { + margin-top: 0; + margin-bottom: 0; + font-size: 16px; + color: inherit; +} +.panel-title > a, +.panel-title > small, +.panel-title > .small, +.panel-title > small > a, +.panel-title > .small > a { + color: inherit; +} +.panel-footer { + padding: 10px 15px; + background-color: #f5f5f5; + border-top: 1px solid #ddd; + border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px; +} +.panel > .list-group, +.panel > .panel-collapse > .list-group { + margin-bottom: 0; +} +.panel > .list-group .list-group-item, +.panel > .panel-collapse > .list-group .list-group-item { + border-width: 1px 0; + border-radius: 0; +} +.panel > .list-group:first-child .list-group-item:first-child, +.panel > .panel-collapse > .list-group:first-child .list-group-item:first-child { + border-top: 0; + border-top-left-radius: 3px; + border-top-right-radius: 3px; +} +.panel > .list-group:last-child .list-group-item:last-child, +.panel > .panel-collapse > .list-group:last-child .list-group-item:last-child { + border-bottom: 0; + border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px; +} +.panel-heading + .list-group .list-group-item:first-child { + border-top-width: 0; +} +.list-group + .panel-footer { + border-top-width: 0; +} +.panel > .table, +.panel > .table-responsive > .table, +.panel > .panel-collapse > .table { + margin-bottom: 0; +} +.panel > .table caption, +.panel > .table-responsive > .table caption, +.panel > .panel-collapse > .table caption { + padding-right: 15px; + padding-left: 15px; +} +.panel > .table:first-child, +.panel > .table-responsive:first-child > .table:first-child { + border-top-left-radius: 3px; + border-top-right-radius: 3px; +} +.panel > .table:first-child > thead:first-child > tr:first-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child, +.panel > .table:first-child > tbody:first-child > tr:first-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child { + border-top-left-radius: 3px; + border-top-right-radius: 3px; +} +.panel > .table:first-child > thead:first-child > tr:first-child td:first-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:first-child, +.panel > .table:first-child > tbody:first-child > tr:first-child td:first-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:first-child, +.panel > .table:first-child > thead:first-child > tr:first-child th:first-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:first-child, +.panel > .table:first-child > tbody:first-child > tr:first-child th:first-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:first-child { + border-top-left-radius: 3px; +} +.panel > .table:first-child > thead:first-child > tr:first-child td:last-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:last-child, +.panel > .table:first-child > tbody:first-child > tr:first-child td:last-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:last-child, +.panel > .table:first-child > thead:first-child > tr:first-child th:last-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:last-child, +.panel > .table:first-child > tbody:first-child > tr:first-child th:last-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:last-child { + border-top-right-radius: 3px; +} +.panel > .table:last-child, +.panel > .table-responsive:last-child > .table:last-child { + border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px; +} +.panel > .table:last-child > tbody:last-child > tr:last-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child { + border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px; +} +.panel > .table:last-child > tbody:last-child > tr:last-child td:first-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:first-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child td:first-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:first-child, +.panel > .table:last-child > tbody:last-child > tr:last-child th:first-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:first-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child th:first-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:first-child { + border-bottom-left-radius: 3px; +} +.panel > .table:last-child > tbody:last-child > tr:last-child td:last-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:last-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child td:last-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:last-child, +.panel > .table:last-child > tbody:last-child > tr:last-child th:last-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:last-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child th:last-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:last-child { + border-bottom-right-radius: 3px; +} +.panel > .panel-body + .table, +.panel > .panel-body + .table-responsive, +.panel > .table + .panel-body, +.panel > .table-responsive + .panel-body { + border-top: 1px solid #ddd; +} +.panel > .table > tbody:first-child > tr:first-child th, +.panel > .table > tbody:first-child > tr:first-child td { + border-top: 0; +} +.panel > .table-bordered, +.panel > .table-responsive > .table-bordered { + border: 0; +} +.panel > .table-bordered > thead > tr > th:first-child, +.panel > .table-responsive > .table-bordered > thead > tr > th:first-child, +.panel > .table-bordered > tbody > tr > th:first-child, +.panel > .table-responsive > .table-bordered > tbody > tr > th:first-child, +.panel > .table-bordered > tfoot > tr > th:first-child, +.panel > .table-responsive > .table-bordered > tfoot > tr > th:first-child, +.panel > .table-bordered > thead > tr > td:first-child, +.panel > .table-responsive > .table-bordered > thead > tr > td:first-child, +.panel > .table-bordered > tbody > tr > td:first-child, +.panel > .table-responsive > .table-bordered > tbody > tr > td:first-child, +.panel > .table-bordered > tfoot > tr > td:first-child, +.panel > .table-responsive > .table-bordered > tfoot > tr > td:first-child { + border-left: 0; +} +.panel > .table-bordered > thead > tr > th:last-child, +.panel > .table-responsive > .table-bordered > thead > tr > th:last-child, +.panel > .table-bordered > tbody > tr > th:last-child, +.panel > .table-responsive > .table-bordered > tbody > tr > th:last-child, +.panel > .table-bordered > tfoot > tr > th:last-child, +.panel > .table-responsive > .table-bordered > tfoot > tr > th:last-child, +.panel > .table-bordered > thead > tr > td:last-child, +.panel > .table-responsive > .table-bordered > thead > tr > td:last-child, +.panel > .table-bordered > tbody > tr > td:last-child, +.panel > .table-responsive > .table-bordered > tbody > tr > td:last-child, +.panel > .table-bordered > tfoot > tr > td:last-child, +.panel > .table-responsive > .table-bordered > tfoot > tr > td:last-child { + border-right: 0; +} +.panel > .table-bordered > thead > tr:first-child > td, +.panel > .table-responsive > .table-bordered > thead > tr:first-child > td, +.panel > .table-bordered > tbody > tr:first-child > td, +.panel > .table-responsive > .table-bordered > tbody > tr:first-child > td, +.panel > .table-bordered > thead > tr:first-child > th, +.panel > .table-responsive > .table-bordered > thead > tr:first-child > th, +.panel > .table-bordered > tbody > tr:first-child > th, +.panel > .table-responsive > .table-bordered > tbody > tr:first-child > th { + border-bottom: 0; +} +.panel > .table-bordered > tbody > tr:last-child > td, +.panel > .table-responsive > .table-bordered > tbody > tr:last-child > td, +.panel > .table-bordered > tfoot > tr:last-child > td, +.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > td, +.panel > .table-bordered > tbody > tr:last-child > th, +.panel > .table-responsive > .table-bordered > tbody > tr:last-child > th, +.panel > .table-bordered > tfoot > tr:last-child > th, +.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > th { + border-bottom: 0; +} +.panel > .table-responsive { + margin-bottom: 0; + border: 0; +} +.panel-group { + margin-bottom: 20px; +} +.panel-group .panel { + margin-bottom: 0; + border-radius: 4px; +} +.panel-group .panel + .panel { + margin-top: 5px; +} +.panel-group .panel-heading { + border-bottom: 0; +} +.panel-group .panel-heading + .panel-collapse > .panel-body, +.panel-group .panel-heading + .panel-collapse > .list-group { + border-top: 1px solid #ddd; +} +.panel-group .panel-footer { + border-top: 0; +} +.panel-group .panel-footer + .panel-collapse .panel-body { + border-bottom: 1px solid #ddd; +} +.panel-default { + border-color: #ddd; +} +.panel-default > .panel-heading { + color: #333; + background-color: #f5f5f5; + border-color: #ddd; +} +.panel-default > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #ddd; +} +.panel-default > .panel-heading .badge { + color: #f5f5f5; + background-color: #333; +} +.panel-default > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #ddd; +} +.panel-primary { + border-color: #337ab7; +} +.panel-primary > .panel-heading { + color: #fff; + background-color: #337ab7; + border-color: #337ab7; +} +.panel-primary > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #337ab7; +} +.panel-primary > .panel-heading .badge { + color: #337ab7; + background-color: #fff; +} +.panel-primary > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #337ab7; +} +.panel-success { + border-color: #d6e9c6; +} +.panel-success > .panel-heading { + color: #3c763d; + background-color: #dff0d8; + border-color: #d6e9c6; +} +.panel-success > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #d6e9c6; +} +.panel-success > .panel-heading .badge { + color: #dff0d8; + background-color: #3c763d; +} +.panel-success > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #d6e9c6; +} +.panel-info { + border-color: #bce8f1; +} +.panel-info > .panel-heading { + color: #31708f; + background-color: #d9edf7; + border-color: #bce8f1; +} +.panel-info > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #bce8f1; +} +.panel-info > .panel-heading .badge { + color: #d9edf7; + background-color: #31708f; +} +.panel-info > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #bce8f1; +} +.panel-warning { + border-color: #faebcc; +} +.panel-warning > .panel-heading { + color: #8a6d3b; + background-color: #fcf8e3; + border-color: #faebcc; +} +.panel-warning > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #faebcc; +} +.panel-warning > .panel-heading .badge { + color: #fcf8e3; + background-color: #8a6d3b; +} +.panel-warning > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #faebcc; +} +.panel-danger { + border-color: #ebccd1; +} +.panel-danger > .panel-heading { + color: #a94442; + background-color: #f2dede; + border-color: #ebccd1; +} +.panel-danger > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #ebccd1; +} +.panel-danger > .panel-heading .badge { + color: #f2dede; + background-color: #a94442; +} +.panel-danger > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #ebccd1; +} +.embed-responsive { + position: relative; + display: block; + height: 0; + padding: 0; + overflow: hidden; +} +.embed-responsive .embed-responsive-item, +.embed-responsive iframe, +.embed-responsive embed, +.embed-responsive object, +.embed-responsive video { + position: absolute; + top: 0; + bottom: 0; + left: 0; + width: 100%; + height: 100%; + border: 0; +} +.embed-responsive-16by9 { + padding-bottom: 56.25%; +} +.embed-responsive-4by3 { + padding-bottom: 75%; +} +.well { + min-height: 20px; + padding: 19px; + margin-bottom: 20px; + background-color: #f5f5f5; + border: 1px solid #e3e3e3; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .05); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .05); +} +.well blockquote { + border-color: #ddd; + border-color: rgba(0, 0, 0, .15); +} +.well-lg { + padding: 24px; + border-radius: 6px; +} +.well-sm { + padding: 9px; + border-radius: 3px; +} +.close { + float: right; + font-size: 21px; + font-weight: bold; + line-height: 1; + color: #000; + text-shadow: 0 1px 0 #fff; + filter: alpha(opacity=20); + opacity: .2; +} +.close:hover, +.close:focus { + color: #000; + text-decoration: none; + cursor: pointer; + filter: alpha(opacity=50); + opacity: .5; +} +button.close { + -webkit-appearance: none; + padding: 0; + cursor: pointer; + background: transparent; + border: 0; +} +.modal-open { + overflow: hidden; +} +.modal { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 1050; + display: none; + overflow: hidden; + -webkit-overflow-scrolling: touch; + outline: 0; +} +.modal.fade .modal-dialog { + -webkit-transition: -webkit-transform .3s ease-out; + -o-transition: -o-transform .3s ease-out; + transition: transform .3s ease-out; + -webkit-transform: translate(0, -25%); + -ms-transform: translate(0, -25%); + -o-transform: translate(0, -25%); + transform: translate(0, -25%); +} +.modal.in .modal-dialog { + -webkit-transform: translate(0, 0); + -ms-transform: translate(0, 0); + -o-transform: translate(0, 0); + transform: translate(0, 0); +} +.modal-open .modal { + overflow-x: hidden; + overflow-y: auto; +} +.modal-dialog { + position: relative; + width: auto; + margin: 10px; +} +.modal-content { + position: relative; + background-color: #fff; + -webkit-background-clip: padding-box; + background-clip: padding-box; + border: 1px solid #999; + border: 1px solid rgba(0, 0, 0, .2); + border-radius: 6px; + outline: 0; + -webkit-box-shadow: 0 3px 9px rgba(0, 0, 0, .5); + box-shadow: 0 3px 9px rgba(0, 0, 0, .5); +} +.modal-backdrop { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 1040; + background-color: #000; +} +.modal-backdrop.fade { + filter: alpha(opacity=0); + opacity: 0; +} +.modal-backdrop.in { + filter: alpha(opacity=50); + opacity: .5; +} +.modal-header { + min-height: 16.42857143px; + padding: 15px; + border-bottom: 1px solid #e5e5e5; +} +.modal-header .close { + margin-top: -2px; +} +.modal-title { + margin: 0; + line-height: 1.42857143; +} +.modal-body { + position: relative; + padding: 15px; +} +.modal-footer { + padding: 15px; + text-align: right; + border-top: 1px solid #e5e5e5; +} +.modal-footer .btn + .btn { + margin-bottom: 0; + margin-left: 5px; +} +.modal-footer .btn-group .btn + .btn { + margin-left: -1px; +} +.modal-footer .btn-block + .btn-block { + margin-left: 0; +} +.modal-scrollbar-measure { + position: absolute; + top: -9999px; + width: 50px; + height: 50px; + overflow: scroll; +} +@media (min-width: 768px) { + .modal-dialog { + width: 600px; + margin: 30px auto; + } + .modal-content { + -webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, .5); + box-shadow: 0 5px 15px rgba(0, 0, 0, .5); + } + .modal-sm { + width: 300px; + } +} +@media (min-width: 992px) { + .modal-lg { + width: 900px; + } +} +.tooltip { + position: absolute; + z-index: 1070; + display: block; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 12px; + font-weight: normal; + line-height: 1.4; + filter: alpha(opacity=0); + opacity: 0; +} +.tooltip.in { + filter: alpha(opacity=90); + opacity: .9; +} +.tooltip.top { + padding: 5px 0; + margin-top: -3px; +} +.tooltip.right { + padding: 0 5px; + margin-left: 3px; +} +.tooltip.bottom { + padding: 5px 0; + margin-top: 3px; +} +.tooltip.left { + padding: 0 5px; + margin-left: -3px; +} +.tooltip-inner { + max-width: 200px; + padding: 3px 8px; + color: #fff; + text-align: center; + text-decoration: none; + background-color: #000; + border-radius: 4px; +} +.tooltip-arrow { + position: absolute; + width: 0; + height: 0; + border-color: transparent; + border-style: solid; +} +.tooltip.top .tooltip-arrow { + bottom: 0; + left: 50%; + margin-left: -5px; + border-width: 5px 5px 0; + border-top-color: #000; +} +.tooltip.top-left .tooltip-arrow { + right: 5px; + bottom: 0; + margin-bottom: -5px; + border-width: 5px 5px 0; + border-top-color: #000; +} +.tooltip.top-right .tooltip-arrow { + bottom: 0; + left: 5px; + margin-bottom: -5px; + border-width: 5px 5px 0; + border-top-color: #000; +} +.tooltip.right .tooltip-arrow { + top: 50%; + left: 0; + margin-top: -5px; + border-width: 5px 5px 5px 0; + border-right-color: #000; +} +.tooltip.left .tooltip-arrow { + top: 50%; + right: 0; + margin-top: -5px; + border-width: 5px 0 5px 5px; + border-left-color: #000; +} +.tooltip.bottom .tooltip-arrow { + top: 0; + left: 50%; + margin-left: -5px; + border-width: 0 5px 5px; + border-bottom-color: #000; +} +.tooltip.bottom-left .tooltip-arrow { + top: 0; + right: 5px; + margin-top: -5px; + border-width: 0 5px 5px; + border-bottom-color: #000; +} +.tooltip.bottom-right .tooltip-arrow { + top: 0; + left: 5px; + margin-top: -5px; + border-width: 0 5px 5px; + border-bottom-color: #000; +} +.popover { + position: absolute; + top: 0; + left: 0; + z-index: 1060; + display: none; + max-width: 276px; + padding: 1px; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 14px; + font-weight: normal; + line-height: 1.42857143; + text-align: left; + white-space: normal; + background-color: #fff; + -webkit-background-clip: padding-box; + background-clip: padding-box; + border: 1px solid #ccc; + border: 1px solid rgba(0, 0, 0, .2); + border-radius: 6px; + -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, .2); + box-shadow: 0 5px 10px rgba(0, 0, 0, .2); +} +.popover.top { + margin-top: -10px; +} +.popover.right { + margin-left: 10px; +} +.popover.bottom { + margin-top: 10px; +} +.popover.left { + margin-left: -10px; +} +.popover-title { + padding: 8px 14px; + margin: 0; + font-size: 14px; + background-color: #f7f7f7; + border-bottom: 1px solid #ebebeb; + border-radius: 5px 5px 0 0; +} +.popover-content { + padding: 9px 14px; +} +.popover > .arrow, +.popover > .arrow:after { + position: absolute; + display: block; + width: 0; + height: 0; + border-color: transparent; + border-style: solid; +} +.popover > .arrow { + border-width: 11px; +} +.popover > .arrow:after { + content: ""; + border-width: 10px; +} +.popover.top > .arrow { + bottom: -11px; + left: 50%; + margin-left: -11px; + border-top-color: #999; + border-top-color: rgba(0, 0, 0, .25); + border-bottom-width: 0; +} +.popover.top > .arrow:after { + bottom: 1px; + margin-left: -10px; + content: " "; + border-top-color: #fff; + border-bottom-width: 0; +} +.popover.right > .arrow { + top: 50%; + left: -11px; + margin-top: -11px; + border-right-color: #999; + border-right-color: rgba(0, 0, 0, .25); + border-left-width: 0; +} +.popover.right > .arrow:after { + bottom: -10px; + left: 1px; + content: " "; + border-right-color: #fff; + border-left-width: 0; +} +.popover.bottom > .arrow { + top: -11px; + left: 50%; + margin-left: -11px; + border-top-width: 0; + border-bottom-color: #999; + border-bottom-color: rgba(0, 0, 0, .25); +} +.popover.bottom > .arrow:after { + top: 1px; + margin-left: -10px; + content: " "; + border-top-width: 0; + border-bottom-color: #fff; +} +.popover.left > .arrow { + top: 50%; + right: -11px; + margin-top: -11px; + border-right-width: 0; + border-left-color: #999; + border-left-color: rgba(0, 0, 0, .25); +} +.popover.left > .arrow:after { + right: 1px; + bottom: -10px; + content: " "; + border-right-width: 0; + border-left-color: #fff; +} +.carousel { + position: relative; +} +.carousel-inner { + position: relative; + width: 100%; + overflow: hidden; +} +.carousel-inner > .item { + position: relative; + display: none; + -webkit-transition: .6s ease-in-out left; + -o-transition: .6s ease-in-out left; + transition: .6s ease-in-out left; +} +.carousel-inner > .item > img, +.carousel-inner > .item > a > img { + line-height: 1; +} +@media all and (transform-3d), (-webkit-transform-3d) { + .carousel-inner > .item { + -webkit-transition: -webkit-transform .6s ease-in-out; + -o-transition: -o-transform .6s ease-in-out; + transition: transform .6s ease-in-out; + + -webkit-backface-visibility: hidden; + backface-visibility: hidden; + -webkit-perspective: 1000; + perspective: 1000; + } + .carousel-inner > .item.next, + .carousel-inner > .item.active.right { + left: 0; + -webkit-transform: translate3d(100%, 0, 0); + transform: translate3d(100%, 0, 0); + } + .carousel-inner > .item.prev, + .carousel-inner > .item.active.left { + left: 0; + -webkit-transform: translate3d(-100%, 0, 0); + transform: translate3d(-100%, 0, 0); + } + .carousel-inner > .item.next.left, + .carousel-inner > .item.prev.right, + .carousel-inner > .item.active { + left: 0; + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } +} +.carousel-inner > .active, +.carousel-inner > .next, +.carousel-inner > .prev { + display: block; +} +.carousel-inner > .active { + left: 0; +} +.carousel-inner > .next, +.carousel-inner > .prev { + position: absolute; + top: 0; + width: 100%; +} +.carousel-inner > .next { + left: 100%; +} +.carousel-inner > .prev { + left: -100%; +} +.carousel-inner > .next.left, +.carousel-inner > .prev.right { + left: 0; +} +.carousel-inner > .active.left { + left: -100%; +} +.carousel-inner > .active.right { + left: 100%; +} +.carousel-control { + position: absolute; + top: 0; + bottom: 0; + left: 0; + width: 15%; + font-size: 20px; + color: #fff; + text-align: center; + text-shadow: 0 1px 2px rgba(0, 0, 0, .6); + filter: alpha(opacity=50); + opacity: .5; +} +.carousel-control.left { + background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, .5) 0%, rgba(0, 0, 0, .0001) 100%); + background-image: -o-linear-gradient(left, rgba(0, 0, 0, .5) 0%, rgba(0, 0, 0, .0001) 100%); + background-image: -webkit-gradient(linear, left top, right top, from(rgba(0, 0, 0, .5)), to(rgba(0, 0, 0, .0001))); + background-image: linear-gradient(to right, rgba(0, 0, 0, .5) 0%, rgba(0, 0, 0, .0001) 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1); + background-repeat: repeat-x; +} +.carousel-control.right { + right: 0; + left: auto; + background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, .0001) 0%, rgba(0, 0, 0, .5) 100%); + background-image: -o-linear-gradient(left, rgba(0, 0, 0, .0001) 0%, rgba(0, 0, 0, .5) 100%); + background-image: -webkit-gradient(linear, left top, right top, from(rgba(0, 0, 0, .0001)), to(rgba(0, 0, 0, .5))); + background-image: linear-gradient(to right, rgba(0, 0, 0, .0001) 0%, rgba(0, 0, 0, .5) 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1); + background-repeat: repeat-x; +} +.carousel-control:hover, +.carousel-control:focus { + color: #fff; + text-decoration: none; + filter: alpha(opacity=90); + outline: 0; + opacity: .9; +} +.carousel-control .icon-prev, +.carousel-control .icon-next, +.carousel-control .glyphicon-chevron-left, +.carousel-control .glyphicon-chevron-right { + position: absolute; + top: 50%; + z-index: 5; + display: inline-block; +} +.carousel-control .icon-prev, +.carousel-control .glyphicon-chevron-left { + left: 50%; + margin-left: -10px; +} +.carousel-control .icon-next, +.carousel-control .glyphicon-chevron-right { + right: 50%; + margin-right: -10px; +} +.carousel-control .icon-prev, +.carousel-control .icon-next { + width: 20px; + height: 20px; + margin-top: -10px; + font-family: serif; + line-height: 1; +} +.carousel-control .icon-prev:before { + content: '\2039'; +} +.carousel-control .icon-next:before { + content: '\203a'; +} +.carousel-indicators { + position: absolute; + bottom: 10px; + left: 50%; + z-index: 15; + width: 60%; + padding-left: 0; + margin-left: -30%; + text-align: center; + list-style: none; +} +.carousel-indicators li { + display: inline-block; + width: 10px; + height: 10px; + margin: 1px; + text-indent: -999px; + cursor: pointer; + background-color: #000 \9; + background-color: rgba(0, 0, 0, 0); + border: 1px solid #fff; + border-radius: 10px; +} +.carousel-indicators .active { + width: 12px; + height: 12px; + margin: 0; + background-color: #fff; +} +.carousel-caption { + position: absolute; + right: 15%; + bottom: 20px; + left: 15%; + z-index: 10; + padding-top: 20px; + padding-bottom: 20px; + color: #fff; + text-align: center; + text-shadow: 0 1px 2px rgba(0, 0, 0, .6); +} +.carousel-caption .btn { + text-shadow: none; +} +@media screen and (min-width: 768px) { + .carousel-control .glyphicon-chevron-left, + .carousel-control .glyphicon-chevron-right, + .carousel-control .icon-prev, + .carousel-control .icon-next { + width: 30px; + height: 30px; + margin-top: -15px; + font-size: 30px; + } + .carousel-control .glyphicon-chevron-left, + .carousel-control .icon-prev { + margin-left: -15px; + } + .carousel-control .glyphicon-chevron-right, + .carousel-control .icon-next { + margin-right: -15px; + } + .carousel-caption { + right: 20%; + left: 20%; + padding-bottom: 30px; + } + .carousel-indicators { + bottom: 20px; + } +} +.clearfix:before, +.clearfix:after, +.dl-horizontal dd:before, +.dl-horizontal dd:after, +.container:before, +.container:after, +.container-fluid:before, +.container-fluid:after, +.row:before, +.row:after, +.form-horizontal .form-group:before, +.form-horizontal .form-group:after, +.btn-toolbar:before, +.btn-toolbar:after, +.btn-group-vertical > .btn-group:before, +.btn-group-vertical > .btn-group:after, +.nav:before, +.nav:after, +.navbar:before, +.navbar:after, +.navbar-header:before, +.navbar-header:after, +.navbar-collapse:before, +.navbar-collapse:after, +.pager:before, +.pager:after, +.panel-body:before, +.panel-body:after, +.modal-footer:before, +.modal-footer:after { + display: table; + content: " "; +} +.clearfix:after, +.dl-horizontal dd:after, +.container:after, +.container-fluid:after, +.row:after, +.form-horizontal .form-group:after, +.btn-toolbar:after, +.btn-group-vertical > .btn-group:after, +.nav:after, +.navbar:after, +.navbar-header:after, +.navbar-collapse:after, +.pager:after, +.panel-body:after, +.modal-footer:after { + clear: both; +} +.center-block { + display: block; + margin-right: auto; + margin-left: auto; +} +.pull-right { + float: right !important; +} +.pull-left { + float: left !important; +} +.hide { + display: none !important; +} +.show { + display: block !important; +} +.invisible { + visibility: hidden; +} +.text-hide { + font: 0/0 a; + color: transparent; + text-shadow: none; + background-color: transparent; + border: 0; +} +.hidden { + display: none !important; +} +.affix { + position: fixed; +} +@-ms-viewport { + width: device-width; +} +.visible-xs, +.visible-sm, +.visible-md, +.visible-lg { + display: none !important; +} +.visible-xs-block, +.visible-xs-inline, +.visible-xs-inline-block, +.visible-sm-block, +.visible-sm-inline, +.visible-sm-inline-block, +.visible-md-block, +.visible-md-inline, +.visible-md-inline-block, +.visible-lg-block, +.visible-lg-inline, +.visible-lg-inline-block { + display: none !important; +} +@media (max-width: 767px) { + .visible-xs { + display: block !important; + } + table.visible-xs { + display: table; + } + tr.visible-xs { + display: table-row !important; + } + th.visible-xs, + td.visible-xs { + display: table-cell !important; + } +} +@media (max-width: 767px) { + .visible-xs-block { + display: block !important; + } +} +@media (max-width: 767px) { + .visible-xs-inline { + display: inline !important; + } +} +@media (max-width: 767px) { + .visible-xs-inline-block { + display: inline-block !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .visible-sm { + display: block !important; + } + table.visible-sm { + display: table; + } + tr.visible-sm { + display: table-row !important; + } + th.visible-sm, + td.visible-sm { + display: table-cell !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .visible-sm-block { + display: block !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .visible-sm-inline { + display: inline !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .visible-sm-inline-block { + display: inline-block !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .visible-md { + display: block !important; + } + table.visible-md { + display: table; + } + tr.visible-md { + display: table-row !important; + } + th.visible-md, + td.visible-md { + display: table-cell !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .visible-md-block { + display: block !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .visible-md-inline { + display: inline !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .visible-md-inline-block { + display: inline-block !important; + } +} +@media (min-width: 1200px) { + .visible-lg { + display: block !important; + } + table.visible-lg { + display: table; + } + tr.visible-lg { + display: table-row !important; + } + th.visible-lg, + td.visible-lg { + display: table-cell !important; + } +} +@media (min-width: 1200px) { + .visible-lg-block { + display: block !important; + } +} +@media (min-width: 1200px) { + .visible-lg-inline { + display: inline !important; + } +} +@media (min-width: 1200px) { + .visible-lg-inline-block { + display: inline-block !important; + } +} +@media (max-width: 767px) { + .hidden-xs { + display: none !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .hidden-sm { + display: none !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .hidden-md { + display: none !important; + } +} +@media (min-width: 1200px) { + .hidden-lg { + display: none !important; + } +} +.visible-print { + display: none !important; +} +@media print { + .visible-print { + display: block !important; + } + table.visible-print { + display: table; + } + tr.visible-print { + display: table-row !important; + } + th.visible-print, + td.visible-print { + display: table-cell !important; + } +} +.visible-print-block { + display: none !important; +} +@media print { + .visible-print-block { + display: block !important; + } +} +.visible-print-inline { + display: none !important; +} +@media print { + .visible-print-inline { + display: inline !important; + } +} +.visible-print-inline-block { + display: none !important; +} +@media print { + .visible-print-inline-block { + display: inline-block !important; + } +} +@media print { + .hidden-print { + display: none !important; + } +} +/*# sourceMappingURL=bootstrap.css.map */ diff --git "a/web/112 \350\214\266\345\217\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/css/css.css" "b/web/112 \350\214\266\345\217\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/css/css.css" new file mode 100644 index 00000000..cbfc4c38 --- /dev/null +++ "b/web/112 \350\214\266\345\217\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/css/css.css" @@ -0,0 +1,150 @@ +@charset 'UTF-8'; + +/* 公共样式*/ + +html, +body, +ul, +li, +ol, +dl, +dd, +dt, +p, +h1, +h2, +h3, +h4, +h5, +h6, +form, +fieldset, +legend, +img { + margin: 0; + padding: 0; +} + +body { + color: #000; + font: 0.15rem/0.25rem "Microsoft YaHei", "微软雅黑", "Arial Narrow", HELVETICA; + background: #fff +} + +fieldset, +img { + border: 0; +} + +img { + display: block; +} + +address, +caption, +cite, +code, +dfn, +th, +var { + font-style: normal; + font-weight: normal; +} + +ul, +ol { + list-style: none; +} + +h1, +h2, +h3, +h4, +h5, +h6 { + font-weight: normal; +} + +input { + padding-top: 0; + padding-bottom: 0; + font-family: 'SimSun', '微软雅黑'; +} + +input::-moz-focus-inner { + border: 0; + padding: 0; +} + +select, +input { + vertical-align: middle; +} + +select, +input, +textarea { + margin: 0; + outline-style: none; +} + +input, +textarea { + outline-style: none; + /* -webkit-appearance: none; */ +} + +textarea { + resize: none; +} + +table { + border-collapse: collapse; +} + +.clearfix:after { + content: '.'; + display: block; + height: 0; + visibility: hidden; + clear: both; +} + +.clearfix { + zoom: 1; +} + +.clearit { + clear: both; + height: 0; + font-size: 0; + overflow: hidden; +} + +.fl { + float: left; + _display: inline; +} + +.fr { + float: right; + _display: inline; +} + +a { + text-decoration: none; +} + +a:hover, +a:active, +a:focus, +a:visited { + text-decoration: underline; + text-decoration: none; +} + + +/* 公共样式结束*/ +#non { + display: none; +} diff --git "a/web/112 \350\214\266\345\217\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/css/daterangepicker.css" "b/web/112 \350\214\266\345\217\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/css/daterangepicker.css" new file mode 100644 index 00000000..c222647d --- /dev/null +++ "b/web/112 \350\214\266\345\217\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/css/daterangepicker.css" @@ -0,0 +1,415 @@ +.daterangepicker { + position: absolute; + color: inherit; + background: #fff; + border-radius: 0.05rem; + width: 3.475rem; + padding: 0.05rem; + margin-top: 0.0125rem; + top: 1.25rem; + left: 0.25rem; + /* Calendars */ +} + +.daterangepicker:before, +.daterangepicker:after { + position: absolute; + display: inline-block; + border-bottom-color: rgba(0, 0, 0, 0.2); + content: ''; +} + +.daterangepicker:before { + top: -0.0875rem; + border-right: 0.0875rem solid transparent; + border-left: 0.0875rem solid transparent; + border-bottom: 0.0875rem solid #ccc; +} + +.daterangepicker:after { + top: -0.075rem; + border-right: 0.075rem solid transparent; + border-bottom: 0.075rem solid #fff; + border-left: 0.075rem solid transparent; +} + +.daterangepicker.opensleft:before { + right: 0.1125rem; +} + +.daterangepicker.opensleft:after { + right: 0.125rem; +} + +.daterangepicker.openscenter:before { + left: 0; + right: 0; + width: 0; + margin-left: auto; + margin-right: auto; +} + +.daterangepicker.openscenter:after { + left: 0; + right: 0; + width: 0; + margin-left: auto; + margin-right: auto; +} + +.daterangepicker.opensright:before { + left: 0.1125rem; +} + +.daterangepicker.opensright:after { + left: 0.125rem; +} + +.daterangepicker.dropup { + margin-top: -0.0625rem; +} + +.daterangepicker.dropup:before { + top: initial; + bottom: -0.0875rem; + border-bottom: initial; + border-top: 0.0875rem solid #ccc; +} + +.daterangepicker.dropup:after { + top: initial; + bottom: -0.075rem; + border-bottom: initial; + border-top: 0.075rem solid #fff; +} + +.daterangepicker.dropdown-menu { + max-width: none; + z-index: 3001; +} + +.daterangepicker.single .ranges, +.daterangepicker.single .calendar { + float: none; +} + +.daterangepicker.show-calendar .calendar { + display: block; +} + +.daterangepicker .calendar { + display: none; + max-width: 3.375rem; + margin: 0.05rem; +} + +.daterangepicker .calendar.single .calendar-table { + border: none; +} + +.daterangepicker .calendar th, +.daterangepicker .calendar td { + white-space: nowrap; + text-align: center; + min-width: 0.4rem; +} + +.daterangepicker .calendar-table { + border: 0.0125rem solid #fff; + padding: 0.05rem; + border-radius: 0.05rem; + background: #fff; +} + +.daterangepicker table { + width: 100%; + margin: 0; +} + +.daterangepicker td, +.daterangepicker th { + text-align: center; + width: 0.25rem; + height: 0.25rem; + border-radius: 0.05rem; + border: 0.0125rem solid transparent; + white-space: nowrap; + cursor: pointer; +} + +.daterangepicker td.available:hover, +.daterangepicker th.available:hover { + background-color: #eee; + border-color: transparent; + color: inherit; +} + +.daterangepicker td.week, +.daterangepicker th.week { + font-size: 80%; + color: #ccc; +} + +.daterangepicker td.off, +.daterangepicker td.off.in-range, +.daterangepicker td.off.start-date, +.daterangepicker td.off.end-date { + background-color: #fff; + border-color: transparent; + color: #999; +} + +.daterangepicker td.in-range { + background-color: #ebf4f8; + border-color: transparent; + color: #000; + border-radius: 0; +} + +.daterangepicker td.start-date { + border-radius: 0.05rem 0 0 0.05rem; +} + +.daterangepicker td.end-date { + border-radius: 0 0.05rem 0.05rem 0; +} + +.daterangepicker td.start-date.end-date { + border-radius: 0.05rem; +} + +.daterangepicker td.active, +.daterangepicker td.active:hover { + background-color: #357ebd; + border-color: transparent; + color: #fff; +} + +.daterangepicker th.month { + width: auto; +} + +.daterangepicker td.disabled, +.daterangepicker option.disabled { + color: #999; + cursor: not-allowed; + text-decoration: line-through; +} + +.daterangepicker select.monthselect, +.daterangepicker select.yearselect { + font-size: 0.15rem; + padding: 0.0125rem; + height: auto; + margin: 0; + cursor: default; +} + +.daterangepicker select.monthselect { + margin-right: 2%; + width: 56%; +} + +.daterangepicker select.yearselect { + width: 40%; +} + +.daterangepicker select.hourselect, +.daterangepicker select.minuteselect, +.daterangepicker select.secondselect, +.daterangepicker select.ampmselect { + width: 0.625rem; + margin-bottom: 0; +} + +.daterangepicker .input-mini { + border: 0.0125rem solid #ccc; + border-radius: 0.05rem; + color: #555; + height: 0.375rem; + line-height: 0.375rem; + display: block; + vertical-align: middle; + margin: 0 0 0.0625rem 0; + padding: 0 0.075rem 0 0.35rem; + width: 100%; +} + +.daterangepicker .input-mini.active { + border: 0.0125rem solid #08c; + border-radius: 0.05rem; +} + +.daterangepicker .daterangepicker_input { + position: relative; +} + +.daterangepicker .daterangepicker_input i { + position: absolute; + left: 0.1rem; + top: 0.1rem; +} + +.daterangepicker.rtl .input-mini { + padding-right: 0.35rem; + padding-left: 0.075rem; +} + +.daterangepicker.rtl .daterangepicker_input i { + left: auto; + right: 0.1rem; +} + +.daterangepicker .calendar-time { + text-align: center; + margin: 0.0625rem auto; + line-height: 0.375rem; + position: relative; + padding-left: 0.35rem; +} + +.daterangepicker .calendar-time select.disabled { + color: #ccc; + cursor: not-allowed; +} + +.ranges { + font-size: 0.1375rem; + float: none; + margin: 0.05rem; + text-align: left; +} + +.ranges ul { + list-style: none; + margin: 0 auto; + padding: 0; + width: 100%; +} + +.ranges li { + font-size: 0.1625rem; + background: #f5f5f5; + border: 0.0125rem solid #f5f5f5; + border-radius: 0.05rem; + color: #08c; + padding: 0.0375rem 0.15rem; + margin-bottom: 0.1rem; + cursor: pointer; +} + +.ranges li:hover { + background: #08c; + border: 0.0125rem solid #08c; + color: #fff; +} + +.ranges li.active { + background: #08c; + border: 0.0125rem solid #08c; + color: #fff; +} + + +/* Larger Screen Styling */ + +@media (min-width: 7.05rem) { + .daterangepicker { + width: auto; + } + .daterangepicker .ranges ul { + width: 2rem; + } + .daterangepicker.single .ranges ul { + width: 100%; + } + .daterangepicker.single .calendar.left { + clear: none; + } + .daterangepicker.single.ltr .ranges, + .daterangepicker.single.ltr .calendar { + float: left; + } + .daterangepicker.single.rtl .ranges, + .daterangepicker.single.rtl .calendar { + float: right; + } + .daterangepicker.ltr { + direction: ltr; + text-align: left; + } + .daterangepicker.ltr .calendar.left { + clear: left; + margin-right: 0; + } + .daterangepicker.ltr .calendar.left .calendar-table { + border-right: none; + border-top-right-radius: 0; + border-bottom-right-radius: 0; + } + .daterangepicker.ltr .calendar.right { + margin-left: 0; + } + .daterangepicker.ltr .calendar.right .calendar-table { + border-left: none; + border-top-left-radius: 0; + border-bottom-left-radius: 0; + } + .daterangepicker.ltr .left .daterangepicker_input { + padding-right: 0.15rem; + } + .daterangepicker.ltr .calendar.left .calendar-table { + padding-right: 0.15rem; + } + .daterangepicker.ltr .ranges, + .daterangepicker.ltr .calendar { + float: left; + } + .daterangepicker.rtl { + direction: rtl; + text-align: right; + } + .daterangepicker.rtl .calendar.left { + clear: right; + margin-left: 0; + } + .daterangepicker.rtl .calendar.left .calendar-table { + border-left: none; + border-top-left-radius: 0; + border-bottom-left-radius: 0; + } + .daterangepicker.rtl .calendar.right { + margin-right: 0; + } + .daterangepicker.rtl .calendar.right .calendar-table { + border-right: none; + border-top-right-radius: 0; + border-bottom-right-radius: 0; + } + .daterangepicker.rtl .left .daterangepicker_input { + padding-left: 0.15rem; + } + .daterangepicker.rtl .calendar.left .calendar-table { + padding-left: 0.15rem; + } + .daterangepicker.rtl .ranges, + .daterangepicker.rtl .calendar { + text-align: right; + float: right; + } +} + +@media (min-width: 9.125rem) { + .daterangepicker .ranges { + width: auto; + } + .daterangepicker.ltr .ranges { + float: left; + } + .daterangepicker.rtl .ranges { + float: right; + } + .daterangepicker .calendar.left { + clear: none !important; + } +} \ No newline at end of file diff --git "a/web/112 \350\214\266\345\217\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/css/index.css" "b/web/112 \350\214\266\345\217\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/css/index.css" new file mode 100644 index 00000000..6f3d4bf8 --- /dev/null +++ "b/web/112 \350\214\266\345\217\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/css/index.css" @@ -0,0 +1,1039 @@ +.content { + width: 100%; + background: url(../images/bg_02.jpg) center no-repeat; + background-size: 100% 100%; + padding-top: 0.175rem; + padding-bottom: 0.55rem; + box-sizing: border-box; +} + +.content .header { + width: 100%; + height: 1.05rem; + padding: 0 0.375rem; + display: flex; + justify-content: space-between; + box-sizing: border-box; +} + +.content .header .header_l { + width: 5.625rem; +} + +.content .header .header_l ul { + width: 100%; + height: 1.05rem; + padding-top: 0.225rem; + display: flex; + box-sizing: border-box; +} + +.content .header .header_l ul li { + width: 1.475rem; + height: 0.6rem; + background: url(../images/header-2.png) center no-repeat; + background-size: 100% 100%; + margin-right: 0.25rem; +} + +.content .header .header_l ul li a { + width: 100%; + height: 100%; + display: flex; + align-items: center; + justify-content: center; +} + +.content .header .header_l ul li a img { + width: 0.25rem; + height: 0.25rem; + margin-right: 0.1375rem; +} + +.content .header .header_l ul li a span { + font-size: 0.25rem; + font-family: SourceHanSansCN; + font-weight: 400; + color: #9da4b6; + line-height: 0.4rem; +} + +.content .header .header_l ul .sel_li { + background: url(../images/header-4.png) center no-repeat; + background-size: 100% 100%; +} + +.content .header .header_l ul .sel_li a span { + color: #fff; +} + +.content .header .header_m { + width: 8.125rem; + height: 100%; +} + +.content .header .header_m h1 { + width: 100%; + font-size: 0.525rem; + font-family: SourceHanSansCN; + font-weight: 500; + color: #FFFFFF; + line-height: 1.05rem; + background: linear-gradient(0deg, #a7c0ff 0%, #f9faff 0%); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + text-align: center; +} + +.content .header .header_r { + width: 5.625rem; +} + +.content .header .header_r ul { + width: 100%; + height: 1.05rem; + padding-top: 0.225rem; + display: flex; + justify-content: flex-end; + box-sizing: border-box; +} + +.content .header .header_r ul li { + width: 1.475rem; + height: 0.6rem; + background: url(../images/header-2.png) center no-repeat; + background-size: 100% 100%; + margin-right: 0.25rem; +} + +.content .header .header_r ul li a { + width: 100%; + height: 100%; + display: flex; + align-items: center; + justify-content: center; +} + +.content .header .header_r ul li a img { + width: 0.25rem; + height: 0.25rem; + margin-right: 0.1375rem; +} + +.content .header .header_r ul li a span { + font-size: 0.25rem; + font-family: SourceHanSansCN; + font-weight: 400; + color: #9da4b6; + line-height: 0.4rem; +} + +.content .header .header_r ul li:last-child { + width: 1.3375rem; + box-sizing: border-box; + margin-right: 0; + padding-right: 0.025rem; + margin-left: 0.3rem; + background: none !important; +} + +.content .header .header_r ul li:last-child a { + justify-content: flex-end; +} + +.content .header .header_r ul li:last-child img { + margin-right: 0.125rem; +} + +.content .header .header_r ul li:last-child span { + font-size: 0.25rem; + font-family: SourceHanSansCN; + font-weight: 400; + color: #FFFFFF; + line-height: 0.4rem; +} + +.content .header .header_r ul .sel_li { + background: url(../images/header-4.png) center no-repeat; + background-size: 100% 100%; +} + +.content .main { + width: 100%; + padding: 0 0.375rem; + box-sizing: border-box; + padding-top: 0.4rem; + display: flex; + justify-content: space-between; + position: relative; +} + +.content .main .item { + width: 6.25rem; + height: 3.6375rem; + background: url(../images/mainl1-bg.png) center no-repeat; + background-size: 100% 100%; + margin-bottom: 0.1875rem; + padding-top: 0.075rem; + box-sizing: border-box; +} + +.content .main .title { + width: 100%; + display: flex; + align-items: center; + justify-content: space-between; +} + +.content .main .title h2 { + width: 1.9375rem; + font-size: 0.25rem; + font-family: SourceHanSansCN; + font-weight: 500; + color: #FFFFFF; + line-height: 0.6rem; + padding-left: 0.25rem; +} + +.content .main .title p { + width: 2.25rem; + height: 0.35rem; + background: rgba(75, 126, 254, 0.16); + border-radius: 0.175rem; + line-height: 0.35rem; + font-size: 0.175rem; + font-family: SourceHanSansCN; + font-weight: 400; + color: #FFFFFF; + margin-right: 0.15rem; + margin-left: 0.0875rem; +} + +.content .main .title p span { + display: inline-block; + width: 1.125rem; + height: 0.35rem; + border-radius: 0.175rem; + text-align: center; + cursor: pointer; +} + +.content .main .title p .span_c { + background-color: #4b7efe; +} + +.content .main .main_l { + width: 6.25rem; + z-index: 99; +} + +.content .main .main_l .mainl1 .title { + width: 100%; + display: flex; + align-items: center; +} + +.content .main .main_l .mainl1 .title h2 { + width: 1.9375rem; + font-size: 0.25rem; + font-family: SourceHanSansCN; + font-weight: 500; + color: #FFFFFF; + line-height: 0.6rem; + padding-left: 0.25rem; +} + +.content .main .main_l .mainl1 .title p { + width: 1.95rem; + height: 0.35rem; + background: rgba(75, 126, 254, 0.16); + border-radius: 0.175rem; + line-height: 0.35rem; + font-size: 0.175rem; + font-family: SourceHanSansCN; + font-weight: 400; + color: #FFFFFF; + margin-right: 0.3125rem; + margin-left: 0.0875rem; +} + +.content .main .main_l .mainl1 .title p span { + display: inline-block; + width: 0.65rem; + height: 0.35rem; + border-radius: 0.175rem; + text-align: center; +} + +.content .main .main_l .mainl1 .title p .span_c { + background-color: #4b7efe; +} + +.content .main .main_l .mainl1 .title button { + width: 1.4625rem; + height: 0.6rem; + background: url(../images/mainl-5.png) center no-repeat; + background-size: 100% 57%; + background-position: 0% 90%; + border: none; + cursor: pointer; + margin-right: 0.15rem; +} + +.content .main .main_l .mainl1 ul { + width: 100%; + padding: 0 0.625rem 0 0.15rem; + padding-top: 0.475rem; + box-sizing: border-box; + display: flex; + flex-wrap: wrap; + justify-content: space-between; +} + +.content .main .main_l .mainl1 ul li { + width: 2.5rem; + height: 0.8rem; + margin-bottom: 0.425rem; + padding-left: 0.9125rem; + padding-top: 0.1rem; + box-sizing: border-box; +} + +.content .main .main_l .mainl1 ul li span { + width: 0.525rem; + height: 0.175rem; + font-size: 0.175rem; + font-family: SourceHanSansCN; + font-weight: 400; + color: #a0a9c0; + line-height: 0.175rem; + white-space: nowrap; +} + +.content .main .main_l .mainl1 ul li p { + font-size: 0.175rem; + font-family: SourceHanSansCN; + font-weight: 500; + color: #4B7EFE; + line-height: 0.25rem; + margin-top: 0.0625rem; +} + +.content .main .main_l .mainl1 ul li p span { + font-size: 0.25rem; + font-family: SourceHanSansCN; + font-weight: 500; + color: #4B7EFE; + line-height: 0.25rem; +} + +.content .main .main_l .mainl1 ul li:nth-child(1) { + background: url(../images/mainl-4.png) center no-repeat; + background-size: 100% 100%; +} + +.content .main .main_l .mainl1 ul li:nth-child(2) { + background: url(../images/mainl-3.png) center no-repeat; + background-size: 100% 100%; +} + +.content .main .main_l .mainl1 ul li:nth-child(3) { + background: url(../images/mainl-2.png) center no-repeat; + background-size: 100% 100%; +} + +.content .main .main_l .mainl1 ul li:nth-child(4) { + background: url(../images/mainl-1.png) center no-repeat; + background-size: 100% 100%; +} + +.content .main .main_l .item { + background: rgba(12, 31, 86, 0.7); +} + +.content .main .main_l .item .con { + width: 100%; +} + +.content .main .main_l .item .con .con_t { + width: 100%; + padding-top: 0.1875rem; + display: flex; + justify-content: space-between; +} + +.content .main .main_l .item .con .con_t p { + padding-left: 0.2625rem; +} + +.content .main .main_l .item .con .con_t p span { + display: inline-block; + margin-right: 0.25rem; + font-size: 0.175rem; + font-family: SourceHanSansCN; + font-weight: 400; + color: #FFFFFF; + line-height: 0.25rem; + cursor: pointer; +} + +.content .main .main_l .item .con .con_t p span i { + display: inline-block; + width: 0.1rem; + height: 0.1rem; + border: 0.0125rem solid #244393; + border-radius: 50%; + margin-right: 0.1rem; +} + +.content .main .main_l .item .con .con_t p .span_c1 i { + background-color: #4b7efe; +} + +.content .main .main_l .item .con .con_t button { + width: 1.125rem; + height: 0.175rem; + background: url(../images/mainl-10.png) center no-repeat; + background-size: 100% 100%; + border: none; + margin-right: 0.125rem; + cursor: pointer; + margin-top: 0.0375rem; +} + +.content .main .main_l .item .con .con_m { + width: 100%; + margin-top: 0.0625rem; + margin-bottom: 0.1625rem; +} + +.content .main .main_l .item .con .con_m ul { + width: 100%; + display: flex; + justify-content: space-between; + padding: 0 0.175rem; + box-sizing: border-box; +} + +.content .main .main_l .item .con .con_m ul li { + width: 1.95rem; + padding-bottom: 0.3rem; + background: url(../images/mainl-12.png) no-repeat; + background-size: 100% 0.05rem; + background-position: 0% 93%; + cursor: pointer; +} + +.content .main .main_l .item .con .con_m ul li p { + width: 100%; + font-family: DINPro; + font-weight: 500; + color: #4B7EFE; + line-height: 0.4rem; + text-align: center; + font-size: 0.15rem; +} + +.content .main .main_l .item .con .con_m ul li p span { + font-size: 0.3rem; + line-height: 0.4rem; + font-weight: 500; + color: #4B7EFE; +} + +.content .main .main_l .item .con .con_m ul li h6 { + width: 100%; + text-align: center; + font-size: 0.175rem; + font-family: SourceHanSansCN; + font-weight: 400; + color: #6d7999; + line-height: 0.175rem; +} + +.content .main .main_l .item .con .con_m ul li:nth-child(2) p { + color: #00FFEA; +} + +.content .main .main_l .item .con .con_m ul li:nth-child(2) p span { + color: #00FFEA; +} + +.content .main .main_l .item .con .con_m ul li:nth-child(3) p { + color: #FEC31D; +} + +.content .main .main_l .item .con .con_m ul li:nth-child(3) p span { + color: #FEC31D; +} + +.content .main .main_l .item .con .con_m ul .li-sel1 { + background: url(../images/mainl-13.png) no-repeat; + background-size: 100% 0.1125rem; + background-position: 0% 100%; +} + +.content .main .main_l .item .con .con_m ul .li-sel1 h6 { + color: #fff; +} + +.content .main .main_l .item .con .con_f { + width: 100%; + height: 1.3125rem; +} + +.content .main .main_m { + width: 9.75rem; +} + +.content .main .main_m .main_m_t { + width: 100%; + margin-bottom: 0.3125rem; + display: flex; + justify-content: space-between; + position: relative; + z-index: 99; +} + +.content .main .main_m .main_m_t .item1 { + width: 2.25rem; + height: 2.5875rem; + background: url(../images/mainm-1.png) center no-repeat; + background-size: 100% 100%; + padding-top: 0.4875rem; + box-sizing: border-box; +} + +.content .main .main_m .main_m_t .item1 p { + width: 100%; + font-size: 0.175rem; + font-family: DINPro; + font-weight: 500; + color: #4B7EFE; + line-height: 0.3125rem; + text-align: center; + padding-top: 0.0875rem; + padding-bottom: 0.0375rem; + margin-bottom: 0.25rem; + box-sizing: border-box; +} + +.content .main .main_m .main_m_t .item1 p span { + display: inline-block; + font-size: 0.4rem; + font-family: SourceHanSansCN; + font-weight: 400; + color: #4B7EFE; + line-height: 0.3125rem; + margin-right: 0.075rem; +} + +.content .main .main_m .main_m_t .item1 p:nth-child(1) { + padding-right: 0.15rem; +} + +.content .main .main_m .main_m_t .item1 p:last-child { + padding: 0; + margin: 0; + margin-top: -0.125rem; + color: #adf3e6; +} + +.content .main .main_m .main_m_t .item1:nth-child(2) p { + color: #00FFEA; +} + +.content .main .main_m .main_m_t .item1:nth-child(2) p span { + color: #00FFEA; +} + +.content .main .main_m .main_m_t .item1:nth-child(2) p:last-child { + color: #adf3e6; +} + +.content .main .main_m .main_m_t .item1:nth-child(3) p { + color: #FEC31D; +} + +.content .main .main_m .main_m_t .item1:nth-child(3) p span { + color: #FEC31D; +} + +.content .main .main_m .main_m_t .item1:nth-child(3) p:last-child { + color: #adf3e6; +} + +.content .main .main_m .main_m_t .item1:nth-child(4) p { + color: #917CFF; +} + +.content .main .main_m .main_m_t .item1:nth-child(4) p span { + color: #917CFF; +} + +.content .main .main_m .main_m_t .item1:nth-child(4) p:last-child { + color: #adf3e6; +} + +.content .main .main_m .main_m_m { + width: 100%; + position: relative; + padding-top: 0.075rem; + z-index: 99; +} + +.content .main .main_m .main_m_m h2 { + width: 6.25rem; + height: 0.6875rem; + background: url(../images/mainm-2.png) center no-repeat; + background-size: 100% 100%; + position: absolute; + top: 0; + left: 0; + font-size: 0.25rem; + font-family: SourceHanSansCN; + font-weight: 400; + color: #FFFFFF; + line-height: 0.725rem; + padding-left: 0.3rem; + box-sizing: border-box; + z-index: 999; +} + +.content .main .main_m .main_m_m .con { + width: 100%; + height: 6.375rem; + background: url(../images/mainm-12.jpg) center no-repeat; + background-size: 100% 100%; +} + +.content .main .main_m_f { + position: absolute; + width: 9.75rem; + padding-top: 0.5rem; + bottom: 0.4375rem; + left: 0; + right: 0; + margin: 0 auto; + z-index: 99; +} + +.content .main .main_m_f ul { + width: 100%; + display: flex; + justify-content: space-between; +} + +.content .main .main_m_f ul li { + width: 0.9rem; +} + +.content .main .main_m_f ul li a { + display: block; + width: 100%; + height: 0.8rem; + margin-bottom: 0.1375rem; +} + +.content .main .main_m_f ul li a img { + width: 0.875rem; + height: 0.8rem; +} + +.content .main .main_m_f ul li a img:nth-child(1) { + display: block; +} + +.content .main .main_m_f ul li a img:nth-child(2) { + display: none; +} + +.content .main .main_m_f ul li span { + display: block; + width: 100%; + font-size: 0.2rem; + font-family: SourceHanSansCN; + font-weight: 400; + color: #adf3e6; + line-height: 0.2rem; + text-align: center; + white-space: nowrap; + cursor: pointer; +} + +.content .main .main_m_f ul li.active span { + background: linear-gradient(180deg, #ffb63b, #adf3e6); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; +} + +.content .main .main_m_f ul li.active a img:nth-child(1) { + display: none; +} + +.content .main .main_m_f ul li.active a img:nth-child(2) { + display: block; +} + +.content .main .main_r { + z-index: 99; +} + +.content .main .main_r .item { + background: rgba(12, 31, 86, 0.7); +} + +.content .main .main_r .item .con { + width: 100%; +} + +.content .main .main_r .item .con .con_t { + width: 100%; + padding-top: 0.1875rem; + display: flex; + justify-content: space-between; +} + +.content .main .main_r .item .con .con_t p { + padding-left: 0.2625rem; +} + +.content .main .main_r .item .con .con_t p span { + display: inline-block; + margin-right: 0.25rem; + font-size: 0.175rem; + font-family: SourceHanSansCN; + font-weight: 400; + color: #FFFFFF; + line-height: 0.25rem; + cursor: pointer; +} + +.content .main .main_r .item .con .con_t p span i { + display: inline-block; + width: 0.1rem; + height: 0.1rem; + border: 0.0125rem solid #244393; + border-radius: 50%; + margin-right: 0.1rem; +} + +.content .main .main_r .item .con .con_t p .span_c1 i { + background-color: #4b7efe; +} + +.content .main .main_r .item .con .con_t button { + width: 1.125rem; + height: 0.175rem; + background: url(../images/mainl-10.png) center no-repeat; + background-size: 100% 100%; + border: none; + margin-right: 0.125rem; + cursor: pointer; + margin-top: 0.0375rem; +} + +.content .main .main_r .item .con .con_m { + width: 100%; + margin-top: 0.0625rem; + margin-bottom: 0.1625rem; +} + +.content .main .main_r .item .con .con_m ul { + width: 100%; + display: flex; + justify-content: space-between; + padding: 0 0.175rem; + box-sizing: border-box; +} + +.content .main .main_r .item .con .con_m ul li { + width: 1.95rem; + padding-bottom: 0.3rem; + background: url(../images/mainl-12.png) no-repeat; + background-size: 100% 4; + background-position: 0% 93%; + cursor: pointer; +} + +.content .main .main_r .item .con .con_m ul li p { + width: 100%; + font-family: DINPro; + font-weight: 500; + color: #4B7EFE; + line-height: 0.4rem; + text-align: center; + font-size: 0.15rem; +} + +.content .main .main_r .item .con .con_m ul li p span { + font-size: 0.3rem; + line-height: 0.4rem; + font-weight: 500; + color: #4B7EFE; +} + +.content .main .main_r .item .con .con_m ul li h6 { + width: 100%; + text-align: center; + font-size: 0.175rem; + font-family: SourceHanSansCN; + font-weight: 400; + color: #6d7999; + line-height: 0.175rem; +} + +.content .main .main_r .item .con .con_m ul li:nth-child(2) p { + color: #00FFEA; +} + +.content .main .main_r .item .con .con_m ul li:nth-child(2) p span { + color: #00FFEA; +} + +.content .main .main_r .item .con .con_m ul li:nth-child(3) p { + color: #FEC31D; +} + +.content .main .main_r .item .con .con_m ul li:nth-child(3) p span { + color: #FEC31D; +} + +.content .main .main_r .item .con .con_m ul .li-sel1 { + background: url(../images/mainl-13.png) no-repeat; + background-size: 100% 4; + background-position: 0% 100%; +} + +.content .main .main_r .item .con .con_m ul .li-sel1 h6 { + color: #fff; +} + +.content .main .main_r .item .con .con_f { + width: 100%; + height: 1.3125rem; +} + +.content .main .main_r .mainr3 .con { + width: 100%; + padding: 0.225rem 0.325rem 0 0.775rem; + box-sizing: border-box; + display: flex; + justify-content: space-between; +} + +.content .main .main_r .mainr3 .con .con_box { + width: 2.3rem; + height: 1.4375rem; + margin-bottom: 0.275rem; + padding-top: 0.0625rem; + box-sizing: border-box; +} + +.content .main .main_r .mainr3 .con .con_box p { + width: 100%; + font-size: 0.2rem; + font-family: SourceHanSansCN; + font-weight: 400; + color: #FFFFFF; + line-height: 0.25rem; + padding-right: 0.175rem; + text-align: right; + box-sizing: border-box; +} + +.content .main .main_r .mainr3 .con .con_box span { + display: block; + width: 100%; + font-size: 0.2rem; + font-family: SourceHanSansCN; + font-weight: 400; + color: #FFFFFF; + line-height: 0.2rem; + padding-right: 0.175rem; + text-align: right; + box-sizing: border-box; +} + +.content .main .main_r .mainr3 .con .con_box b { + font-weight: normal; +} + +.content .main .main_r .mainr3 .con .box1 { + background: url(../images/mainr-1.png) center no-repeat; + background-size: 100% 100%; +} + +.content .main .main_r .mainr3 .con .box2 { + background: url(../images/mainr-2.png) center no-repeat; + background-size: 100% 100%; +} + +.content .main .main_r .mainr3 .text_box { + width: 100%; + height: 1rem; +} + +.content .main .main_r .mainr3 .text_box .text1 { + width: 100%; + display: flex; + padding: 0 0.9375rem 0 0.5rem; + box-sizing: border-box; + justify-content: space-between; +} + +.content .main .main_r .mainr3 .text_box .text1 p { + width: 1.875rem; + height: 0.4rem; + font-size: 0.175rem; + font-family: DINPro; + font-weight: 500; + color: #4B7EFE; + line-height: 0.4rem; + text-align: center; +} + +.content .main .main_r .mainr3 .text_box .text1 p span { + font-size: 0.3rem; + margin-right: 0.0375rem; + white-space: nowrap; +} + +.content .main .main_r .mainr3 .text_box .text1 p:last-child { + font-weight: 500; + color: #00FFEA; +} + +.content .main .main_r .mainr3 .text_box .text2 { + width: 100%; + display: flex; + padding: 0 1.475rem 0 0.95rem; + box-sizing: border-box; + justify-content: space-between; +} + +.content .main .main_r .mainr3 .text_box .text2 span { + font-size: 0.175rem; + font-family: SourceHanSansCN; + font-weight: 400; + color: #4B7EFE; + line-height: 0.4rem; +} + +.content .main .map { + position: absolute; + width: 100%; + top: 0; + left: 0; + height: 11.6875rem; + background-color: rgba(0, 0, 0, 0) !important; +} + +.daterangepicker { + background: #061745 !important; +} + +.daterangepicker .calendar-table { + background: #061745 !important; +} + +.daterangepicker td.active { + color: #000 !important; + background: #4b7efe !important; +} + +.daterangepicker td.off { + background: #061745 !important; + color: #193d5c !important; +} + +.daterangepicker .calendar th, +.daterangepicker .calendar td { + color: #357ebd; +} + +.daterangepicker .calendar-table { + border-color: #061745 !important; +} + +.btn-success { + background-color: #357ebd; + border-color: #357ebd; + outline: none; +} + +.btn-success:hover { + background-color: #357ebd; + border-color: #357ebd; +} + +.btn-success[disabled] { + background-color: #357ebd; + border-color: #357ebd; +} + +.btn-success:focus { + background-color: #357ebd; + border-color: #357ebd; + outline: none; +} + +.btn-success:active { + background-color: #357ebd; + border-color: #357ebd; +} + +.daterangepicker:after { + display: none !important; +} + +.daterangepicker:before { + display: none !important; +} + +.amap-logo { + display: none !important; + visibility: hidden !important; +} + +.amap-copyright { + display: none !important; + visibility: hidden !important; +} + +.point { + position: relative; +} + +.point i { + display: block; + background-color: #8233b8; + border-radius: 50%; + margin: 0 auto; +} + +.point span { + position: absolute; + top: -0.25rem; + left: 0; + display: none; + font-size: 0.175rem; + color: yellow; + text-align: center; + white-space: nowrap; +} + +.point:hover span { + display: block; + font-size: 42px; + font-family: Microsoft YaHei; + font-weight: bold; + color: #CECECE; +} + +.area span { + font-size: 0.175rem; + color: #fff; + text-align: center; + white-space: nowrap; +} \ No newline at end of file diff --git "a/web/112 \350\214\266\345\217\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/fonts/glyphicons-halflings-regular.eot" "b/web/112 \350\214\266\345\217\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/fonts/glyphicons-halflings-regular.eot" new file mode 100644 index 00000000..b93a4953 Binary files /dev/null and "b/web/112 \350\214\266\345\217\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/fonts/glyphicons-halflings-regular.eot" differ diff --git "a/web/112 \350\214\266\345\217\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/fonts/glyphicons-halflings-regular.svg" "b/web/112 \350\214\266\345\217\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/fonts/glyphicons-halflings-regular.svg" new file mode 100644 index 00000000..94fb5490 --- /dev/null +++ "b/web/112 \350\214\266\345\217\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/fonts/glyphicons-halflings-regular.svg" @@ -0,0 +1,288 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git "a/web/112 \350\214\266\345\217\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/fonts/glyphicons-halflings-regular.ttf" "b/web/112 \350\214\266\345\217\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/fonts/glyphicons-halflings-regular.ttf" new file mode 100644 index 00000000..1413fc60 Binary files /dev/null and "b/web/112 \350\214\266\345\217\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/fonts/glyphicons-halflings-regular.ttf" differ diff --git "a/web/112 \350\214\266\345\217\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/fonts/glyphicons-halflings-regular.woff" "b/web/112 \350\214\266\345\217\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/fonts/glyphicons-halflings-regular.woff" new file mode 100644 index 00000000..9e612858 Binary files /dev/null and "b/web/112 \350\214\266\345\217\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/fonts/glyphicons-halflings-regular.woff" differ diff --git "a/web/112 \350\214\266\345\217\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/fonts/glyphicons-halflings-regular.woff2" "b/web/112 \350\214\266\345\217\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/fonts/glyphicons-halflings-regular.woff2" new file mode 100644 index 00000000..64539b54 Binary files /dev/null and "b/web/112 \350\214\266\345\217\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/fonts/glyphicons-halflings-regular.woff2" differ diff --git "a/web/112 \350\214\266\345\217\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/images/bg_02.jpg" "b/web/112 \350\214\266\345\217\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/images/bg_02.jpg" new file mode 100644 index 00000000..0970fe8f Binary files /dev/null and "b/web/112 \350\214\266\345\217\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/images/bg_02.jpg" differ diff --git "a/web/112 \350\214\266\345\217\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/images/header-2.png" "b/web/112 \350\214\266\345\217\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/images/header-2.png" new file mode 100644 index 00000000..2b736085 Binary files /dev/null and "b/web/112 \350\214\266\345\217\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/images/header-2.png" differ diff --git "a/web/112 \350\214\266\345\217\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/images/header-4.png" "b/web/112 \350\214\266\345\217\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/images/header-4.png" new file mode 100644 index 00000000..c7e83f73 Binary files /dev/null and "b/web/112 \350\214\266\345\217\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/images/header-4.png" differ diff --git "a/web/112 \350\214\266\345\217\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/images/mainl-1.png" "b/web/112 \350\214\266\345\217\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/images/mainl-1.png" new file mode 100644 index 00000000..0893adb4 Binary files /dev/null and "b/web/112 \350\214\266\345\217\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/images/mainl-1.png" differ diff --git "a/web/112 \350\214\266\345\217\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/images/mainl-10.png" "b/web/112 \350\214\266\345\217\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/images/mainl-10.png" new file mode 100644 index 00000000..2b9016cb Binary files /dev/null and "b/web/112 \350\214\266\345\217\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/images/mainl-10.png" differ diff --git "a/web/112 \350\214\266\345\217\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/images/mainl-12.png" "b/web/112 \350\214\266\345\217\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/images/mainl-12.png" new file mode 100644 index 00000000..035cf60f Binary files /dev/null and "b/web/112 \350\214\266\345\217\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/images/mainl-12.png" differ diff --git "a/web/112 \350\214\266\345\217\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/images/mainl-13.png" "b/web/112 \350\214\266\345\217\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/images/mainl-13.png" new file mode 100644 index 00000000..5ab5e228 Binary files /dev/null and "b/web/112 \350\214\266\345\217\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/images/mainl-13.png" differ diff --git "a/web/112 \350\214\266\345\217\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/images/mainl-2.png" "b/web/112 \350\214\266\345\217\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/images/mainl-2.png" new file mode 100644 index 00000000..785c77dd Binary files /dev/null and "b/web/112 \350\214\266\345\217\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/images/mainl-2.png" differ diff --git "a/web/112 \350\214\266\345\217\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/images/mainl-3.png" "b/web/112 \350\214\266\345\217\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/images/mainl-3.png" new file mode 100644 index 00000000..9b807201 Binary files /dev/null and "b/web/112 \350\214\266\345\217\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/images/mainl-3.png" differ diff --git "a/web/112 \350\214\266\345\217\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/images/mainl-4.png" "b/web/112 \350\214\266\345\217\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/images/mainl-4.png" new file mode 100644 index 00000000..33286113 Binary files /dev/null and "b/web/112 \350\214\266\345\217\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/images/mainl-4.png" differ diff --git "a/web/112 \350\214\266\345\217\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/images/mainl-5.png" "b/web/112 \350\214\266\345\217\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/images/mainl-5.png" new file mode 100644 index 00000000..8e095a1e Binary files /dev/null and "b/web/112 \350\214\266\345\217\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/images/mainl-5.png" differ diff --git "a/web/112 \350\214\266\345\217\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/images/mainl1-bg.png" "b/web/112 \350\214\266\345\217\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/images/mainl1-bg.png" new file mode 100644 index 00000000..dde3d641 Binary files /dev/null and "b/web/112 \350\214\266\345\217\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/images/mainl1-bg.png" differ diff --git "a/web/112 \350\214\266\345\217\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/images/mainm-1.png" "b/web/112 \350\214\266\345\217\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/images/mainm-1.png" new file mode 100644 index 00000000..41cf264c Binary files /dev/null and "b/web/112 \350\214\266\345\217\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/images/mainm-1.png" differ diff --git "a/web/112 \350\214\266\345\217\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/images/mainm-12.jpg" "b/web/112 \350\214\266\345\217\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/images/mainm-12.jpg" new file mode 100644 index 00000000..3f71d059 Binary files /dev/null and "b/web/112 \350\214\266\345\217\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/images/mainm-12.jpg" differ diff --git "a/web/112 \350\214\266\345\217\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/images/mainm-2.png" "b/web/112 \350\214\266\345\217\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/images/mainm-2.png" new file mode 100644 index 00000000..fabc6958 Binary files /dev/null and "b/web/112 \350\214\266\345\217\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/images/mainm-2.png" differ diff --git "a/web/112 \350\214\266\345\217\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/images/mainr-1.png" "b/web/112 \350\214\266\345\217\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/images/mainr-1.png" new file mode 100644 index 00000000..3e8409d6 Binary files /dev/null and "b/web/112 \350\214\266\345\217\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/images/mainr-1.png" differ diff --git "a/web/112 \350\214\266\345\217\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/images/mainr-2.png" "b/web/112 \350\214\266\345\217\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/images/mainr-2.png" new file mode 100644 index 00000000..fb8ecf55 Binary files /dev/null and "b/web/112 \350\214\266\345\217\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/images/mainr-2.png" differ diff --git "a/web/112 \350\214\266\345\217\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/images/\346\233\264\345\244\232\345\206\205\345\256\271\345\205\263\346\263\250\345\205\254\344\274\227\345\217\267.gif" "b/web/112 \350\214\266\345\217\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/images/\346\233\264\345\244\232\345\206\205\345\256\271\345\205\263\346\263\250\345\205\254\344\274\227\345\217\267.gif" new file mode 100644 index 00000000..f2951f1d Binary files /dev/null and "b/web/112 \350\214\266\345\217\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/images/\346\233\264\345\244\232\345\206\205\345\256\271\345\205\263\346\263\250\345\205\254\344\274\227\345\217\267.gif" differ diff --git "a/web/112 \350\214\266\345\217\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/js/bootstrap-3.3.4.js" "b/web/112 \350\214\266\345\217\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/js/bootstrap-3.3.4.js" new file mode 100644 index 00000000..e62f981c --- /dev/null +++ "b/web/112 \350\214\266\345\217\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/js/bootstrap-3.3.4.js" @@ -0,0 +1,3 @@ +/*-防止各大cdn公共库加载地址失效问题,此地址我们会时时监控,及调整以保障正常访问-www.jq22.com为您服务*/ +/*当前为百度cdn公共库提供的bootstrap-3.3.4*/ +document.write(" + + + +
+
+ +
+

福鼎白茶大数据溯源平台

+
+ +
+
+
+
+
+

交易产量

+

+ +
+
+
+

当日茶青交易产量:150.9公斤

+
+
+
+
+
+
+

交易产量

+

+ +
+
+
+

当日毛茶交易产量:150.9公斤

+
+
+
+
+ +
+ + +
+
+

产业介绍

+
+ +
+

福鼎是中国白茶发源地和核心产区,也是唯一由国家部委授予的“中国白茶之乡”,素有“世界白茶在中国,中国白茶在福鼎”之美誉。这里三面环山一面临海,以花岗岩地貌、微酸性砂砾土壤为主,千百年来,独特的地理气候条件孕育出福鼎大白茶、福鼎大毫茶两大国家级茶树良种。福鼎白茶运用传统独特工艺,最大限度地保留了茶叶中的营养和活性,造就了福鼎白茶“毫香蜜韵、历久弥香、自然健康”的特质。新茶有甜爽之美,老茶有甘醇之韵,广为世人所推崇。 +

+

福鼎市大力实施基地化生态茶园建设,推行茶园不使用化学农药全覆盖,始终坚持做老百姓喝得起的放心茶、健康茶。福鼎白茶大数据溯源系统于2021年3月10日正式启用,必将更好地维护消费者的权益,确保每一份福鼎白茶都来自福鼎正宗原产地。 +

+

福鼎白茶,让世界更美好!

+
+
+
+
+
+
+

6551

+ 茶农 (户) +

150.6

+ 经纪人(家) +
+
+

85

+ 茶企 (家) +

65.8

+ 加工点(家) +
+
+

14,374.64

+ 茶园总面积 (万亩) +

35.40

+ 交易额 (亿元) +
+
+

338,029.51

+ 交易产量 (万吨) +

2.4576

+ 溯源码量 (个) +
+ +
+
+
+
+
+

地区名称

+
+

茶农(户):152

+

茶企(家):152

+

茶园面积(千克):152

+

预测产量(户):152

+

当年实际产量(千克):152

+

当年溯源产量(千克):152

+

茶叶产值

+
+
+
+ +
+ + +
+
+
    +
  • + + + + 数字溯源 +
  • +
  • + + + + 病虫害测报 +
  • +
  • + + + + 非化学农药监管 +
  • +
  • + + + + 茶山地貌 +
  • +
  • + + + + 数字交易 +
  • +
  • + + + + 数字加工 +
  • +
  • + + + + 白茶文旅 +
  • +
  • + + + + 茶文化 +
  • +
+
+ +
+
+
+

交易额

+

+ +
+
+
+

当月茶青交易额:150.9万元

+
+
+
+
+
+
+

交易额

+

+ +
+
+
+

当月毛茶交易额:150.9公斤

+
+
+
+
+
+
+ +
+
+
+ +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git "a/web/113 \347\231\275\350\214\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/css/bootstrap-3.3.4.css" "b/web/113 \347\231\275\350\214\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/css/bootstrap-3.3.4.css" new file mode 100644 index 00000000..85b74019 --- /dev/null +++ "b/web/113 \347\231\275\350\214\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/css/bootstrap-3.3.4.css" @@ -0,0 +1,3 @@ +/*-防止各大cdn公共库加载地址失效问题,此地址我们会时时监控,及调整-www.jq22.com为您服务*/ +/*当前为百度 cdn公共库提供的bootstrap-3.3.4 Css样式文件*/ +@import url("bootstrap.css"); diff --git "a/web/113 \347\231\275\350\214\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/css/bootstrap.css" "b/web/113 \347\231\275\350\214\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/css/bootstrap.css" new file mode 100644 index 00000000..15179b7f --- /dev/null +++ "b/web/113 \347\231\275\350\214\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/css/bootstrap.css" @@ -0,0 +1,6584 @@ +/*! + * Bootstrap v3.3.4 (http://getbootstrap.com) + * Copyright 2011-2015 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + */ + +/*! normalize.css v3.0.2 | MIT License | git.io/normalize */ +html { + font-family: sans-serif; + -webkit-text-size-adjust: 100%; + -ms-text-size-adjust: 100%; +} +body { + margin: 0; +} +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +main, +menu, +nav, +section, +summary { + display: block; +} +audio, +canvas, +progress, +video { + display: inline-block; + vertical-align: baseline; +} +audio:not([controls]) { + display: none; + height: 0; +} +[hidden], +template { + display: none; +} +a { + background-color: transparent; +} +a:active, +a:hover { + outline: 0; +} +abbr[title] { + border-bottom: 1px dotted; +} +b, +strong { + font-weight: bold; +} +dfn { + font-style: italic; +} +h1 { + margin: .67em 0; + font-size: 2em; +} +mark { + color: #000; + background: #ff0; +} +small { + font-size: 80%; +} +sub, +sup { + position: relative; + font-size: 75%; + line-height: 0; + vertical-align: baseline; +} +sup { + top: -.5em; +} +sub { + bottom: -.25em; +} +img { + border: 0; +} +svg:not(:root) { + overflow: hidden; +} +figure { + margin: 1em 40px; +} +hr { + height: 0; + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; +} +pre { + overflow: auto; +} +code, +kbd, +pre, +samp { + font-family: monospace, monospace; + font-size: 1em; +} +button, +input, +optgroup, +select, +textarea { + margin: 0; + font: inherit; + color: inherit; +} +button { + overflow: visible; +} +button, +select { + text-transform: none; +} +button, +html input[type="button"], +input[type="reset"], +input[type="submit"] { + -webkit-appearance: button; + cursor: pointer; +} +button[disabled], +html input[disabled] { + cursor: default; +} +button::-moz-focus-inner, +input::-moz-focus-inner { + padding: 0; + border: 0; +} +input { + line-height: normal; +} +input[type="checkbox"], +input[type="radio"] { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + padding: 0; +} +input[type="number"]::-webkit-inner-spin-button, +input[type="number"]::-webkit-outer-spin-button { + height: auto; +} +input[type="search"] { + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; + -webkit-appearance: textfield; +} +input[type="search"]::-webkit-search-cancel-button, +input[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; +} +fieldset { + padding: .35em .625em .75em; + margin: 0 2px; + border: 1px solid #c0c0c0; +} +legend { + padding: 0; + border: 0; +} +textarea { + overflow: auto; +} +optgroup { + font-weight: bold; +} +table { + border-spacing: 0; + border-collapse: collapse; +} +td, +th { + padding: 0; +} +/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */ +@media print { + *, + *:before, + *:after { + color: #000 !important; + text-shadow: none !important; + background: transparent !important; + -webkit-box-shadow: none !important; + box-shadow: none !important; + } + a, + a:visited { + text-decoration: underline; + } + a[href]:after { + content: " (" attr(href) ")"; + } + abbr[title]:after { + content: " (" attr(title) ")"; + } + a[href^="#"]:after, + a[href^="javascript:"]:after { + content: ""; + } + pre, + blockquote { + border: 1px solid #999; + + page-break-inside: avoid; + } + thead { + display: table-header-group; + } + tr, + img { + page-break-inside: avoid; + } + img { + max-width: 100% !important; + } + p, + h2, + h3 { + orphans: 3; + widows: 3; + } + h2, + h3 { + page-break-after: avoid; + } + select { + background: #fff !important; + } + .navbar { + display: none; + } + .btn > .caret, + .dropup > .btn > .caret { + border-top-color: #000 !important; + } + .label { + border: 1px solid #000; + } + .table { + border-collapse: collapse !important; + } + .table td, + .table th { + background-color: #fff !important; + } + .table-bordered th, + .table-bordered td { + border: 1px solid #ddd !important; + } +} +@font-face { + font-family: 'Glyphicons Halflings'; + + src: url('../fonts/glyphicons-halflings-regular.eot'); + src: url('../fonts/glyphicons-halflings-regular.eot') format('embedded-opentype'), url('../fonts/glyphicons-halflings-regular.woff2') format('woff2'), url('../fonts/glyphicons-halflings-regular.woff') format('woff'), url('../fonts/glyphicons-halflings-regular.ttf') format('truetype'), url('../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg'); +} +.glyphicon { + position: relative; + top: 1px; + display: inline-block; + font-family: 'Glyphicons Halflings'; + font-style: normal; + font-weight: normal; + line-height: 1; + + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} +.glyphicon-asterisk:before { + content: "\2a"; +} +.glyphicon-plus:before { + content: "\2b"; +} +.glyphicon-euro:before, +.glyphicon-eur:before { + content: "\20ac"; +} +.glyphicon-minus:before { + content: "\2212"; +} +.glyphicon-cloud:before { + content: "\2601"; +} +.glyphicon-envelope:before { + content: "\2709"; +} +.glyphicon-pencil:before { + content: "\270f"; +} +.glyphicon-glass:before { + content: "\e001"; +} +.glyphicon-music:before { + content: "\e002"; +} +.glyphicon-search:before { + content: "\e003"; +} +.glyphicon-heart:before { + content: "\e005"; +} +.glyphicon-star:before { + content: "\e006"; +} +.glyphicon-star-empty:before { + content: "\e007"; +} +.glyphicon-user:before { + content: "\e008"; +} +.glyphicon-film:before { + content: "\e009"; +} +.glyphicon-th-large:before { + content: "\e010"; +} +.glyphicon-th:before { + content: "\e011"; +} +.glyphicon-th-list:before { + content: "\e012"; +} +.glyphicon-ok:before { + content: "\e013"; +} +.glyphicon-remove:before { + content: "\e014"; +} +.glyphicon-zoom-in:before { + content: "\e015"; +} +.glyphicon-zoom-out:before { + content: "\e016"; +} +.glyphicon-off:before { + content: "\e017"; +} +.glyphicon-signal:before { + content: "\e018"; +} +.glyphicon-cog:before { + content: "\e019"; +} +.glyphicon-trash:before { + content: "\e020"; +} +.glyphicon-home:before { + content: "\e021"; +} +.glyphicon-file:before { + content: "\e022"; +} +.glyphicon-time:before { + content: "\e023"; +} +.glyphicon-road:before { + content: "\e024"; +} +.glyphicon-download-alt:before { + content: "\e025"; +} +.glyphicon-download:before { + content: "\e026"; +} +.glyphicon-upload:before { + content: "\e027"; +} +.glyphicon-inbox:before { + content: "\e028"; +} +.glyphicon-play-circle:before { + content: "\e029"; +} +.glyphicon-repeat:before { + content: "\e030"; +} +.glyphicon-refresh:before { + content: "\e031"; +} +.glyphicon-list-alt:before { + content: "\e032"; +} +.glyphicon-lock:before { + content: "\e033"; +} +.glyphicon-flag:before { + content: "\e034"; +} +.glyphicon-headphones:before { + content: "\e035"; +} +.glyphicon-volume-off:before { + content: "\e036"; +} +.glyphicon-volume-down:before { + content: "\e037"; +} +.glyphicon-volume-up:before { + content: "\e038"; +} +.glyphicon-qrcode:before { + content: "\e039"; +} +.glyphicon-barcode:before { + content: "\e040"; +} +.glyphicon-tag:before { + content: "\e041"; +} +.glyphicon-tags:before { + content: "\e042"; +} +.glyphicon-book:before { + content: "\e043"; +} +.glyphicon-bookmark:before { + content: "\e044"; +} +.glyphicon-print:before { + content: "\e045"; +} +.glyphicon-camera:before { + content: "\e046"; +} +.glyphicon-font:before { + content: "\e047"; +} +.glyphicon-bold:before { + content: "\e048"; +} +.glyphicon-italic:before { + content: "\e049"; +} +.glyphicon-text-height:before { + content: "\e050"; +} +.glyphicon-text-width:before { + content: "\e051"; +} +.glyphicon-align-left:before { + content: "\e052"; +} +.glyphicon-align-center:before { + content: "\e053"; +} +.glyphicon-align-right:before { + content: "\e054"; +} +.glyphicon-align-justify:before { + content: "\e055"; +} +.glyphicon-list:before { + content: "\e056"; +} +.glyphicon-indent-left:before { + content: "\e057"; +} +.glyphicon-indent-right:before { + content: "\e058"; +} +.glyphicon-facetime-video:before { + content: "\e059"; +} +.glyphicon-picture:before { + content: "\e060"; +} +.glyphicon-map-marker:before { + content: "\e062"; +} +.glyphicon-adjust:before { + content: "\e063"; +} +.glyphicon-tint:before { + content: "\e064"; +} +.glyphicon-edit:before { + content: "\e065"; +} +.glyphicon-share:before { + content: "\e066"; +} +.glyphicon-check:before { + content: "\e067"; +} +.glyphicon-move:before { + content: "\e068"; +} +.glyphicon-step-backward:before { + content: "\e069"; +} +.glyphicon-fast-backward:before { + content: "\e070"; +} +.glyphicon-backward:before { + content: "\e071"; +} +.glyphicon-play:before { + content: "\e072"; +} +.glyphicon-pause:before { + content: "\e073"; +} +.glyphicon-stop:before { + content: "\e074"; +} +.glyphicon-forward:before { + content: "\e075"; +} +.glyphicon-fast-forward:before { + content: "\e076"; +} +.glyphicon-step-forward:before { + content: "\e077"; +} +.glyphicon-eject:before { + content: "\e078"; +} +.glyphicon-chevron-left:before { + content: "\e079"; +} +.glyphicon-chevron-right:before { + content: "\e080"; +} +.glyphicon-plus-sign:before { + content: "\e081"; +} +.glyphicon-minus-sign:before { + content: "\e082"; +} +.glyphicon-remove-sign:before { + content: "\e083"; +} +.glyphicon-ok-sign:before { + content: "\e084"; +} +.glyphicon-question-sign:before { + content: "\e085"; +} +.glyphicon-info-sign:before { + content: "\e086"; +} +.glyphicon-screenshot:before { + content: "\e087"; +} +.glyphicon-remove-circle:before { + content: "\e088"; +} +.glyphicon-ok-circle:before { + content: "\e089"; +} +.glyphicon-ban-circle:before { + content: "\e090"; +} +.glyphicon-arrow-left:before { + content: "\e091"; +} +.glyphicon-arrow-right:before { + content: "\e092"; +} +.glyphicon-arrow-up:before { + content: "\e093"; +} +.glyphicon-arrow-down:before { + content: "\e094"; +} +.glyphicon-share-alt:before { + content: "\e095"; +} +.glyphicon-resize-full:before { + content: "\e096"; +} +.glyphicon-resize-small:before { + content: "\e097"; +} +.glyphicon-exclamation-sign:before { + content: "\e101"; +} +.glyphicon-gift:before { + content: "\e102"; +} +.glyphicon-leaf:before { + content: "\e103"; +} +.glyphicon-fire:before { + content: "\e104"; +} +.glyphicon-eye-open:before { + content: "\e105"; +} +.glyphicon-eye-close:before { + content: "\e106"; +} +.glyphicon-warning-sign:before { + content: "\e107"; +} +.glyphicon-plane:before { + content: "\e108"; +} +.glyphicon-calendar:before { + content: "\e109"; +} +.glyphicon-random:before { + content: "\e110"; +} +.glyphicon-comment:before { + content: "\e111"; +} +.glyphicon-magnet:before { + content: "\e112"; +} +.glyphicon-chevron-up:before { + content: "\e113"; +} +.glyphicon-chevron-down:before { + content: "\e114"; +} +.glyphicon-retweet:before { + content: "\e115"; +} +.glyphicon-shopping-cart:before { + content: "\e116"; +} +.glyphicon-folder-close:before { + content: "\e117"; +} +.glyphicon-folder-open:before { + content: "\e118"; +} +.glyphicon-resize-vertical:before { + content: "\e119"; +} +.glyphicon-resize-horizontal:before { + content: "\e120"; +} +.glyphicon-hdd:before { + content: "\e121"; +} +.glyphicon-bullhorn:before { + content: "\e122"; +} +.glyphicon-bell:before { + content: "\e123"; +} +.glyphicon-certificate:before { + content: "\e124"; +} +.glyphicon-thumbs-up:before { + content: "\e125"; +} +.glyphicon-thumbs-down:before { + content: "\e126"; +} +.glyphicon-hand-right:before { + content: "\e127"; +} +.glyphicon-hand-left:before { + content: "\e128"; +} +.glyphicon-hand-up:before { + content: "\e129"; +} +.glyphicon-hand-down:before { + content: "\e130"; +} +.glyphicon-circle-arrow-right:before { + content: "\e131"; +} +.glyphicon-circle-arrow-left:before { + content: "\e132"; +} +.glyphicon-circle-arrow-up:before { + content: "\e133"; +} +.glyphicon-circle-arrow-down:before { + content: "\e134"; +} +.glyphicon-globe:before { + content: "\e135"; +} +.glyphicon-wrench:before { + content: "\e136"; +} +.glyphicon-tasks:before { + content: "\e137"; +} +.glyphicon-filter:before { + content: "\e138"; +} +.glyphicon-briefcase:before { + content: "\e139"; +} +.glyphicon-fullscreen:before { + content: "\e140"; +} +.glyphicon-dashboard:before { + content: "\e141"; +} +.glyphicon-paperclip:before { + content: "\e142"; +} +.glyphicon-heart-empty:before { + content: "\e143"; +} +.glyphicon-link:before { + content: "\e144"; +} +.glyphicon-phone:before { + content: "\e145"; +} +.glyphicon-pushpin:before { + content: "\e146"; +} +.glyphicon-usd:before { + content: "\e148"; +} +.glyphicon-gbp:before { + content: "\e149"; +} +.glyphicon-sort:before { + content: "\e150"; +} +.glyphicon-sort-by-alphabet:before { + content: "\e151"; +} +.glyphicon-sort-by-alphabet-alt:before { + content: "\e152"; +} +.glyphicon-sort-by-order:before { + content: "\e153"; +} +.glyphicon-sort-by-order-alt:before { + content: "\e154"; +} +.glyphicon-sort-by-attributes:before { + content: "\e155"; +} +.glyphicon-sort-by-attributes-alt:before { + content: "\e156"; +} +.glyphicon-unchecked:before { + content: "\e157"; +} +.glyphicon-expand:before { + content: "\e158"; +} +.glyphicon-collapse-down:before { + content: "\e159"; +} +.glyphicon-collapse-up:before { + content: "\e160"; +} +.glyphicon-log-in:before { + content: "\e161"; +} +.glyphicon-flash:before { + content: "\e162"; +} +.glyphicon-log-out:before { + content: "\e163"; +} +.glyphicon-new-window:before { + content: "\e164"; +} +.glyphicon-record:before { + content: "\e165"; +} +.glyphicon-save:before { + content: "\e166"; +} +.glyphicon-open:before { + content: "\e167"; +} +.glyphicon-saved:before { + content: "\e168"; +} +.glyphicon-import:before { + content: "\e169"; +} +.glyphicon-export:before { + content: "\e170"; +} +.glyphicon-send:before { + content: "\e171"; +} +.glyphicon-floppy-disk:before { + content: "\e172"; +} +.glyphicon-floppy-saved:before { + content: "\e173"; +} +.glyphicon-floppy-remove:before { + content: "\e174"; +} +.glyphicon-floppy-save:before { + content: "\e175"; +} +.glyphicon-floppy-open:before { + content: "\e176"; +} +.glyphicon-credit-card:before { + content: "\e177"; +} +.glyphicon-transfer:before { + content: "\e178"; +} +.glyphicon-cutlery:before { + content: "\e179"; +} +.glyphicon-header:before { + content: "\e180"; +} +.glyphicon-compressed:before { + content: "\e181"; +} +.glyphicon-earphone:before { + content: "\e182"; +} +.glyphicon-phone-alt:before { + content: "\e183"; +} +.glyphicon-tower:before { + content: "\e184"; +} +.glyphicon-stats:before { + content: "\e185"; +} +.glyphicon-sd-video:before { + content: "\e186"; +} +.glyphicon-hd-video:before { + content: "\e187"; +} +.glyphicon-subtitles:before { + content: "\e188"; +} +.glyphicon-sound-stereo:before { + content: "\e189"; +} +.glyphicon-sound-dolby:before { + content: "\e190"; +} +.glyphicon-sound-5-1:before { + content: "\e191"; +} +.glyphicon-sound-6-1:before { + content: "\e192"; +} +.glyphicon-sound-7-1:before { + content: "\e193"; +} +.glyphicon-copyright-mark:before { + content: "\e194"; +} +.glyphicon-registration-mark:before { + content: "\e195"; +} +.glyphicon-cloud-download:before { + content: "\e197"; +} +.glyphicon-cloud-upload:before { + content: "\e198"; +} +.glyphicon-tree-conifer:before { + content: "\e199"; +} +.glyphicon-tree-deciduous:before { + content: "\e200"; +} +.glyphicon-cd:before { + content: "\e201"; +} +.glyphicon-save-file:before { + content: "\e202"; +} +.glyphicon-open-file:before { + content: "\e203"; +} +.glyphicon-level-up:before { + content: "\e204"; +} +.glyphicon-copy:before { + content: "\e205"; +} +.glyphicon-paste:before { + content: "\e206"; +} +.glyphicon-alert:before { + content: "\e209"; +} +.glyphicon-equalizer:before { + content: "\e210"; +} +.glyphicon-king:before { + content: "\e211"; +} +.glyphicon-queen:before { + content: "\e212"; +} +.glyphicon-pawn:before { + content: "\e213"; +} +.glyphicon-bishop:before { + content: "\e214"; +} +.glyphicon-knight:before { + content: "\e215"; +} +.glyphicon-baby-formula:before { + content: "\e216"; +} +.glyphicon-tent:before { + content: "\26fa"; +} +.glyphicon-blackboard:before { + content: "\e218"; +} +.glyphicon-bed:before { + content: "\e219"; +} +.glyphicon-apple:before { + content: "\f8ff"; +} +.glyphicon-erase:before { + content: "\e221"; +} +.glyphicon-hourglass:before { + content: "\231b"; +} +.glyphicon-lamp:before { + content: "\e223"; +} +.glyphicon-duplicate:before { + content: "\e224"; +} +.glyphicon-piggy-bank:before { + content: "\e225"; +} +.glyphicon-scissors:before { + content: "\e226"; +} +.glyphicon-bitcoin:before { + content: "\e227"; +} +.glyphicon-btc:before { + content: "\e227"; +} +.glyphicon-xbt:before { + content: "\e227"; +} +.glyphicon-yen:before { + content: "\00a5"; +} +.glyphicon-jpy:before { + content: "\00a5"; +} +.glyphicon-ruble:before { + content: "\20bd"; +} +.glyphicon-rub:before { + content: "\20bd"; +} +.glyphicon-scale:before { + content: "\e230"; +} +.glyphicon-ice-lolly:before { + content: "\e231"; +} +.glyphicon-ice-lolly-tasted:before { + content: "\e232"; +} +.glyphicon-education:before { + content: "\e233"; +} +.glyphicon-option-horizontal:before { + content: "\e234"; +} +.glyphicon-option-vertical:before { + content: "\e235"; +} +.glyphicon-menu-hamburger:before { + content: "\e236"; +} +.glyphicon-modal-window:before { + content: "\e237"; +} +.glyphicon-oil:before { + content: "\e238"; +} +.glyphicon-grain:before { + content: "\e239"; +} +.glyphicon-sunglasses:before { + content: "\e240"; +} +.glyphicon-text-size:before { + content: "\e241"; +} +.glyphicon-text-color:before { + content: "\e242"; +} +.glyphicon-text-background:before { + content: "\e243"; +} +.glyphicon-object-align-top:before { + content: "\e244"; +} +.glyphicon-object-align-bottom:before { + content: "\e245"; +} +.glyphicon-object-align-horizontal:before { + content: "\e246"; +} +.glyphicon-object-align-left:before { + content: "\e247"; +} +.glyphicon-object-align-vertical:before { + content: "\e248"; +} +.glyphicon-object-align-right:before { + content: "\e249"; +} +.glyphicon-triangle-right:before { + content: "\e250"; +} +.glyphicon-triangle-left:before { + content: "\e251"; +} +.glyphicon-triangle-bottom:before { + content: "\e252"; +} +.glyphicon-triangle-top:before { + content: "\e253"; +} +.glyphicon-console:before { + content: "\e254"; +} +.glyphicon-superscript:before { + content: "\e255"; +} +.glyphicon-subscript:before { + content: "\e256"; +} +.glyphicon-menu-left:before { + content: "\e257"; +} +.glyphicon-menu-right:before { + content: "\e258"; +} +.glyphicon-menu-down:before { + content: "\e259"; +} +.glyphicon-menu-up:before { + content: "\e260"; +} +* { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +*:before, +*:after { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +html { + font-size: 10px; + + -webkit-tap-highlight-color: rgba(0, 0, 0, 0); +} +body { + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 14px; + line-height: 1.42857143; + color: #333; + background-color: #fff; +} +input, +button, +select, +textarea { + font-family: inherit; + font-size: inherit; + line-height: inherit; +} +a { + color: #337ab7; + text-decoration: none; +} +a:hover, +a:focus { + color: #23527c; + text-decoration: underline; +} +a:focus { + outline: thin dotted; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} +figure { + margin: 0; +} +img { + vertical-align: middle; +} +.img-responsive, +.thumbnail > img, +.thumbnail a > img, +.carousel-inner > .item > img, +.carousel-inner > .item > a > img { + display: block; + max-width: 100%; + height: auto; +} +.img-rounded { + border-radius: 6px; +} +.img-thumbnail { + display: inline-block; + max-width: 100%; + height: auto; + padding: 4px; + line-height: 1.42857143; + background-color: #fff; + border: 1px solid #ddd; + border-radius: 4px; + -webkit-transition: all .2s ease-in-out; + -o-transition: all .2s ease-in-out; + transition: all .2s ease-in-out; +} +.img-circle { + border-radius: 50%; +} +hr { + margin-top: 20px; + margin-bottom: 20px; + border: 0; + border-top: 1px solid #eee; +} +.sr-only { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; +} +.sr-only-focusable:active, +.sr-only-focusable:focus { + position: static; + width: auto; + height: auto; + margin: 0; + overflow: visible; + clip: auto; +} +[role="button"] { + cursor: pointer; +} +h1, +h2, +h3, +h4, +h5, +h6, +.h1, +.h2, +.h3, +.h4, +.h5, +.h6 { + font-family: inherit; + font-weight: 500; + line-height: 1.1; + color: inherit; +} +h1 small, +h2 small, +h3 small, +h4 small, +h5 small, +h6 small, +.h1 small, +.h2 small, +.h3 small, +.h4 small, +.h5 small, +.h6 small, +h1 .small, +h2 .small, +h3 .small, +h4 .small, +h5 .small, +h6 .small, +.h1 .small, +.h2 .small, +.h3 .small, +.h4 .small, +.h5 .small, +.h6 .small { + font-weight: normal; + line-height: 1; + color: #777; +} +h1, +.h1, +h2, +.h2, +h3, +.h3 { + margin-top: 20px; + margin-bottom: 10px; +} +h1 small, +.h1 small, +h2 small, +.h2 small, +h3 small, +.h3 small, +h1 .small, +.h1 .small, +h2 .small, +.h2 .small, +h3 .small, +.h3 .small { + font-size: 65%; +} +h4, +.h4, +h5, +.h5, +h6, +.h6 { + margin-top: 10px; + margin-bottom: 10px; +} +h4 small, +.h4 small, +h5 small, +.h5 small, +h6 small, +.h6 small, +h4 .small, +.h4 .small, +h5 .small, +.h5 .small, +h6 .small, +.h6 .small { + font-size: 75%; +} +h1, +.h1 { + font-size: 36px; +} +h2, +.h2 { + font-size: 30px; +} +h3, +.h3 { + font-size: 24px; +} +h4, +.h4 { + font-size: 18px; +} +h5, +.h5 { + font-size: 14px; +} +h6, +.h6 { + font-size: 12px; +} +p { + margin: 0 0 10px; +} +.lead { + margin-bottom: 20px; + font-size: 16px; + font-weight: 300; + line-height: 1.4; +} +@media (min-width: 768px) { + .lead { + font-size: 21px; + } +} +small, +.small { + font-size: 85%; +} +mark, +.mark { + padding: .2em; + background-color: #fcf8e3; +} +.text-left { + text-align: left; +} +.text-right { + text-align: right; +} +.text-center { + text-align: center; +} +.text-justify { + text-align: justify; +} +.text-nowrap { + white-space: nowrap; +} +.text-lowercase { + text-transform: lowercase; +} +.text-uppercase { + text-transform: uppercase; +} +.text-capitalize { + text-transform: capitalize; +} +.text-muted { + color: #777; +} +.text-primary { + color: #337ab7; +} +a.text-primary:hover { + color: #286090; +} +.text-success { + color: #3c763d; +} +a.text-success:hover { + color: #2b542c; +} +.text-info { + color: #31708f; +} +a.text-info:hover { + color: #245269; +} +.text-warning { + color: #8a6d3b; +} +a.text-warning:hover { + color: #66512c; +} +.text-danger { + color: #a94442; +} +a.text-danger:hover { + color: #843534; +} +.bg-primary { + color: #fff; + background-color: #337ab7; +} +a.bg-primary:hover { + background-color: #286090; +} +.bg-success { + background-color: #dff0d8; +} +a.bg-success:hover { + background-color: #c1e2b3; +} +.bg-info { + background-color: #d9edf7; +} +a.bg-info:hover { + background-color: #afd9ee; +} +.bg-warning { + background-color: #fcf8e3; +} +a.bg-warning:hover { + background-color: #f7ecb5; +} +.bg-danger { + background-color: #f2dede; +} +a.bg-danger:hover { + background-color: #e4b9b9; +} +.page-header { + padding-bottom: 9px; + margin: 40px 0 20px; + border-bottom: 1px solid #eee; +} +ul, +ol { + margin-top: 0; + margin-bottom: 10px; +} +ul ul, +ol ul, +ul ol, +ol ol { + margin-bottom: 0; +} +.list-unstyled { + padding-left: 0; + list-style: none; +} +.list-inline { + padding-left: 0; + margin-left: -5px; + list-style: none; +} +.list-inline > li { + display: inline-block; + padding-right: 5px; + padding-left: 5px; +} +dl { + margin-top: 0; + margin-bottom: 20px; +} +dt, +dd { + line-height: 1.42857143; +} +dt { + font-weight: bold; +} +dd { + margin-left: 0; +} +@media (min-width: 768px) { + .dl-horizontal dt { + float: left; + width: 160px; + overflow: hidden; + clear: left; + text-align: right; + text-overflow: ellipsis; + white-space: nowrap; + } + .dl-horizontal dd { + margin-left: 180px; + } +} +abbr[title], +abbr[data-original-title] { + cursor: help; + border-bottom: 1px dotted #777; +} +.initialism { + font-size: 90%; + text-transform: uppercase; +} +blockquote { + padding: 10px 20px; + margin: 0 0 20px; + font-size: 17.5px; + border-left: 5px solid #eee; +} +blockquote p:last-child, +blockquote ul:last-child, +blockquote ol:last-child { + margin-bottom: 0; +} +blockquote footer, +blockquote small, +blockquote .small { + display: block; + font-size: 80%; + line-height: 1.42857143; + color: #777; +} +blockquote footer:before, +blockquote small:before, +blockquote .small:before { + content: '\2014 \00A0'; +} +.blockquote-reverse, +blockquote.pull-right { + padding-right: 15px; + padding-left: 0; + text-align: right; + border-right: 5px solid #eee; + border-left: 0; +} +.blockquote-reverse footer:before, +blockquote.pull-right footer:before, +.blockquote-reverse small:before, +blockquote.pull-right small:before, +.blockquote-reverse .small:before, +blockquote.pull-right .small:before { + content: ''; +} +.blockquote-reverse footer:after, +blockquote.pull-right footer:after, +.blockquote-reverse small:after, +blockquote.pull-right small:after, +.blockquote-reverse .small:after, +blockquote.pull-right .small:after { + content: '\00A0 \2014'; +} +address { + margin-bottom: 20px; + font-style: normal; + line-height: 1.42857143; +} +code, +kbd, +pre, +samp { + font-family: Menlo, Monaco, Consolas, "Courier New", monospace; +} +code { + padding: 2px 4px; + font-size: 90%; + color: #c7254e; + background-color: #f9f2f4; + border-radius: 4px; +} +kbd { + padding: 2px 4px; + font-size: 90%; + color: #fff; + background-color: #333; + border-radius: 3px; + -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .25); + box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .25); +} +kbd kbd { + padding: 0; + font-size: 100%; + font-weight: bold; + -webkit-box-shadow: none; + box-shadow: none; +} +pre { + display: block; + padding: 9.5px; + margin: 0 0 10px; + font-size: 13px; + line-height: 1.42857143; + color: #333; + word-break: break-all; + word-wrap: break-word; + background-color: #f5f5f5; + border: 1px solid #ccc; + border-radius: 4px; +} +pre code { + padding: 0; + font-size: inherit; + color: inherit; + white-space: pre-wrap; + background-color: transparent; + border-radius: 0; +} +.pre-scrollable { + max-height: 340px; + overflow-y: scroll; +} +.container { + padding-right: 15px; + padding-left: 15px; + margin-right: auto; + margin-left: auto; +} +@media (min-width: 768px) { + .container { + width: 750px; + } +} +@media (min-width: 992px) { + .container { + width: 970px; + } +} +@media (min-width: 1200px) { + .container { + width: 1170px; + } +} +.container-fluid { + padding-right: 15px; + padding-left: 15px; + margin-right: auto; + margin-left: auto; +} +.row { + margin-right: -15px; + margin-left: -15px; +} +.col-xs-1, .col-sm-1, .col-md-1, .col-lg-1, .col-xs-2, .col-sm-2, .col-md-2, .col-lg-2, .col-xs-3, .col-sm-3, .col-md-3, .col-lg-3, .col-xs-4, .col-sm-4, .col-md-4, .col-lg-4, .col-xs-5, .col-sm-5, .col-md-5, .col-lg-5, .col-xs-6, .col-sm-6, .col-md-6, .col-lg-6, .col-xs-7, .col-sm-7, .col-md-7, .col-lg-7, .col-xs-8, .col-sm-8, .col-md-8, .col-lg-8, .col-xs-9, .col-sm-9, .col-md-9, .col-lg-9, .col-xs-10, .col-sm-10, .col-md-10, .col-lg-10, .col-xs-11, .col-sm-11, .col-md-11, .col-lg-11, .col-xs-12, .col-sm-12, .col-md-12, .col-lg-12 { + position: relative; + min-height: 1px; + padding-right: 15px; + padding-left: 15px; +} +.col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12 { + float: left; +} +.col-xs-12 { + width: 100%; +} +.col-xs-11 { + width: 91.66666667%; +} +.col-xs-10 { + width: 83.33333333%; +} +.col-xs-9 { + width: 75%; +} +.col-xs-8 { + width: 66.66666667%; +} +.col-xs-7 { + width: 58.33333333%; +} +.col-xs-6 { + width: 50%; +} +.col-xs-5 { + width: 41.66666667%; +} +.col-xs-4 { + width: 33.33333333%; +} +.col-xs-3 { + width: 25%; +} +.col-xs-2 { + width: 16.66666667%; +} +.col-xs-1 { + width: 8.33333333%; +} +.col-xs-pull-12 { + right: 100%; +} +.col-xs-pull-11 { + right: 91.66666667%; +} +.col-xs-pull-10 { + right: 83.33333333%; +} +.col-xs-pull-9 { + right: 75%; +} +.col-xs-pull-8 { + right: 66.66666667%; +} +.col-xs-pull-7 { + right: 58.33333333%; +} +.col-xs-pull-6 { + right: 50%; +} +.col-xs-pull-5 { + right: 41.66666667%; +} +.col-xs-pull-4 { + right: 33.33333333%; +} +.col-xs-pull-3 { + right: 25%; +} +.col-xs-pull-2 { + right: 16.66666667%; +} +.col-xs-pull-1 { + right: 8.33333333%; +} +.col-xs-pull-0 { + right: auto; +} +.col-xs-push-12 { + left: 100%; +} +.col-xs-push-11 { + left: 91.66666667%; +} +.col-xs-push-10 { + left: 83.33333333%; +} +.col-xs-push-9 { + left: 75%; +} +.col-xs-push-8 { + left: 66.66666667%; +} +.col-xs-push-7 { + left: 58.33333333%; +} +.col-xs-push-6 { + left: 50%; +} +.col-xs-push-5 { + left: 41.66666667%; +} +.col-xs-push-4 { + left: 33.33333333%; +} +.col-xs-push-3 { + left: 25%; +} +.col-xs-push-2 { + left: 16.66666667%; +} +.col-xs-push-1 { + left: 8.33333333%; +} +.col-xs-push-0 { + left: auto; +} +.col-xs-offset-12 { + margin-left: 100%; +} +.col-xs-offset-11 { + margin-left: 91.66666667%; +} +.col-xs-offset-10 { + margin-left: 83.33333333%; +} +.col-xs-offset-9 { + margin-left: 75%; +} +.col-xs-offset-8 { + margin-left: 66.66666667%; +} +.col-xs-offset-7 { + margin-left: 58.33333333%; +} +.col-xs-offset-6 { + margin-left: 50%; +} +.col-xs-offset-5 { + margin-left: 41.66666667%; +} +.col-xs-offset-4 { + margin-left: 33.33333333%; +} +.col-xs-offset-3 { + margin-left: 25%; +} +.col-xs-offset-2 { + margin-left: 16.66666667%; +} +.col-xs-offset-1 { + margin-left: 8.33333333%; +} +.col-xs-offset-0 { + margin-left: 0; +} +@media (min-width: 768px) { + .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12 { + float: left; + } + .col-sm-12 { + width: 100%; + } + .col-sm-11 { + width: 91.66666667%; + } + .col-sm-10 { + width: 83.33333333%; + } + .col-sm-9 { + width: 75%; + } + .col-sm-8 { + width: 66.66666667%; + } + .col-sm-7 { + width: 58.33333333%; + } + .col-sm-6 { + width: 50%; + } + .col-sm-5 { + width: 41.66666667%; + } + .col-sm-4 { + width: 33.33333333%; + } + .col-sm-3 { + width: 25%; + } + .col-sm-2 { + width: 16.66666667%; + } + .col-sm-1 { + width: 8.33333333%; + } + .col-sm-pull-12 { + right: 100%; + } + .col-sm-pull-11 { + right: 91.66666667%; + } + .col-sm-pull-10 { + right: 83.33333333%; + } + .col-sm-pull-9 { + right: 75%; + } + .col-sm-pull-8 { + right: 66.66666667%; + } + .col-sm-pull-7 { + right: 58.33333333%; + } + .col-sm-pull-6 { + right: 50%; + } + .col-sm-pull-5 { + right: 41.66666667%; + } + .col-sm-pull-4 { + right: 33.33333333%; + } + .col-sm-pull-3 { + right: 25%; + } + .col-sm-pull-2 { + right: 16.66666667%; + } + .col-sm-pull-1 { + right: 8.33333333%; + } + .col-sm-pull-0 { + right: auto; + } + .col-sm-push-12 { + left: 100%; + } + .col-sm-push-11 { + left: 91.66666667%; + } + .col-sm-push-10 { + left: 83.33333333%; + } + .col-sm-push-9 { + left: 75%; + } + .col-sm-push-8 { + left: 66.66666667%; + } + .col-sm-push-7 { + left: 58.33333333%; + } + .col-sm-push-6 { + left: 50%; + } + .col-sm-push-5 { + left: 41.66666667%; + } + .col-sm-push-4 { + left: 33.33333333%; + } + .col-sm-push-3 { + left: 25%; + } + .col-sm-push-2 { + left: 16.66666667%; + } + .col-sm-push-1 { + left: 8.33333333%; + } + .col-sm-push-0 { + left: auto; + } + .col-sm-offset-12 { + margin-left: 100%; + } + .col-sm-offset-11 { + margin-left: 91.66666667%; + } + .col-sm-offset-10 { + margin-left: 83.33333333%; + } + .col-sm-offset-9 { + margin-left: 75%; + } + .col-sm-offset-8 { + margin-left: 66.66666667%; + } + .col-sm-offset-7 { + margin-left: 58.33333333%; + } + .col-sm-offset-6 { + margin-left: 50%; + } + .col-sm-offset-5 { + margin-left: 41.66666667%; + } + .col-sm-offset-4 { + margin-left: 33.33333333%; + } + .col-sm-offset-3 { + margin-left: 25%; + } + .col-sm-offset-2 { + margin-left: 16.66666667%; + } + .col-sm-offset-1 { + margin-left: 8.33333333%; + } + .col-sm-offset-0 { + margin-left: 0; + } +} +@media (min-width: 992px) { + .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12 { + float: left; + } + .col-md-12 { + width: 100%; + } + .col-md-11 { + width: 91.66666667%; + } + .col-md-10 { + width: 83.33333333%; + } + .col-md-9 { + width: 75%; + } + .col-md-8 { + width: 66.66666667%; + } + .col-md-7 { + width: 58.33333333%; + } + .col-md-6 { + width: 50%; + } + .col-md-5 { + width: 41.66666667%; + } + .col-md-4 { + width: 33.33333333%; + } + .col-md-3 { + width: 25%; + } + .col-md-2 { + width: 16.66666667%; + } + .col-md-1 { + width: 8.33333333%; + } + .col-md-pull-12 { + right: 100%; + } + .col-md-pull-11 { + right: 91.66666667%; + } + .col-md-pull-10 { + right: 83.33333333%; + } + .col-md-pull-9 { + right: 75%; + } + .col-md-pull-8 { + right: 66.66666667%; + } + .col-md-pull-7 { + right: 58.33333333%; + } + .col-md-pull-6 { + right: 50%; + } + .col-md-pull-5 { + right: 41.66666667%; + } + .col-md-pull-4 { + right: 33.33333333%; + } + .col-md-pull-3 { + right: 25%; + } + .col-md-pull-2 { + right: 16.66666667%; + } + .col-md-pull-1 { + right: 8.33333333%; + } + .col-md-pull-0 { + right: auto; + } + .col-md-push-12 { + left: 100%; + } + .col-md-push-11 { + left: 91.66666667%; + } + .col-md-push-10 { + left: 83.33333333%; + } + .col-md-push-9 { + left: 75%; + } + .col-md-push-8 { + left: 66.66666667%; + } + .col-md-push-7 { + left: 58.33333333%; + } + .col-md-push-6 { + left: 50%; + } + .col-md-push-5 { + left: 41.66666667%; + } + .col-md-push-4 { + left: 33.33333333%; + } + .col-md-push-3 { + left: 25%; + } + .col-md-push-2 { + left: 16.66666667%; + } + .col-md-push-1 { + left: 8.33333333%; + } + .col-md-push-0 { + left: auto; + } + .col-md-offset-12 { + margin-left: 100%; + } + .col-md-offset-11 { + margin-left: 91.66666667%; + } + .col-md-offset-10 { + margin-left: 83.33333333%; + } + .col-md-offset-9 { + margin-left: 75%; + } + .col-md-offset-8 { + margin-left: 66.66666667%; + } + .col-md-offset-7 { + margin-left: 58.33333333%; + } + .col-md-offset-6 { + margin-left: 50%; + } + .col-md-offset-5 { + margin-left: 41.66666667%; + } + .col-md-offset-4 { + margin-left: 33.33333333%; + } + .col-md-offset-3 { + margin-left: 25%; + } + .col-md-offset-2 { + margin-left: 16.66666667%; + } + .col-md-offset-1 { + margin-left: 8.33333333%; + } + .col-md-offset-0 { + margin-left: 0; + } +} +@media (min-width: 1200px) { + .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12 { + float: left; + } + .col-lg-12 { + width: 100%; + } + .col-lg-11 { + width: 91.66666667%; + } + .col-lg-10 { + width: 83.33333333%; + } + .col-lg-9 { + width: 75%; + } + .col-lg-8 { + width: 66.66666667%; + } + .col-lg-7 { + width: 58.33333333%; + } + .col-lg-6 { + width: 50%; + } + .col-lg-5 { + width: 41.66666667%; + } + .col-lg-4 { + width: 33.33333333%; + } + .col-lg-3 { + width: 25%; + } + .col-lg-2 { + width: 16.66666667%; + } + .col-lg-1 { + width: 8.33333333%; + } + .col-lg-pull-12 { + right: 100%; + } + .col-lg-pull-11 { + right: 91.66666667%; + } + .col-lg-pull-10 { + right: 83.33333333%; + } + .col-lg-pull-9 { + right: 75%; + } + .col-lg-pull-8 { + right: 66.66666667%; + } + .col-lg-pull-7 { + right: 58.33333333%; + } + .col-lg-pull-6 { + right: 50%; + } + .col-lg-pull-5 { + right: 41.66666667%; + } + .col-lg-pull-4 { + right: 33.33333333%; + } + .col-lg-pull-3 { + right: 25%; + } + .col-lg-pull-2 { + right: 16.66666667%; + } + .col-lg-pull-1 { + right: 8.33333333%; + } + .col-lg-pull-0 { + right: auto; + } + .col-lg-push-12 { + left: 100%; + } + .col-lg-push-11 { + left: 91.66666667%; + } + .col-lg-push-10 { + left: 83.33333333%; + } + .col-lg-push-9 { + left: 75%; + } + .col-lg-push-8 { + left: 66.66666667%; + } + .col-lg-push-7 { + left: 58.33333333%; + } + .col-lg-push-6 { + left: 50%; + } + .col-lg-push-5 { + left: 41.66666667%; + } + .col-lg-push-4 { + left: 33.33333333%; + } + .col-lg-push-3 { + left: 25%; + } + .col-lg-push-2 { + left: 16.66666667%; + } + .col-lg-push-1 { + left: 8.33333333%; + } + .col-lg-push-0 { + left: auto; + } + .col-lg-offset-12 { + margin-left: 100%; + } + .col-lg-offset-11 { + margin-left: 91.66666667%; + } + .col-lg-offset-10 { + margin-left: 83.33333333%; + } + .col-lg-offset-9 { + margin-left: 75%; + } + .col-lg-offset-8 { + margin-left: 66.66666667%; + } + .col-lg-offset-7 { + margin-left: 58.33333333%; + } + .col-lg-offset-6 { + margin-left: 50%; + } + .col-lg-offset-5 { + margin-left: 41.66666667%; + } + .col-lg-offset-4 { + margin-left: 33.33333333%; + } + .col-lg-offset-3 { + margin-left: 25%; + } + .col-lg-offset-2 { + margin-left: 16.66666667%; + } + .col-lg-offset-1 { + margin-left: 8.33333333%; + } + .col-lg-offset-0 { + margin-left: 0; + } +} +table { + background-color: transparent; +} +caption { + padding-top: 8px; + padding-bottom: 8px; + color: #777; + text-align: left; +} +th { + text-align: left; +} +.table { + width: 100%; + max-width: 100%; + margin-bottom: 20px; +} +.table > thead > tr > th, +.table > tbody > tr > th, +.table > tfoot > tr > th, +.table > thead > tr > td, +.table > tbody > tr > td, +.table > tfoot > tr > td { + padding: 8px; + line-height: 1.42857143; + vertical-align: top; + border-top: 1px solid #ddd; +} +.table > thead > tr > th { + vertical-align: bottom; + border-bottom: 2px solid #ddd; +} +.table > caption + thead > tr:first-child > th, +.table > colgroup + thead > tr:first-child > th, +.table > thead:first-child > tr:first-child > th, +.table > caption + thead > tr:first-child > td, +.table > colgroup + thead > tr:first-child > td, +.table > thead:first-child > tr:first-child > td { + border-top: 0; +} +.table > tbody + tbody { + border-top: 2px solid #ddd; +} +.table .table { + background-color: #fff; +} +.table-condensed > thead > tr > th, +.table-condensed > tbody > tr > th, +.table-condensed > tfoot > tr > th, +.table-condensed > thead > tr > td, +.table-condensed > tbody > tr > td, +.table-condensed > tfoot > tr > td { + padding: 5px; +} +.table-bordered { + border: 1px solid #ddd; +} +.table-bordered > thead > tr > th, +.table-bordered > tbody > tr > th, +.table-bordered > tfoot > tr > th, +.table-bordered > thead > tr > td, +.table-bordered > tbody > tr > td, +.table-bordered > tfoot > tr > td { + border: 1px solid #ddd; +} +.table-bordered > thead > tr > th, +.table-bordered > thead > tr > td { + border-bottom-width: 2px; +} +.table-striped > tbody > tr:nth-of-type(odd) { + background-color: #f9f9f9; +} +.table-hover > tbody > tr:hover { + background-color: #f5f5f5; +} +table col[class*="col-"] { + position: static; + display: table-column; + float: none; +} +table td[class*="col-"], +table th[class*="col-"] { + position: static; + display: table-cell; + float: none; +} +.table > thead > tr > td.active, +.table > tbody > tr > td.active, +.table > tfoot > tr > td.active, +.table > thead > tr > th.active, +.table > tbody > tr > th.active, +.table > tfoot > tr > th.active, +.table > thead > tr.active > td, +.table > tbody > tr.active > td, +.table > tfoot > tr.active > td, +.table > thead > tr.active > th, +.table > tbody > tr.active > th, +.table > tfoot > tr.active > th { + background-color: #f5f5f5; +} +.table-hover > tbody > tr > td.active:hover, +.table-hover > tbody > tr > th.active:hover, +.table-hover > tbody > tr.active:hover > td, +.table-hover > tbody > tr:hover > .active, +.table-hover > tbody > tr.active:hover > th { + background-color: #e8e8e8; +} +.table > thead > tr > td.success, +.table > tbody > tr > td.success, +.table > tfoot > tr > td.success, +.table > thead > tr > th.success, +.table > tbody > tr > th.success, +.table > tfoot > tr > th.success, +.table > thead > tr.success > td, +.table > tbody > tr.success > td, +.table > tfoot > tr.success > td, +.table > thead > tr.success > th, +.table > tbody > tr.success > th, +.table > tfoot > tr.success > th { + background-color: #dff0d8; +} +.table-hover > tbody > tr > td.success:hover, +.table-hover > tbody > tr > th.success:hover, +.table-hover > tbody > tr.success:hover > td, +.table-hover > tbody > tr:hover > .success, +.table-hover > tbody > tr.success:hover > th { + background-color: #d0e9c6; +} +.table > thead > tr > td.info, +.table > tbody > tr > td.info, +.table > tfoot > tr > td.info, +.table > thead > tr > th.info, +.table > tbody > tr > th.info, +.table > tfoot > tr > th.info, +.table > thead > tr.info > td, +.table > tbody > tr.info > td, +.table > tfoot > tr.info > td, +.table > thead > tr.info > th, +.table > tbody > tr.info > th, +.table > tfoot > tr.info > th { + background-color: #d9edf7; +} +.table-hover > tbody > tr > td.info:hover, +.table-hover > tbody > tr > th.info:hover, +.table-hover > tbody > tr.info:hover > td, +.table-hover > tbody > tr:hover > .info, +.table-hover > tbody > tr.info:hover > th { + background-color: #c4e3f3; +} +.table > thead > tr > td.warning, +.table > tbody > tr > td.warning, +.table > tfoot > tr > td.warning, +.table > thead > tr > th.warning, +.table > tbody > tr > th.warning, +.table > tfoot > tr > th.warning, +.table > thead > tr.warning > td, +.table > tbody > tr.warning > td, +.table > tfoot > tr.warning > td, +.table > thead > tr.warning > th, +.table > tbody > tr.warning > th, +.table > tfoot > tr.warning > th { + background-color: #fcf8e3; +} +.table-hover > tbody > tr > td.warning:hover, +.table-hover > tbody > tr > th.warning:hover, +.table-hover > tbody > tr.warning:hover > td, +.table-hover > tbody > tr:hover > .warning, +.table-hover > tbody > tr.warning:hover > th { + background-color: #faf2cc; +} +.table > thead > tr > td.danger, +.table > tbody > tr > td.danger, +.table > tfoot > tr > td.danger, +.table > thead > tr > th.danger, +.table > tbody > tr > th.danger, +.table > tfoot > tr > th.danger, +.table > thead > tr.danger > td, +.table > tbody > tr.danger > td, +.table > tfoot > tr.danger > td, +.table > thead > tr.danger > th, +.table > tbody > tr.danger > th, +.table > tfoot > tr.danger > th { + background-color: #f2dede; +} +.table-hover > tbody > tr > td.danger:hover, +.table-hover > tbody > tr > th.danger:hover, +.table-hover > tbody > tr.danger:hover > td, +.table-hover > tbody > tr:hover > .danger, +.table-hover > tbody > tr.danger:hover > th { + background-color: #ebcccc; +} +.table-responsive { + min-height: .01%; + overflow-x: auto; +} +@media screen and (max-width: 767px) { + .table-responsive { + width: 100%; + margin-bottom: 15px; + overflow-y: hidden; + -ms-overflow-style: -ms-autohiding-scrollbar; + border: 1px solid #ddd; + } + .table-responsive > .table { + margin-bottom: 0; + } + .table-responsive > .table > thead > tr > th, + .table-responsive > .table > tbody > tr > th, + .table-responsive > .table > tfoot > tr > th, + .table-responsive > .table > thead > tr > td, + .table-responsive > .table > tbody > tr > td, + .table-responsive > .table > tfoot > tr > td { + white-space: nowrap; + } + .table-responsive > .table-bordered { + border: 0; + } + .table-responsive > .table-bordered > thead > tr > th:first-child, + .table-responsive > .table-bordered > tbody > tr > th:first-child, + .table-responsive > .table-bordered > tfoot > tr > th:first-child, + .table-responsive > .table-bordered > thead > tr > td:first-child, + .table-responsive > .table-bordered > tbody > tr > td:first-child, + .table-responsive > .table-bordered > tfoot > tr > td:first-child { + border-left: 0; + } + .table-responsive > .table-bordered > thead > tr > th:last-child, + .table-responsive > .table-bordered > tbody > tr > th:last-child, + .table-responsive > .table-bordered > tfoot > tr > th:last-child, + .table-responsive > .table-bordered > thead > tr > td:last-child, + .table-responsive > .table-bordered > tbody > tr > td:last-child, + .table-responsive > .table-bordered > tfoot > tr > td:last-child { + border-right: 0; + } + .table-responsive > .table-bordered > tbody > tr:last-child > th, + .table-responsive > .table-bordered > tfoot > tr:last-child > th, + .table-responsive > .table-bordered > tbody > tr:last-child > td, + .table-responsive > .table-bordered > tfoot > tr:last-child > td { + border-bottom: 0; + } +} +fieldset { + min-width: 0; + padding: 0; + margin: 0; + border: 0; +} +legend { + display: block; + width: 100%; + padding: 0; + margin-bottom: 20px; + font-size: 21px; + line-height: inherit; + color: #333; + border: 0; + border-bottom: 1px solid #e5e5e5; +} +label { + display: inline-block; + max-width: 100%; + margin-bottom: 5px; + font-weight: bold; +} +input[type="search"] { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +input[type="radio"], +input[type="checkbox"] { + margin: 4px 0 0; + margin-top: 1px \9; + line-height: normal; +} +input[type="file"] { + display: block; +} +input[type="range"] { + display: block; + width: 100%; +} +select[multiple], +select[size] { + height: auto; +} +input[type="file"]:focus, +input[type="radio"]:focus, +input[type="checkbox"]:focus { + outline: thin dotted; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} +output { + display: block; + padding-top: 7px; + font-size: 14px; + line-height: 1.42857143; + color: #555; +} +.form-control { + display: block; + width: 100%; + height: 34px; + padding: 6px 12px; + font-size: 14px; + line-height: 1.42857143; + color: #555; + background-color: #fff; + background-image: none; + border: 1px solid #ccc; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); + -webkit-transition: border-color ease-in-out .15s, -webkit-box-shadow ease-in-out .15s; + -o-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; + transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; +} +.form-control:focus { + border-color: #66afe9; + outline: 0; + -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, .6); + box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, .6); +} +.form-control::-moz-placeholder { + color: #999; + opacity: 1; +} +.form-control:-ms-input-placeholder { + color: #999; +} +.form-control::-webkit-input-placeholder { + color: #999; +} +.form-control[disabled], +.form-control[readonly], +fieldset[disabled] .form-control { + background-color: #eee; + opacity: 1; +} +.form-control[disabled], +fieldset[disabled] .form-control { + cursor: not-allowed; +} +textarea.form-control { + height: auto; +} +input[type="search"] { + -webkit-appearance: none; +} +@media screen and (-webkit-min-device-pixel-ratio: 0) { + input[type="date"], + input[type="time"], + input[type="datetime-local"], + input[type="month"] { + line-height: 34px; + } + input[type="date"].input-sm, + input[type="time"].input-sm, + input[type="datetime-local"].input-sm, + input[type="month"].input-sm, + .input-group-sm input[type="date"], + .input-group-sm input[type="time"], + .input-group-sm input[type="datetime-local"], + .input-group-sm input[type="month"] { + line-height: 30px; + } + input[type="date"].input-lg, + input[type="time"].input-lg, + input[type="datetime-local"].input-lg, + input[type="month"].input-lg, + .input-group-lg input[type="date"], + .input-group-lg input[type="time"], + .input-group-lg input[type="datetime-local"], + .input-group-lg input[type="month"] { + line-height: 46px; + } +} +.form-group { + margin-bottom: 15px; +} +.radio, +.checkbox { + position: relative; + display: block; + margin-top: 10px; + margin-bottom: 10px; +} +.radio label, +.checkbox label { + min-height: 20px; + padding-left: 20px; + margin-bottom: 0; + font-weight: normal; + cursor: pointer; +} +.radio input[type="radio"], +.radio-inline input[type="radio"], +.checkbox input[type="checkbox"], +.checkbox-inline input[type="checkbox"] { + position: absolute; + margin-top: 4px \9; + margin-left: -20px; +} +.radio + .radio, +.checkbox + .checkbox { + margin-top: -5px; +} +.radio-inline, +.checkbox-inline { + position: relative; + display: inline-block; + padding-left: 20px; + margin-bottom: 0; + font-weight: normal; + vertical-align: middle; + cursor: pointer; +} +.radio-inline + .radio-inline, +.checkbox-inline + .checkbox-inline { + margin-top: 0; + margin-left: 10px; +} +input[type="radio"][disabled], +input[type="checkbox"][disabled], +input[type="radio"].disabled, +input[type="checkbox"].disabled, +fieldset[disabled] input[type="radio"], +fieldset[disabled] input[type="checkbox"] { + cursor: not-allowed; +} +.radio-inline.disabled, +.checkbox-inline.disabled, +fieldset[disabled] .radio-inline, +fieldset[disabled] .checkbox-inline { + cursor: not-allowed; +} +.radio.disabled label, +.checkbox.disabled label, +fieldset[disabled] .radio label, +fieldset[disabled] .checkbox label { + cursor: not-allowed; +} +.form-control-static { + min-height: 34px; + padding-top: 7px; + padding-bottom: 7px; + margin-bottom: 0; +} +.form-control-static.input-lg, +.form-control-static.input-sm { + padding-right: 0; + padding-left: 0; +} +.input-sm { + height: 30px; + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +select.input-sm { + height: 30px; + line-height: 30px; +} +textarea.input-sm, +select[multiple].input-sm { + height: auto; +} +.form-group-sm .form-control { + height: 30px; + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +select.form-group-sm .form-control { + height: 30px; + line-height: 30px; +} +textarea.form-group-sm .form-control, +select[multiple].form-group-sm .form-control { + height: auto; +} +.form-group-sm .form-control-static { + height: 30px; + min-height: 32px; + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; +} +.input-lg { + height: 46px; + padding: 10px 16px; + font-size: 18px; + line-height: 1.3333333; + border-radius: 6px; +} +select.input-lg { + height: 46px; + line-height: 46px; +} +textarea.input-lg, +select[multiple].input-lg { + height: auto; +} +.form-group-lg .form-control { + height: 46px; + padding: 10px 16px; + font-size: 18px; + line-height: 1.3333333; + border-radius: 6px; +} +select.form-group-lg .form-control { + height: 46px; + line-height: 46px; +} +textarea.form-group-lg .form-control, +select[multiple].form-group-lg .form-control { + height: auto; +} +.form-group-lg .form-control-static { + height: 46px; + min-height: 38px; + padding: 10px 16px; + font-size: 18px; + line-height: 1.3333333; +} +.has-feedback { + position: relative; +} +.has-feedback .form-control { + padding-right: 42.5px; +} +.form-control-feedback { + position: absolute; + top: 0; + right: 0; + z-index: 2; + display: block; + width: 34px; + height: 34px; + line-height: 34px; + text-align: center; + pointer-events: none; +} +.input-lg + .form-control-feedback { + width: 46px; + height: 46px; + line-height: 46px; +} +.input-sm + .form-control-feedback { + width: 30px; + height: 30px; + line-height: 30px; +} +.has-success .help-block, +.has-success .control-label, +.has-success .radio, +.has-success .checkbox, +.has-success .radio-inline, +.has-success .checkbox-inline, +.has-success.radio label, +.has-success.checkbox label, +.has-success.radio-inline label, +.has-success.checkbox-inline label { + color: #3c763d; +} +.has-success .form-control { + border-color: #3c763d; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); +} +.has-success .form-control:focus { + border-color: #2b542c; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #67b168; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #67b168; +} +.has-success .input-group-addon { + color: #3c763d; + background-color: #dff0d8; + border-color: #3c763d; +} +.has-success .form-control-feedback { + color: #3c763d; +} +.has-warning .help-block, +.has-warning .control-label, +.has-warning .radio, +.has-warning .checkbox, +.has-warning .radio-inline, +.has-warning .checkbox-inline, +.has-warning.radio label, +.has-warning.checkbox label, +.has-warning.radio-inline label, +.has-warning.checkbox-inline label { + color: #8a6d3b; +} +.has-warning .form-control { + border-color: #8a6d3b; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); +} +.has-warning .form-control:focus { + border-color: #66512c; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #c0a16b; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #c0a16b; +} +.has-warning .input-group-addon { + color: #8a6d3b; + background-color: #fcf8e3; + border-color: #8a6d3b; +} +.has-warning .form-control-feedback { + color: #8a6d3b; +} +.has-error .help-block, +.has-error .control-label, +.has-error .radio, +.has-error .checkbox, +.has-error .radio-inline, +.has-error .checkbox-inline, +.has-error.radio label, +.has-error.checkbox label, +.has-error.radio-inline label, +.has-error.checkbox-inline label { + color: #a94442; +} +.has-error .form-control { + border-color: #a94442; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); +} +.has-error .form-control:focus { + border-color: #843534; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #ce8483; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #ce8483; +} +.has-error .input-group-addon { + color: #a94442; + background-color: #f2dede; + border-color: #a94442; +} +.has-error .form-control-feedback { + color: #a94442; +} +.has-feedback label ~ .form-control-feedback { + top: 25px; +} +.has-feedback label.sr-only ~ .form-control-feedback { + top: 0; +} +.help-block { + display: block; + margin-top: 5px; + margin-bottom: 10px; + color: #737373; +} +@media (min-width: 768px) { + .form-inline .form-group { + display: inline-block; + margin-bottom: 0; + vertical-align: middle; + } + .form-inline .form-control { + display: inline-block; + width: auto; + vertical-align: middle; + } + .form-inline .form-control-static { + display: inline-block; + } + .form-inline .input-group { + display: inline-table; + vertical-align: middle; + } + .form-inline .input-group .input-group-addon, + .form-inline .input-group .input-group-btn, + .form-inline .input-group .form-control { + width: auto; + } + .form-inline .input-group > .form-control { + width: 100%; + } + .form-inline .control-label { + margin-bottom: 0; + vertical-align: middle; + } + .form-inline .radio, + .form-inline .checkbox { + display: inline-block; + margin-top: 0; + margin-bottom: 0; + vertical-align: middle; + } + .form-inline .radio label, + .form-inline .checkbox label { + padding-left: 0; + } + .form-inline .radio input[type="radio"], + .form-inline .checkbox input[type="checkbox"] { + position: relative; + margin-left: 0; + } + .form-inline .has-feedback .form-control-feedback { + top: 0; + } +} +.form-horizontal .radio, +.form-horizontal .checkbox, +.form-horizontal .radio-inline, +.form-horizontal .checkbox-inline { + padding-top: 7px; + margin-top: 0; + margin-bottom: 0; +} +.form-horizontal .radio, +.form-horizontal .checkbox { + min-height: 27px; +} +.form-horizontal .form-group { + margin-right: -15px; + margin-left: -15px; +} +@media (min-width: 768px) { + .form-horizontal .control-label { + padding-top: 7px; + margin-bottom: 0; + text-align: right; + } +} +.form-horizontal .has-feedback .form-control-feedback { + right: 15px; +} +@media (min-width: 768px) { + .form-horizontal .form-group-lg .control-label { + padding-top: 14.333333px; + } +} +@media (min-width: 768px) { + .form-horizontal .form-group-sm .control-label { + padding-top: 6px; + } +} +.btn { + display: inline-block; + padding: 6px 12px; + margin-bottom: 0; + font-size: 14px; + font-weight: normal; + line-height: 1.42857143; + text-align: center; + white-space: nowrap; + vertical-align: middle; + -ms-touch-action: manipulation; + touch-action: manipulation; + cursor: pointer; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + background-image: none; + border: 1px solid transparent; + border-radius: 4px; +} +.btn:focus, +.btn:active:focus, +.btn.active:focus, +.btn.focus, +.btn:active.focus, +.btn.active.focus { + outline: thin dotted; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} +.btn:hover, +.btn:focus, +.btn.focus { + color: #333; + text-decoration: none; +} +.btn:active, +.btn.active { + background-image: none; + outline: 0; + -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); + box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); +} +.btn.disabled, +.btn[disabled], +fieldset[disabled] .btn { + pointer-events: none; + cursor: not-allowed; + filter: alpha(opacity=65); + -webkit-box-shadow: none; + box-shadow: none; + opacity: .65; +} +.btn-default { + color: #333; + background-color: #fff; + border-color: #ccc; +} +.btn-default:hover, +.btn-default:focus, +.btn-default.focus, +.btn-default:active, +.btn-default.active, +.open > .dropdown-toggle.btn-default { + color: #333; + background-color: #e6e6e6; + border-color: #adadad; +} +.btn-default:active, +.btn-default.active, +.open > .dropdown-toggle.btn-default { + background-image: none; +} +.btn-default.disabled, +.btn-default[disabled], +fieldset[disabled] .btn-default, +.btn-default.disabled:hover, +.btn-default[disabled]:hover, +fieldset[disabled] .btn-default:hover, +.btn-default.disabled:focus, +.btn-default[disabled]:focus, +fieldset[disabled] .btn-default:focus, +.btn-default.disabled.focus, +.btn-default[disabled].focus, +fieldset[disabled] .btn-default.focus, +.btn-default.disabled:active, +.btn-default[disabled]:active, +fieldset[disabled] .btn-default:active, +.btn-default.disabled.active, +.btn-default[disabled].active, +fieldset[disabled] .btn-default.active { + background-color: #fff; + border-color: #ccc; +} +.btn-default .badge { + color: #fff; + background-color: #333; +} +.btn-primary { + color: #fff; + background-color: #337ab7; + border-color: #2e6da4; +} +.btn-primary:hover, +.btn-primary:focus, +.btn-primary.focus, +.btn-primary:active, +.btn-primary.active, +.open > .dropdown-toggle.btn-primary { + color: #fff; + background-color: #286090; + border-color: #204d74; +} +.btn-primary:active, +.btn-primary.active, +.open > .dropdown-toggle.btn-primary { + background-image: none; +} +.btn-primary.disabled, +.btn-primary[disabled], +fieldset[disabled] .btn-primary, +.btn-primary.disabled:hover, +.btn-primary[disabled]:hover, +fieldset[disabled] .btn-primary:hover, +.btn-primary.disabled:focus, +.btn-primary[disabled]:focus, +fieldset[disabled] .btn-primary:focus, +.btn-primary.disabled.focus, +.btn-primary[disabled].focus, +fieldset[disabled] .btn-primary.focus, +.btn-primary.disabled:active, +.btn-primary[disabled]:active, +fieldset[disabled] .btn-primary:active, +.btn-primary.disabled.active, +.btn-primary[disabled].active, +fieldset[disabled] .btn-primary.active { + background-color: #337ab7; + border-color: #2e6da4; +} +.btn-primary .badge { + color: #337ab7; + background-color: #fff; +} +.btn-success { + color: #fff; + background-color: #5cb85c; + border-color: #4cae4c; +} +.btn-success:hover, +.btn-success:focus, +.btn-success.focus, +.btn-success:active, +.btn-success.active, +.open > .dropdown-toggle.btn-success { + color: #fff; + background-color: #449d44; + border-color: #398439; +} +.btn-success:active, +.btn-success.active, +.open > .dropdown-toggle.btn-success { + background-image: none; +} +.btn-success.disabled, +.btn-success[disabled], +fieldset[disabled] .btn-success, +.btn-success.disabled:hover, +.btn-success[disabled]:hover, +fieldset[disabled] .btn-success:hover, +.btn-success.disabled:focus, +.btn-success[disabled]:focus, +fieldset[disabled] .btn-success:focus, +.btn-success.disabled.focus, +.btn-success[disabled].focus, +fieldset[disabled] .btn-success.focus, +.btn-success.disabled:active, +.btn-success[disabled]:active, +fieldset[disabled] .btn-success:active, +.btn-success.disabled.active, +.btn-success[disabled].active, +fieldset[disabled] .btn-success.active { + background-color: #5cb85c; + border-color: #4cae4c; +} +.btn-success .badge { + color: #5cb85c; + background-color: #fff; +} +.btn-info { + color: #fff; + background-color: #5bc0de; + border-color: #46b8da; +} +.btn-info:hover, +.btn-info:focus, +.btn-info.focus, +.btn-info:active, +.btn-info.active, +.open > .dropdown-toggle.btn-info { + color: #fff; + background-color: #31b0d5; + border-color: #269abc; +} +.btn-info:active, +.btn-info.active, +.open > .dropdown-toggle.btn-info { + background-image: none; +} +.btn-info.disabled, +.btn-info[disabled], +fieldset[disabled] .btn-info, +.btn-info.disabled:hover, +.btn-info[disabled]:hover, +fieldset[disabled] .btn-info:hover, +.btn-info.disabled:focus, +.btn-info[disabled]:focus, +fieldset[disabled] .btn-info:focus, +.btn-info.disabled.focus, +.btn-info[disabled].focus, +fieldset[disabled] .btn-info.focus, +.btn-info.disabled:active, +.btn-info[disabled]:active, +fieldset[disabled] .btn-info:active, +.btn-info.disabled.active, +.btn-info[disabled].active, +fieldset[disabled] .btn-info.active { + background-color: #5bc0de; + border-color: #46b8da; +} +.btn-info .badge { + color: #5bc0de; + background-color: #fff; +} +.btn-warning { + color: #fff; + background-color: #f0ad4e; + border-color: #eea236; +} +.btn-warning:hover, +.btn-warning:focus, +.btn-warning.focus, +.btn-warning:active, +.btn-warning.active, +.open > .dropdown-toggle.btn-warning { + color: #fff; + background-color: #ec971f; + border-color: #d58512; +} +.btn-warning:active, +.btn-warning.active, +.open > .dropdown-toggle.btn-warning { + background-image: none; +} +.btn-warning.disabled, +.btn-warning[disabled], +fieldset[disabled] .btn-warning, +.btn-warning.disabled:hover, +.btn-warning[disabled]:hover, +fieldset[disabled] .btn-warning:hover, +.btn-warning.disabled:focus, +.btn-warning[disabled]:focus, +fieldset[disabled] .btn-warning:focus, +.btn-warning.disabled.focus, +.btn-warning[disabled].focus, +fieldset[disabled] .btn-warning.focus, +.btn-warning.disabled:active, +.btn-warning[disabled]:active, +fieldset[disabled] .btn-warning:active, +.btn-warning.disabled.active, +.btn-warning[disabled].active, +fieldset[disabled] .btn-warning.active { + background-color: #f0ad4e; + border-color: #eea236; +} +.btn-warning .badge { + color: #f0ad4e; + background-color: #fff; +} +.btn-danger { + color: #fff; + background-color: #d9534f; + border-color: #d43f3a; +} +.btn-danger:hover, +.btn-danger:focus, +.btn-danger.focus, +.btn-danger:active, +.btn-danger.active, +.open > .dropdown-toggle.btn-danger { + color: #fff; + background-color: #c9302c; + border-color: #ac2925; +} +.btn-danger:active, +.btn-danger.active, +.open > .dropdown-toggle.btn-danger { + background-image: none; +} +.btn-danger.disabled, +.btn-danger[disabled], +fieldset[disabled] .btn-danger, +.btn-danger.disabled:hover, +.btn-danger[disabled]:hover, +fieldset[disabled] .btn-danger:hover, +.btn-danger.disabled:focus, +.btn-danger[disabled]:focus, +fieldset[disabled] .btn-danger:focus, +.btn-danger.disabled.focus, +.btn-danger[disabled].focus, +fieldset[disabled] .btn-danger.focus, +.btn-danger.disabled:active, +.btn-danger[disabled]:active, +fieldset[disabled] .btn-danger:active, +.btn-danger.disabled.active, +.btn-danger[disabled].active, +fieldset[disabled] .btn-danger.active { + background-color: #d9534f; + border-color: #d43f3a; +} +.btn-danger .badge { + color: #d9534f; + background-color: #fff; +} +.btn-link { + font-weight: normal; + color: #337ab7; + border-radius: 0; +} +.btn-link, +.btn-link:active, +.btn-link.active, +.btn-link[disabled], +fieldset[disabled] .btn-link { + background-color: transparent; + -webkit-box-shadow: none; + box-shadow: none; +} +.btn-link, +.btn-link:hover, +.btn-link:focus, +.btn-link:active { + border-color: transparent; +} +.btn-link:hover, +.btn-link:focus { + color: #23527c; + text-decoration: underline; + background-color: transparent; +} +.btn-link[disabled]:hover, +fieldset[disabled] .btn-link:hover, +.btn-link[disabled]:focus, +fieldset[disabled] .btn-link:focus { + color: #777; + text-decoration: none; +} +.btn-lg, +.btn-group-lg > .btn { + padding: 10px 16px; + font-size: 18px; + line-height: 1.3333333; + border-radius: 6px; +} +.btn-sm, +.btn-group-sm > .btn { + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +.btn-xs, +.btn-group-xs > .btn { + padding: 1px 5px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +.btn-block { + display: block; + width: 100%; +} +.btn-block + .btn-block { + margin-top: 5px; +} +input[type="submit"].btn-block, +input[type="reset"].btn-block, +input[type="button"].btn-block { + width: 100%; +} +.fade { + opacity: 0; + -webkit-transition: opacity .15s linear; + -o-transition: opacity .15s linear; + transition: opacity .15s linear; +} +.fade.in { + opacity: 1; +} +.collapse { + display: none; +} +.collapse.in { + display: block; +} +tr.collapse.in { + display: table-row; +} +tbody.collapse.in { + display: table-row-group; +} +.collapsing { + position: relative; + height: 0; + overflow: hidden; + -webkit-transition-timing-function: ease; + -o-transition-timing-function: ease; + transition-timing-function: ease; + -webkit-transition-duration: .35s; + -o-transition-duration: .35s; + transition-duration: .35s; + -webkit-transition-property: height, visibility; + -o-transition-property: height, visibility; + transition-property: height, visibility; +} +.caret { + display: inline-block; + width: 0; + height: 0; + margin-left: 2px; + vertical-align: middle; + border-top: 4px dashed; + border-right: 4px solid transparent; + border-left: 4px solid transparent; +} +.dropup, +.dropdown { + position: relative; +} +.dropdown-toggle:focus { + outline: 0; +} +.dropdown-menu { + position: absolute; + top: 100%; + left: 0; + z-index: 1000; + display: none; + float: left; + min-width: 160px; + padding: 5px 0; + margin: 2px 0 0; + font-size: 14px; + text-align: left; + list-style: none; + background-color: #fff; + -webkit-background-clip: padding-box; + background-clip: padding-box; + border: 1px solid #ccc; + border: 1px solid rgba(0, 0, 0, .15); + border-radius: 4px; + -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, .175); + box-shadow: 0 6px 12px rgba(0, 0, 0, .175); +} +.dropdown-menu.pull-right { + right: 0; + left: auto; +} +.dropdown-menu .divider { + height: 1px; + margin: 9px 0; + overflow: hidden; + background-color: #e5e5e5; +} +.dropdown-menu > li > a { + display: block; + padding: 3px 20px; + clear: both; + font-weight: normal; + line-height: 1.42857143; + color: #333; + white-space: nowrap; +} +.dropdown-menu > li > a:hover, +.dropdown-menu > li > a:focus { + color: #262626; + text-decoration: none; + background-color: #f5f5f5; +} +.dropdown-menu > .active > a, +.dropdown-menu > .active > a:hover, +.dropdown-menu > .active > a:focus { + color: #fff; + text-decoration: none; + background-color: #337ab7; + outline: 0; +} +.dropdown-menu > .disabled > a, +.dropdown-menu > .disabled > a:hover, +.dropdown-menu > .disabled > a:focus { + color: #777; +} +.dropdown-menu > .disabled > a:hover, +.dropdown-menu > .disabled > a:focus { + text-decoration: none; + cursor: not-allowed; + background-color: transparent; + background-image: none; + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); +} +.open > .dropdown-menu { + display: block; +} +.open > a { + outline: 0; +} +.dropdown-menu-right { + right: 0; + left: auto; +} +.dropdown-menu-left { + right: auto; + left: 0; +} +.dropdown-header { + display: block; + padding: 3px 20px; + font-size: 12px; + line-height: 1.42857143; + color: #777; + white-space: nowrap; +} +.dropdown-backdrop { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 990; +} +.pull-right > .dropdown-menu { + right: 0; + left: auto; +} +.dropup .caret, +.navbar-fixed-bottom .dropdown .caret { + content: ""; + border-top: 0; + border-bottom: 4px solid; +} +.dropup .dropdown-menu, +.navbar-fixed-bottom .dropdown .dropdown-menu { + top: auto; + bottom: 100%; + margin-bottom: 2px; +} +@media (min-width: 768px) { + .navbar-right .dropdown-menu { + right: 0; + left: auto; + } + .navbar-right .dropdown-menu-left { + right: auto; + left: 0; + } +} +.btn-group, +.btn-group-vertical { + position: relative; + display: inline-block; + vertical-align: middle; +} +.btn-group > .btn, +.btn-group-vertical > .btn { + position: relative; + float: left; +} +.btn-group > .btn:hover, +.btn-group-vertical > .btn:hover, +.btn-group > .btn:focus, +.btn-group-vertical > .btn:focus, +.btn-group > .btn:active, +.btn-group-vertical > .btn:active, +.btn-group > .btn.active, +.btn-group-vertical > .btn.active { + z-index: 2; +} +.btn-group .btn + .btn, +.btn-group .btn + .btn-group, +.btn-group .btn-group + .btn, +.btn-group .btn-group + .btn-group { + margin-left: -1px; +} +.btn-toolbar { + margin-left: -5px; +} +.btn-toolbar .btn-group, +.btn-toolbar .input-group { + float: left; +} +.btn-toolbar > .btn, +.btn-toolbar > .btn-group, +.btn-toolbar > .input-group { + margin-left: 5px; +} +.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) { + border-radius: 0; +} +.btn-group > .btn:first-child { + margin-left: 0; +} +.btn-group > .btn:first-child:not(:last-child):not(.dropdown-toggle) { + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} +.btn-group > .btn:last-child:not(:first-child), +.btn-group > .dropdown-toggle:not(:first-child) { + border-top-left-radius: 0; + border-bottom-left-radius: 0; +} +.btn-group > .btn-group { + float: left; +} +.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn { + border-radius: 0; +} +.btn-group > .btn-group:first-child:not(:last-child) > .btn:last-child, +.btn-group > .btn-group:first-child:not(:last-child) > .dropdown-toggle { + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} +.btn-group > .btn-group:last-child:not(:first-child) > .btn:first-child { + border-top-left-radius: 0; + border-bottom-left-radius: 0; +} +.btn-group .dropdown-toggle:active, +.btn-group.open .dropdown-toggle { + outline: 0; +} +.btn-group > .btn + .dropdown-toggle { + padding-right: 8px; + padding-left: 8px; +} +.btn-group > .btn-lg + .dropdown-toggle { + padding-right: 12px; + padding-left: 12px; +} +.btn-group.open .dropdown-toggle { + -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); + box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); +} +.btn-group.open .dropdown-toggle.btn-link { + -webkit-box-shadow: none; + box-shadow: none; +} +.btn .caret { + margin-left: 0; +} +.btn-lg .caret { + border-width: 5px 5px 0; + border-bottom-width: 0; +} +.dropup .btn-lg .caret { + border-width: 0 5px 5px; +} +.btn-group-vertical > .btn, +.btn-group-vertical > .btn-group, +.btn-group-vertical > .btn-group > .btn { + display: block; + float: none; + width: 100%; + max-width: 100%; +} +.btn-group-vertical > .btn-group > .btn { + float: none; +} +.btn-group-vertical > .btn + .btn, +.btn-group-vertical > .btn + .btn-group, +.btn-group-vertical > .btn-group + .btn, +.btn-group-vertical > .btn-group + .btn-group { + margin-top: -1px; + margin-left: 0; +} +.btn-group-vertical > .btn:not(:first-child):not(:last-child) { + border-radius: 0; +} +.btn-group-vertical > .btn:first-child:not(:last-child) { + border-top-right-radius: 4px; + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} +.btn-group-vertical > .btn:last-child:not(:first-child) { + border-top-left-radius: 0; + border-top-right-radius: 0; + border-bottom-left-radius: 4px; +} +.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn { + border-radius: 0; +} +.btn-group-vertical > .btn-group:first-child:not(:last-child) > .btn:last-child, +.btn-group-vertical > .btn-group:first-child:not(:last-child) > .dropdown-toggle { + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} +.btn-group-vertical > .btn-group:last-child:not(:first-child) > .btn:first-child { + border-top-left-radius: 0; + border-top-right-radius: 0; +} +.btn-group-justified { + display: table; + width: 100%; + table-layout: fixed; + border-collapse: separate; +} +.btn-group-justified > .btn, +.btn-group-justified > .btn-group { + display: table-cell; + float: none; + width: 1%; +} +.btn-group-justified > .btn-group .btn { + width: 100%; +} +.btn-group-justified > .btn-group .dropdown-menu { + left: auto; +} +[data-toggle="buttons"] > .btn input[type="radio"], +[data-toggle="buttons"] > .btn-group > .btn input[type="radio"], +[data-toggle="buttons"] > .btn input[type="checkbox"], +[data-toggle="buttons"] > .btn-group > .btn input[type="checkbox"] { + position: absolute; + clip: rect(0, 0, 0, 0); + pointer-events: none; +} +.input-group { + position: relative; + display: table; + border-collapse: separate; +} +.input-group[class*="col-"] { + float: none; + padding-right: 0; + padding-left: 0; +} +.input-group .form-control { + position: relative; + z-index: 2; + float: left; + width: 100%; + margin-bottom: 0; +} +.input-group-lg > .form-control, +.input-group-lg > .input-group-addon, +.input-group-lg > .input-group-btn > .btn { + height: 46px; + padding: 10px 16px; + font-size: 18px; + line-height: 1.3333333; + border-radius: 6px; +} +select.input-group-lg > .form-control, +select.input-group-lg > .input-group-addon, +select.input-group-lg > .input-group-btn > .btn { + height: 46px; + line-height: 46px; +} +textarea.input-group-lg > .form-control, +textarea.input-group-lg > .input-group-addon, +textarea.input-group-lg > .input-group-btn > .btn, +select[multiple].input-group-lg > .form-control, +select[multiple].input-group-lg > .input-group-addon, +select[multiple].input-group-lg > .input-group-btn > .btn { + height: auto; +} +.input-group-sm > .form-control, +.input-group-sm > .input-group-addon, +.input-group-sm > .input-group-btn > .btn { + height: 30px; + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +select.input-group-sm > .form-control, +select.input-group-sm > .input-group-addon, +select.input-group-sm > .input-group-btn > .btn { + height: 30px; + line-height: 30px; +} +textarea.input-group-sm > .form-control, +textarea.input-group-sm > .input-group-addon, +textarea.input-group-sm > .input-group-btn > .btn, +select[multiple].input-group-sm > .form-control, +select[multiple].input-group-sm > .input-group-addon, +select[multiple].input-group-sm > .input-group-btn > .btn { + height: auto; +} +.input-group-addon, +.input-group-btn, +.input-group .form-control { + display: table-cell; +} +.input-group-addon:not(:first-child):not(:last-child), +.input-group-btn:not(:first-child):not(:last-child), +.input-group .form-control:not(:first-child):not(:last-child) { + border-radius: 0; +} +.input-group-addon, +.input-group-btn { + width: 1%; + white-space: nowrap; + vertical-align: middle; +} +.input-group-addon { + padding: 6px 12px; + font-size: 14px; + font-weight: normal; + line-height: 1; + color: #555; + text-align: center; + background-color: #eee; + border: 1px solid #ccc; + border-radius: 4px; +} +.input-group-addon.input-sm { + padding: 5px 10px; + font-size: 12px; + border-radius: 3px; +} +.input-group-addon.input-lg { + padding: 10px 16px; + font-size: 18px; + border-radius: 6px; +} +.input-group-addon input[type="radio"], +.input-group-addon input[type="checkbox"] { + margin-top: 0; +} +.input-group .form-control:first-child, +.input-group-addon:first-child, +.input-group-btn:first-child > .btn, +.input-group-btn:first-child > .btn-group > .btn, +.input-group-btn:first-child > .dropdown-toggle, +.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle), +.input-group-btn:last-child > .btn-group:not(:last-child) > .btn { + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} +.input-group-addon:first-child { + border-right: 0; +} +.input-group .form-control:last-child, +.input-group-addon:last-child, +.input-group-btn:last-child > .btn, +.input-group-btn:last-child > .btn-group > .btn, +.input-group-btn:last-child > .dropdown-toggle, +.input-group-btn:first-child > .btn:not(:first-child), +.input-group-btn:first-child > .btn-group:not(:first-child) > .btn { + border-top-left-radius: 0; + border-bottom-left-radius: 0; +} +.input-group-addon:last-child { + border-left: 0; +} +.input-group-btn { + position: relative; + font-size: 0; + white-space: nowrap; +} +.input-group-btn > .btn { + position: relative; +} +.input-group-btn > .btn + .btn { + margin-left: -1px; +} +.input-group-btn > .btn:hover, +.input-group-btn > .btn:focus, +.input-group-btn > .btn:active { + z-index: 2; +} +.input-group-btn:first-child > .btn, +.input-group-btn:first-child > .btn-group { + margin-right: -1px; +} +.input-group-btn:last-child > .btn, +.input-group-btn:last-child > .btn-group { + margin-left: -1px; +} +.nav { + padding-left: 0; + margin-bottom: 0; + list-style: none; +} +.nav > li { + position: relative; + display: block; +} +.nav > li > a { + position: relative; + display: block; + padding: 10px 15px; +} +.nav > li > a:hover, +.nav > li > a:focus { + text-decoration: none; + background-color: #eee; +} +.nav > li.disabled > a { + color: #777; +} +.nav > li.disabled > a:hover, +.nav > li.disabled > a:focus { + color: #777; + text-decoration: none; + cursor: not-allowed; + background-color: transparent; +} +.nav .open > a, +.nav .open > a:hover, +.nav .open > a:focus { + background-color: #eee; + border-color: #337ab7; +} +.nav .nav-divider { + height: 1px; + margin: 9px 0; + overflow: hidden; + background-color: #e5e5e5; +} +.nav > li > a > img { + max-width: none; +} +.nav-tabs { + border-bottom: 1px solid #ddd; +} +.nav-tabs > li { + float: left; + margin-bottom: -1px; +} +.nav-tabs > li > a { + margin-right: 2px; + line-height: 1.42857143; + border: 1px solid transparent; + border-radius: 4px 4px 0 0; +} +.nav-tabs > li > a:hover { + border-color: #eee #eee #ddd; +} +.nav-tabs > li.active > a, +.nav-tabs > li.active > a:hover, +.nav-tabs > li.active > a:focus { + color: #555; + cursor: default; + background-color: #fff; + border: 1px solid #ddd; + border-bottom-color: transparent; +} +.nav-tabs.nav-justified { + width: 100%; + border-bottom: 0; +} +.nav-tabs.nav-justified > li { + float: none; +} +.nav-tabs.nav-justified > li > a { + margin-bottom: 5px; + text-align: center; +} +.nav-tabs.nav-justified > .dropdown .dropdown-menu { + top: auto; + left: auto; +} +@media (min-width: 768px) { + .nav-tabs.nav-justified > li { + display: table-cell; + width: 1%; + } + .nav-tabs.nav-justified > li > a { + margin-bottom: 0; + } +} +.nav-tabs.nav-justified > li > a { + margin-right: 0; + border-radius: 4px; +} +.nav-tabs.nav-justified > .active > a, +.nav-tabs.nav-justified > .active > a:hover, +.nav-tabs.nav-justified > .active > a:focus { + border: 1px solid #ddd; +} +@media (min-width: 768px) { + .nav-tabs.nav-justified > li > a { + border-bottom: 1px solid #ddd; + border-radius: 4px 4px 0 0; + } + .nav-tabs.nav-justified > .active > a, + .nav-tabs.nav-justified > .active > a:hover, + .nav-tabs.nav-justified > .active > a:focus { + border-bottom-color: #fff; + } +} +.nav-pills > li { + float: left; +} +.nav-pills > li > a { + border-radius: 4px; +} +.nav-pills > li + li { + margin-left: 2px; +} +.nav-pills > li.active > a, +.nav-pills > li.active > a:hover, +.nav-pills > li.active > a:focus { + color: #fff; + background-color: #337ab7; +} +.nav-stacked > li { + float: none; +} +.nav-stacked > li + li { + margin-top: 2px; + margin-left: 0; +} +.nav-justified { + width: 100%; +} +.nav-justified > li { + float: none; +} +.nav-justified > li > a { + margin-bottom: 5px; + text-align: center; +} +.nav-justified > .dropdown .dropdown-menu { + top: auto; + left: auto; +} +@media (min-width: 768px) { + .nav-justified > li { + display: table-cell; + width: 1%; + } + .nav-justified > li > a { + margin-bottom: 0; + } +} +.nav-tabs-justified { + border-bottom: 0; +} +.nav-tabs-justified > li > a { + margin-right: 0; + border-radius: 4px; +} +.nav-tabs-justified > .active > a, +.nav-tabs-justified > .active > a:hover, +.nav-tabs-justified > .active > a:focus { + border: 1px solid #ddd; +} +@media (min-width: 768px) { + .nav-tabs-justified > li > a { + border-bottom: 1px solid #ddd; + border-radius: 4px 4px 0 0; + } + .nav-tabs-justified > .active > a, + .nav-tabs-justified > .active > a:hover, + .nav-tabs-justified > .active > a:focus { + border-bottom-color: #fff; + } +} +.tab-content > .tab-pane { + display: none; +} +.tab-content > .active { + display: block; +} +.nav-tabs .dropdown-menu { + margin-top: -1px; + border-top-left-radius: 0; + border-top-right-radius: 0; +} +.navbar { + position: relative; + min-height: 50px; + margin-bottom: 20px; + border: 1px solid transparent; +} +@media (min-width: 768px) { + .navbar { + border-radius: 4px; + } +} +@media (min-width: 768px) { + .navbar-header { + float: left; + } +} +.navbar-collapse { + padding-right: 15px; + padding-left: 15px; + overflow-x: visible; + -webkit-overflow-scrolling: touch; + border-top: 1px solid transparent; + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1); +} +.navbar-collapse.in { + overflow-y: auto; +} +@media (min-width: 768px) { + .navbar-collapse { + width: auto; + border-top: 0; + -webkit-box-shadow: none; + box-shadow: none; + } + .navbar-collapse.collapse { + display: block !important; + height: auto !important; + padding-bottom: 0; + overflow: visible !important; + } + .navbar-collapse.in { + overflow-y: visible; + } + .navbar-fixed-top .navbar-collapse, + .navbar-static-top .navbar-collapse, + .navbar-fixed-bottom .navbar-collapse { + padding-right: 0; + padding-left: 0; + } +} +.navbar-fixed-top .navbar-collapse, +.navbar-fixed-bottom .navbar-collapse { + max-height: 340px; +} +@media (max-device-width: 480px) and (orientation: landscape) { + .navbar-fixed-top .navbar-collapse, + .navbar-fixed-bottom .navbar-collapse { + max-height: 200px; + } +} +.container > .navbar-header, +.container-fluid > .navbar-header, +.container > .navbar-collapse, +.container-fluid > .navbar-collapse { + margin-right: -15px; + margin-left: -15px; +} +@media (min-width: 768px) { + .container > .navbar-header, + .container-fluid > .navbar-header, + .container > .navbar-collapse, + .container-fluid > .navbar-collapse { + margin-right: 0; + margin-left: 0; + } +} +.navbar-static-top { + z-index: 1000; + border-width: 0 0 1px; +} +@media (min-width: 768px) { + .navbar-static-top { + border-radius: 0; + } +} +.navbar-fixed-top, +.navbar-fixed-bottom { + position: fixed; + right: 0; + left: 0; + z-index: 1030; +} +@media (min-width: 768px) { + .navbar-fixed-top, + .navbar-fixed-bottom { + border-radius: 0; + } +} +.navbar-fixed-top { + top: 0; + border-width: 0 0 1px; +} +.navbar-fixed-bottom { + bottom: 0; + margin-bottom: 0; + border-width: 1px 0 0; +} +.navbar-brand { + float: left; + height: 50px; + padding: 15px 15px; + font-size: 18px; + line-height: 20px; +} +.navbar-brand:hover, +.navbar-brand:focus { + text-decoration: none; +} +.navbar-brand > img { + display: block; +} +@media (min-width: 768px) { + .navbar > .container .navbar-brand, + .navbar > .container-fluid .navbar-brand { + margin-left: -15px; + } +} +.navbar-toggle { + position: relative; + float: right; + padding: 9px 10px; + margin-top: 8px; + margin-right: 15px; + margin-bottom: 8px; + background-color: transparent; + background-image: none; + border: 1px solid transparent; + border-radius: 4px; +} +.navbar-toggle:focus { + outline: 0; +} +.navbar-toggle .icon-bar { + display: block; + width: 22px; + height: 2px; + border-radius: 1px; +} +.navbar-toggle .icon-bar + .icon-bar { + margin-top: 4px; +} +@media (min-width: 768px) { + .navbar-toggle { + display: none; + } +} +.navbar-nav { + margin: 7.5px -15px; +} +.navbar-nav > li > a { + padding-top: 10px; + padding-bottom: 10px; + line-height: 20px; +} +@media (max-width: 767px) { + .navbar-nav .open .dropdown-menu { + position: static; + float: none; + width: auto; + margin-top: 0; + background-color: transparent; + border: 0; + -webkit-box-shadow: none; + box-shadow: none; + } + .navbar-nav .open .dropdown-menu > li > a, + .navbar-nav .open .dropdown-menu .dropdown-header { + padding: 5px 15px 5px 25px; + } + .navbar-nav .open .dropdown-menu > li > a { + line-height: 20px; + } + .navbar-nav .open .dropdown-menu > li > a:hover, + .navbar-nav .open .dropdown-menu > li > a:focus { + background-image: none; + } +} +@media (min-width: 768px) { + .navbar-nav { + float: left; + margin: 0; + } + .navbar-nav > li { + float: left; + } + .navbar-nav > li > a { + padding-top: 15px; + padding-bottom: 15px; + } +} +.navbar-form { + padding: 10px 15px; + margin-top: 8px; + margin-right: -15px; + margin-bottom: 8px; + margin-left: -15px; + border-top: 1px solid transparent; + border-bottom: 1px solid transparent; + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1), 0 1px 0 rgba(255, 255, 255, .1); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1), 0 1px 0 rgba(255, 255, 255, .1); +} +@media (min-width: 768px) { + .navbar-form .form-group { + display: inline-block; + margin-bottom: 0; + vertical-align: middle; + } + .navbar-form .form-control { + display: inline-block; + width: auto; + vertical-align: middle; + } + .navbar-form .form-control-static { + display: inline-block; + } + .navbar-form .input-group { + display: inline-table; + vertical-align: middle; + } + .navbar-form .input-group .input-group-addon, + .navbar-form .input-group .input-group-btn, + .navbar-form .input-group .form-control { + width: auto; + } + .navbar-form .input-group > .form-control { + width: 100%; + } + .navbar-form .control-label { + margin-bottom: 0; + vertical-align: middle; + } + .navbar-form .radio, + .navbar-form .checkbox { + display: inline-block; + margin-top: 0; + margin-bottom: 0; + vertical-align: middle; + } + .navbar-form .radio label, + .navbar-form .checkbox label { + padding-left: 0; + } + .navbar-form .radio input[type="radio"], + .navbar-form .checkbox input[type="checkbox"] { + position: relative; + margin-left: 0; + } + .navbar-form .has-feedback .form-control-feedback { + top: 0; + } +} +@media (max-width: 767px) { + .navbar-form .form-group { + margin-bottom: 5px; + } + .navbar-form .form-group:last-child { + margin-bottom: 0; + } +} +@media (min-width: 768px) { + .navbar-form { + width: auto; + padding-top: 0; + padding-bottom: 0; + margin-right: 0; + margin-left: 0; + border: 0; + -webkit-box-shadow: none; + box-shadow: none; + } +} +.navbar-nav > li > .dropdown-menu { + margin-top: 0; + border-top-left-radius: 0; + border-top-right-radius: 0; +} +.navbar-fixed-bottom .navbar-nav > li > .dropdown-menu { + margin-bottom: 0; + border-top-left-radius: 4px; + border-top-right-radius: 4px; + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} +.navbar-btn { + margin-top: 8px; + margin-bottom: 8px; +} +.navbar-btn.btn-sm { + margin-top: 10px; + margin-bottom: 10px; +} +.navbar-btn.btn-xs { + margin-top: 14px; + margin-bottom: 14px; +} +.navbar-text { + margin-top: 15px; + margin-bottom: 15px; +} +@media (min-width: 768px) { + .navbar-text { + float: left; + margin-right: 15px; + margin-left: 15px; + } +} +@media (min-width: 768px) { + .navbar-left { + float: left !important; + } + .navbar-right { + float: right !important; + margin-right: -15px; + } + .navbar-right ~ .navbar-right { + margin-right: 0; + } +} +.navbar-default { + background-color: #f8f8f8; + border-color: #e7e7e7; +} +.navbar-default .navbar-brand { + color: #777; +} +.navbar-default .navbar-brand:hover, +.navbar-default .navbar-brand:focus { + color: #5e5e5e; + background-color: transparent; +} +.navbar-default .navbar-text { + color: #777; +} +.navbar-default .navbar-nav > li > a { + color: #777; +} +.navbar-default .navbar-nav > li > a:hover, +.navbar-default .navbar-nav > li > a:focus { + color: #333; + background-color: transparent; +} +.navbar-default .navbar-nav > .active > a, +.navbar-default .navbar-nav > .active > a:hover, +.navbar-default .navbar-nav > .active > a:focus { + color: #555; + background-color: #e7e7e7; +} +.navbar-default .navbar-nav > .disabled > a, +.navbar-default .navbar-nav > .disabled > a:hover, +.navbar-default .navbar-nav > .disabled > a:focus { + color: #ccc; + background-color: transparent; +} +.navbar-default .navbar-toggle { + border-color: #ddd; +} +.navbar-default .navbar-toggle:hover, +.navbar-default .navbar-toggle:focus { + background-color: #ddd; +} +.navbar-default .navbar-toggle .icon-bar { + background-color: #888; +} +.navbar-default .navbar-collapse, +.navbar-default .navbar-form { + border-color: #e7e7e7; +} +.navbar-default .navbar-nav > .open > a, +.navbar-default .navbar-nav > .open > a:hover, +.navbar-default .navbar-nav > .open > a:focus { + color: #555; + background-color: #e7e7e7; +} +@media (max-width: 767px) { + .navbar-default .navbar-nav .open .dropdown-menu > li > a { + color: #777; + } + .navbar-default .navbar-nav .open .dropdown-menu > li > a:hover, + .navbar-default .navbar-nav .open .dropdown-menu > li > a:focus { + color: #333; + background-color: transparent; + } + .navbar-default .navbar-nav .open .dropdown-menu > .active > a, + .navbar-default .navbar-nav .open .dropdown-menu > .active > a:hover, + .navbar-default .navbar-nav .open .dropdown-menu > .active > a:focus { + color: #555; + background-color: #e7e7e7; + } + .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a, + .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:hover, + .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:focus { + color: #ccc; + background-color: transparent; + } +} +.navbar-default .navbar-link { + color: #777; +} +.navbar-default .navbar-link:hover { + color: #333; +} +.navbar-default .btn-link { + color: #777; +} +.navbar-default .btn-link:hover, +.navbar-default .btn-link:focus { + color: #333; +} +.navbar-default .btn-link[disabled]:hover, +fieldset[disabled] .navbar-default .btn-link:hover, +.navbar-default .btn-link[disabled]:focus, +fieldset[disabled] .navbar-default .btn-link:focus { + color: #ccc; +} +.navbar-inverse { + background-color: #222; + border-color: #080808; +} +.navbar-inverse .navbar-brand { + color: #9d9d9d; +} +.navbar-inverse .navbar-brand:hover, +.navbar-inverse .navbar-brand:focus { + color: #fff; + background-color: transparent; +} +.navbar-inverse .navbar-text { + color: #9d9d9d; +} +.navbar-inverse .navbar-nav > li > a { + color: #9d9d9d; +} +.navbar-inverse .navbar-nav > li > a:hover, +.navbar-inverse .navbar-nav > li > a:focus { + color: #fff; + background-color: transparent; +} +.navbar-inverse .navbar-nav > .active > a, +.navbar-inverse .navbar-nav > .active > a:hover, +.navbar-inverse .navbar-nav > .active > a:focus { + color: #fff; + background-color: #080808; +} +.navbar-inverse .navbar-nav > .disabled > a, +.navbar-inverse .navbar-nav > .disabled > a:hover, +.navbar-inverse .navbar-nav > .disabled > a:focus { + color: #444; + background-color: transparent; +} +.navbar-inverse .navbar-toggle { + border-color: #333; +} +.navbar-inverse .navbar-toggle:hover, +.navbar-inverse .navbar-toggle:focus { + background-color: #333; +} +.navbar-inverse .navbar-toggle .icon-bar { + background-color: #fff; +} +.navbar-inverse .navbar-collapse, +.navbar-inverse .navbar-form { + border-color: #101010; +} +.navbar-inverse .navbar-nav > .open > a, +.navbar-inverse .navbar-nav > .open > a:hover, +.navbar-inverse .navbar-nav > .open > a:focus { + color: #fff; + background-color: #080808; +} +@media (max-width: 767px) { + .navbar-inverse .navbar-nav .open .dropdown-menu > .dropdown-header { + border-color: #080808; + } + .navbar-inverse .navbar-nav .open .dropdown-menu .divider { + background-color: #080808; + } + .navbar-inverse .navbar-nav .open .dropdown-menu > li > a { + color: #9d9d9d; + } + .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:hover, + .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:focus { + color: #fff; + background-color: transparent; + } + .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a, + .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:hover, + .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:focus { + color: #fff; + background-color: #080808; + } + .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a, + .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:hover, + .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:focus { + color: #444; + background-color: transparent; + } +} +.navbar-inverse .navbar-link { + color: #9d9d9d; +} +.navbar-inverse .navbar-link:hover { + color: #fff; +} +.navbar-inverse .btn-link { + color: #9d9d9d; +} +.navbar-inverse .btn-link:hover, +.navbar-inverse .btn-link:focus { + color: #fff; +} +.navbar-inverse .btn-link[disabled]:hover, +fieldset[disabled] .navbar-inverse .btn-link:hover, +.navbar-inverse .btn-link[disabled]:focus, +fieldset[disabled] .navbar-inverse .btn-link:focus { + color: #444; +} +.breadcrumb { + padding: 8px 15px; + margin-bottom: 20px; + list-style: none; + background-color: #f5f5f5; + border-radius: 4px; +} +.breadcrumb > li { + display: inline-block; +} +.breadcrumb > li + li:before { + padding: 0 5px; + color: #ccc; + content: "/\00a0"; +} +.breadcrumb > .active { + color: #777; +} +.pagination { + display: inline-block; + padding-left: 0; + margin: 20px 0; + border-radius: 4px; +} +.pagination > li { + display: inline; +} +.pagination > li > a, +.pagination > li > span { + position: relative; + float: left; + padding: 6px 12px; + margin-left: -1px; + line-height: 1.42857143; + color: #337ab7; + text-decoration: none; + background-color: #fff; + border: 1px solid #ddd; +} +.pagination > li:first-child > a, +.pagination > li:first-child > span { + margin-left: 0; + border-top-left-radius: 4px; + border-bottom-left-radius: 4px; +} +.pagination > li:last-child > a, +.pagination > li:last-child > span { + border-top-right-radius: 4px; + border-bottom-right-radius: 4px; +} +.pagination > li > a:hover, +.pagination > li > span:hover, +.pagination > li > a:focus, +.pagination > li > span:focus { + color: #23527c; + background-color: #eee; + border-color: #ddd; +} +.pagination > .active > a, +.pagination > .active > span, +.pagination > .active > a:hover, +.pagination > .active > span:hover, +.pagination > .active > a:focus, +.pagination > .active > span:focus { + z-index: 2; + color: #fff; + cursor: default; + background-color: #337ab7; + border-color: #337ab7; +} +.pagination > .disabled > span, +.pagination > .disabled > span:hover, +.pagination > .disabled > span:focus, +.pagination > .disabled > a, +.pagination > .disabled > a:hover, +.pagination > .disabled > a:focus { + color: #777; + cursor: not-allowed; + background-color: #fff; + border-color: #ddd; +} +.pagination-lg > li > a, +.pagination-lg > li > span { + padding: 10px 16px; + font-size: 18px; +} +.pagination-lg > li:first-child > a, +.pagination-lg > li:first-child > span { + border-top-left-radius: 6px; + border-bottom-left-radius: 6px; +} +.pagination-lg > li:last-child > a, +.pagination-lg > li:last-child > span { + border-top-right-radius: 6px; + border-bottom-right-radius: 6px; +} +.pagination-sm > li > a, +.pagination-sm > li > span { + padding: 5px 10px; + font-size: 12px; +} +.pagination-sm > li:first-child > a, +.pagination-sm > li:first-child > span { + border-top-left-radius: 3px; + border-bottom-left-radius: 3px; +} +.pagination-sm > li:last-child > a, +.pagination-sm > li:last-child > span { + border-top-right-radius: 3px; + border-bottom-right-radius: 3px; +} +.pager { + padding-left: 0; + margin: 20px 0; + text-align: center; + list-style: none; +} +.pager li { + display: inline; +} +.pager li > a, +.pager li > span { + display: inline-block; + padding: 5px 14px; + background-color: #fff; + border: 1px solid #ddd; + border-radius: 15px; +} +.pager li > a:hover, +.pager li > a:focus { + text-decoration: none; + background-color: #eee; +} +.pager .next > a, +.pager .next > span { + float: right; +} +.pager .previous > a, +.pager .previous > span { + float: left; +} +.pager .disabled > a, +.pager .disabled > a:hover, +.pager .disabled > a:focus, +.pager .disabled > span { + color: #777; + cursor: not-allowed; + background-color: #fff; +} +.label { + display: inline; + padding: .2em .6em .3em; + font-size: 75%; + font-weight: bold; + line-height: 1; + color: #fff; + text-align: center; + white-space: nowrap; + vertical-align: baseline; + border-radius: .25em; +} +a.label:hover, +a.label:focus { + color: #fff; + text-decoration: none; + cursor: pointer; +} +.label:empty { + display: none; +} +.btn .label { + position: relative; + top: -1px; +} +.label-default { + background-color: #777; +} +.label-default[href]:hover, +.label-default[href]:focus { + background-color: #5e5e5e; +} +.label-primary { + background-color: #337ab7; +} +.label-primary[href]:hover, +.label-primary[href]:focus { + background-color: #286090; +} +.label-success { + background-color: #5cb85c; +} +.label-success[href]:hover, +.label-success[href]:focus { + background-color: #449d44; +} +.label-info { + background-color: #5bc0de; +} +.label-info[href]:hover, +.label-info[href]:focus { + background-color: #31b0d5; +} +.label-warning { + background-color: #f0ad4e; +} +.label-warning[href]:hover, +.label-warning[href]:focus { + background-color: #ec971f; +} +.label-danger { + background-color: #d9534f; +} +.label-danger[href]:hover, +.label-danger[href]:focus { + background-color: #c9302c; +} +.badge { + display: inline-block; + min-width: 10px; + padding: 3px 7px; + font-size: 12px; + font-weight: bold; + line-height: 1; + color: #fff; + text-align: center; + white-space: nowrap; + vertical-align: baseline; + background-color: #777; + border-radius: 10px; +} +.badge:empty { + display: none; +} +.btn .badge { + position: relative; + top: -1px; +} +.btn-xs .badge, +.btn-group-xs > .btn .badge { + top: 0; + padding: 1px 5px; +} +a.badge:hover, +a.badge:focus { + color: #fff; + text-decoration: none; + cursor: pointer; +} +.list-group-item.active > .badge, +.nav-pills > .active > a > .badge { + color: #337ab7; + background-color: #fff; +} +.list-group-item > .badge { + float: right; +} +.list-group-item > .badge + .badge { + margin-right: 5px; +} +.nav-pills > li > a > .badge { + margin-left: 3px; +} +.jumbotron { + padding: 30px 15px; + margin-bottom: 30px; + color: inherit; + background-color: #eee; +} +.jumbotron h1, +.jumbotron .h1 { + color: inherit; +} +.jumbotron p { + margin-bottom: 15px; + font-size: 21px; + font-weight: 200; +} +.jumbotron > hr { + border-top-color: #d5d5d5; +} +.container .jumbotron, +.container-fluid .jumbotron { + border-radius: 6px; +} +.jumbotron .container { + max-width: 100%; +} +@media screen and (min-width: 768px) { + .jumbotron { + padding: 48px 0; + } + .container .jumbotron, + .container-fluid .jumbotron { + padding-right: 60px; + padding-left: 60px; + } + .jumbotron h1, + .jumbotron .h1 { + font-size: 63px; + } +} +.thumbnail { + display: block; + padding: 4px; + margin-bottom: 20px; + line-height: 1.42857143; + background-color: #fff; + border: 1px solid #ddd; + border-radius: 4px; + -webkit-transition: border .2s ease-in-out; + -o-transition: border .2s ease-in-out; + transition: border .2s ease-in-out; +} +.thumbnail > img, +.thumbnail a > img { + margin-right: auto; + margin-left: auto; +} +a.thumbnail:hover, +a.thumbnail:focus, +a.thumbnail.active { + border-color: #337ab7; +} +.thumbnail .caption { + padding: 9px; + color: #333; +} +.alert { + padding: 15px; + margin-bottom: 20px; + border: 1px solid transparent; + border-radius: 4px; +} +.alert h4 { + margin-top: 0; + color: inherit; +} +.alert .alert-link { + font-weight: bold; +} +.alert > p, +.alert > ul { + margin-bottom: 0; +} +.alert > p + p { + margin-top: 5px; +} +.alert-dismissable, +.alert-dismissible { + padding-right: 35px; +} +.alert-dismissable .close, +.alert-dismissible .close { + position: relative; + top: -2px; + right: -21px; + color: inherit; +} +.alert-success { + color: #3c763d; + background-color: #dff0d8; + border-color: #d6e9c6; +} +.alert-success hr { + border-top-color: #c9e2b3; +} +.alert-success .alert-link { + color: #2b542c; +} +.alert-info { + color: #31708f; + background-color: #d9edf7; + border-color: #bce8f1; +} +.alert-info hr { + border-top-color: #a6e1ec; +} +.alert-info .alert-link { + color: #245269; +} +.alert-warning { + color: #8a6d3b; + background-color: #fcf8e3; + border-color: #faebcc; +} +.alert-warning hr { + border-top-color: #f7e1b5; +} +.alert-warning .alert-link { + color: #66512c; +} +.alert-danger { + color: #a94442; + background-color: #f2dede; + border-color: #ebccd1; +} +.alert-danger hr { + border-top-color: #e4b9c0; +} +.alert-danger .alert-link { + color: #843534; +} +@-webkit-keyframes progress-bar-stripes { + from { + background-position: 40px 0; + } + to { + background-position: 0 0; + } +} +@-o-keyframes progress-bar-stripes { + from { + background-position: 40px 0; + } + to { + background-position: 0 0; + } +} +@keyframes progress-bar-stripes { + from { + background-position: 40px 0; + } + to { + background-position: 0 0; + } +} +.progress { + height: 20px; + margin-bottom: 20px; + overflow: hidden; + background-color: #f5f5f5; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, .1); + box-shadow: inset 0 1px 2px rgba(0, 0, 0, .1); +} +.progress-bar { + float: left; + width: 0; + height: 100%; + font-size: 12px; + line-height: 20px; + color: #fff; + text-align: center; + background-color: #337ab7; + -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .15); + box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .15); + -webkit-transition: width .6s ease; + -o-transition: width .6s ease; + transition: width .6s ease; +} +.progress-striped .progress-bar, +.progress-bar-striped { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + -webkit-background-size: 40px 40px; + background-size: 40px 40px; +} +.progress.active .progress-bar, +.progress-bar.active { + -webkit-animation: progress-bar-stripes 2s linear infinite; + -o-animation: progress-bar-stripes 2s linear infinite; + animation: progress-bar-stripes 2s linear infinite; +} +.progress-bar-success { + background-color: #5cb85c; +} +.progress-striped .progress-bar-success { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); +} +.progress-bar-info { + background-color: #5bc0de; +} +.progress-striped .progress-bar-info { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); +} +.progress-bar-warning { + background-color: #f0ad4e; +} +.progress-striped .progress-bar-warning { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); +} +.progress-bar-danger { + background-color: #d9534f; +} +.progress-striped .progress-bar-danger { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); +} +.media { + margin-top: 15px; +} +.media:first-child { + margin-top: 0; +} +.media, +.media-body { + overflow: hidden; + zoom: 1; +} +.media-body { + width: 10000px; +} +.media-object { + display: block; +} +.media-right, +.media > .pull-right { + padding-left: 10px; +} +.media-left, +.media > .pull-left { + padding-right: 10px; +} +.media-left, +.media-right, +.media-body { + display: table-cell; + vertical-align: top; +} +.media-middle { + vertical-align: middle; +} +.media-bottom { + vertical-align: bottom; +} +.media-heading { + margin-top: 0; + margin-bottom: 5px; +} +.media-list { + padding-left: 0; + list-style: none; +} +.list-group { + padding-left: 0; + margin-bottom: 20px; +} +.list-group-item { + position: relative; + display: block; + padding: 10px 15px; + margin-bottom: -1px; + background-color: #fff; + border: 1px solid #ddd; +} +.list-group-item:first-child { + border-top-left-radius: 4px; + border-top-right-radius: 4px; +} +.list-group-item:last-child { + margin-bottom: 0; + border-bottom-right-radius: 4px; + border-bottom-left-radius: 4px; +} +a.list-group-item { + color: #555; +} +a.list-group-item .list-group-item-heading { + color: #333; +} +a.list-group-item:hover, +a.list-group-item:focus { + color: #555; + text-decoration: none; + background-color: #f5f5f5; +} +.list-group-item.disabled, +.list-group-item.disabled:hover, +.list-group-item.disabled:focus { + color: #777; + cursor: not-allowed; + background-color: #eee; +} +.list-group-item.disabled .list-group-item-heading, +.list-group-item.disabled:hover .list-group-item-heading, +.list-group-item.disabled:focus .list-group-item-heading { + color: inherit; +} +.list-group-item.disabled .list-group-item-text, +.list-group-item.disabled:hover .list-group-item-text, +.list-group-item.disabled:focus .list-group-item-text { + color: #777; +} +.list-group-item.active, +.list-group-item.active:hover, +.list-group-item.active:focus { + z-index: 2; + color: #fff; + background-color: #337ab7; + border-color: #337ab7; +} +.list-group-item.active .list-group-item-heading, +.list-group-item.active:hover .list-group-item-heading, +.list-group-item.active:focus .list-group-item-heading, +.list-group-item.active .list-group-item-heading > small, +.list-group-item.active:hover .list-group-item-heading > small, +.list-group-item.active:focus .list-group-item-heading > small, +.list-group-item.active .list-group-item-heading > .small, +.list-group-item.active:hover .list-group-item-heading > .small, +.list-group-item.active:focus .list-group-item-heading > .small { + color: inherit; +} +.list-group-item.active .list-group-item-text, +.list-group-item.active:hover .list-group-item-text, +.list-group-item.active:focus .list-group-item-text { + color: #c7ddef; +} +.list-group-item-success { + color: #3c763d; + background-color: #dff0d8; +} +a.list-group-item-success { + color: #3c763d; +} +a.list-group-item-success .list-group-item-heading { + color: inherit; +} +a.list-group-item-success:hover, +a.list-group-item-success:focus { + color: #3c763d; + background-color: #d0e9c6; +} +a.list-group-item-success.active, +a.list-group-item-success.active:hover, +a.list-group-item-success.active:focus { + color: #fff; + background-color: #3c763d; + border-color: #3c763d; +} +.list-group-item-info { + color: #31708f; + background-color: #d9edf7; +} +a.list-group-item-info { + color: #31708f; +} +a.list-group-item-info .list-group-item-heading { + color: inherit; +} +a.list-group-item-info:hover, +a.list-group-item-info:focus { + color: #31708f; + background-color: #c4e3f3; +} +a.list-group-item-info.active, +a.list-group-item-info.active:hover, +a.list-group-item-info.active:focus { + color: #fff; + background-color: #31708f; + border-color: #31708f; +} +.list-group-item-warning { + color: #8a6d3b; + background-color: #fcf8e3; +} +a.list-group-item-warning { + color: #8a6d3b; +} +a.list-group-item-warning .list-group-item-heading { + color: inherit; +} +a.list-group-item-warning:hover, +a.list-group-item-warning:focus { + color: #8a6d3b; + background-color: #faf2cc; +} +a.list-group-item-warning.active, +a.list-group-item-warning.active:hover, +a.list-group-item-warning.active:focus { + color: #fff; + background-color: #8a6d3b; + border-color: #8a6d3b; +} +.list-group-item-danger { + color: #a94442; + background-color: #f2dede; +} +a.list-group-item-danger { + color: #a94442; +} +a.list-group-item-danger .list-group-item-heading { + color: inherit; +} +a.list-group-item-danger:hover, +a.list-group-item-danger:focus { + color: #a94442; + background-color: #ebcccc; +} +a.list-group-item-danger.active, +a.list-group-item-danger.active:hover, +a.list-group-item-danger.active:focus { + color: #fff; + background-color: #a94442; + border-color: #a94442; +} +.list-group-item-heading { + margin-top: 0; + margin-bottom: 5px; +} +.list-group-item-text { + margin-bottom: 0; + line-height: 1.3; +} +.panel { + margin-bottom: 20px; + background-color: #fff; + border: 1px solid transparent; + border-radius: 4px; + -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, .05); + box-shadow: 0 1px 1px rgba(0, 0, 0, .05); +} +.panel-body { + padding: 15px; +} +.panel-heading { + padding: 10px 15px; + border-bottom: 1px solid transparent; + border-top-left-radius: 3px; + border-top-right-radius: 3px; +} +.panel-heading > .dropdown .dropdown-toggle { + color: inherit; +} +.panel-title { + margin-top: 0; + margin-bottom: 0; + font-size: 16px; + color: inherit; +} +.panel-title > a, +.panel-title > small, +.panel-title > .small, +.panel-title > small > a, +.panel-title > .small > a { + color: inherit; +} +.panel-footer { + padding: 10px 15px; + background-color: #f5f5f5; + border-top: 1px solid #ddd; + border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px; +} +.panel > .list-group, +.panel > .panel-collapse > .list-group { + margin-bottom: 0; +} +.panel > .list-group .list-group-item, +.panel > .panel-collapse > .list-group .list-group-item { + border-width: 1px 0; + border-radius: 0; +} +.panel > .list-group:first-child .list-group-item:first-child, +.panel > .panel-collapse > .list-group:first-child .list-group-item:first-child { + border-top: 0; + border-top-left-radius: 3px; + border-top-right-radius: 3px; +} +.panel > .list-group:last-child .list-group-item:last-child, +.panel > .panel-collapse > .list-group:last-child .list-group-item:last-child { + border-bottom: 0; + border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px; +} +.panel-heading + .list-group .list-group-item:first-child { + border-top-width: 0; +} +.list-group + .panel-footer { + border-top-width: 0; +} +.panel > .table, +.panel > .table-responsive > .table, +.panel > .panel-collapse > .table { + margin-bottom: 0; +} +.panel > .table caption, +.panel > .table-responsive > .table caption, +.panel > .panel-collapse > .table caption { + padding-right: 15px; + padding-left: 15px; +} +.panel > .table:first-child, +.panel > .table-responsive:first-child > .table:first-child { + border-top-left-radius: 3px; + border-top-right-radius: 3px; +} +.panel > .table:first-child > thead:first-child > tr:first-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child, +.panel > .table:first-child > tbody:first-child > tr:first-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child { + border-top-left-radius: 3px; + border-top-right-radius: 3px; +} +.panel > .table:first-child > thead:first-child > tr:first-child td:first-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:first-child, +.panel > .table:first-child > tbody:first-child > tr:first-child td:first-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:first-child, +.panel > .table:first-child > thead:first-child > tr:first-child th:first-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:first-child, +.panel > .table:first-child > tbody:first-child > tr:first-child th:first-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:first-child { + border-top-left-radius: 3px; +} +.panel > .table:first-child > thead:first-child > tr:first-child td:last-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:last-child, +.panel > .table:first-child > tbody:first-child > tr:first-child td:last-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:last-child, +.panel > .table:first-child > thead:first-child > tr:first-child th:last-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:last-child, +.panel > .table:first-child > tbody:first-child > tr:first-child th:last-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:last-child { + border-top-right-radius: 3px; +} +.panel > .table:last-child, +.panel > .table-responsive:last-child > .table:last-child { + border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px; +} +.panel > .table:last-child > tbody:last-child > tr:last-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child { + border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px; +} +.panel > .table:last-child > tbody:last-child > tr:last-child td:first-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:first-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child td:first-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:first-child, +.panel > .table:last-child > tbody:last-child > tr:last-child th:first-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:first-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child th:first-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:first-child { + border-bottom-left-radius: 3px; +} +.panel > .table:last-child > tbody:last-child > tr:last-child td:last-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:last-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child td:last-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:last-child, +.panel > .table:last-child > tbody:last-child > tr:last-child th:last-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:last-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child th:last-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:last-child { + border-bottom-right-radius: 3px; +} +.panel > .panel-body + .table, +.panel > .panel-body + .table-responsive, +.panel > .table + .panel-body, +.panel > .table-responsive + .panel-body { + border-top: 1px solid #ddd; +} +.panel > .table > tbody:first-child > tr:first-child th, +.panel > .table > tbody:first-child > tr:first-child td { + border-top: 0; +} +.panel > .table-bordered, +.panel > .table-responsive > .table-bordered { + border: 0; +} +.panel > .table-bordered > thead > tr > th:first-child, +.panel > .table-responsive > .table-bordered > thead > tr > th:first-child, +.panel > .table-bordered > tbody > tr > th:first-child, +.panel > .table-responsive > .table-bordered > tbody > tr > th:first-child, +.panel > .table-bordered > tfoot > tr > th:first-child, +.panel > .table-responsive > .table-bordered > tfoot > tr > th:first-child, +.panel > .table-bordered > thead > tr > td:first-child, +.panel > .table-responsive > .table-bordered > thead > tr > td:first-child, +.panel > .table-bordered > tbody > tr > td:first-child, +.panel > .table-responsive > .table-bordered > tbody > tr > td:first-child, +.panel > .table-bordered > tfoot > tr > td:first-child, +.panel > .table-responsive > .table-bordered > tfoot > tr > td:first-child { + border-left: 0; +} +.panel > .table-bordered > thead > tr > th:last-child, +.panel > .table-responsive > .table-bordered > thead > tr > th:last-child, +.panel > .table-bordered > tbody > tr > th:last-child, +.panel > .table-responsive > .table-bordered > tbody > tr > th:last-child, +.panel > .table-bordered > tfoot > tr > th:last-child, +.panel > .table-responsive > .table-bordered > tfoot > tr > th:last-child, +.panel > .table-bordered > thead > tr > td:last-child, +.panel > .table-responsive > .table-bordered > thead > tr > td:last-child, +.panel > .table-bordered > tbody > tr > td:last-child, +.panel > .table-responsive > .table-bordered > tbody > tr > td:last-child, +.panel > .table-bordered > tfoot > tr > td:last-child, +.panel > .table-responsive > .table-bordered > tfoot > tr > td:last-child { + border-right: 0; +} +.panel > .table-bordered > thead > tr:first-child > td, +.panel > .table-responsive > .table-bordered > thead > tr:first-child > td, +.panel > .table-bordered > tbody > tr:first-child > td, +.panel > .table-responsive > .table-bordered > tbody > tr:first-child > td, +.panel > .table-bordered > thead > tr:first-child > th, +.panel > .table-responsive > .table-bordered > thead > tr:first-child > th, +.panel > .table-bordered > tbody > tr:first-child > th, +.panel > .table-responsive > .table-bordered > tbody > tr:first-child > th { + border-bottom: 0; +} +.panel > .table-bordered > tbody > tr:last-child > td, +.panel > .table-responsive > .table-bordered > tbody > tr:last-child > td, +.panel > .table-bordered > tfoot > tr:last-child > td, +.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > td, +.panel > .table-bordered > tbody > tr:last-child > th, +.panel > .table-responsive > .table-bordered > tbody > tr:last-child > th, +.panel > .table-bordered > tfoot > tr:last-child > th, +.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > th { + border-bottom: 0; +} +.panel > .table-responsive { + margin-bottom: 0; + border: 0; +} +.panel-group { + margin-bottom: 20px; +} +.panel-group .panel { + margin-bottom: 0; + border-radius: 4px; +} +.panel-group .panel + .panel { + margin-top: 5px; +} +.panel-group .panel-heading { + border-bottom: 0; +} +.panel-group .panel-heading + .panel-collapse > .panel-body, +.panel-group .panel-heading + .panel-collapse > .list-group { + border-top: 1px solid #ddd; +} +.panel-group .panel-footer { + border-top: 0; +} +.panel-group .panel-footer + .panel-collapse .panel-body { + border-bottom: 1px solid #ddd; +} +.panel-default { + border-color: #ddd; +} +.panel-default > .panel-heading { + color: #333; + background-color: #f5f5f5; + border-color: #ddd; +} +.panel-default > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #ddd; +} +.panel-default > .panel-heading .badge { + color: #f5f5f5; + background-color: #333; +} +.panel-default > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #ddd; +} +.panel-primary { + border-color: #337ab7; +} +.panel-primary > .panel-heading { + color: #fff; + background-color: #337ab7; + border-color: #337ab7; +} +.panel-primary > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #337ab7; +} +.panel-primary > .panel-heading .badge { + color: #337ab7; + background-color: #fff; +} +.panel-primary > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #337ab7; +} +.panel-success { + border-color: #d6e9c6; +} +.panel-success > .panel-heading { + color: #3c763d; + background-color: #dff0d8; + border-color: #d6e9c6; +} +.panel-success > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #d6e9c6; +} +.panel-success > .panel-heading .badge { + color: #dff0d8; + background-color: #3c763d; +} +.panel-success > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #d6e9c6; +} +.panel-info { + border-color: #bce8f1; +} +.panel-info > .panel-heading { + color: #31708f; + background-color: #d9edf7; + border-color: #bce8f1; +} +.panel-info > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #bce8f1; +} +.panel-info > .panel-heading .badge { + color: #d9edf7; + background-color: #31708f; +} +.panel-info > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #bce8f1; +} +.panel-warning { + border-color: #faebcc; +} +.panel-warning > .panel-heading { + color: #8a6d3b; + background-color: #fcf8e3; + border-color: #faebcc; +} +.panel-warning > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #faebcc; +} +.panel-warning > .panel-heading .badge { + color: #fcf8e3; + background-color: #8a6d3b; +} +.panel-warning > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #faebcc; +} +.panel-danger { + border-color: #ebccd1; +} +.panel-danger > .panel-heading { + color: #a94442; + background-color: #f2dede; + border-color: #ebccd1; +} +.panel-danger > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #ebccd1; +} +.panel-danger > .panel-heading .badge { + color: #f2dede; + background-color: #a94442; +} +.panel-danger > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #ebccd1; +} +.embed-responsive { + position: relative; + display: block; + height: 0; + padding: 0; + overflow: hidden; +} +.embed-responsive .embed-responsive-item, +.embed-responsive iframe, +.embed-responsive embed, +.embed-responsive object, +.embed-responsive video { + position: absolute; + top: 0; + bottom: 0; + left: 0; + width: 100%; + height: 100%; + border: 0; +} +.embed-responsive-16by9 { + padding-bottom: 56.25%; +} +.embed-responsive-4by3 { + padding-bottom: 75%; +} +.well { + min-height: 20px; + padding: 19px; + margin-bottom: 20px; + background-color: #f5f5f5; + border: 1px solid #e3e3e3; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .05); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .05); +} +.well blockquote { + border-color: #ddd; + border-color: rgba(0, 0, 0, .15); +} +.well-lg { + padding: 24px; + border-radius: 6px; +} +.well-sm { + padding: 9px; + border-radius: 3px; +} +.close { + float: right; + font-size: 21px; + font-weight: bold; + line-height: 1; + color: #000; + text-shadow: 0 1px 0 #fff; + filter: alpha(opacity=20); + opacity: .2; +} +.close:hover, +.close:focus { + color: #000; + text-decoration: none; + cursor: pointer; + filter: alpha(opacity=50); + opacity: .5; +} +button.close { + -webkit-appearance: none; + padding: 0; + cursor: pointer; + background: transparent; + border: 0; +} +.modal-open { + overflow: hidden; +} +.modal { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 1050; + display: none; + overflow: hidden; + -webkit-overflow-scrolling: touch; + outline: 0; +} +.modal.fade .modal-dialog { + -webkit-transition: -webkit-transform .3s ease-out; + -o-transition: -o-transform .3s ease-out; + transition: transform .3s ease-out; + -webkit-transform: translate(0, -25%); + -ms-transform: translate(0, -25%); + -o-transform: translate(0, -25%); + transform: translate(0, -25%); +} +.modal.in .modal-dialog { + -webkit-transform: translate(0, 0); + -ms-transform: translate(0, 0); + -o-transform: translate(0, 0); + transform: translate(0, 0); +} +.modal-open .modal { + overflow-x: hidden; + overflow-y: auto; +} +.modal-dialog { + position: relative; + width: auto; + margin: 10px; +} +.modal-content { + position: relative; + background-color: #fff; + -webkit-background-clip: padding-box; + background-clip: padding-box; + border: 1px solid #999; + border: 1px solid rgba(0, 0, 0, .2); + border-radius: 6px; + outline: 0; + -webkit-box-shadow: 0 3px 9px rgba(0, 0, 0, .5); + box-shadow: 0 3px 9px rgba(0, 0, 0, .5); +} +.modal-backdrop { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 1040; + background-color: #000; +} +.modal-backdrop.fade { + filter: alpha(opacity=0); + opacity: 0; +} +.modal-backdrop.in { + filter: alpha(opacity=50); + opacity: .5; +} +.modal-header { + min-height: 16.42857143px; + padding: 15px; + border-bottom: 1px solid #e5e5e5; +} +.modal-header .close { + margin-top: -2px; +} +.modal-title { + margin: 0; + line-height: 1.42857143; +} +.modal-body { + position: relative; + padding: 15px; +} +.modal-footer { + padding: 15px; + text-align: right; + border-top: 1px solid #e5e5e5; +} +.modal-footer .btn + .btn { + margin-bottom: 0; + margin-left: 5px; +} +.modal-footer .btn-group .btn + .btn { + margin-left: -1px; +} +.modal-footer .btn-block + .btn-block { + margin-left: 0; +} +.modal-scrollbar-measure { + position: absolute; + top: -9999px; + width: 50px; + height: 50px; + overflow: scroll; +} +@media (min-width: 768px) { + .modal-dialog { + width: 600px; + margin: 30px auto; + } + .modal-content { + -webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, .5); + box-shadow: 0 5px 15px rgba(0, 0, 0, .5); + } + .modal-sm { + width: 300px; + } +} +@media (min-width: 992px) { + .modal-lg { + width: 900px; + } +} +.tooltip { + position: absolute; + z-index: 1070; + display: block; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 12px; + font-weight: normal; + line-height: 1.4; + filter: alpha(opacity=0); + opacity: 0; +} +.tooltip.in { + filter: alpha(opacity=90); + opacity: .9; +} +.tooltip.top { + padding: 5px 0; + margin-top: -3px; +} +.tooltip.right { + padding: 0 5px; + margin-left: 3px; +} +.tooltip.bottom { + padding: 5px 0; + margin-top: 3px; +} +.tooltip.left { + padding: 0 5px; + margin-left: -3px; +} +.tooltip-inner { + max-width: 200px; + padding: 3px 8px; + color: #fff; + text-align: center; + text-decoration: none; + background-color: #000; + border-radius: 4px; +} +.tooltip-arrow { + position: absolute; + width: 0; + height: 0; + border-color: transparent; + border-style: solid; +} +.tooltip.top .tooltip-arrow { + bottom: 0; + left: 50%; + margin-left: -5px; + border-width: 5px 5px 0; + border-top-color: #000; +} +.tooltip.top-left .tooltip-arrow { + right: 5px; + bottom: 0; + margin-bottom: -5px; + border-width: 5px 5px 0; + border-top-color: #000; +} +.tooltip.top-right .tooltip-arrow { + bottom: 0; + left: 5px; + margin-bottom: -5px; + border-width: 5px 5px 0; + border-top-color: #000; +} +.tooltip.right .tooltip-arrow { + top: 50%; + left: 0; + margin-top: -5px; + border-width: 5px 5px 5px 0; + border-right-color: #000; +} +.tooltip.left .tooltip-arrow { + top: 50%; + right: 0; + margin-top: -5px; + border-width: 5px 0 5px 5px; + border-left-color: #000; +} +.tooltip.bottom .tooltip-arrow { + top: 0; + left: 50%; + margin-left: -5px; + border-width: 0 5px 5px; + border-bottom-color: #000; +} +.tooltip.bottom-left .tooltip-arrow { + top: 0; + right: 5px; + margin-top: -5px; + border-width: 0 5px 5px; + border-bottom-color: #000; +} +.tooltip.bottom-right .tooltip-arrow { + top: 0; + left: 5px; + margin-top: -5px; + border-width: 0 5px 5px; + border-bottom-color: #000; +} +.popover { + position: absolute; + top: 0; + left: 0; + z-index: 1060; + display: none; + max-width: 276px; + padding: 1px; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 14px; + font-weight: normal; + line-height: 1.42857143; + text-align: left; + white-space: normal; + background-color: #fff; + -webkit-background-clip: padding-box; + background-clip: padding-box; + border: 1px solid #ccc; + border: 1px solid rgba(0, 0, 0, .2); + border-radius: 6px; + -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, .2); + box-shadow: 0 5px 10px rgba(0, 0, 0, .2); +} +.popover.top { + margin-top: -10px; +} +.popover.right { + margin-left: 10px; +} +.popover.bottom { + margin-top: 10px; +} +.popover.left { + margin-left: -10px; +} +.popover-title { + padding: 8px 14px; + margin: 0; + font-size: 14px; + background-color: #f7f7f7; + border-bottom: 1px solid #ebebeb; + border-radius: 5px 5px 0 0; +} +.popover-content { + padding: 9px 14px; +} +.popover > .arrow, +.popover > .arrow:after { + position: absolute; + display: block; + width: 0; + height: 0; + border-color: transparent; + border-style: solid; +} +.popover > .arrow { + border-width: 11px; +} +.popover > .arrow:after { + content: ""; + border-width: 10px; +} +.popover.top > .arrow { + bottom: -11px; + left: 50%; + margin-left: -11px; + border-top-color: #999; + border-top-color: rgba(0, 0, 0, .25); + border-bottom-width: 0; +} +.popover.top > .arrow:after { + bottom: 1px; + margin-left: -10px; + content: " "; + border-top-color: #fff; + border-bottom-width: 0; +} +.popover.right > .arrow { + top: 50%; + left: -11px; + margin-top: -11px; + border-right-color: #999; + border-right-color: rgba(0, 0, 0, .25); + border-left-width: 0; +} +.popover.right > .arrow:after { + bottom: -10px; + left: 1px; + content: " "; + border-right-color: #fff; + border-left-width: 0; +} +.popover.bottom > .arrow { + top: -11px; + left: 50%; + margin-left: -11px; + border-top-width: 0; + border-bottom-color: #999; + border-bottom-color: rgba(0, 0, 0, .25); +} +.popover.bottom > .arrow:after { + top: 1px; + margin-left: -10px; + content: " "; + border-top-width: 0; + border-bottom-color: #fff; +} +.popover.left > .arrow { + top: 50%; + right: -11px; + margin-top: -11px; + border-right-width: 0; + border-left-color: #999; + border-left-color: rgba(0, 0, 0, .25); +} +.popover.left > .arrow:after { + right: 1px; + bottom: -10px; + content: " "; + border-right-width: 0; + border-left-color: #fff; +} +.carousel { + position: relative; +} +.carousel-inner { + position: relative; + width: 100%; + overflow: hidden; +} +.carousel-inner > .item { + position: relative; + display: none; + -webkit-transition: .6s ease-in-out left; + -o-transition: .6s ease-in-out left; + transition: .6s ease-in-out left; +} +.carousel-inner > .item > img, +.carousel-inner > .item > a > img { + line-height: 1; +} +@media all and (transform-3d), (-webkit-transform-3d) { + .carousel-inner > .item { + -webkit-transition: -webkit-transform .6s ease-in-out; + -o-transition: -o-transform .6s ease-in-out; + transition: transform .6s ease-in-out; + + -webkit-backface-visibility: hidden; + backface-visibility: hidden; + -webkit-perspective: 1000; + perspective: 1000; + } + .carousel-inner > .item.next, + .carousel-inner > .item.active.right { + left: 0; + -webkit-transform: translate3d(100%, 0, 0); + transform: translate3d(100%, 0, 0); + } + .carousel-inner > .item.prev, + .carousel-inner > .item.active.left { + left: 0; + -webkit-transform: translate3d(-100%, 0, 0); + transform: translate3d(-100%, 0, 0); + } + .carousel-inner > .item.next.left, + .carousel-inner > .item.prev.right, + .carousel-inner > .item.active { + left: 0; + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } +} +.carousel-inner > .active, +.carousel-inner > .next, +.carousel-inner > .prev { + display: block; +} +.carousel-inner > .active { + left: 0; +} +.carousel-inner > .next, +.carousel-inner > .prev { + position: absolute; + top: 0; + width: 100%; +} +.carousel-inner > .next { + left: 100%; +} +.carousel-inner > .prev { + left: -100%; +} +.carousel-inner > .next.left, +.carousel-inner > .prev.right { + left: 0; +} +.carousel-inner > .active.left { + left: -100%; +} +.carousel-inner > .active.right { + left: 100%; +} +.carousel-control { + position: absolute; + top: 0; + bottom: 0; + left: 0; + width: 15%; + font-size: 20px; + color: #fff; + text-align: center; + text-shadow: 0 1px 2px rgba(0, 0, 0, .6); + filter: alpha(opacity=50); + opacity: .5; +} +.carousel-control.left { + background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, .5) 0%, rgba(0, 0, 0, .0001) 100%); + background-image: -o-linear-gradient(left, rgba(0, 0, 0, .5) 0%, rgba(0, 0, 0, .0001) 100%); + background-image: -webkit-gradient(linear, left top, right top, from(rgba(0, 0, 0, .5)), to(rgba(0, 0, 0, .0001))); + background-image: linear-gradient(to right, rgba(0, 0, 0, .5) 0%, rgba(0, 0, 0, .0001) 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1); + background-repeat: repeat-x; +} +.carousel-control.right { + right: 0; + left: auto; + background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, .0001) 0%, rgba(0, 0, 0, .5) 100%); + background-image: -o-linear-gradient(left, rgba(0, 0, 0, .0001) 0%, rgba(0, 0, 0, .5) 100%); + background-image: -webkit-gradient(linear, left top, right top, from(rgba(0, 0, 0, .0001)), to(rgba(0, 0, 0, .5))); + background-image: linear-gradient(to right, rgba(0, 0, 0, .0001) 0%, rgba(0, 0, 0, .5) 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1); + background-repeat: repeat-x; +} +.carousel-control:hover, +.carousel-control:focus { + color: #fff; + text-decoration: none; + filter: alpha(opacity=90); + outline: 0; + opacity: .9; +} +.carousel-control .icon-prev, +.carousel-control .icon-next, +.carousel-control .glyphicon-chevron-left, +.carousel-control .glyphicon-chevron-right { + position: absolute; + top: 50%; + z-index: 5; + display: inline-block; +} +.carousel-control .icon-prev, +.carousel-control .glyphicon-chevron-left { + left: 50%; + margin-left: -10px; +} +.carousel-control .icon-next, +.carousel-control .glyphicon-chevron-right { + right: 50%; + margin-right: -10px; +} +.carousel-control .icon-prev, +.carousel-control .icon-next { + width: 20px; + height: 20px; + margin-top: -10px; + font-family: serif; + line-height: 1; +} +.carousel-control .icon-prev:before { + content: '\2039'; +} +.carousel-control .icon-next:before { + content: '\203a'; +} +.carousel-indicators { + position: absolute; + bottom: 10px; + left: 50%; + z-index: 15; + width: 60%; + padding-left: 0; + margin-left: -30%; + text-align: center; + list-style: none; +} +.carousel-indicators li { + display: inline-block; + width: 10px; + height: 10px; + margin: 1px; + text-indent: -999px; + cursor: pointer; + background-color: #000 \9; + background-color: rgba(0, 0, 0, 0); + border: 1px solid #fff; + border-radius: 10px; +} +.carousel-indicators .active { + width: 12px; + height: 12px; + margin: 0; + background-color: #fff; +} +.carousel-caption { + position: absolute; + right: 15%; + bottom: 20px; + left: 15%; + z-index: 10; + padding-top: 20px; + padding-bottom: 20px; + color: #fff; + text-align: center; + text-shadow: 0 1px 2px rgba(0, 0, 0, .6); +} +.carousel-caption .btn { + text-shadow: none; +} +@media screen and (min-width: 768px) { + .carousel-control .glyphicon-chevron-left, + .carousel-control .glyphicon-chevron-right, + .carousel-control .icon-prev, + .carousel-control .icon-next { + width: 30px; + height: 30px; + margin-top: -15px; + font-size: 30px; + } + .carousel-control .glyphicon-chevron-left, + .carousel-control .icon-prev { + margin-left: -15px; + } + .carousel-control .glyphicon-chevron-right, + .carousel-control .icon-next { + margin-right: -15px; + } + .carousel-caption { + right: 20%; + left: 20%; + padding-bottom: 30px; + } + .carousel-indicators { + bottom: 20px; + } +} +.clearfix:before, +.clearfix:after, +.dl-horizontal dd:before, +.dl-horizontal dd:after, +.container:before, +.container:after, +.container-fluid:before, +.container-fluid:after, +.row:before, +.row:after, +.form-horizontal .form-group:before, +.form-horizontal .form-group:after, +.btn-toolbar:before, +.btn-toolbar:after, +.btn-group-vertical > .btn-group:before, +.btn-group-vertical > .btn-group:after, +.nav:before, +.nav:after, +.navbar:before, +.navbar:after, +.navbar-header:before, +.navbar-header:after, +.navbar-collapse:before, +.navbar-collapse:after, +.pager:before, +.pager:after, +.panel-body:before, +.panel-body:after, +.modal-footer:before, +.modal-footer:after { + display: table; + content: " "; +} +.clearfix:after, +.dl-horizontal dd:after, +.container:after, +.container-fluid:after, +.row:after, +.form-horizontal .form-group:after, +.btn-toolbar:after, +.btn-group-vertical > .btn-group:after, +.nav:after, +.navbar:after, +.navbar-header:after, +.navbar-collapse:after, +.pager:after, +.panel-body:after, +.modal-footer:after { + clear: both; +} +.center-block { + display: block; + margin-right: auto; + margin-left: auto; +} +.pull-right { + float: right !important; +} +.pull-left { + float: left !important; +} +.hide { + display: none !important; +} +.show { + display: block !important; +} +.invisible { + visibility: hidden; +} +.text-hide { + font: 0/0 a; + color: transparent; + text-shadow: none; + background-color: transparent; + border: 0; +} +.hidden { + display: none !important; +} +.affix { + position: fixed; +} +@-ms-viewport { + width: device-width; +} +.visible-xs, +.visible-sm, +.visible-md, +.visible-lg { + display: none !important; +} +.visible-xs-block, +.visible-xs-inline, +.visible-xs-inline-block, +.visible-sm-block, +.visible-sm-inline, +.visible-sm-inline-block, +.visible-md-block, +.visible-md-inline, +.visible-md-inline-block, +.visible-lg-block, +.visible-lg-inline, +.visible-lg-inline-block { + display: none !important; +} +@media (max-width: 767px) { + .visible-xs { + display: block !important; + } + table.visible-xs { + display: table; + } + tr.visible-xs { + display: table-row !important; + } + th.visible-xs, + td.visible-xs { + display: table-cell !important; + } +} +@media (max-width: 767px) { + .visible-xs-block { + display: block !important; + } +} +@media (max-width: 767px) { + .visible-xs-inline { + display: inline !important; + } +} +@media (max-width: 767px) { + .visible-xs-inline-block { + display: inline-block !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .visible-sm { + display: block !important; + } + table.visible-sm { + display: table; + } + tr.visible-sm { + display: table-row !important; + } + th.visible-sm, + td.visible-sm { + display: table-cell !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .visible-sm-block { + display: block !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .visible-sm-inline { + display: inline !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .visible-sm-inline-block { + display: inline-block !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .visible-md { + display: block !important; + } + table.visible-md { + display: table; + } + tr.visible-md { + display: table-row !important; + } + th.visible-md, + td.visible-md { + display: table-cell !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .visible-md-block { + display: block !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .visible-md-inline { + display: inline !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .visible-md-inline-block { + display: inline-block !important; + } +} +@media (min-width: 1200px) { + .visible-lg { + display: block !important; + } + table.visible-lg { + display: table; + } + tr.visible-lg { + display: table-row !important; + } + th.visible-lg, + td.visible-lg { + display: table-cell !important; + } +} +@media (min-width: 1200px) { + .visible-lg-block { + display: block !important; + } +} +@media (min-width: 1200px) { + .visible-lg-inline { + display: inline !important; + } +} +@media (min-width: 1200px) { + .visible-lg-inline-block { + display: inline-block !important; + } +} +@media (max-width: 767px) { + .hidden-xs { + display: none !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .hidden-sm { + display: none !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .hidden-md { + display: none !important; + } +} +@media (min-width: 1200px) { + .hidden-lg { + display: none !important; + } +} +.visible-print { + display: none !important; +} +@media print { + .visible-print { + display: block !important; + } + table.visible-print { + display: table; + } + tr.visible-print { + display: table-row !important; + } + th.visible-print, + td.visible-print { + display: table-cell !important; + } +} +.visible-print-block { + display: none !important; +} +@media print { + .visible-print-block { + display: block !important; + } +} +.visible-print-inline { + display: none !important; +} +@media print { + .visible-print-inline { + display: inline !important; + } +} +.visible-print-inline-block { + display: none !important; +} +@media print { + .visible-print-inline-block { + display: inline-block !important; + } +} +@media print { + .hidden-print { + display: none !important; + } +} +/*# sourceMappingURL=bootstrap.css.map */ diff --git "a/web/113 \347\231\275\350\214\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/css/css.css" "b/web/113 \347\231\275\350\214\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/css/css.css" new file mode 100644 index 00000000..cbfc4c38 --- /dev/null +++ "b/web/113 \347\231\275\350\214\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/css/css.css" @@ -0,0 +1,150 @@ +@charset 'UTF-8'; + +/* 公共样式*/ + +html, +body, +ul, +li, +ol, +dl, +dd, +dt, +p, +h1, +h2, +h3, +h4, +h5, +h6, +form, +fieldset, +legend, +img { + margin: 0; + padding: 0; +} + +body { + color: #000; + font: 0.15rem/0.25rem "Microsoft YaHei", "微软雅黑", "Arial Narrow", HELVETICA; + background: #fff +} + +fieldset, +img { + border: 0; +} + +img { + display: block; +} + +address, +caption, +cite, +code, +dfn, +th, +var { + font-style: normal; + font-weight: normal; +} + +ul, +ol { + list-style: none; +} + +h1, +h2, +h3, +h4, +h5, +h6 { + font-weight: normal; +} + +input { + padding-top: 0; + padding-bottom: 0; + font-family: 'SimSun', '微软雅黑'; +} + +input::-moz-focus-inner { + border: 0; + padding: 0; +} + +select, +input { + vertical-align: middle; +} + +select, +input, +textarea { + margin: 0; + outline-style: none; +} + +input, +textarea { + outline-style: none; + /* -webkit-appearance: none; */ +} + +textarea { + resize: none; +} + +table { + border-collapse: collapse; +} + +.clearfix:after { + content: '.'; + display: block; + height: 0; + visibility: hidden; + clear: both; +} + +.clearfix { + zoom: 1; +} + +.clearit { + clear: both; + height: 0; + font-size: 0; + overflow: hidden; +} + +.fl { + float: left; + _display: inline; +} + +.fr { + float: right; + _display: inline; +} + +a { + text-decoration: none; +} + +a:hover, +a:active, +a:focus, +a:visited { + text-decoration: underline; + text-decoration: none; +} + + +/* 公共样式结束*/ +#non { + display: none; +} diff --git "a/web/113 \347\231\275\350\214\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/css/daterangepicker.css" "b/web/113 \347\231\275\350\214\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/css/daterangepicker.css" new file mode 100644 index 00000000..c222647d --- /dev/null +++ "b/web/113 \347\231\275\350\214\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/css/daterangepicker.css" @@ -0,0 +1,415 @@ +.daterangepicker { + position: absolute; + color: inherit; + background: #fff; + border-radius: 0.05rem; + width: 3.475rem; + padding: 0.05rem; + margin-top: 0.0125rem; + top: 1.25rem; + left: 0.25rem; + /* Calendars */ +} + +.daterangepicker:before, +.daterangepicker:after { + position: absolute; + display: inline-block; + border-bottom-color: rgba(0, 0, 0, 0.2); + content: ''; +} + +.daterangepicker:before { + top: -0.0875rem; + border-right: 0.0875rem solid transparent; + border-left: 0.0875rem solid transparent; + border-bottom: 0.0875rem solid #ccc; +} + +.daterangepicker:after { + top: -0.075rem; + border-right: 0.075rem solid transparent; + border-bottom: 0.075rem solid #fff; + border-left: 0.075rem solid transparent; +} + +.daterangepicker.opensleft:before { + right: 0.1125rem; +} + +.daterangepicker.opensleft:after { + right: 0.125rem; +} + +.daterangepicker.openscenter:before { + left: 0; + right: 0; + width: 0; + margin-left: auto; + margin-right: auto; +} + +.daterangepicker.openscenter:after { + left: 0; + right: 0; + width: 0; + margin-left: auto; + margin-right: auto; +} + +.daterangepicker.opensright:before { + left: 0.1125rem; +} + +.daterangepicker.opensright:after { + left: 0.125rem; +} + +.daterangepicker.dropup { + margin-top: -0.0625rem; +} + +.daterangepicker.dropup:before { + top: initial; + bottom: -0.0875rem; + border-bottom: initial; + border-top: 0.0875rem solid #ccc; +} + +.daterangepicker.dropup:after { + top: initial; + bottom: -0.075rem; + border-bottom: initial; + border-top: 0.075rem solid #fff; +} + +.daterangepicker.dropdown-menu { + max-width: none; + z-index: 3001; +} + +.daterangepicker.single .ranges, +.daterangepicker.single .calendar { + float: none; +} + +.daterangepicker.show-calendar .calendar { + display: block; +} + +.daterangepicker .calendar { + display: none; + max-width: 3.375rem; + margin: 0.05rem; +} + +.daterangepicker .calendar.single .calendar-table { + border: none; +} + +.daterangepicker .calendar th, +.daterangepicker .calendar td { + white-space: nowrap; + text-align: center; + min-width: 0.4rem; +} + +.daterangepicker .calendar-table { + border: 0.0125rem solid #fff; + padding: 0.05rem; + border-radius: 0.05rem; + background: #fff; +} + +.daterangepicker table { + width: 100%; + margin: 0; +} + +.daterangepicker td, +.daterangepicker th { + text-align: center; + width: 0.25rem; + height: 0.25rem; + border-radius: 0.05rem; + border: 0.0125rem solid transparent; + white-space: nowrap; + cursor: pointer; +} + +.daterangepicker td.available:hover, +.daterangepicker th.available:hover { + background-color: #eee; + border-color: transparent; + color: inherit; +} + +.daterangepicker td.week, +.daterangepicker th.week { + font-size: 80%; + color: #ccc; +} + +.daterangepicker td.off, +.daterangepicker td.off.in-range, +.daterangepicker td.off.start-date, +.daterangepicker td.off.end-date { + background-color: #fff; + border-color: transparent; + color: #999; +} + +.daterangepicker td.in-range { + background-color: #ebf4f8; + border-color: transparent; + color: #000; + border-radius: 0; +} + +.daterangepicker td.start-date { + border-radius: 0.05rem 0 0 0.05rem; +} + +.daterangepicker td.end-date { + border-radius: 0 0.05rem 0.05rem 0; +} + +.daterangepicker td.start-date.end-date { + border-radius: 0.05rem; +} + +.daterangepicker td.active, +.daterangepicker td.active:hover { + background-color: #357ebd; + border-color: transparent; + color: #fff; +} + +.daterangepicker th.month { + width: auto; +} + +.daterangepicker td.disabled, +.daterangepicker option.disabled { + color: #999; + cursor: not-allowed; + text-decoration: line-through; +} + +.daterangepicker select.monthselect, +.daterangepicker select.yearselect { + font-size: 0.15rem; + padding: 0.0125rem; + height: auto; + margin: 0; + cursor: default; +} + +.daterangepicker select.monthselect { + margin-right: 2%; + width: 56%; +} + +.daterangepicker select.yearselect { + width: 40%; +} + +.daterangepicker select.hourselect, +.daterangepicker select.minuteselect, +.daterangepicker select.secondselect, +.daterangepicker select.ampmselect { + width: 0.625rem; + margin-bottom: 0; +} + +.daterangepicker .input-mini { + border: 0.0125rem solid #ccc; + border-radius: 0.05rem; + color: #555; + height: 0.375rem; + line-height: 0.375rem; + display: block; + vertical-align: middle; + margin: 0 0 0.0625rem 0; + padding: 0 0.075rem 0 0.35rem; + width: 100%; +} + +.daterangepicker .input-mini.active { + border: 0.0125rem solid #08c; + border-radius: 0.05rem; +} + +.daterangepicker .daterangepicker_input { + position: relative; +} + +.daterangepicker .daterangepicker_input i { + position: absolute; + left: 0.1rem; + top: 0.1rem; +} + +.daterangepicker.rtl .input-mini { + padding-right: 0.35rem; + padding-left: 0.075rem; +} + +.daterangepicker.rtl .daterangepicker_input i { + left: auto; + right: 0.1rem; +} + +.daterangepicker .calendar-time { + text-align: center; + margin: 0.0625rem auto; + line-height: 0.375rem; + position: relative; + padding-left: 0.35rem; +} + +.daterangepicker .calendar-time select.disabled { + color: #ccc; + cursor: not-allowed; +} + +.ranges { + font-size: 0.1375rem; + float: none; + margin: 0.05rem; + text-align: left; +} + +.ranges ul { + list-style: none; + margin: 0 auto; + padding: 0; + width: 100%; +} + +.ranges li { + font-size: 0.1625rem; + background: #f5f5f5; + border: 0.0125rem solid #f5f5f5; + border-radius: 0.05rem; + color: #08c; + padding: 0.0375rem 0.15rem; + margin-bottom: 0.1rem; + cursor: pointer; +} + +.ranges li:hover { + background: #08c; + border: 0.0125rem solid #08c; + color: #fff; +} + +.ranges li.active { + background: #08c; + border: 0.0125rem solid #08c; + color: #fff; +} + + +/* Larger Screen Styling */ + +@media (min-width: 7.05rem) { + .daterangepicker { + width: auto; + } + .daterangepicker .ranges ul { + width: 2rem; + } + .daterangepicker.single .ranges ul { + width: 100%; + } + .daterangepicker.single .calendar.left { + clear: none; + } + .daterangepicker.single.ltr .ranges, + .daterangepicker.single.ltr .calendar { + float: left; + } + .daterangepicker.single.rtl .ranges, + .daterangepicker.single.rtl .calendar { + float: right; + } + .daterangepicker.ltr { + direction: ltr; + text-align: left; + } + .daterangepicker.ltr .calendar.left { + clear: left; + margin-right: 0; + } + .daterangepicker.ltr .calendar.left .calendar-table { + border-right: none; + border-top-right-radius: 0; + border-bottom-right-radius: 0; + } + .daterangepicker.ltr .calendar.right { + margin-left: 0; + } + .daterangepicker.ltr .calendar.right .calendar-table { + border-left: none; + border-top-left-radius: 0; + border-bottom-left-radius: 0; + } + .daterangepicker.ltr .left .daterangepicker_input { + padding-right: 0.15rem; + } + .daterangepicker.ltr .calendar.left .calendar-table { + padding-right: 0.15rem; + } + .daterangepicker.ltr .ranges, + .daterangepicker.ltr .calendar { + float: left; + } + .daterangepicker.rtl { + direction: rtl; + text-align: right; + } + .daterangepicker.rtl .calendar.left { + clear: right; + margin-left: 0; + } + .daterangepicker.rtl .calendar.left .calendar-table { + border-left: none; + border-top-left-radius: 0; + border-bottom-left-radius: 0; + } + .daterangepicker.rtl .calendar.right { + margin-right: 0; + } + .daterangepicker.rtl .calendar.right .calendar-table { + border-right: none; + border-top-right-radius: 0; + border-bottom-right-radius: 0; + } + .daterangepicker.rtl .left .daterangepicker_input { + padding-left: 0.15rem; + } + .daterangepicker.rtl .calendar.left .calendar-table { + padding-left: 0.15rem; + } + .daterangepicker.rtl .ranges, + .daterangepicker.rtl .calendar { + text-align: right; + float: right; + } +} + +@media (min-width: 9.125rem) { + .daterangepicker .ranges { + width: auto; + } + .daterangepicker.ltr .ranges { + float: left; + } + .daterangepicker.rtl .ranges { + float: right; + } + .daterangepicker .calendar.left { + clear: none !important; + } +} \ No newline at end of file diff --git "a/web/113 \347\231\275\350\214\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/css/index2.css" "b/web/113 \347\231\275\350\214\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/css/index2.css" new file mode 100644 index 00000000..dcfc8adb --- /dev/null +++ "b/web/113 \347\231\275\350\214\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/css/index2.css" @@ -0,0 +1,792 @@ +.content { + width: 100%; + background: url(../images/bg_02.jpg) center no-repeat; + background-size: 100% 100%; + padding-top: 0.175rem; + padding-bottom: 0.55rem; + box-sizing: border-box; +} + +.content .header { + width: 100%; + height: 1.05rem; + padding: 0 0.375rem; + display: flex; + justify-content: space-between; + box-sizing: border-box; +} + +.content .header .header_l { + width: 5.625rem; +} + +.content .header .header_l ul { + width: 100%; + height: 1.05rem; + padding-top: 0.225rem; + display: flex; + box-sizing: border-box; +} + +.content .header .header_l ul li { + width: 1.475rem; + height: 0.6rem; + background: url(../images/header-2.png) center no-repeat; + background-size: 100% 100%; + margin-right: 0.25rem; +} + +.content .header .header_l ul li a { + width: 100%; + height: 100%; + display: flex; + align-items: center; + justify-content: center; +} + +.content .header .header_l ul li a img { + width: 0.25rem; + height: 0.25rem; + margin-right: 0.1375rem; +} + +.content .header .header_l ul li a span { + font-size: 0.25rem; + font-family: SourceHanSansCN; + font-weight: 400; + color: #9da4b6; + line-height: 0.4rem; +} + +.content .header .header_l ul .sel_li { + background: url(../images/header-4.png) center no-repeat; + background-size: 100% 100%; +} + +.content .header .header_l ul .sel_li a span { + color: #fff; +} + +.content .header .header_m { + width: 8.125rem; + height: 100%; +} + +.content .header .header_m h1 { + width: 100%; + font-size: 0.525rem; + font-family: SourceHanSansCN; + font-weight: 500; + color: #FFFFFF; + line-height: 1.05rem; + background: linear-gradient(0deg, #a7c0ff 0%, #f9faff 0%); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + text-align: center; +} + +.content .header .header_r { + width: 5.625rem; +} + +.content .header .header_r ul { + width: 100%; + height: 1.05rem; + padding-top: 0.225rem; + display: flex; + justify-content: flex-end; + box-sizing: border-box; +} + +.content .header .header_r ul li { + width: 1.475rem; + height: 0.6rem; + background: url(../images/header-2.png) center no-repeat; + background-size: 100% 100%; + margin-right: 0.25rem; +} + +.content .header .header_r ul li a { + width: 100%; + height: 100%; + display: flex; + align-items: center; + justify-content: center; +} + +.content .header .header_r ul li a img { + width: 0.25rem; + height: 0.25rem; + margin-right: 0.1375rem; +} + +.content .header .header_r ul li a span { + font-size: 0.25rem; + font-family: SourceHanSansCN; + font-weight: 400; + color: #9da4b6; + line-height: 0.4rem; +} + +.content .header .header_r ul li:last-child { + width: 1.3375rem; + box-sizing: border-box; + margin-right: 0; + padding-right: 0.025rem; + margin-left: 0.3rem; + background: none !important; +} + +.content .header .header_r ul li:last-child a { + justify-content: flex-end; +} + +.content .header .header_r ul li:last-child img { + margin-right: 0.125rem; +} + +.content .header .header_r ul li:last-child span { + font-size: 0.25rem; + font-family: SourceHanSansCN; + font-weight: 400; + color: #FFFFFF; + line-height: 0.4rem; +} + +.content .header .header_r ul .sel_li { + background: url(../images/header-4.png) center no-repeat; + background-size: 100% 100%; +} + +.content .main { + width: 100%; + height: 11.5rem; + padding: 0 0.375rem; + display: flex; + justify-content: space-between; + position: relative; + box-sizing: border-box; +} + +.content .main .item { + width: 6.25rem; + height: 5.375rem; + background: url(../images/main2-c-bg.png) center no-repeat; + background-size: 100% 100%; + margin-bottom: 0.175rem; + padding-top: 0.075rem; + box-sizing: border-box; +} + +.content .main .title { + width: 100%; + display: flex; + align-items: center; +} + +.content .main .title h2 { + width: 2.1875rem; + font-size: 0.25rem; + font-family: SourceHanSansCN; + font-weight: 500; + color: #FFFFFF; + line-height: 0.6rem; + padding-left: 0.25rem; +} + +.content .main .title p { + width: 1.95rem; + height: 0.35rem; + background: rgba(75, 126, 254, 0.16); + border-radius: 0.175rem; + line-height: 0.35rem; + font-size: 0.175rem; + font-family: SourceHanSansCN; + font-weight: 400; + color: #FFFFFF; + margin-right: 0.3125rem; + margin-left: 0.0875rem; +} + +.content .main .title p span { + display: inline-block; + width: 0.65rem; + height: 0.35rem; + border-radius: 0.175rem; + text-align: center; + cursor: pointer; +} + +.content .main .title p .span_c { + background-color: #4b7efe; +} + +.content .main .title button { + width: 1.4625rem; + height: 0.6rem; + background: url(../images/mainl-5.png) center no-repeat; + background-size: 100% 57%; + background-position: 0% 90%; + border: none; + cursor: pointer; + margin-right: 0.15rem; +} + +.content .main .main_l { + width: 6.25rem; + padding-top: 0.4rem; + z-index: 9; +} + +.content .main .main_l .item { + background: rgba(12, 31, 86, 0.7); +} + +.content .main .main_l .item .con { + width: 100%; +} + +.content .main .main_l .item .con .con_t { + width: 100%; + height: 0.875rem; + padding-top: 0.1875rem; + display: flex; + justify-content: space-between; + box-sizing: border-box; +} + +.content .main .main_l .item .con .con_t p { + width: 3.75rem; + font-size: 0.2rem; + font-family: SourceHanSansCN; + font-weight: 400; + color: #FFFFFF; + line-height: 0.4rem; + margin: 0 auto; + background: url(../images/mainl2-1.png) center no-repeat; + background-size: 100% 0.3rem; + background-position: 0% 100%; + text-align: center; +} + +.content .main .main_l .item .con .con_t p span { + font-size: 0.4rem; + font-family: DINPro; + font-weight: 600; + color: #00FFEA; + line-height: 0.4rem; + margin-right: 0.0375rem; + margin-left: -0.0625rem; +} + +.content .main .main_l .item .con .con_t p b { + font-size: 0.2rem; + font-family: SourceHanSansCN; + font-weight: 500; + color: #00FFEA; + line-height: 0.4rem; +} + +.content .main .main_l .item .con .con_t button { + width: 1.125rem; + height: 0.175rem; + background: url(../images/mainl-10.png) center no-repeat; + background-size: 100% 100%; + border: none; + margin-right: 0.125rem; + cursor: pointer; + margin-top: 0.0375rem; +} + +.content .main .main_l .item .con .con_f { + width: 100%; + height: 3.75rem; + margin-top: 0.025rem; +} + +.content .main .main_l .item:last-child .con .con_t p span { + color: #6299FF; +} + +.content .main .main_l .item:last-child .con .con_t p b { + color: #6299FF; +} + +.content .main .eject_bigbox { + width: 9.75rem; + height: 9.4375rem; + position: absolute; + top: 0.375rem; + left: 0; + right: 0; + margin: 0 auto; + margin-top: 0.4rem; + background: url(../images/eject1.png) center no-repeat; + background-size: 100% 100%; + z-index: 9999; + padding: 0 0.25rem; + padding-top: 0.1875rem; + box-sizing: border-box; +} + +.content .main .eject_bigbox h2 { + width: 100%; + height: 0.8375rem; + font-size: 0.3rem; + font-family: SourceHanSansCN; + font-weight: 500; + color: #FFFFFF; + line-height: 0.8375rem; + text-align: center; +} + +.content .main .eject_bigbox .close2 { + width: 0.5rem; + height: 0.5rem; + position: absolute; + top: 0; + right: 0; + cursor: pointer; +} + +.content .main .eject_bigbox .con_box { + width: 100%; + height: 8.125rem; + overflow-y: scroll; +} + +.content .main .eject_bigbox .con_box::-webkit-scrollbar { + /*滚动条整体样式*/ + width: 0.1rem; + /*高宽分别对应横竖滚动条的尺寸*/ + height: 0.1rem; +} + +.content .main .eject_bigbox .con_box::-webkit-scrollbar-thumb { + /*滚动条里面小方块*/ + border-radius: 0.0625rem; + -webkit-box-shadow: inset 0 0 0.0625rem rgba(0, 0, 0, 0.2); + background: #00FFEA; +} + +.content .main .eject_bigbox .con_box::-webkit-scrollbar-track { + /*滚动条里面轨道*/ + -webkit-box-shadow: inset 0 0 0.0625rem rgba(0, 0, 0, 0.2); + border-radius: 0.0625rem; +} + +.content .main .eject_bigbox video { + width: 100%; + height: 5.125rem; + margin-bottom: 0.125rem; +} + +.content .main .eject_bigbox p { + font-size: 0.2rem; + font-family: SourceHanSansCN; + font-weight: 400; + color: #FFFFFF; + line-height: 0.3rem; + padding-bottom: 0.125rem; +} + +.content .main .eject_bigbox .textbox { + margin-bottom: 0.125rem; +} + +.content .main .eject_bigbox_control { + display: none; +} + +.content .main .main_m { + width: calc(100% - 13.25rem); + position: absolute; + padding-top: 0.375rem; + top: 0; + left: 0; + right: 0; + margin: 0 auto; + z-index: 9; + margin-bottom: 0.3125rem; +} + +.content .main .main_m .main_m_t { + width: 9.75rem; + display: flex; + justify-content: space-between; + margin: 0 auto; + background: rgba(12, 31, 86, 0.7); +} + +.content .main .main_m .main_m_t .item1 { + width: 2.25rem; + height: 2.5875rem; + background: url(../images/mainm2-1.png) center no-repeat; + background-size: 100% 100%; + padding-top: 0.45rem; + box-sizing: border-box; +} + +.content .main .main_m .main_m_t .item1 p { + width: 100%; + font-size: 0.4rem; + font-family: DINPro; + font-weight: 500; + color: #4B7EFE; + line-height: 0.2875rem; + text-align: center; + margin-bottom: 0.175rem; +} + +.content .main .main_m .main_m_t .item1 span { + display: block; + width: 100%; + font-size: 0.175rem; + font-family: SourceHanSansCN; + font-weight: 400; + color: #FFFFFF; + line-height: 0.175rem; + opacity: 0.6; + text-align: center; + margin-bottom: 0.4875rem; +} + +.content .main .main_m .main_m_t .item1 span:last-child { + margin-bottom: 0; +} + +.content .main .main_m .main_m_t .item1:nth-child(2) p { + color: #00FFEA; +} + +.content .main .main_m .main_m_t .item1:nth-child(3) p { + color: #FEC31D; +} + +.content .main .main_m .main_m_t .item1:nth-child(4) p { + color: #917CFF; +} + +.content .main .eject { + position: absolute; + top: 3.75rem; + left: 7rem; + width: 3.625rem; + height: 5.5625rem; + background: url(../images/eject.png) center no-repeat; + background-size: 100% 100%; + z-index: 999; + padding-top: 0.425rem; + padding-left: 0.3rem; + box-sizing: border-box; +} + +.content .main .eject .close { + width: 0.3125rem; + height: 0.3125rem; + position: absolute; + top: 0; + right: 0; + cursor: pointer; +} + +.content .main .eject h2 { + height: 0.3rem; + width: 2.25rem; + font-size: 0.25rem; + font-family: SourceHanSansCN; + font-weight: 400; + color: #FFFFFF; + line-height: 0.3rem; + display: flex; + margin-bottom: 0.125rem; +} + +.content .main .eject h2 img { + margin-right: 0.1rem; +} + +.content .main .eject .con_text { + width: 2.5rem; +} + +.content .main .eject .con_text p { + font-size: 0.2rem; + font-family: SourceHanSansCN; + font-weight: 400; + color: #8a93b5; + line-height: 0.4rem; +} + +.content .main .eject .con_text p span { + color: #00FFEA; + font-size: 0.225rem; +} + +.content .main .eject .line5 { + width: 3.125rem; + height: 1.5rem; + margin-left: -0.0625rem; +} + +.content .main .control { + display: none !important; +} + +.content .main .main_m_f { + position: absolute; + width: 9.75rem; + padding-top: 0.5rem; + padding-bottom: 0.3rem; + bottom: 0.2rem; + left: 0; + right: 0; + margin: 0 auto; + z-index: 9; +} + +.content .main .main_m_f ul { + width: 100%; + display: flex; + justify-content: space-between; +} + +.content .main .main_m_f ul li { + width: 0.9rem; +} + +.content .main .main_m_f ul li a { + display: block; + width: 100%; + height: 0.8rem; + margin-bottom: 0.1375rem; +} + +.content .main .main_m_f ul li span { + display: block; + width: 100%; + font-size: 0.2rem; + font-family: SourceHanSansCN; + font-weight: 400; + color: #adf3e6; + line-height: 0.2rem; + text-align: center; +} + +.content .main .main_m_f ul li img { + width: 0.8875rem; + height: 0.7875rem; +} + + +.content .main .main_m_f ul li a img:nth-child(1) { + display: block; +} + +.content .main .main_m_f ul li a img:nth-child(2) { + display: none; +} + +.content .main .main_m_f ul li span { + display: block; + width: 100%; + font-size: 0.2rem; + font-family: SourceHanSansCN; + font-weight: 400; + color: #adf3e6; + line-height: 0.2rem; + text-align: center; + white-space: nowrap; + cursor: pointer; +} + +.content .main .main_m_f ul li.active span { + background: linear-gradient(180deg, #ffb63b, #adf3e6); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; +} + +.content .main .main_m_f ul li.active a img:nth-child(1) { + display: none; +} + +.content .main .main_m_f ul li.active a img:nth-child(2) { + display: block; +} + +.content .main .main_r { + z-index: 9; + padding-top: 0.4rem; +} + +.content .main .main_r .item { + background: rgba(12, 31, 86, 0.7); +} + +.content .main .main_r .item .con { + width: 100%; +} + +.content .main .main_r .item .con .con_t { + width: 100%; + height: 0.875rem; + padding-top: 0.1875rem; + display: flex; + justify-content: space-between; + box-sizing: border-box; +} + +.content .main .main_r .item .con .con_t p { + width: 3.75rem; + font-size: 0.2rem; + font-family: SourceHanSansCN; + font-weight: 400; + color: #FFFFFF; + line-height: 0.4rem; + margin: 0 auto; + background: url(../images/mainl2-1.png) center no-repeat; + background-size: 100% 0.3rem; + background-position: 0% 100%; + text-align: center; +} + +.content .main .main_r .item .con .con_t p span { + font-size: 0.4rem; + font-family: DINPro; + font-weight: 600; + color: #E0AB14; + line-height: 0.4rem; + margin-right: 0.0375rem; + margin-left: -0.0625rem; +} + +.content .main .main_r .item .con .con_t p b { + font-size: 0.2rem; + font-family: SourceHanSansCN; + font-weight: 500; + color: #E0AB14; + line-height: 0.4rem; +} + +.content .main .main_r .item .con .con_t button { + width: 1.125rem; + height: 0.175rem; + background: url(../images/mainl-10.png) center no-repeat; + background-size: 100% 100%; + border: none; + margin-right: 0.125rem; + cursor: pointer; + margin-top: 0.0375rem; +} + +.content .main .main_r .item .con .con_f { + width: 100%; + height: 3.75rem; + margin-top: 0.025rem; +} + +.content .main .main_r .item:last-child .con .con_t p span { + color: #917CFF; +} + +.content .main .main_r .item:last-child .con .con_t p b { + color: #917CFF; +} + +.content .main .map2 { + width: 98%; + box-sizing: border-box; + height: 11.5rem; + position: absolute; + top: 0; + left: 0.375rem; + z-index: 0; +} + +.content .main .map3 { + width: 100%; + box-sizing: border-box; + height: 11.5rem; + position: absolute; + top: 0; + left: 0; + z-index: 0; + padding: 0 0.375rem; + background: rgba(0, 0, 0, 0) !important; +} + +.daterangepicker { + background: #061745 !important; +} + +.daterangepicker .calendar-table { + background: #061745 !important; +} + +.daterangepicker td.active { + color: #000 !important; + background: #4b7efe !important; +} + +.daterangepicker td.off { + background: #061745 !important; + color: #193d5c !important; +} + +.daterangepicker .calendar th, +.daterangepicker .calendar td { + color: #357ebd; +} + +.daterangepicker .calendar-table { + border-color: #061745 !important; +} + +.btn-success { + background-color: #357ebd; + border-color: #357ebd; + outline: none; +} + +.btn-success:hover { + background-color: #357ebd; + border-color: #357ebd; +} + +.btn-success[disabled] { + background-color: #357ebd; + border-color: #357ebd; +} + +.btn-success:focus { + background-color: #357ebd; + border-color: #357ebd; + outline: none; +} + +.btn-success:active { + background-color: #357ebd; + border-color: #357ebd; +} + +.daterangepicker.dropdown-menu { + z-index: 99999 !important; +} + +.amap-logo { + display: none !important; + visibility: hidden !important; +} + +.amap-copyright { + display: none !important; + visibility: hidden !important; +} + +.content .main .eject_bigbox p { + text-indent: 2em; +} + +.content .main .main_m_f ul li { + width: 1rem; +} \ No newline at end of file diff --git "a/web/113 \347\231\275\350\214\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/fonts/glyphicons-halflings-regular.eot" "b/web/113 \347\231\275\350\214\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/fonts/glyphicons-halflings-regular.eot" new file mode 100644 index 00000000..b93a4953 Binary files /dev/null and "b/web/113 \347\231\275\350\214\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/fonts/glyphicons-halflings-regular.eot" differ diff --git "a/web/113 \347\231\275\350\214\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/fonts/glyphicons-halflings-regular.svg" "b/web/113 \347\231\275\350\214\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/fonts/glyphicons-halflings-regular.svg" new file mode 100644 index 00000000..94fb5490 --- /dev/null +++ "b/web/113 \347\231\275\350\214\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/fonts/glyphicons-halflings-regular.svg" @@ -0,0 +1,288 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git "a/web/113 \347\231\275\350\214\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/fonts/glyphicons-halflings-regular.ttf" "b/web/113 \347\231\275\350\214\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/fonts/glyphicons-halflings-regular.ttf" new file mode 100644 index 00000000..1413fc60 Binary files /dev/null and "b/web/113 \347\231\275\350\214\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/fonts/glyphicons-halflings-regular.ttf" differ diff --git "a/web/113 \347\231\275\350\214\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/fonts/glyphicons-halflings-regular.woff" "b/web/113 \347\231\275\350\214\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/fonts/glyphicons-halflings-regular.woff" new file mode 100644 index 00000000..9e612858 Binary files /dev/null and "b/web/113 \347\231\275\350\214\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/fonts/glyphicons-halflings-regular.woff" differ diff --git "a/web/113 \347\231\275\350\214\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/fonts/glyphicons-halflings-regular.woff2" "b/web/113 \347\231\275\350\214\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/fonts/glyphicons-halflings-regular.woff2" new file mode 100644 index 00000000..64539b54 Binary files /dev/null and "b/web/113 \347\231\275\350\214\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/fonts/glyphicons-halflings-regular.woff2" differ diff --git "a/web/113 \347\231\275\350\214\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/images/bg_02.jpg" "b/web/113 \347\231\275\350\214\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/images/bg_02.jpg" new file mode 100644 index 00000000..0970fe8f Binary files /dev/null and "b/web/113 \347\231\275\350\214\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/images/bg_02.jpg" differ diff --git "a/web/113 \347\231\275\350\214\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/images/eject.png" "b/web/113 \347\231\275\350\214\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/images/eject.png" new file mode 100644 index 00000000..6699debe Binary files /dev/null and "b/web/113 \347\231\275\350\214\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/images/eject.png" differ diff --git "a/web/113 \347\231\275\350\214\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/images/eject1.png" "b/web/113 \347\231\275\350\214\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/images/eject1.png" new file mode 100644 index 00000000..caddac49 Binary files /dev/null and "b/web/113 \347\231\275\350\214\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/images/eject1.png" differ diff --git "a/web/113 \347\231\275\350\214\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/images/header-2.png" "b/web/113 \347\231\275\350\214\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/images/header-2.png" new file mode 100644 index 00000000..2b736085 Binary files /dev/null and "b/web/113 \347\231\275\350\214\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/images/header-2.png" differ diff --git "a/web/113 \347\231\275\350\214\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/images/header-4.png" "b/web/113 \347\231\275\350\214\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/images/header-4.png" new file mode 100644 index 00000000..c7e83f73 Binary files /dev/null and "b/web/113 \347\231\275\350\214\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/images/header-4.png" differ diff --git "a/web/113 \347\231\275\350\214\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/images/main2-c-bg.png" "b/web/113 \347\231\275\350\214\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/images/main2-c-bg.png" new file mode 100644 index 00000000..143b6646 Binary files /dev/null and "b/web/113 \347\231\275\350\214\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/images/main2-c-bg.png" differ diff --git "a/web/113 \347\231\275\350\214\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/images/mainl-10.png" "b/web/113 \347\231\275\350\214\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/images/mainl-10.png" new file mode 100644 index 00000000..2b9016cb Binary files /dev/null and "b/web/113 \347\231\275\350\214\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/images/mainl-10.png" differ diff --git "a/web/113 \347\231\275\350\214\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/images/mainl-5.png" "b/web/113 \347\231\275\350\214\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/images/mainl-5.png" new file mode 100644 index 00000000..8e095a1e Binary files /dev/null and "b/web/113 \347\231\275\350\214\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/images/mainl-5.png" differ diff --git "a/web/113 \347\231\275\350\214\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/images/mainl2-1.png" "b/web/113 \347\231\275\350\214\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/images/mainl2-1.png" new file mode 100644 index 00000000..f74c041c Binary files /dev/null and "b/web/113 \347\231\275\350\214\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/images/mainl2-1.png" differ diff --git "a/web/113 \347\231\275\350\214\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/images/mainm2-1.png" "b/web/113 \347\231\275\350\214\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/images/mainm2-1.png" new file mode 100644 index 00000000..ccb23641 Binary files /dev/null and "b/web/113 \347\231\275\350\214\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/images/mainm2-1.png" differ diff --git "a/web/113 \347\231\275\350\214\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/images/\346\233\264\345\244\232\345\206\205\345\256\271\345\205\263\346\263\250\345\205\254\344\274\227\345\217\267.gif" "b/web/113 \347\231\275\350\214\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/images/\346\233\264\345\244\232\345\206\205\345\256\271\345\205\263\346\263\250\345\205\254\344\274\227\345\217\267.gif" new file mode 100644 index 00000000..f2951f1d Binary files /dev/null and "b/web/113 \347\231\275\350\214\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/images/\346\233\264\345\244\232\345\206\205\345\256\271\345\205\263\346\263\250\345\205\254\344\274\227\345\217\267.gif" differ diff --git "a/web/113 \347\231\275\350\214\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/js/bootstrap-3.3.4.js" "b/web/113 \347\231\275\350\214\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/js/bootstrap-3.3.4.js" new file mode 100644 index 00000000..e62f981c --- /dev/null +++ "b/web/113 \347\231\275\350\214\266\347\247\215\346\244\215\345\244\247\346\225\260\346\215\256\346\272\257\346\272\220\345\271\263\345\217\260/static/js/bootstrap-3.3.4.js" @@ -0,0 +1,3 @@ +/*-防止各大cdn公共库加载地址失效问题,此地址我们会时时监控,及调整以保障正常访问-www.jq22.com为您服务*/ +/*当前为百度cdn公共库提供的bootstrap-3.3.4*/ +document.write(" + + + + + + + +
+

HELLO共享单车运营管理平台

+
+
+
+
+
+

按季节:每小时租赁数

+
+ +
+
+

注册用户:每小时租赁数

+
+ +
+
+

注册、非注册用户按周:每天租赁数

+
+ +
+
+ + +
+
+

注册与非注册用户对比

+
+ +
+
+

租赁数影响因素分析

+
+ +
+
+ +
+
+

按周:每小时租赁数

+
+ +
+
+

天气分析

+
+ +
+
+

租赁概况

+
+ +
+
+
+ + + \ No newline at end of file diff --git "a/web/114 HELLO\345\205\261\344\272\253\345\215\225\350\275\246\350\277\220\350\220\245\347\256\241\347\220\206\345\271\263\345\217\260/js/echarts-gl.js" "b/web/114 HELLO\345\205\261\344\272\253\345\215\225\350\275\246\350\277\220\350\220\245\347\256\241\347\220\206\345\271\263\345\217\260/js/echarts-gl.js" new file mode 100644 index 00000000..09910548 --- /dev/null +++ "b/web/114 HELLO\345\205\261\344\272\253\345\215\225\350\275\246\350\277\220\350\220\245\347\256\241\347\220\206\345\271\263\345\217\260/js/echarts-gl.js" @@ -0,0 +1,56990 @@ +(function webpackUniversalModuleDefinition(root, factory) { + if(typeof exports === 'object' && typeof module === 'object') + module.exports = factory(require("echarts")); + else if(typeof define === 'function' && define.amd) + define(["echarts"], factory); + else if(typeof exports === 'object') + exports["echarts-gl"] = factory(require("echarts")); + else + root["echarts-gl"] = factory(root["echarts"]); +})(this, function(__WEBPACK_EXTERNAL_MODULE_0__) { +return /******/ (function(modules) { // webpackBootstrap +/******/ // The module cache +/******/ var installedModules = {}; +/******/ +/******/ // The require function +/******/ function __webpack_require__(moduleId) { +/******/ +/******/ // Check if module is in cache +/******/ if(installedModules[moduleId]) { +/******/ return installedModules[moduleId].exports; +/******/ } +/******/ // Create a new module (and put it into the cache) +/******/ var module = installedModules[moduleId] = { +/******/ i: moduleId, +/******/ l: false, +/******/ exports: {} +/******/ }; +/******/ +/******/ // Execute the module function +/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); +/******/ +/******/ // Flag the module as loaded +/******/ module.l = true; +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/******/ +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = modules; +/******/ +/******/ // expose the module cache +/******/ __webpack_require__.c = installedModules; +/******/ +/******/ // define getter function for harmony exports +/******/ __webpack_require__.d = function(exports, name, getter) { +/******/ if(!__webpack_require__.o(exports, name)) { +/******/ Object.defineProperty(exports, name, { +/******/ configurable: false, +/******/ enumerable: true, +/******/ get: getter +/******/ }); +/******/ } +/******/ }; +/******/ +/******/ // getDefaultExport function for compatibility with non-harmony modules +/******/ __webpack_require__.n = function(module) { +/******/ var getter = module && module.__esModule ? +/******/ function getDefault() { return module['default']; } : +/******/ function getModuleExports() { return module; }; +/******/ __webpack_require__.d(getter, 'a', getter); +/******/ return getter; +/******/ }; +/******/ +/******/ // Object.prototype.hasOwnProperty.call +/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; +/******/ +/******/ // __webpack_public_path__ +/******/ __webpack_require__.p = ""; +/******/ +/******/ // Load entry module and return exports +/******/ return __webpack_require__(__webpack_require__.s = 106); +/******/ }) +/************************************************************************/ +/******/ ([ +/* 0 */ +/***/ (function(module, exports) { + +module.exports = __WEBPACK_EXTERNAL_MODULE_0__; + +/***/ }), +/* 1 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_claygl_src_Mesh__ = __webpack_require__(40); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_claygl_src_Renderer__ = __webpack_require__(52); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2_claygl_src_Texture2D__ = __webpack_require__(5); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3_claygl_src_Texture__ = __webpack_require__(4); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4_claygl_src_Shader__ = __webpack_require__(8); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_5_claygl_src_Material__ = __webpack_require__(19); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_6_claygl_src_Node__ = __webpack_require__(35); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_7_claygl_src_Geometry__ = __webpack_require__(15); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_8_echarts_lib_echarts__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_8_echarts_lib_echarts___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_8_echarts_lib_echarts__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_9_claygl_src_Scene__ = __webpack_require__(36); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_10_zrender_lib_core_LRU__ = __webpack_require__(60); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_10_zrender_lib_core_LRU___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_10_zrender_lib_core_LRU__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_11_claygl_src_util_texture__ = __webpack_require__(61); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_12__EChartsSurface__ = __webpack_require__(124); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_13_claygl_src_light_AmbientCubemap__ = __webpack_require__(125); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_14_claygl_src_light_AmbientSH__ = __webpack_require__(129); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_15_claygl_src_util_sh__ = __webpack_require__(130); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_16__retrieve__ = __webpack_require__(2); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_17_claygl_src_geometry_Sphere__ = __webpack_require__(132); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_18_claygl_src_geometry_Plane__ = __webpack_require__(43); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_19_claygl_src_geometry_Cube__ = __webpack_require__(76); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_20_claygl_src_light_Ambient__ = __webpack_require__(133); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_21_claygl_src_light_Directional__ = __webpack_require__(134); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_22_claygl_src_light_Point__ = __webpack_require__(135); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_23_claygl_src_light_Spot__ = __webpack_require__(136); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_24_claygl_src_camera_Perspective__ = __webpack_require__(41); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_25_claygl_src_camera_Orthographic__ = __webpack_require__(37); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_26_claygl_src_math_Vector2__ = __webpack_require__(26); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_27_claygl_src_math_Vector3__ = __webpack_require__(3); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_28_claygl_src_math_Vector4__ = __webpack_require__(137); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_29_claygl_src_math_Quaternion__ = __webpack_require__(56); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_30_claygl_src_math_Matrix2__ = __webpack_require__(138); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_31_claygl_src_math_Matrix2d__ = __webpack_require__(139); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_32_claygl_src_math_Matrix3__ = __webpack_require__(140); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_33_claygl_src_math_Matrix4__ = __webpack_require__(9); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_34_claygl_src_math_Plane__ = __webpack_require__(74); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_35_claygl_src_math_Ray__ = __webpack_require__(54); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_36_claygl_src_math_BoundingBox__ = __webpack_require__(18); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_37_claygl_src_math_Frustum__ = __webpack_require__(59); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_38__animatableMixin__ = __webpack_require__(141); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_39_claygl_src_shader_source_util_glsl_js__ = __webpack_require__(146); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_40_claygl_src_shader_source_prez_glsl_js__ = __webpack_require__(71); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_41__shader_common_glsl_js__ = __webpack_require__(147); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_42__shader_color_glsl_js__ = __webpack_require__(148); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_43__shader_lambert_glsl_js__ = __webpack_require__(149); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_44__shader_realistic_glsl_js__ = __webpack_require__(150); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_45__shader_hatching_glsl_js__ = __webpack_require__(151); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_46__shader_shadow_glsl_js__ = __webpack_require__(152); + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +// Math + + + + + + + + + + + + + + + + + +// Some common shaders + + + + + + + + + + +__WEBPACK_IMPORTED_MODULE_8_echarts_lib_echarts___default.a.util.extend(__WEBPACK_IMPORTED_MODULE_6_claygl_src_Node__["a" /* default */].prototype, __WEBPACK_IMPORTED_MODULE_38__animatableMixin__["a" /* default */]); + +__WEBPACK_IMPORTED_MODULE_4_claygl_src_Shader__["a" /* default */].import(__WEBPACK_IMPORTED_MODULE_39_claygl_src_shader_source_util_glsl_js__["a" /* default */]); +__WEBPACK_IMPORTED_MODULE_4_claygl_src_Shader__["a" /* default */].import(__WEBPACK_IMPORTED_MODULE_40_claygl_src_shader_source_prez_glsl_js__["a" /* default */]); +__WEBPACK_IMPORTED_MODULE_4_claygl_src_Shader__["a" /* default */].import(__WEBPACK_IMPORTED_MODULE_41__shader_common_glsl_js__["a" /* default */]); +__WEBPACK_IMPORTED_MODULE_4_claygl_src_Shader__["a" /* default */].import(__WEBPACK_IMPORTED_MODULE_42__shader_color_glsl_js__["a" /* default */]); +__WEBPACK_IMPORTED_MODULE_4_claygl_src_Shader__["a" /* default */].import(__WEBPACK_IMPORTED_MODULE_43__shader_lambert_glsl_js__["a" /* default */]); +__WEBPACK_IMPORTED_MODULE_4_claygl_src_Shader__["a" /* default */].import(__WEBPACK_IMPORTED_MODULE_44__shader_realistic_glsl_js__["a" /* default */]); +__WEBPACK_IMPORTED_MODULE_4_claygl_src_Shader__["a" /* default */].import(__WEBPACK_IMPORTED_MODULE_45__shader_hatching_glsl_js__["a" /* default */]); +__WEBPACK_IMPORTED_MODULE_4_claygl_src_Shader__["a" /* default */].import(__WEBPACK_IMPORTED_MODULE_46__shader_shadow_glsl_js__["a" /* default */]); + +function isValueNone(value) { + return !value || value === 'none'; +} + +function isValueImage(value) { + return value instanceof HTMLCanvasElement + || value instanceof HTMLImageElement + || value instanceof Image; +} + +function isECharts(value) { + return value.getZr && value.setOption; +} + +// Overwrite addToScene and removeFromScene +var oldAddToScene = __WEBPACK_IMPORTED_MODULE_9_claygl_src_Scene__["a" /* default */].prototype.addToScene; +var oldRemoveFromScene = __WEBPACK_IMPORTED_MODULE_9_claygl_src_Scene__["a" /* default */].prototype.removeFromScene; + +__WEBPACK_IMPORTED_MODULE_9_claygl_src_Scene__["a" /* default */].prototype.addToScene = function (node) { + oldAddToScene.call(this, node); + + if (this.__zr) { + var zr = this.__zr; + node.traverse(function (child) { + child.__zr = zr; + if (child.addAnimatorsToZr) { + child.addAnimatorsToZr(zr); + } + }); + } +}; + +__WEBPACK_IMPORTED_MODULE_9_claygl_src_Scene__["a" /* default */].prototype.removeFromScene = function (node) { + oldRemoveFromScene.call(this, node); + + node.traverse(function (child) { + var zr = child.__zr; + child.__zr = null; + if (zr && child.removeAnimatorsFromZr) { + child.removeAnimatorsFromZr(zr); + } + }); +}; + +/** + * @param {string} textureName + * @param {string|HTMLImageElement|HTMLCanvasElement} imgValue + * @param {module:echarts/ExtensionAPI} api + * @param {Object} [textureOpts] + */ +__WEBPACK_IMPORTED_MODULE_5_claygl_src_Material__["a" /* default */].prototype.setTextureImage = function (textureName, imgValue, api, textureOpts) { + if (!this.shader) { + return; + } + + var zr = api.getZr(); + var material = this; + var texture; + material.autoUpdateTextureStatus = false; + // disableTexture first + material.disableTexture(textureName); + if (!isValueNone(imgValue)) { + texture = graphicGL.loadTexture(imgValue, api, textureOpts, function (texture) { + material.enableTexture(textureName); + zr && zr.refresh(); + }); + // Set texture immediately for other code to verify if have this texture. + material.set(textureName, texture); + } + + return texture; +}; + +var graphicGL = {}; + +graphicGL.Renderer = __WEBPACK_IMPORTED_MODULE_1_claygl_src_Renderer__["a" /* default */]; + +graphicGL.Node = __WEBPACK_IMPORTED_MODULE_6_claygl_src_Node__["a" /* default */]; + +graphicGL.Mesh = __WEBPACK_IMPORTED_MODULE_0_claygl_src_Mesh__["a" /* default */]; + +graphicGL.Shader = __WEBPACK_IMPORTED_MODULE_4_claygl_src_Shader__["a" /* default */]; + +graphicGL.Material = __WEBPACK_IMPORTED_MODULE_5_claygl_src_Material__["a" /* default */]; + +graphicGL.Texture = __WEBPACK_IMPORTED_MODULE_3_claygl_src_Texture__["a" /* default */]; + +graphicGL.Texture2D = __WEBPACK_IMPORTED_MODULE_2_claygl_src_Texture2D__["a" /* default */]; + +// Geometries +graphicGL.Geometry = __WEBPACK_IMPORTED_MODULE_7_claygl_src_Geometry__["a" /* default */]; +graphicGL.SphereGeometry = __WEBPACK_IMPORTED_MODULE_17_claygl_src_geometry_Sphere__["a" /* default */]; +graphicGL.PlaneGeometry = __WEBPACK_IMPORTED_MODULE_18_claygl_src_geometry_Plane__["a" /* default */]; +graphicGL.CubeGeometry = __WEBPACK_IMPORTED_MODULE_19_claygl_src_geometry_Cube__["a" /* default */]; + +// Lights +graphicGL.AmbientLight = __WEBPACK_IMPORTED_MODULE_20_claygl_src_light_Ambient__["a" /* default */]; +graphicGL.DirectionalLight = __WEBPACK_IMPORTED_MODULE_21_claygl_src_light_Directional__["a" /* default */]; +graphicGL.PointLight = __WEBPACK_IMPORTED_MODULE_22_claygl_src_light_Point__["a" /* default */]; +graphicGL.SpotLight = __WEBPACK_IMPORTED_MODULE_23_claygl_src_light_Spot__["a" /* default */]; + +// Cameras +graphicGL.PerspectiveCamera = __WEBPACK_IMPORTED_MODULE_24_claygl_src_camera_Perspective__["a" /* default */]; +graphicGL.OrthographicCamera = __WEBPACK_IMPORTED_MODULE_25_claygl_src_camera_Orthographic__["a" /* default */]; + +// Math +graphicGL.Vector2 = __WEBPACK_IMPORTED_MODULE_26_claygl_src_math_Vector2__["a" /* default */]; +graphicGL.Vector3 = __WEBPACK_IMPORTED_MODULE_27_claygl_src_math_Vector3__["a" /* default */]; +graphicGL.Vector4 = __WEBPACK_IMPORTED_MODULE_28_claygl_src_math_Vector4__["a" /* default */]; + +graphicGL.Quaternion = __WEBPACK_IMPORTED_MODULE_29_claygl_src_math_Quaternion__["a" /* default */]; + +graphicGL.Matrix2 = __WEBPACK_IMPORTED_MODULE_30_claygl_src_math_Matrix2__["a" /* default */]; +graphicGL.Matrix2d = __WEBPACK_IMPORTED_MODULE_31_claygl_src_math_Matrix2d__["a" /* default */]; +graphicGL.Matrix3 = __WEBPACK_IMPORTED_MODULE_32_claygl_src_math_Matrix3__["a" /* default */]; +graphicGL.Matrix4 = __WEBPACK_IMPORTED_MODULE_33_claygl_src_math_Matrix4__["a" /* default */]; + +graphicGL.Plane = __WEBPACK_IMPORTED_MODULE_34_claygl_src_math_Plane__["a" /* default */]; +graphicGL.Ray = __WEBPACK_IMPORTED_MODULE_35_claygl_src_math_Ray__["a" /* default */]; +graphicGL.BoundingBox = __WEBPACK_IMPORTED_MODULE_36_claygl_src_math_BoundingBox__["a" /* default */]; +graphicGL.Frustum = __WEBPACK_IMPORTED_MODULE_37_claygl_src_math_Frustum__["a" /* default */]; + +// Texture utilities + +var blankImage = __WEBPACK_IMPORTED_MODULE_11_claygl_src_util_texture__["a" /* default */].createBlank('rgba(255,255,255,0)').image; + + +function nearestPowerOfTwo(val) { + return Math.pow(2, Math.round(Math.log(val) / Math.LN2)); +} +function convertTextureToPowerOfTwo(texture) { + if ((texture.wrapS === __WEBPACK_IMPORTED_MODULE_3_claygl_src_Texture__["a" /* default */].REPEAT || texture.wrapT === __WEBPACK_IMPORTED_MODULE_3_claygl_src_Texture__["a" /* default */].REPEAT) + && texture.image + ) { + // var canvas = document.createElement('canvas'); + var width = nearestPowerOfTwo(texture.width); + var height = nearestPowerOfTwo(texture.height); + if (width !== texture.width || height !== texture.height) { + var canvas = document.createElement('canvas'); + canvas.width = width; + canvas.height = height; + var ctx = canvas.getContext('2d'); + ctx.drawImage(texture.image, 0, 0, width, height); + texture.image = canvas; + } + } +} +/** + * @param {string|HTMLImageElement|HTMLCanvasElement} imgValue + * @param {module:echarts/ExtensionAPI} api + * @param {Object} [textureOpts] + * @param {Function} cb + */ +// TODO Promise, test +graphicGL.loadTexture = function (imgValue, api, textureOpts, cb) { + if (typeof textureOpts === 'function') { + cb = textureOpts; + textureOpts = {}; + } + textureOpts = textureOpts || {}; + + var keys = Object.keys(textureOpts).sort(); + var prefix = ''; + for (var i = 0; i < keys.length; i++) { + prefix += keys[i] + '_' + textureOpts[keys[i]] + '_'; + } + + var textureCache = api.__textureCache = api.__textureCache || new __WEBPACK_IMPORTED_MODULE_10_zrender_lib_core_LRU___default.a(20); + + if (isECharts(imgValue)) { + var id = imgValue.__textureid__; + var textureObj = textureCache.get(prefix + id); + if (!textureObj) { + var surface = new __WEBPACK_IMPORTED_MODULE_12__EChartsSurface__["a" /* default */](imgValue); + surface.onupdate = function () { + api.getZr().refresh(); + }; + textureObj = { + texture: surface.getTexture() + }; + for (var i = 0; i < keys.length; i++) { + textureObj.texture[keys[i]] = textureOpts[keys[i]]; + } + id = imgValue.__textureid__ || '__ecgl_ec__' + textureObj.texture.__uid__; + imgValue.__textureid__ = id; + textureCache.put(prefix + id, textureObj); + cb && cb(textureObj.texture); + } + else { + textureObj.texture.surface.setECharts(imgValue); + + cb && cb(textureObj.texture); + } + return textureObj.texture; + } + else if (isValueImage(imgValue)) { + var id = imgValue.__textureid__; + var textureObj = textureCache.get(prefix + id); + if (!textureObj) { + textureObj = { + texture: new graphicGL.Texture2D({ + image: imgValue + }) + }; + for (var i = 0; i < keys.length; i++) { + textureObj.texture[keys[i]] = textureOpts[keys[i]]; + } + id = imgValue.__textureid__ || '__ecgl_image__' + textureObj.texture.__uid__; + imgValue.__textureid__ = id; + textureCache.put(prefix + id, textureObj); + + convertTextureToPowerOfTwo(textureObj.texture); + // TODO Next tick? + cb && cb(textureObj.texture); + } + return textureObj.texture; + } + else { + var textureObj = textureCache.get(prefix + imgValue); + if (textureObj) { + if (textureObj.callbacks) { + // Add to pending callbacks + textureObj.callbacks.push(cb); + } + else { + // TODO Next tick? + cb && cb(textureObj.texture); + } + } + else { + // Maybe base64 + if (imgValue.match(/.hdr$|^data:application\/octet-stream/)) { + textureObj = { + callbacks: [cb] + }; + var texture = __WEBPACK_IMPORTED_MODULE_11_claygl_src_util_texture__["a" /* default */].loadTexture(imgValue, { + exposure: textureOpts.exposure, + fileType: 'hdr' + }, function () { + texture.dirty(); + textureObj.callbacks.forEach(function (cb) { + cb && cb(texture); + }); + textureObj.callbacks = null; + }); + textureObj.texture = texture; + textureCache.put(prefix + imgValue, textureObj); + } + else { + var texture = new graphicGL.Texture2D({ + image: new Image() + }); + for (var i = 0; i < keys.length; i++) { + texture[keys[i]] = textureOpts[keys[i]]; + } + + textureObj = { + texture: texture, + callbacks: [cb] + }; + var originalImage = texture.image; + originalImage.onload = function () { + texture.image = originalImage; + convertTextureToPowerOfTwo(texture); + + texture.dirty(); + textureObj.callbacks.forEach(function (cb) { + cb && cb(texture); + }); + textureObj.callbacks = null; + }; + originalImage.src = imgValue; + // Use blank image as place holder. + texture.image = blankImage; + + textureCache.put(prefix + imgValue, textureObj); + } + } + + return textureObj.texture; + } +}; + +/** + * Create ambientCubemap and ambientSH light. respectively to have specular and diffuse light + * @return {Object} { specular, diffuse } + */ +graphicGL.createAmbientCubemap = function (opt, renderer, api, cb) { + opt = opt || {}; + var textureUrl = opt.texture; + var exposure = __WEBPACK_IMPORTED_MODULE_16__retrieve__["a" /* default */].firstNotNull(opt.exposure, 1.0); + + var ambientCubemap = new __WEBPACK_IMPORTED_MODULE_13_claygl_src_light_AmbientCubemap__["a" /* default */]({ + intensity: __WEBPACK_IMPORTED_MODULE_16__retrieve__["a" /* default */].firstNotNull(opt.specularIntensity, 1.0) + }); + var ambientSH = new __WEBPACK_IMPORTED_MODULE_14_claygl_src_light_AmbientSH__["a" /* default */]({ + intensity: __WEBPACK_IMPORTED_MODULE_16__retrieve__["a" /* default */].firstNotNull(opt.diffuseIntensity, 1.0), + coefficients: [0.844, 0.712, 0.691, -0.037, 0.083, 0.167, 0.343, 0.288, 0.299, -0.041, -0.021, -0.009, -0.003, -0.041, -0.064, -0.011, -0.007, -0.004, -0.031, 0.034, 0.081, -0.060, -0.049, -0.060, 0.046, 0.056, 0.050] + }); + + + ambientCubemap.cubemap = graphicGL.loadTexture(textureUrl, api, { + exposure: exposure + }, function () { + // TODO Performance when multiple view + ambientCubemap.cubemap.flipY = false; + if (true) { + var time = Date.now(); + } + ambientCubemap.prefilter(renderer, 32); + if (true) { + var dTime = Date.now() - time; + console.log('Prefilter environment map: ' + dTime + 'ms'); + } + ambientSH.coefficients = __WEBPACK_IMPORTED_MODULE_15_claygl_src_util_sh__["a" /* default */].projectEnvironmentMap(renderer, ambientCubemap.cubemap, { + lod: 1 + }); + + cb && cb(); + + // TODO Refresh ? + }); + + return { + specular: ambientCubemap, + diffuse: ambientSH + }; +}; + +/** + * Create a blank texture for placeholder + */ +graphicGL.createBlankTexture = __WEBPACK_IMPORTED_MODULE_11_claygl_src_util_texture__["a" /* default */].createBlank; + +/** + * If value is image + * @param {*} + * @return {boolean} + */ +graphicGL.isImage = isValueImage; + +graphicGL.additiveBlend = function (gl) { + gl.blendEquation(gl.FUNC_ADD); + gl.blendFunc(gl.SRC_ALPHA, gl.ONE); +}; + +/** + * @param {string|Array.} colorStr + * @param {Array.} [rgba] + * @return {Array.} rgba + */ +graphicGL.parseColor = function (colorStr, rgba) { + if (colorStr instanceof Array) { + if (!rgba) { + rgba = []; + } + // Color has been parsed. + rgba[0] = colorStr[0]; + rgba[1] = colorStr[1]; + rgba[2] = colorStr[2]; + if (colorStr.length > 3) { + rgba[3] = colorStr[3]; + } + else { + rgba[3] = 1; + } + return rgba; + } + + rgba = __WEBPACK_IMPORTED_MODULE_8_echarts_lib_echarts___default.a.color.parse(colorStr || '#000', rgba) || [0, 0, 0, 0]; + rgba[0] /= 255; + rgba[1] /= 255; + rgba[2] /= 255; + return rgba; +}; + +/** + * Convert alpha beta rotation to direction. + * @param {number} alpha + * @param {number} beta + * @return {Array.} + */ +graphicGL.directionFromAlphaBeta = function (alpha, beta) { + var theta = alpha / 180 * Math.PI + Math.PI / 2; + var phi = -beta / 180 * Math.PI + Math.PI / 2; + + var dir = []; + var r = Math.sin(theta); + dir[0] = r * Math.cos(phi); + dir[1] = -Math.cos(theta); + dir[2] = r * Math.sin(phi); + + return dir; +}; +/** + * Get shadow resolution from shadowQuality configuration + */ +graphicGL.getShadowResolution = function (shadowQuality) { + var shadowResolution = 1024; + switch (shadowQuality) { + case 'low': + shadowResolution = 512; + break; + case 'medium': + break; + case 'high': + shadowResolution = 2048; + break; + case 'ultra': + shadowResolution = 4096; + break; + } + return shadowResolution; +}; + +/** + * Shading utilities + */ +graphicGL.COMMON_SHADERS = ['lambert', 'color', 'realistic', 'hatching']; + +/** + * Create shader including vertex and fragment + * @param {string} prefix. + */ +graphicGL.createShader = function (prefix) { + var vertexShaderStr = __WEBPACK_IMPORTED_MODULE_4_claygl_src_Shader__["a" /* default */].source(prefix + '.vertex'); + var fragmentShaderStr = __WEBPACK_IMPORTED_MODULE_4_claygl_src_Shader__["a" /* default */].source(prefix + '.fragment'); + if (!vertexShaderStr) { + console.error('Vertex shader of \'%s\' not exits', prefix); + } + if (!fragmentShaderStr) { + console.error('Fragment shader of \'%s\' not exits', prefix); + } + var shader = new __WEBPACK_IMPORTED_MODULE_4_claygl_src_Shader__["a" /* default */](vertexShaderStr, fragmentShaderStr); + shader.name = prefix; + return shader; +}; + +graphicGL.createMaterial = function (prefix, defines) { + if (!(defines instanceof Array)) { + defines = [defines]; + } + var shader = graphicGL.createShader(prefix); + var material = new __WEBPACK_IMPORTED_MODULE_5_claygl_src_Material__["a" /* default */]({ + shader: shader + }); + defines.forEach(function (defineName) { + if (typeof defineName === 'string') { + material.define(defineName); + } + }); + return material; +}; +/** + * Set material from model. + * @param {clay.Material} material + * @param {module:echarts/model/Model} model + * @param {module:echarts/ExtensionAPI} api + */ +graphicGL.setMaterialFromModel = function (shading, material, model, api) { + material.autoUpdateTextureStatus = false; + + var materialModel = model.getModel(shading + 'Material'); + var detailTexture = materialModel.get('detailTexture'); + var uvRepeat = __WEBPACK_IMPORTED_MODULE_16__retrieve__["a" /* default */].firstNotNull(materialModel.get('textureTiling'), 1.0); + var uvOffset = __WEBPACK_IMPORTED_MODULE_16__retrieve__["a" /* default */].firstNotNull(materialModel.get('textureOffset'), 0.0); + if (typeof uvRepeat === 'number') { + uvRepeat = [uvRepeat, uvRepeat]; + } + if (typeof uvOffset === 'number') { + uvOffset = [uvOffset, uvOffset]; + } + var repeatParam = (uvRepeat[0] > 1 || uvRepeat[1] > 1) ? graphicGL.Texture.REPEAT : graphicGL.Texture.CLAMP_TO_EDGE; + var textureOpt = { + anisotropic: 8, + wrapS: repeatParam, + wrapT: repeatParam + }; + if (shading === 'realistic') { + var roughness = materialModel.get('roughness'); + var metalness = materialModel.get('metalness'); + if (metalness != null) { + // Try to treat as a texture, TODO More check + if (isNaN(metalness)) { + material.setTextureImage('metalnessMap', metalness, api, textureOpt); + metalness = __WEBPACK_IMPORTED_MODULE_16__retrieve__["a" /* default */].firstNotNull(materialModel.get('metalnessAdjust'), 0.5); + } + } + else { + // Default metalness. + metalness = 0; + } + if (roughness != null) { + // Try to treat as a texture, TODO More check + if (isNaN(roughness)) { + material.setTextureImage('roughnessMap', roughness, api, textureOpt); + roughness = __WEBPACK_IMPORTED_MODULE_16__retrieve__["a" /* default */].firstNotNull(materialModel.get('roughnessAdjust'), 0.5); + } + } + else { + // Default roughness. + roughness = 0.5; + } + var normalTextureVal = materialModel.get('normalTexture'); + material.setTextureImage('detailMap', detailTexture, api, textureOpt); + material.setTextureImage('normalMap', normalTextureVal, api, textureOpt); + material.set({ + roughness: roughness, + metalness: metalness, + detailUvRepeat: uvRepeat, + detailUvOffset: uvOffset + }); + // var normalTexture = material.get('normalMap'); + // if (normalTexture) { + // PENDING + // normalTexture.format = Texture.SRGB; + // } + } + else if (shading === 'lambert') { + material.setTextureImage('detailMap', detailTexture, api, textureOpt); + material.set({ + detailUvRepeat: uvRepeat, + detailUvOffset: uvOffset + }); + } + else if (shading === 'color') { + material.setTextureImage('detailMap', detailTexture, api, textureOpt); + material.set({ + detailUvRepeat: uvRepeat, + detailUvOffset: uvOffset + }); + } + else if (shading === 'hatching') { + var tams = materialModel.get('hatchingTextures') || []; + if (tams.length < 6) { + if (true) { + console.error('Invalid hatchingTextures.'); + } + } + for (var i = 0; i < 6; i++) { + material.setTextureImage('hatch' + (i + 1), tams[i], api, { + anisotropic: 8, + wrapS: graphicGL.Texture.REPEAT, + wrapT: graphicGL.Texture.REPEAT + }); + } + material.set({ + detailUvRepeat: uvRepeat, + detailUvOffset: uvOffset + }); + } +}; + +graphicGL.updateVertexAnimation = function ( + mappingAttributes, previousMesh, currentMesh, seriesModel +) { + var enableAnimation = seriesModel.get('animation'); + var duration = seriesModel.get('animationDurationUpdate'); + var easing = seriesModel.get('animationEasingUpdate'); + var shadowDepthMaterial = currentMesh.shadowDepthMaterial; + + if (enableAnimation && previousMesh && duration > 0 + // Only animate when bar count are not changed + && previousMesh.geometry.vertexCount === currentMesh.geometry.vertexCount + ) { + currentMesh.material.define('vertex', 'VERTEX_ANIMATION'); + currentMesh.ignorePreZ = true; + if (shadowDepthMaterial) { + shadowDepthMaterial.define('vertex', 'VERTEX_ANIMATION'); + } + for (var i = 0; i < mappingAttributes.length; i++) { + currentMesh.geometry.attributes[mappingAttributes[i][0]].value = + previousMesh.geometry.attributes[mappingAttributes[i][1]].value; + } + currentMesh.geometry.dirty(); + currentMesh.__percent = 0; + currentMesh.material.set('percent', 0); + currentMesh.stopAnimation(); + currentMesh.animate() + .when(duration, { + __percent: 1 + }) + .during(function () { + currentMesh.material.set('percent', currentMesh.__percent); + if (shadowDepthMaterial) { + shadowDepthMaterial.set('percent', currentMesh.__percent); + } + }) + .done(function () { + currentMesh.ignorePreZ = false; + currentMesh.material.undefine('vertex', 'VERTEX_ANIMATION'); + if (shadowDepthMaterial) { + shadowDepthMaterial.undefine('vertex', 'VERTEX_ANIMATION'); + } + }) + .start(easing); + } + else { + currentMesh.material.undefine('vertex', 'VERTEX_ANIMATION'); + if (shadowDepthMaterial) { + shadowDepthMaterial.undefine('vertex', 'VERTEX_ANIMATION'); + } + } +}; + +/* harmony default export */ __webpack_exports__["a"] = (graphicGL); + +/***/ }), +/* 2 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__); + + +var retrieve = { + + firstNotNull: function () { + for (var i = 0, len = arguments.length; i < len; i++) { + if (arguments[i] != null) { + return arguments[i]; + } + } + }, + + /** + * @param {module:echarts/data/List} data + * @param {Object} payload Contains dataIndex (means rawIndex) / dataIndexInside / name + * each of which can be Array or primary type. + * @return {number|Array.} dataIndex If not found, return undefined/null. + */ + queryDataIndex: function (data, payload) { + if (payload.dataIndexInside != null) { + return payload.dataIndexInside; + } + else if (payload.dataIndex != null) { + return __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.util.isArray(payload.dataIndex) + ? __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.util.map(payload.dataIndex, function (value) { + return data.indexOfRawIndex(value); + }) + : data.indexOfRawIndex(payload.dataIndex); + } + else if (payload.name != null) { + return __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.util.isArray(payload.name) + ? __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.util.map(payload.name, function (value) { + return data.indexOfName(value); + }) + : data.indexOfName(payload.name); + } + } +}; + +/* harmony default export */ __webpack_exports__["a"] = (retrieve); + +/***/ }), +/* 3 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec3__ = __webpack_require__(12); + + +/** + * @constructor + * @alias clay.Vector3 + * @param {number} x + * @param {number} y + * @param {number} z + */ +var Vector3 = function(x, y, z) { + + x = x || 0; + y = y || 0; + z = z || 0; + + /** + * Storage of Vector3, read and write of x, y, z will change the values in array + * All methods also operate on the array instead of x, y, z components + * @name array + * @type {Float32Array} + * @memberOf clay.Vector3# + */ + this.array = __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec3__["a" /* default */].fromValues(x, y, z); + + /** + * Dirty flag is used by the Node to determine + * if the matrix is updated to latest + * @name _dirty + * @type {boolean} + * @memberOf clay.Vector3# + */ + this._dirty = true; +}; + +Vector3.prototype = { + + constructor: Vector3, + + /** + * Add b to self + * @param {clay.Vector3} b + * @return {clay.Vector3} + */ + add: function (b) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec3__["a" /* default */].add(this.array, this.array, b.array); + this._dirty = true; + return this; + }, + + /** + * Set x, y and z components + * @param {number} x + * @param {number} y + * @param {number} z + * @return {clay.Vector3} + */ + set: function (x, y, z) { + this.array[0] = x; + this.array[1] = y; + this.array[2] = z; + this._dirty = true; + return this; + }, + + /** + * Set x, y and z components from array + * @param {Float32Array|number[]} arr + * @return {clay.Vector3} + */ + setArray: function (arr) { + this.array[0] = arr[0]; + this.array[1] = arr[1]; + this.array[2] = arr[2]; + + this._dirty = true; + return this; + }, + + /** + * Clone a new Vector3 + * @return {clay.Vector3} + */ + clone: function () { + return new Vector3(this.x, this.y, this.z); + }, + + /** + * Copy from b + * @param {clay.Vector3} b + * @return {clay.Vector3} + */ + copy: function (b) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec3__["a" /* default */].copy(this.array, b.array); + this._dirty = true; + return this; + }, + + /** + * Cross product of self and b, written to a Vector3 out + * @param {clay.Vector3} a + * @param {clay.Vector3} b + * @return {clay.Vector3} + */ + cross: function (a, b) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec3__["a" /* default */].cross(this.array, a.array, b.array); + this._dirty = true; + return this; + }, + + /** + * Alias for distance + * @param {clay.Vector3} b + * @return {number} + */ + dist: function (b) { + return __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec3__["a" /* default */].dist(this.array, b.array); + }, + + /** + * Distance between self and b + * @param {clay.Vector3} b + * @return {number} + */ + distance: function (b) { + return __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec3__["a" /* default */].distance(this.array, b.array); + }, + + /** + * Alias for divide + * @param {clay.Vector3} b + * @return {clay.Vector3} + */ + div: function (b) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec3__["a" /* default */].div(this.array, this.array, b.array); + this._dirty = true; + return this; + }, + + /** + * Divide self by b + * @param {clay.Vector3} b + * @return {clay.Vector3} + */ + divide: function (b) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec3__["a" /* default */].divide(this.array, this.array, b.array); + this._dirty = true; + return this; + }, + + /** + * Dot product of self and b + * @param {clay.Vector3} b + * @return {number} + */ + dot: function (b) { + return __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec3__["a" /* default */].dot(this.array, b.array); + }, + + /** + * Alias of length + * @return {number} + */ + len: function () { + return __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec3__["a" /* default */].len(this.array); + }, + + /** + * Calculate the length + * @return {number} + */ + length: function () { + return __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec3__["a" /* default */].length(this.array); + }, + /** + * Linear interpolation between a and b + * @param {clay.Vector3} a + * @param {clay.Vector3} b + * @param {number} t + * @return {clay.Vector3} + */ + lerp: function (a, b, t) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec3__["a" /* default */].lerp(this.array, a.array, b.array, t); + this._dirty = true; + return this; + }, + + /** + * Minimum of self and b + * @param {clay.Vector3} b + * @return {clay.Vector3} + */ + min: function (b) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec3__["a" /* default */].min(this.array, this.array, b.array); + this._dirty = true; + return this; + }, + + /** + * Maximum of self and b + * @param {clay.Vector3} b + * @return {clay.Vector3} + */ + max: function (b) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec3__["a" /* default */].max(this.array, this.array, b.array); + this._dirty = true; + return this; + }, + + /** + * Alias for multiply + * @param {clay.Vector3} b + * @return {clay.Vector3} + */ + mul: function (b) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec3__["a" /* default */].mul(this.array, this.array, b.array); + this._dirty = true; + return this; + }, + + /** + * Mutiply self and b + * @param {clay.Vector3} b + * @return {clay.Vector3} + */ + multiply: function (b) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec3__["a" /* default */].multiply(this.array, this.array, b.array); + this._dirty = true; + return this; + }, + + /** + * Negate self + * @return {clay.Vector3} + */ + negate: function () { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec3__["a" /* default */].negate(this.array, this.array); + this._dirty = true; + return this; + }, + + /** + * Normalize self + * @return {clay.Vector3} + */ + normalize: function () { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec3__["a" /* default */].normalize(this.array, this.array); + this._dirty = true; + return this; + }, + + /** + * Generate random x, y, z components with a given scale + * @param {number} scale + * @return {clay.Vector3} + */ + random: function (scale) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec3__["a" /* default */].random(this.array, scale); + this._dirty = true; + return this; + }, + + /** + * Scale self + * @param {number} scale + * @return {clay.Vector3} + */ + scale: function (s) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec3__["a" /* default */].scale(this.array, this.array, s); + this._dirty = true; + return this; + }, + + /** + * Scale b and add to self + * @param {clay.Vector3} b + * @param {number} scale + * @return {clay.Vector3} + */ + scaleAndAdd: function (b, s) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec3__["a" /* default */].scaleAndAdd(this.array, this.array, b.array, s); + this._dirty = true; + return this; + }, + + /** + * Alias for squaredDistance + * @param {clay.Vector3} b + * @return {number} + */ + sqrDist: function (b) { + return __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec3__["a" /* default */].sqrDist(this.array, b.array); + }, + + /** + * Squared distance between self and b + * @param {clay.Vector3} b + * @return {number} + */ + squaredDistance: function (b) { + return __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec3__["a" /* default */].squaredDistance(this.array, b.array); + }, + + /** + * Alias for squaredLength + * @return {number} + */ + sqrLen: function () { + return __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec3__["a" /* default */].sqrLen(this.array); + }, + + /** + * Squared length of self + * @return {number} + */ + squaredLength: function () { + return __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec3__["a" /* default */].squaredLength(this.array); + }, + + /** + * Alias for subtract + * @param {clay.Vector3} b + * @return {clay.Vector3} + */ + sub: function (b) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec3__["a" /* default */].sub(this.array, this.array, b.array); + this._dirty = true; + return this; + }, + + /** + * Subtract b from self + * @param {clay.Vector3} b + * @return {clay.Vector3} + */ + subtract: function (b) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec3__["a" /* default */].subtract(this.array, this.array, b.array); + this._dirty = true; + return this; + }, + + /** + * Transform self with a Matrix3 m + * @param {clay.Matrix3} m + * @return {clay.Vector3} + */ + transformMat3: function (m) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec3__["a" /* default */].transformMat3(this.array, this.array, m.array); + this._dirty = true; + return this; + }, + + /** + * Transform self with a Matrix4 m + * @param {clay.Matrix4} m + * @return {clay.Vector3} + */ + transformMat4: function (m) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec3__["a" /* default */].transformMat4(this.array, this.array, m.array); + this._dirty = true; + return this; + }, + /** + * Transform self with a Quaternion q + * @param {clay.Quaternion} q + * @return {clay.Vector3} + */ + transformQuat: function (q) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec3__["a" /* default */].transformQuat(this.array, this.array, q.array); + this._dirty = true; + return this; + }, + + /** + * Trasnform self into projection space with m + * @param {clay.Matrix4} m + * @return {clay.Vector3} + */ + applyProjection: function (m) { + var v = this.array; + m = m.array; + + // Perspective projection + if (m[15] === 0) { + var w = -1 / v[2]; + v[0] = m[0] * v[0] * w; + v[1] = m[5] * v[1] * w; + v[2] = (m[10] * v[2] + m[14]) * w; + } + else { + v[0] = m[0] * v[0] + m[12]; + v[1] = m[5] * v[1] + m[13]; + v[2] = m[10] * v[2] + m[14]; + } + this._dirty = true; + + return this; + }, + + eulerFromQuat: function(q, order) { + Vector3.eulerFromQuat(this, q, order); + }, + + eulerFromMat3: function (m, order) { + Vector3.eulerFromMat3(this, m, order); + }, + + toString: function() { + return '[' + Array.prototype.join.call(this.array, ',') + ']'; + }, + + toArray: function () { + return Array.prototype.slice.call(this.array); + } +}; + +var defineProperty = Object.defineProperty; +// Getter and Setter +if (defineProperty) { + + var proto = Vector3.prototype; + /** + * @name x + * @type {number} + * @memberOf clay.Vector3 + * @instance + */ + defineProperty(proto, 'x', { + get: function () { + return this.array[0]; + }, + set: function (value) { + this.array[0] = value; + this._dirty = true; + } + }); + + /** + * @name y + * @type {number} + * @memberOf clay.Vector3 + * @instance + */ + defineProperty(proto, 'y', { + get: function () { + return this.array[1]; + }, + set: function (value) { + this.array[1] = value; + this._dirty = true; + } + }); + + /** + * @name z + * @type {number} + * @memberOf clay.Vector3 + * @instance + */ + defineProperty(proto, 'z', { + get: function () { + return this.array[2]; + }, + set: function (value) { + this.array[2] = value; + this._dirty = true; + } + }); +} + + +// Supply methods that are not in place + +/** + * @param {clay.Vector3} out + * @param {clay.Vector3} a + * @param {clay.Vector3} b + * @return {clay.Vector3} + */ +Vector3.add = function(out, a, b) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec3__["a" /* default */].add(out.array, a.array, b.array); + out._dirty = true; + return out; +}; + +/** + * @param {clay.Vector3} out + * @param {number} x + * @param {number} y + * @param {number} z + * @return {clay.Vector3} + */ +Vector3.set = function(out, x, y, z) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec3__["a" /* default */].set(out.array, x, y, z); + out._dirty = true; +}; + +/** + * @param {clay.Vector3} out + * @param {clay.Vector3} b + * @return {clay.Vector3} + */ +Vector3.copy = function(out, b) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec3__["a" /* default */].copy(out.array, b.array); + out._dirty = true; + return out; +}; + +/** + * @param {clay.Vector3} out + * @param {clay.Vector3} a + * @param {clay.Vector3} b + * @return {clay.Vector3} + */ +Vector3.cross = function(out, a, b) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec3__["a" /* default */].cross(out.array, a.array, b.array); + out._dirty = true; + return out; +}; + +/** + * @param {clay.Vector3} a + * @param {clay.Vector3} b + * @return {number} + */ +Vector3.dist = function(a, b) { + return __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec3__["a" /* default */].distance(a.array, b.array); +}; + +/** + * @function + * @param {clay.Vector3} a + * @param {clay.Vector3} b + * @return {number} + */ +Vector3.distance = Vector3.dist; + +/** + * @param {clay.Vector3} out + * @param {clay.Vector3} a + * @param {clay.Vector3} b + * @return {clay.Vector3} + */ +Vector3.div = function(out, a, b) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec3__["a" /* default */].divide(out.array, a.array, b.array); + out._dirty = true; + return out; +}; + +/** + * @function + * @param {clay.Vector3} out + * @param {clay.Vector3} a + * @param {clay.Vector3} b + * @return {clay.Vector3} + */ +Vector3.divide = Vector3.div; + +/** + * @param {clay.Vector3} a + * @param {clay.Vector3} b + * @return {number} + */ +Vector3.dot = function(a, b) { + return __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec3__["a" /* default */].dot(a.array, b.array); +}; + +/** + * @param {clay.Vector3} a + * @return {number} + */ +Vector3.len = function(b) { + return __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec3__["a" /* default */].length(b.array); +}; + +// Vector3.length = Vector3.len; + +/** + * @param {clay.Vector3} out + * @param {clay.Vector3} a + * @param {clay.Vector3} b + * @param {number} t + * @return {clay.Vector3} + */ +Vector3.lerp = function(out, a, b, t) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec3__["a" /* default */].lerp(out.array, a.array, b.array, t); + out._dirty = true; + return out; +}; +/** + * @param {clay.Vector3} out + * @param {clay.Vector3} a + * @param {clay.Vector3} b + * @return {clay.Vector3} + */ +Vector3.min = function(out, a, b) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec3__["a" /* default */].min(out.array, a.array, b.array); + out._dirty = true; + return out; +}; + +/** + * @param {clay.Vector3} out + * @param {clay.Vector3} a + * @param {clay.Vector3} b + * @return {clay.Vector3} + */ +Vector3.max = function(out, a, b) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec3__["a" /* default */].max(out.array, a.array, b.array); + out._dirty = true; + return out; +}; +/** + * @param {clay.Vector3} out + * @param {clay.Vector3} a + * @param {clay.Vector3} b + * @return {clay.Vector3} + */ +Vector3.mul = function(out, a, b) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec3__["a" /* default */].multiply(out.array, a.array, b.array); + out._dirty = true; + return out; +}; +/** + * @function + * @param {clay.Vector3} out + * @param {clay.Vector3} a + * @param {clay.Vector3} b + * @return {clay.Vector3} + */ +Vector3.multiply = Vector3.mul; +/** + * @param {clay.Vector3} out + * @param {clay.Vector3} a + * @return {clay.Vector3} + */ +Vector3.negate = function(out, a) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec3__["a" /* default */].negate(out.array, a.array); + out._dirty = true; + return out; +}; +/** + * @param {clay.Vector3} out + * @param {clay.Vector3} a + * @return {clay.Vector3} + */ +Vector3.normalize = function(out, a) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec3__["a" /* default */].normalize(out.array, a.array); + out._dirty = true; + return out; +}; +/** + * @param {clay.Vector3} out + * @param {number} scale + * @return {clay.Vector3} + */ +Vector3.random = function(out, scale) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec3__["a" /* default */].random(out.array, scale); + out._dirty = true; + return out; +}; +/** + * @param {clay.Vector3} out + * @param {clay.Vector3} a + * @param {number} scale + * @return {clay.Vector3} + */ +Vector3.scale = function(out, a, scale) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec3__["a" /* default */].scale(out.array, a.array, scale); + out._dirty = true; + return out; +}; +/** + * @param {clay.Vector3} out + * @param {clay.Vector3} a + * @param {clay.Vector3} b + * @param {number} scale + * @return {clay.Vector3} + */ +Vector3.scaleAndAdd = function(out, a, b, scale) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec3__["a" /* default */].scaleAndAdd(out.array, a.array, b.array, scale); + out._dirty = true; + return out; +}; +/** + * @param {clay.Vector3} a + * @param {clay.Vector3} b + * @return {number} + */ +Vector3.sqrDist = function(a, b) { + return __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec3__["a" /* default */].sqrDist(a.array, b.array); +}; +/** + * @function + * @param {clay.Vector3} a + * @param {clay.Vector3} b + * @return {number} + */ +Vector3.squaredDistance = Vector3.sqrDist; +/** + * @param {clay.Vector3} a + * @return {number} + */ +Vector3.sqrLen = function(a) { + return __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec3__["a" /* default */].sqrLen(a.array); +}; +/** + * @function + * @param {clay.Vector3} a + * @return {number} + */ +Vector3.squaredLength = Vector3.sqrLen; + +/** + * @param {clay.Vector3} out + * @param {clay.Vector3} a + * @param {clay.Vector3} b + * @return {clay.Vector3} + */ +Vector3.sub = function(out, a, b) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec3__["a" /* default */].subtract(out.array, a.array, b.array); + out._dirty = true; + return out; +}; +/** + * @function + * @param {clay.Vector3} out + * @param {clay.Vector3} a + * @param {clay.Vector3} b + * @return {clay.Vector3} + */ +Vector3.subtract = Vector3.sub; + +/** + * @param {clay.Vector3} out + * @param {clay.Vector3} a + * @param {Matrix3} m + * @return {clay.Vector3} + */ +Vector3.transformMat3 = function(out, a, m) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec3__["a" /* default */].transformMat3(out.array, a.array, m.array); + out._dirty = true; + return out; +}; + +/** + * @param {clay.Vector3} out + * @param {clay.Vector3} a + * @param {clay.Matrix4} m + * @return {clay.Vector3} + */ +Vector3.transformMat4 = function(out, a, m) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec3__["a" /* default */].transformMat4(out.array, a.array, m.array); + out._dirty = true; + return out; +}; +/** + * @param {clay.Vector3} out + * @param {clay.Vector3} a + * @param {clay.Quaternion} q + * @return {clay.Vector3} + */ +Vector3.transformQuat = function(out, a, q) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec3__["a" /* default */].transformQuat(out.array, a.array, q.array); + out._dirty = true; + return out; +}; + +function clamp(val, min, max) { + return val < min ? min : (val > max ? max : val); +} +var atan2 = Math.atan2; +var asin = Math.asin; +var abs = Math.abs; +/** + * Convert quaternion to euler angle + * Quaternion must be normalized + * From three.js + */ +Vector3.eulerFromQuat = function (out, q, order) { + out._dirty = true; + q = q.array; + + var target = out.array; + var x = q[0], y = q[1], z = q[2], w = q[3]; + var x2 = x * x; + var y2 = y * y; + var z2 = z * z; + var w2 = w * w; + + var order = (order || 'XYZ').toUpperCase(); + + switch (order) { + case 'XYZ': + target[0] = atan2(2 * (x * w - y * z), (w2 - x2 - y2 + z2)); + target[1] = asin(clamp(2 * (x * z + y * w), - 1, 1)); + target[2] = atan2(2 * (z * w - x * y), (w2 + x2 - y2 - z2)); + break; + case 'YXZ': + target[0] = asin(clamp(2 * (x * w - y * z), - 1, 1)); + target[1] = atan2(2 * (x * z + y * w), (w2 - x2 - y2 + z2)); + target[2] = atan2(2 * (x * y + z * w), (w2 - x2 + y2 - z2)); + break; + case 'ZXY': + target[0] = asin(clamp(2 * (x * w + y * z), - 1, 1)); + target[1] = atan2(2 * (y * w - z * x), (w2 - x2 - y2 + z2)); + target[2] = atan2(2 * (z * w - x * y), (w2 - x2 + y2 - z2)); + break; + case 'ZYX': + target[0] = atan2(2 * (x * w + z * y), (w2 - x2 - y2 + z2)); + target[1] = asin(clamp(2 * (y * w - x * z), - 1, 1)); + target[2] = atan2(2 * (x * y + z * w), (w2 + x2 - y2 - z2)); + break; + case 'YZX': + target[0] = atan2(2 * (x * w - z * y), (w2 - x2 + y2 - z2)); + target[1] = atan2(2 * (y * w - x * z), (w2 + x2 - y2 - z2)); + target[2] = asin(clamp(2 * (x * y + z * w), - 1, 1)); + break; + case 'XZY': + target[0] = atan2(2 * (x * w + y * z), (w2 - x2 + y2 - z2)); + target[1] = atan2(2 * (x * z + y * w), (w2 + x2 - y2 - z2)); + target[2] = asin(clamp(2 * (z * w - x * y), - 1, 1)); + break; + default: + console.warn('Unkown order: ' + order); + } + return out; +}; + +/** + * Convert rotation matrix to euler angle + * from three.js + */ +Vector3.eulerFromMat3 = function (out, m, order) { + // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled) + var te = m.array; + var m11 = te[0], m12 = te[3], m13 = te[6]; + var m21 = te[1], m22 = te[4], m23 = te[7]; + var m31 = te[2], m32 = te[5], m33 = te[8]; + var target = out.array; + + var order = (order || 'XYZ').toUpperCase(); + + switch (order) { + case 'XYZ': + target[1] = asin(clamp(m13, -1, 1)); + if (abs(m13) < 0.99999) { + target[0] = atan2(-m23, m33); + target[2] = atan2(-m12, m11); + } + else { + target[0] = atan2(m32, m22); + target[2] = 0; + } + break; + case 'YXZ': + target[0] = asin(-clamp(m23, -1, 1)); + if (abs(m23) < 0.99999) { + target[1] = atan2(m13, m33); + target[2] = atan2(m21, m22); + } + else { + target[1] = atan2(-m31, m11); + target[2] = 0; + } + break; + case 'ZXY': + target[0] = asin(clamp(m32, -1, 1)); + if (abs(m32) < 0.99999) { + target[1] = atan2(-m31, m33); + target[2] = atan2(-m12, m22); + } + else { + target[1] = 0; + target[2] = atan2(m21, m11); + } + break; + case 'ZYX': + target[1] = asin(-clamp(m31, -1, 1)); + if (abs(m31) < 0.99999) { + target[0] = atan2(m32, m33); + target[2] = atan2(m21, m11); + } + else { + target[0] = 0; + target[2] = atan2(-m12, m22); + } + break; + case 'YZX': + target[2] = asin(clamp(m21, -1, 1)); + if (abs(m21) < 0.99999) { + target[0] = atan2(-m23, m22); + target[1] = atan2(-m31, m11); + } + else { + target[0] = 0; + target[1] = atan2(m13, m33); + } + break; + case 'XZY': + target[2] = asin(-clamp(m12, -1, 1)); + if (abs(m12) < 0.99999) { + target[0] = atan2(m32, m22); + target[1] = atan2(m13, m11); + } + else { + target[0] = atan2(-m23, m33); + target[1] = 0; + } + break; + default: + console.warn('Unkown order: ' + order); + } + out._dirty = true; + + return out; +}; + +Object.defineProperties(Vector3, { + /** + * @type {clay.Vector3} + * @readOnly + * @memberOf clay.Vector3 + */ + POSITIVE_X: { + get: function () { + return new Vector3(1, 0, 0); + } + }, + /** + * @type {clay.Vector3} + * @readOnly + * @memberOf clay.Vector3 + */ + NEGATIVE_X: { + get: function () { + return new Vector3(-1, 0, 0); + } + }, + /** + * @type {clay.Vector3} + * @readOnly + * @memberOf clay.Vector3 + */ + POSITIVE_Y: { + get: function () { + return new Vector3(0, 1, 0); + } + }, + /** + * @type {clay.Vector3} + * @readOnly + * @memberOf clay.Vector3 + */ + NEGATIVE_Y: { + get: function () { + return new Vector3(0, -1, 0); + } + }, + /** + * @type {clay.Vector3} + * @readOnly + * @memberOf clay.Vector3 + */ + POSITIVE_Z: { + get: function () { + return new Vector3(0, 0, 1); + } + }, + /** + * @type {clay.Vector3} + * @readOnly + */ + NEGATIVE_Z: { + get: function () { + return new Vector3(0, 0, -1); + } + }, + /** + * @type {clay.Vector3} + * @readOnly + * @memberOf clay.Vector3 + */ + UP: { + get: function () { + return new Vector3(0, 1, 0); + } + }, + /** + * @type {clay.Vector3} + * @readOnly + * @memberOf clay.Vector3 + */ + ZERO: { + get: function () { + return new Vector3(); + } + } +}); + +/* harmony default export */ __webpack_exports__["a"] = (Vector3); + + +/***/ }), +/* 4 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__core_Base__ = __webpack_require__(7); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__core_glenum__ = __webpack_require__(11); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__core_Cache__ = __webpack_require__(57); +/** + * Base class for all textures like compressed texture, texture2d, texturecube + * TODO mapping + */ + + + + +/** + * @constructor + * @alias clay.Texture + * @extends clay.core.Base + */ +var Texture = __WEBPACK_IMPORTED_MODULE_0__core_Base__["a" /* default */].extend( /** @lends clay.Texture# */ { + /** + * Texture width, readonly when the texture source is image + * @type {number} + */ + width: 512, + /** + * Texture height, readonly when the texture source is image + * @type {number} + */ + height: 512, + /** + * Texel data type. + * Possible values: + * + {@link clay.Texture.UNSIGNED_BYTE} + * + {@link clay.Texture.HALF_FLOAT} + * + {@link clay.Texture.FLOAT} + * + {@link clay.Texture.UNSIGNED_INT_24_8_WEBGL} + * + {@link clay.Texture.UNSIGNED_INT} + * @type {number} + */ + type: __WEBPACK_IMPORTED_MODULE_1__core_glenum__["a" /* default */].UNSIGNED_BYTE, + /** + * Format of texel data + * Possible values: + * + {@link clay.Texture.RGBA} + * + {@link clay.Texture.DEPTH_COMPONENT} + * + {@link clay.Texture.DEPTH_STENCIL} + * @type {number} + */ + format: __WEBPACK_IMPORTED_MODULE_1__core_glenum__["a" /* default */].RGBA, + /** + * Texture wrap. Default to be REPEAT. + * Possible values: + * + {@link clay.Texture.CLAMP_TO_EDGE} + * + {@link clay.Texture.REPEAT} + * + {@link clay.Texture.MIRRORED_REPEAT} + * @type {number} + */ + wrapS: __WEBPACK_IMPORTED_MODULE_1__core_glenum__["a" /* default */].REPEAT, + /** + * Texture wrap. Default to be REPEAT. + * Possible values: + * + {@link clay.Texture.CLAMP_TO_EDGE} + * + {@link clay.Texture.REPEAT} + * + {@link clay.Texture.MIRRORED_REPEAT} + * @type {number} + */ + wrapT: __WEBPACK_IMPORTED_MODULE_1__core_glenum__["a" /* default */].REPEAT, + /** + * Possible values: + * + {@link clay.Texture.NEAREST} + * + {@link clay.Texture.LINEAR} + * + {@link clay.Texture.NEAREST_MIPMAP_NEAREST} + * + {@link clay.Texture.LINEAR_MIPMAP_NEAREST} + * + {@link clay.Texture.NEAREST_MIPMAP_LINEAR} + * + {@link clay.Texture.LINEAR_MIPMAP_LINEAR} + * @type {number} + */ + minFilter: __WEBPACK_IMPORTED_MODULE_1__core_glenum__["a" /* default */].LINEAR_MIPMAP_LINEAR, + /** + * Possible values: + * + {@link clay.Texture.NEAREST} + * + {@link clay.Texture.LINEAR} + * @type {number} + */ + magFilter: __WEBPACK_IMPORTED_MODULE_1__core_glenum__["a" /* default */].LINEAR, + /** + * If enable mimap. + * @type {boolean} + */ + useMipmap: true, + + /** + * Anisotropic filtering, enabled if value is larger than 1 + * @see https://developer.mozilla.org/en-US/docs/Web/API/EXT_texture_filter_anisotropic + * @type {number} + */ + anisotropic: 1, + // pixelStorei parameters, not available when texture is used as render target + // http://www.khronos.org/opengles/sdk/docs/man/xhtml/glPixelStorei.xml + /** + * If flip in y axis for given image source + * @type {boolean} + * @default true + */ + flipY: true, + + /** + * A flag to indicate if texture source is sRGB + */ + sRGB: true, + /** + * @type {number} + * @default 4 + */ + unpackAlignment: 4, + /** + * @type {boolean} + * @default false + */ + premultiplyAlpha: false, + + /** + * Dynamic option for texture like video + * @type {boolean} + */ + dynamic: false, + + NPOT: false, + + // PENDING + // Init it here to avoid deoptimization when it's assigned in application dynamically + __used: 0 + +}, function () { + this._cache = new __WEBPACK_IMPORTED_MODULE_2__core_Cache__["a" /* default */](); +}, +/** @lends clay.Texture.prototype */ +{ + + getWebGLTexture: function (renderer) { + var _gl = renderer.gl; + var cache = this._cache; + cache.use(renderer.__uid__); + + if (cache.miss('webgl_texture')) { + // In a new gl context, create new texture and set dirty true + cache.put('webgl_texture', _gl.createTexture()); + } + if (this.dynamic) { + this.update(renderer); + } + else if (cache.isDirty()) { + this.update(renderer); + cache.fresh(); + } + + return cache.get('webgl_texture'); + }, + + bind: function () {}, + unbind: function () {}, + + /** + * Mark texture is dirty and update in the next frame + */ + dirty: function () { + if (this._cache) { + this._cache.dirtyAll(); + } + }, + + update: function (renderer) {}, + + // Update the common parameters of texture + updateCommon: function (renderer) { + var _gl = renderer.gl; + _gl.pixelStorei(_gl.UNPACK_FLIP_Y_WEBGL, this.flipY); + _gl.pixelStorei(_gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, this.premultiplyAlpha); + _gl.pixelStorei(_gl.UNPACK_ALIGNMENT, this.unpackAlignment); + + // Use of none-power of two texture + // http://www.khronos.org/webgl/wiki/WebGL_and_OpenGL_Differences + if (this.format === __WEBPACK_IMPORTED_MODULE_1__core_glenum__["a" /* default */].DEPTH_COMPONENT) { + this.useMipmap = false; + } + + var sRGBExt = renderer.getGLExtension('EXT_sRGB'); + // Fallback + if (this.format === Texture.SRGB && !sRGBExt) { + this.format = Texture.RGB; + } + if (this.format === Texture.SRGB_ALPHA && !sRGBExt) { + this.format = Texture.RGBA; + } + + this.NPOT = !this.isPowerOfTwo(); + }, + + getAvailableWrapS: function () { + if (this.NPOT) { + return __WEBPACK_IMPORTED_MODULE_1__core_glenum__["a" /* default */].CLAMP_TO_EDGE; + } + return this.wrapS; + }, + getAvailableWrapT: function () { + if (this.NPOT) { + return __WEBPACK_IMPORTED_MODULE_1__core_glenum__["a" /* default */].CLAMP_TO_EDGE; + } + return this.wrapT; + }, + getAvailableMinFilter: function () { + var minFilter = this.minFilter; + if (this.NPOT || !this.useMipmap) { + if (minFilter === __WEBPACK_IMPORTED_MODULE_1__core_glenum__["a" /* default */].NEAREST_MIPMAP_NEAREST || + minFilter === __WEBPACK_IMPORTED_MODULE_1__core_glenum__["a" /* default */].NEAREST_MIPMAP_LINEAR + ) { + return __WEBPACK_IMPORTED_MODULE_1__core_glenum__["a" /* default */].NEAREST; + } + else if (minFilter === __WEBPACK_IMPORTED_MODULE_1__core_glenum__["a" /* default */].LINEAR_MIPMAP_LINEAR || + minFilter === __WEBPACK_IMPORTED_MODULE_1__core_glenum__["a" /* default */].LINEAR_MIPMAP_NEAREST + ) { + return __WEBPACK_IMPORTED_MODULE_1__core_glenum__["a" /* default */].LINEAR; + } + else { + return minFilter; + } + } + else { + return minFilter; + } + }, + getAvailableMagFilter: function () { + return this.magFilter; + }, + + nextHighestPowerOfTwo: function (x) { + --x; + for (var i = 1; i < 32; i <<= 1) { + x = x | x >> i; + } + return x + 1; + }, + /** + * @param {clay.Renderer} renderer + */ + dispose: function (renderer) { + + var cache = this._cache; + + cache.use(renderer.__uid__); + + var webglTexture = cache.get('webgl_texture'); + if (webglTexture){ + renderer.gl.deleteTexture(webglTexture); + } + cache.deleteContext(renderer.__uid__); + + }, + /** + * Test if image of texture is valid and loaded. + * @return {boolean} + */ + isRenderable: function () {}, + + /** + * Test if texture size is power of two + * @return {boolean} + */ + isPowerOfTwo: function () {} +}); + +Object.defineProperty(Texture.prototype, 'width', { + get: function () { + return this._width; + }, + set: function (value) { + this._width = value; + } +}); +Object.defineProperty(Texture.prototype, 'height', { + get: function () { + return this._height; + }, + set: function (value) { + this._height = value; + } +}); + +/* DataType */ + +/** + * @type {number} + */ +Texture.BYTE = __WEBPACK_IMPORTED_MODULE_1__core_glenum__["a" /* default */].BYTE; +/** + * @type {number} + */ +Texture.UNSIGNED_BYTE = __WEBPACK_IMPORTED_MODULE_1__core_glenum__["a" /* default */].UNSIGNED_BYTE; +/** + * @type {number} + */ +Texture.SHORT = __WEBPACK_IMPORTED_MODULE_1__core_glenum__["a" /* default */].SHORT; +/** + * @type {number} + */ +Texture.UNSIGNED_SHORT = __WEBPACK_IMPORTED_MODULE_1__core_glenum__["a" /* default */].UNSIGNED_SHORT; +/** + * @type {number} + */ +Texture.INT = __WEBPACK_IMPORTED_MODULE_1__core_glenum__["a" /* default */].INT; +/** + * @type {number} + */ +Texture.UNSIGNED_INT = __WEBPACK_IMPORTED_MODULE_1__core_glenum__["a" /* default */].UNSIGNED_INT; +/** + * @type {number} + */ +Texture.FLOAT = __WEBPACK_IMPORTED_MODULE_1__core_glenum__["a" /* default */].FLOAT; +/** + * @type {number} + */ +Texture.HALF_FLOAT = 0x8D61; + +/** + * UNSIGNED_INT_24_8_WEBGL for WEBGL_depth_texture extension + * @type {number} + */ +Texture.UNSIGNED_INT_24_8_WEBGL = 34042; + +/* PixelFormat */ +/** + * @type {number} + */ +Texture.DEPTH_COMPONENT = __WEBPACK_IMPORTED_MODULE_1__core_glenum__["a" /* default */].DEPTH_COMPONENT; +/** + * @type {number} + */ +Texture.DEPTH_STENCIL = __WEBPACK_IMPORTED_MODULE_1__core_glenum__["a" /* default */].DEPTH_STENCIL; +/** + * @type {number} + */ +Texture.ALPHA = __WEBPACK_IMPORTED_MODULE_1__core_glenum__["a" /* default */].ALPHA; +/** + * @type {number} + */ +Texture.RGB = __WEBPACK_IMPORTED_MODULE_1__core_glenum__["a" /* default */].RGB; +/** + * @type {number} + */ +Texture.RGBA = __WEBPACK_IMPORTED_MODULE_1__core_glenum__["a" /* default */].RGBA; +/** + * @type {number} + */ +Texture.LUMINANCE = __WEBPACK_IMPORTED_MODULE_1__core_glenum__["a" /* default */].LUMINANCE; +/** + * @type {number} + */ +Texture.LUMINANCE_ALPHA = __WEBPACK_IMPORTED_MODULE_1__core_glenum__["a" /* default */].LUMINANCE_ALPHA; + +/** + * @see https://www.khronos.org/registry/webgl/extensions/EXT_sRGB/ + * @type {number} + */ +Texture.SRGB = 0x8C40; +/** + * @see https://www.khronos.org/registry/webgl/extensions/EXT_sRGB/ + * @type {number} + */ +Texture.SRGB_ALPHA = 0x8C42; + +/* Compressed Texture */ +Texture.COMPRESSED_RGB_S3TC_DXT1_EXT = 0x83F0; +Texture.COMPRESSED_RGBA_S3TC_DXT1_EXT = 0x83F1; +Texture.COMPRESSED_RGBA_S3TC_DXT3_EXT = 0x83F2; +Texture.COMPRESSED_RGBA_S3TC_DXT5_EXT = 0x83F3; + +/* TextureMagFilter */ +/** + * @type {number} + */ +Texture.NEAREST = __WEBPACK_IMPORTED_MODULE_1__core_glenum__["a" /* default */].NEAREST; +/** + * @type {number} + */ +Texture.LINEAR = __WEBPACK_IMPORTED_MODULE_1__core_glenum__["a" /* default */].LINEAR; + +/* TextureMinFilter */ +/** + * @type {number} + */ +Texture.NEAREST_MIPMAP_NEAREST = __WEBPACK_IMPORTED_MODULE_1__core_glenum__["a" /* default */].NEAREST_MIPMAP_NEAREST; +/** + * @type {number} + */ +Texture.LINEAR_MIPMAP_NEAREST = __WEBPACK_IMPORTED_MODULE_1__core_glenum__["a" /* default */].LINEAR_MIPMAP_NEAREST; +/** + * @type {number} + */ +Texture.NEAREST_MIPMAP_LINEAR = __WEBPACK_IMPORTED_MODULE_1__core_glenum__["a" /* default */].NEAREST_MIPMAP_LINEAR; +/** + * @type {number} + */ +Texture.LINEAR_MIPMAP_LINEAR = __WEBPACK_IMPORTED_MODULE_1__core_glenum__["a" /* default */].LINEAR_MIPMAP_LINEAR; + +/* TextureWrapMode */ +/** + * @type {number} + */ +Texture.REPEAT = __WEBPACK_IMPORTED_MODULE_1__core_glenum__["a" /* default */].REPEAT; +/** + * @type {number} + */ +Texture.CLAMP_TO_EDGE = __WEBPACK_IMPORTED_MODULE_1__core_glenum__["a" /* default */].CLAMP_TO_EDGE; +/** + * @type {number} + */ +Texture.MIRRORED_REPEAT = __WEBPACK_IMPORTED_MODULE_1__core_glenum__["a" /* default */].MIRRORED_REPEAT; + + +/* harmony default export */ __webpack_exports__["a"] = (Texture); + + +/***/ }), +/* 5 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__Texture__ = __webpack_require__(4); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__core_glenum__ = __webpack_require__(11); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__core_vendor__ = __webpack_require__(14); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__math_util__ = __webpack_require__(73); + + + + +var isPowerOfTwo = __WEBPACK_IMPORTED_MODULE_3__math_util__["a" /* default */].isPowerOfTwo; + +function nearestPowerOfTwo(val) { + return Math.pow(2, Math.round(Math.log(val) / Math.LN2)); +} +function convertTextureToPowerOfTwo(texture, canvas) { + // var canvas = document.createElement('canvas'); + var width = nearestPowerOfTwo(texture.width); + var height = nearestPowerOfTwo(texture.height); + canvas = canvas || document.createElement('canvas'); + canvas.width = width; + canvas.height = height; + var ctx = canvas.getContext('2d'); + ctx.drawImage(texture.image, 0, 0, width, height); + + return canvas; +} + +/** + * @constructor clay.Texture2D + * @extends clay.Texture + * + * @example + * ... + * var mat = new clay.Material({ + * shader: clay.shader.library.get('clay.phong', 'diffuseMap') + * }); + * var diffuseMap = new clay.Texture2D(); + * diffuseMap.load('assets/textures/diffuse.jpg'); + * mat.set('diffuseMap', diffuseMap); + * ... + * diffuseMap.success(function () { + * // Wait for the diffuse texture loaded + * animation.on('frame', function (frameTime) { + * renderer.render(scene, camera); + * }); + * }); + */ +var Texture2D = __WEBPACK_IMPORTED_MODULE_0__Texture__["a" /* default */].extend(function () { + return /** @lends clay.Texture2D# */ { + /** + * @type {?HTMLImageElement|HTMLCanvasElemnet} + */ + // TODO mark dirty when assigned. + image: null, + /** + * Pixels data. Will be ignored if image is set. + * @type {?Uint8Array|Float32Array} + */ + pixels: null, + /** + * @type {Array.} + * @example + * [{ + * image: mipmap0, + * pixels: null + * }, { + * image: mipmap1, + * pixels: null + * }, ....] + */ + mipmaps: [], + + /** + * If convert texture to power-of-two + * @type {boolean} + */ + convertToPOT: false + }; +}, { + + textureType: 'texture2D', + + update: function (renderer) { + + var _gl = renderer.gl; + _gl.bindTexture(_gl.TEXTURE_2D, this._cache.get('webgl_texture')); + + this.updateCommon(renderer); + + var glFormat = this.format; + var glType = this.type; + + // Convert to pot is only available when using image/canvas/video element. + var convertToPOT = !!(this.convertToPOT + && !this.mipmaps.length && this.image + && (this.wrapS === __WEBPACK_IMPORTED_MODULE_0__Texture__["a" /* default */].REPEAT || this.wrapT === __WEBPACK_IMPORTED_MODULE_0__Texture__["a" /* default */].REPEAT) + && this.NPOT + ); + + _gl.texParameteri(_gl.TEXTURE_2D, _gl.TEXTURE_WRAP_S, convertToPOT ? this.wrapS : this.getAvailableWrapS()); + _gl.texParameteri(_gl.TEXTURE_2D, _gl.TEXTURE_WRAP_T, convertToPOT ? this.wrapT : this.getAvailableWrapT()); + + _gl.texParameteri(_gl.TEXTURE_2D, _gl.TEXTURE_MAG_FILTER, convertToPOT ? this.magFilter : this.getAvailableMagFilter()); + _gl.texParameteri(_gl.TEXTURE_2D, _gl.TEXTURE_MIN_FILTER, convertToPOT ? this.minFilter : this.getAvailableMinFilter()); + + var anisotropicExt = renderer.getGLExtension('EXT_texture_filter_anisotropic'); + if (anisotropicExt && this.anisotropic > 1) { + _gl.texParameterf(_gl.TEXTURE_2D, anisotropicExt.TEXTURE_MAX_ANISOTROPY_EXT, this.anisotropic); + } + + // Fallback to float type if browser don't have half float extension + if (glType === 36193) { + var halfFloatExt = renderer.getGLExtension('OES_texture_half_float'); + if (!halfFloatExt) { + glType = __WEBPACK_IMPORTED_MODULE_1__core_glenum__["a" /* default */].FLOAT; + } + } + + if (this.mipmaps.length) { + var width = this.width; + var height = this.height; + for (var i = 0; i < this.mipmaps.length; i++) { + var mipmap = this.mipmaps[i]; + this._updateTextureData(_gl, mipmap, i, width, height, glFormat, glType, false); + width /= 2; + height /= 2; + } + } + else { + this._updateTextureData(_gl, this, 0, this.width, this.height, glFormat, glType, convertToPOT); + + if (this.useMipmap && (!this.NPOT || convertToPOT)) { + _gl.generateMipmap(_gl.TEXTURE_2D); + } + } + + _gl.bindTexture(_gl.TEXTURE_2D, null); + }, + + _updateTextureData: function (_gl, data, level, width, height, glFormat, glType, convertToPOT) { + if (data.image) { + var imgData = data.image; + if (convertToPOT) { + this._potCanvas = convertTextureToPowerOfTwo(this, this._potCanvas); + imgData = this._potCanvas; + } + _gl.texImage2D(_gl.TEXTURE_2D, level, glFormat, glFormat, glType, imgData); + } + else { + // Can be used as a blank texture when writing render to texture(RTT) + if ( + glFormat <= __WEBPACK_IMPORTED_MODULE_0__Texture__["a" /* default */].COMPRESSED_RGBA_S3TC_DXT5_EXT + && glFormat >= __WEBPACK_IMPORTED_MODULE_0__Texture__["a" /* default */].COMPRESSED_RGB_S3TC_DXT1_EXT + ) { + _gl.compressedTexImage2D(_gl.TEXTURE_2D, level, glFormat, width, height, 0, data.pixels); + } + else { + // Is a render target if pixels is null + _gl.texImage2D(_gl.TEXTURE_2D, level, glFormat, width, height, 0, glFormat, glType, data.pixels); + } + } + }, + + /** + * @param {clay.Renderer} renderer + * @memberOf clay.Texture2D.prototype + */ + generateMipmap: function (renderer) { + var _gl = renderer.gl; + if (this.useMipmap && !this.NPOT) { + _gl.bindTexture(_gl.TEXTURE_2D, this._cache.get('webgl_texture')); + _gl.generateMipmap(_gl.TEXTURE_2D); + } + }, + + isPowerOfTwo: function () { + return isPowerOfTwo(this.width) && isPowerOfTwo(this.height); + }, + + isRenderable: function () { + if (this.image) { + return this.image.nodeName === 'CANVAS' + || this.image.nodeName === 'VIDEO' + || this.image.complete; + } + else { + return !!(this.width && this.height); + } + }, + + bind: function (renderer) { + renderer.gl.bindTexture(renderer.gl.TEXTURE_2D, this.getWebGLTexture(renderer)); + }, + + unbind: function (renderer) { + renderer.gl.bindTexture(renderer.gl.TEXTURE_2D, null); + }, + + load: function (src, crossOrigin) { + var image = __WEBPACK_IMPORTED_MODULE_2__core_vendor__["a" /* default */].createImage(); + if (crossOrigin) { + image.crossOrigin = crossOrigin; + } + var self = this; + image.onload = function () { + self.dirty(); + self.trigger('success', self); + image.onload = null; + }; + image.onerror = function () { + self.trigger('error', self); + image.onerror = null; + }; + + image.src = src; + this.image = image; + + return this; + } +}); + +Object.defineProperty(Texture2D.prototype, 'width', { + get: function () { + if (this.image) { + return this.image.width; + } + return this._width; + }, + set: function (value) { + if (this.image) { + console.warn('Texture from image can\'t set width'); + } + else { + if (this._width !== value) { + this.dirty(); + } + this._width = value; + } + } +}); +Object.defineProperty(Texture2D.prototype, 'height', { + get: function () { + if (this.image) { + return this.image.height; + } + return this._height; + }, + set: function (value) { + if (this.image) { + console.warn('Texture from image can\'t set height'); + } + else { + if (this._height !== value) { + this.dirty(); + } + this._height = value; + } + } +}); + +/* harmony default export */ __webpack_exports__["a"] = (Texture2D); + + +/***/ }), +/* 6 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__glmatrix__ = __webpack_require__(161); +// DEPRECATED + + +/* harmony default export */ __webpack_exports__["a"] = (__WEBPACK_IMPORTED_MODULE_0__glmatrix__["a" /* default */]); + + +/***/ }), +/* 7 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__mixin_extend__ = __webpack_require__(110); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__mixin_notifier__ = __webpack_require__(53); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__util__ = __webpack_require__(23); + + + + +/** + * Base class of all objects + * @constructor + * @alias clay.core.Base + * @mixes clay.core.mixin.notifier + */ +var Base = function () { + /** + * @type {number} + */ + this.__uid__ = __WEBPACK_IMPORTED_MODULE_2__util__["a" /* default */].genGUID(); +}; + +Base.__initializers__ = [ + function (opts) { + __WEBPACK_IMPORTED_MODULE_2__util__["a" /* default */].extend(this, opts); + } +]; + +__WEBPACK_IMPORTED_MODULE_2__util__["a" /* default */].extend(Base, __WEBPACK_IMPORTED_MODULE_0__mixin_extend__["a" /* default */]); +__WEBPACK_IMPORTED_MODULE_2__util__["a" /* default */].extend(Base.prototype, __WEBPACK_IMPORTED_MODULE_1__mixin_notifier__["a" /* default */]); + +/* harmony default export */ __webpack_exports__["a"] = (Base); + + +/***/ }), +/* 8 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__core_util__ = __webpack_require__(23); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__core_vendor__ = __webpack_require__(14); +/** + * Mainly do the parse and compile of shader string + * Support shader code chunk import and export + * Support shader semantics + * http://www.nvidia.com/object/using_sas.html + * https://github.com/KhronosGroup/collada2json/issues/45 + */ + + + +var uniformRegex = /uniform\s+(bool|float|int|vec2|vec3|vec4|ivec2|ivec3|ivec4|mat2|mat3|mat4|sampler2D|samplerCube)\s+([\s\S]*?);/g; +var attributeRegex = /attribute\s+(float|int|vec2|vec3|vec4)\s+([\s\S]*?);/g; +// Only parse number define. +var defineRegex = /#define\s+(\w+)?(\s+[\d-.]+)?\s*;?\s*\n/g; + +var uniformTypeMap = { + 'bool': '1i', + 'int': '1i', + 'sampler2D': 't', + 'samplerCube': 't', + 'float': '1f', + 'vec2': '2f', + 'vec3': '3f', + 'vec4': '4f', + 'ivec2': '2i', + 'ivec3': '3i', + 'ivec4': '4i', + 'mat2': 'm2', + 'mat3': 'm3', + 'mat4': 'm4' +}; + +function createZeroArray(len) { + var arr = []; + for (var i = 0; i < len; i++) { + arr[i] = 0; + } + return arr; +} + +var uniformValueConstructor = { + 'bool': function () { return true; }, + 'int': function () { return 0; }, + 'float': function () { return 0; }, + 'sampler2D': function () { return null; }, + 'samplerCube': function () { return null; }, + + 'vec2': function () { return createZeroArray(2); }, + 'vec3': function () { return createZeroArray(3); }, + 'vec4': function () { return createZeroArray(4); }, + + 'ivec2': function () { return createZeroArray(2); }, + 'ivec3': function () { return createZeroArray(3); }, + 'ivec4': function () { return createZeroArray(4); }, + + 'mat2': function () { return createZeroArray(4); }, + 'mat3': function () { return createZeroArray(9); }, + 'mat4': function () { return createZeroArray(16); }, + + 'array': function () { return []; } +}; + +var attributeSemantics = [ + 'POSITION', + 'NORMAL', + 'BINORMAL', + 'TANGENT', + 'TEXCOORD', + 'TEXCOORD_0', + 'TEXCOORD_1', + 'COLOR', + // Skinning + // https://github.com/KhronosGroup/glTF/blob/master/specification/README.md#semantics + 'JOINT', + 'WEIGHT' +]; +var uniformSemantics = [ + 'SKIN_MATRIX', + // Information about viewport + 'VIEWPORT_SIZE', + 'VIEWPORT', + 'DEVICEPIXELRATIO', + // Window size for window relative coordinate + // https://www.opengl.org/sdk/docs/man/html/gl_FragCoord.xhtml + 'WINDOW_SIZE', + // Infomation about camera + 'NEAR', + 'FAR', + // Time + 'TIME' +]; +var matrixSemantics = [ + 'WORLD', + 'VIEW', + 'PROJECTION', + 'WORLDVIEW', + 'VIEWPROJECTION', + 'WORLDVIEWPROJECTION', + 'WORLDINVERSE', + 'VIEWINVERSE', + 'PROJECTIONINVERSE', + 'WORLDVIEWINVERSE', + 'VIEWPROJECTIONINVERSE', + 'WORLDVIEWPROJECTIONINVERSE', + 'WORLDTRANSPOSE', + 'VIEWTRANSPOSE', + 'PROJECTIONTRANSPOSE', + 'WORLDVIEWTRANSPOSE', + 'VIEWPROJECTIONTRANSPOSE', + 'WORLDVIEWPROJECTIONTRANSPOSE', + 'WORLDINVERSETRANSPOSE', + 'VIEWINVERSETRANSPOSE', + 'PROJECTIONINVERSETRANSPOSE', + 'WORLDVIEWINVERSETRANSPOSE', + 'VIEWPROJECTIONINVERSETRANSPOSE', + 'WORLDVIEWPROJECTIONINVERSETRANSPOSE' +]; + +var attributeSizeMap = { + // WebGL does not support integer attributes + 'vec4': 4, + 'vec3': 3, + 'vec2': 2, + 'float': 1 +}; + + +var shaderIDCache = {}; +var shaderCodeCache = {}; + +function getShaderID(vertex, fragment) { + var key = 'vertex:' + vertex + 'fragment:' + fragment; + if (shaderIDCache[key]) { + return shaderIDCache[key]; + } + var id = __WEBPACK_IMPORTED_MODULE_0__core_util__["a" /* default */].genGUID(); + shaderIDCache[key] = id; + + shaderCodeCache[id] = { + vertex: vertex, + fragment: fragment + }; + + return id; +} + +function removeComment(code) { + return code.replace(/[ \t]*\/\/.*\n/g, '' ) // remove // + .replace(/[ \t]*\/\*[\s\S]*?\*\//g, '' ); // remove /* */ +} + +function logSyntaxError() { + console.error('Wrong uniform/attributes syntax'); +} + +function parseDeclarations(type, line) { + var speratorsRegexp = /[,=\(\):]/; + var tokens = line + // Convert `symbol: [1,2,3]` to `symbol: vec3(1,2,3)` + .replace(/:\s*\[\s*(.*)\s*\]/g, '=' + type + '($1)') + .replace(/\s+/g, '') + .split(/(?=[,=\(\):])/g); + + var newTokens = []; + for (var i = 0; i < tokens.length; i++) { + if (tokens[i].match(speratorsRegexp)) { + newTokens.push( + tokens[i].charAt(0), + tokens[i].slice(1) + ); + } + else { + newTokens.push(tokens[i]); + } + } + tokens = newTokens; + + var TYPE_SYMBOL = 0; + var TYPE_ASSIGN = 1; + var TYPE_VEC = 2; + var TYPE_ARR = 3; + var TYPE_SEMANTIC = 4; + var TYPE_NORMAL = 5; + + var opType = TYPE_SYMBOL; + var declarations = {}; + var declarationValue = null; + var currentDeclaration; + + addSymbol(tokens[0]); + + function addSymbol(symbol) { + if (!symbol) { + logSyntaxError(); + } + var arrResult = symbol.match(/\[(.*?)\]/); + currentDeclaration = symbol.replace(/\[(.*?)\]/, ''); + declarations[currentDeclaration] = {}; + if (arrResult) { + declarations[currentDeclaration].isArray = true; + declarations[currentDeclaration].arraySize = arrResult[1]; + } + } + + for (var i = 1; i < tokens.length; i++) { + var token = tokens[i]; + if (!token) { // Empty token; + continue; + } + if (token === '=') { + if (opType !== TYPE_SYMBOL + && opType !== TYPE_ARR) { + logSyntaxError(); + break; + } + opType = TYPE_ASSIGN; + + continue; + } + else if (token === ':') { + opType = TYPE_SEMANTIC; + + continue; + } + else if (token === ',') { + if (opType === TYPE_VEC) { + if (!(declarationValue instanceof Array)) { + logSyntaxError(); + break; + } + declarationValue.push(+tokens[++i]); + } + else { + opType = TYPE_NORMAL; + } + + continue; + } + else if (token === ')') { + declarations[currentDeclaration].value = new __WEBPACK_IMPORTED_MODULE_1__core_vendor__["a" /* default */].Float32Array(declarationValue); + declarationValue = null; + opType = TYPE_NORMAL; + continue; + } + else if (token === '(') { + if (opType !== TYPE_VEC) { + logSyntaxError(); + break; + } + if (!(declarationValue instanceof Array)) { + logSyntaxError(); + break; + } + declarationValue.push(+tokens[++i]); + continue; + } + else if (token.indexOf('vec') >= 0) { + if (opType !== TYPE_ASSIGN + // Compatitable with old syntax `symbol: [1,2,3]` + && opType !== TYPE_SEMANTIC) { + logSyntaxError(); + break; + } + opType = TYPE_VEC; + declarationValue = []; + continue; + } + else if (opType === TYPE_ASSIGN) { + if (type === 'bool') { + declarations[currentDeclaration].value = token === 'true'; + } + else { + declarations[currentDeclaration].value = parseFloat(token); + } + declarationValue = null; + continue; + } + else if (opType === TYPE_SEMANTIC) { + var semantic = token; + if (attributeSemantics.indexOf(semantic) >= 0 + || uniformSemantics.indexOf(semantic) >= 0 + || matrixSemantics.indexOf(semantic) >= 0 + ) { + declarations[currentDeclaration].semantic = semantic; + } + else if (semantic === 'ignore' || semantic === 'unconfigurable') { + declarations[currentDeclaration].ignore = true; + } + else { + // Try to parse as a default tvalue. + if (type === 'bool') { + declarations[currentDeclaration].value = semantic === 'true'; + } + else { + declarations[currentDeclaration].value = parseFloat(semantic); + } + } + continue; + } + + // treat as symbol. + addSymbol(token); + opType = TYPE_SYMBOL; + } + + return declarations; +} + + +/** + * @constructor + * @extends clay.core.Base + * @alias clay.Shader + * @param {string} vertex + * @param {string} fragment + * @example + * // Create a phong shader + * var shader = new clay.Shader( + * clay.Shader.source('clay.standard.vertex'), + * clay.Shader.source('clay.standard.fragment') + * ); + */ +function Shader(vertex, fragment) { + // First argument can be { vertex, fragment } + if (typeof vertex === 'object') { + fragment = vertex.fragment; + vertex = vertex.vertex; + } + + vertex = removeComment(vertex); + fragment = removeComment(fragment); + + this._shaderID = getShaderID(vertex, fragment); + + this._vertexCode = Shader.parseImport(vertex); + this._fragmentCode = Shader.parseImport(fragment); + + /** + * @readOnly + */ + this.attributeSemantics = {}; + /** + * @readOnly + */ + this.matrixSemantics = {}; + /** + * @readOnly + */ + this.uniformSemantics = {}; + /** + * @readOnly + */ + this.matrixSemanticKeys = []; + /** + * @readOnly + */ + this.uniformTemplates = {}; + /** + * @readOnly + */ + this.attributes = {}; + /** + * @readOnly + */ + this.textures = {}; + /** + * @readOnly + */ + this.vertexDefines = {}; + /** + * @readOnly + */ + this.fragmentDefines = {}; + + this._parseAttributes(); + this._parseUniforms(); + this._parseDefines(); +} + +Shader.prototype = { + + constructor: Shader, + + // Create a new uniform instance for material + createUniforms: function () { + var uniforms = {}; + + for (var symbol in this.uniformTemplates){ + var uniformTpl = this.uniformTemplates[symbol]; + uniforms[symbol] = { + type: uniformTpl.type, + value: uniformTpl.value() + }; + } + + return uniforms; + }, + + _parseImport: function () { + this._vertexCode = Shader.parseImport(this.vertex); + this._fragmentCode = Shader.parseImport(this.fragment); + }, + + _addSemanticUniform: function (symbol, uniformType, semantic) { + // This case is only for SKIN_MATRIX + // TODO + if (attributeSemantics.indexOf(semantic) >= 0) { + this.attributeSemantics[semantic] = { + symbol: symbol, + type: uniformType + }; + } + else if (matrixSemantics.indexOf(semantic) >= 0) { + var isTranspose = false; + var semanticNoTranspose = semantic; + if (semantic.match(/TRANSPOSE$/)) { + isTranspose = true; + semanticNoTranspose = semantic.slice(0, -9); + } + this.matrixSemantics[semantic] = { + symbol: symbol, + type: uniformType, + isTranspose: isTranspose, + semanticNoTranspose: semanticNoTranspose + }; + } + else if (uniformSemantics.indexOf(semantic) >= 0) { + this.uniformSemantics[semantic] = { + symbol: symbol, + type: uniformType + }; + } + }, + + _addMaterialUniform: function (symbol, type, uniformType, defaultValueFunc, isArray, materialUniforms) { + materialUniforms[symbol] = { + type: uniformType, + value: isArray ? uniformValueConstructor['array'] : (defaultValueFunc || uniformValueConstructor[type]), + semantic: null + }; + }, + + _parseUniforms: function () { + var uniforms = {}; + var self = this; + var shaderType = 'vertex'; + this._uniformList = []; + + this._vertexCode = this._vertexCode.replace(uniformRegex, _uniformParser); + shaderType = 'fragment'; + this._fragmentCode = this._fragmentCode.replace(uniformRegex, _uniformParser); + + self.matrixSemanticKeys = Object.keys(this.matrixSemantics); + + function makeDefaultValueFunc(value) { + return value != null ? function () { return value; } : null; + } + + function _uniformParser(str, type, content) { + var declaredUniforms = parseDeclarations(type, content); + var uniformMainStr = []; + for (var symbol in declaredUniforms) { + + var uniformInfo = declaredUniforms[symbol]; + var semantic = uniformInfo.semantic; + var tmpStr = symbol; + var uniformType = uniformTypeMap[type]; + var defaultValueFunc = makeDefaultValueFunc(declaredUniforms[symbol].value); + if (declaredUniforms[symbol].isArray) { + tmpStr += '[' + declaredUniforms[symbol].arraySize + ']'; + uniformType += 'v'; + } + + uniformMainStr.push(tmpStr); + + self._uniformList.push(symbol); + + if (!uniformInfo.ignore) { + if (type === 'sampler2D' || type === 'samplerCube') { + // Texture is default disabled + self.textures[symbol] = { + shaderType: shaderType, + type: type + }; + } + + if (semantic) { + // TODO Should not declare multiple symbols if have semantic. + self._addSemanticUniform(symbol, uniformType, semantic); + } + else { + self._addMaterialUniform( + symbol, type, uniformType, defaultValueFunc, + declaredUniforms[symbol].isArray, uniforms + ); + } + } + } + return uniformMainStr.length > 0 + ? 'uniform ' + type + ' ' + uniformMainStr.join(',') + ';\n' : ''; + } + + this.uniformTemplates = uniforms; + }, + + _parseAttributes: function () { + var attributes = {}; + var self = this; + this._vertexCode = this._vertexCode.replace(attributeRegex, _attributeParser); + + function _attributeParser(str, type, content) { + var declaredAttributes = parseDeclarations(type, content); + + var size = attributeSizeMap[type] || 1; + var attributeMainStr = []; + for (var symbol in declaredAttributes) { + var semantic = declaredAttributes[symbol].semantic; + attributes[symbol] = { + // TODO Can only be float + type: 'float', + size: size, + semantic: semantic || null + }; + // TODO Should not declare multiple symbols if have semantic. + if (semantic) { + if (attributeSemantics.indexOf(semantic) < 0) { + throw new Error('Unkown semantic "' + semantic + '"'); + } + else { + self.attributeSemantics[semantic] = { + symbol: symbol, + type: type + }; + } + } + attributeMainStr.push(symbol); + } + + return 'attribute ' + type + ' ' + attributeMainStr.join(',') + ';\n'; + } + + this.attributes = attributes; + }, + + _parseDefines: function () { + var self = this; + var shaderType = 'vertex'; + this._vertexCode = this._vertexCode.replace(defineRegex, _defineParser); + shaderType = 'fragment'; + this._fragmentCode = this._fragmentCode.replace(defineRegex, _defineParser); + + function _defineParser(str, symbol, value) { + var defines = shaderType === 'vertex' ? self.vertexDefines : self.fragmentDefines; + if (!defines[symbol]) { // Haven't been defined by user + if (value === 'false') { + defines[symbol] = false; + } + else if (value === 'true') { + defines[symbol] = true; + } + else { + defines[symbol] = value + // If can parse to float + ? (isNaN(parseFloat(value)) ? value.trim() : parseFloat(value)) + : null; + } + } + return ''; + } + }, + + /** + * Clone a new shader + * @return {clay.Shader} + */ + clone: function () { + var code = shaderCodeCache[this._shaderID]; + var shader = new Shader(code.vertex, code.fragment); + return shader; + } +}; + +if (Object.defineProperty) { + Object.defineProperty(Shader.prototype, 'shaderID', { + get: function () { + return this._shaderID; + } + }); + Object.defineProperty(Shader.prototype, 'vertex', { + get: function () { + return this._vertexCode; + } + }); + Object.defineProperty(Shader.prototype, 'fragment', { + get: function () { + return this._fragmentCode; + } + }); + Object.defineProperty(Shader.prototype, 'uniforms', { + get: function () { + return this._uniformList; + } + }); +} + +var importRegex = /(@import)\s*([0-9a-zA-Z_\-\.]*)/g; +Shader.parseImport = function (shaderStr) { + shaderStr = shaderStr.replace(importRegex, function (str, importSymbol, importName) { + var str = Shader.source(importName); + if (str) { + // Recursively parse + return Shader.parseImport(str); + } + else { + console.error('Shader chunk "' + importName + '" not existed in library'); + return ''; + } + }); + return shaderStr; +}; + +var exportRegex = /(@export)\s*([0-9a-zA-Z_\-\.]*)\s*\n([\s\S]*?)@end/g; + +/** + * Import shader source + * @param {string} shaderStr + * @memberOf clay.Shader + */ +Shader['import'] = function (shaderStr) { + shaderStr.replace(exportRegex, function (str, exportSymbol, exportName, code) { + var code = code.replace(/(^[\s\t\xa0\u3000]+)|([\u3000\xa0\s\t]+\x24)/g, ''); + if (code) { + var parts = exportName.split('.'); + var obj = Shader.codes; + var i = 0; + var key; + while (i < parts.length - 1) { + key = parts[i++]; + if (!obj[key]) { + obj[key] = {}; + } + obj = obj[key]; + } + key = parts[i]; + obj[key] = code; + } + return code; + }); +}; + +/** + * Library to store all the loaded shader codes + * @type {Object} + * @readOnly + * @memberOf clay.Shader + */ +Shader.codes = {}; + +/** + * Get shader source + * @param {string} name + * @return {string} + */ +Shader.source = function (name) { + var parts = name.split('.'); + var obj = Shader.codes; + var i = 0; + while (obj && i < parts.length) { + var key = parts[i++]; + obj = obj[key]; + } + if (typeof obj !== 'string') { + // FIXME Use default instead + console.error('Shader "' + name + '" not existed in library'); + return ''; + } + return obj; +}; + +/* harmony default export */ __webpack_exports__["a"] = (Shader); + + +/***/ }), +/* 9 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat4__ = __webpack_require__(21); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__glmatrix_vec3__ = __webpack_require__(12); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__glmatrix_quat__ = __webpack_require__(55); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__glmatrix_mat3__ = __webpack_require__(34); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4__Vector3__ = __webpack_require__(3); + + + + + + +/** + * @constructor + * @alias clay.Matrix4 + */ +var Matrix4 = function() { + + this._axisX = new __WEBPACK_IMPORTED_MODULE_4__Vector3__["a" /* default */](); + this._axisY = new __WEBPACK_IMPORTED_MODULE_4__Vector3__["a" /* default */](); + this._axisZ = new __WEBPACK_IMPORTED_MODULE_4__Vector3__["a" /* default */](); + + /** + * Storage of Matrix4 + * @name array + * @type {Float32Array} + * @memberOf clay.Matrix4# + */ + this.array = __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat4__["a" /* default */].create(); + + /** + * @name _dirty + * @type {boolean} + * @memberOf clay.Matrix4# + */ + this._dirty = true; +}; + +Matrix4.prototype = { + + constructor: Matrix4, + + /** + * Set components from array + * @param {Float32Array|number[]} arr + */ + setArray: function (arr) { + for (var i = 0; i < this.array.length; i++) { + this.array[i] = arr[i]; + } + this._dirty = true; + return this; + }, + /** + * Calculate the adjugate of self, in-place + * @return {clay.Matrix4} + */ + adjoint: function() { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat4__["a" /* default */].adjoint(this.array, this.array); + this._dirty = true; + return this; + }, + + /** + * Clone a new Matrix4 + * @return {clay.Matrix4} + */ + clone: function() { + return (new Matrix4()).copy(this); + }, + + /** + * Copy from b + * @param {clay.Matrix4} b + * @return {clay.Matrix4} + */ + copy: function(a) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat4__["a" /* default */].copy(this.array, a.array); + this._dirty = true; + return this; + }, + + /** + * Calculate matrix determinant + * @return {number} + */ + determinant: function() { + return __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat4__["a" /* default */].determinant(this.array); + }, + + /** + * Set upper 3x3 part from quaternion + * @param {clay.Quaternion} q + * @return {clay.Matrix4} + */ + fromQuat: function(q) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat4__["a" /* default */].fromQuat(this.array, q.array); + this._dirty = true; + return this; + }, + + /** + * Set from a quaternion rotation and a vector translation + * @param {clay.Quaternion} q + * @param {clay.Vector3} v + * @return {clay.Matrix4} + */ + fromRotationTranslation: function(q, v) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat4__["a" /* default */].fromRotationTranslation(this.array, q.array, v.array); + this._dirty = true; + return this; + }, + + /** + * Set from Matrix2d, it is used when converting a 2d shape to 3d space. + * In 3d space it is equivalent to ranslate on xy plane and rotate about z axis + * @param {clay.Matrix2d} m2d + * @return {clay.Matrix4} + */ + fromMat2d: function(m2d) { + Matrix4.fromMat2d(this, m2d); + return this; + }, + + /** + * Set from frustum bounds + * @param {number} left + * @param {number} right + * @param {number} bottom + * @param {number} top + * @param {number} near + * @param {number} far + * @return {clay.Matrix4} + */ + frustum: function (left, right, bottom, top, near, far) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat4__["a" /* default */].frustum(this.array, left, right, bottom, top, near, far); + this._dirty = true; + return this; + }, + + /** + * Set to a identity matrix + * @return {clay.Matrix4} + */ + identity: function() { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat4__["a" /* default */].identity(this.array); + this._dirty = true; + return this; + }, + + /** + * Invert self + * @return {clay.Matrix4} + */ + invert: function() { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat4__["a" /* default */].invert(this.array, this.array); + this._dirty = true; + return this; + }, + + /** + * Set as a matrix with the given eye position, focal point, and up axis + * @param {clay.Vector3} eye + * @param {clay.Vector3} center + * @param {clay.Vector3} up + * @return {clay.Matrix4} + */ + lookAt: function(eye, center, up) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat4__["a" /* default */].lookAt(this.array, eye.array, center.array, up.array); + this._dirty = true; + return this; + }, + + /** + * Alias for mutiply + * @param {clay.Matrix4} b + * @return {clay.Matrix4} + */ + mul: function(b) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat4__["a" /* default */].mul(this.array, this.array, b.array); + this._dirty = true; + return this; + }, + + /** + * Alias for multiplyLeft + * @param {clay.Matrix4} a + * @return {clay.Matrix4} + */ + mulLeft: function(a) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat4__["a" /* default */].mul(this.array, a.array, this.array); + this._dirty = true; + return this; + }, + + /** + * Multiply self and b + * @param {clay.Matrix4} b + * @return {clay.Matrix4} + */ + multiply: function(b) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat4__["a" /* default */].multiply(this.array, this.array, b.array); + this._dirty = true; + return this; + }, + + /** + * Multiply a and self, a is on the left + * @param {clay.Matrix3} a + * @return {clay.Matrix3} + */ + multiplyLeft: function(a) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat4__["a" /* default */].multiply(this.array, a.array, this.array); + this._dirty = true; + return this; + }, + + /** + * Set as a orthographic projection matrix + * @param {number} left + * @param {number} right + * @param {number} bottom + * @param {number} top + * @param {number} near + * @param {number} far + * @return {clay.Matrix4} + */ + ortho: function(left, right, bottom, top, near, far) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat4__["a" /* default */].ortho(this.array, left, right, bottom, top, near, far); + this._dirty = true; + return this; + }, + /** + * Set as a perspective projection matrix + * @param {number} fovy + * @param {number} aspect + * @param {number} near + * @param {number} far + * @return {clay.Matrix4} + */ + perspective: function(fovy, aspect, near, far) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat4__["a" /* default */].perspective(this.array, fovy, aspect, near, far); + this._dirty = true; + return this; + }, + + /** + * Rotate self by rad about axis. + * Equal to right-multiply a rotaion matrix + * @param {number} rad + * @param {clay.Vector3} axis + * @return {clay.Matrix4} + */ + rotate: function(rad, axis) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat4__["a" /* default */].rotate(this.array, this.array, rad, axis.array); + this._dirty = true; + return this; + }, + + /** + * Rotate self by a given radian about X axis. + * Equal to right-multiply a rotaion matrix + * @param {number} rad + * @return {clay.Matrix4} + */ + rotateX: function(rad) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat4__["a" /* default */].rotateX(this.array, this.array, rad); + this._dirty = true; + return this; + }, + + /** + * Rotate self by a given radian about Y axis. + * Equal to right-multiply a rotaion matrix + * @param {number} rad + * @return {clay.Matrix4} + */ + rotateY: function(rad) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat4__["a" /* default */].rotateY(this.array, this.array, rad); + this._dirty = true; + return this; + }, + + /** + * Rotate self by a given radian about Z axis. + * Equal to right-multiply a rotaion matrix + * @param {number} rad + * @return {clay.Matrix4} + */ + rotateZ: function(rad) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat4__["a" /* default */].rotateZ(this.array, this.array, rad); + this._dirty = true; + return this; + }, + + /** + * Scale self by s + * Equal to right-multiply a scale matrix + * @param {clay.Vector3} s + * @return {clay.Matrix4} + */ + scale: function(v) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat4__["a" /* default */].scale(this.array, this.array, v.array); + this._dirty = true; + return this; + }, + + /** + * Translate self by v. + * Equal to right-multiply a translate matrix + * @param {clay.Vector3} v + * @return {clay.Matrix4} + */ + translate: function(v) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat4__["a" /* default */].translate(this.array, this.array, v.array); + this._dirty = true; + return this; + }, + + /** + * Transpose self, in-place. + * @return {clay.Matrix2} + */ + transpose: function() { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat4__["a" /* default */].transpose(this.array, this.array); + this._dirty = true; + return this; + }, + + /** + * Decompose a matrix to SRT + * @param {clay.Vector3} [scale] + * @param {clay.Quaternion} rotation + * @param {clay.Vector} position + * @see http://msdn.microsoft.com/en-us/library/microsoft.xna.framework.matrix.decompose.aspx + */ + decomposeMatrix: (function() { + + var x = __WEBPACK_IMPORTED_MODULE_1__glmatrix_vec3__["a" /* default */].create(); + var y = __WEBPACK_IMPORTED_MODULE_1__glmatrix_vec3__["a" /* default */].create(); + var z = __WEBPACK_IMPORTED_MODULE_1__glmatrix_vec3__["a" /* default */].create(); + + var m3 = __WEBPACK_IMPORTED_MODULE_3__glmatrix_mat3__["a" /* default */].create(); + + return function(scale, rotation, position) { + + var el = this.array; + __WEBPACK_IMPORTED_MODULE_1__glmatrix_vec3__["a" /* default */].set(x, el[0], el[1], el[2]); + __WEBPACK_IMPORTED_MODULE_1__glmatrix_vec3__["a" /* default */].set(y, el[4], el[5], el[6]); + __WEBPACK_IMPORTED_MODULE_1__glmatrix_vec3__["a" /* default */].set(z, el[8], el[9], el[10]); + + var sx = __WEBPACK_IMPORTED_MODULE_1__glmatrix_vec3__["a" /* default */].length(x); + var sy = __WEBPACK_IMPORTED_MODULE_1__glmatrix_vec3__["a" /* default */].length(y); + var sz = __WEBPACK_IMPORTED_MODULE_1__glmatrix_vec3__["a" /* default */].length(z); + + // if determine is negative, we need to invert one scale + var det = this.determinant(); + if (det < 0) { + sx = -sx; + } + + if (scale) { + scale.set(sx, sy, sz); + } + + position.set(el[12], el[13], el[14]); + + __WEBPACK_IMPORTED_MODULE_3__glmatrix_mat3__["a" /* default */].fromMat4(m3, el); + // Not like mat4, mat3 in glmatrix seems to be row-based + // Seems fixed in gl-matrix 2.2.2 + // https://github.com/toji/gl-matrix/issues/114 + // mat3.transpose(m3, m3); + + m3[0] /= sx; + m3[1] /= sx; + m3[2] /= sx; + + m3[3] /= sy; + m3[4] /= sy; + m3[5] /= sy; + + m3[6] /= sz; + m3[7] /= sz; + m3[8] /= sz; + + __WEBPACK_IMPORTED_MODULE_2__glmatrix_quat__["a" /* default */].fromMat3(rotation.array, m3); + __WEBPACK_IMPORTED_MODULE_2__glmatrix_quat__["a" /* default */].normalize(rotation.array, rotation.array); + + rotation._dirty = true; + position._dirty = true; + }; + })(), + + toString: function() { + return '[' + Array.prototype.join.call(this.array, ',') + ']'; + }, + + toArray: function () { + return Array.prototype.slice.call(this.array); + } +}; + +var defineProperty = Object.defineProperty; + +if (defineProperty) { + var proto = Matrix4.prototype; + /** + * Z Axis of local transform + * @name z + * @type {clay.Vector3} + * @memberOf clay.Matrix4 + * @instance + */ + defineProperty(proto, 'z', { + get: function () { + var el = this.array; + this._axisZ.set(el[8], el[9], el[10]); + return this._axisZ; + }, + set: function (v) { + // TODO Here has a problem + // If only set an item of vector will not work + var el = this.array; + v = v.array; + el[8] = v[0]; + el[9] = v[1]; + el[10] = v[2]; + + this._dirty = true; + } + }); + + /** + * Y Axis of local transform + * @name y + * @type {clay.Vector3} + * @memberOf clay.Matrix4 + * @instance + */ + defineProperty(proto, 'y', { + get: function () { + var el = this.array; + this._axisY.set(el[4], el[5], el[6]); + return this._axisY; + }, + set: function (v) { + var el = this.array; + v = v.array; + el[4] = v[0]; + el[5] = v[1]; + el[6] = v[2]; + + this._dirty = true; + } + }); + + /** + * X Axis of local transform + * @name x + * @type {clay.Vector3} + * @memberOf clay.Matrix4 + * @instance + */ + defineProperty(proto, 'x', { + get: function () { + var el = this.array; + this._axisX.set(el[0], el[1], el[2]); + return this._axisX; + }, + set: function (v) { + var el = this.array; + v = v.array; + el[0] = v[0]; + el[1] = v[1]; + el[2] = v[2]; + + this._dirty = true; + } + }) +} + +/** + * @param {clay.Matrix4} out + * @param {clay.Matrix4} a + * @return {clay.Matrix4} + */ +Matrix4.adjoint = function(out, a) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat4__["a" /* default */].adjoint(out.array, a.array); + out._dirty = true; + return out; +}; + +/** + * @param {clay.Matrix4} out + * @param {clay.Matrix4} a + * @return {clay.Matrix4} + */ +Matrix4.copy = function(out, a) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat4__["a" /* default */].copy(out.array, a.array); + out._dirty = true; + return out; +}; + +/** + * @param {clay.Matrix4} a + * @return {number} + */ +Matrix4.determinant = function(a) { + return __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat4__["a" /* default */].determinant(a.array); +}; + +/** + * @param {clay.Matrix4} out + * @return {clay.Matrix4} + */ +Matrix4.identity = function(out) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat4__["a" /* default */].identity(out.array); + out._dirty = true; + return out; +}; + +/** + * @param {clay.Matrix4} out + * @param {number} left + * @param {number} right + * @param {number} bottom + * @param {number} top + * @param {number} near + * @param {number} far + * @return {clay.Matrix4} + */ +Matrix4.ortho = function(out, left, right, bottom, top, near, far) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat4__["a" /* default */].ortho(out.array, left, right, bottom, top, near, far); + out._dirty = true; + return out; +}; + +/** + * @param {clay.Matrix4} out + * @param {number} fovy + * @param {number} aspect + * @param {number} near + * @param {number} far + * @return {clay.Matrix4} + */ +Matrix4.perspective = function(out, fovy, aspect, near, far) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat4__["a" /* default */].perspective(out.array, fovy, aspect, near, far); + out._dirty = true; + return out; +}; + +/** + * @param {clay.Matrix4} out + * @param {clay.Vector3} eye + * @param {clay.Vector3} center + * @param {clay.Vector3} up + * @return {clay.Matrix4} + */ +Matrix4.lookAt = function(out, eye, center, up) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat4__["a" /* default */].lookAt(out.array, eye.array, center.array, up.array); + out._dirty = true; + return out; +}; + +/** + * @param {clay.Matrix4} out + * @param {clay.Matrix4} a + * @return {clay.Matrix4} + */ +Matrix4.invert = function(out, a) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat4__["a" /* default */].invert(out.array, a.array); + out._dirty = true; + return out; +}; + +/** + * @param {clay.Matrix4} out + * @param {clay.Matrix4} a + * @param {clay.Matrix4} b + * @return {clay.Matrix4} + */ +Matrix4.mul = function(out, a, b) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat4__["a" /* default */].mul(out.array, a.array, b.array); + out._dirty = true; + return out; +}; + +/** + * @function + * @param {clay.Matrix4} out + * @param {clay.Matrix4} a + * @param {clay.Matrix4} b + * @return {clay.Matrix4} + */ +Matrix4.multiply = Matrix4.mul; + +/** + * @param {clay.Matrix4} out + * @param {clay.Quaternion} q + * @return {clay.Matrix4} + */ +Matrix4.fromQuat = function(out, q) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat4__["a" /* default */].fromQuat(out.array, q.array); + out._dirty = true; + return out; +}; + +/** + * @param {clay.Matrix4} out + * @param {clay.Quaternion} q + * @param {clay.Vector3} v + * @return {clay.Matrix4} + */ +Matrix4.fromRotationTranslation = function(out, q, v) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat4__["a" /* default */].fromRotationTranslation(out.array, q.array, v.array); + out._dirty = true; + return out; +}; + +/** + * @param {clay.Matrix4} m4 + * @param {clay.Matrix2d} m2d + * @return {clay.Matrix4} + */ +Matrix4.fromMat2d = function(m4, m2d) { + m4._dirty = true; + var m2d = m2d.array; + var m4 = m4.array; + + m4[0] = m2d[0]; + m4[4] = m2d[2]; + m4[12] = m2d[4]; + + m4[1] = m2d[1]; + m4[5] = m2d[3]; + m4[13] = m2d[5]; + + return m4; +}; + +/** + * @param {clay.Matrix4} out + * @param {clay.Matrix4} a + * @param {number} rad + * @param {clay.Vector3} axis + * @return {clay.Matrix4} + */ +Matrix4.rotate = function(out, a, rad, axis) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat4__["a" /* default */].rotate(out.array, a.array, rad, axis.array); + out._dirty = true; + return out; +}; + +/** + * @param {clay.Matrix4} out + * @param {clay.Matrix4} a + * @param {number} rad + * @return {clay.Matrix4} + */ +Matrix4.rotateX = function(out, a, rad) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat4__["a" /* default */].rotateX(out.array, a.array, rad); + out._dirty = true; + return out; +}; + +/** + * @param {clay.Matrix4} out + * @param {clay.Matrix4} a + * @param {number} rad + * @return {clay.Matrix4} + */ +Matrix4.rotateY = function(out, a, rad) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat4__["a" /* default */].rotateY(out.array, a.array, rad); + out._dirty = true; + return out; +}; + +/** + * @param {clay.Matrix4} out + * @param {clay.Matrix4} a + * @param {number} rad + * @return {clay.Matrix4} + */ +Matrix4.rotateZ = function(out, a, rad) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat4__["a" /* default */].rotateZ(out.array, a.array, rad); + out._dirty = true; + return out; +}; + +/** + * @param {clay.Matrix4} out + * @param {clay.Matrix4} a + * @param {clay.Vector3} v + * @return {clay.Matrix4} + */ +Matrix4.scale = function(out, a, v) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat4__["a" /* default */].scale(out.array, a.array, v.array); + out._dirty = true; + return out; +}; + +/** + * @param {clay.Matrix4} out + * @param {clay.Matrix4} a + * @return {clay.Matrix4} + */ +Matrix4.transpose = function(out, a) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat4__["a" /* default */].transpose(out.array, a.array); + out._dirty = true; + return out; +}; + +/** + * @param {clay.Matrix4} out + * @param {clay.Matrix4} a + * @param {clay.Vector3} v + * @return {clay.Matrix4} + */ +Matrix4.translate = function(out, a, v) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat4__["a" /* default */].translate(out.array, a.array, v.array); + out._dirty = true; + return out; +}; + +/* harmony default export */ __webpack_exports__["a"] = (Matrix4); + + +/***/ }), +/* 10 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__core_Base__ = __webpack_require__(7); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__Texture__ = __webpack_require__(4); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__TextureCube__ = __webpack_require__(27); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__core_glenum__ = __webpack_require__(11); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4__core_Cache__ = __webpack_require__(57); + + + + + + +var KEY_FRAMEBUFFER = 'framebuffer'; +var KEY_RENDERBUFFER = 'renderbuffer'; +var KEY_RENDERBUFFER_WIDTH = KEY_RENDERBUFFER + '_width'; +var KEY_RENDERBUFFER_HEIGHT = KEY_RENDERBUFFER + '_height'; +var KEY_RENDERBUFFER_ATTACHED = KEY_RENDERBUFFER + '_attached'; +var KEY_DEPTHTEXTURE_ATTACHED = 'depthtexture_attached'; + +var GL_FRAMEBUFFER = __WEBPACK_IMPORTED_MODULE_3__core_glenum__["a" /* default */].FRAMEBUFFER; +var GL_RENDERBUFFER = __WEBPACK_IMPORTED_MODULE_3__core_glenum__["a" /* default */].RENDERBUFFER; +var GL_DEPTH_ATTACHMENT = __WEBPACK_IMPORTED_MODULE_3__core_glenum__["a" /* default */].DEPTH_ATTACHMENT; +var GL_COLOR_ATTACHMENT0 = __WEBPACK_IMPORTED_MODULE_3__core_glenum__["a" /* default */].COLOR_ATTACHMENT0; +/** + * @constructor clay.FrameBuffer + * @extends clay.core.Base + */ +var FrameBuffer = __WEBPACK_IMPORTED_MODULE_0__core_Base__["a" /* default */].extend( +/** @lends clay.FrameBuffer# */ +{ + /** + * If use depth buffer + * @type {boolean} + */ + depthBuffer: true, + + /** + * @type {Object} + */ + viewport: null, + + _width: 0, + _height: 0, + + _textures: null, + + _boundRenderer: null, +}, function () { + // Use cache + this._cache = new __WEBPACK_IMPORTED_MODULE_4__core_Cache__["a" /* default */](); + + this._textures = {}; +}, + +/**@lends clay.FrameBuffer.prototype. */ +{ + /** + * Get attached texture width + * {number} + */ + // FIXME Can't use before #bind + getTextureWidth: function () { + return this._width; + }, + + /** + * Get attached texture height + * {number} + */ + getTextureHeight: function () { + return this._height; + }, + + /** + * Bind the framebuffer to given renderer before rendering + * @param {clay.Renderer} renderer + */ + bind: function (renderer) { + + if (renderer.__currentFrameBuffer) { + // Already bound + if (renderer.__currentFrameBuffer === this) { + return; + } + + console.warn('Renderer already bound with another framebuffer. Unbind it first'); + } + renderer.__currentFrameBuffer = this; + + var _gl = renderer.gl; + + _gl.bindFramebuffer(GL_FRAMEBUFFER, this._getFrameBufferGL(renderer)); + this._boundRenderer = renderer; + var cache = this._cache; + + cache.put('viewport', renderer.viewport); + + var hasTextureAttached = false; + var width; + var height; + for (var attachment in this._textures) { + hasTextureAttached = true; + var obj = this._textures[attachment]; + if (obj) { + // TODO Do width, height checking, make sure size are same + width = obj.texture.width; + height = obj.texture.height; + // Attach textures + this._doAttach(renderer, obj.texture, attachment, obj.target); + } + } + + this._width = width; + this._height = height; + + if (!hasTextureAttached && this.depthBuffer) { + console.error('Must attach texture before bind, or renderbuffer may have incorrect width and height.') + } + + if (this.viewport) { + renderer.setViewport(this.viewport); + } + else { + renderer.setViewport(0, 0, width, height, 1); + } + + var attachedTextures = cache.get('attached_textures'); + if (attachedTextures) { + for (var attachment in attachedTextures) { + if (!this._textures[attachment]) { + var target = attachedTextures[attachment]; + this._doDetach(_gl, attachment, target); + } + } + } + if (!cache.get(KEY_DEPTHTEXTURE_ATTACHED) && this.depthBuffer) { + // Create a new render buffer + if (cache.miss(KEY_RENDERBUFFER)) { + cache.put(KEY_RENDERBUFFER, _gl.createRenderbuffer()); + } + var renderbuffer = cache.get(KEY_RENDERBUFFER); + + if (width !== cache.get(KEY_RENDERBUFFER_WIDTH) + || height !== cache.get(KEY_RENDERBUFFER_HEIGHT)) { + _gl.bindRenderbuffer(GL_RENDERBUFFER, renderbuffer); + _gl.renderbufferStorage(GL_RENDERBUFFER, _gl.DEPTH_COMPONENT16, width, height); + cache.put(KEY_RENDERBUFFER_WIDTH, width); + cache.put(KEY_RENDERBUFFER_HEIGHT, height); + _gl.bindRenderbuffer(GL_RENDERBUFFER, null); + } + if (!cache.get(KEY_RENDERBUFFER_ATTACHED)) { + _gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, renderbuffer); + cache.put(KEY_RENDERBUFFER_ATTACHED, true); + } + } + }, + + /** + * Unbind the frame buffer after rendering + * @param {clay.Renderer} renderer + */ + unbind: function (renderer) { + // Remove status record on renderer + renderer.__currentFrameBuffer = null; + + var _gl = renderer.gl; + + _gl.bindFramebuffer(GL_FRAMEBUFFER, null); + this._boundRenderer = null; + + this._cache.use(renderer.__uid__); + var viewport = this._cache.get('viewport'); + // Reset viewport; + if (viewport) { + renderer.setViewport(viewport); + } + + this.updateMipmap(renderer); + }, + + // Because the data of texture is changed over time, + // Here update the mipmaps of texture each time after rendered; + updateMipmap: function (renderer) { + var _gl = renderer.gl; + for (var attachment in this._textures) { + var obj = this._textures[attachment]; + if (obj) { + var texture = obj.texture; + // FIXME some texture format can't generate mipmap + if (!texture.NPOT && texture.useMipmap + && texture.minFilter === __WEBPACK_IMPORTED_MODULE_1__Texture__["a" /* default */].LINEAR_MIPMAP_LINEAR) { + var target = texture.textureType === 'textureCube' ? __WEBPACK_IMPORTED_MODULE_3__core_glenum__["a" /* default */].TEXTURE_CUBE_MAP : __WEBPACK_IMPORTED_MODULE_3__core_glenum__["a" /* default */].TEXTURE_2D; + _gl.bindTexture(target, texture.getWebGLTexture(renderer)); + _gl.generateMipmap(target); + _gl.bindTexture(target, null); + } + } + } + }, + + + // 0x8CD5, 36053, FRAMEBUFFER_COMPLETE + // 0x8CD6, 36054, FRAMEBUFFER_INCOMPLETE_ATTACHMENT + // 0x8CD7, 36055, FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT + // 0x8CD9, 36057, FRAMEBUFFER_INCOMPLETE_DIMENSIONS + // 0x8CDD, 36061, FRAMEBUFFER_UNSUPPORTED + checkStatus: function (_gl) { + return _gl.checkFramebufferStatus(GL_FRAMEBUFFER); + }, + + _getFrameBufferGL: function (renderer) { + var cache = this._cache; + cache.use(renderer.__uid__); + + if (cache.miss(KEY_FRAMEBUFFER)) { + cache.put(KEY_FRAMEBUFFER, renderer.gl.createFramebuffer()); + } + + return cache.get(KEY_FRAMEBUFFER); + }, + + /** + * Attach a texture(RTT) to the framebuffer + * @param {clay.Texture} texture + * @param {number} [attachment=gl.COLOR_ATTACHMENT0] + * @param {number} [target=gl.TEXTURE_2D] + */ + attach: function (texture, attachment, target) { + + if (!texture.width) { + throw new Error('The texture attached to color buffer is not a valid.'); + } + // TODO width and height check + + // If the depth_texture extension is enabled, developers + // Can attach a depth texture to the depth buffer + // http://blog.tojicode.com/2012/07/using-webgldepthtexture.html + attachment = attachment || GL_COLOR_ATTACHMENT0; + target = target || __WEBPACK_IMPORTED_MODULE_3__core_glenum__["a" /* default */].TEXTURE_2D; + + var boundRenderer = this._boundRenderer; + var _gl = boundRenderer && boundRenderer.gl; + var attachedTextures; + + if (_gl) { + var cache = this._cache; + cache.use(boundRenderer.__uid__); + attachedTextures = cache.get('attached_textures'); + } + + // Check if texture attached + var previous = this._textures[attachment]; + if (previous && previous.target === target + && previous.texture === texture + && (attachedTextures && attachedTextures[attachment] != null) + ) { + return; + } + + var canAttach = true; + if (boundRenderer) { + canAttach = this._doAttach(boundRenderer, texture, attachment, target); + // Set viewport again incase attached to different size textures. + if (!this.viewport) { + boundRenderer.setViewport(0, 0, texture.width, texture.height, 1); + } + } + + if (canAttach) { + this._textures[attachment] = this._textures[attachment] || {}; + this._textures[attachment].texture = texture; + this._textures[attachment].target = target; + } + }, + + _doAttach: function (renderer, texture, attachment, target) { + var _gl = renderer.gl; + // Make sure texture is always updated + // Because texture width or height may be changed and in this we can't be notified + // FIXME awkward; + var webglTexture = texture.getWebGLTexture(renderer); + // Assume cache has been used. + var attachedTextures = this._cache.get('attached_textures'); + if (attachedTextures && attachedTextures[attachment]) { + var obj = attachedTextures[attachment]; + // Check if texture and target not changed + if (obj.texture === texture && obj.target === target) { + return; + } + } + attachment = +attachment; + + var canAttach = true; + if (attachment === GL_DEPTH_ATTACHMENT || attachment === __WEBPACK_IMPORTED_MODULE_3__core_glenum__["a" /* default */].DEPTH_STENCIL_ATTACHMENT) { + var extension = renderer.getGLExtension('WEBGL_depth_texture'); + + if (!extension) { + console.error('Depth texture is not supported by the browser'); + canAttach = false; + } + if (texture.format !== __WEBPACK_IMPORTED_MODULE_3__core_glenum__["a" /* default */].DEPTH_COMPONENT + && texture.format !== __WEBPACK_IMPORTED_MODULE_3__core_glenum__["a" /* default */].DEPTH_STENCIL + ) { + console.error('The texture attached to depth buffer is not a valid.'); + canAttach = false; + } + + // Dispose render buffer created previous + if (canAttach) { + var renderbuffer = this._cache.get(KEY_RENDERBUFFER); + if (renderbuffer) { + _gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, null); + _gl.deleteRenderbuffer(renderbuffer); + this._cache.put(KEY_RENDERBUFFER, false); + } + + this._cache.put(KEY_RENDERBUFFER_ATTACHED, false); + this._cache.put(KEY_DEPTHTEXTURE_ATTACHED, true); + } + } + + // Mipmap level can only be 0 + _gl.framebufferTexture2D(GL_FRAMEBUFFER, attachment, target, webglTexture, 0); + + if (!attachedTextures) { + attachedTextures = {}; + this._cache.put('attached_textures', attachedTextures); + } + attachedTextures[attachment] = attachedTextures[attachment] || {}; + attachedTextures[attachment].texture = texture; + attachedTextures[attachment].target = target; + + return canAttach; + }, + + _doDetach: function (_gl, attachment, target) { + // Detach a texture from framebuffer + // https://github.com/KhronosGroup/WebGL/blob/master/conformance-suites/1.0.0/conformance/framebuffer-test.html#L145 + _gl.framebufferTexture2D(GL_FRAMEBUFFER, attachment, target, null, 0); + + // Assume cache has been used. + var attachedTextures = this._cache.get('attached_textures'); + if (attachedTextures && attachedTextures[attachment]) { + attachedTextures[attachment] = null; + } + + if (attachment === GL_DEPTH_ATTACHMENT || attachment === __WEBPACK_IMPORTED_MODULE_3__core_glenum__["a" /* default */].DEPTH_STENCIL_ATTACHMENT) { + this._cache.put(KEY_DEPTHTEXTURE_ATTACHED, false); + } + }, + + /** + * Detach a texture + * @param {number} [attachment=gl.COLOR_ATTACHMENT0] + * @param {number} [target=gl.TEXTURE_2D] + */ + detach: function (attachment, target) { + // TODO depth extension check ? + this._textures[attachment] = null; + if (this._boundRenderer) { + var cache = this._cache; + cache.use(this._boundRenderer.__uid__); + this._doDetach(this._boundRenderer.gl, attachment, target); + } + }, + /** + * Dispose + * @param {WebGLRenderingContext} _gl + */ + dispose: function (renderer) { + + var _gl = renderer.gl; + var cache = this._cache; + + cache.use(renderer.__uid__); + + var renderBuffer = cache.get(KEY_RENDERBUFFER); + if (renderBuffer) { + _gl.deleteRenderbuffer(renderBuffer); + } + var frameBuffer = cache.get(KEY_FRAMEBUFFER); + if (frameBuffer) { + _gl.deleteFramebuffer(frameBuffer); + } + cache.deleteContext(renderer.__uid__); + + // Clear cache for reusing + this._textures = {}; + + } +}); + +FrameBuffer.DEPTH_ATTACHMENT = GL_DEPTH_ATTACHMENT; +FrameBuffer.COLOR_ATTACHMENT0 = GL_COLOR_ATTACHMENT0; +FrameBuffer.STENCIL_ATTACHMENT = __WEBPACK_IMPORTED_MODULE_3__core_glenum__["a" /* default */].STENCIL_ATTACHMENT; +FrameBuffer.DEPTH_STENCIL_ATTACHMENT = __WEBPACK_IMPORTED_MODULE_3__core_glenum__["a" /* default */].DEPTH_STENCIL_ATTACHMENT; + +/* harmony default export */ __webpack_exports__["a"] = (FrameBuffer); + + +/***/ }), +/* 11 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/** + * @namespace clay.core.glenum + * @see http://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14 + */ +/* harmony default export */ __webpack_exports__["a"] = ({ + /* ClearBufferMask */ + DEPTH_BUFFER_BIT : 0x00000100, + STENCIL_BUFFER_BIT : 0x00000400, + COLOR_BUFFER_BIT : 0x00004000, + + /* BeginMode */ + POINTS : 0x0000, + LINES : 0x0001, + LINE_LOOP : 0x0002, + LINE_STRIP : 0x0003, + TRIANGLES : 0x0004, + TRIANGLE_STRIP : 0x0005, + TRIANGLE_FAN : 0x0006, + + /* AlphaFunction (not supported in ES20) */ + /* NEVER */ + /* LESS */ + /* EQUAL */ + /* LEQUAL */ + /* GREATER */ + /* NOTEQUAL */ + /* GEQUAL */ + /* ALWAYS */ + + /* BlendingFactorDest */ + ZERO : 0, + ONE : 1, + SRC_COLOR : 0x0300, + ONE_MINUS_SRC_COLOR : 0x0301, + SRC_ALPHA : 0x0302, + ONE_MINUS_SRC_ALPHA : 0x0303, + DST_ALPHA : 0x0304, + ONE_MINUS_DST_ALPHA : 0x0305, + + /* BlendingFactorSrc */ + /* ZERO */ + /* ONE */ + DST_COLOR : 0x0306, + ONE_MINUS_DST_COLOR : 0x0307, + SRC_ALPHA_SATURATE : 0x0308, + /* SRC_ALPHA */ + /* ONE_MINUS_SRC_ALPHA */ + /* DST_ALPHA */ + /* ONE_MINUS_DST_ALPHA */ + + /* BlendEquationSeparate */ + FUNC_ADD : 0x8006, + BLEND_EQUATION : 0x8009, + BLEND_EQUATION_RGB : 0x8009, /* same as BLEND_EQUATION */ + BLEND_EQUATION_ALPHA : 0x883D, + + /* BlendSubtract */ + FUNC_SUBTRACT : 0x800A, + FUNC_REVERSE_SUBTRACT : 0x800B, + + /* Separate Blend Functions */ + BLEND_DST_RGB : 0x80C8, + BLEND_SRC_RGB : 0x80C9, + BLEND_DST_ALPHA : 0x80CA, + BLEND_SRC_ALPHA : 0x80CB, + CONSTANT_COLOR : 0x8001, + ONE_MINUS_CONSTANT_COLOR : 0x8002, + CONSTANT_ALPHA : 0x8003, + ONE_MINUS_CONSTANT_ALPHA : 0x8004, + BLEND_COLOR : 0x8005, + + /* Buffer Objects */ + ARRAY_BUFFER : 0x8892, + ELEMENT_ARRAY_BUFFER : 0x8893, + ARRAY_BUFFER_BINDING : 0x8894, + ELEMENT_ARRAY_BUFFER_BINDING : 0x8895, + + STREAM_DRAW : 0x88E0, + STATIC_DRAW : 0x88E4, + DYNAMIC_DRAW : 0x88E8, + + BUFFER_SIZE : 0x8764, + BUFFER_USAGE : 0x8765, + + CURRENT_VERTEX_ATTRIB : 0x8626, + + /* CullFaceMode */ + FRONT : 0x0404, + BACK : 0x0405, + FRONT_AND_BACK : 0x0408, + + /* DepthFunction */ + /* NEVER */ + /* LESS */ + /* EQUAL */ + /* LEQUAL */ + /* GREATER */ + /* NOTEQUAL */ + /* GEQUAL */ + /* ALWAYS */ + + /* EnableCap */ + /* TEXTURE_2D */ + CULL_FACE : 0x0B44, + BLEND : 0x0BE2, + DITHER : 0x0BD0, + STENCIL_TEST : 0x0B90, + DEPTH_TEST : 0x0B71, + SCISSOR_TEST : 0x0C11, + POLYGON_OFFSET_FILL : 0x8037, + SAMPLE_ALPHA_TO_COVERAGE : 0x809E, + SAMPLE_COVERAGE : 0x80A0, + + /* ErrorCode */ + NO_ERROR : 0, + INVALID_ENUM : 0x0500, + INVALID_VALUE : 0x0501, + INVALID_OPERATION : 0x0502, + OUT_OF_MEMORY : 0x0505, + + /* FrontFaceDirection */ + CW : 0x0900, + CCW : 0x0901, + + /* GetPName */ + LINE_WIDTH : 0x0B21, + ALIASED_POINT_SIZE_RANGE : 0x846D, + ALIASED_LINE_WIDTH_RANGE : 0x846E, + CULL_FACE_MODE : 0x0B45, + FRONT_FACE : 0x0B46, + DEPTH_RANGE : 0x0B70, + DEPTH_WRITEMASK : 0x0B72, + DEPTH_CLEAR_VALUE : 0x0B73, + DEPTH_FUNC : 0x0B74, + STENCIL_CLEAR_VALUE : 0x0B91, + STENCIL_FUNC : 0x0B92, + STENCIL_FAIL : 0x0B94, + STENCIL_PASS_DEPTH_FAIL : 0x0B95, + STENCIL_PASS_DEPTH_PASS : 0x0B96, + STENCIL_REF : 0x0B97, + STENCIL_VALUE_MASK : 0x0B93, + STENCIL_WRITEMASK : 0x0B98, + STENCIL_BACK_FUNC : 0x8800, + STENCIL_BACK_FAIL : 0x8801, + STENCIL_BACK_PASS_DEPTH_FAIL : 0x8802, + STENCIL_BACK_PASS_DEPTH_PASS : 0x8803, + STENCIL_BACK_REF : 0x8CA3, + STENCIL_BACK_VALUE_MASK : 0x8CA4, + STENCIL_BACK_WRITEMASK : 0x8CA5, + VIEWPORT : 0x0BA2, + SCISSOR_BOX : 0x0C10, + /* SCISSOR_TEST */ + COLOR_CLEAR_VALUE : 0x0C22, + COLOR_WRITEMASK : 0x0C23, + UNPACK_ALIGNMENT : 0x0CF5, + PACK_ALIGNMENT : 0x0D05, + MAX_TEXTURE_SIZE : 0x0D33, + MAX_VIEWPORT_DIMS : 0x0D3A, + SUBPIXEL_BITS : 0x0D50, + RED_BITS : 0x0D52, + GREEN_BITS : 0x0D53, + BLUE_BITS : 0x0D54, + ALPHA_BITS : 0x0D55, + DEPTH_BITS : 0x0D56, + STENCIL_BITS : 0x0D57, + POLYGON_OFFSET_UNITS : 0x2A00, + /* POLYGON_OFFSET_FILL */ + POLYGON_OFFSET_FACTOR : 0x8038, + TEXTURE_BINDING_2D : 0x8069, + SAMPLE_BUFFERS : 0x80A8, + SAMPLES : 0x80A9, + SAMPLE_COVERAGE_VALUE : 0x80AA, + SAMPLE_COVERAGE_INVERT : 0x80AB, + + /* GetTextureParameter */ + /* TEXTURE_MAG_FILTER */ + /* TEXTURE_MIN_FILTER */ + /* TEXTURE_WRAP_S */ + /* TEXTURE_WRAP_T */ + + COMPRESSED_TEXTURE_FORMATS : 0x86A3, + + /* HintMode */ + DONT_CARE : 0x1100, + FASTEST : 0x1101, + NICEST : 0x1102, + + /* HintTarget */ + GENERATE_MIPMAP_HINT : 0x8192, + + /* DataType */ + BYTE : 0x1400, + UNSIGNED_BYTE : 0x1401, + SHORT : 0x1402, + UNSIGNED_SHORT : 0x1403, + INT : 0x1404, + UNSIGNED_INT : 0x1405, + FLOAT : 0x1406, + + /* PixelFormat */ + DEPTH_COMPONENT : 0x1902, + ALPHA : 0x1906, + RGB : 0x1907, + RGBA : 0x1908, + LUMINANCE : 0x1909, + LUMINANCE_ALPHA : 0x190A, + + /* PixelType */ + /* UNSIGNED_BYTE */ + UNSIGNED_SHORT_4_4_4_4 : 0x8033, + UNSIGNED_SHORT_5_5_5_1 : 0x8034, + UNSIGNED_SHORT_5_6_5 : 0x8363, + + /* Shaders */ + FRAGMENT_SHADER : 0x8B30, + VERTEX_SHADER : 0x8B31, + MAX_VERTEX_ATTRIBS : 0x8869, + MAX_VERTEX_UNIFORM_VECTORS : 0x8DFB, + MAX_VARYING_VECTORS : 0x8DFC, + MAX_COMBINED_TEXTURE_IMAGE_UNITS : 0x8B4D, + MAX_VERTEX_TEXTURE_IMAGE_UNITS : 0x8B4C, + MAX_TEXTURE_IMAGE_UNITS : 0x8872, + MAX_FRAGMENT_UNIFORM_VECTORS : 0x8DFD, + SHADER_TYPE : 0x8B4F, + DELETE_STATUS : 0x8B80, + LINK_STATUS : 0x8B82, + VALIDATE_STATUS : 0x8B83, + ATTACHED_SHADERS : 0x8B85, + ACTIVE_UNIFORMS : 0x8B86, + ACTIVE_ATTRIBUTES : 0x8B89, + SHADING_LANGUAGE_VERSION : 0x8B8C, + CURRENT_PROGRAM : 0x8B8D, + + /* StencilFunction */ + NEVER : 0x0200, + LESS : 0x0201, + EQUAL : 0x0202, + LEQUAL : 0x0203, + GREATER : 0x0204, + NOTEQUAL : 0x0205, + GEQUAL : 0x0206, + ALWAYS : 0x0207, + + /* StencilOp */ + /* ZERO */ + KEEP : 0x1E00, + REPLACE : 0x1E01, + INCR : 0x1E02, + DECR : 0x1E03, + INVERT : 0x150A, + INCR_WRAP : 0x8507, + DECR_WRAP : 0x8508, + + /* StringName */ + VENDOR : 0x1F00, + RENDERER : 0x1F01, + VERSION : 0x1F02, + + /* TextureMagFilter */ + NEAREST : 0x2600, + LINEAR : 0x2601, + + /* TextureMinFilter */ + /* NEAREST */ + /* LINEAR */ + NEAREST_MIPMAP_NEAREST : 0x2700, + LINEAR_MIPMAP_NEAREST : 0x2701, + NEAREST_MIPMAP_LINEAR : 0x2702, + LINEAR_MIPMAP_LINEAR : 0x2703, + + /* TextureParameterName */ + TEXTURE_MAG_FILTER : 0x2800, + TEXTURE_MIN_FILTER : 0x2801, + TEXTURE_WRAP_S : 0x2802, + TEXTURE_WRAP_T : 0x2803, + + /* TextureTarget */ + TEXTURE_2D : 0x0DE1, + TEXTURE : 0x1702, + + TEXTURE_CUBE_MAP : 0x8513, + TEXTURE_BINDING_CUBE_MAP : 0x8514, + TEXTURE_CUBE_MAP_POSITIVE_X : 0x8515, + TEXTURE_CUBE_MAP_NEGATIVE_X : 0x8516, + TEXTURE_CUBE_MAP_POSITIVE_Y : 0x8517, + TEXTURE_CUBE_MAP_NEGATIVE_Y : 0x8518, + TEXTURE_CUBE_MAP_POSITIVE_Z : 0x8519, + TEXTURE_CUBE_MAP_NEGATIVE_Z : 0x851A, + MAX_CUBE_MAP_TEXTURE_SIZE : 0x851C, + + /* TextureUnit */ + TEXTURE0 : 0x84C0, + TEXTURE1 : 0x84C1, + TEXTURE2 : 0x84C2, + TEXTURE3 : 0x84C3, + TEXTURE4 : 0x84C4, + TEXTURE5 : 0x84C5, + TEXTURE6 : 0x84C6, + TEXTURE7 : 0x84C7, + TEXTURE8 : 0x84C8, + TEXTURE9 : 0x84C9, + TEXTURE10 : 0x84CA, + TEXTURE11 : 0x84CB, + TEXTURE12 : 0x84CC, + TEXTURE13 : 0x84CD, + TEXTURE14 : 0x84CE, + TEXTURE15 : 0x84CF, + TEXTURE16 : 0x84D0, + TEXTURE17 : 0x84D1, + TEXTURE18 : 0x84D2, + TEXTURE19 : 0x84D3, + TEXTURE20 : 0x84D4, + TEXTURE21 : 0x84D5, + TEXTURE22 : 0x84D6, + TEXTURE23 : 0x84D7, + TEXTURE24 : 0x84D8, + TEXTURE25 : 0x84D9, + TEXTURE26 : 0x84DA, + TEXTURE27 : 0x84DB, + TEXTURE28 : 0x84DC, + TEXTURE29 : 0x84DD, + TEXTURE30 : 0x84DE, + TEXTURE31 : 0x84DF, + ACTIVE_TEXTURE : 0x84E0, + + /* TextureWrapMode */ + REPEAT : 0x2901, + CLAMP_TO_EDGE : 0x812F, + MIRRORED_REPEAT : 0x8370, + + /* Uniform Types */ + FLOAT_VEC2 : 0x8B50, + FLOAT_VEC3 : 0x8B51, + FLOAT_VEC4 : 0x8B52, + INT_VEC2 : 0x8B53, + INT_VEC3 : 0x8B54, + INT_VEC4 : 0x8B55, + BOOL : 0x8B56, + BOOL_VEC2 : 0x8B57, + BOOL_VEC3 : 0x8B58, + BOOL_VEC4 : 0x8B59, + FLOAT_MAT2 : 0x8B5A, + FLOAT_MAT3 : 0x8B5B, + FLOAT_MAT4 : 0x8B5C, + SAMPLER_2D : 0x8B5E, + SAMPLER_CUBE : 0x8B60, + + /* Vertex Arrays */ + VERTEX_ATTRIB_ARRAY_ENABLED : 0x8622, + VERTEX_ATTRIB_ARRAY_SIZE : 0x8623, + VERTEX_ATTRIB_ARRAY_STRIDE : 0x8624, + VERTEX_ATTRIB_ARRAY_TYPE : 0x8625, + VERTEX_ATTRIB_ARRAY_NORMALIZED : 0x886A, + VERTEX_ATTRIB_ARRAY_POINTER : 0x8645, + VERTEX_ATTRIB_ARRAY_BUFFER_BINDING : 0x889F, + + /* Shader Source */ + COMPILE_STATUS : 0x8B81, + + /* Shader Precision-Specified Types */ + LOW_FLOAT : 0x8DF0, + MEDIUM_FLOAT : 0x8DF1, + HIGH_FLOAT : 0x8DF2, + LOW_INT : 0x8DF3, + MEDIUM_INT : 0x8DF4, + HIGH_INT : 0x8DF5, + + /* Framebuffer Object. */ + FRAMEBUFFER : 0x8D40, + RENDERBUFFER : 0x8D41, + + RGBA4 : 0x8056, + RGB5_A1 : 0x8057, + RGB565 : 0x8D62, + DEPTH_COMPONENT16 : 0x81A5, + STENCIL_INDEX : 0x1901, + STENCIL_INDEX8 : 0x8D48, + DEPTH_STENCIL : 0x84F9, + + RENDERBUFFER_WIDTH : 0x8D42, + RENDERBUFFER_HEIGHT : 0x8D43, + RENDERBUFFER_INTERNAL_FORMAT : 0x8D44, + RENDERBUFFER_RED_SIZE : 0x8D50, + RENDERBUFFER_GREEN_SIZE : 0x8D51, + RENDERBUFFER_BLUE_SIZE : 0x8D52, + RENDERBUFFER_ALPHA_SIZE : 0x8D53, + RENDERBUFFER_DEPTH_SIZE : 0x8D54, + RENDERBUFFER_STENCIL_SIZE : 0x8D55, + + FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE : 0x8CD0, + FRAMEBUFFER_ATTACHMENT_OBJECT_NAME : 0x8CD1, + FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL : 0x8CD2, + FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE : 0x8CD3, + + COLOR_ATTACHMENT0 : 0x8CE0, + DEPTH_ATTACHMENT : 0x8D00, + STENCIL_ATTACHMENT : 0x8D20, + DEPTH_STENCIL_ATTACHMENT : 0x821A, + + NONE : 0, + + FRAMEBUFFER_COMPLETE : 0x8CD5, + FRAMEBUFFER_INCOMPLETE_ATTACHMENT : 0x8CD6, + FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT : 0x8CD7, + FRAMEBUFFER_INCOMPLETE_DIMENSIONS : 0x8CD9, + FRAMEBUFFER_UNSUPPORTED : 0x8CDD, + + FRAMEBUFFER_BINDING : 0x8CA6, + RENDERBUFFER_BINDING : 0x8CA7, + MAX_RENDERBUFFER_SIZE : 0x84E8, + + INVALID_FRAMEBUFFER_OPERATION : 0x0506, + + /* WebGL-specific enums */ + UNPACK_FLIP_Y_WEBGL : 0x9240, + UNPACK_PREMULTIPLY_ALPHA_WEBGL : 0x9241, + CONTEXT_LOST_WEBGL : 0x9242, + UNPACK_COLORSPACE_CONVERSION_WEBGL : 0x9243, + BROWSER_DEFAULT_WEBGL : 0x9244, +}); + + +/***/ }), +/* 12 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__common__ = __webpack_require__(20); + +/* Copyright (c) 2013, Brandon Jones, Colin MacKenzie IV. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + + + +/** + * @class 3 Dimensional Vector + * @name vec3 + */ + +var vec3 = {}; + +/** + * Creates a new, empty vec3 + * + * @returns {vec3} a new 3D vector + */ +vec3.create = function() { + var out = new __WEBPACK_IMPORTED_MODULE_0__common__["a" /* GLMAT_ARRAY_TYPE */](3); + out[0] = 0; + out[1] = 0; + out[2] = 0; + return out; +}; + +/** + * Creates a new vec3 initialized with values from an existing vector + * + * @param {vec3} a vector to clone + * @returns {vec3} a new 3D vector + */ +vec3.clone = function(a) { + var out = new __WEBPACK_IMPORTED_MODULE_0__common__["a" /* GLMAT_ARRAY_TYPE */](3); + out[0] = a[0]; + out[1] = a[1]; + out[2] = a[2]; + return out; +}; + +/** + * Creates a new vec3 initialized with the given values + * + * @param {Number} x X component + * @param {Number} y Y component + * @param {Number} z Z component + * @returns {vec3} a new 3D vector + */ +vec3.fromValues = function(x, y, z) { + var out = new __WEBPACK_IMPORTED_MODULE_0__common__["a" /* GLMAT_ARRAY_TYPE */](3); + out[0] = x; + out[1] = y; + out[2] = z; + return out; +}; + +/** + * Copy the values from one vec3 to another + * + * @param {vec3} out the receiving vector + * @param {vec3} a the source vector + * @returns {vec3} out + */ +vec3.copy = function(out, a) { + out[0] = a[0]; + out[1] = a[1]; + out[2] = a[2]; + return out; +}; + +/** + * Set the components of a vec3 to the given values + * + * @param {vec3} out the receiving vector + * @param {Number} x X component + * @param {Number} y Y component + * @param {Number} z Z component + * @returns {vec3} out + */ +vec3.set = function(out, x, y, z) { + out[0] = x; + out[1] = y; + out[2] = z; + return out; +}; + +/** + * Adds two vec3's + * + * @param {vec3} out the receiving vector + * @param {vec3} a the first operand + * @param {vec3} b the second operand + * @returns {vec3} out + */ +vec3.add = function(out, a, b) { + out[0] = a[0] + b[0]; + out[1] = a[1] + b[1]; + out[2] = a[2] + b[2]; + return out; +}; + +/** + * Subtracts vector b from vector a + * + * @param {vec3} out the receiving vector + * @param {vec3} a the first operand + * @param {vec3} b the second operand + * @returns {vec3} out + */ +vec3.subtract = function(out, a, b) { + out[0] = a[0] - b[0]; + out[1] = a[1] - b[1]; + out[2] = a[2] - b[2]; + return out; +}; + +/** + * Alias for {@link vec3.subtract} + * @function + */ +vec3.sub = vec3.subtract; + +/** + * Multiplies two vec3's + * + * @param {vec3} out the receiving vector + * @param {vec3} a the first operand + * @param {vec3} b the second operand + * @returns {vec3} out + */ +vec3.multiply = function(out, a, b) { + out[0] = a[0] * b[0]; + out[1] = a[1] * b[1]; + out[2] = a[2] * b[2]; + return out; +}; + +/** + * Alias for {@link vec3.multiply} + * @function + */ +vec3.mul = vec3.multiply; + +/** + * Divides two vec3's + * + * @param {vec3} out the receiving vector + * @param {vec3} a the first operand + * @param {vec3} b the second operand + * @returns {vec3} out + */ +vec3.divide = function(out, a, b) { + out[0] = a[0] / b[0]; + out[1] = a[1] / b[1]; + out[2] = a[2] / b[2]; + return out; +}; + +/** + * Alias for {@link vec3.divide} + * @function + */ +vec3.div = vec3.divide; + +/** + * Returns the minimum of two vec3's + * + * @param {vec3} out the receiving vector + * @param {vec3} a the first operand + * @param {vec3} b the second operand + * @returns {vec3} out + */ +vec3.min = function(out, a, b) { + out[0] = Math.min(a[0], b[0]); + out[1] = Math.min(a[1], b[1]); + out[2] = Math.min(a[2], b[2]); + return out; +}; + +/** + * Returns the maximum of two vec3's + * + * @param {vec3} out the receiving vector + * @param {vec3} a the first operand + * @param {vec3} b the second operand + * @returns {vec3} out + */ +vec3.max = function(out, a, b) { + out[0] = Math.max(a[0], b[0]); + out[1] = Math.max(a[1], b[1]); + out[2] = Math.max(a[2], b[2]); + return out; +}; + +/** + * Scales a vec3 by a scalar number + * + * @param {vec3} out the receiving vector + * @param {vec3} a the vector to scale + * @param {Number} b amount to scale the vector by + * @returns {vec3} out + */ +vec3.scale = function(out, a, b) { + out[0] = a[0] * b; + out[1] = a[1] * b; + out[2] = a[2] * b; + return out; +}; + +/** + * Adds two vec3's after scaling the second operand by a scalar value + * + * @param {vec3} out the receiving vector + * @param {vec3} a the first operand + * @param {vec3} b the second operand + * @param {Number} scale the amount to scale b by before adding + * @returns {vec3} out + */ +vec3.scaleAndAdd = function(out, a, b, scale) { + out[0] = a[0] + (b[0] * scale); + out[1] = a[1] + (b[1] * scale); + out[2] = a[2] + (b[2] * scale); + return out; +}; + +/** + * Calculates the euclidian distance between two vec3's + * + * @param {vec3} a the first operand + * @param {vec3} b the second operand + * @returns {Number} distance between a and b + */ +vec3.distance = function(a, b) { + var x = b[0] - a[0], + y = b[1] - a[1], + z = b[2] - a[2]; + return Math.sqrt(x*x + y*y + z*z); +}; + +/** + * Alias for {@link vec3.distance} + * @function + */ +vec3.dist = vec3.distance; + +/** + * Calculates the squared euclidian distance between two vec3's + * + * @param {vec3} a the first operand + * @param {vec3} b the second operand + * @returns {Number} squared distance between a and b + */ +vec3.squaredDistance = function(a, b) { + var x = b[0] - a[0], + y = b[1] - a[1], + z = b[2] - a[2]; + return x*x + y*y + z*z; +}; + +/** + * Alias for {@link vec3.squaredDistance} + * @function + */ +vec3.sqrDist = vec3.squaredDistance; + +/** + * Calculates the length of a vec3 + * + * @param {vec3} a vector to calculate length of + * @returns {Number} length of a + */ +vec3.length = function (a) { + var x = a[0], + y = a[1], + z = a[2]; + return Math.sqrt(x*x + y*y + z*z); +}; + +/** + * Alias for {@link vec3.length} + * @function + */ +vec3.len = vec3.length; + +/** + * Calculates the squared length of a vec3 + * + * @param {vec3} a vector to calculate squared length of + * @returns {Number} squared length of a + */ +vec3.squaredLength = function (a) { + var x = a[0], + y = a[1], + z = a[2]; + return x*x + y*y + z*z; +}; + +/** + * Alias for {@link vec3.squaredLength} + * @function + */ +vec3.sqrLen = vec3.squaredLength; + +/** + * Negates the components of a vec3 + * + * @param {vec3} out the receiving vector + * @param {vec3} a vector to negate + * @returns {vec3} out + */ +vec3.negate = function(out, a) { + out[0] = -a[0]; + out[1] = -a[1]; + out[2] = -a[2]; + return out; +}; + +/** + * Returns the inverse of the components of a vec3 + * + * @param {vec3} out the receiving vector + * @param {vec3} a vector to invert + * @returns {vec3} out + */ +vec3.inverse = function(out, a) { + out[0] = 1.0 / a[0]; + out[1] = 1.0 / a[1]; + out[2] = 1.0 / a[2]; + return out; +}; + +/** + * Normalize a vec3 + * + * @param {vec3} out the receiving vector + * @param {vec3} a vector to normalize + * @returns {vec3} out + */ +vec3.normalize = function(out, a) { + var x = a[0], + y = a[1], + z = a[2]; + var len = x*x + y*y + z*z; + if (len > 0) { + //TODO: evaluate use of glm_invsqrt here? + len = 1 / Math.sqrt(len); + out[0] = a[0] * len; + out[1] = a[1] * len; + out[2] = a[2] * len; + } + return out; +}; + +/** + * Calculates the dot product of two vec3's + * + * @param {vec3} a the first operand + * @param {vec3} b the second operand + * @returns {Number} dot product of a and b + */ +vec3.dot = function (a, b) { + return a[0] * b[0] + a[1] * b[1] + a[2] * b[2]; +}; + +/** + * Computes the cross product of two vec3's + * + * @param {vec3} out the receiving vector + * @param {vec3} a the first operand + * @param {vec3} b the second operand + * @returns {vec3} out + */ +vec3.cross = function(out, a, b) { + var ax = a[0], ay = a[1], az = a[2], + bx = b[0], by = b[1], bz = b[2]; + + out[0] = ay * bz - az * by; + out[1] = az * bx - ax * bz; + out[2] = ax * by - ay * bx; + return out; +}; + +/** + * Performs a linear interpolation between two vec3's + * + * @param {vec3} out the receiving vector + * @param {vec3} a the first operand + * @param {vec3} b the second operand + * @param {Number} t interpolation amount between the two inputs + * @returns {vec3} out + */ +vec3.lerp = function (out, a, b, t) { + var ax = a[0], + ay = a[1], + az = a[2]; + out[0] = ax + t * (b[0] - ax); + out[1] = ay + t * (b[1] - ay); + out[2] = az + t * (b[2] - az); + return out; +}; + +/** + * Generates a random vector with the given scale + * + * @param {vec3} out the receiving vector + * @param {Number} [scale] Length of the resulting vector. If ommitted, a unit vector will be returned + * @returns {vec3} out + */ +vec3.random = function (out, scale) { + scale = scale || 1.0; + + var r = Object(__WEBPACK_IMPORTED_MODULE_0__common__["c" /* GLMAT_RANDOM */])() * 2.0 * Math.PI; + var z = (Object(__WEBPACK_IMPORTED_MODULE_0__common__["c" /* GLMAT_RANDOM */])() * 2.0) - 1.0; + var zScale = Math.sqrt(1.0-z*z) * scale; + + out[0] = Math.cos(r) * zScale; + out[1] = Math.sin(r) * zScale; + out[2] = z * scale; + return out; +}; + +/** + * Transforms the vec3 with a mat4. + * 4th vector component is implicitly '1' + * + * @param {vec3} out the receiving vector + * @param {vec3} a the vector to transform + * @param {mat4} m matrix to transform with + * @returns {vec3} out + */ +vec3.transformMat4 = function(out, a, m) { + var x = a[0], y = a[1], z = a[2], + w = m[3] * x + m[7] * y + m[11] * z + m[15]; + w = w || 1.0; + out[0] = (m[0] * x + m[4] * y + m[8] * z + m[12]) / w; + out[1] = (m[1] * x + m[5] * y + m[9] * z + m[13]) / w; + out[2] = (m[2] * x + m[6] * y + m[10] * z + m[14]) / w; + return out; +}; + +/** + * Transforms the vec3 with a mat3. + * + * @param {vec3} out the receiving vector + * @param {vec3} a the vector to transform + * @param {mat4} m the 3x3 matrix to transform with + * @returns {vec3} out + */ +vec3.transformMat3 = function(out, a, m) { + var x = a[0], y = a[1], z = a[2]; + out[0] = x * m[0] + y * m[3] + z * m[6]; + out[1] = x * m[1] + y * m[4] + z * m[7]; + out[2] = x * m[2] + y * m[5] + z * m[8]; + return out; +}; + +/** + * Transforms the vec3 with a quat + * + * @param {vec3} out the receiving vector + * @param {vec3} a the vector to transform + * @param {quat} q quaternion to transform with + * @returns {vec3} out + */ +vec3.transformQuat = function(out, a, q) { + // benchmarks: http://jsperf.com/quaternion-transform-vec3-implementations + + var x = a[0], y = a[1], z = a[2], + qx = q[0], qy = q[1], qz = q[2], qw = q[3], + + // calculate quat * vec + ix = qw * x + qy * z - qz * y, + iy = qw * y + qz * x - qx * z, + iz = qw * z + qx * y - qy * x, + iw = -qx * x - qy * y - qz * z; + + // calculate result * inverse quat + out[0] = ix * qw + iw * -qx + iy * -qz - iz * -qy; + out[1] = iy * qw + iw * -qy + iz * -qx - ix * -qz; + out[2] = iz * qw + iw * -qz + ix * -qy - iy * -qx; + return out; +}; + +/** + * Rotate a 3D vector around the x-axis + * @param {vec3} out The receiving vec3 + * @param {vec3} a The vec3 point to rotate + * @param {vec3} b The origin of the rotation + * @param {Number} c The angle of rotation + * @returns {vec3} out + */ +vec3.rotateX = function(out, a, b, c){ + var p = [], r=[]; + //Translate point to the origin + p[0] = a[0] - b[0]; + p[1] = a[1] - b[1]; + p[2] = a[2] - b[2]; + + //perform rotation + r[0] = p[0]; + r[1] = p[1]*Math.cos(c) - p[2]*Math.sin(c); + r[2] = p[1]*Math.sin(c) + p[2]*Math.cos(c); + + //translate to correct position + out[0] = r[0] + b[0]; + out[1] = r[1] + b[1]; + out[2] = r[2] + b[2]; + + return out; +}; + +/** + * Rotate a 3D vector around the y-axis + * @param {vec3} out The receiving vec3 + * @param {vec3} a The vec3 point to rotate + * @param {vec3} b The origin of the rotation + * @param {Number} c The angle of rotation + * @returns {vec3} out + */ +vec3.rotateY = function(out, a, b, c){ + var p = [], r=[]; + //Translate point to the origin + p[0] = a[0] - b[0]; + p[1] = a[1] - b[1]; + p[2] = a[2] - b[2]; + + //perform rotation + r[0] = p[2]*Math.sin(c) + p[0]*Math.cos(c); + r[1] = p[1]; + r[2] = p[2]*Math.cos(c) - p[0]*Math.sin(c); + + //translate to correct position + out[0] = r[0] + b[0]; + out[1] = r[1] + b[1]; + out[2] = r[2] + b[2]; + + return out; +}; + +/** + * Rotate a 3D vector around the z-axis + * @param {vec3} out The receiving vec3 + * @param {vec3} a The vec3 point to rotate + * @param {vec3} b The origin of the rotation + * @param {Number} c The angle of rotation + * @returns {vec3} out + */ +vec3.rotateZ = function(out, a, b, c){ + var p = [], r=[]; + //Translate point to the origin + p[0] = a[0] - b[0]; + p[1] = a[1] - b[1]; + p[2] = a[2] - b[2]; + + //perform rotation + r[0] = p[0]*Math.cos(c) - p[1]*Math.sin(c); + r[1] = p[0]*Math.sin(c) + p[1]*Math.cos(c); + r[2] = p[2]; + + //translate to correct position + out[0] = r[0] + b[0]; + out[1] = r[1] + b[1]; + out[2] = r[2] + b[2]; + + return out; +}; + +/** + * Perform some operation over an array of vec3s. + * + * @param {Array} a the array of vectors to iterate over + * @param {Number} stride Number of elements between the start of each vec3. If 0 assumes tightly packed + * @param {Number} offset Number of elements to skip at the beginning of the array + * @param {Number} count Number of vec3s to iterate over. If 0 iterates over entire array + * @param {Function} fn Function to call for each vector in the array + * @param {Object} [arg] additional argument to pass to fn + * @returns {Array} a + * @function + */ +vec3.forEach = (function() { + var vec = vec3.create(); + + return function(a, stride, offset, count, fn, arg) { + var i, l; + if(!stride) { + stride = 3; + } + + if(!offset) { + offset = 0; + } + + if(count) { + l = Math.min((count * stride) + offset, a.length); + } else { + l = a.length; + } + + for(i = offset; i < l; i += stride) { + vec[0] = a[i]; vec[1] = a[i+1]; vec[2] = a[i+2]; + fn(vec, vec, arg); + a[i] = vec[0]; a[i+1] = vec[1]; a[i+2] = vec[2]; + } + + return a; + }; +})(); + +/** + * Get the angle between two 3D vectors + * @param {vec3} a The first operand + * @param {vec3} b The second operand + * @returns {Number} The angle in radians + */ +vec3.angle = function(a, b) { + + var tempA = vec3.fromValues(a[0], a[1], a[2]); + var tempB = vec3.fromValues(b[0], b[1], b[2]); + + vec3.normalize(tempA, tempA); + vec3.normalize(tempB, tempB); + + var cosine = vec3.dot(tempA, tempB); + + if(cosine > 1.0){ + return 0; + } else { + return Math.acos(cosine); + } +}; + +/* harmony default export */ __webpack_exports__["a"] = (vec3); + +/***/ }), +/* 13 */ +/***/ (function(module, exports) { + +/** + * @module zrender/core/util + */ +// 用于处理merge时无法遍历Date等对象的问题 +var BUILTIN_OBJECT = { + '[object Function]': 1, + '[object RegExp]': 1, + '[object Date]': 1, + '[object Error]': 1, + '[object CanvasGradient]': 1, + '[object CanvasPattern]': 1, + // For node-canvas + '[object Image]': 1, + '[object Canvas]': 1 +}; +var TYPED_ARRAY = { + '[object Int8Array]': 1, + '[object Uint8Array]': 1, + '[object Uint8ClampedArray]': 1, + '[object Int16Array]': 1, + '[object Uint16Array]': 1, + '[object Int32Array]': 1, + '[object Uint32Array]': 1, + '[object Float32Array]': 1, + '[object Float64Array]': 1 +}; +var objToString = Object.prototype.toString; +var arrayProto = Array.prototype; +var nativeForEach = arrayProto.forEach; +var nativeFilter = arrayProto.filter; +var nativeSlice = arrayProto.slice; +var nativeMap = arrayProto.map; +var nativeReduce = arrayProto.reduce; // Avoid assign to an exported variable, for transforming to cjs. + +var methods = {}; + +function $override(name, fn) { + // Clear ctx instance for different environment + if (name === 'createCanvas') { + _ctx = null; + } + + methods[name] = fn; +} +/** + * Those data types can be cloned: + * Plain object, Array, TypedArray, number, string, null, undefined. + * Those data types will be assgined using the orginal data: + * BUILTIN_OBJECT + * Instance of user defined class will be cloned to a plain object, without + * properties in prototype. + * Other data types is not supported (not sure what will happen). + * + * Caution: do not support clone Date, for performance consideration. + * (There might be a large number of date in `series.data`). + * So date should not be modified in and out of echarts. + * + * @param {*} source + * @return {*} new + */ + + +function clone(source) { + if (source == null || typeof source != 'object') { + return source; + } + + var result = source; + var typeStr = objToString.call(source); + + if (typeStr === '[object Array]') { + if (!isPrimitive(source)) { + result = []; + + for (var i = 0, len = source.length; i < len; i++) { + result[i] = clone(source[i]); + } + } + } else if (TYPED_ARRAY[typeStr]) { + if (!isPrimitive(source)) { + var Ctor = source.constructor; + + if (source.constructor.from) { + result = Ctor.from(source); + } else { + result = new Ctor(source.length); + + for (var i = 0, len = source.length; i < len; i++) { + result[i] = clone(source[i]); + } + } + } + } else if (!BUILTIN_OBJECT[typeStr] && !isPrimitive(source) && !isDom(source)) { + result = {}; + + for (var key in source) { + if (source.hasOwnProperty(key)) { + result[key] = clone(source[key]); + } + } + } + + return result; +} +/** + * @memberOf module:zrender/core/util + * @param {*} target + * @param {*} source + * @param {boolean} [overwrite=false] + */ + + +function merge(target, source, overwrite) { + // We should escapse that source is string + // and enter for ... in ... + if (!isObject(source) || !isObject(target)) { + return overwrite ? clone(source) : target; + } + + for (var key in source) { + if (source.hasOwnProperty(key)) { + var targetProp = target[key]; + var sourceProp = source[key]; + + if (isObject(sourceProp) && isObject(targetProp) && !isArray(sourceProp) && !isArray(targetProp) && !isDom(sourceProp) && !isDom(targetProp) && !isBuiltInObject(sourceProp) && !isBuiltInObject(targetProp) && !isPrimitive(sourceProp) && !isPrimitive(targetProp)) { + // 如果需要递归覆盖,就递归调用merge + merge(targetProp, sourceProp, overwrite); + } else if (overwrite || !(key in target)) { + // 否则只处理overwrite为true,或者在目标对象中没有此属性的情况 + // NOTE,在 target[key] 不存在的时候也是直接覆盖 + target[key] = clone(source[key], true); + } + } + } + + return target; +} +/** + * @param {Array} targetAndSources The first item is target, and the rests are source. + * @param {boolean} [overwrite=false] + * @return {*} target + */ + + +function mergeAll(targetAndSources, overwrite) { + var result = targetAndSources[0]; + + for (var i = 1, len = targetAndSources.length; i < len; i++) { + result = merge(result, targetAndSources[i], overwrite); + } + + return result; +} +/** + * @param {*} target + * @param {*} source + * @memberOf module:zrender/core/util + */ + + +function extend(target, source) { + for (var key in source) { + if (source.hasOwnProperty(key)) { + target[key] = source[key]; + } + } + + return target; +} +/** + * @param {*} target + * @param {*} source + * @param {boolean} [overlay=false] + * @memberOf module:zrender/core/util + */ + + +function defaults(target, source, overlay) { + for (var key in source) { + if (source.hasOwnProperty(key) && (overlay ? source[key] != null : target[key] == null)) { + target[key] = source[key]; + } + } + + return target; +} + +var createCanvas = function () { + return methods.createCanvas(); +}; + +methods.createCanvas = function () { + return document.createElement('canvas'); +}; // FIXME + + +var _ctx; + +function getContext() { + if (!_ctx) { + // Use util.createCanvas instead of createCanvas + // because createCanvas may be overwritten in different environment + _ctx = createCanvas().getContext('2d'); + } + + return _ctx; +} +/** + * 查询数组中元素的index + * @memberOf module:zrender/core/util + */ + + +function indexOf(array, value) { + if (array) { + if (array.indexOf) { + return array.indexOf(value); + } + + for (var i = 0, len = array.length; i < len; i++) { + if (array[i] === value) { + return i; + } + } + } + + return -1; +} +/** + * 构造类继承关系 + * + * @memberOf module:zrender/core/util + * @param {Function} clazz 源类 + * @param {Function} baseClazz 基类 + */ + + +function inherits(clazz, baseClazz) { + var clazzPrototype = clazz.prototype; + + function F() {} + + F.prototype = baseClazz.prototype; + clazz.prototype = new F(); + + for (var prop in clazzPrototype) { + clazz.prototype[prop] = clazzPrototype[prop]; + } + + clazz.prototype.constructor = clazz; + clazz.superClass = baseClazz; +} +/** + * @memberOf module:zrender/core/util + * @param {Object|Function} target + * @param {Object|Function} sorce + * @param {boolean} overlay + */ + + +function mixin(target, source, overlay) { + target = 'prototype' in target ? target.prototype : target; + source = 'prototype' in source ? source.prototype : source; + defaults(target, source, overlay); +} +/** + * Consider typed array. + * @param {Array|TypedArray} data + */ + + +function isArrayLike(data) { + if (!data) { + return; + } + + if (typeof data == 'string') { + return false; + } + + return typeof data.length == 'number'; +} +/** + * 数组或对象遍历 + * @memberOf module:zrender/core/util + * @param {Object|Array} obj + * @param {Function} cb + * @param {*} [context] + */ + + +function each(obj, cb, context) { + if (!(obj && cb)) { + return; + } + + if (obj.forEach && obj.forEach === nativeForEach) { + obj.forEach(cb, context); + } else if (obj.length === +obj.length) { + for (var i = 0, len = obj.length; i < len; i++) { + cb.call(context, obj[i], i, obj); + } + } else { + for (var key in obj) { + if (obj.hasOwnProperty(key)) { + cb.call(context, obj[key], key, obj); + } + } + } +} +/** + * 数组映射 + * @memberOf module:zrender/core/util + * @param {Array} obj + * @param {Function} cb + * @param {*} [context] + * @return {Array} + */ + + +function map(obj, cb, context) { + if (!(obj && cb)) { + return; + } + + if (obj.map && obj.map === nativeMap) { + return obj.map(cb, context); + } else { + var result = []; + + for (var i = 0, len = obj.length; i < len; i++) { + result.push(cb.call(context, obj[i], i, obj)); + } + + return result; + } +} +/** + * @memberOf module:zrender/core/util + * @param {Array} obj + * @param {Function} cb + * @param {Object} [memo] + * @param {*} [context] + * @return {Array} + */ + + +function reduce(obj, cb, memo, context) { + if (!(obj && cb)) { + return; + } + + if (obj.reduce && obj.reduce === nativeReduce) { + return obj.reduce(cb, memo, context); + } else { + for (var i = 0, len = obj.length; i < len; i++) { + memo = cb.call(context, memo, obj[i], i, obj); + } + + return memo; + } +} +/** + * 数组过滤 + * @memberOf module:zrender/core/util + * @param {Array} obj + * @param {Function} cb + * @param {*} [context] + * @return {Array} + */ + + +function filter(obj, cb, context) { + if (!(obj && cb)) { + return; + } + + if (obj.filter && obj.filter === nativeFilter) { + return obj.filter(cb, context); + } else { + var result = []; + + for (var i = 0, len = obj.length; i < len; i++) { + if (cb.call(context, obj[i], i, obj)) { + result.push(obj[i]); + } + } + + return result; + } +} +/** + * 数组项查找 + * @memberOf module:zrender/core/util + * @param {Array} obj + * @param {Function} cb + * @param {*} [context] + * @return {*} + */ + + +function find(obj, cb, context) { + if (!(obj && cb)) { + return; + } + + for (var i = 0, len = obj.length; i < len; i++) { + if (cb.call(context, obj[i], i, obj)) { + return obj[i]; + } + } +} +/** + * @memberOf module:zrender/core/util + * @param {Function} func + * @param {*} context + * @return {Function} + */ + + +function bind(func, context) { + var args = nativeSlice.call(arguments, 2); + return function () { + return func.apply(context, args.concat(nativeSlice.call(arguments))); + }; +} +/** + * @memberOf module:zrender/core/util + * @param {Function} func + * @return {Function} + */ + + +function curry(func) { + var args = nativeSlice.call(arguments, 1); + return function () { + return func.apply(this, args.concat(nativeSlice.call(arguments))); + }; +} +/** + * @memberOf module:zrender/core/util + * @param {*} value + * @return {boolean} + */ + + +function isArray(value) { + return objToString.call(value) === '[object Array]'; +} +/** + * @memberOf module:zrender/core/util + * @param {*} value + * @return {boolean} + */ + + +function isFunction(value) { + return typeof value === 'function'; +} +/** + * @memberOf module:zrender/core/util + * @param {*} value + * @return {boolean} + */ + + +function isString(value) { + return objToString.call(value) === '[object String]'; +} +/** + * @memberOf module:zrender/core/util + * @param {*} value + * @return {boolean} + */ + + +function isObject(value) { + // Avoid a V8 JIT bug in Chrome 19-20. + // See https://code.google.com/p/v8/issues/detail?id=2291 for more details. + var type = typeof value; + return type === 'function' || !!value && type == 'object'; +} +/** + * @memberOf module:zrender/core/util + * @param {*} value + * @return {boolean} + */ + + +function isBuiltInObject(value) { + return !!BUILTIN_OBJECT[objToString.call(value)]; +} +/** + * @memberOf module:zrender/core/util + * @param {*} value + * @return {boolean} + */ + + +function isTypedArray(value) { + return !!TYPED_ARRAY[objToString.call(value)]; +} +/** + * @memberOf module:zrender/core/util + * @param {*} value + * @return {boolean} + */ + + +function isDom(value) { + return typeof value === 'object' && typeof value.nodeType === 'number' && typeof value.ownerDocument === 'object'; +} +/** + * Whether is exactly NaN. Notice isNaN('a') returns true. + * @param {*} value + * @return {boolean} + */ + + +function eqNaN(value) { + return value !== value; +} +/** + * If value1 is not null, then return value1, otherwise judget rest of values. + * Low performance. + * @memberOf module:zrender/core/util + * @return {*} Final value + */ + + +function retrieve(values) { + for (var i = 0, len = arguments.length; i < len; i++) { + if (arguments[i] != null) { + return arguments[i]; + } + } +} + +function retrieve2(value0, value1) { + return value0 != null ? value0 : value1; +} + +function retrieve3(value0, value1, value2) { + return value0 != null ? value0 : value1 != null ? value1 : value2; +} +/** + * @memberOf module:zrender/core/util + * @param {Array} arr + * @param {number} startIndex + * @param {number} endIndex + * @return {Array} + */ + + +function slice() { + return Function.call.apply(nativeSlice, arguments); +} +/** + * Normalize css liked array configuration + * e.g. + * 3 => [3, 3, 3, 3] + * [4, 2] => [4, 2, 4, 2] + * [4, 3, 2] => [4, 3, 2, 3] + * @param {number|Array.} val + * @return {Array.} + */ + + +function normalizeCssArray(val) { + if (typeof val === 'number') { + return [val, val, val, val]; + } + + var len = val.length; + + if (len === 2) { + // vertical | horizontal + return [val[0], val[1], val[0], val[1]]; + } else if (len === 3) { + // top | horizontal | bottom + return [val[0], val[1], val[2], val[1]]; + } + + return val; +} +/** + * @memberOf module:zrender/core/util + * @param {boolean} condition + * @param {string} message + */ + + +function assert(condition, message) { + if (!condition) { + throw new Error(message); + } +} +/** + * @memberOf module:zrender/core/util + * @param {string} str string to be trimed + * @return {string} trimed string + */ + + +function trim(str) { + if (str == null) { + return null; + } else if (typeof str.trim === 'function') { + return str.trim(); + } else { + return str.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, ''); + } +} + +var primitiveKey = '__ec_primitive__'; +/** + * Set an object as primitive to be ignored traversing children in clone or merge + */ + +function setAsPrimitive(obj) { + obj[primitiveKey] = true; +} + +function isPrimitive(obj) { + return obj[primitiveKey]; +} +/** + * @constructor + * @param {Object} obj Only apply `ownProperty`. + */ + + +function HashMap(obj) { + var isArr = isArray(obj); + var thisMap = this; + obj instanceof HashMap ? obj.each(visit) : obj && each(obj, visit); + + function visit(value, key) { + isArr ? thisMap.set(value, key) : thisMap.set(key, value); + } +} // Add prefix to avoid conflict with Object.prototype. + + +HashMap.prototype = { + constructor: HashMap, + // Do not provide `has` method to avoid defining what is `has`. + // (We usually treat `null` and `undefined` as the same, different + // from ES6 Map). + get: function (key) { + return this.hasOwnProperty(key) ? this[key] : null; + }, + set: function (key, value) { + // Comparing with invocation chaining, `return value` is more commonly + // used in this case: `var someVal = map.set('a', genVal());` + return this[key] = value; + }, + // Although util.each can be performed on this hashMap directly, user + // should not use the exposed keys, who are prefixed. + each: function (cb, context) { + context !== void 0 && (cb = bind(cb, context)); + + for (var key in this) { + this.hasOwnProperty(key) && cb(this[key], key); + } + }, + // Do not use this method if performance sensitive. + removeKey: function (key) { + delete this[key]; + } +}; + +function createHashMap(obj) { + return new HashMap(obj); +} + +function concatArray(a, b) { + var newArray = new a.constructor(a.length + b.length); + + for (var i = 0; i < a.length; i++) { + newArray[i] = a[i]; + } + + var offset = a.length; + + for (i = 0; i < b.length; i++) { + newArray[i + offset] = b[i]; + } + + return newArray; +} + +function noop() {} + +exports.$override = $override; +exports.clone = clone; +exports.merge = merge; +exports.mergeAll = mergeAll; +exports.extend = extend; +exports.defaults = defaults; +exports.createCanvas = createCanvas; +exports.getContext = getContext; +exports.indexOf = indexOf; +exports.inherits = inherits; +exports.mixin = mixin; +exports.isArrayLike = isArrayLike; +exports.each = each; +exports.map = map; +exports.reduce = reduce; +exports.filter = filter; +exports.find = find; +exports.bind = bind; +exports.curry = curry; +exports.isArray = isArray; +exports.isFunction = isFunction; +exports.isString = isString; +exports.isObject = isObject; +exports.isBuiltInObject = isBuiltInObject; +exports.isTypedArray = isTypedArray; +exports.isDom = isDom; +exports.eqNaN = eqNaN; +exports.retrieve = retrieve; +exports.retrieve2 = retrieve2; +exports.retrieve3 = retrieve3; +exports.slice = slice; +exports.normalizeCssArray = normalizeCssArray; +exports.assert = assert; +exports.trim = trim; +exports.setAsPrimitive = setAsPrimitive; +exports.isPrimitive = isPrimitive; +exports.createHashMap = createHashMap; +exports.concatArray = concatArray; +exports.noop = noop; + +/***/ }), +/* 14 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* WEBPACK VAR INJECTION */(function(global) {/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__request__ = __webpack_require__(112); + + +var supportWebGL; + +var vendor = {}; + +/** + * If support WebGL + * @return {boolean} + */ +vendor.supportWebGL = function () { + if (supportWebGL == null) { + try { + var canvas = document.createElement('canvas'); + var gl = canvas.getContext('webgl') || canvas.getContext('experimental-webgl'); + if (!gl) { + throw new Error(); + } + } + catch (e) { + supportWebGL = false; + } + + } + return supportWebGL; +}; + +vendor.Int8Array = typeof Int8Array === 'undefined' ? Array : Int8Array; + +vendor.Uint8Array = typeof Uint8Array === 'undefined' ? Array : Uint8Array; + +vendor.Uint16Array = typeof Uint16Array === 'undefined' ? Array : Uint16Array; + +vendor.Uint32Array = typeof Uint32Array === 'undefined' ? Array : Uint32Array; + +vendor.Int16Array = typeof Int16Array === 'undefined' ? Array : Int16Array; + +vendor.Float32Array = typeof Float32Array === 'undefined' ? Array : Float32Array; + +vendor.Float64Array = typeof Float64Array === 'undefined' ? Array : Float64Array; + +var g = {}; +if (typeof window !== 'undefined') { + g = window; +} +else if (typeof global !== 'undefined') { + g = global; +} +vendor.requestAnimationFrame = g.requestAnimationFrame + || g.msRequestAnimationFrame + || g.mozRequestAnimationFrame + || g.webkitRequestAnimationFrame + || function (func){ setTimeout(func, 16); }; + +vendor.createCanvas = function () { + return document.createElement('canvas'); +}; + +vendor.createImage = function () { + return new g.Image(); +}; + +vendor.request = { + get: __WEBPACK_IMPORTED_MODULE_0__request__["a" /* default */].get +}; + +/* harmony default export */ __webpack_exports__["a"] = (vendor); + +/* WEBPACK VAR INJECTION */}.call(__webpack_exports__, __webpack_require__(68))) + +/***/ }), +/* 15 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__core_vendor__ = __webpack_require__(14); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__glmatrix_vec3__ = __webpack_require__(12); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__glmatrix_mat4__ = __webpack_require__(21); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__math_BoundingBox__ = __webpack_require__(18); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4__GeometryBase__ = __webpack_require__(118); + + + + + + +var vec3Create = __WEBPACK_IMPORTED_MODULE_1__glmatrix_vec3__["a" /* default */].create; +var vec3Add = __WEBPACK_IMPORTED_MODULE_1__glmatrix_vec3__["a" /* default */].add; +var vec3Set = __WEBPACK_IMPORTED_MODULE_1__glmatrix_vec3__["a" /* default */].set; + +var Attribute = __WEBPACK_IMPORTED_MODULE_4__GeometryBase__["a" /* default */].Attribute; + +/** + * Geometry in ClayGL contains vertex attributes of mesh. These vertex attributes will be finally provided to the {@link clay.Shader}. + * Different {@link clay.Shader} needs different attributes. Here is a list of attributes used in the builtin shaders. + * + * + position: `clay.basic`, `clay.lambert`, `clay.standard` + * + texcoord0: `clay.basic`, `clay.lambert`, `clay.standard` + * + color: `clay.basic`, `clay.lambert`, `clay.standard` + * + weight: `clay.basic`, `clay.lambert`, `clay.standard` + * + joint: `clay.basic`, `clay.lambert`, `clay.standard` + * + normal: `clay.lambert`, `clay.standard` + * + tangent: `clay.standard` + * + * #### Create a procedural geometry + * + * ClayGL provides a couple of builtin procedural geometries. Inlcuding: + * + * + {@link clay.geometry.Cube} + * + {@link clay.geometry.Sphere} + * + {@link clay.geometry.Plane} + * + {@link clay.geometry.Cylinder} + * + {@link clay.geometry.Cone} + * + {@link clay.geometry.ParametricSurface} + * + * It's simple to create a basic geometry with these classes. + * +```js +var sphere = new clay.geometry.Sphere({ + radius: 2 +}); +``` + * + * #### Create the geometry data by yourself + * + * Usually the vertex attributes data are created by the {@link clay.loader.GLTF} or procedural geometries like {@link clay.geometry.Sphere}. + * Besides these, you can create the data manually. Here is a simple example to create a triangle. +```js +var TRIANGLE_POSITIONS = [ + [-0.5, -0.5, 0], + [0.5, -0.5, 0], + [0, 0.5, 0] +]; +var geometry = new clay.StaticGeometryBase(); +// Add triangle vertices to position attribute. +geometry.attributes.position.fromArray(TRIANGLE_POSITIONS); +``` + * Then you can use the utility methods like `generateVertexNormals`, `generateTangents` to create the remaining necessary attributes. + * + * + * #### Use with custom shaders + * + * If you wan't to write custom shaders. Don't forget to add SEMANTICS to these attributes. For example + * + ```glsl +uniform mat4 worldViewProjection : WORLDVIEWPROJECTION; +uniform mat4 worldInverseTranspose : WORLDINVERSETRANSPOSE; +uniform mat4 world : WORLD; + +attribute vec3 position : POSITION; +attribute vec2 texcoord : TEXCOORD_0; +attribute vec3 normal : NORMAL; +``` + * These `POSITION`, `TEXCOORD_0`, `NORMAL` are SEMANTICS which will map the attributes in shader to the attributes in the GeometryBase + * + * Available attributes SEMANTICS includes `POSITION`, `TEXCOORD_0`, `TEXCOORD_1` `NORMAL`, `TANGENT`, `COLOR`, `WEIGHT`, `JOINT`. + * + * + * @constructor clay.Geometry + * @extends clay.GeometryBase + */ +var Geometry = __WEBPACK_IMPORTED_MODULE_4__GeometryBase__["a" /* default */].extend(function () { + return /** @lends clay.Geometry# */ { + /** + * Attributes of geometry. Including: + * + `position` + * + `texcoord0` + * + `texcoord1` + * + `normal` + * + `tangent` + * + `color` + * + `weight` + * + `joint` + * + `barycentric` + * + * @type {Object.} + */ + attributes: { + position: new Attribute('position', 'float', 3, 'POSITION'), + texcoord0: new Attribute('texcoord0', 'float', 2, 'TEXCOORD_0'), + texcoord1: new Attribute('texcoord1', 'float', 2, 'TEXCOORD_1'), + normal: new Attribute('normal', 'float', 3, 'NORMAL'), + tangent: new Attribute('tangent', 'float', 4, 'TANGENT'), + color: new Attribute('color', 'float', 4, 'COLOR'), + // Skinning attributes + // Each vertex can be bind to 4 bones, because the + // sum of weights is 1, so the weights is stored in vec3 and the last + // can be calculated by 1-w.x-w.y-w.z + weight: new Attribute('weight', 'float', 3, 'WEIGHT'), + joint: new Attribute('joint', 'float', 4, 'JOINT'), + // For wireframe display + // http://codeflow.org/entries/2012/aug/02/easy-wireframe-display-with-barycentric-coordinates/ + barycentric: new Attribute('barycentric', 'float', 3, null), + }, + /** + * Calculated bounding box of geometry. + * @type {clay.BoundingBox} + */ + boundingBox: null + }; +}, +/** @lends clay.Geometry.prototype */ +{ + + mainAttribute: 'position', + + /** + * Update boundingBox of Geometry + */ + updateBoundingBox: function () { + var bbox = this.boundingBox; + if (!bbox) { + bbox = this.boundingBox = new __WEBPACK_IMPORTED_MODULE_3__math_BoundingBox__["a" /* default */](); + } + var posArr = this.attributes.position.value; + if (posArr && posArr.length) { + var min = bbox.min; + var max = bbox.max; + var minArr = min.array; + var maxArr = max.array; + __WEBPACK_IMPORTED_MODULE_1__glmatrix_vec3__["a" /* default */].set(minArr, posArr[0], posArr[1], posArr[2]); + __WEBPACK_IMPORTED_MODULE_1__glmatrix_vec3__["a" /* default */].set(maxArr, posArr[0], posArr[1], posArr[2]); + for (var i = 3; i < posArr.length;) { + var x = posArr[i++]; + var y = posArr[i++]; + var z = posArr[i++]; + if (x < minArr[0]) { minArr[0] = x; } + if (y < minArr[1]) { minArr[1] = y; } + if (z < minArr[2]) { minArr[2] = z; } + + if (x > maxArr[0]) { maxArr[0] = x; } + if (y > maxArr[1]) { maxArr[1] = y; } + if (z > maxArr[2]) { maxArr[2] = z; } + } + min._dirty = true; + max._dirty = true; + } + }, + + /** + * Generate normals per vertex. + */ + generateVertexNormals: function () { + if (!this.vertexCount) { + return; + } + + var indices = this.indices; + var attributes = this.attributes; + var positions = attributes.position.value; + var normals = attributes.normal.value; + + if (!normals || normals.length !== positions.length) { + normals = attributes.normal.value = new __WEBPACK_IMPORTED_MODULE_0__core_vendor__["a" /* default */].Float32Array(positions.length); + } + else { + // Reset + for (var i = 0; i < normals.length; i++) { + normals[i] = 0; + } + } + + var p1 = vec3Create(); + var p2 = vec3Create(); + var p3 = vec3Create(); + + var v21 = vec3Create(); + var v32 = vec3Create(); + + var n = vec3Create(); + + var len = indices ? indices.length : this.vertexCount; + var i1, i2, i3; + for (var f = 0; f < len;) { + if (indices) { + i1 = indices[f++]; + i2 = indices[f++]; + i3 = indices[f++]; + } + else { + i1 = f++; + i2 = f++; + i3 = f++; + } + + vec3Set(p1, positions[i1*3], positions[i1*3+1], positions[i1*3+2]); + vec3Set(p2, positions[i2*3], positions[i2*3+1], positions[i2*3+2]); + vec3Set(p3, positions[i3*3], positions[i3*3+1], positions[i3*3+2]); + + __WEBPACK_IMPORTED_MODULE_1__glmatrix_vec3__["a" /* default */].sub(v21, p1, p2); + __WEBPACK_IMPORTED_MODULE_1__glmatrix_vec3__["a" /* default */].sub(v32, p2, p3); + __WEBPACK_IMPORTED_MODULE_1__glmatrix_vec3__["a" /* default */].cross(n, v21, v32); + // Already be weighted by the triangle area + for (var i = 0; i < 3; i++) { + normals[i1*3+i] = normals[i1*3+i] + n[i]; + normals[i2*3+i] = normals[i2*3+i] + n[i]; + normals[i3*3+i] = normals[i3*3+i] + n[i]; + } + } + + for (var i = 0; i < normals.length;) { + vec3Set(n, normals[i], normals[i+1], normals[i+2]); + __WEBPACK_IMPORTED_MODULE_1__glmatrix_vec3__["a" /* default */].normalize(n, n); + normals[i++] = n[0]; + normals[i++] = n[1]; + normals[i++] = n[2]; + } + this.dirty(); + }, + + /** + * Generate normals per face. + */ + generateFaceNormals: function () { + if (!this.vertexCount) { + return; + } + + if (!this.isUniqueVertex()) { + this.generateUniqueVertex(); + } + + var indices = this.indices; + var attributes = this.attributes; + var positions = attributes.position.value; + var normals = attributes.normal.value; + + var p1 = vec3Create(); + var p2 = vec3Create(); + var p3 = vec3Create(); + + var v21 = vec3Create(); + var v32 = vec3Create(); + var n = vec3Create(); + + if (!normals) { + normals = attributes.normal.value = new Float32Array(positions.length); + } + var len = indices ? indices.length : this.vertexCount; + var i1, i2, i3; + for (var f = 0; f < len;) { + if (indices) { + i1 = indices[f++]; + i2 = indices[f++]; + i3 = indices[f++]; + } + else { + i1 = f++; + i2 = f++; + i3 = f++; + } + + vec3Set(p1, positions[i1*3], positions[i1*3+1], positions[i1*3+2]); + vec3Set(p2, positions[i2*3], positions[i2*3+1], positions[i2*3+2]); + vec3Set(p3, positions[i3*3], positions[i3*3+1], positions[i3*3+2]); + + __WEBPACK_IMPORTED_MODULE_1__glmatrix_vec3__["a" /* default */].sub(v21, p1, p2); + __WEBPACK_IMPORTED_MODULE_1__glmatrix_vec3__["a" /* default */].sub(v32, p2, p3); + __WEBPACK_IMPORTED_MODULE_1__glmatrix_vec3__["a" /* default */].cross(n, v21, v32); + + __WEBPACK_IMPORTED_MODULE_1__glmatrix_vec3__["a" /* default */].normalize(n, n); + + for (var i = 0; i < 3; i++) { + normals[i1*3 + i] = n[i]; + normals[i2*3 + i] = n[i]; + normals[i3*3 + i] = n[i]; + } + } + this.dirty(); + }, + + /** + * Generate tangents attributes. + */ + generateTangents: function () { + if (!this.vertexCount) { + return; + } + + var nVertex = this.vertexCount; + var attributes = this.attributes; + if (!attributes.tangent.value) { + attributes.tangent.value = new Float32Array(nVertex * 4); + } + var texcoords = attributes.texcoord0.value; + var positions = attributes.position.value; + var tangents = attributes.tangent.value; + var normals = attributes.normal.value; + + if (!texcoords) { + console.warn('Geometry without texcoords can\'t generate tangents.'); + return; + } + + var tan1 = []; + var tan2 = []; + for (var i = 0; i < nVertex; i++) { + tan1[i] = [0.0, 0.0, 0.0]; + tan2[i] = [0.0, 0.0, 0.0]; + } + + var sdir = [0.0, 0.0, 0.0]; + var tdir = [0.0, 0.0, 0.0]; + var indices = this.indices; + + var len = indices ? indices.length : this.vertexCount; + var i1, i2, i3; + for (var i = 0; i < len;) { + if (indices) { + i1 = indices[i++]; + i2 = indices[i++]; + i3 = indices[i++]; + } + else { + i1 = i++; + i2 = i++; + i3 = i++; + } + + var st1s = texcoords[i1 * 2], + st2s = texcoords[i2 * 2], + st3s = texcoords[i3 * 2], + st1t = texcoords[i1 * 2 + 1], + st2t = texcoords[i2 * 2 + 1], + st3t = texcoords[i3 * 2 + 1], + + p1x = positions[i1 * 3], + p2x = positions[i2 * 3], + p3x = positions[i3 * 3], + p1y = positions[i1 * 3 + 1], + p2y = positions[i2 * 3 + 1], + p3y = positions[i3 * 3 + 1], + p1z = positions[i1 * 3 + 2], + p2z = positions[i2 * 3 + 2], + p3z = positions[i3 * 3 + 2]; + + var x1 = p2x - p1x, + x2 = p3x - p1x, + y1 = p2y - p1y, + y2 = p3y - p1y, + z1 = p2z - p1z, + z2 = p3z - p1z; + + var s1 = st2s - st1s, + s2 = st3s - st1s, + t1 = st2t - st1t, + t2 = st3t - st1t; + + var r = 1.0 / (s1 * t2 - t1 * s2); + sdir[0] = (t2 * x1 - t1 * x2) * r; + sdir[1] = (t2 * y1 - t1 * y2) * r; + sdir[2] = (t2 * z1 - t1 * z2) * r; + + tdir[0] = (s1 * x2 - s2 * x1) * r; + tdir[1] = (s1 * y2 - s2 * y1) * r; + tdir[2] = (s1 * z2 - s2 * z1) * r; + + vec3Add(tan1[i1], tan1[i1], sdir); + vec3Add(tan1[i2], tan1[i2], sdir); + vec3Add(tan1[i3], tan1[i3], sdir); + vec3Add(tan2[i1], tan2[i1], tdir); + vec3Add(tan2[i2], tan2[i2], tdir); + vec3Add(tan2[i3], tan2[i3], tdir); + } + var tmp = vec3Create(); + var nCrossT = vec3Create(); + var n = vec3Create(); + for (var i = 0; i < nVertex; i++) { + n[0] = normals[i * 3]; + n[1] = normals[i * 3 + 1]; + n[2] = normals[i * 3 + 2]; + var t = tan1[i]; + + // Gram-Schmidt orthogonalize + __WEBPACK_IMPORTED_MODULE_1__glmatrix_vec3__["a" /* default */].scale(tmp, n, __WEBPACK_IMPORTED_MODULE_1__glmatrix_vec3__["a" /* default */].dot(n, t)); + __WEBPACK_IMPORTED_MODULE_1__glmatrix_vec3__["a" /* default */].sub(tmp, t, tmp); + __WEBPACK_IMPORTED_MODULE_1__glmatrix_vec3__["a" /* default */].normalize(tmp, tmp); + // Calculate handedness. + __WEBPACK_IMPORTED_MODULE_1__glmatrix_vec3__["a" /* default */].cross(nCrossT, n, t); + tangents[i * 4] = tmp[0]; + tangents[i * 4 + 1] = tmp[1]; + tangents[i * 4 + 2] = tmp[2]; + // PENDING can config ? + tangents[i * 4 + 3] = __WEBPACK_IMPORTED_MODULE_1__glmatrix_vec3__["a" /* default */].dot(nCrossT, tan2[i]) < 0.0 ? -1.0 : 1.0; + } + this.dirty(); + }, + + /** + * If vertices are not shared by different indices. + */ + isUniqueVertex: function () { + if (this.isUseIndices()) { + return this.vertexCount === this.indices.length; + } + else { + return true; + } + }, + /** + * Create a unique vertex for each index. + */ + generateUniqueVertex: function () { + if (!this.vertexCount || !this.indices) { + return; + } + + if (this.indices.length > 0xffff) { + this.indices = new __WEBPACK_IMPORTED_MODULE_0__core_vendor__["a" /* default */].Uint32Array(this.indices); + } + + var attributes = this.attributes; + var indices = this.indices; + + var attributeNameList = this.getEnabledAttributes(); + + var oldAttrValues = {}; + for (var a = 0; a < attributeNameList.length; a++) { + var name = attributeNameList[a]; + oldAttrValues[name] = attributes[name].value; + attributes[name].init(this.indices.length); + } + + var cursor = 0; + for (var i = 0; i < indices.length; i++) { + var ii = indices[i]; + for (var a = 0; a < attributeNameList.length; a++) { + var name = attributeNameList[a]; + var array = attributes[name].value; + var size = attributes[name].size; + + for (var k = 0; k < size; k++) { + array[cursor * size + k] = oldAttrValues[name][ii * size + k]; + } + } + indices[i] = cursor; + cursor++; + } + + this.dirty(); + }, + + /** + * Generate barycentric coordinates for wireframe draw. + */ + generateBarycentric: function () { + if (!this.vertexCount) { + return; + } + + if (!this.isUniqueVertex()) { + this.generateUniqueVertex(); + } + + var attributes = this.attributes; + var array = attributes.barycentric.value; + var indices = this.indices; + // Already existed; + if (array && array.length === indices.length * 3) { + return; + } + array = attributes.barycentric.value = new Float32Array(indices.length * 3); + + for (var i = 0; i < (indices ? indices.length : this.vertexCount / 3);) { + for (var j = 0; j < 3; j++) { + var ii = indices ? indices[i++] : (i * 3 + j); + array[ii * 3 + j] = 1; + } + } + this.dirty(); + }, + + /** + * Apply transform to geometry attributes. + * @param {clay.Matrix4} matrix + */ + applyTransform: function (matrix) { + + var attributes = this.attributes; + var positions = attributes.position.value; + var normals = attributes.normal.value; + var tangents = attributes.tangent.value; + + matrix = matrix.array; + // Normal Matrix + var inverseTransposeMatrix = __WEBPACK_IMPORTED_MODULE_2__glmatrix_mat4__["a" /* default */].create(); + __WEBPACK_IMPORTED_MODULE_2__glmatrix_mat4__["a" /* default */].invert(inverseTransposeMatrix, matrix); + __WEBPACK_IMPORTED_MODULE_2__glmatrix_mat4__["a" /* default */].transpose(inverseTransposeMatrix, inverseTransposeMatrix); + + var vec3TransformMat4 = __WEBPACK_IMPORTED_MODULE_1__glmatrix_vec3__["a" /* default */].transformMat4; + var vec3ForEach = __WEBPACK_IMPORTED_MODULE_1__glmatrix_vec3__["a" /* default */].forEach; + vec3ForEach(positions, 3, 0, null, vec3TransformMat4, matrix); + if (normals) { + vec3ForEach(normals, 3, 0, null, vec3TransformMat4, inverseTransposeMatrix); + } + if (tangents) { + vec3ForEach(tangents, 4, 0, null, vec3TransformMat4, inverseTransposeMatrix); + } + + if (this.boundingBox) { + this.updateBoundingBox(); + } + }, + /** + * Dispose geometry data in GL context. + * @param {clay.Renderer} renderer + */ + dispose: function (renderer) { + + var cache = this._cache; + + cache.use(renderer.__uid__); + var chunks = cache.get('chunks'); + if (chunks) { + for (var c = 0; c < chunks.length; c++) { + var chunk = chunks[c]; + + for (var k = 0; k < chunk.attributeBuffers.length; k++) { + var attribs = chunk.attributeBuffers[k]; + renderer.gl.deleteBuffer(attribs.buffer); + } + + if (chunk.indicesBuffer) { + renderer.gl.deleteBuffer(chunk.indicesBuffer.buffer); + } + } + } + if (this.__vaoCache) { + var vaoExt = renderer.getGLExtension('OES_vertex_array_object'); + for (var id in this.__vaoCache) { + var vao = this.__vaoCache[id].vao; + if (vao) { + vaoExt.deleteVertexArrayOES(vao); + } + } + } + this.__vaoCache = {}; + cache.deleteContext(renderer.__uid__); + } + +}); + +Geometry.STATIC_DRAW = __WEBPACK_IMPORTED_MODULE_4__GeometryBase__["a" /* default */].STATIC_DRAW; +Geometry.DYNAMIC_DRAW = __WEBPACK_IMPORTED_MODULE_4__GeometryBase__["a" /* default */].DYNAMIC_DRAW; +Geometry.STREAM_DRAW = __WEBPACK_IMPORTED_MODULE_4__GeometryBase__["a" /* default */].STREAM_DRAW; + +Geometry.AttributeBuffer = __WEBPACK_IMPORTED_MODULE_4__GeometryBase__["a" /* default */].AttributeBuffer; +Geometry.IndicesBuffer = __WEBPACK_IMPORTED_MODULE_4__GeometryBase__["a" /* default */].IndicesBuffer; + +Geometry.Attribute = Attribute; + +/* harmony default export */ __webpack_exports__["a"] = (Geometry); + + +/***/ }), +/* 16 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__core_Base__ = __webpack_require__(7); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__camera_Orthographic__ = __webpack_require__(37); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__geometry_Plane__ = __webpack_require__(43); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__Shader__ = __webpack_require__(8); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4__Material__ = __webpack_require__(19); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_5__Mesh__ = __webpack_require__(40); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_6__core_glenum__ = __webpack_require__(11); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_7__shader_source_compositor_vertex_glsl_js__ = __webpack_require__(126); + + + + + + + + + +__WEBPACK_IMPORTED_MODULE_3__Shader__["a" /* default */]['import'](__WEBPACK_IMPORTED_MODULE_7__shader_source_compositor_vertex_glsl_js__["a" /* default */]); + +var planeGeo = new __WEBPACK_IMPORTED_MODULE_2__geometry_Plane__["a" /* default */](); +var mesh = new __WEBPACK_IMPORTED_MODULE_5__Mesh__["a" /* default */]({ + geometry: planeGeo, + frustumCulling: false +}); +var camera = new __WEBPACK_IMPORTED_MODULE_1__camera_Orthographic__["a" /* default */](); + +/** + * @constructor clay.compositor.Pass + * @extends clay.core.Base + */ +var Pass = __WEBPACK_IMPORTED_MODULE_0__core_Base__["a" /* default */].extend(function () { + return /** @lends clay.compositor.Pass# */ { + /** + * Fragment shader string + * @type {string} + */ + // PENDING shader or fragment ? + fragment: '', + + /** + * @type {Object} + */ + outputs: null, + + /** + * @type {clay.Material} + */ + material: null, + + /** + * @type {Boolean} + */ + blendWithPrevious: false, + + /** + * @type {Boolean} + */ + clearColor: false, + + /** + * @type {Boolean} + */ + clearDepth: true + }; +}, function() { + + var shader = new __WEBPACK_IMPORTED_MODULE_3__Shader__["a" /* default */](__WEBPACK_IMPORTED_MODULE_3__Shader__["a" /* default */].source('clay.compositor.vertex'), this.fragment); + var material = new __WEBPACK_IMPORTED_MODULE_4__Material__["a" /* default */]({ + shader: shader + }); + material.enableTexturesAll(); + + this.material = material; + +}, +/** @lends clay.compositor.Pass.prototype */ +{ + /** + * @param {string} name + * @param {} value + */ + setUniform: function(name, value) { + this.material.setUniform(name, value); + }, + /** + * @param {string} name + * @return {} + */ + getUniform: function(name) { + var uniform = this.material.uniforms[name]; + if (uniform) { + return uniform.value; + } + }, + /** + * @param {clay.Texture} texture + * @param {number} attachment + */ + attachOutput: function(texture, attachment) { + if (!this.outputs) { + this.outputs = {}; + } + attachment = attachment || __WEBPACK_IMPORTED_MODULE_6__core_glenum__["a" /* default */].COLOR_ATTACHMENT0; + this.outputs[attachment] = texture; + }, + /** + * @param {clay.Texture} texture + */ + detachOutput: function(texture) { + for (var attachment in this.outputs) { + if (this.outputs[attachment] === texture) { + this.outputs[attachment] = null; + } + } + }, + + bind: function(renderer, frameBuffer) { + + if (this.outputs) { + for (var attachment in this.outputs) { + var texture = this.outputs[attachment]; + if (texture) { + frameBuffer.attach(texture, attachment); + } + } + } + + if (frameBuffer) { + frameBuffer.bind(renderer); + } + }, + + unbind: function(renderer, frameBuffer) { + frameBuffer.unbind(renderer); + }, + /** + * @param {clay.Renderer} renderer + * @param {clay.FrameBuffer} [frameBuffer] + */ + render: function(renderer, frameBuffer) { + + var _gl = renderer.gl; + + if (frameBuffer) { + this.bind(renderer, frameBuffer); + // MRT Support in chrome + // https://www.khronos.org/registry/webgl/sdk/tests/conformance/extensions/ext-draw-buffers.html + var ext = renderer.getGLExtension('EXT_draw_buffers'); + if (ext && this.outputs) { + var bufs = []; + for (var attachment in this.outputs) { + attachment = +attachment; + if (attachment >= _gl.COLOR_ATTACHMENT0 && attachment <= _gl.COLOR_ATTACHMENT0 + 8) { + bufs.push(attachment); + } + } + ext.drawBuffersEXT(bufs); + } + } + + this.trigger('beforerender', this, renderer); + + // FIXME Don't clear in each pass in default, let the color overwrite the buffer + // FIXME pixels may be discard + var clearBit = this.clearDepth ? _gl.DEPTH_BUFFER_BIT : 0; + _gl.depthMask(true); + if (this.clearColor) { + clearBit = clearBit | _gl.COLOR_BUFFER_BIT; + _gl.colorMask(true, true, true, true); + var cc = this.clearColor; + if (Array.isArray(cc)) { + _gl.clearColor(cc[0], cc[1], cc[2], cc[3]); + } + } + _gl.clear(clearBit); + + if (this.blendWithPrevious) { + // Blend with previous rendered scene in the final output + // FIXME Configure blend. + // FIXME It will cause screen blink? + _gl.enable(_gl.BLEND); + this.material.transparent = true; + } + else { + _gl.disable(_gl.BLEND); + this.material.transparent = false; + } + + this.renderQuad(renderer); + + this.trigger('afterrender', this, renderer); + + if (frameBuffer) { + this.unbind(renderer, frameBuffer); + } + }, + + /** + * Simply do quad rendering + */ + renderQuad: function (renderer) { + mesh.material = this.material; + renderer.renderPass([mesh], camera); + }, + + /** + * @param {clay.Renderer} renderer + */ + dispose: function (renderer) {} +}); + +/* harmony default export */ __webpack_exports__["a"] = (Pass); + + +/***/ }), +/* 17 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony default export */ __webpack_exports__["a"] = (function (seriesType, ecModel, api) { + return { + seriesType: seriesType, + reset: function (seriesModel, ecModel) { + var data = seriesModel.getData(); + var opacityAccessPath = seriesModel.visualColorAccessPath.split('.'); + opacityAccessPath[opacityAccessPath.length - 1] ='opacity'; + + var opacity = seriesModel.get(opacityAccessPath); + + data.setVisual('opacity', opacity == null ? 1 : opacity); + + function dataEach(data, idx) { + var itemModel = data.getItemModel(idx); + var opacity = itemModel.get(opacityAccessPath, true); + if (opacity != null) { + data.setItemVisual(idx, 'opacity', opacity); + } + } + + return { + dataEach: data.hasItemOption ? dataEach : null + }; + } + }; +}); + +/***/ }), +/* 18 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__Vector3__ = __webpack_require__(3); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__glmatrix_vec3__ = __webpack_require__(12); + + + +var vec3Set = __WEBPACK_IMPORTED_MODULE_1__glmatrix_vec3__["a" /* default */].set; +var vec3Copy = __WEBPACK_IMPORTED_MODULE_1__glmatrix_vec3__["a" /* default */].copy; + +/** + * Axis aligned bounding box + * @constructor + * @alias clay.BoundingBox + * @param {clay.Vector3} [min] + * @param {clay.Vector3} [max] + */ +var BoundingBox = function (min, max) { + + /** + * Minimum coords of bounding box + * @type {clay.Vector3} + */ + this.min = min || new __WEBPACK_IMPORTED_MODULE_0__Vector3__["a" /* default */](Infinity, Infinity, Infinity); + + /** + * Maximum coords of bounding box + * @type {clay.Vector3} + */ + this.max = max || new __WEBPACK_IMPORTED_MODULE_0__Vector3__["a" /* default */](-Infinity, -Infinity, -Infinity); + + this.vertices = null; +}; + +BoundingBox.prototype = { + + constructor: BoundingBox, + /** + * Update min and max coords from a vertices array + * @param {array} vertices + */ + updateFromVertices: function (vertices) { + if (vertices.length > 0) { + var min = this.min; + var max = this.max; + var minArr = min.array; + var maxArr = max.array; + vec3Copy(minArr, vertices[0]); + vec3Copy(maxArr, vertices[0]); + for (var i = 1; i < vertices.length; i++) { + var vertex = vertices[i]; + + if (vertex[0] < minArr[0]) { minArr[0] = vertex[0]; } + if (vertex[1] < minArr[1]) { minArr[1] = vertex[1]; } + if (vertex[2] < minArr[2]) { minArr[2] = vertex[2]; } + + if (vertex[0] > maxArr[0]) { maxArr[0] = vertex[0]; } + if (vertex[1] > maxArr[1]) { maxArr[1] = vertex[1]; } + if (vertex[2] > maxArr[2]) { maxArr[2] = vertex[2]; } + } + min._dirty = true; + max._dirty = true; + } + }, + + /** + * Union operation with another bounding box + * @param {clay.BoundingBox} bbox + */ + union: function (bbox) { + var min = this.min; + var max = this.max; + __WEBPACK_IMPORTED_MODULE_1__glmatrix_vec3__["a" /* default */].min(min.array, min.array, bbox.min.array); + __WEBPACK_IMPORTED_MODULE_1__glmatrix_vec3__["a" /* default */].max(max.array, max.array, bbox.max.array); + min._dirty = true; + max._dirty = true; + return this; + }, + + /** + * Intersection operation with another bounding box + * @param {clay.BoundingBox} bbox + */ + intersection: function (bbox) { + var min = this.min; + var max = this.max; + __WEBPACK_IMPORTED_MODULE_1__glmatrix_vec3__["a" /* default */].max(min.array, min.array, bbox.min.array); + __WEBPACK_IMPORTED_MODULE_1__glmatrix_vec3__["a" /* default */].min(max.array, max.array, bbox.max.array); + min._dirty = true; + max._dirty = true; + return this; + }, + + /** + * If intersect with another bounding box + * @param {clay.BoundingBox} bbox + * @return {boolean} + */ + intersectBoundingBox: function (bbox) { + var _min = this.min.array; + var _max = this.max.array; + + var _min2 = bbox.min.array; + var _max2 = bbox.max.array; + + return ! (_min[0] > _max2[0] || _min[1] > _max2[1] || _min[2] > _max2[2] + || _max[0] < _min2[0] || _max[1] < _min2[1] || _max[2] < _min2[2]); + }, + + /** + * If contain another bounding box entirely + * @param {clay.BoundingBox} bbox + * @return {boolean} + */ + containBoundingBox: function (bbox) { + + var _min = this.min.array; + var _max = this.max.array; + + var _min2 = bbox.min.array; + var _max2 = bbox.max.array; + + return _min[0] <= _min2[0] && _min[1] <= _min2[1] && _min[2] <= _min2[2] + && _max[0] >= _max2[0] && _max[1] >= _max2[1] && _max[2] >= _max2[2]; + }, + + /** + * If contain point entirely + * @param {clay.Vector3} point + * @return {boolean} + */ + containPoint: function (p) { + var _min = this.min.array; + var _max = this.max.array; + + var _p = p.array; + + return _min[0] <= _p[0] && _min[1] <= _p[1] && _min[2] <= _p[2] + && _max[0] >= _p[0] && _max[1] >= _p[1] && _max[2] >= _p[2]; + }, + + /** + * If bounding box is finite + */ + isFinite: function () { + var _min = this.min.array; + var _max = this.max.array; + return isFinite(_min[0]) && isFinite(_min[1]) && isFinite(_min[2]) + && isFinite(_max[0]) && isFinite(_max[1]) && isFinite(_max[2]); + }, + + /** + * Apply an affine transform matrix to the bounding box + * @param {clay.Matrix4} matrix + */ + applyTransform: function (matrix) { + this.transformFrom(this, matrix); + }, + + /** + * Get from another bounding box and an affine transform matrix. + * @param {clay.BoundingBox} source + * @param {clay.Matrix4} matrix + */ + transformFrom: (function () { + // http://dev.theomader.com/transform-bounding-boxes/ + var xa = __WEBPACK_IMPORTED_MODULE_1__glmatrix_vec3__["a" /* default */].create(); + var xb = __WEBPACK_IMPORTED_MODULE_1__glmatrix_vec3__["a" /* default */].create(); + var ya = __WEBPACK_IMPORTED_MODULE_1__glmatrix_vec3__["a" /* default */].create(); + var yb = __WEBPACK_IMPORTED_MODULE_1__glmatrix_vec3__["a" /* default */].create(); + var za = __WEBPACK_IMPORTED_MODULE_1__glmatrix_vec3__["a" /* default */].create(); + var zb = __WEBPACK_IMPORTED_MODULE_1__glmatrix_vec3__["a" /* default */].create(); + + return function (source, matrix) { + var min = source.min.array; + var max = source.max.array; + + var m = matrix.array; + + xa[0] = m[0] * min[0]; xa[1] = m[1] * min[0]; xa[2] = m[2] * min[0]; + xb[0] = m[0] * max[0]; xb[1] = m[1] * max[0]; xb[2] = m[2] * max[0]; + + ya[0] = m[4] * min[1]; ya[1] = m[5] * min[1]; ya[2] = m[6] * min[1]; + yb[0] = m[4] * max[1]; yb[1] = m[5] * max[1]; yb[2] = m[6] * max[1]; + + za[0] = m[8] * min[2]; za[1] = m[9] * min[2]; za[2] = m[10] * min[2]; + zb[0] = m[8] * max[2]; zb[1] = m[9] * max[2]; zb[2] = m[10] * max[2]; + + min = this.min.array; + max = this.max.array; + min[0] = Math.min(xa[0], xb[0]) + Math.min(ya[0], yb[0]) + Math.min(za[0], zb[0]) + m[12]; + min[1] = Math.min(xa[1], xb[1]) + Math.min(ya[1], yb[1]) + Math.min(za[1], zb[1]) + m[13]; + min[2] = Math.min(xa[2], xb[2]) + Math.min(ya[2], yb[2]) + Math.min(za[2], zb[2]) + m[14]; + + max[0] = Math.max(xa[0], xb[0]) + Math.max(ya[0], yb[0]) + Math.max(za[0], zb[0]) + m[12]; + max[1] = Math.max(xa[1], xb[1]) + Math.max(ya[1], yb[1]) + Math.max(za[1], zb[1]) + m[13]; + max[2] = Math.max(xa[2], xb[2]) + Math.max(ya[2], yb[2]) + Math.max(za[2], zb[2]) + m[14]; + + this.min._dirty = true; + this.max._dirty = true; + + return this; + }; + })(), + + /** + * Apply a projection matrix to the bounding box + * @param {clay.Matrix4} matrix + */ + applyProjection: function (matrix) { + var min = this.min.array; + var max = this.max.array; + + var m = matrix.array; + // min in min z + var v10 = min[0]; + var v11 = min[1]; + var v12 = min[2]; + // max in min z + var v20 = max[0]; + var v21 = max[1]; + var v22 = min[2]; + // max in max z + var v30 = max[0]; + var v31 = max[1]; + var v32 = max[2]; + + if (m[15] === 1) { // Orthographic projection + min[0] = m[0] * v10 + m[12]; + min[1] = m[5] * v11 + m[13]; + max[2] = m[10] * v12 + m[14]; + + max[0] = m[0] * v30 + m[12]; + max[1] = m[5] * v31 + m[13]; + min[2] = m[10] * v32 + m[14]; + } + else { + var w = -1 / v12; + min[0] = m[0] * v10 * w; + min[1] = m[5] * v11 * w; + max[2] = (m[10] * v12 + m[14]) * w; + + w = -1 / v22; + max[0] = m[0] * v20 * w; + max[1] = m[5] * v21 * w; + + w = -1 / v32; + min[2] = (m[10] * v32 + m[14]) * w; + } + this.min._dirty = true; + this.max._dirty = true; + + return this; + }, + + updateVertices: function () { + var vertices = this.vertices; + if (!vertices) { + // Cube vertices + vertices = []; + for (var i = 0; i < 8; i++) { + vertices[i] = __WEBPACK_IMPORTED_MODULE_1__glmatrix_vec3__["a" /* default */].fromValues(0, 0, 0); + } + + /** + * Eight coords of bounding box + * @type {Float32Array[]} + */ + this.vertices = vertices; + } + var min = this.min.array; + var max = this.max.array; + //--- min z + // min x + vec3Set(vertices[0], min[0], min[1], min[2]); + vec3Set(vertices[1], min[0], max[1], min[2]); + // max x + vec3Set(vertices[2], max[0], min[1], min[2]); + vec3Set(vertices[3], max[0], max[1], min[2]); + + //-- max z + vec3Set(vertices[4], min[0], min[1], max[2]); + vec3Set(vertices[5], min[0], max[1], max[2]); + vec3Set(vertices[6], max[0], min[1], max[2]); + vec3Set(vertices[7], max[0], max[1], max[2]); + + return this; + }, + /** + * Copy values from another bounding box + * @param {clay.BoundingBox} bbox + */ + copy: function (bbox) { + var min = this.min; + var max = this.max; + vec3Copy(min.array, bbox.min.array); + vec3Copy(max.array, bbox.max.array); + min._dirty = true; + max._dirty = true; + return this; + }, + + /** + * Clone a new bounding box + * @return {clay.BoundingBox} + */ + clone: function () { + var boundingBox = new BoundingBox(); + boundingBox.copy(this); + return boundingBox; + } +}; + +/* harmony default export */ __webpack_exports__["a"] = (BoundingBox); + + +/***/ }), +/* 19 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__core_Base__ = __webpack_require__(7); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__core_util__ = __webpack_require__(23); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__core_color__ = __webpack_require__(113); + + + +var parseColor = __WEBPACK_IMPORTED_MODULE_2__core_color__["a" /* default */].parseToFloat; + +var programKeyCache = {}; + +function getDefineCode(defines) { + var defineKeys = Object.keys(defines); + defineKeys.sort(); + var defineStr = []; + // Custom Defines + for (var i = 0; i < defineKeys.length; i++) { + var key = defineKeys[i]; + var value = defines[key]; + if (value === null) { + defineStr.push(key); + } + else{ + defineStr.push(key + ' ' + value.toString()); + } + } + return defineStr.join('\n'); +} + +function getProgramKey(vertexDefines, fragmentDefines, enabledTextures) { + enabledTextures.sort(); + var defineStr = []; + for (var i = 0; i < enabledTextures.length; i++) { + var symbol = enabledTextures[i]; + defineStr.push(symbol); + } + var key = getDefineCode(vertexDefines) + '\n' + + getDefineCode(fragmentDefines) + '\n' + + defineStr.join('\n'); + + if (programKeyCache[key]) { + return programKeyCache[key]; + } + + var id = __WEBPACK_IMPORTED_MODULE_1__core_util__["a" /* default */].genGUID(); + programKeyCache[key] = id; + return id; +} + +/** + * Material defines the appearance of mesh surface, like `color`, `roughness`, `metalness`, etc. + * It contains a {@link clay.Shader} and corresponding uniforms. + * + * Here is a basic example to create a standard material +```js +var material = new clay.Material({ + shader: new clay.Shader( + clay.Shader.source('clay.vertex'), + clay.Shader.source('clay.fragment') + ) +}); +``` + * @constructor clay.Material + * @extends clay.core.Base + */ +var Material = __WEBPACK_IMPORTED_MODULE_0__core_Base__["a" /* default */].extend(function () { + return /** @lends clay.Material# */ { + /** + * @type {string} + */ + name: '', + + /** + * @type {Object} + */ + // uniforms: null, + + /** + * @type {clay.Shader} + */ + // shader: null, + + /** + * @type {boolean} + */ + depthTest: true, + + /** + * @type {boolean} + */ + depthMask: true, + + /** + * @type {boolean} + */ + transparent: false, + /** + * Blend func is a callback function when the material + * have custom blending + * The gl context will be the only argument passed in tho the + * blend function + * Detail of blend function in WebGL: + * http://www.khronos.org/registry/gles/specs/2.0/es_full_spec_2.0.25.pdf + * + * Example : + * function(_gl) { + * _gl.blendEquation(_gl.FUNC_ADD); + * _gl.blendFunc(_gl.SRC_ALPHA, _gl.ONE_MINUS_SRC_ALPHA); + * } + */ + blend: null, + + /** + * If update texture status automatically. + */ + autoUpdateTextureStatus: true, + + uniforms: {}, + vertexDefines: {}, + fragmentDefines: {}, + _textureStatus: {}, + + // shadowTransparentMap : null + + // PENDING enable the uniform that only used in shader. + _enabledUniforms: null, + }; +}, function () { + if (!this.name) { + this.name = 'MATERIAL_' + this.__uid__; + } + + if (this.shader) { + // Keep status, mainly preset uniforms, vertexDefines and fragmentDefines + this.attachShader(this.shader, true); + } +}, +/** @lends clay.Material.prototype */ +{ + precision: 'highp', + + /** + * Set material uniform + * @example + * mat.setUniform('color', [1, 1, 1, 1]); + * @param {string} symbol + * @param {number|array|clay.Texture|ArrayBufferView} value + */ + setUniform: function (symbol, value) { + if (value === undefined) { + console.warn('Uniform value "' + symbol + '" is undefined'); + } + var uniform = this.uniforms[symbol]; + if (uniform) { + + if (typeof value === 'string') { + // Try to parse as a color. Invalid color string will return null. + value = parseColor(value) || value; + } + + uniform.value = value; + + if (this.autoUpdateTextureStatus && uniform.type === 't') { + if (value) { + this.enableTexture(symbol); + } + else { + this.disableTexture(symbol); + } + } + } + }, + + /** + * @param {Object} obj + */ + setUniforms: function(obj) { + for (var key in obj) { + var val = obj[key]; + this.setUniform(key, val); + } + }, + + /** + * @param {string} symbol + * @return {boolean} + */ + isUniformEnabled: function (symbol) { + return this._enabledUniforms.indexOf(symbol) >= 0; + }, + + getEnabledUniforms: function () { + return this._enabledUniforms; + }, + getTextureUniforms: function () { + return this._textureUniforms; + }, + + /** + * Alias of setUniform and setUniforms + * @param {object|string} symbol + * @param {number|array|clay.Texture|ArrayBufferView} [value] + */ + set: function (symbol, value) { + if (typeof(symbol) === 'object') { + for (var key in symbol) { + var val = symbol[key]; + this.setUniform(key, val); + } + } + else { + this.setUniform(symbol, value); + } + }, + /** + * Get uniform value + * @param {string} symbol + * @return {number|array|clay.Texture|ArrayBufferView} + */ + get: function (symbol) { + var uniform = this.uniforms[symbol]; + if (uniform) { + return uniform.value; + } + }, + /** + * Attach a shader instance + * @param {clay.Shader} shader + * @param {boolean} keepStatus If try to keep uniform and texture + */ + attachShader: function(shader, keepStatus) { + var originalUniforms = this.uniforms; + + // Ignore if uniform can use in shader. + this.uniforms = shader.createUniforms(); + this.shader = shader; + + var uniforms = this.uniforms; + this._enabledUniforms = Object.keys(uniforms); + // Make sure uniforms are set in same order to avoid texture slot wrong + this._enabledUniforms.sort(); + this._textureUniforms = this._enabledUniforms.filter(function (uniformName) { + var type = this.uniforms[uniformName].type; + return type === 't' || type === 'tv'; + }, this); + + var originalVertexDefines = this.vertexDefines; + var originalFragmentDefines = this.fragmentDefines; + + this.vertexDefines = __WEBPACK_IMPORTED_MODULE_1__core_util__["a" /* default */].clone(shader.vertexDefines); + this.fragmentDefines = __WEBPACK_IMPORTED_MODULE_1__core_util__["a" /* default */].clone(shader.fragmentDefines); + + if (keepStatus) { + for (var symbol in originalUniforms) { + if (uniforms[symbol]) { + uniforms[symbol].value = originalUniforms[symbol].value; + } + } + + __WEBPACK_IMPORTED_MODULE_1__core_util__["a" /* default */].defaults(this.vertexDefines, originalVertexDefines); + __WEBPACK_IMPORTED_MODULE_1__core_util__["a" /* default */].defaults(this.fragmentDefines, originalFragmentDefines); + } + + var textureStatus = {}; + for (var key in shader.textures) { + textureStatus[key] = { + shaderType: shader.textures[key].shaderType, + type: shader.textures[key].type, + enabled: (keepStatus && this._textureStatus[key]) ? this._textureStatus[key].enabled : false + }; + } + + this._textureStatus = textureStatus; + + this._programKey = ''; + }, + + /** + * Clone a new material and keep uniforms, shader will not be cloned + * @return {clay.Material} + */ + clone: function () { + var material = new this.constructor({ + name: this.name, + shader: this.shader + }); + for (var symbol in this.uniforms) { + material.uniforms[symbol].value = this.uniforms[symbol].value; + } + material.depthTest = this.depthTest; + material.depthMask = this.depthMask; + material.transparent = this.transparent; + material.blend = this.blend; + + material.vertexDefines = __WEBPACK_IMPORTED_MODULE_1__core_util__["a" /* default */].clone(this.vertexDefines); + material.fragmentDefines = __WEBPACK_IMPORTED_MODULE_1__core_util__["a" /* default */].clone(this.fragmentDefines); + material.enableTexture(this.getEnabledTextures()); + material.precision = this.precision; + + return material; + }, + + /** + * Add a #define macro in shader code + * @param {string} shaderType Can be vertex, fragment or both + * @param {string} symbol + * @param {number} [val] + */ + define: function (shaderType, symbol, val) { + var vertexDefines = this.vertexDefines; + var fragmentDefines = this.fragmentDefines; + if (shaderType !== 'vertex' && shaderType !== 'fragment' && shaderType !== 'both' + && arguments.length < 3 + ) { + // shaderType default to be 'both' + val = symbol; + symbol = shaderType; + shaderType = 'both'; + } + val = val != null ? val : null; + if (shaderType === 'vertex' || shaderType === 'both') { + if (vertexDefines[symbol] !== val) { + vertexDefines[symbol] = val; + // Mark as dirty + this._programKey = ''; + } + } + if (shaderType === 'fragment' || shaderType === 'both') { + if (fragmentDefines[symbol] !== val) { + fragmentDefines[symbol] = val; + if (shaderType !== 'both') { + this._programKey = ''; + } + } + } + }, + + /** + * Remove a #define macro in shader code + * @param {string} shaderType Can be vertex, fragment or both + * @param {string} symbol + */ + undefine: function (shaderType, symbol) { + if (shaderType !== 'vertex' && shaderType !== 'fragment' && shaderType !== 'both' + && arguments.length < 2 + ) { + // shaderType default to be 'both' + symbol = shaderType; + shaderType = 'both'; + } + if (shaderType === 'vertex' || shaderType === 'both') { + if (this.isDefined('vertex', symbol)) { + delete this.vertexDefines[symbol]; + // Mark as dirty + this._programKey = ''; + } + } + if (shaderType === 'fragment' || shaderType === 'both') { + if (this.isDefined('fragment', symbol)) { + delete this.fragmentDefines[symbol]; + if (shaderType !== 'both') { + this._programKey = ''; + } + } + } + }, + + /** + * If macro is defined in shader. + * @param {string} shaderType Can be vertex, fragment or both + * @param {string} symbol + */ + isDefined: function (shaderType, symbol) { + // PENDING hasOwnProperty ? + switch (shaderType) { + case 'vertex': + return this.vertexDefines[symbol] !== undefined; + case 'fragment': + return this.fragmentDefines[symbol] !== undefined; + } + }, + /** + * Get macro value defined in shader. + * @param {string} shaderType Can be vertex, fragment or both + * @param {string} symbol + */ + getDefine: function (shaderType, symbol) { + switch(shaderType) { + case 'vertex': + return this.vertexDefines[symbol]; + case 'fragment': + return this.fragmentDefines[symbol]; + } + }, + /** + * Enable a texture, actually it will add a #define macro in the shader code + * For example, if texture symbol is diffuseMap, it will add a line `#define DIFFUSEMAP_ENABLED` in the shader code + * @param {string} symbol + */ + enableTexture: function (symbol) { + if (Array.isArray(symbol)) { + for (var i = 0; i < symbol.length; i++) { + this.enableTexture(symbol[i]); + } + return; + } + + var status = this._textureStatus[symbol]; + if (status) { + var isEnabled = status.enabled; + if (!isEnabled) { + status.enabled = true; + this._programKey = ''; + } + } + }, + /** + * Enable all textures used in the shader + */ + enableTexturesAll: function () { + var textureStatus = this._textureStatus; + for (var symbol in textureStatus) { + textureStatus[symbol].enabled = true; + } + + this._programKey = ''; + }, + /** + * Disable a texture, it remove a #define macro in the shader + * @param {string} symbol + */ + disableTexture: function (symbol) { + if (Array.isArray(symbol)) { + for (var i = 0; i < symbol.length; i++) { + this.disableTexture(symbol[i]); + } + return; + } + + var status = this._textureStatus[symbol]; + if (status) { + var isDisabled = ! status.enabled; + if (!isDisabled) { + status.enabled = false; + this._programKey = ''; + } + } + }, + /** + * Disable all textures used in the shader + */ + disableTexturesAll: function () { + var textureStatus = this._textureStatus; + for (var symbol in textureStatus) { + textureStatus[symbol].enabled = false; + } + + this._programKey = ''; + }, + /** + * If texture of given type is enabled. + * @param {string} symbol + * @return {boolean} + */ + isTextureEnabled: function (symbol) { + var textureStatus = this._textureStatus; + return !!textureStatus[symbol] + && textureStatus[symbol].enabled; + }, + + /** + * Get all enabled textures + * @return {string[]} + */ + getEnabledTextures: function () { + var enabledTextures = []; + var textureStatus = this._textureStatus; + for (var symbol in textureStatus) { + if (textureStatus[symbol].enabled) { + enabledTextures.push(symbol); + } + } + return enabledTextures; + }, + + /** + * Mark defines are updated. + */ + dirtyDefines: function () { + this._programKey = ''; + }, + + getProgramKey: function () { + if (!this._programKey) { + this._programKey = getProgramKey( + this.vertexDefines, this.fragmentDefines, this.getEnabledTextures() + ); + } + return this._programKey; + } +}); + +/* harmony default export */ __webpack_exports__["a"] = (Material); + + +/***/ }), +/* 20 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "b", function() { return GLMAT_EPSILON; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return GLMAT_ARRAY_TYPE; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "c", function() { return GLMAT_RANDOM; }); + +var GLMAT_EPSILON = 0.000001; + +// Use Array instead of Float32Array. It seems to be much faster and higher precision. +var GLMAT_ARRAY_TYPE = Array; +// if(!GLMAT_ARRAY_TYPE) { +// GLMAT_ARRAY_TYPE = (typeof Float32Array !== 'undefined') ? Float32Array : Array; +// } + +var GLMAT_RANDOM = Math.random; + + +/***/ }), +/* 21 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__common__ = __webpack_require__(20); + +/* Copyright (c) 2013, Brandon Jones, Colin MacKenzie IV. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + + + +/** + * @class 4x4 Matrix + * @name mat4 + */ + +var mat4 = {}; + +/** + * Creates a new identity mat4 + * + * @returns {mat4} a new 4x4 matrix + */ +mat4.create = function() { + var out = new __WEBPACK_IMPORTED_MODULE_0__common__["a" /* GLMAT_ARRAY_TYPE */](16); + out[0] = 1; + out[1] = 0; + out[2] = 0; + out[3] = 0; + out[4] = 0; + out[5] = 1; + out[6] = 0; + out[7] = 0; + out[8] = 0; + out[9] = 0; + out[10] = 1; + out[11] = 0; + out[12] = 0; + out[13] = 0; + out[14] = 0; + out[15] = 1; + return out; +}; + +/** + * Creates a new mat4 initialized with values from an existing matrix + * + * @param {mat4} a matrix to clone + * @returns {mat4} a new 4x4 matrix + */ +mat4.clone = function(a) { + var out = new __WEBPACK_IMPORTED_MODULE_0__common__["a" /* GLMAT_ARRAY_TYPE */](16); + out[0] = a[0]; + out[1] = a[1]; + out[2] = a[2]; + out[3] = a[3]; + out[4] = a[4]; + out[5] = a[5]; + out[6] = a[6]; + out[7] = a[7]; + out[8] = a[8]; + out[9] = a[9]; + out[10] = a[10]; + out[11] = a[11]; + out[12] = a[12]; + out[13] = a[13]; + out[14] = a[14]; + out[15] = a[15]; + return out; +}; + +/** + * Copy the values from one mat4 to another + * + * @param {mat4} out the receiving matrix + * @param {mat4} a the source matrix + * @returns {mat4} out + */ +mat4.copy = function(out, a) { + out[0] = a[0]; + out[1] = a[1]; + out[2] = a[2]; + out[3] = a[3]; + out[4] = a[4]; + out[5] = a[5]; + out[6] = a[6]; + out[7] = a[7]; + out[8] = a[8]; + out[9] = a[9]; + out[10] = a[10]; + out[11] = a[11]; + out[12] = a[12]; + out[13] = a[13]; + out[14] = a[14]; + out[15] = a[15]; + return out; +}; + +/** + * Set a mat4 to the identity matrix + * + * @param {mat4} out the receiving matrix + * @returns {mat4} out + */ +mat4.identity = function(out) { + out[0] = 1; + out[1] = 0; + out[2] = 0; + out[3] = 0; + out[4] = 0; + out[5] = 1; + out[6] = 0; + out[7] = 0; + out[8] = 0; + out[9] = 0; + out[10] = 1; + out[11] = 0; + out[12] = 0; + out[13] = 0; + out[14] = 0; + out[15] = 1; + return out; +}; + +/** + * Transpose the values of a mat4 + * + * @param {mat4} out the receiving matrix + * @param {mat4} a the source matrix + * @returns {mat4} out + */ +mat4.transpose = function(out, a) { + // If we are transposing ourselves we can skip a few steps but have to cache some values + if (out === a) { + var a01 = a[1], a02 = a[2], a03 = a[3], + a12 = a[6], a13 = a[7], + a23 = a[11]; + + out[1] = a[4]; + out[2] = a[8]; + out[3] = a[12]; + out[4] = a01; + out[6] = a[9]; + out[7] = a[13]; + out[8] = a02; + out[9] = a12; + out[11] = a[14]; + out[12] = a03; + out[13] = a13; + out[14] = a23; + } else { + out[0] = a[0]; + out[1] = a[4]; + out[2] = a[8]; + out[3] = a[12]; + out[4] = a[1]; + out[5] = a[5]; + out[6] = a[9]; + out[7] = a[13]; + out[8] = a[2]; + out[9] = a[6]; + out[10] = a[10]; + out[11] = a[14]; + out[12] = a[3]; + out[13] = a[7]; + out[14] = a[11]; + out[15] = a[15]; + } + + return out; +}; + +/** + * Inverts a mat4 + * + * @param {mat4} out the receiving matrix + * @param {mat4} a the source matrix + * @returns {mat4} out + */ +mat4.invert = function(out, a) { + var a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3], + a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7], + a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11], + a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15], + + b00 = a00 * a11 - a01 * a10, + b01 = a00 * a12 - a02 * a10, + b02 = a00 * a13 - a03 * a10, + b03 = a01 * a12 - a02 * a11, + b04 = a01 * a13 - a03 * a11, + b05 = a02 * a13 - a03 * a12, + b06 = a20 * a31 - a21 * a30, + b07 = a20 * a32 - a22 * a30, + b08 = a20 * a33 - a23 * a30, + b09 = a21 * a32 - a22 * a31, + b10 = a21 * a33 - a23 * a31, + b11 = a22 * a33 - a23 * a32, + + // Calculate the determinant + det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06; + + if (!det) { + return null; + } + det = 1.0 / det; + + out[0] = (a11 * b11 - a12 * b10 + a13 * b09) * det; + out[1] = (a02 * b10 - a01 * b11 - a03 * b09) * det; + out[2] = (a31 * b05 - a32 * b04 + a33 * b03) * det; + out[3] = (a22 * b04 - a21 * b05 - a23 * b03) * det; + out[4] = (a12 * b08 - a10 * b11 - a13 * b07) * det; + out[5] = (a00 * b11 - a02 * b08 + a03 * b07) * det; + out[6] = (a32 * b02 - a30 * b05 - a33 * b01) * det; + out[7] = (a20 * b05 - a22 * b02 + a23 * b01) * det; + out[8] = (a10 * b10 - a11 * b08 + a13 * b06) * det; + out[9] = (a01 * b08 - a00 * b10 - a03 * b06) * det; + out[10] = (a30 * b04 - a31 * b02 + a33 * b00) * det; + out[11] = (a21 * b02 - a20 * b04 - a23 * b00) * det; + out[12] = (a11 * b07 - a10 * b09 - a12 * b06) * det; + out[13] = (a00 * b09 - a01 * b07 + a02 * b06) * det; + out[14] = (a31 * b01 - a30 * b03 - a32 * b00) * det; + out[15] = (a20 * b03 - a21 * b01 + a22 * b00) * det; + + return out; +}; + +/** + * Calculates the adjugate of a mat4 + * + * @param {mat4} out the receiving matrix + * @param {mat4} a the source matrix + * @returns {mat4} out + */ +mat4.adjoint = function(out, a) { + var a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3], + a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7], + a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11], + a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15]; + + out[0] = (a11 * (a22 * a33 - a23 * a32) - a21 * (a12 * a33 - a13 * a32) + a31 * (a12 * a23 - a13 * a22)); + out[1] = -(a01 * (a22 * a33 - a23 * a32) - a21 * (a02 * a33 - a03 * a32) + a31 * (a02 * a23 - a03 * a22)); + out[2] = (a01 * (a12 * a33 - a13 * a32) - a11 * (a02 * a33 - a03 * a32) + a31 * (a02 * a13 - a03 * a12)); + out[3] = -(a01 * (a12 * a23 - a13 * a22) - a11 * (a02 * a23 - a03 * a22) + a21 * (a02 * a13 - a03 * a12)); + out[4] = -(a10 * (a22 * a33 - a23 * a32) - a20 * (a12 * a33 - a13 * a32) + a30 * (a12 * a23 - a13 * a22)); + out[5] = (a00 * (a22 * a33 - a23 * a32) - a20 * (a02 * a33 - a03 * a32) + a30 * (a02 * a23 - a03 * a22)); + out[6] = -(a00 * (a12 * a33 - a13 * a32) - a10 * (a02 * a33 - a03 * a32) + a30 * (a02 * a13 - a03 * a12)); + out[7] = (a00 * (a12 * a23 - a13 * a22) - a10 * (a02 * a23 - a03 * a22) + a20 * (a02 * a13 - a03 * a12)); + out[8] = (a10 * (a21 * a33 - a23 * a31) - a20 * (a11 * a33 - a13 * a31) + a30 * (a11 * a23 - a13 * a21)); + out[9] = -(a00 * (a21 * a33 - a23 * a31) - a20 * (a01 * a33 - a03 * a31) + a30 * (a01 * a23 - a03 * a21)); + out[10] = (a00 * (a11 * a33 - a13 * a31) - a10 * (a01 * a33 - a03 * a31) + a30 * (a01 * a13 - a03 * a11)); + out[11] = -(a00 * (a11 * a23 - a13 * a21) - a10 * (a01 * a23 - a03 * a21) + a20 * (a01 * a13 - a03 * a11)); + out[12] = -(a10 * (a21 * a32 - a22 * a31) - a20 * (a11 * a32 - a12 * a31) + a30 * (a11 * a22 - a12 * a21)); + out[13] = (a00 * (a21 * a32 - a22 * a31) - a20 * (a01 * a32 - a02 * a31) + a30 * (a01 * a22 - a02 * a21)); + out[14] = -(a00 * (a11 * a32 - a12 * a31) - a10 * (a01 * a32 - a02 * a31) + a30 * (a01 * a12 - a02 * a11)); + out[15] = (a00 * (a11 * a22 - a12 * a21) - a10 * (a01 * a22 - a02 * a21) + a20 * (a01 * a12 - a02 * a11)); + return out; +}; + +/** + * Calculates the determinant of a mat4 + * + * @param {mat4} a the source matrix + * @returns {Number} determinant of a + */ +mat4.determinant = function (a) { + var a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3], + a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7], + a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11], + a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15], + + b00 = a00 * a11 - a01 * a10, + b01 = a00 * a12 - a02 * a10, + b02 = a00 * a13 - a03 * a10, + b03 = a01 * a12 - a02 * a11, + b04 = a01 * a13 - a03 * a11, + b05 = a02 * a13 - a03 * a12, + b06 = a20 * a31 - a21 * a30, + b07 = a20 * a32 - a22 * a30, + b08 = a20 * a33 - a23 * a30, + b09 = a21 * a32 - a22 * a31, + b10 = a21 * a33 - a23 * a31, + b11 = a22 * a33 - a23 * a32; + + // Calculate the determinant + return b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06; +}; + +/** + * Multiplies two mat4's + * + * @param {mat4} out the receiving matrix + * @param {mat4} a the first operand + * @param {mat4} b the second operand + * @returns {mat4} out + */ +mat4.multiply = function (out, a, b) { + var a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3], + a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7], + a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11], + a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15]; + + // Cache only the current line of the second matrix + var b0 = b[0], b1 = b[1], b2 = b[2], b3 = b[3]; + out[0] = b0*a00 + b1*a10 + b2*a20 + b3*a30; + out[1] = b0*a01 + b1*a11 + b2*a21 + b3*a31; + out[2] = b0*a02 + b1*a12 + b2*a22 + b3*a32; + out[3] = b0*a03 + b1*a13 + b2*a23 + b3*a33; + + b0 = b[4]; b1 = b[5]; b2 = b[6]; b3 = b[7]; + out[4] = b0*a00 + b1*a10 + b2*a20 + b3*a30; + out[5] = b0*a01 + b1*a11 + b2*a21 + b3*a31; + out[6] = b0*a02 + b1*a12 + b2*a22 + b3*a32; + out[7] = b0*a03 + b1*a13 + b2*a23 + b3*a33; + + b0 = b[8]; b1 = b[9]; b2 = b[10]; b3 = b[11]; + out[8] = b0*a00 + b1*a10 + b2*a20 + b3*a30; + out[9] = b0*a01 + b1*a11 + b2*a21 + b3*a31; + out[10] = b0*a02 + b1*a12 + b2*a22 + b3*a32; + out[11] = b0*a03 + b1*a13 + b2*a23 + b3*a33; + + b0 = b[12]; b1 = b[13]; b2 = b[14]; b3 = b[15]; + out[12] = b0*a00 + b1*a10 + b2*a20 + b3*a30; + out[13] = b0*a01 + b1*a11 + b2*a21 + b3*a31; + out[14] = b0*a02 + b1*a12 + b2*a22 + b3*a32; + out[15] = b0*a03 + b1*a13 + b2*a23 + b3*a33; + return out; +}; + +/** + * Multiplies two affine mat4's + * Add by https://github.com/pissang + * @param {mat4} out the receiving matrix + * @param {mat4} a the first operand + * @param {mat4} b the second operand + * @returns {mat4} out + */ +mat4.multiplyAffine = function (out, a, b) { + var a00 = a[0], a01 = a[1], a02 = a[2], + a10 = a[4], a11 = a[5], a12 = a[6], + a20 = a[8], a21 = a[9], a22 = a[10], + a30 = a[12], a31 = a[13], a32 = a[14]; + + // Cache only the current line of the second matrix + var b0 = b[0], b1 = b[1], b2 = b[2]; + out[0] = b0*a00 + b1*a10 + b2*a20; + out[1] = b0*a01 + b1*a11 + b2*a21; + out[2] = b0*a02 + b1*a12 + b2*a22; + // out[3] = 0; + + b0 = b[4]; b1 = b[5]; b2 = b[6]; + out[4] = b0*a00 + b1*a10 + b2*a20; + out[5] = b0*a01 + b1*a11 + b2*a21; + out[6] = b0*a02 + b1*a12 + b2*a22; + // out[7] = 0; + + b0 = b[8]; b1 = b[9]; b2 = b[10]; + out[8] = b0*a00 + b1*a10 + b2*a20; + out[9] = b0*a01 + b1*a11 + b2*a21; + out[10] = b0*a02 + b1*a12 + b2*a22; + // out[11] = 0; + + b0 = b[12]; b1 = b[13]; b2 = b[14]; + out[12] = b0*a00 + b1*a10 + b2*a20 + a30; + out[13] = b0*a01 + b1*a11 + b2*a21 + a31; + out[14] = b0*a02 + b1*a12 + b2*a22 + a32; + // out[15] = 1; + return out; +}; + +/** + * Alias for {@link mat4.multiply} + * @function + */ +mat4.mul = mat4.multiply; + +/** + * Alias for {@link mat4.multiplyAffine} + * @function + */ +mat4.mulAffine = mat4.multiplyAffine; +/** + * Translate a mat4 by the given vector + * + * @param {mat4} out the receiving matrix + * @param {mat4} a the matrix to translate + * @param {vec3} v vector to translate by + * @returns {mat4} out + */ +mat4.translate = function (out, a, v) { + var x = v[0], y = v[1], z = v[2], + a00, a01, a02, a03, + a10, a11, a12, a13, + a20, a21, a22, a23; + + if (a === out) { + out[12] = a[0] * x + a[4] * y + a[8] * z + a[12]; + out[13] = a[1] * x + a[5] * y + a[9] * z + a[13]; + out[14] = a[2] * x + a[6] * y + a[10] * z + a[14]; + out[15] = a[3] * x + a[7] * y + a[11] * z + a[15]; + } else { + a00 = a[0]; a01 = a[1]; a02 = a[2]; a03 = a[3]; + a10 = a[4]; a11 = a[5]; a12 = a[6]; a13 = a[7]; + a20 = a[8]; a21 = a[9]; a22 = a[10]; a23 = a[11]; + + out[0] = a00; out[1] = a01; out[2] = a02; out[3] = a03; + out[4] = a10; out[5] = a11; out[6] = a12; out[7] = a13; + out[8] = a20; out[9] = a21; out[10] = a22; out[11] = a23; + + out[12] = a00 * x + a10 * y + a20 * z + a[12]; + out[13] = a01 * x + a11 * y + a21 * z + a[13]; + out[14] = a02 * x + a12 * y + a22 * z + a[14]; + out[15] = a03 * x + a13 * y + a23 * z + a[15]; + } + + return out; +}; + +/** + * Scales the mat4 by the dimensions in the given vec3 + * + * @param {mat4} out the receiving matrix + * @param {mat4} a the matrix to scale + * @param {vec3} v the vec3 to scale the matrix by + * @returns {mat4} out + **/ +mat4.scale = function(out, a, v) { + var x = v[0], y = v[1], z = v[2]; + + out[0] = a[0] * x; + out[1] = a[1] * x; + out[2] = a[2] * x; + out[3] = a[3] * x; + out[4] = a[4] * y; + out[5] = a[5] * y; + out[6] = a[6] * y; + out[7] = a[7] * y; + out[8] = a[8] * z; + out[9] = a[9] * z; + out[10] = a[10] * z; + out[11] = a[11] * z; + out[12] = a[12]; + out[13] = a[13]; + out[14] = a[14]; + out[15] = a[15]; + return out; +}; + +/** + * Rotates a mat4 by the given angle + * + * @param {mat4} out the receiving matrix + * @param {mat4} a the matrix to rotate + * @param {Number} rad the angle to rotate the matrix by + * @param {vec3} axis the axis to rotate around + * @returns {mat4} out + */ +mat4.rotate = function (out, a, rad, axis) { + var x = axis[0], y = axis[1], z = axis[2], + len = Math.sqrt(x * x + y * y + z * z), + s, c, t, + a00, a01, a02, a03, + a10, a11, a12, a13, + a20, a21, a22, a23, + b00, b01, b02, + b10, b11, b12, + b20, b21, b22; + + if (Math.abs(len) < __WEBPACK_IMPORTED_MODULE_0__common__["b" /* GLMAT_EPSILON */]) { return null; } + + len = 1 / len; + x *= len; + y *= len; + z *= len; + + s = Math.sin(rad); + c = Math.cos(rad); + t = 1 - c; + + a00 = a[0]; a01 = a[1]; a02 = a[2]; a03 = a[3]; + a10 = a[4]; a11 = a[5]; a12 = a[6]; a13 = a[7]; + a20 = a[8]; a21 = a[9]; a22 = a[10]; a23 = a[11]; + + // Construct the elements of the rotation matrix + b00 = x * x * t + c; b01 = y * x * t + z * s; b02 = z * x * t - y * s; + b10 = x * y * t - z * s; b11 = y * y * t + c; b12 = z * y * t + x * s; + b20 = x * z * t + y * s; b21 = y * z * t - x * s; b22 = z * z * t + c; + + // Perform rotation-specific matrix multiplication + out[0] = a00 * b00 + a10 * b01 + a20 * b02; + out[1] = a01 * b00 + a11 * b01 + a21 * b02; + out[2] = a02 * b00 + a12 * b01 + a22 * b02; + out[3] = a03 * b00 + a13 * b01 + a23 * b02; + out[4] = a00 * b10 + a10 * b11 + a20 * b12; + out[5] = a01 * b10 + a11 * b11 + a21 * b12; + out[6] = a02 * b10 + a12 * b11 + a22 * b12; + out[7] = a03 * b10 + a13 * b11 + a23 * b12; + out[8] = a00 * b20 + a10 * b21 + a20 * b22; + out[9] = a01 * b20 + a11 * b21 + a21 * b22; + out[10] = a02 * b20 + a12 * b21 + a22 * b22; + out[11] = a03 * b20 + a13 * b21 + a23 * b22; + + if (a !== out) { // If the source and destination differ, copy the unchanged last row + out[12] = a[12]; + out[13] = a[13]; + out[14] = a[14]; + out[15] = a[15]; + } + return out; +}; + +/** + * Rotates a matrix by the given angle around the X axis + * + * @param {mat4} out the receiving matrix + * @param {mat4} a the matrix to rotate + * @param {Number} rad the angle to rotate the matrix by + * @returns {mat4} out + */ +mat4.rotateX = function (out, a, rad) { + var s = Math.sin(rad), + c = Math.cos(rad), + a10 = a[4], + a11 = a[5], + a12 = a[6], + a13 = a[7], + a20 = a[8], + a21 = a[9], + a22 = a[10], + a23 = a[11]; + + if (a !== out) { // If the source and destination differ, copy the unchanged rows + out[0] = a[0]; + out[1] = a[1]; + out[2] = a[2]; + out[3] = a[3]; + out[12] = a[12]; + out[13] = a[13]; + out[14] = a[14]; + out[15] = a[15]; + } + + // Perform axis-specific matrix multiplication + out[4] = a10 * c + a20 * s; + out[5] = a11 * c + a21 * s; + out[6] = a12 * c + a22 * s; + out[7] = a13 * c + a23 * s; + out[8] = a20 * c - a10 * s; + out[9] = a21 * c - a11 * s; + out[10] = a22 * c - a12 * s; + out[11] = a23 * c - a13 * s; + return out; +}; + +/** + * Rotates a matrix by the given angle around the Y axis + * + * @param {mat4} out the receiving matrix + * @param {mat4} a the matrix to rotate + * @param {Number} rad the angle to rotate the matrix by + * @returns {mat4} out + */ +mat4.rotateY = function (out, a, rad) { + var s = Math.sin(rad), + c = Math.cos(rad), + a00 = a[0], + a01 = a[1], + a02 = a[2], + a03 = a[3], + a20 = a[8], + a21 = a[9], + a22 = a[10], + a23 = a[11]; + + if (a !== out) { // If the source and destination differ, copy the unchanged rows + out[4] = a[4]; + out[5] = a[5]; + out[6] = a[6]; + out[7] = a[7]; + out[12] = a[12]; + out[13] = a[13]; + out[14] = a[14]; + out[15] = a[15]; + } + + // Perform axis-specific matrix multiplication + out[0] = a00 * c - a20 * s; + out[1] = a01 * c - a21 * s; + out[2] = a02 * c - a22 * s; + out[3] = a03 * c - a23 * s; + out[8] = a00 * s + a20 * c; + out[9] = a01 * s + a21 * c; + out[10] = a02 * s + a22 * c; + out[11] = a03 * s + a23 * c; + return out; +}; + +/** + * Rotates a matrix by the given angle around the Z axis + * + * @param {mat4} out the receiving matrix + * @param {mat4} a the matrix to rotate + * @param {Number} rad the angle to rotate the matrix by + * @returns {mat4} out + */ +mat4.rotateZ = function (out, a, rad) { + var s = Math.sin(rad), + c = Math.cos(rad), + a00 = a[0], + a01 = a[1], + a02 = a[2], + a03 = a[3], + a10 = a[4], + a11 = a[5], + a12 = a[6], + a13 = a[7]; + + if (a !== out) { // If the source and destination differ, copy the unchanged last row + out[8] = a[8]; + out[9] = a[9]; + out[10] = a[10]; + out[11] = a[11]; + out[12] = a[12]; + out[13] = a[13]; + out[14] = a[14]; + out[15] = a[15]; + } + + // Perform axis-specific matrix multiplication + out[0] = a00 * c + a10 * s; + out[1] = a01 * c + a11 * s; + out[2] = a02 * c + a12 * s; + out[3] = a03 * c + a13 * s; + out[4] = a10 * c - a00 * s; + out[5] = a11 * c - a01 * s; + out[6] = a12 * c - a02 * s; + out[7] = a13 * c - a03 * s; + return out; +}; + +/** + * Creates a matrix from a quaternion rotation and vector translation + * This is equivalent to (but much faster than): + * + * mat4.identity(dest); + * mat4.translate(dest, vec); + * var quatMat = mat4.create(); + * quat4.toMat4(quat, quatMat); + * mat4.multiply(dest, quatMat); + * + * @param {mat4} out mat4 receiving operation result + * @param {quat4} q Rotation quaternion + * @param {vec3} v Translation vector + * @returns {mat4} out + */ +mat4.fromRotationTranslation = function (out, q, v) { + // Quaternion math + var x = q[0], y = q[1], z = q[2], w = q[3], + x2 = x + x, + y2 = y + y, + z2 = z + z, + + xx = x * x2, + xy = x * y2, + xz = x * z2, + yy = y * y2, + yz = y * z2, + zz = z * z2, + wx = w * x2, + wy = w * y2, + wz = w * z2; + + out[0] = 1 - (yy + zz); + out[1] = xy + wz; + out[2] = xz - wy; + out[3] = 0; + out[4] = xy - wz; + out[5] = 1 - (xx + zz); + out[6] = yz + wx; + out[7] = 0; + out[8] = xz + wy; + out[9] = yz - wx; + out[10] = 1 - (xx + yy); + out[11] = 0; + out[12] = v[0]; + out[13] = v[1]; + out[14] = v[2]; + out[15] = 1; + + return out; +}; + +mat4.fromQuat = function (out, q) { + var x = q[0], y = q[1], z = q[2], w = q[3], + x2 = x + x, + y2 = y + y, + z2 = z + z, + + xx = x * x2, + yx = y * x2, + yy = y * y2, + zx = z * x2, + zy = z * y2, + zz = z * z2, + wx = w * x2, + wy = w * y2, + wz = w * z2; + + out[0] = 1 - yy - zz; + out[1] = yx + wz; + out[2] = zx - wy; + out[3] = 0; + + out[4] = yx - wz; + out[5] = 1 - xx - zz; + out[6] = zy + wx; + out[7] = 0; + + out[8] = zx + wy; + out[9] = zy - wx; + out[10] = 1 - xx - yy; + out[11] = 0; + + out[12] = 0; + out[13] = 0; + out[14] = 0; + out[15] = 1; + + return out; +}; + +/** + * Generates a frustum matrix with the given bounds + * + * @param {mat4} out mat4 frustum matrix will be written into + * @param {Number} left Left bound of the frustum + * @param {Number} right Right bound of the frustum + * @param {Number} bottom Bottom bound of the frustum + * @param {Number} top Top bound of the frustum + * @param {Number} near Near bound of the frustum + * @param {Number} far Far bound of the frustum + * @returns {mat4} out + */ +mat4.frustum = function (out, left, right, bottom, top, near, far) { + var rl = 1 / (right - left), + tb = 1 / (top - bottom), + nf = 1 / (near - far); + out[0] = (near * 2) * rl; + out[1] = 0; + out[2] = 0; + out[3] = 0; + out[4] = 0; + out[5] = (near * 2) * tb; + out[6] = 0; + out[7] = 0; + out[8] = (right + left) * rl; + out[9] = (top + bottom) * tb; + out[10] = (far + near) * nf; + out[11] = -1; + out[12] = 0; + out[13] = 0; + out[14] = (far * near * 2) * nf; + out[15] = 0; + return out; +}; + +/** + * Generates a perspective projection matrix with the given bounds + * + * @param {mat4} out mat4 frustum matrix will be written into + * @param {number} fovy Vertical field of view in radians + * @param {number} aspect Aspect ratio. typically viewport width/height + * @param {number} near Near bound of the frustum + * @param {number} far Far bound of the frustum + * @returns {mat4} out + */ +mat4.perspective = function (out, fovy, aspect, near, far) { + var f = 1.0 / Math.tan(fovy / 2), + nf = 1 / (near - far); + out[0] = f / aspect; + out[1] = 0; + out[2] = 0; + out[3] = 0; + out[4] = 0; + out[5] = f; + out[6] = 0; + out[7] = 0; + out[8] = 0; + out[9] = 0; + out[10] = (far + near) * nf; + out[11] = -1; + out[12] = 0; + out[13] = 0; + out[14] = (2 * far * near) * nf; + out[15] = 0; + return out; +}; + +/** + * Generates a orthogonal projection matrix with the given bounds + * + * @param {mat4} out mat4 frustum matrix will be written into + * @param {number} left Left bound of the frustum + * @param {number} right Right bound of the frustum + * @param {number} bottom Bottom bound of the frustum + * @param {number} top Top bound of the frustum + * @param {number} near Near bound of the frustum + * @param {number} far Far bound of the frustum + * @returns {mat4} out + */ +mat4.ortho = function (out, left, right, bottom, top, near, far) { + var lr = 1 / (left - right), + bt = 1 / (bottom - top), + nf = 1 / (near - far); + out[0] = -2 * lr; + out[1] = 0; + out[2] = 0; + out[3] = 0; + out[4] = 0; + out[5] = -2 * bt; + out[6] = 0; + out[7] = 0; + out[8] = 0; + out[9] = 0; + out[10] = 2 * nf; + out[11] = 0; + out[12] = (left + right) * lr; + out[13] = (top + bottom) * bt; + out[14] = (far + near) * nf; + out[15] = 1; + return out; +}; + +/** + * Generates a look-at matrix with the given eye position, focal point, and up axis + * + * @param {mat4} out mat4 frustum matrix will be written into + * @param {vec3} eye Position of the viewer + * @param {vec3} center Point the viewer is looking at + * @param {vec3} up vec3 pointing up + * @returns {mat4} out + */ +mat4.lookAt = function (out, eye, center, up) { + var x0, x1, x2, y0, y1, y2, z0, z1, z2, len, + eyex = eye[0], + eyey = eye[1], + eyez = eye[2], + upx = up[0], + upy = up[1], + upz = up[2], + centerx = center[0], + centery = center[1], + centerz = center[2]; + + if (Math.abs(eyex - centerx) < __WEBPACK_IMPORTED_MODULE_0__common__["b" /* GLMAT_EPSILON */] && + Math.abs(eyey - centery) < __WEBPACK_IMPORTED_MODULE_0__common__["b" /* GLMAT_EPSILON */] && + Math.abs(eyez - centerz) < __WEBPACK_IMPORTED_MODULE_0__common__["b" /* GLMAT_EPSILON */]) { + return mat4.identity(out); + } + + z0 = eyex - centerx; + z1 = eyey - centery; + z2 = eyez - centerz; + + len = 1 / Math.sqrt(z0 * z0 + z1 * z1 + z2 * z2); + z0 *= len; + z1 *= len; + z2 *= len; + + x0 = upy * z2 - upz * z1; + x1 = upz * z0 - upx * z2; + x2 = upx * z1 - upy * z0; + len = Math.sqrt(x0 * x0 + x1 * x1 + x2 * x2); + if (!len) { + x0 = 0; + x1 = 0; + x2 = 0; + } else { + len = 1 / len; + x0 *= len; + x1 *= len; + x2 *= len; + } + + y0 = z1 * x2 - z2 * x1; + y1 = z2 * x0 - z0 * x2; + y2 = z0 * x1 - z1 * x0; + + len = Math.sqrt(y0 * y0 + y1 * y1 + y2 * y2); + if (!len) { + y0 = 0; + y1 = 0; + y2 = 0; + } else { + len = 1 / len; + y0 *= len; + y1 *= len; + y2 *= len; + } + + out[0] = x0; + out[1] = y0; + out[2] = z0; + out[3] = 0; + out[4] = x1; + out[5] = y1; + out[6] = z1; + out[7] = 0; + out[8] = x2; + out[9] = y2; + out[10] = z2; + out[11] = 0; + out[12] = -(x0 * eyex + x1 * eyey + x2 * eyez); + out[13] = -(y0 * eyex + y1 * eyey + y2 * eyez); + out[14] = -(z0 * eyex + z1 * eyey + z2 * eyez); + out[15] = 1; + + return out; +}; + +/** + * Returns Frobenius norm of a mat4 + * + * @param {mat4} a the matrix to calculate Frobenius norm of + * @returns {Number} Frobenius norm + */ +mat4.frob = function (a) { + return(Math.sqrt(Math.pow(a[0], 2) + Math.pow(a[1], 2) + Math.pow(a[2], 2) + Math.pow(a[3], 2) + Math.pow(a[4], 2) + Math.pow(a[5], 2) + Math.pow(a[6], 2) + Math.pow(a[7], 2) + Math.pow(a[8], 2) + Math.pow(a[9], 2) + Math.pow(a[10], 2) + Math.pow(a[11], 2) + Math.pow(a[12], 2) + Math.pow(a[13], 2) + Math.pow(a[14], 2) + Math.pow(a[15], 2) )) +}; + +/* harmony default export */ __webpack_exports__["a"] = (mat4); + +/***/ }), +/* 22 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_claygl_src_Scene__ = __webpack_require__(36); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2_claygl_src_prePass_ShadowMap__ = __webpack_require__(174); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3_claygl_src_camera_Perspective__ = __webpack_require__(41); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4_claygl_src_camera_Orthographic__ = __webpack_require__(37); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_5_claygl_src_math_Matrix4__ = __webpack_require__(9); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_6_claygl_src_math_Vector3__ = __webpack_require__(3); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_7_claygl_src_math_Vector2__ = __webpack_require__(26); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_8_claygl_src_core_mixin_notifier__ = __webpack_require__(53); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_9__effect_EffectCompositor__ = __webpack_require__(176); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_10__effect_TemporalSuperSampling__ = __webpack_require__(200); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_11__effect_halton__ = __webpack_require__(49); +/* + * @module echarts-gl/core/ViewGL + * @author Yi Shen(http://github.com/pissang) + */ + + + + + + + + + + + + + + + + + +/** + * @constructor + * @alias module:echarts-gl/core/ViewGL + * @param {string} [projection='perspective'] + */ +function ViewGL(projection) { + + projection = projection || 'perspective'; + + /** + * @type {module:echarts-gl/core/LayerGL} + */ + this.layer = null; + /** + * @type {clay.Scene} + */ + this.scene = new __WEBPACK_IMPORTED_MODULE_1_claygl_src_Scene__["a" /* default */](); + + /** + * @type {clay.Node} + */ + this.rootNode = this.scene; + + this.viewport = { + x: 0, y: 0, width: 0, height: 0 + }; + + this.setProjection(projection); + + this._compositor = new __WEBPACK_IMPORTED_MODULE_9__effect_EffectCompositor__["a" /* default */](); + + this._temporalSS = new __WEBPACK_IMPORTED_MODULE_10__effect_TemporalSuperSampling__["a" /* default */](); + + this._shadowMapPass = new __WEBPACK_IMPORTED_MODULE_2_claygl_src_prePass_ShadowMap__["a" /* default */](); + + var pcfKernels = []; + var off = 0; + for (var i = 0; i < 30; i++) { + var pcfKernel = []; + for (var k = 0; k < 6; k++) { + pcfKernel.push(Object(__WEBPACK_IMPORTED_MODULE_11__effect_halton__["a" /* default */])(off, 2) * 4.0 - 2.0); + pcfKernel.push(Object(__WEBPACK_IMPORTED_MODULE_11__effect_halton__["a" /* default */])(off, 3) * 4.0 - 2.0); + off++; + } + pcfKernels.push(pcfKernel); + } + this._pcfKernels = pcfKernels; + + this.scene.on('beforerender', function (renderer, scene, camera) { + if (this.needsTemporalSS()) { + this._temporalSS.jitterProjection(renderer, camera); + } + }, this); +} + +/** + * Set camera type of group + * @param {string} cameraType 'perspective' | 'orthographic' + */ +ViewGL.prototype.setProjection = function (projection) { + var oldCamera = this.camera; + oldCamera && oldCamera.update(); + if (projection === 'perspective') { + if (!(this.camera instanceof __WEBPACK_IMPORTED_MODULE_3_claygl_src_camera_Perspective__["a" /* default */])) { + this.camera = new __WEBPACK_IMPORTED_MODULE_3_claygl_src_camera_Perspective__["a" /* default */](); + if (oldCamera) { + this.camera.setLocalTransform(oldCamera.localTransform); + } + } + } + else { + if (!(this.camera instanceof __WEBPACK_IMPORTED_MODULE_4_claygl_src_camera_Orthographic__["a" /* default */])) { + this.camera = new __WEBPACK_IMPORTED_MODULE_4_claygl_src_camera_Orthographic__["a" /* default */](); + if (oldCamera) { + this.camera.setLocalTransform(oldCamera.localTransform); + } + } + } + // PENDING + this.camera.near = 0.1; + this.camera.far = 2000; +}; + +/** + * Set viewport of group + * @param {number} x Viewport left bottom x + * @param {number} y Viewport left bottom y + * @param {number} width Viewport height + * @param {number} height Viewport height + * @param {number} [dpr=1] + */ +ViewGL.prototype.setViewport = function (x, y, width, height, dpr) { + if (this.camera instanceof __WEBPACK_IMPORTED_MODULE_3_claygl_src_camera_Perspective__["a" /* default */]) { + this.camera.aspect = width / height; + } + dpr = dpr || 1; + + this.viewport.x = x; + this.viewport.y = y; + this.viewport.width = width; + this.viewport.height = height; + this.viewport.devicePixelRatio = dpr; + + // Source and output of compositor use high dpr texture. + // But the intermediate texture of bloom, dof effects use fixed 1.0 dpr + this._compositor.resize(width * dpr, height * dpr); + this._temporalSS.resize(width * dpr, height * dpr); +}; + +/** + * If contain screen point x, y + * @param {number} x offsetX + * @param {number} y offsetY + * @return {boolean} + */ +ViewGL.prototype.containPoint = function (x, y) { + var viewport = this.viewport; + var height = this.layer.renderer.getHeight(); + // Flip y; + y = height - y; + return x >= viewport.x && y >= viewport.y + && x <= viewport.x + viewport.width && y <= viewport.y + viewport.height; +}; + +/** + * Cast a ray + * @param {number} x offsetX + * @param {number} y offsetY + * @param {clay.math.Ray} out + * @return {clay.math.Ray} + */ +var ndc = new __WEBPACK_IMPORTED_MODULE_7_claygl_src_math_Vector2__["a" /* default */](); +ViewGL.prototype.castRay = function (x, y, out) { + var renderer = this.layer.renderer; + + var oldViewport = renderer.viewport; + renderer.viewport = this.viewport; + renderer.screenToNDC(x, y, ndc); + this.camera.castRay(ndc, out); + renderer.viewport = oldViewport; + + return out; +}; + +/** + * Prepare and update scene before render + */ +ViewGL.prototype.prepareRender = function () { + this.scene.update(); + this.camera.update(); + this.scene.updateLights(); + var renderList = this.scene.updateRenderList(this.camera); + + this._needsSortProgressively = false; + // If has any transparent mesh needs sort triangles progressively. + for (var i = 0; i < renderList.transparent.length; i++) { + var renderable = renderList.transparent[i]; + var geometry = renderable.geometry; + if (geometry.needsSortVerticesProgressively && geometry.needsSortVerticesProgressively()) { + this._needsSortProgressively = true; + } + if (geometry.needsSortTrianglesProgressively && geometry.needsSortTrianglesProgressively()) { + this._needsSortProgressively = true; + } + } + + this._frame = 0; + this._temporalSS.resetFrame(); + + // var lights = this.scene.getLights(); + // for (var i = 0; i < lights.length; i++) { + // if (lights[i].cubemap) { + // if (this._compositor && this._compositor.isSSREnabled()) { + // lights[i].invisible = true; + // } + // else { + // lights[i].invisible = false; + // } + // } + // } +}; + +ViewGL.prototype.render = function (renderer, accumulating) { + this._doRender(renderer, accumulating, this._frame); + this._frame++; +}; + +ViewGL.prototype.needsAccumulate = function () { + return this.needsTemporalSS() || this._needsSortProgressively; +}; + +ViewGL.prototype.needsTemporalSS = function () { + var enableTemporalSS = this._enableTemporalSS; + if (enableTemporalSS === 'auto') { + enableTemporalSS = this._enablePostEffect; + } + return enableTemporalSS; +}; + +ViewGL.prototype.hasDOF = function () { + return this._enableDOF; +}; + +ViewGL.prototype.isAccumulateFinished = function () { + return this.needsTemporalSS() ? this._temporalSS.isFinished() + : (this._frame > 30); +}; + +ViewGL.prototype._doRender = function (renderer, accumulating, accumFrame) { + + var scene = this.scene; + var camera = this.camera; + + accumFrame = accumFrame || 0; + + this._updateTransparent(renderer, scene, camera, accumFrame); + + if (!accumulating) { + this._shadowMapPass.kernelPCF = this._pcfKernels[0]; + // Not render shadowmap pass in accumulating frame. + this._shadowMapPass.render(renderer, scene, camera, true); + } + + this._updateShadowPCFKernel(accumFrame); + + // Shadowmap will set clear color. + var bgColor = renderer.clearColor; + renderer.gl.clearColor(bgColor[0], bgColor[1], bgColor[2], bgColor[3]); + + if (this._enablePostEffect) { + // normal render also needs to be jittered when have edge pass. + if (this.needsTemporalSS()) { + this._temporalSS.jitterProjection(renderer, camera); + } + this._compositor.updateNormal(renderer, scene, camera, this._temporalSS.getFrame()); + } + + // Always update SSAO to make sure have correct ssaoMap status + this._updateSSAO(renderer, scene, camera, this._temporalSS.getFrame()); + + if (this._enablePostEffect) { + + var frameBuffer = this._compositor.getSourceFrameBuffer(); + frameBuffer.bind(renderer); + renderer.gl.clear(renderer.gl.DEPTH_BUFFER_BIT | renderer.gl.COLOR_BUFFER_BIT); + renderer.render(scene, camera, true, true); + frameBuffer.unbind(renderer); + + if (this.needsTemporalSS() && accumulating) { + this._compositor.composite(renderer, scene, camera, this._temporalSS.getSourceFrameBuffer(), this._temporalSS.getFrame()); + renderer.setViewport(this.viewport); + this._temporalSS.render(renderer); + } + else { + renderer.setViewport(this.viewport); + this._compositor.composite(renderer, scene, camera, null, 0); + } + } + else { + if (this.needsTemporalSS() && accumulating) { + var frameBuffer = this._temporalSS.getSourceFrameBuffer(); + frameBuffer.bind(renderer); + renderer.saveClear(); + renderer.clearBit = renderer.gl.DEPTH_BUFFER_BIT | renderer.gl.COLOR_BUFFER_BIT; + renderer.render(scene, camera, true, true); + renderer.restoreClear(); + frameBuffer.unbind(renderer); + + renderer.setViewport(this.viewport); + this._temporalSS.render(renderer); + } + else { + renderer.setViewport(this.viewport); + renderer.render(scene, camera, true, true); + } + } + + // this._shadowMapPass.renderDebug(renderer); + // this._compositor._normalPass.renderDebug(renderer); +}; + +ViewGL.prototype._updateTransparent = function (renderer, scene, camera, frame) { + + var v3 = new __WEBPACK_IMPORTED_MODULE_6_claygl_src_math_Vector3__["a" /* default */](); + var invWorldTransform = new __WEBPACK_IMPORTED_MODULE_5_claygl_src_math_Matrix4__["a" /* default */](); + var cameraWorldPosition = camera.getWorldPosition(); + var transparentList = scene.getRenderList(camera).transparent; + + // Sort transparent object. + for (var i = 0; i < transparentList.length; i++) { + var renderable = transparentList[i]; + var geometry = renderable.geometry; + __WEBPACK_IMPORTED_MODULE_5_claygl_src_math_Matrix4__["a" /* default */].invert(invWorldTransform, renderable.worldTransform); + __WEBPACK_IMPORTED_MODULE_6_claygl_src_math_Vector3__["a" /* default */].transformMat4(v3, cameraWorldPosition, invWorldTransform); + if (geometry.needsSortTriangles && geometry.needsSortTriangles()) { + geometry.doSortTriangles(v3, frame); + } + if (geometry.needsSortVertices && geometry.needsSortVertices()) { + geometry.doSortVertices(v3, frame); + } + } +}; + +ViewGL.prototype._updateSSAO = function (renderer, scene, camera) { + var ifEnableSSAO = this._enableSSAO && this._enablePostEffect; + if (ifEnableSSAO) { + this._compositor.updateSSAO(renderer, scene, camera, this._temporalSS.getFrame()); + } + var renderList = scene.getRenderList(camera); + + for (var i = 0; i < renderList.opaque.length; i++) { + var renderable = renderList.opaque[i]; + // PENDING + if (renderable.renderNormal) { + renderable.material[ifEnableSSAO ? 'enableTexture' : 'disableTexture']('ssaoMap'); + } + if (ifEnableSSAO) { + renderable.material.set('ssaoMap', this._compositor.getSSAOTexture()); + } + } +}; + +ViewGL.prototype._updateShadowPCFKernel = function (frame) { + var pcfKernel = this._pcfKernels[frame % this._pcfKernels.length]; + var renderList = this.scene.getRenderList(this.camera); + var opaqueList = renderList.opaque; + for (var i = 0; i < opaqueList.length; i++) { + if (opaqueList[i].receiveShadow) { + opaqueList[i].material.set('pcfKernel', pcfKernel); + opaqueList[i].material.define('fragment', 'PCF_KERNEL_SIZE', pcfKernel.length / 2); + } + } +}; + +ViewGL.prototype.dispose = function (renderer) { + this._compositor.dispose(renderer.gl); + this._temporalSS.dispose(renderer.gl); + this._shadowMapPass.dispose(renderer); +}; +/** + * @param {module:echarts/Model} Post effect model + */ +ViewGL.prototype.setPostEffect = function (postEffectModel, api) { + var compositor = this._compositor; + this._enablePostEffect = postEffectModel.get('enable'); + var bloomModel = postEffectModel.getModel('bloom'); + var edgeModel = postEffectModel.getModel('edge'); + var dofModel = postEffectModel.getModel('DOF', postEffectModel.getModel('depthOfField')); + var ssaoModel = postEffectModel.getModel('SSAO', postEffectModel.getModel('screenSpaceAmbientOcclusion')); + var ssrModel = postEffectModel.getModel('SSR', postEffectModel.getModel('screenSpaceReflection')); + var fxaaModel = postEffectModel.getModel('FXAA'); + var colorCorrModel = postEffectModel.getModel('colorCorrection'); + bloomModel.get('enable') ? compositor.enableBloom() : compositor.disableBloom(); + dofModel.get('enable') ? compositor.enableDOF() : compositor.disableDOF(); + ssrModel.get('enable') ? compositor.enableSSR() : compositor.disableSSR(); + colorCorrModel.get('enable') ? compositor.enableColorCorrection() : compositor.disableColorCorrection(); + edgeModel.get('enable') ? compositor.enableEdge() : compositor.disableEdge(); + fxaaModel.get('enable') ? compositor.enableFXAA() : compositor.disableFXAA(); + + this._enableDOF = dofModel.get('enable'); + this._enableSSAO = ssaoModel.get('enable'); + + this._enableSSAO ? compositor.enableSSAO() : compositor.disableSSAO(); + + compositor.setBloomIntensity(bloomModel.get('intensity')); + compositor.setEdgeColor(edgeModel.get('color')); + compositor.setColorLookupTexture(colorCorrModel.get('lookupTexture'), api); + compositor.setExposure(colorCorrModel.get('exposure')); + + ['radius', 'quality', 'intensity'].forEach(function (name) { + compositor.setSSAOParameter(name, ssaoModel.get(name)); + }); + ['quality', 'maxRoughness', 'physical'].forEach(function (name) { + compositor.setSSRParameter(name, ssrModel.get(name)); + }); + ['quality', 'focalDistance', 'focalRange', 'blurRadius', 'fstop'].forEach(function (name) { + compositor.setDOFParameter(name, dofModel.get(name)); + }); + ['brightness', 'contrast', 'saturation'].forEach(function (name) { + compositor.setColorCorrection(name, colorCorrModel.get(name)); + }); + +}; + +ViewGL.prototype.setDOFFocusOnPoint = function (depth) { + if (this._enablePostEffect) { + + if (depth > this.camera.far || depth < this.camera.near) { + return; + } + + this._compositor.setDOFParameter('focalDistance', depth); + return true; + } +}; + +ViewGL.prototype.setTemporalSuperSampling = function (temporalSuperSamplingModel) { + this._enableTemporalSS = temporalSuperSamplingModel.get('enable'); +}; + +ViewGL.prototype.isLinearSpace = function () { + return this._enablePostEffect; +}; + +ViewGL.prototype.setRootNode = function (rootNode) { + if (this.rootNode === rootNode) { + return; + } + var children = this.rootNode.children(); + for (var i = 0; i < children.length; i++) { + rootNode.add(children[i]); + } + if (rootNode !== this.scene) { + this.scene.add(rootNode); + } + + this.rootNode = rootNode; +}; +// Proxies +ViewGL.prototype.add = function (node3D) { + this.rootNode.add(node3D); +}; +ViewGL.prototype.remove = function (node3D) { + this.rootNode.remove(node3D); +}; +ViewGL.prototype.removeAll = function (node3D) { + this.rootNode.removeAll(node3D); +}; + +__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.util.extend(ViewGL.prototype, __WEBPACK_IMPORTED_MODULE_8_claygl_src_core_mixin_notifier__["a" /* default */]); + +/* harmony default export */ __webpack_exports__["a"] = (ViewGL); + +/***/ }), +/* 23 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +var guid = 0; + +var ArrayProto = Array.prototype; +var nativeForEach = ArrayProto.forEach; + +/** + * Util functions + * @namespace clay.core.util + */ +var util = { + + /** + * Generate GUID + * @return {number} + * @memberOf clay.core.util + */ + genGUID: function () { + return ++guid; + }, + /** + * Relative path to absolute path + * @param {string} path + * @param {string} basePath + * @return {string} + * @memberOf clay.core.util + */ + relative2absolute: function (path, basePath) { + if (!basePath || path.match(/^\//)) { + return path; + } + var pathParts = path.split('/'); + var basePathParts = basePath.split('/'); + + var item = pathParts[0]; + while(item === '.' || item === '..') { + if (item === '..') { + basePathParts.pop(); + } + pathParts.shift(); + item = pathParts[0]; + } + return basePathParts.join('/') + '/' + pathParts.join('/'); + }, + + /** + * Extend target with source + * @param {Object} target + * @param {Object} source + * @return {Object} + * @memberOf clay.core.util + */ + extend: function (target, source) { + if (source) { + for (var name in source) { + if (source.hasOwnProperty(name)) { + target[name] = source[name]; + } + } + } + return target; + }, + + /** + * Extend properties to target if not exist. + * @param {Object} target + * @param {Object} source + * @return {Object} + * @memberOf clay.core.util + */ + defaults: function (target, source) { + if (source) { + for (var propName in source) { + if (target[propName] === undefined) { + target[propName] = source[propName]; + } + } + } + return target; + }, + /** + * Extend properties with a given property list to avoid for..in.. iteration. + * @param {Object} target + * @param {Object} source + * @param {Array.} propList + * @return {Object} + * @memberOf clay.core.util + */ + extendWithPropList: function (target, source, propList) { + if (source) { + for (var i = 0; i < propList.length; i++) { + var propName = propList[i]; + target[propName] = source[propName]; + } + } + return target; + }, + /** + * Extend properties to target if not exist. With a given property list avoid for..in.. iteration. + * @param {Object} target + * @param {Object} source + * @param {Array.} propList + * @return {Object} + * @memberOf clay.core.util + */ + defaultsWithPropList: function (target, source, propList) { + if (source) { + for (var i = 0; i < propList.length; i++) { + var propName = propList[i]; + if (target[propName] == null) { + target[propName] = source[propName]; + } + } + } + return target; + }, + /** + * @param {Object|Array} obj + * @param {Function} iterator + * @param {Object} [context] + * @memberOf clay.core.util + */ + each: function (obj, iterator, context) { + if (!(obj && iterator)) { + return; + } + if (obj.forEach && obj.forEach === nativeForEach) { + obj.forEach(iterator, context); + } + else if (obj.length === + obj.length) { + for (var i = 0, len = obj.length; i < len; i++) { + iterator.call(context, obj[i], i, obj); + } + } + else { + for (var key in obj) { + if (obj.hasOwnProperty(key)) { + iterator.call(context, obj[key], key, obj); + } + } + } + }, + + /** + * Is object + * @param {} obj + * @return {boolean} + * @memberOf clay.core.util + */ + isObject: function (obj) { + return obj === Object(obj); + }, + + /** + * Is array ? + * @param {} obj + * @return {boolean} + * @memberOf clay.core.util + */ + isArray: function (obj) { + return Array.isArray(obj); + }, + + /** + * Is array like, which have a length property + * @param {} obj + * @return {boolean} + * @memberOf clay.core.util + */ + isArrayLike: function (obj) { + if (!obj) { + return false; + } + else { + return obj.length === + obj.length; + } + }, + + /** + * @param {} obj + * @return {} + * @memberOf clay.core.util + */ + clone: function (obj) { + if (!util.isObject(obj)) { + return obj; + } + else if (util.isArray(obj)) { + return obj.slice(); + } + else if (util.isArrayLike(obj)) { // is typed array + var ret = new obj.constructor(obj.length); + for (var i = 0; i < obj.length; i++) { + ret[i] = obj[i]; + } + return ret; + } + else { + return util.extend({}, obj); + } + } +}; + +/* harmony default export */ __webpack_exports__["a"] = (util); + + +/***/ }), +/* 24 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__Node__ = __webpack_require__(35); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__Shader__ = __webpack_require__(8); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__shader_source_header_light__ = __webpack_require__(119); + + + + +__WEBPACK_IMPORTED_MODULE_1__Shader__["a" /* default */]['import'](__WEBPACK_IMPORTED_MODULE_2__shader_source_header_light__["a" /* default */]); + +/** + * @constructor clay.Light + * @extends clay.Node + */ +var Light = __WEBPACK_IMPORTED_MODULE_0__Node__["a" /* default */].extend(function(){ + return /** @lends clay.Light# */ { + /** + * Light RGB color + * @type {number[]} + */ + color: [1, 1, 1], + + /** + * Light intensity + * @type {number} + */ + intensity: 1.0, + + // Config for shadow map + /** + * If light cast shadow + * @type {boolean} + */ + castShadow: true, + + /** + * Shadow map size + * @type {number} + */ + shadowResolution: 512, + + /** + * Light group, shader with same `lightGroup` will be affected + * + * Only useful in forward rendering + * @type {number} + */ + group: 0 + }; +}, +/** @lends clay.Light.prototype. */ +{ + /** + * Light type + * @type {string} + * @memberOf clay.Light# + */ + type: '', + + /** + * @return {clay.Light} + * @memberOf clay.Light.prototype + */ + clone: function() { + var light = __WEBPACK_IMPORTED_MODULE_0__Node__["a" /* default */].prototype.clone.call(this); + light.color = Array.prototype.slice.call(this.color); + light.intensity = this.intensity; + light.castShadow = this.castShadow; + light.shadowResolution = this.shadowResolution; + + return light; + } +}); + +/* harmony default export */ __webpack_exports__["a"] = (Light); + + +/***/ }), +/* 25 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_claygl_src_Geometry__ = __webpack_require__(15); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_echarts_lib_echarts__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_echarts_lib_echarts___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_echarts_lib_echarts__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__dynamicConvertMixin__ = __webpack_require__(38); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3_claygl_src_dep_glmatrix__ = __webpack_require__(6); +/** + * Lines geometry + * Use screen space projected lines lineWidth > MAX_LINE_WIDTH + * https://mattdesl.svbtle.com/drawing-lines-is-hard + * @module echarts-gl/util/geometry/LinesGeometry + * @author Yi Shen(http://github.com/pissang) + */ + + + + + +var vec3 = __WEBPACK_IMPORTED_MODULE_3_claygl_src_dep_glmatrix__["a" /* default */].vec3; + +// var CURVE_RECURSION_LIMIT = 8; +// var CURVE_COLLINEAR_EPSILON = 40; + +var sampleLinePoints = [[0, 0], [1, 1]]; +/** + * @constructor + * @alias module:echarts-gl/util/geometry/LinesGeometry + * @extends clay.Geometry + */ + +var LinesGeometry = __WEBPACK_IMPORTED_MODULE_0_claygl_src_Geometry__["a" /* default */].extend(function () { + return { + + segmentScale: 1, + + dynamic: true, + /** + * Need to use mesh to expand lines if lineWidth > MAX_LINE_WIDTH + */ + useNativeLine: true, + + attributes: { + position: new __WEBPACK_IMPORTED_MODULE_0_claygl_src_Geometry__["a" /* default */].Attribute('position', 'float', 3, 'POSITION'), + positionPrev: new __WEBPACK_IMPORTED_MODULE_0_claygl_src_Geometry__["a" /* default */].Attribute('positionPrev', 'float', 3), + positionNext: new __WEBPACK_IMPORTED_MODULE_0_claygl_src_Geometry__["a" /* default */].Attribute('positionNext', 'float', 3), + prevPositionPrev: new __WEBPACK_IMPORTED_MODULE_0_claygl_src_Geometry__["a" /* default */].Attribute('prevPositionPrev', 'float', 3), + prevPosition: new __WEBPACK_IMPORTED_MODULE_0_claygl_src_Geometry__["a" /* default */].Attribute('prevPosition', 'float', 3), + prevPositionNext: new __WEBPACK_IMPORTED_MODULE_0_claygl_src_Geometry__["a" /* default */].Attribute('prevPositionNext', 'float', 3), + offset: new __WEBPACK_IMPORTED_MODULE_0_claygl_src_Geometry__["a" /* default */].Attribute('offset', 'float', 1), + color: new __WEBPACK_IMPORTED_MODULE_0_claygl_src_Geometry__["a" /* default */].Attribute('color', 'float', 4, 'COLOR') + } + }; +}, +/** @lends module: echarts-gl/util/geometry/LinesGeometry.prototype */ +{ + + /** + * Reset offset + */ + resetOffset: function () { + this._vertexOffset = 0; + this._triangleOffset = 0; + + this._itemVertexOffsets = []; + }, + + /** + * @param {number} nVertex + */ + setVertexCount: function (nVertex) { + var attributes = this.attributes; + if (this.vertexCount !== nVertex) { + attributes.position.init(nVertex); + attributes.color.init(nVertex); + + if (!this.useNativeLine) { + attributes.positionPrev.init(nVertex); + attributes.positionNext.init(nVertex); + attributes.offset.init(nVertex); + } + + if (nVertex > 0xffff) { + if (this.indices instanceof Uint16Array) { + this.indices = new Uint32Array(this.indices); + } + } + else { + if (this.indices instanceof Uint32Array) { + this.indices = new Uint16Array(this.indices); + } + } + } + }, + + /** + * @param {number} nTriangle + */ + setTriangleCount: function (nTriangle) { + if (this.triangleCount !== nTriangle) { + if (nTriangle === 0) { + this.indices = null; + } + else { + this.indices = this.vertexCount > 0xffff ? new Uint32Array(nTriangle * 3) : new Uint16Array(nTriangle * 3); + } + } + }, + + _getCubicCurveApproxStep: function (p0, p1, p2, p3) { + var len = vec3.dist(p0, p1) + vec3.dist(p2, p1) + vec3.dist(p3, p2); + var step = 1 / (len + 1) * this.segmentScale; + return step; + }, + + /** + * Get vertex count of cubic curve + * @param {Array.} p0 + * @param {Array.} p1 + * @param {Array.} p2 + * @param {Array.} p3 + * @return number + */ + getCubicCurveVertexCount: function (p0, p1, p2, p3) { + var step = this._getCubicCurveApproxStep(p0, p1, p2, p3); + var segCount = Math.ceil(1 / step); + if (!this.useNativeLine) { + return segCount * 2 + 2; + } + else { + return segCount * 2; + } + }, + + /** + * Get face count of cubic curve + * @param {Array.} p0 + * @param {Array.} p1 + * @param {Array.} p2 + * @param {Array.} p3 + * @return number + */ + getCubicCurveTriangleCount: function (p0, p1, p2, p3) { + var step = this._getCubicCurveApproxStep(p0, p1, p2, p3); + var segCount = Math.ceil(1 / step); + if (!this.useNativeLine) { + return segCount * 2; + } + else { + return 0; + } + }, + + /** + * Get vertex count of line + * @return {number} + */ + getLineVertexCount: function () { + return this.getPolylineVertexCount(sampleLinePoints); + }, + + /** + * Get face count of line + * @return {number} + */ + getLineTriangleCount: function () { + return this.getPolylineTriangleCount(sampleLinePoints); + }, + + /** + * Get how many vertices will polyline take. + * @type {number|Array} points Can be a 1d/2d list of points, or a number of points amount. + * @return {number} + */ + getPolylineVertexCount: function (points) { + var pointsLen; + if (typeof points === 'number') { + pointsLen = points; + } + else { + var is2DArray = typeof points[0] !== 'number'; + pointsLen = is2DArray ? points.length : (points.length / 3); + } + return !this.useNativeLine ? ((pointsLen - 1) * 2 + 2) : (pointsLen - 1) * 2; + }, + + /** + * Get how many triangles will polyline take. + * @type {number|Array} points Can be a 1d/2d list of points, or a number of points amount. + * @return {number} + */ + getPolylineTriangleCount: function (points) { + var pointsLen; + if (typeof points === 'number') { + pointsLen = points; + } + else { + var is2DArray = typeof points[0] !== 'number'; + pointsLen = is2DArray ? points.length : (points.length / 3); + } + return !this.useNativeLine ? Math.max(pointsLen - 1, 0) * 2 : 0; + }, + + /** + * Add a cubic curve + * @param {Array.} p0 + * @param {Array.} p1 + * @param {Array.} p2 + * @param {Array.} p3 + * @param {Array.} color + * @param {number} [lineWidth=1] + */ + addCubicCurve: function (p0, p1, p2, p3, color, lineWidth) { + if (lineWidth == null) { + lineWidth = 1; + } + // incremental interpolation + // http://antigrain.com/research/bezier_interpolation/index.html#PAGE_BEZIER_INTERPOLATION + var x0 = p0[0], y0 = p0[1], z0 = p0[2]; + var x1 = p1[0], y1 = p1[1], z1 = p1[2]; + var x2 = p2[0], y2 = p2[1], z2 = p2[2]; + var x3 = p3[0], y3 = p3[1], z3 = p3[2]; + + var step = this._getCubicCurveApproxStep(p0, p1, p2, p3); + + var step2 = step * step; + var step3 = step2 * step; + + var pre1 = 3.0 * step; + var pre2 = 3.0 * step2; + var pre4 = 6.0 * step2; + var pre5 = 6.0 * step3; + + var tmp1x = x0 - x1 * 2.0 + x2; + var tmp1y = y0 - y1 * 2.0 + y2; + var tmp1z = z0 - z1 * 2.0 + z2; + + var tmp2x = (x1 - x2) * 3.0 - x0 + x3; + var tmp2y = (y1 - y2) * 3.0 - y0 + y3; + var tmp2z = (z1 - z2) * 3.0 - z0 + z3; + + var fx = x0; + var fy = y0; + var fz = z0; + + var dfx = (x1 - x0) * pre1 + tmp1x * pre2 + tmp2x * step3; + var dfy = (y1 - y0) * pre1 + tmp1y * pre2 + tmp2y * step3; + var dfz = (z1 - z0) * pre1 + tmp1z * pre2 + tmp2z * step3; + + var ddfx = tmp1x * pre4 + tmp2x * pre5; + var ddfy = tmp1y * pre4 + tmp2y * pre5; + var ddfz = tmp1z * pre4 + tmp2z * pre5; + + var dddfx = tmp2x * pre5; + var dddfy = tmp2y * pre5; + var dddfz = tmp2z * pre5; + + var t = 0; + + var k = 0; + var segCount = Math.ceil(1 / step); + + var points = new Float32Array((segCount + 1) * 3); + var points = []; + var offset = 0; + for (var k = 0; k < segCount + 1; k++) { + points[offset++] = fx; + points[offset++] = fy; + points[offset++] = fz; + + fx += dfx; fy += dfy; fz += dfz; + dfx += ddfx; dfy += ddfy; dfz += ddfz; + ddfx += dddfx; ddfy += dddfy; ddfz += dddfz; + t += step; + + if (t > 1) { + fx = dfx > 0 ? Math.min(fx, x3) : Math.max(fx, x3); + fy = dfy > 0 ? Math.min(fy, y3) : Math.max(fy, y3); + fz = dfz > 0 ? Math.min(fz, z3) : Math.max(fz, z3); + } + } + + return this.addPolyline(points, color, lineWidth); + }, + + /** + * Add a straight line + * @param {Array.} p0 + * @param {Array.} p1 + * @param {Array.} color + * @param {number} [lineWidth=1] + */ + addLine: function (p0, p1, color, lineWidth) { + return this.addPolyline([p0, p1], color, lineWidth); + }, + + /** + * Add a straight line + * @param {Array. | Array.} points + * @param {Array. | Array.} color + * @param {number} [lineWidth=1] + * @param {number} [startOffset=0] + * @param {number} [pointsCount] Default to be amount of points in the first argument + */ + addPolyline: function (points, color, lineWidth, startOffset, pointsCount) { + if (!points.length) { + return; + } + var is2DArray = typeof points[0] !== 'number'; + if (pointsCount == null) { + pointsCount = is2DArray ? points.length : points.length / 3; + } + if (pointsCount < 2) { + return; + } + if (startOffset == null) { + startOffset = 0; + } + if (lineWidth == null) { + lineWidth = 1; + } + + this._itemVertexOffsets.push(this._vertexOffset); + + var is2DArray = typeof points[0] !== 'number'; + var notSharingColor = is2DArray + ? typeof color[0] !== 'number' + : color.length / 4 === pointsCount; + + var positionAttr = this.attributes.position; + var positionPrevAttr = this.attributes.positionPrev; + var positionNextAttr = this.attributes.positionNext; + var colorAttr = this.attributes.color; + var offsetAttr = this.attributes.offset; + var indices = this.indices; + + var vertexOffset = this._vertexOffset; + var point; + var pointColor; + + lineWidth = Math.max(lineWidth, 0.01); + + for (var k = startOffset; k < pointsCount; k++) { + if (is2DArray) { + point = points[k]; + if (notSharingColor) { + pointColor = color[k]; + } + else { + pointColor = color; + } + } + else { + var k3 = k * 3; + point = point || []; + point[0] = points[k3]; + point[1] = points[k3 + 1]; + point[2] = points[k3 + 2]; + + if (notSharingColor) { + var k4 = k * 4; + pointColor = pointColor || []; + pointColor[0] = color[k4]; + pointColor[1] = color[k4 + 1]; + pointColor[2] = color[k4 + 2]; + pointColor[3] = color[k4 + 3]; + } + else { + pointColor = color; + } + } + if (!this.useNativeLine) { + if (k < pointsCount - 1) { + // Set to next two points + positionPrevAttr.set(vertexOffset + 2, point); + positionPrevAttr.set(vertexOffset + 3, point); + } + if (k > 0) { + // Set to previous two points + positionNextAttr.set(vertexOffset - 2, point); + positionNextAttr.set(vertexOffset - 1, point); + } + + positionAttr.set(vertexOffset, point); + positionAttr.set(vertexOffset + 1, point); + + colorAttr.set(vertexOffset, pointColor); + colorAttr.set(vertexOffset + 1, pointColor); + + offsetAttr.set(vertexOffset, lineWidth / 2); + offsetAttr.set(vertexOffset + 1, -lineWidth / 2); + + vertexOffset += 2; + } + else { + if (k > 1) { + positionAttr.copy(vertexOffset, vertexOffset - 1); + colorAttr.copy(vertexOffset, vertexOffset - 1); + vertexOffset++; + } + } + + if (!this.useNativeLine) { + if (k > 0) { + var idx3 = this._triangleOffset * 3; + var indices = this.indices; + // 0-----2 + // 1-----3 + // 0->1->2, 1->3->2 + indices[idx3] = vertexOffset - 4; + indices[idx3 + 1] = vertexOffset - 3; + indices[idx3 + 2] = vertexOffset - 2; + + indices[idx3 + 3] = vertexOffset - 3; + indices[idx3 + 4] = vertexOffset - 1; + indices[idx3 + 5] = vertexOffset - 2; + + this._triangleOffset += 2; + } + } + else { + colorAttr.set(vertexOffset, pointColor); + positionAttr.set(vertexOffset, point); + vertexOffset++; + } + } + if (!this.useNativeLine) { + var start = this._vertexOffset; + var end = this._vertexOffset + pointsCount * 2; + positionPrevAttr.copy(start, start + 2); + positionPrevAttr.copy(start + 1, start + 3); + positionNextAttr.copy(end - 1, end - 3); + positionNextAttr.copy(end - 2, end - 4); + } + + this._vertexOffset = vertexOffset; + + return this._vertexOffset; + }, + + /** + * Set color of single line. + */ + setItemColor: function (idx, color) { + var startOffset = this._itemVertexOffsets[idx]; + var endOffset = idx < this._itemVertexOffsets.length - 1 ? this._itemVertexOffsets[idx + 1] : this._vertexOffset; + + for (var i = startOffset; i < endOffset; i++) { + this.attributes.color.set(i, color); + } + this.dirty('color'); + }, + + /** + * @return {number} + */ + currentTriangleOffset: function () { + return this._triangleOffset; + }, + + /** + * @return {number} + */ + currentVertexOffset: function () { + return this._vertexOffset; + } +}); + +__WEBPACK_IMPORTED_MODULE_1_echarts_lib_echarts___default.a.util.defaults(LinesGeometry.prototype, __WEBPACK_IMPORTED_MODULE_2__dynamicConvertMixin__["a" /* default */]); + +/* harmony default export */ __webpack_exports__["a"] = (LinesGeometry); + +/***/ }), +/* 26 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec2__ = __webpack_require__(70); + + +/** + * @constructor + * @alias clay.Vector2 + * @param {number} x + * @param {number} y + */ +var Vector2 = function(x, y) { + + x = x || 0; + y = y || 0; + + /** + * Storage of Vector2, read and write of x, y will change the values in array + * All methods also operate on the array instead of x, y components + * @name array + * @type {Float32Array} + * @memberOf clay.Vector2# + */ + this.array = __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec2__["a" /* default */].fromValues(x, y); + + /** + * Dirty flag is used by the Node to determine + * if the matrix is updated to latest + * @name _dirty + * @type {boolean} + * @memberOf clay.Vector2# + */ + this._dirty = true; +}; + +Vector2.prototype = { + + constructor: Vector2, + + /** + * Add b to self + * @param {clay.Vector2} b + * @return {clay.Vector2} + */ + add: function(b) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec2__["a" /* default */].add(this.array, this.array, b.array); + this._dirty = true; + return this; + }, + + /** + * Set x and y components + * @param {number} x + * @param {number} y + * @return {clay.Vector2} + */ + set: function(x, y) { + this.array[0] = x; + this.array[1] = y; + this._dirty = true; + return this; + }, + + /** + * Set x and y components from array + * @param {Float32Array|number[]} arr + * @return {clay.Vector2} + */ + setArray: function(arr) { + this.array[0] = arr[0]; + this.array[1] = arr[1]; + + this._dirty = true; + return this; + }, + + /** + * Clone a new Vector2 + * @return {clay.Vector2} + */ + clone: function() { + return new Vector2(this.x, this.y); + }, + + /** + * Copy x, y from b + * @param {clay.Vector2} b + * @return {clay.Vector2} + */ + copy: function(b) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec2__["a" /* default */].copy(this.array, b.array); + this._dirty = true; + return this; + }, + + /** + * Cross product of self and b, written to a Vector3 out + * @param {clay.Vector3} out + * @param {clay.Vector2} b + * @return {clay.Vector2} + */ + cross: function(out, b) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec2__["a" /* default */].cross(out.array, this.array, b.array); + out._dirty = true; + return this; + }, + + /** + * Alias for distance + * @param {clay.Vector2} b + * @return {number} + */ + dist: function(b) { + return __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec2__["a" /* default */].dist(this.array, b.array); + }, + + /** + * Distance between self and b + * @param {clay.Vector2} b + * @return {number} + */ + distance: function(b) { + return __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec2__["a" /* default */].distance(this.array, b.array); + }, + + /** + * Alias for divide + * @param {clay.Vector2} b + * @return {clay.Vector2} + */ + div: function(b) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec2__["a" /* default */].div(this.array, this.array, b.array); + this._dirty = true; + return this; + }, + + /** + * Divide self by b + * @param {clay.Vector2} b + * @return {clay.Vector2} + */ + divide: function(b) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec2__["a" /* default */].divide(this.array, this.array, b.array); + this._dirty = true; + return this; + }, + + /** + * Dot product of self and b + * @param {clay.Vector2} b + * @return {number} + */ + dot: function(b) { + return __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec2__["a" /* default */].dot(this.array, b.array); + }, + + /** + * Alias of length + * @return {number} + */ + len: function() { + return __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec2__["a" /* default */].len(this.array); + }, + + /** + * Calculate the length + * @return {number} + */ + length: function() { + return __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec2__["a" /* default */].length(this.array); + }, + + /** + * Linear interpolation between a and b + * @param {clay.Vector2} a + * @param {clay.Vector2} b + * @param {number} t + * @return {clay.Vector2} + */ + lerp: function(a, b, t) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec2__["a" /* default */].lerp(this.array, a.array, b.array, t); + this._dirty = true; + return this; + }, + + /** + * Minimum of self and b + * @param {clay.Vector2} b + * @return {clay.Vector2} + */ + min: function(b) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec2__["a" /* default */].min(this.array, this.array, b.array); + this._dirty = true; + return this; + }, + + /** + * Maximum of self and b + * @param {clay.Vector2} b + * @return {clay.Vector2} + */ + max: function(b) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec2__["a" /* default */].max(this.array, this.array, b.array); + this._dirty = true; + return this; + }, + + /** + * Alias for multiply + * @param {clay.Vector2} b + * @return {clay.Vector2} + */ + mul: function(b) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec2__["a" /* default */].mul(this.array, this.array, b.array); + this._dirty = true; + return this; + }, + + /** + * Mutiply self and b + * @param {clay.Vector2} b + * @return {clay.Vector2} + */ + multiply: function(b) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec2__["a" /* default */].multiply(this.array, this.array, b.array); + this._dirty = true; + return this; + }, + + /** + * Negate self + * @return {clay.Vector2} + */ + negate: function() { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec2__["a" /* default */].negate(this.array, this.array); + this._dirty = true; + return this; + }, + + /** + * Normalize self + * @return {clay.Vector2} + */ + normalize: function() { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec2__["a" /* default */].normalize(this.array, this.array); + this._dirty = true; + return this; + }, + + /** + * Generate random x, y components with a given scale + * @param {number} scale + * @return {clay.Vector2} + */ + random: function(scale) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec2__["a" /* default */].random(this.array, scale); + this._dirty = true; + return this; + }, + + /** + * Scale self + * @param {number} scale + * @return {clay.Vector2} + */ + scale: function(s) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec2__["a" /* default */].scale(this.array, this.array, s); + this._dirty = true; + return this; + }, + + /** + * Scale b and add to self + * @param {clay.Vector2} b + * @param {number} scale + * @return {clay.Vector2} + */ + scaleAndAdd: function(b, s) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec2__["a" /* default */].scaleAndAdd(this.array, this.array, b.array, s); + this._dirty = true; + return this; + }, + + /** + * Alias for squaredDistance + * @param {clay.Vector2} b + * @return {number} + */ + sqrDist: function(b) { + return __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec2__["a" /* default */].sqrDist(this.array, b.array); + }, + + /** + * Squared distance between self and b + * @param {clay.Vector2} b + * @return {number} + */ + squaredDistance: function(b) { + return __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec2__["a" /* default */].squaredDistance(this.array, b.array); + }, + + /** + * Alias for squaredLength + * @return {number} + */ + sqrLen: function() { + return __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec2__["a" /* default */].sqrLen(this.array); + }, + + /** + * Squared length of self + * @return {number} + */ + squaredLength: function() { + return __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec2__["a" /* default */].squaredLength(this.array); + }, + + /** + * Alias for subtract + * @param {clay.Vector2} b + * @return {clay.Vector2} + */ + sub: function(b) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec2__["a" /* default */].sub(this.array, this.array, b.array); + this._dirty = true; + return this; + }, + + /** + * Subtract b from self + * @param {clay.Vector2} b + * @return {clay.Vector2} + */ + subtract: function(b) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec2__["a" /* default */].subtract(this.array, this.array, b.array); + this._dirty = true; + return this; + }, + + /** + * Transform self with a Matrix2 m + * @param {clay.Matrix2} m + * @return {clay.Vector2} + */ + transformMat2: function(m) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec2__["a" /* default */].transformMat2(this.array, this.array, m.array); + this._dirty = true; + return this; + }, + + /** + * Transform self with a Matrix2d m + * @param {clay.Matrix2d} m + * @return {clay.Vector2} + */ + transformMat2d: function(m) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec2__["a" /* default */].transformMat2d(this.array, this.array, m.array); + this._dirty = true; + return this; + }, + + /** + * Transform self with a Matrix3 m + * @param {clay.Matrix3} m + * @return {clay.Vector2} + */ + transformMat3: function(m) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec2__["a" /* default */].transformMat3(this.array, this.array, m.array); + this._dirty = true; + return this; + }, + + /** + * Transform self with a Matrix4 m + * @param {clay.Matrix4} m + * @return {clay.Vector2} + */ + transformMat4: function(m) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec2__["a" /* default */].transformMat4(this.array, this.array, m.array); + this._dirty = true; + return this; + }, + + toString: function() { + return '[' + Array.prototype.join.call(this.array, ',') + ']'; + }, + + toArray: function () { + return Array.prototype.slice.call(this.array); + } +}; + +// Getter and Setter +if (Object.defineProperty) { + + var proto = Vector2.prototype; + /** + * @name x + * @type {number} + * @memberOf clay.Vector2 + * @instance + */ + Object.defineProperty(proto, 'x', { + get: function () { + return this.array[0]; + }, + set: function (value) { + this.array[0] = value; + this._dirty = true; + } + }); + + /** + * @name y + * @type {number} + * @memberOf clay.Vector2 + * @instance + */ + Object.defineProperty(proto, 'y', { + get: function () { + return this.array[1]; + }, + set: function (value) { + this.array[1] = value; + this._dirty = true; + } + }); +} + +// Supply methods that are not in place + +/** + * @param {clay.Vector2} out + * @param {clay.Vector2} a + * @param {clay.Vector2} b + * @return {clay.Vector2} + */ +Vector2.add = function(out, a, b) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec2__["a" /* default */].add(out.array, a.array, b.array); + out._dirty = true; + return out; +}; + +/** + * @param {clay.Vector2} out + * @param {number} x + * @param {number} y + * @return {clay.Vector2} + */ +Vector2.set = function(out, x, y) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec2__["a" /* default */].set(out.array, x, y); + out._dirty = true; + return out; +}; + +/** + * @param {clay.Vector2} out + * @param {clay.Vector2} b + * @return {clay.Vector2} + */ +Vector2.copy = function(out, b) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec2__["a" /* default */].copy(out.array, b.array); + out._dirty = true; + return out; +}; + +/** + * @param {clay.Vector3} out + * @param {clay.Vector2} a + * @param {clay.Vector2} b + * @return {clay.Vector2} + */ +Vector2.cross = function(out, a, b) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec2__["a" /* default */].cross(out.array, a.array, b.array); + out._dirty = true; + return out; +}; +/** + * @param {clay.Vector2} a + * @param {clay.Vector2} b + * @return {number} + */ +Vector2.dist = function(a, b) { + return __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec2__["a" /* default */].distance(a.array, b.array); +}; +/** + * @function + * @param {clay.Vector2} a + * @param {clay.Vector2} b + * @return {number} + */ +Vector2.distance = Vector2.dist; +/** + * @param {clay.Vector2} out + * @param {clay.Vector2} a + * @param {clay.Vector2} b + * @return {clay.Vector2} + */ +Vector2.div = function(out, a, b) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec2__["a" /* default */].divide(out.array, a.array, b.array); + out._dirty = true; + return out; +}; +/** + * @function + * @param {clay.Vector2} out + * @param {clay.Vector2} a + * @param {clay.Vector2} b + * @return {clay.Vector2} + */ +Vector2.divide = Vector2.div; +/** + * @param {clay.Vector2} a + * @param {clay.Vector2} b + * @return {number} + */ +Vector2.dot = function(a, b) { + return __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec2__["a" /* default */].dot(a.array, b.array); +}; + +/** + * @param {clay.Vector2} a + * @return {number} + */ +Vector2.len = function(b) { + return __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec2__["a" /* default */].length(b.array); +}; + +// Vector2.length = Vector2.len; + +/** + * @param {clay.Vector2} out + * @param {clay.Vector2} a + * @param {clay.Vector2} b + * @param {number} t + * @return {clay.Vector2} + */ +Vector2.lerp = function(out, a, b, t) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec2__["a" /* default */].lerp(out.array, a.array, b.array, t); + out._dirty = true; + return out; +}; +/** + * @param {clay.Vector2} out + * @param {clay.Vector2} a + * @param {clay.Vector2} b + * @return {clay.Vector2} + */ +Vector2.min = function(out, a, b) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec2__["a" /* default */].min(out.array, a.array, b.array); + out._dirty = true; + return out; +}; + +/** + * @param {clay.Vector2} out + * @param {clay.Vector2} a + * @param {clay.Vector2} b + * @return {clay.Vector2} + */ +Vector2.max = function(out, a, b) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec2__["a" /* default */].max(out.array, a.array, b.array); + out._dirty = true; + return out; +}; +/** + * @param {clay.Vector2} out + * @param {clay.Vector2} a + * @param {clay.Vector2} b + * @return {clay.Vector2} + */ +Vector2.mul = function(out, a, b) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec2__["a" /* default */].multiply(out.array, a.array, b.array); + out._dirty = true; + return out; +}; +/** + * @function + * @param {clay.Vector2} out + * @param {clay.Vector2} a + * @param {clay.Vector2} b + * @return {clay.Vector2} + */ +Vector2.multiply = Vector2.mul; +/** + * @param {clay.Vector2} out + * @param {clay.Vector2} a + * @return {clay.Vector2} + */ +Vector2.negate = function(out, a) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec2__["a" /* default */].negate(out.array, a.array); + out._dirty = true; + return out; +}; +/** + * @param {clay.Vector2} out + * @param {clay.Vector2} a + * @return {clay.Vector2} + */ +Vector2.normalize = function(out, a) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec2__["a" /* default */].normalize(out.array, a.array); + out._dirty = true; + return out; +}; +/** + * @param {clay.Vector2} out + * @param {number} scale + * @return {clay.Vector2} + */ +Vector2.random = function(out, scale) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec2__["a" /* default */].random(out.array, scale); + out._dirty = true; + return out; +}; +/** + * @param {clay.Vector2} out + * @param {clay.Vector2} a + * @param {number} scale + * @return {clay.Vector2} + */ +Vector2.scale = function(out, a, scale) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec2__["a" /* default */].scale(out.array, a.array, scale); + out._dirty = true; + return out; +}; +/** + * @param {clay.Vector2} out + * @param {clay.Vector2} a + * @param {clay.Vector2} b + * @param {number} scale + * @return {clay.Vector2} + */ +Vector2.scaleAndAdd = function(out, a, b, scale) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec2__["a" /* default */].scaleAndAdd(out.array, a.array, b.array, scale); + out._dirty = true; + return out; +}; +/** + * @param {clay.Vector2} a + * @param {clay.Vector2} b + * @return {number} + */ +Vector2.sqrDist = function(a, b) { + return __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec2__["a" /* default */].sqrDist(a.array, b.array); +}; +/** + * @function + * @param {clay.Vector2} a + * @param {clay.Vector2} b + * @return {number} + */ +Vector2.squaredDistance = Vector2.sqrDist; + +/** + * @param {clay.Vector2} a + * @return {number} + */ +Vector2.sqrLen = function(a) { + return __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec2__["a" /* default */].sqrLen(a.array); +}; +/** + * @function + * @param {clay.Vector2} a + * @return {number} + */ +Vector2.squaredLength = Vector2.sqrLen; + +/** + * @param {clay.Vector2} out + * @param {clay.Vector2} a + * @param {clay.Vector2} b + * @return {clay.Vector2} + */ +Vector2.sub = function(out, a, b) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec2__["a" /* default */].subtract(out.array, a.array, b.array); + out._dirty = true; + return out; +}; +/** + * @function + * @param {clay.Vector2} out + * @param {clay.Vector2} a + * @param {clay.Vector2} b + * @return {clay.Vector2} + */ +Vector2.subtract = Vector2.sub; +/** + * @param {clay.Vector2} out + * @param {clay.Vector2} a + * @param {clay.Matrix2} m + * @return {clay.Vector2} + */ +Vector2.transformMat2 = function(out, a, m) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec2__["a" /* default */].transformMat2(out.array, a.array, m.array); + out._dirty = true; + return out; +}; +/** + * @param {clay.Vector2} out + * @param {clay.Vector2} a + * @param {clay.Matrix2d} m + * @return {clay.Vector2} + */ +Vector2.transformMat2d = function(out, a, m) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec2__["a" /* default */].transformMat2d(out.array, a.array, m.array); + out._dirty = true; + return out; +}; +/** + * @param {clay.Vector2} out + * @param {clay.Vector2} a + * @param {Matrix3} m + * @return {clay.Vector2} + */ +Vector2.transformMat3 = function(out, a, m) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec2__["a" /* default */].transformMat3(out.array, a.array, m.array); + out._dirty = true; + return out; +}; +/** + * @param {clay.Vector2} out + * @param {clay.Vector2} a + * @param {clay.Matrix4} m + * @return {clay.Vector2} + */ +Vector2.transformMat4 = function(out, a, m) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec2__["a" /* default */].transformMat4(out.array, a.array, m.array); + out._dirty = true; + return out; +}; + +/* harmony default export */ __webpack_exports__["a"] = (Vector2); + + +/***/ }), +/* 27 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__Texture__ = __webpack_require__(4); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__core_glenum__ = __webpack_require__(11); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__core_util__ = __webpack_require__(23); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__math_util__ = __webpack_require__(73); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4__core_vendor__ = __webpack_require__(14); + + + + + +var isPowerOfTwo = __WEBPACK_IMPORTED_MODULE_3__math_util__["a" /* default */].isPowerOfTwo; + +var targetList = ['px', 'nx', 'py', 'ny', 'pz', 'nz']; + +/** + * @constructor clay.TextureCube + * @extends clay.Texture + * + * @example + * ... + * var mat = new clay.Material({ + * shader: clay.shader.library.get('clay.phong', 'environmentMap') + * }); + * var envMap = new clay.TextureCube(); + * envMap.load({ + * 'px': 'assets/textures/sky/px.jpg', + * 'nx': 'assets/textures/sky/nx.jpg' + * 'py': 'assets/textures/sky/py.jpg' + * 'ny': 'assets/textures/sky/ny.jpg' + * 'pz': 'assets/textures/sky/pz.jpg' + * 'nz': 'assets/textures/sky/nz.jpg' + * }); + * mat.set('environmentMap', envMap); + * ... + * envMap.success(function () { + * // Wait for the sky texture loaded + * animation.on('frame', function (frameTime) { + * renderer.render(scene, camera); + * }); + * }); + */ +var TextureCube = __WEBPACK_IMPORTED_MODULE_0__Texture__["a" /* default */].extend(function () { + return /** @lends clay.TextureCube# */{ + + /** + * @type {boolean} + * @default false + */ + // PENDING cubemap should not flipY in default. + // flipY: false, + + /** + * @type {Object} + * @property {?HTMLImageElement|HTMLCanvasElemnet} px + * @property {?HTMLImageElement|HTMLCanvasElemnet} nx + * @property {?HTMLImageElement|HTMLCanvasElemnet} py + * @property {?HTMLImageElement|HTMLCanvasElemnet} ny + * @property {?HTMLImageElement|HTMLCanvasElemnet} pz + * @property {?HTMLImageElement|HTMLCanvasElemnet} nz + */ + image: { + px: null, + nx: null, + py: null, + ny: null, + pz: null, + nz: null + }, + /** + * Pixels data of each side. Will be ignored if images are set. + * @type {Object} + * @property {?Uint8Array} px + * @property {?Uint8Array} nx + * @property {?Uint8Array} py + * @property {?Uint8Array} ny + * @property {?Uint8Array} pz + * @property {?Uint8Array} nz + */ + pixels: { + px: null, + nx: null, + py: null, + ny: null, + pz: null, + nz: null + }, + + /** + * @type {Array.} + */ + mipmaps: [] + }; +}, { + + textureType: 'textureCube', + + update: function (renderer) { + var _gl = renderer.gl; + _gl.bindTexture(_gl.TEXTURE_CUBE_MAP, this._cache.get('webgl_texture')); + + this.updateCommon(renderer); + + var glFormat = this.format; + var glType = this.type; + + _gl.texParameteri(_gl.TEXTURE_CUBE_MAP, _gl.TEXTURE_WRAP_S, this.getAvailableWrapS()); + _gl.texParameteri(_gl.TEXTURE_CUBE_MAP, _gl.TEXTURE_WRAP_T, this.getAvailableWrapT()); + + _gl.texParameteri(_gl.TEXTURE_CUBE_MAP, _gl.TEXTURE_MAG_FILTER, this.getAvailableMagFilter()); + _gl.texParameteri(_gl.TEXTURE_CUBE_MAP, _gl.TEXTURE_MIN_FILTER, this.getAvailableMinFilter()); + + var anisotropicExt = renderer.getGLExtension('EXT_texture_filter_anisotropic'); + if (anisotropicExt && this.anisotropic > 1) { + _gl.texParameterf(_gl.TEXTURE_CUBE_MAP, anisotropicExt.TEXTURE_MAX_ANISOTROPY_EXT, this.anisotropic); + } + + // Fallback to float type if browser don't have half float extension + if (glType === 36193) { + var halfFloatExt = renderer.getGLExtension('OES_texture_half_float'); + if (!halfFloatExt) { + glType = __WEBPACK_IMPORTED_MODULE_1__core_glenum__["a" /* default */].FLOAT; + } + } + + if (this.mipmaps.length) { + var width = this.width; + var height = this.height; + for (var i = 0; i < this.mipmaps.length; i++) { + var mipmap = this.mipmaps[i]; + this._updateTextureData(_gl, mipmap, i, width, height, glFormat, glType); + width /= 2; + height /= 2; + } + } + else { + this._updateTextureData(_gl, this, 0, this.width, this.height, glFormat, glType); + + if (!this.NPOT && this.useMipmap) { + _gl.generateMipmap(_gl.TEXTURE_CUBE_MAP); + } + } + + _gl.bindTexture(_gl.TEXTURE_CUBE_MAP, null); + }, + + _updateTextureData: function (_gl, data, level, width, height, glFormat, glType) { + for (var i = 0; i < 6; i++) { + var target = targetList[i]; + var img = data.image && data.image[target]; + if (img) { + _gl.texImage2D(_gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, level, glFormat, glFormat, glType, img); + } + else { + _gl.texImage2D(_gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, level, glFormat, width, height, 0, glFormat, glType, data.pixels && data.pixels[target]); + } + } + }, + + /** + * @param {clay.Renderer} renderer + * @memberOf clay.TextureCube.prototype + */ + generateMipmap: function (renderer) { + var _gl = renderer.gl; + if (this.useMipmap && !this.NPOT) { + _gl.bindTexture(_gl.TEXTURE_CUBE_MAP, this._cache.get('webgl_texture')); + _gl.generateMipmap(_gl.TEXTURE_CUBE_MAP); + } + }, + + bind: function (renderer) { + renderer.gl.bindTexture(renderer.gl.TEXTURE_CUBE_MAP, this.getWebGLTexture(renderer)); + }, + + unbind: function (renderer) { + renderer.gl.bindTexture(renderer.gl.TEXTURE_CUBE_MAP, null); + }, + + // Overwrite the isPowerOfTwo method + isPowerOfTwo: function () { + if (this.image.px) { + return isPowerOfTwo(this.image.px.width) + && isPowerOfTwo(this.image.px.height); + } + else { + return isPowerOfTwo(this.width) + && isPowerOfTwo(this.height); + } + }, + + isRenderable: function () { + if (this.image.px) { + return isImageRenderable(this.image.px) + && isImageRenderable(this.image.nx) + && isImageRenderable(this.image.py) + && isImageRenderable(this.image.ny) + && isImageRenderable(this.image.pz) + && isImageRenderable(this.image.nz); + } + else { + return !!(this.width && this.height); + } + }, + + load: function (imageList, crossOrigin) { + var loading = 0; + var self = this; + __WEBPACK_IMPORTED_MODULE_2__core_util__["a" /* default */].each(imageList, function (src, target){ + var image = __WEBPACK_IMPORTED_MODULE_4__core_vendor__["a" /* default */].createImage(); + if (crossOrigin) { + image.crossOrigin = crossOrigin; + } + image.onload = function () { + loading --; + if (loading === 0){ + self.dirty(); + self.trigger('success', self); + } + image.onload = null; + }; + image.onerror = function () { + loading --; + image.onerror = null; + }; + + loading++; + image.src = src; + self.image[target] = image; + }); + + return this; + } +}); + +Object.defineProperty(TextureCube.prototype, 'width', { + get: function () { + if (this.image && this.image.px) { + return this.image.px.width; + } + return this._width; + }, + set: function (value) { + if (this.image && this.image.px) { + console.warn('Texture from image can\'t set width'); + } + else { + if (this._width !== value) { + this.dirty(); + } + this._width = value; + } + } +}); +Object.defineProperty(TextureCube.prototype, 'height', { + get: function () { + if (this.image && this.image.px) { + return this.image.px.height; + } + return this._height; + }, + set: function (value) { + if (this.image && this.image.px) { + console.warn('Texture from image can\'t set height'); + } + else { + if (this._height !== value) { + this.dirty(); + } + this._height = value; + } + } +}); +function isImageRenderable(image) { + return image.nodeName === 'CANVAS' || + image.nodeName === 'VIDEO' || + image.complete; +} + +/* harmony default export */ __webpack_exports__["a"] = (TextureCube); + + +/***/ }), +/* 28 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony default export */ __webpack_exports__["a"] = ({ + defaultOption: { + // Post effect + postEffect: { + enable: false, + + bloom: { + enable: true, + intensity: 0.1 + }, + depthOfField: { + enable: false, + focalRange: 20, + focalDistance: 50, + blurRadius: 10, + fstop: 2.8, + quality: 'medium' + }, + + screenSpaceAmbientOcclusion: { + enable: false, + radius: 2, + // low, medium, high, ultra + quality: 'medium', + intensity: 1 + }, + + screenSpaceReflection: { + enable: false, + quality: 'medium', + maxRoughness: 0.8 + }, + + colorCorrection: { + enable: true, + + exposure: 0, + + brightness: 0, + + contrast: 1, + + saturation: 1, + + lookupTexture: '' + }, + + edge: { + enable: false + }, + + FXAA: { + enable: false + } + }, + + // Temporal super sampling when the picture is still. + temporalSuperSampling: { + // Only enabled when postEffect is enabled + enable: 'auto' + } + } +}); + +/***/ }), +/* 29 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony default export */ __webpack_exports__["a"] = ({ + defaultOption: { + // Light is available when material.shading is not color + light: { + // Main light + main: { + shadow: false, + // low, medium, high, ultra + shadowQuality: 'high', + + color: '#fff', + intensity: 1, + + alpha: 0, + beta: 0 + }, + ambient: { + color: '#fff', + intensity: 0.2 + }, + ambientCubemap: { + // Panorama environment texture, + // Support .hdr and commmon web formats. + texture: null, + // Available when texture is hdr. + exposure: 1, + // Intensity for diffuse term + diffuseIntensity: 0.5, + // Intensity for specular term, only available when shading is realastic + specularIntensity: 0.5 + } + } + } +}); + +/***/ }), +/* 30 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__util_graphicGL__ = __webpack_require__(1); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_claygl_src_plugin_Skybox__ = __webpack_require__(42); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2_echarts_lib_echarts__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2_echarts_lib_echarts___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_2_echarts_lib_echarts__); + + + + +function SceneHelper() { +} + +SceneHelper.prototype = { + constructor: SceneHelper, + + setScene: function (scene) { + this._scene = scene; + + if (this._skybox) { + this._skybox.attachScene(this._scene); + } + }, + + initLight: function (rootNode) { + this._lightRoot = rootNode; + /** + * @type {clay.light.Directional} + */ + this.mainLight = new __WEBPACK_IMPORTED_MODULE_0__util_graphicGL__["a" /* default */].DirectionalLight({ + shadowBias: 0.005 + }); + + /** + * @type {clay.light.Ambient} + */ + this.ambientLight = new __WEBPACK_IMPORTED_MODULE_0__util_graphicGL__["a" /* default */].AmbientLight(); + + rootNode.add(this.mainLight); + rootNode.add(this.ambientLight); + }, + + dispose: function () { + if (this._lightRoot) { + this._lightRoot.remove(this.mainLight); + this._lightRoot.remove(this.ambientLight); + } + }, + + updateLight: function (componentModel) { + + var mainLight = this.mainLight; + var ambientLight = this.ambientLight; + + var lightModel = componentModel.getModel('light'); + var mainLightModel = lightModel.getModel('main'); + var ambientLightModel = lightModel.getModel('ambient'); + + mainLight.intensity = mainLightModel.get('intensity'); + ambientLight.intensity = ambientLightModel.get('intensity'); + mainLight.color = __WEBPACK_IMPORTED_MODULE_0__util_graphicGL__["a" /* default */].parseColor(mainLightModel.get('color')).slice(0, 3); + ambientLight.color = __WEBPACK_IMPORTED_MODULE_0__util_graphicGL__["a" /* default */].parseColor(ambientLightModel.get('color')).slice(0, 3); + + var alpha = mainLightModel.get('alpha') || 0; + var beta = mainLightModel.get('beta') || 0; + mainLight.position.setArray(__WEBPACK_IMPORTED_MODULE_0__util_graphicGL__["a" /* default */].directionFromAlphaBeta(alpha, beta)); + mainLight.lookAt(__WEBPACK_IMPORTED_MODULE_0__util_graphicGL__["a" /* default */].Vector3.ZERO); + + mainLight.castShadow = mainLightModel.get('shadow'); + mainLight.shadowResolution = __WEBPACK_IMPORTED_MODULE_0__util_graphicGL__["a" /* default */].getShadowResolution(mainLightModel.get('shadowQuality')); + }, + + updateAmbientCubemap: function (renderer, componentModel, api) { + var ambientCubemapModel = componentModel.getModel('light.ambientCubemap'); + + var textureUrl = ambientCubemapModel.get('texture'); + if (textureUrl) { + this._cubemapLightsCache = this._cubemapLightsCache || {}; + var lights = this._cubemapLightsCache[textureUrl]; + if (!lights) { + var self = this; + lights = this._cubemapLightsCache[textureUrl] + = __WEBPACK_IMPORTED_MODULE_0__util_graphicGL__["a" /* default */].createAmbientCubemap(ambientCubemapModel.option, renderer, api, function () { + // Use prefitered cubemap + if (self._isSkyboxFromAmbientCubemap) { + self._skybox.setEnvironmentMap(lights.specular.cubemap); + } + + api.getZr().refresh(); + }); + } + this._lightRoot.add(lights.diffuse); + this._lightRoot.add(lights.specular); + + this._currentCubemapLights = lights; + } + else if (this._currentCubemapLights) { + this._lightRoot.remove(this._currentCubemapLights.diffuse); + this._lightRoot.remove(this._currentCubemapLights.specular); + this._currentCubemapLights = null; + } + }, + + updateSkybox: function (renderer, componentModel, api) { + var environmentUrl = componentModel.get('environment'); + + var self = this; + function getSkybox() { + self._skybox = self._skybox || new __WEBPACK_IMPORTED_MODULE_1_claygl_src_plugin_Skybox__["a" /* default */](); + return self._skybox; + } + + var skybox = getSkybox(); + if (environmentUrl && environmentUrl !== 'none') { + if (environmentUrl === 'auto') { + this._isSkyboxFromAmbientCubemap = true; + // Use environment in ambient cubemap + if (this._currentCubemapLights) { + var cubemap = this._currentCubemapLights.specular.cubemap; + skybox.setEnvironmentMap(cubemap); + if (this._scene) { + skybox.attachScene(this._scene); + } + skybox.material.set('lod', 3); + } + else if (this._skybox) { + this._skybox.detachScene(); + } + } + // Is gradient or color string + else if ((typeof environmentUrl === 'object' && environmentUrl.colorStops) + || (typeof environmentUrl === 'string' && __WEBPACK_IMPORTED_MODULE_2_echarts_lib_echarts___default.a.color.parse(environmentUrl)) + ) { + this._isSkyboxFromAmbientCubemap = false; + var texture = new __WEBPACK_IMPORTED_MODULE_0__util_graphicGL__["a" /* default */].Texture2D({ + anisotropic: 8, + flipY: false + }); + skybox.setEnvironmentMap(texture); + var canvas = texture.image = document.createElement('canvas'); + canvas.width = canvas.height = 16; + var ctx = canvas.getContext('2d'); + var rect = new __WEBPACK_IMPORTED_MODULE_2_echarts_lib_echarts___default.a.graphic.Rect({ + shape: { x: 0, y: 0, width: 16, height: 16 }, + style: { fill: environmentUrl } + }); + rect.brush(ctx); + + skybox.attachScene(this._scene); + } + else { + this._isSkyboxFromAmbientCubemap = false; + // Panorama + var texture = __WEBPACK_IMPORTED_MODULE_0__util_graphicGL__["a" /* default */].loadTexture(environmentUrl, api, { + anisotropic: 8, + flipY: false + }); + skybox.setEnvironmentMap(texture); + + skybox.attachScene(this._scene); + } + } + else { + if (this._skybox) { + this._skybox.detachScene(this._scene); + } + this._skybox = null; + } + + var coordSys = componentModel.coordinateSystem; + if (this._skybox) { + if (coordSys && coordSys.viewGL + && environmentUrl !== 'auto' + && !(environmentUrl.match && environmentUrl.match(/.hdr$/)) + ) { + var srgbDefineMethod = coordSys.viewGL.isLinearSpace() ? 'define' : 'undefine'; + this._skybox.material[srgbDefineMethod]('fragment', 'SRGB_DECODE'); + } + else { + this._skybox.material.undefine('fragment', 'SRGB_DECODE'); + } + // var ambientCubemapUrl = environmentUrl === 'auto' + // ? componentModel.get('light.ambientCubemap.texture') + // : environmentUrl; + } + } +}; + +/* harmony default export */ __webpack_exports__["a"] = (SceneHelper); + +/***/ }), +/* 31 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony default export */ __webpack_exports__["a"] = ({ + defaultOption: { + shading: null, + + realisticMaterial: { + textureTiling: 1, + textureOffset: 0, + + detailTexture: null + }, + + lambertMaterial: { + textureTiling: 1, + textureOffset: 0, + + detailTexture: null + }, + + colorMaterial: { + textureTiling: 1, + textureOffset: 0, + + detailTexture: null + }, + + hatchingMaterial: { + textureTiling: 1, + textureOffset: 0, + + paperColor: '#fff' + } + } +}); + +/***/ }), +/* 32 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__); + + +var formatUtil = {}; +formatUtil.getFormattedLabel = function (seriesModel, dataIndex, status, dataType, dimIndex) { + status = status || 'normal'; + var data = seriesModel.getData(dataType); + var itemModel = data.getItemModel(dataIndex); + + var params = seriesModel.getDataParams(dataIndex, dataType); + if (dimIndex != null && (params.value instanceof Array)) { + params.value = params.value[dimIndex]; + } + + var formatter = itemModel.get(status === 'normal' ? ['label', 'formatter'] : ['emphasis', 'label', 'formatter']); + if (formatter == null) { + formatter = itemModel.get(['label', 'formatter']); + } + var text; + if (typeof formatter === 'function') { + params.status = status; + text = formatter(params); + } + else if (typeof formatter === 'string') { + text = __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.format.formatTpl(formatter, params); + } + return text; +}; + +/** + * If value is not array, then convert it to array. + * @param {*} value + * @return {Array} [value] or value + */ +formatUtil.normalizeToArray = function (value) { + return value instanceof Array + ? value + : value == null + ? [] + : [value]; +}; + +/* harmony default export */ __webpack_exports__["a"] = (formatUtil); + +/***/ }), +/* 33 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* unused harmony export vec4 */ +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__common__ = __webpack_require__(20); + +/* Copyright (c) 2013, Brandon Jones, Colin MacKenzie IV. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + + + +/** + * @class 4 Dimensional Vector + * @name vec4 + */ + +var vec4 = {}; + +/** + * Creates a new, empty vec4 + * + * @returns {vec4} a new 4D vector + */ +vec4.create = function() { + var out = new __WEBPACK_IMPORTED_MODULE_0__common__["a" /* GLMAT_ARRAY_TYPE */](4); + out[0] = 0; + out[1] = 0; + out[2] = 0; + out[3] = 0; + return out; +}; + +/** + * Creates a new vec4 initialized with values from an existing vector + * + * @param {vec4} a vector to clone + * @returns {vec4} a new 4D vector + */ +vec4.clone = function(a) { + var out = new __WEBPACK_IMPORTED_MODULE_0__common__["a" /* GLMAT_ARRAY_TYPE */](4); + out[0] = a[0]; + out[1] = a[1]; + out[2] = a[2]; + out[3] = a[3]; + return out; +}; + +/** + * Creates a new vec4 initialized with the given values + * + * @param {Number} x X component + * @param {Number} y Y component + * @param {Number} z Z component + * @param {Number} w W component + * @returns {vec4} a new 4D vector + */ +vec4.fromValues = function(x, y, z, w) { + var out = new __WEBPACK_IMPORTED_MODULE_0__common__["a" /* GLMAT_ARRAY_TYPE */](4); + out[0] = x; + out[1] = y; + out[2] = z; + out[3] = w; + return out; +}; + +/** + * Copy the values from one vec4 to another + * + * @param {vec4} out the receiving vector + * @param {vec4} a the source vector + * @returns {vec4} out + */ +vec4.copy = function(out, a) { + out[0] = a[0]; + out[1] = a[1]; + out[2] = a[2]; + out[3] = a[3]; + return out; +}; + +/** + * Set the components of a vec4 to the given values + * + * @param {vec4} out the receiving vector + * @param {Number} x X component + * @param {Number} y Y component + * @param {Number} z Z component + * @param {Number} w W component + * @returns {vec4} out + */ +vec4.set = function(out, x, y, z, w) { + out[0] = x; + out[1] = y; + out[2] = z; + out[3] = w; + return out; +}; + +/** + * Adds two vec4's + * + * @param {vec4} out the receiving vector + * @param {vec4} a the first operand + * @param {vec4} b the second operand + * @returns {vec4} out + */ +vec4.add = function(out, a, b) { + out[0] = a[0] + b[0]; + out[1] = a[1] + b[1]; + out[2] = a[2] + b[2]; + out[3] = a[3] + b[3]; + return out; +}; + +/** + * Subtracts vector b from vector a + * + * @param {vec4} out the receiving vector + * @param {vec4} a the first operand + * @param {vec4} b the second operand + * @returns {vec4} out + */ +vec4.subtract = function(out, a, b) { + out[0] = a[0] - b[0]; + out[1] = a[1] - b[1]; + out[2] = a[2] - b[2]; + out[3] = a[3] - b[3]; + return out; +}; + +/** + * Alias for {@link vec4.subtract} + * @function + */ +vec4.sub = vec4.subtract; + +/** + * Multiplies two vec4's + * + * @param {vec4} out the receiving vector + * @param {vec4} a the first operand + * @param {vec4} b the second operand + * @returns {vec4} out + */ +vec4.multiply = function(out, a, b) { + out[0] = a[0] * b[0]; + out[1] = a[1] * b[1]; + out[2] = a[2] * b[2]; + out[3] = a[3] * b[3]; + return out; +}; + +/** + * Alias for {@link vec4.multiply} + * @function + */ +vec4.mul = vec4.multiply; + +/** + * Divides two vec4's + * + * @param {vec4} out the receiving vector + * @param {vec4} a the first operand + * @param {vec4} b the second operand + * @returns {vec4} out + */ +vec4.divide = function(out, a, b) { + out[0] = a[0] / b[0]; + out[1] = a[1] / b[1]; + out[2] = a[2] / b[2]; + out[3] = a[3] / b[3]; + return out; +}; + +/** + * Alias for {@link vec4.divide} + * @function + */ +vec4.div = vec4.divide; + +/** + * Returns the minimum of two vec4's + * + * @param {vec4} out the receiving vector + * @param {vec4} a the first operand + * @param {vec4} b the second operand + * @returns {vec4} out + */ +vec4.min = function(out, a, b) { + out[0] = Math.min(a[0], b[0]); + out[1] = Math.min(a[1], b[1]); + out[2] = Math.min(a[2], b[2]); + out[3] = Math.min(a[3], b[3]); + return out; +}; + +/** + * Returns the maximum of two vec4's + * + * @param {vec4} out the receiving vector + * @param {vec4} a the first operand + * @param {vec4} b the second operand + * @returns {vec4} out + */ +vec4.max = function(out, a, b) { + out[0] = Math.max(a[0], b[0]); + out[1] = Math.max(a[1], b[1]); + out[2] = Math.max(a[2], b[2]); + out[3] = Math.max(a[3], b[3]); + return out; +}; + +/** + * Scales a vec4 by a scalar number + * + * @param {vec4} out the receiving vector + * @param {vec4} a the vector to scale + * @param {Number} b amount to scale the vector by + * @returns {vec4} out + */ +vec4.scale = function(out, a, b) { + out[0] = a[0] * b; + out[1] = a[1] * b; + out[2] = a[2] * b; + out[3] = a[3] * b; + return out; +}; + +/** + * Adds two vec4's after scaling the second operand by a scalar value + * + * @param {vec4} out the receiving vector + * @param {vec4} a the first operand + * @param {vec4} b the second operand + * @param {Number} scale the amount to scale b by before adding + * @returns {vec4} out + */ +vec4.scaleAndAdd = function(out, a, b, scale) { + out[0] = a[0] + (b[0] * scale); + out[1] = a[1] + (b[1] * scale); + out[2] = a[2] + (b[2] * scale); + out[3] = a[3] + (b[3] * scale); + return out; +}; + +/** + * Calculates the euclidian distance between two vec4's + * + * @param {vec4} a the first operand + * @param {vec4} b the second operand + * @returns {Number} distance between a and b + */ +vec4.distance = function(a, b) { + var x = b[0] - a[0], + y = b[1] - a[1], + z = b[2] - a[2], + w = b[3] - a[3]; + return Math.sqrt(x*x + y*y + z*z + w*w); +}; + +/** + * Alias for {@link vec4.distance} + * @function + */ +vec4.dist = vec4.distance; + +/** + * Calculates the squared euclidian distance between two vec4's + * + * @param {vec4} a the first operand + * @param {vec4} b the second operand + * @returns {Number} squared distance between a and b + */ +vec4.squaredDistance = function(a, b) { + var x = b[0] - a[0], + y = b[1] - a[1], + z = b[2] - a[2], + w = b[3] - a[3]; + return x*x + y*y + z*z + w*w; +}; + +/** + * Alias for {@link vec4.squaredDistance} + * @function + */ +vec4.sqrDist = vec4.squaredDistance; + +/** + * Calculates the length of a vec4 + * + * @param {vec4} a vector to calculate length of + * @returns {Number} length of a + */ +vec4.length = function (a) { + var x = a[0], + y = a[1], + z = a[2], + w = a[3]; + return Math.sqrt(x*x + y*y + z*z + w*w); +}; + +/** + * Alias for {@link vec4.length} + * @function + */ +vec4.len = vec4.length; + +/** + * Calculates the squared length of a vec4 + * + * @param {vec4} a vector to calculate squared length of + * @returns {Number} squared length of a + */ +vec4.squaredLength = function (a) { + var x = a[0], + y = a[1], + z = a[2], + w = a[3]; + return x*x + y*y + z*z + w*w; +}; + +/** + * Alias for {@link vec4.squaredLength} + * @function + */ +vec4.sqrLen = vec4.squaredLength; + +/** + * Negates the components of a vec4 + * + * @param {vec4} out the receiving vector + * @param {vec4} a vector to negate + * @returns {vec4} out + */ +vec4.negate = function(out, a) { + out[0] = -a[0]; + out[1] = -a[1]; + out[2] = -a[2]; + out[3] = -a[3]; + return out; +}; + +/** + * Returns the inverse of the components of a vec4 + * + * @param {vec4} out the receiving vector + * @param {vec4} a vector to invert + * @returns {vec4} out + */ +vec4.inverse = function(out, a) { + out[0] = 1.0 / a[0]; + out[1] = 1.0 / a[1]; + out[2] = 1.0 / a[2]; + out[3] = 1.0 / a[3]; + return out; +}; + +/** + * Normalize a vec4 + * + * @param {vec4} out the receiving vector + * @param {vec4} a vector to normalize + * @returns {vec4} out + */ +vec4.normalize = function(out, a) { + var x = a[0], + y = a[1], + z = a[2], + w = a[3]; + var len = x*x + y*y + z*z + w*w; + if (len > 0) { + len = 1 / Math.sqrt(len); + out[0] = a[0] * len; + out[1] = a[1] * len; + out[2] = a[2] * len; + out[3] = a[3] * len; + } + return out; +}; + +/** + * Calculates the dot product of two vec4's + * + * @param {vec4} a the first operand + * @param {vec4} b the second operand + * @returns {Number} dot product of a and b + */ +vec4.dot = function (a, b) { + return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3]; +}; + +/** + * Performs a linear interpolation between two vec4's + * + * @param {vec4} out the receiving vector + * @param {vec4} a the first operand + * @param {vec4} b the second operand + * @param {Number} t interpolation amount between the two inputs + * @returns {vec4} out + */ +vec4.lerp = function (out, a, b, t) { + var ax = a[0], + ay = a[1], + az = a[2], + aw = a[3]; + out[0] = ax + t * (b[0] - ax); + out[1] = ay + t * (b[1] - ay); + out[2] = az + t * (b[2] - az); + out[3] = aw + t * (b[3] - aw); + return out; +}; + +/** + * Generates a random vector with the given scale + * + * @param {vec4} out the receiving vector + * @param {Number} [scale] Length of the resulting vector. If ommitted, a unit vector will be returned + * @returns {vec4} out + */ +vec4.random = function (out, scale) { + scale = scale || 1.0; + + //TODO: This is a pretty awful way of doing this. Find something better. + out[0] = Object(__WEBPACK_IMPORTED_MODULE_0__common__["c" /* GLMAT_RANDOM */])(); + out[1] = Object(__WEBPACK_IMPORTED_MODULE_0__common__["c" /* GLMAT_RANDOM */])(); + out[2] = Object(__WEBPACK_IMPORTED_MODULE_0__common__["c" /* GLMAT_RANDOM */])(); + out[3] = Object(__WEBPACK_IMPORTED_MODULE_0__common__["c" /* GLMAT_RANDOM */])(); + vec4.normalize(out, out); + vec4.scale(out, out, scale); + return out; +}; + +/** + * Transforms the vec4 with a mat4. + * + * @param {vec4} out the receiving vector + * @param {vec4} a the vector to transform + * @param {mat4} m matrix to transform with + * @returns {vec4} out + */ +vec4.transformMat4 = function(out, a, m) { + var x = a[0], y = a[1], z = a[2], w = a[3]; + out[0] = m[0] * x + m[4] * y + m[8] * z + m[12] * w; + out[1] = m[1] * x + m[5] * y + m[9] * z + m[13] * w; + out[2] = m[2] * x + m[6] * y + m[10] * z + m[14] * w; + out[3] = m[3] * x + m[7] * y + m[11] * z + m[15] * w; + return out; +}; + +/** + * Transforms the vec4 with a quat + * + * @param {vec4} out the receiving vector + * @param {vec4} a the vector to transform + * @param {quat} q quaternion to transform with + * @returns {vec4} out + */ +vec4.transformQuat = function(out, a, q) { + var x = a[0], y = a[1], z = a[2], + qx = q[0], qy = q[1], qz = q[2], qw = q[3], + + // calculate quat * vec + ix = qw * x + qy * z - qz * y, + iy = qw * y + qz * x - qx * z, + iz = qw * z + qx * y - qy * x, + iw = -qx * x - qy * y - qz * z; + + // calculate result * inverse quat + out[0] = ix * qw + iw * -qx + iy * -qz - iz * -qy; + out[1] = iy * qw + iw * -qy + iz * -qx - ix * -qz; + out[2] = iz * qw + iw * -qz + ix * -qy - iy * -qx; + return out; +}; + +/** + * Perform some operation over an array of vec4s. + * + * @param {Array} a the array of vectors to iterate over + * @param {Number} stride Number of elements between the start of each vec4. If 0 assumes tightly packed + * @param {Number} offset Number of elements to skip at the beginning of the array + * @param {Number} count Number of vec4s to iterate over. If 0 iterates over entire array + * @param {Function} fn Function to call for each vector in the array + * @param {Object} [arg] additional argument to pass to fn + * @returns {Array} a + * @function + */ +vec4.forEach = (function() { + var vec = vec4.create(); + + return function(a, stride, offset, count, fn, arg) { + var i, l; + if(!stride) { + stride = 4; + } + + if(!offset) { + offset = 0; + } + + if(count) { + l = Math.min((count * stride) + offset, a.length); + } else { + l = a.length; + } + + for(i = offset; i < l; i += stride) { + vec[0] = a[i]; vec[1] = a[i+1]; vec[2] = a[i+2]; vec[3] = a[i+3]; + fn(vec, vec, arg); + a[i] = vec[0]; a[i+1] = vec[1]; a[i+2] = vec[2]; a[i+3] = vec[3]; + } + + return a; + }; +})(); + +/* harmony default export */ __webpack_exports__["a"] = (vec4); + +/***/ }), +/* 34 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__common__ = __webpack_require__(20); + +/* Copyright (c) 2013, Brandon Jones, Colin MacKenzie IV. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + + + +/** + * @class 3x3 Matrix + * @name mat3 + */ + +var mat3 = {}; + +/** + * Creates a new identity mat3 + * + * @returns {mat3} a new 3x3 matrix + */ +mat3.create = function() { + var out = new __WEBPACK_IMPORTED_MODULE_0__common__["a" /* GLMAT_ARRAY_TYPE */](9); + out[0] = 1; + out[1] = 0; + out[2] = 0; + out[3] = 0; + out[4] = 1; + out[5] = 0; + out[6] = 0; + out[7] = 0; + out[8] = 1; + return out; +}; + +/** + * Copies the upper-left 3x3 values into the given mat3. + * + * @param {mat3} out the receiving 3x3 matrix + * @param {mat4} a the source 4x4 matrix + * @returns {mat3} out + */ +mat3.fromMat4 = function(out, a) { + out[0] = a[0]; + out[1] = a[1]; + out[2] = a[2]; + out[3] = a[4]; + out[4] = a[5]; + out[5] = a[6]; + out[6] = a[8]; + out[7] = a[9]; + out[8] = a[10]; + return out; +}; + +/** + * Creates a new mat3 initialized with values from an existing matrix + * + * @param {mat3} a matrix to clone + * @returns {mat3} a new 3x3 matrix + */ +mat3.clone = function(a) { + var out = new __WEBPACK_IMPORTED_MODULE_0__common__["a" /* GLMAT_ARRAY_TYPE */](9); + out[0] = a[0]; + out[1] = a[1]; + out[2] = a[2]; + out[3] = a[3]; + out[4] = a[4]; + out[5] = a[5]; + out[6] = a[6]; + out[7] = a[7]; + out[8] = a[8]; + return out; +}; + +/** + * Copy the values from one mat3 to another + * + * @param {mat3} out the receiving matrix + * @param {mat3} a the source matrix + * @returns {mat3} out + */ +mat3.copy = function(out, a) { + out[0] = a[0]; + out[1] = a[1]; + out[2] = a[2]; + out[3] = a[3]; + out[4] = a[4]; + out[5] = a[5]; + out[6] = a[6]; + out[7] = a[7]; + out[8] = a[8]; + return out; +}; + +/** + * Set a mat3 to the identity matrix + * + * @param {mat3} out the receiving matrix + * @returns {mat3} out + */ +mat3.identity = function(out) { + out[0] = 1; + out[1] = 0; + out[2] = 0; + out[3] = 0; + out[4] = 1; + out[5] = 0; + out[6] = 0; + out[7] = 0; + out[8] = 1; + return out; +}; + +/** + * Transpose the values of a mat3 + * + * @param {mat3} out the receiving matrix + * @param {mat3} a the source matrix + * @returns {mat3} out + */ +mat3.transpose = function(out, a) { + // If we are transposing ourselves we can skip a few steps but have to cache some values + if (out === a) { + var a01 = a[1], a02 = a[2], a12 = a[5]; + out[1] = a[3]; + out[2] = a[6]; + out[3] = a01; + out[5] = a[7]; + out[6] = a02; + out[7] = a12; + } else { + out[0] = a[0]; + out[1] = a[3]; + out[2] = a[6]; + out[3] = a[1]; + out[4] = a[4]; + out[5] = a[7]; + out[6] = a[2]; + out[7] = a[5]; + out[8] = a[8]; + } + + return out; +}; + +/** + * Inverts a mat3 + * + * @param {mat3} out the receiving matrix + * @param {mat3} a the source matrix + * @returns {mat3} out + */ +mat3.invert = function(out, a) { + var a00 = a[0], a01 = a[1], a02 = a[2], + a10 = a[3], a11 = a[4], a12 = a[5], + a20 = a[6], a21 = a[7], a22 = a[8], + + b01 = a22 * a11 - a12 * a21, + b11 = -a22 * a10 + a12 * a20, + b21 = a21 * a10 - a11 * a20, + + // Calculate the determinant + det = a00 * b01 + a01 * b11 + a02 * b21; + + if (!det) { + return null; + } + det = 1.0 / det; + + out[0] = b01 * det; + out[1] = (-a22 * a01 + a02 * a21) * det; + out[2] = (a12 * a01 - a02 * a11) * det; + out[3] = b11 * det; + out[4] = (a22 * a00 - a02 * a20) * det; + out[5] = (-a12 * a00 + a02 * a10) * det; + out[6] = b21 * det; + out[7] = (-a21 * a00 + a01 * a20) * det; + out[8] = (a11 * a00 - a01 * a10) * det; + return out; +}; + +/** + * Calculates the adjugate of a mat3 + * + * @param {mat3} out the receiving matrix + * @param {mat3} a the source matrix + * @returns {mat3} out + */ +mat3.adjoint = function(out, a) { + var a00 = a[0], a01 = a[1], a02 = a[2], + a10 = a[3], a11 = a[4], a12 = a[5], + a20 = a[6], a21 = a[7], a22 = a[8]; + + out[0] = (a11 * a22 - a12 * a21); + out[1] = (a02 * a21 - a01 * a22); + out[2] = (a01 * a12 - a02 * a11); + out[3] = (a12 * a20 - a10 * a22); + out[4] = (a00 * a22 - a02 * a20); + out[5] = (a02 * a10 - a00 * a12); + out[6] = (a10 * a21 - a11 * a20); + out[7] = (a01 * a20 - a00 * a21); + out[8] = (a00 * a11 - a01 * a10); + return out; +}; + +/** + * Calculates the determinant of a mat3 + * + * @param {mat3} a the source matrix + * @returns {Number} determinant of a + */ +mat3.determinant = function (a) { + var a00 = a[0], a01 = a[1], a02 = a[2], + a10 = a[3], a11 = a[4], a12 = a[5], + a20 = a[6], a21 = a[7], a22 = a[8]; + + return a00 * (a22 * a11 - a12 * a21) + a01 * (-a22 * a10 + a12 * a20) + a02 * (a21 * a10 - a11 * a20); +}; + +/** + * Multiplies two mat3's + * + * @param {mat3} out the receiving matrix + * @param {mat3} a the first operand + * @param {mat3} b the second operand + * @returns {mat3} out + */ +mat3.multiply = function (out, a, b) { + var a00 = a[0], a01 = a[1], a02 = a[2], + a10 = a[3], a11 = a[4], a12 = a[5], + a20 = a[6], a21 = a[7], a22 = a[8], + + b00 = b[0], b01 = b[1], b02 = b[2], + b10 = b[3], b11 = b[4], b12 = b[5], + b20 = b[6], b21 = b[7], b22 = b[8]; + + out[0] = b00 * a00 + b01 * a10 + b02 * a20; + out[1] = b00 * a01 + b01 * a11 + b02 * a21; + out[2] = b00 * a02 + b01 * a12 + b02 * a22; + + out[3] = b10 * a00 + b11 * a10 + b12 * a20; + out[4] = b10 * a01 + b11 * a11 + b12 * a21; + out[5] = b10 * a02 + b11 * a12 + b12 * a22; + + out[6] = b20 * a00 + b21 * a10 + b22 * a20; + out[7] = b20 * a01 + b21 * a11 + b22 * a21; + out[8] = b20 * a02 + b21 * a12 + b22 * a22; + return out; +}; + +/** + * Alias for {@link mat3.multiply} + * @function + */ +mat3.mul = mat3.multiply; + +/** + * Translate a mat3 by the given vector + * + * @param {mat3} out the receiving matrix + * @param {mat3} a the matrix to translate + * @param {vec2} v vector to translate by + * @returns {mat3} out + */ +mat3.translate = function(out, a, v) { + var a00 = a[0], a01 = a[1], a02 = a[2], + a10 = a[3], a11 = a[4], a12 = a[5], + a20 = a[6], a21 = a[7], a22 = a[8], + x = v[0], y = v[1]; + + out[0] = a00; + out[1] = a01; + out[2] = a02; + + out[3] = a10; + out[4] = a11; + out[5] = a12; + + out[6] = x * a00 + y * a10 + a20; + out[7] = x * a01 + y * a11 + a21; + out[8] = x * a02 + y * a12 + a22; + return out; +}; + +/** + * Rotates a mat3 by the given angle + * + * @param {mat3} out the receiving matrix + * @param {mat3} a the matrix to rotate + * @param {Number} rad the angle to rotate the matrix by + * @returns {mat3} out + */ +mat3.rotate = function (out, a, rad) { + var a00 = a[0], a01 = a[1], a02 = a[2], + a10 = a[3], a11 = a[4], a12 = a[5], + a20 = a[6], a21 = a[7], a22 = a[8], + + s = Math.sin(rad), + c = Math.cos(rad); + + out[0] = c * a00 + s * a10; + out[1] = c * a01 + s * a11; + out[2] = c * a02 + s * a12; + + out[3] = c * a10 - s * a00; + out[4] = c * a11 - s * a01; + out[5] = c * a12 - s * a02; + + out[6] = a20; + out[7] = a21; + out[8] = a22; + return out; +}; + +/** + * Scales the mat3 by the dimensions in the given vec2 + * + * @param {mat3} out the receiving matrix + * @param {mat3} a the matrix to rotate + * @param {vec2} v the vec2 to scale the matrix by + * @returns {mat3} out + **/ +mat3.scale = function(out, a, v) { + var x = v[0], y = v[1]; + + out[0] = x * a[0]; + out[1] = x * a[1]; + out[2] = x * a[2]; + + out[3] = y * a[3]; + out[4] = y * a[4]; + out[5] = y * a[5]; + + out[6] = a[6]; + out[7] = a[7]; + out[8] = a[8]; + return out; +}; + +/** + * Copies the values from a mat2d into a mat3 + * + * @param {mat3} out the receiving matrix + * @param {mat2d} a the matrix to copy + * @returns {mat3} out + **/ +mat3.fromMat2d = function(out, a) { + out[0] = a[0]; + out[1] = a[1]; + out[2] = 0; + + out[3] = a[2]; + out[4] = a[3]; + out[5] = 0; + + out[6] = a[4]; + out[7] = a[5]; + out[8] = 1; + return out; +}; + +/** +* Calculates a 3x3 matrix from the given quaternion +* +* @param {mat3} out mat3 receiving operation result +* @param {quat} q Quaternion to create matrix from +* +* @returns {mat3} out +*/ +mat3.fromQuat = function (out, q) { + var x = q[0], y = q[1], z = q[2], w = q[3], + x2 = x + x, + y2 = y + y, + z2 = z + z, + + xx = x * x2, + yx = y * x2, + yy = y * y2, + zx = z * x2, + zy = z * y2, + zz = z * z2, + wx = w * x2, + wy = w * y2, + wz = w * z2; + + out[0] = 1 - yy - zz; + out[3] = yx - wz; + out[6] = zx + wy; + + out[1] = yx + wz; + out[4] = 1 - xx - zz; + out[7] = zy - wx; + + out[2] = zx - wy; + out[5] = zy + wx; + out[8] = 1 - xx - yy; + + return out; +}; + +/** +* Calculates a 3x3 normal matrix (transpose inverse) from the 4x4 matrix +* +* @param {mat3} out mat3 receiving operation result +* @param {mat4} a Mat4 to derive the normal matrix from +* +* @returns {mat3} out +*/ +mat3.normalFromMat4 = function (out, a) { + var a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3], + a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7], + a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11], + a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15], + + b00 = a00 * a11 - a01 * a10, + b01 = a00 * a12 - a02 * a10, + b02 = a00 * a13 - a03 * a10, + b03 = a01 * a12 - a02 * a11, + b04 = a01 * a13 - a03 * a11, + b05 = a02 * a13 - a03 * a12, + b06 = a20 * a31 - a21 * a30, + b07 = a20 * a32 - a22 * a30, + b08 = a20 * a33 - a23 * a30, + b09 = a21 * a32 - a22 * a31, + b10 = a21 * a33 - a23 * a31, + b11 = a22 * a33 - a23 * a32, + + // Calculate the determinant + det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06; + + if (!det) { + return null; + } + det = 1.0 / det; + + out[0] = (a11 * b11 - a12 * b10 + a13 * b09) * det; + out[1] = (a12 * b08 - a10 * b11 - a13 * b07) * det; + out[2] = (a10 * b10 - a11 * b08 + a13 * b06) * det; + + out[3] = (a02 * b10 - a01 * b11 - a03 * b09) * det; + out[4] = (a00 * b11 - a02 * b08 + a03 * b07) * det; + out[5] = (a01 * b08 - a00 * b10 - a03 * b06) * det; + + out[6] = (a31 * b05 - a32 * b04 + a33 * b03) * det; + out[7] = (a32 * b02 - a30 * b05 - a33 * b01) * det; + out[8] = (a30 * b04 - a31 * b02 + a33 * b00) * det; + + return out; +}; + +/** + * Returns Frobenius norm of a mat3 + * + * @param {mat3} a the matrix to calculate Frobenius norm of + * @returns {Number} Frobenius norm + */ +mat3.frob = function (a) { + return(Math.sqrt(Math.pow(a[0], 2) + Math.pow(a[1], 2) + Math.pow(a[2], 2) + Math.pow(a[3], 2) + Math.pow(a[4], 2) + Math.pow(a[5], 2) + Math.pow(a[6], 2) + Math.pow(a[7], 2) + Math.pow(a[8], 2))) +}; + + +/* harmony default export */ __webpack_exports__["a"] = (mat3); + +/***/ }), +/* 35 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__core_Base__ = __webpack_require__(7); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__math_Vector3__ = __webpack_require__(3); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__math_Quaternion__ = __webpack_require__(56); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__math_Matrix4__ = __webpack_require__(9); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4__glmatrix_mat4__ = __webpack_require__(21); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_5__math_BoundingBox__ = __webpack_require__(18); + + + + + + + +var nameId = 0; + +/** + * @constructor clay.Node + * @extends clay.core.Base + */ +var Node = __WEBPACK_IMPORTED_MODULE_0__core_Base__["a" /* default */].extend(/** @lends clay.Node# */{ + /** + * Scene node name + * @type {string} + */ + name: '', + + /** + * Position relative to its parent node. aka translation. + * @type {clay.Vector3} + */ + position: null, + + /** + * Rotation relative to its parent node. Represented by a quaternion + * @type {clay.Quaternion} + */ + rotation: null, + + /** + * Scale relative to its parent node + * @type {clay.Vector3} + */ + scale: null, + + /** + * Affine transform matrix relative to its root scene. + * @type {clay.Matrix4} + */ + worldTransform: null, + + /** + * Affine transform matrix relative to its parent node. + * Composited with position, rotation and scale. + * @type {clay.Matrix4} + */ + localTransform: null, + + /** + * If the local transform is update from SRT(scale, rotation, translation, which is position here) each frame + * @type {boolean} + */ + autoUpdateLocalTransform: true, + + /** + * Parent of current scene node + * @type {?clay.Node} + * @private + */ + _parent: null, + /** + * The root scene mounted. Null if it is a isolated node + * @type {?clay.Scene} + * @private + */ + _scene: null, + /** + * @type {boolean} + * @private + */ + _needsUpdateWorldTransform: true, + /** + * @type {boolean} + * @private + */ + _inIterating: false, + + // Depth for transparent list sorting + __depth: 0 + +}, function () { + + if (!this.name) { + this.name = (this.type || 'NODE') + '_' + (nameId++); + } + + if (!this.position) { + this.position = new __WEBPACK_IMPORTED_MODULE_1__math_Vector3__["a" /* default */](); + } + if (!this.rotation) { + this.rotation = new __WEBPACK_IMPORTED_MODULE_2__math_Quaternion__["a" /* default */](); + } + if (!this.scale) { + this.scale = new __WEBPACK_IMPORTED_MODULE_1__math_Vector3__["a" /* default */](1, 1, 1); + } + + this.worldTransform = new __WEBPACK_IMPORTED_MODULE_3__math_Matrix4__["a" /* default */](); + this.localTransform = new __WEBPACK_IMPORTED_MODULE_3__math_Matrix4__["a" /* default */](); + + this._children = []; + +}, +/**@lends clay.Node.prototype. */ +{ + + /** + * @type {?clay.Vector3} + * @instance + */ + target: null, + /** + * If node and its chilren invisible + * @type {boolean} + * @instance + */ + invisible: false, + + /** + * If Node is a skinned mesh + * @return {boolean} + */ + isSkinnedMesh: function () { + return false; + }, + /** + * Return true if it is a renderable scene node, like Mesh and ParticleSystem + * @return {boolean} + */ + isRenderable: function () { + return false; + }, + + /** + * Set the name of the scene node + * @param {string} name + */ + setName: function (name) { + var scene = this._scene; + if (scene) { + var nodeRepository = scene._nodeRepository; + delete nodeRepository[this.name]; + nodeRepository[name] = this; + } + this.name = name; + }, + + /** + * Add a child node + * @param {clay.Node} node + */ + add: function (node) { + var originalParent = node._parent; + if (originalParent === this) { + return; + } + if (originalParent) { + originalParent.remove(node); + } + node._parent = this; + this._children.push(node); + + var scene = this._scene; + if (scene && scene !== node.scene) { + node.traverse(this._addSelfToScene, this); + } + // Mark children needs update transform + // In case child are remove and added again after parent moved + node._needsUpdateWorldTransform = true; + }, + + /** + * Remove the given child scene node + * @param {clay.Node} node + */ + remove: function (node) { + var children = this._children; + var idx = children.indexOf(node); + if (idx < 0) { + return; + } + + children.splice(idx, 1); + node._parent = null; + + if (this._scene) { + node.traverse(this._removeSelfFromScene, this); + } + }, + + /** + * Remove all children + */ + removeAll: function () { + var children = this._children; + + for (var idx = 0; idx < children.length; idx++) { + children[idx]._parent = null; + + if (this._scene) { + children[idx].traverse(this._removeSelfFromScene, this); + } + } + + this._children = []; + }, + + /** + * Get the scene mounted + * @return {clay.Scene} + */ + getScene: function () { + return this._scene; + }, + + /** + * Get parent node + * @return {clay.Scene} + */ + getParent: function () { + return this._parent; + }, + + _removeSelfFromScene: function (descendant) { + descendant._scene.removeFromScene(descendant); + descendant._scene = null; + }, + + _addSelfToScene: function (descendant) { + this._scene.addToScene(descendant); + descendant._scene = this._scene; + }, + + /** + * Return true if it is ancestor of the given scene node + * @param {clay.Node} node + */ + isAncestor: function (node) { + var parent = node._parent; + while(parent) { + if (parent === this) { + return true; + } + parent = parent._parent; + } + return false; + }, + + /** + * Get a new created array of all children nodes + * @return {clay.Node[]} + */ + children: function () { + return this._children.slice(); + }, + + /** + * Get child scene node at given index. + * @param {number} idx + * @return {clay.Node} + */ + childAt: function (idx) { + return this._children[idx]; + }, + + /** + * Get first child with the given name + * @param {string} name + * @return {clay.Node} + */ + getChildByName: function (name) { + var children = this._children; + for (var i = 0; i < children.length; i++) { + if (children[i].name === name) { + return children[i]; + } + } + }, + + /** + * Get first descendant have the given name + * @param {string} name + * @return {clay.Node} + */ + getDescendantByName: function (name) { + var children = this._children; + for (var i = 0; i < children.length; i++) { + var child = children[i]; + if (child.name === name) { + return child; + } else { + var res = child.getDescendantByName(name); + if (res) { + return res; + } + } + } + }, + + /** + * Query descendant node by path + * @param {string} path + * @return {clay.Node} + * @example + * node.queryNode('root/parent/child'); + */ + queryNode: function (path) { + if (!path) { + return; + } + // TODO Name have slash ? + var pathArr = path.split('/'); + var current = this; + for (var i = 0; i < pathArr.length; i++) { + var name = pathArr[i]; + // Skip empty + if (!name) { + continue; + } + var found = false; + var children = current._children; + for (var j = 0; j < children.length; j++) { + var child = children[j]; + if (child.name === name) { + current = child; + found = true; + break; + } + } + // Early return if not found + if (!found) { + return; + } + } + + return current; + }, + + /** + * Get query path, relative to rootNode(default is scene) + * @param {clay.Node} [rootNode] + * @return {string} + */ + getPath: function (rootNode) { + if (!this._parent) { + return '/'; + } + + var current = this._parent; + var path = this.name; + while (current._parent) { + path = current.name + '/' + path; + if (current._parent == rootNode) { + break; + } + current = current._parent; + } + if (!current._parent && rootNode) { + return null; + } + return path; + }, + + /** + * Depth first traverse all its descendant scene nodes. + * + * **WARN** Don't do `add`, `remove` operation in the callback during traverse. + * @param {Function} callback + * @param {Node} [context] + */ + traverse: function (callback, context) { + callback.call(context, this); + var _children = this._children; + for(var i = 0, len = _children.length; i < len; i++) { + _children[i].traverse(callback, context); + } + }, + + /** + * Traverse all children nodes. + * + * **WARN** DON'T do `add`, `remove` operation in the callback during iteration. + * + * @param {Function} callback + * @param {Node} [context] + */ + eachChild: function (callback, context) { + var _children = this._children; + for(var i = 0, len = _children.length; i < len; i++) { + var child = _children[i]; + callback.call(context, child, i); + } + }, + + /** + * Set the local transform and decompose to SRT + * @param {clay.Matrix4} matrix + */ + setLocalTransform: function (matrix) { + __WEBPACK_IMPORTED_MODULE_4__glmatrix_mat4__["a" /* default */].copy(this.localTransform.array, matrix.array); + this.decomposeLocalTransform(); + }, + + /** + * Decompose the local transform to SRT + */ + decomposeLocalTransform: function (keepScale) { + var scale = !keepScale ? this.scale: null; + this.localTransform.decomposeMatrix(scale, this.rotation, this.position); + }, + + /** + * Set the world transform and decompose to SRT + * @param {clay.Matrix4} matrix + */ + setWorldTransform: function (matrix) { + __WEBPACK_IMPORTED_MODULE_4__glmatrix_mat4__["a" /* default */].copy(this.worldTransform.array, matrix.array); + this.decomposeWorldTransform(); + }, + + /** + * Decompose the world transform to SRT + * @function + */ + decomposeWorldTransform: (function () { + + var tmp = __WEBPACK_IMPORTED_MODULE_4__glmatrix_mat4__["a" /* default */].create(); + + return function (keepScale) { + var localTransform = this.localTransform; + var worldTransform = this.worldTransform; + // Assume world transform is updated + if (this._parent) { + __WEBPACK_IMPORTED_MODULE_4__glmatrix_mat4__["a" /* default */].invert(tmp, this._parent.worldTransform.array); + __WEBPACK_IMPORTED_MODULE_4__glmatrix_mat4__["a" /* default */].multiply(localTransform.array, tmp, worldTransform.array); + } else { + __WEBPACK_IMPORTED_MODULE_4__glmatrix_mat4__["a" /* default */].copy(localTransform.array, worldTransform.array); + } + var scale = !keepScale ? this.scale: null; + localTransform.decomposeMatrix(scale, this.rotation, this.position); + }; + })(), + + transformNeedsUpdate: function () { + return this.position._dirty + || this.rotation._dirty + || this.scale._dirty; + }, + + /** + * Update local transform from SRT + * Notice that local transform will not be updated if _dirty mark of position, rotation, scale is all false + */ + updateLocalTransform: function () { + var position = this.position; + var rotation = this.rotation; + var scale = this.scale; + + if (this.transformNeedsUpdate()) { + var m = this.localTransform.array; + + // Transform order, scale->rotation->position + __WEBPACK_IMPORTED_MODULE_4__glmatrix_mat4__["a" /* default */].fromRotationTranslation(m, rotation.array, position.array); + + __WEBPACK_IMPORTED_MODULE_4__glmatrix_mat4__["a" /* default */].scale(m, m, scale.array); + + rotation._dirty = false; + scale._dirty = false; + position._dirty = false; + + this._needsUpdateWorldTransform = true; + } + }, + + /** + * Update world transform, assume its parent world transform have been updated + * @private + */ + _updateWorldTransformTopDown: function () { + var localTransform = this.localTransform.array; + var worldTransform = this.worldTransform.array; + if (this._parent) { + __WEBPACK_IMPORTED_MODULE_4__glmatrix_mat4__["a" /* default */].multiplyAffine( + worldTransform, + this._parent.worldTransform.array, + localTransform + ); + } + else { + __WEBPACK_IMPORTED_MODULE_4__glmatrix_mat4__["a" /* default */].copy(worldTransform, localTransform); + } + }, + + /** + * Update world transform before whole scene is updated. + */ + updateWorldTransform: function () { + // Find the root node which transform needs update; + var rootNodeIsDirty = this; + while (rootNodeIsDirty && rootNodeIsDirty.getParent() + && rootNodeIsDirty.getParent().transformNeedsUpdate() + ) { + rootNodeIsDirty = rootNodeIsDirty.getParent(); + } + rootNodeIsDirty.update(); + }, + + /** + * Update local transform and world transform recursively + * @param {boolean} forceUpdateWorld + */ + update: function (forceUpdateWorld) { + if (this.autoUpdateLocalTransform) { + this.updateLocalTransform(); + } + else { + // Transform is manually setted + forceUpdateWorld = true; + } + + if (forceUpdateWorld || this._needsUpdateWorldTransform) { + this._updateWorldTransformTopDown(); + forceUpdateWorld = true; + this._needsUpdateWorldTransform = false; + } + + var children = this._children; + for(var i = 0, len = children.length; i < len; i++) { + children[i].update(forceUpdateWorld); + } + }, + + /** + * Get bounding box of node + * @param {Function} [filter] + * @param {clay.BoundingBox} [out] + * @return {clay.BoundingBox} + */ + // TODO Skinning + getBoundingBox: (function () { + function defaultFilter (el) { + return !el.invisible && el.geometry; + } + var tmpBBox = new __WEBPACK_IMPORTED_MODULE_5__math_BoundingBox__["a" /* default */](); + var tmpMat4 = new __WEBPACK_IMPORTED_MODULE_3__math_Matrix4__["a" /* default */](); + var invWorldTransform = new __WEBPACK_IMPORTED_MODULE_3__math_Matrix4__["a" /* default */](); + return function (filter, out) { + out = out || new __WEBPACK_IMPORTED_MODULE_5__math_BoundingBox__["a" /* default */](); + filter = filter || defaultFilter; + + if (this._parent) { + __WEBPACK_IMPORTED_MODULE_3__math_Matrix4__["a" /* default */].invert(invWorldTransform, this._parent.worldTransform); + } + else { + __WEBPACK_IMPORTED_MODULE_3__math_Matrix4__["a" /* default */].identity(invWorldTransform); + } + + this.traverse(function (mesh) { + if (mesh.geometry && mesh.geometry.boundingBox) { + tmpBBox.copy(mesh.geometry.boundingBox); + __WEBPACK_IMPORTED_MODULE_3__math_Matrix4__["a" /* default */].multiply(tmpMat4, invWorldTransform, mesh.worldTransform); + tmpBBox.applyTransform(tmpMat4); + out.union(tmpBBox); + } + }, this, defaultFilter); + + return out; + }; + })(), + + /** + * Get world position, extracted from world transform + * @param {clay.Vector3} [out] + * @return {clay.Vector3} + */ + getWorldPosition: function (out) { + // PENDING + if (this.transformNeedsUpdate()) { + this.updateWorldTransform(); + } + var m = this.worldTransform.array; + if (out) { + var arr = out.array; + arr[0] = m[12]; + arr[1] = m[13]; + arr[2] = m[14]; + return out; + } + else { + return new __WEBPACK_IMPORTED_MODULE_1__math_Vector3__["a" /* default */](m[12], m[13], m[14]); + } + }, + + /** + * Clone a new node + * @return {Node} + */ + clone: function () { + var node = new this.constructor(); + + var children = this._children; + + node.setName(this.name); + node.position.copy(this.position); + node.rotation.copy(this.rotation); + node.scale.copy(this.scale); + + for (var i = 0; i < children.length; i++) { + node.add(children[i].clone()); + } + + return node; + }, + + /** + * Rotate the node around a axis by angle degrees, axis passes through point + * @param {clay.Vector3} point Center point + * @param {clay.Vector3} axis Center axis + * @param {number} angle Rotation angle + * @see http://docs.unity3d.com/Documentation/ScriptReference/Transform.RotateAround.html + * @function + */ + rotateAround: (function () { + var v = new __WEBPACK_IMPORTED_MODULE_1__math_Vector3__["a" /* default */](); + var RTMatrix = new __WEBPACK_IMPORTED_MODULE_3__math_Matrix4__["a" /* default */](); + + // TODO improve performance + return function (point, axis, angle) { + + v.copy(this.position).subtract(point); + + var localTransform = this.localTransform; + localTransform.identity(); + // parent node + localTransform.translate(point); + localTransform.rotate(angle, axis); + + RTMatrix.fromRotationTranslation(this.rotation, v); + localTransform.multiply(RTMatrix); + localTransform.scale(this.scale); + + this.decomposeLocalTransform(); + this._needsUpdateWorldTransform = true; + }; + })(), + + /** + * @param {clay.Vector3} target + * @param {clay.Vector3} [up] + * @see http://www.opengl.org/sdk/docs/man2/xhtml/gluLookAt.xml + * @function + */ + lookAt: (function () { + var m = new __WEBPACK_IMPORTED_MODULE_3__math_Matrix4__["a" /* default */](); + return function (target, up) { + m.lookAt(this.position, target, up || this.localTransform.y).invert(); + this.setLocalTransform(m); + + this.target = target; + }; + })() +}); + +/* harmony default export */ __webpack_exports__["a"] = (Node); + + +/***/ }), +/* 36 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__Node__ = __webpack_require__(35); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__Light__ = __webpack_require__(24); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__Camera__ = __webpack_require__(58); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__math_BoundingBox__ = __webpack_require__(18); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4__core_util__ = __webpack_require__(23); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_5__glmatrix_mat4__ = __webpack_require__(21); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_6__core_LRU__ = __webpack_require__(69); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_7__math_Matrix4__ = __webpack_require__(9); + + + + + + + + + +var IDENTITY = __WEBPACK_IMPORTED_MODULE_5__glmatrix_mat4__["a" /* default */].create(); +var WORLDVIEW = __WEBPACK_IMPORTED_MODULE_5__glmatrix_mat4__["a" /* default */].create(); + +var programKeyCache = {}; + +function getProgramKey(lightNumbers) { + var defineStr = []; + var lightTypes = Object.keys(lightNumbers); + lightTypes.sort(); + for (var i = 0; i < lightTypes.length; i++) { + var lightType = lightTypes[i]; + defineStr.push(lightType + ' ' + lightNumbers[lightType]); + } + var key = defineStr.join('\n'); + + if (programKeyCache[key]) { + return programKeyCache[key]; + } + + var id = __WEBPACK_IMPORTED_MODULE_4__core_util__["a" /* default */].genGUID(); + programKeyCache[key] = id; + return id; +} + +function RenderList() { + + this.opaque = []; + this.transparent = []; + + this._opaqueCount = 0; + this._transparentCount = 0; +} + +RenderList.prototype.startCount = function () { + this._opaqueCount = 0; + this._transparentCount = 0; +}; + +RenderList.prototype.add = function (object, isTransparent) { + if (isTransparent) { + this.transparent[this._transparentCount++] = object; + } + else { + this.opaque[this._opaqueCount++] = object; + } +}; + +RenderList.prototype.endCount = function () { + this.transparent.length = this._transparentCount; + this.opaque.length = this._opaqueCount; +}; + +/** + * @typedef {Object} clay.Scene.RenderList + * @property {Array.} opaque + * @property {Array.} transparent + */ + +/** + * @constructor clay.Scene + * @extends clay.Node + */ +var Scene = __WEBPACK_IMPORTED_MODULE_0__Node__["a" /* default */].extend(function () { + return /** @lends clay.Scene# */ { + /** + * Global material of scene + * @type {clay.Material} + */ + material: null, + + lights: [], + + /** + * Scene bounding box in view space. + * Used when camera needs to adujst the near and far plane automatically + * so that the view frustum contains the visible objects as tightly as possible. + * Notice: + * It is updated after rendering (in the step of frustum culling passingly). So may be not so accurate, but saves a lot of calculation + * + * @type {clay.BoundingBox} + */ + viewBoundingBoxLastFrame: new __WEBPACK_IMPORTED_MODULE_3__math_BoundingBox__["a" /* default */](), + + // Uniforms for shadow map. + shadowUniforms: {}, + + _cameraList: [], + + // Properties to save the light information in the scene + // Will be set in the render function + _lightUniforms: {}, + + _previousLightNumber: {}, + + _lightNumber: { + // groupId: { + // POINT_LIGHT: 0, + // DIRECTIONAL_LIGHT: 0, + // SPOT_LIGHT: 0, + // AMBIENT_LIGHT: 0, + // AMBIENT_SH_LIGHT: 0 + // } + }, + + _lightProgramKeys: {}, + + _nodeRepository: {}, + + _renderLists: new __WEBPACK_IMPORTED_MODULE_6__core_LRU__["a" /* default */](20) + + }; +}, function () { + this._scene = this; +}, +/** @lends clay.Scene.prototype. */ +{ + + // Add node to scene + addToScene: function (node) { + if (node instanceof __WEBPACK_IMPORTED_MODULE_2__Camera__["a" /* default */]) { + if (this._cameraList.length > 0) { + console.warn('Found multiple camera in one scene. Use the fist one.'); + } + this._cameraList.push(node); + } + else if (node instanceof __WEBPACK_IMPORTED_MODULE_1__Light__["a" /* default */]) { + this.lights.push(node); + } + if (node.name) { + this._nodeRepository[node.name] = node; + } + }, + + // Remove node from scene + removeFromScene: function (node) { + var idx; + if (node instanceof __WEBPACK_IMPORTED_MODULE_2__Camera__["a" /* default */]) { + idx = this._cameraList.indexOf(node); + if (idx >= 0) { + this._cameraList.splice(idx, 1); + } + } + else if (node instanceof __WEBPACK_IMPORTED_MODULE_1__Light__["a" /* default */]) { + idx = this.lights.indexOf(node); + if (idx >= 0) { + this.lights.splice(idx, 1); + } + } + if (node.name) { + delete this._nodeRepository[node.name]; + } + }, + + /** + * Get node by name + * @param {string} name + * @return {Node} + * @DEPRECATED + */ + getNode: function (name) { + return this._nodeRepository[name]; + }, + + /** + * Set main camera of the scene. + * @param {claygl.Camera} camera + */ + setMainCamera: function (camera) { + var idx = this._cameraList.indexOf(camera); + if (idx >= 0) { + this._cameraList.splice(idx, 1); + } + this._cameraList.unshift(camera); + }, + /** + * Get main camera of the scene. + */ + getMainCamera: function () { + return this._cameraList[0]; + }, + + getLights: function () { + return this.lights; + }, + + updateLights: function () { + var lights = this.lights; + this._previousLightNumber = this._lightNumber; + + var lightNumber = {}; + for (var i = 0; i < lights.length; i++) { + var light = lights[i]; + if (light.invisible) { + continue; + } + var group = light.group; + if (!lightNumber[group]) { + lightNumber[group] = {}; + } + // User can use any type of light + lightNumber[group][light.type] = lightNumber[group][light.type] || 0; + lightNumber[group][light.type]++; + } + this._lightNumber = lightNumber; + + for (var groupId in lightNumber) { + this._lightProgramKeys[groupId] = getProgramKey(lightNumber[groupId]); + } + + this._updateLightUniforms(); + }, + + /** + * Clone a node and it's children, including mesh, camera, light, etc. + * Unlike using `Node#clone`. It will clone skeleton and remap the joints. Material will also be cloned. + * + * @param {clay.Node} node + * @return {clay.Node} + */ + cloneNode: function (node) { + var newNode = node.clone(); + var clonedNodesMap = {}; + function buildNodesMap(sNode, tNode) { + clonedNodesMap[sNode.__uid__] = tNode; + + for (var i = 0; i < sNode._children.length; i++) { + var sChild = sNode._children[i]; + var tChild = tNode._children[i]; + buildNodesMap(sChild, tChild); + } + } + buildNodesMap(node, newNode); + + newNode.traverse(function (newChild) { + if (newChild.skeleton) { + newChild.skeleton = newChild.skeleton.clone(clonedNodesMap); + } + if (newChild.material) { + newChild.material = newChild.material.clone(); + } + }); + + return newNode; + }, + + /** + * Traverse the scene and add the renderable object to the render list. + * It needs camera for the frustum culling. + * + * @param {clay.Camera} camera + * @param {boolean} updateSceneBoundingBox + * @return {clay.Scene.RenderList} + */ + updateRenderList: function (camera, updateSceneBoundingBox) { + var id = camera.__uid__; + var renderList = this._renderLists.get(id); + if (!renderList) { + renderList = new RenderList(); + this._renderLists.put(id, renderList); + } + renderList.startCount(); + + if (updateSceneBoundingBox) { + this.viewBoundingBoxLastFrame.min.set(Infinity, Infinity, Infinity); + this.viewBoundingBoxLastFrame.max.set(-Infinity, -Infinity, -Infinity); + } + + var sceneMaterialTransparent = this.material && this.material.transparent || false; + this._doUpdateRenderList(this, camera, sceneMaterialTransparent, renderList, updateSceneBoundingBox); + + renderList.endCount(); + + return renderList; + }, + + /** + * Get render list. Used after {@link clay.Scene#updateRenderList} + * @param {clay.Camera} camera + * @return {clay.Scene.RenderList} + */ + getRenderList: function (camera) { + return this._renderLists.get(camera.__uid__); + }, + + _doUpdateRenderList: function (parent, camera, sceneMaterialTransparent, renderList, updateSceneBoundingBox) { + if (parent.invisible) { + return; + } + // TODO Optimize + for (var i = 0; i < parent._children.length; i++) { + var child = parent._children[i]; + + if (child.isRenderable()) { + // Frustum culling + var worldM = child.isSkinnedMesh() ? IDENTITY : child.worldTransform.array; + var geometry = child.geometry; + + __WEBPACK_IMPORTED_MODULE_5__glmatrix_mat4__["a" /* default */].multiplyAffine(WORLDVIEW, camera.viewMatrix.array, worldM); + if (updateSceneBoundingBox && !geometry.boundingBox || !this.isFrustumCulled(child, camera, WORLDVIEW)) { + renderList.add(child, child.material.transparent || sceneMaterialTransparent); + } + } + if (child._children.length > 0) { + this._doUpdateRenderList(child, camera, sceneMaterialTransparent, renderList, updateSceneBoundingBox); + } + } + }, + + /** + * If an scene object is culled by camera frustum + * + * Object can be a renderable or a light + * + * @param {clay.Node} object + * @param {clay.Camera} camera + * @param {Array.} worldViewMat represented with array + * @param {Array.} projectionMat represented with array + */ + isFrustumCulled: (function () { + // Frustum culling + // http://www.cse.chalmers.se/~uffe/vfc_bbox.pdf + var cullingBoundingBox = new __WEBPACK_IMPORTED_MODULE_3__math_BoundingBox__["a" /* default */](); + var cullingMatrix = new __WEBPACK_IMPORTED_MODULE_7__math_Matrix4__["a" /* default */](); + return function(object, camera, worldViewMat) { + // Bounding box can be a property of object(like light) or renderable.geometry + // PENDING + var geoBBox = object.boundingBox; + if (!geoBBox) { + if (object.skeleton && object.skeleton.boundingBox) { + geoBBox = object.skeleton.boundingBox; + } + else { + geoBBox = object.geometry.boundingBox; + } + } + + if (!geoBBox) { + return false; + } + + cullingMatrix.array = worldViewMat; + cullingBoundingBox.transformFrom(geoBBox, cullingMatrix); + + // Passingly update the scene bounding box + // FIXME exclude very large mesh like ground plane or terrain ? + // FIXME Only rendererable which cast shadow ? + + // FIXME boundingBox becomes much larger after transformd. + if (object.castShadow) { + this.viewBoundingBoxLastFrame.union(cullingBoundingBox); + } + // Ignore frustum culling if object is skinned mesh. + if (object.frustumCulling) { + if (!cullingBoundingBox.intersectBoundingBox(camera.frustum.boundingBox)) { + return true; + } + + cullingMatrix.array = camera.projectionMatrix.array; + if ( + cullingBoundingBox.max.array[2] > 0 && + cullingBoundingBox.min.array[2] < 0 + ) { + // Clip in the near plane + cullingBoundingBox.max.array[2] = -1e-20; + } + + cullingBoundingBox.applyProjection(cullingMatrix); + + var min = cullingBoundingBox.min.array; + var max = cullingBoundingBox.max.array; + + if ( + max[0] < -1 || min[0] > 1 + || max[1] < -1 || min[1] > 1 + || max[2] < -1 || min[2] > 1 + ) { + return true; + } + } + + return false; + }; + })(), + + _updateLightUniforms: function () { + var lights = this.lights; + // Put the light cast shadow before the light not cast shadow + lights.sort(lightSortFunc); + + var lightUniforms = this._lightUniforms; + for (var group in lightUniforms) { + for (var symbol in lightUniforms[group]) { + lightUniforms[group][symbol].value.length = 0; + } + } + for (var i = 0; i < lights.length; i++) { + + var light = lights[i]; + + if (light.invisible) { + continue; + } + + var group = light.group; + + for (var symbol in light.uniformTemplates) { + var uniformTpl = light.uniformTemplates[symbol]; + var value = uniformTpl.value(light); + if (value == null) { + continue; + } + if (!lightUniforms[group]) { + lightUniforms[group] = {}; + } + if (!lightUniforms[group][symbol]) { + lightUniforms[group][symbol] = { + type: '', + value: [] + }; + } + var lu = lightUniforms[group][symbol]; + lu.type = uniformTpl.type + 'v'; + switch (uniformTpl.type) { + case '1i': + case '1f': + case 't': + lu.value.push(value); + break; + case '2f': + case '3f': + case '4f': + for (var j = 0; j < value.length; j++) { + lu.value.push(value[j]); + } + break; + default: + console.error('Unkown light uniform type ' + uniformTpl.type); + } + } + } + }, + + getLightGroups: function () { + var lightGroups = []; + for (var groupId in this._lightNumber) { + lightGroups.push(groupId); + } + return lightGroups; + }, + + getNumberChangedLightGroups: function () { + var lightGroups = []; + for (var groupId in this._lightNumber) { + if (this.isLightNumberChanged(groupId)) { + lightGroups.push(groupId); + } + } + return lightGroups; + }, + + // Determine if light group is different with since last frame + // Used to determine whether to update shader and scene's uniforms in Renderer.render + isLightNumberChanged: function (lightGroup) { + var prevLightNumber = this._previousLightNumber; + var currentLightNumber = this._lightNumber; + // PENDING Performance + for (var type in currentLightNumber[lightGroup]) { + if (!prevLightNumber[lightGroup]) { + return true; + } + if (currentLightNumber[lightGroup][type] !== prevLightNumber[lightGroup][type]) { + return true; + } + } + for (var type in prevLightNumber[lightGroup]) { + if (!currentLightNumber[lightGroup]) { + return true; + } + if (currentLightNumber[lightGroup][type] !== prevLightNumber[lightGroup][type]) { + return true; + } + } + return false; + }, + + getLightsNumbers: function (lightGroup) { + return this._lightNumber[lightGroup]; + }, + + getProgramKey: function (lightGroup) { + return this._lightProgramKeys[lightGroup]; + }, + + setLightUniforms: (function () { + function setUniforms(uniforms, program, renderer) { + for (var symbol in uniforms) { + var lu = uniforms[symbol]; + if (lu.type === 'tv') { + if (!program.hasUniform(symbol)) { + continue; + } + var texSlots = []; + for (var i = 0; i < lu.value.length; i++) { + var texture = lu.value[i]; + var slot = program.takeCurrentTextureSlot(renderer, texture); + texSlots.push(slot); + } + program.setUniform(renderer.gl, '1iv', symbol, texSlots); + } + else { + program.setUniform(renderer.gl, lu.type, symbol, lu.value); + } + } + } + + return function (program, lightGroup, renderer) { + setUniforms(this._lightUniforms[lightGroup], program, renderer); + // Set shadows + setUniforms(this.shadowUniforms, program, renderer); + }; + })(), + + /** + * Dispose self, clear all the scene objects + * But resources of gl like texuture, shader will not be disposed. + * Mostly you should use disposeScene method in Renderer to do dispose. + */ + dispose: function () { + this.material = null; + this._opaqueList = []; + this._transparentList = []; + + this.lights = []; + + this._lightUniforms = {}; + + this._lightNumber = {}; + this._nodeRepository = {}; + } +}); + +function lightSortFunc(a, b) { + if (b.castShadow && !a.castShadow) { + return true; + } +} + +/* harmony default export */ __webpack_exports__["a"] = (Scene); + + +/***/ }), +/* 37 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__Camera__ = __webpack_require__(58); + +/** + * @constructor clay.camera.Orthographic + * @extends clay.Camera + */ +var Orthographic = __WEBPACK_IMPORTED_MODULE_0__Camera__["a" /* default */].extend( +/** @lends clay.camera.Orthographic# */ +{ + /** + * @type {number} + */ + left: -1, + /** + * @type {number} + */ + right: 1, + /** + * @type {number} + */ + near: -1, + /** + * @type {number} + */ + far: 1, + /** + * @type {number} + */ + top: 1, + /** + * @type {number} + */ + bottom: -1 +}, +/** @lends clay.camera.Orthographic.prototype */ +{ + + updateProjectionMatrix: function() { + this.projectionMatrix.ortho(this.left, this.right, this.bottom, this.top, this.near, this.far); + }, + + decomposeProjectionMatrix: function () { + var m = this.projectionMatrix.array; + this.left = (-1 - m[12]) / m[0]; + this.right = (1 - m[12]) / m[0]; + this.top = (1 - m[13]) / m[5]; + this.bottom = (-1 - m[13]) / m[5]; + this.near = -(-1 - m[14]) / m[10]; + this.far = -(1 - m[14]) / m[10]; + }, + /** + * @return {clay.camera.Orthographic} + */ + clone: function() { + var camera = __WEBPACK_IMPORTED_MODULE_0__Camera__["a" /* default */].prototype.clone.call(this); + camera.left = this.left; + camera.right = this.right; + camera.near = this.near; + camera.far = this.far; + camera.top = this.top; + camera.bottom = this.bottom; + + return camera; + } +}); + +/* harmony default export */ __webpack_exports__["a"] = (Orthographic); + + +/***/ }), +/* 38 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony default export */ __webpack_exports__["a"] = ({ + convertToDynamicArray: function (clear) { + if (clear) { + this.resetOffset(); + } + var attributes = this.attributes; + for (var name in attributes) { + if (clear || !attributes[name].value) { + attributes[name].value = []; + } + else { + attributes[name].value = Array.prototype.slice.call(attributes[name].value); + } + } + if (clear || !this.indices) { + this.indices = []; + } + else { + this.indices = Array.prototype.slice.call(this.indices); + } + }, + + convertToTypedArray: function () { + var attributes = this.attributes; + for (var name in attributes) { + if (attributes[name].value && attributes[name].value.length > 0) { + attributes[name].value = new Float32Array(attributes[name].value); + } + else { + attributes[name].value = null; + } + } + if (this.indices && this.indices.length > 0) { + this.indices = this.vertexCount > 0xffff ? new Uint32Array(this.indices) : new Uint16Array(this.indices); + } + + this.dirty(); + } +}); + +/***/ }), +/* 39 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__); + + +function otherDimToDataDim (data, otherDim) { + var dataDim = []; + __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.util.each(data.dimensions, function (dimName) { + var dimItem = data.getDimensionInfo(dimName); + var otherDims = dimItem.otherDims; + var dimIndex = otherDims[otherDim]; + if (dimIndex != null && dimIndex !== false) { + dataDim[dimIndex] = dimItem.name; + } + }); + return dataDim; +} + +/* harmony default export */ __webpack_exports__["a"] = (function (seriesModel, dataIndex, multipleSeries) { + function formatArrayValue(value) { + var vertially = true; + + var result = []; + var tooltipDims = otherDimToDataDim(data, 'tooltip'); + + tooltipDims.length + ? __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.util.each(tooltipDims, function (dimIdx) { + setEachItem(data.get(dimIdx, dataIndex), dimIdx); + }) + // By default, all dims is used on tooltip. + : __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.util.each(value, setEachItem); + + function setEachItem(val, dimIdx) { + var dimInfo = data.getDimensionInfo(dimIdx); + // If `dimInfo.tooltip` is not set, show tooltip. + if (!dimInfo || dimInfo.otherDims.tooltip === false) { + return; + } + var dimType = dimInfo.type; + var valStr = (vertially ? '- ' + (dimInfo.tooltipName || dimInfo.name) + ': ' : '') + + (dimType === 'ordinal' + ? val + '' + : dimType === 'time' + ? (multipleSeries ? '' : __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.format.formatTime('yyyy/MM/dd hh:mm:ss', val)) + : __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.format.addCommas(val) + ); + valStr && result.push(__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.format.encodeHTML(valStr)); + } + + return (vertially ? '
' : '') + result.join(vertially ? '
' : ', '); + } + + var data = seriesModel.getData(); + + var value = seriesModel.getRawValue(dataIndex); + var formattedValue = __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.util.isArray(value) + ? formatArrayValue(value) : __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.format.encodeHTML(__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.format.addCommas(value)); + var name = data.getName(dataIndex); + + var color = data.getItemVisual(dataIndex, 'color'); + if (__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.util.isObject(color) && color.colorStops) { + color = (color.colorStops[0] || {}).color; + } + color = color || 'transparent'; + + var colorEl = __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.format.getTooltipMarker(color); + + var seriesName = seriesModel.name; + // FIXME + if (seriesName === '\0-') { + // Not show '-' + seriesName = ''; + } + seriesName = seriesName + ? __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.format.encodeHTML(seriesName) + (!multipleSeries ? '
' : ': ') + : ''; + return !multipleSeries + ? seriesName + colorEl + + (name + ? __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.format.encodeHTML(name) + ': ' + formattedValue + : formattedValue + ) + : colorEl + seriesName + formattedValue; +});; + +/***/ }), +/* 40 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__Renderable__ = __webpack_require__(72); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__core_glenum__ = __webpack_require__(11); + + + +/** + * @constructor clay.Mesh + * @extends clay.Renderable + */ +var Mesh = __WEBPACK_IMPORTED_MODULE_0__Renderable__["a" /* default */].extend(/** @lends clay.Mesh# */ { + /** + * Used when it is a skinned mesh + * @type {clay.Skeleton} + */ + skeleton: null, + /** + * Joints indices Meshes can share the one skeleton instance and each mesh can use one part of joints. Joints indices indicate the index of joint in the skeleton instance + * @type {number[]} + */ + joints: null, + + /** + * If store the skin matrices in vertex texture + * @type {bool} + */ + useSkinMatricesTexture: false + +}, function () { + if (!this.joints) { + this.joints = []; + } +}, { + + isSkinnedMesh: function () { + return !!(this.skeleton && this.joints && this.joints.length > 0); + }, + + clone: function () { + var mesh = __WEBPACK_IMPORTED_MODULE_0__Renderable__["a" /* default */].prototype.clone.call(this); + mesh.skeleton = this.skeleton; + if (this.joints) { + mesh.joints = this.joints.slice(); + } + return mesh; + } +}); + +// Enums +Mesh.POINTS = __WEBPACK_IMPORTED_MODULE_1__core_glenum__["a" /* default */].POINTS; +Mesh.LINES = __WEBPACK_IMPORTED_MODULE_1__core_glenum__["a" /* default */].LINES; +Mesh.LINE_LOOP = __WEBPACK_IMPORTED_MODULE_1__core_glenum__["a" /* default */].LINE_LOOP; +Mesh.LINE_STRIP = __WEBPACK_IMPORTED_MODULE_1__core_glenum__["a" /* default */].LINE_STRIP; +Mesh.TRIANGLES = __WEBPACK_IMPORTED_MODULE_1__core_glenum__["a" /* default */].TRIANGLES; +Mesh.TRIANGLE_STRIP = __WEBPACK_IMPORTED_MODULE_1__core_glenum__["a" /* default */].TRIANGLE_STRIP; +Mesh.TRIANGLE_FAN = __WEBPACK_IMPORTED_MODULE_1__core_glenum__["a" /* default */].TRIANGLE_FAN; + +Mesh.BACK = __WEBPACK_IMPORTED_MODULE_1__core_glenum__["a" /* default */].BACK; +Mesh.FRONT = __WEBPACK_IMPORTED_MODULE_1__core_glenum__["a" /* default */].FRONT; +Mesh.FRONT_AND_BACK = __WEBPACK_IMPORTED_MODULE_1__core_glenum__["a" /* default */].FRONT_AND_BACK; +Mesh.CW = __WEBPACK_IMPORTED_MODULE_1__core_glenum__["a" /* default */].CW; +Mesh.CCW = __WEBPACK_IMPORTED_MODULE_1__core_glenum__["a" /* default */].CCW; + +/* harmony default export */ __webpack_exports__["a"] = (Mesh); + + +/***/ }), +/* 41 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__Camera__ = __webpack_require__(58); + + +/** + * @constructor clay.camera.Perspective + * @extends clay.Camera + */ +var Perspective = __WEBPACK_IMPORTED_MODULE_0__Camera__["a" /* default */].extend(/** @lends clay.camera.Perspective# */{ + /** + * Vertical field of view in degrees + * @type {number} + */ + fov: 50, + /** + * Aspect ratio, typically viewport width / height + * @type {number} + */ + aspect: 1, + /** + * Near bound of the frustum + * @type {number} + */ + near: 0.1, + /** + * Far bound of the frustum + * @type {number} + */ + far: 2000 +}, +/** @lends clay.camera.Perspective.prototype */ +{ + + updateProjectionMatrix: function() { + var rad = this.fov / 180 * Math.PI; + this.projectionMatrix.perspective(rad, this.aspect, this.near, this.far); + }, + decomposeProjectionMatrix: function () { + var m = this.projectionMatrix.array; + var rad = Math.atan(1 / m[5]) * 2; + this.fov = rad / Math.PI * 180; + this.aspect = m[5] / m[0]; + this.near = m[14] / (m[10] - 1); + this.far = m[14] / (m[10] + 1); + }, + /** + * @return {clay.camera.Perspective} + */ + clone: function() { + var camera = __WEBPACK_IMPORTED_MODULE_0__Camera__["a" /* default */].prototype.clone.call(this); + camera.fov = this.fov; + camera.aspect = this.aspect; + camera.near = this.near; + camera.far = this.far; + + return camera; + } +}); + +/* harmony default export */ __webpack_exports__["a"] = (Perspective); + + +/***/ }), +/* 42 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__Mesh__ = __webpack_require__(40); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__geometry_Cube__ = __webpack_require__(76); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__Shader__ = __webpack_require__(8); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__Material__ = __webpack_require__(19); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4__Texture__ = __webpack_require__(4); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_5__shader_source_skybox_glsl_js__ = __webpack_require__(121); +// TODO Should not derived from mesh? + + + + + + + +__WEBPACK_IMPORTED_MODULE_2__Shader__["a" /* default */].import(__WEBPACK_IMPORTED_MODULE_5__shader_source_skybox_glsl_js__["a" /* default */]); +/** + * @constructor clay.plugin.Skybox + * + * @example + * var skyTex = new clay.TextureCube(); + * skyTex.load({ + * 'px': 'assets/textures/sky/px.jpg', + * 'nx': 'assets/textures/sky/nx.jpg' + * 'py': 'assets/textures/sky/py.jpg' + * 'ny': 'assets/textures/sky/ny.jpg' + * 'pz': 'assets/textures/sky/pz.jpg' + * 'nz': 'assets/textures/sky/nz.jpg' + * }); + * var skybox = new clay.plugin.Skybox({ + * scene: scene + * }); + * skybox.material.set('environmentMap', skyTex); + */ +var Skybox = __WEBPACK_IMPORTED_MODULE_0__Mesh__["a" /* default */].extend(function () { + + var skyboxShader = new __WEBPACK_IMPORTED_MODULE_2__Shader__["a" /* default */]({ + vertex: __WEBPACK_IMPORTED_MODULE_2__Shader__["a" /* default */].source('clay.skybox.vertex'), + fragment: __WEBPACK_IMPORTED_MODULE_2__Shader__["a" /* default */].source('clay.skybox.fragment') + }); + var material = new __WEBPACK_IMPORTED_MODULE_3__Material__["a" /* default */]({ + shader: skyboxShader, + depthMask: false + }); + + return { + /** + * @type {clay.Scene} + * @memberOf clay.plugin.Skybox.prototype + */ + scene: null, + + geometry: new __WEBPACK_IMPORTED_MODULE_1__geometry_Cube__["a" /* default */](), + + material: material, + + environmentMap: null, + + culling: false + }; +}, function () { + var scene = this.scene; + if (scene) { + this.attachScene(scene); + } + if (this.environmentMap) { + this.setEnvironmentMap(this.environmentMap); + } +}, /** @lends clay.plugin.Skybox# */ { + /** + * Attach the skybox to the scene + * @param {clay.Scene} scene + */ + attachScene: function (scene) { + if (this.scene) { + this.detachScene(); + } + scene.skybox = this; + + this.scene = scene; + scene.on('beforerender', this._beforeRenderScene, this); + }, + /** + * Detach from scene + */ + detachScene: function () { + if (this.scene) { + this.scene.off('beforerender', this._beforeRenderScene); + this.scene.skybox = null; + } + this.scene = null; + }, + + /** + * Dispose skybox + * @param {clay.Renderer} renderer + */ + dispose: function (renderer) { + this.detachScene(); + this.geometry.dispose(renderer); + }, + /** + * Set environment map + * @param {clay.TextureCube} envMap + */ + setEnvironmentMap: function (envMap) { + if (envMap.textureType === 'texture2D') { + this.material.define('EQUIRECTANGULAR'); + // LINEAR filter can remove the artifacts in pole + envMap.minFilter = __WEBPACK_IMPORTED_MODULE_4__Texture__["a" /* default */].LINEAR; + } + else { + this.material.undefine('EQUIRECTANGULAR'); + } + this.material.set('environmentMap', envMap); + }, + /** + * Get environment map + * @return {clay.TextureCube} + */ + getEnvironmentMap: function () { + return this.material.get('environmentMap'); + }, + + _beforeRenderScene: function(renderer, scene, camera) { + this.renderSkybox(renderer, camera); + }, + + renderSkybox: function (renderer, camera) { + this.position.copy(camera.getWorldPosition()); + this.update(); + // Don't remember to disable blend + renderer.gl.disable(renderer.gl.BLEND); + if (this.material.get('lod') > 0) { + this.material.define('fragment', 'LOD'); + } + else { + this.material.undefine('fragment', 'LOD'); + } + renderer.renderPass([this], camera); + } +}); + +/* harmony default export */ __webpack_exports__["a"] = (Skybox); + + +/***/ }), +/* 43 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__Geometry__ = __webpack_require__(15); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__math_BoundingBox__ = __webpack_require__(18); + + + +/** + * @constructor clay.geometry.Plane + * @extends clay.Geometry + * @param {Object} [opt] + * @param {number} [opt.widthSegments] + * @param {number} [opt.heightSegments] + */ +var Plane = __WEBPACK_IMPORTED_MODULE_0__Geometry__["a" /* default */].extend( +/** @lends clay.geometry.Plane# */ +{ + dynamic: false, + /** + * @type {number} + */ + widthSegments: 1, + /** + * @type {number} + */ + heightSegments: 1 +}, function() { + this.build(); +}, +/** @lends clay.geometry.Plane.prototype */ +{ + /** + * Build plane geometry + */ + build: function() { + var heightSegments = this.heightSegments; + var widthSegments = this.widthSegments; + var attributes = this.attributes; + var positions = []; + var texcoords = []; + var normals = []; + var faces = []; + + for (var y = 0; y <= heightSegments; y++) { + var t = y / heightSegments; + for (var x = 0; x <= widthSegments; x++) { + var s = x / widthSegments; + + positions.push([2 * s - 1, 2 * t - 1, 0]); + if (texcoords) { + texcoords.push([s, t]); + } + if (normals) { + normals.push([0, 0, 1]); + } + if (x < widthSegments && y < heightSegments) { + var i = x + y * (widthSegments + 1); + faces.push([i, i + 1, i + widthSegments + 1]); + faces.push([i + widthSegments + 1, i + 1, i + widthSegments + 2]); + } + } + } + + attributes.position.fromArray(positions); + attributes.texcoord0.fromArray(texcoords); + attributes.normal.fromArray(normals); + + this.initIndicesFromArray(faces); + + this.boundingBox = new __WEBPACK_IMPORTED_MODULE_1__math_BoundingBox__["a" /* default */](); + this.boundingBox.min.set(-1, -1, 0); + this.boundingBox.max.set(1, 1, 0); + } +}); + +/* harmony default export */ __webpack_exports__["a"] = (Plane); + + +/***/ }), +/* 44 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony default export */ __webpack_exports__["a"] = ({ + defaultOption: { + + viewControl: { + // perspective, orthographic. + // TODO Isometric + projection: 'perspective', + // If rotate on on init + autoRotate: false, + // cw or ccw + autoRotateDirection: 'cw', + // Degree per second + autoRotateSpeed: 10, + + // Start rotating after still for a given time + // default is 3 seconds + autoRotateAfterStill: 3, + + // Rotate, zoom damping. + damping: 0.8, + // Sensitivities for operations. + // Can be array to set x,y respectively + rotateSensitivity: 1, + zoomSensitivity: 1, + // Can be array to set x,y respectively + panSensitivity: 1, + // Which mouse button do rotate or pan + panMouseButton: 'middle', + rotateMouseButton: 'left', + + // Distance to the target + // Only available when camera is perspective. + distance: 150, + // Min distance mouse can zoom in + minDistance: 40, + // Max distance mouse can zoom out + maxDistance: 400, + + // Size of viewing volume. + // Only available when camera is orthographic + orthographicSize: 150, + maxOrthographicSize: 400, + minOrthographicSize: 20, + + // Center view point + center: [0, 0, 0], + // Alpha angle for top-down rotation + // Positive to rotate to top. + alpha: 0, + // beta angle for left-right rotation + // Positive to rotate to right. + beta: 0, + + minAlpha: -90, + maxAlpha: 90 + + // minBeta: -Infinity + // maxBeta: -Infinity + } + }, + + setView: function (opts) { + opts = opts || {}; + this.option.viewControl = this.option.viewControl || {}; + if (opts.alpha != null) { + this.option.viewControl.alpha = opts.alpha; + } + if (opts.beta != null) { + this.option.viewControl.beta = opts.beta; + } + if (opts.distance != null) { + this.option.viewControl.distance = opts.distance; + } + if (opts.center != null) { + this.option.viewControl.center = opts.center; + } + } +}); + +/***/ }), +/* 45 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_claygl_src_core_Base__ = __webpack_require__(7); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_claygl_src_math_Vector2__ = __webpack_require__(26); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2_claygl_src_math_Vector3__ = __webpack_require__(3); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3_claygl_src_math_Quaternion__ = __webpack_require__(56); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4__retrieve__ = __webpack_require__(2); +/** + * Provide orbit control for 3D objects + * + * @module echarts-gl/util/OrbitControl + * @author Yi Shen(http://github.com/pissang) + */ + +// TODO Remove magic numbers on sensitivity + + + + + +var firstNotNull = __WEBPACK_IMPORTED_MODULE_4__retrieve__["a" /* default */].firstNotNull; + + +var MOUSE_BUTTON_KEY_MAP = { + left: 0, + middle: 1, + right: 2 +}; + +function convertToArray(val) { + if (!(val instanceof Array)) { + val = [val, val]; + } + return val; +} + +/** + * @alias module:echarts-x/util/OrbitControl + */ +var OrbitControl = __WEBPACK_IMPORTED_MODULE_0_claygl_src_core_Base__["a" /* default */].extend(function () { + + return { + /** + * @type {module:zrender~ZRender} + */ + zr: null, + + /** + * @type {module:echarts-gl/core/ViewGL} + */ + viewGL: null, + + /** + * @type {clay.math.Vector3} + */ + _center: new __WEBPACK_IMPORTED_MODULE_2_claygl_src_math_Vector3__["a" /* default */](), + + /** + * Minimum distance to the center + * Only available when camera is perspective. + * @type {number} + * @default 0.5 + */ + minDistance: 0.5, + + /** + * Maximum distance to the center + * Only available when camera is perspective. + * @type {number} + * @default 2 + */ + maxDistance: 1.5, + + /** + * Only available when camera is orthographic + */ + maxOrthographicSize: 300, + + /** + * Only available when camera is orthographic + */ + minOrthographicSize: 30, + + /** + * Minimum alpha rotation + */ + minAlpha: -90, + + /** + * Maximum alpha rotation + */ + maxAlpha: 90, + + /** + * Minimum beta rotation + */ + minBeta: -Infinity, + /** + * Maximum beta rotation + */ + maxBeta: Infinity, + + /** + * Start auto rotating after still for the given time + */ + autoRotateAfterStill: 0, + + /** + * Direction of autoRotate. cw or ccw when looking top down. + */ + autoRotateDirection: 'cw', + + /** + * Degree per second + */ + autoRotateSpeed: 60, + + /** + * @param {number} + */ + damping: 0.8, + + /** + * @param {number} + */ + rotateSensitivity: 1, + + /** + * @param {number} + */ + zoomSensitivity: 1, + + /** + * @param {number} + */ + panSensitivity: 1, + + panMouseButton: 'middle', + rotateMouseButton: 'left', + + /** + * Pan or rotate + * @private + * @type {String} + */ + _mode: 'rotate', + + /** + * @private + * @type {clay.Camera} + */ + _camera: null, + + _needsUpdate: false, + + _rotating: false, + + // Rotation around yAxis in radian + _phi: 0, + // Rotation around xAxis in radian + _theta: 0, + + _mouseX: 0, + _mouseY: 0, + + _rotateVelocity: new __WEBPACK_IMPORTED_MODULE_1_claygl_src_math_Vector2__["a" /* default */](), + + _panVelocity: new __WEBPACK_IMPORTED_MODULE_1_claygl_src_math_Vector2__["a" /* default */](), + + _distance: 500, + + _zoomSpeed: 0, + + _stillTimeout: 0, + + _animators: [] + }; +}, function () { + // Each OrbitControl has it's own handler + ['_mouseDownHandler', '_mouseWheelHandler', '_mouseMoveHandler', '_mouseUpHandler', + '_pinchHandler', '_contextMenuHandler', '_update'].forEach(function (hdlName) { + this[hdlName] = this[hdlName].bind(this); + }, this); +}, { + /** + * Initialize. + * Mouse event binding + */ + init: function () { + var zr = this.zr; + + if (zr) { + zr.on('mousedown', this._mouseDownHandler); + zr.on('globalout', this._mouseUpHandler); + zr.on('mousewheel', this._mouseWheelHandler); + zr.on('pinch', this._pinchHandler); + + zr.animation.on('frame', this._update); + + zr.dom.addEventListener('contextmenu', this._contextMenuHandler); + } + }, + + /** + * Dispose. + * Mouse event unbinding + */ + dispose: function () { + var zr = this.zr; + + if (zr) { + zr.off('mousedown', this._mouseDownHandler); + zr.off('mousemove', this._mouseMoveHandler); + zr.off('mouseup', this._mouseUpHandler); + zr.off('mousewheel', this._mouseWheelHandler); + zr.off('pinch', this._pinchHandler); + zr.off('globalout', this._mouseUpHandler); + zr.dom.removeEventListener('contextmenu', this._contextMenuHandler); + + zr.animation.off('frame', this._update); + } + this.stopAllAnimation(); + }, + + /** + * Get distance + * @return {number} + */ + getDistance: function () { + return this._distance; + }, + + /** + * Set distance + * @param {number} distance + */ + setDistance: function (distance) { + this._distance = distance; + this._needsUpdate = true; + }, + + /** + * Get size of orthographic viewing volume + * @return {number} + */ + getOrthographicSize: function () { + return this._orthoSize; + }, + + /** + * Set size of orthographic viewing volume + * @param {number} size + */ + setOrthographicSize: function (size) { + this._orthoSize = size; + this._needsUpdate = true; + }, + + /** + * Get alpha rotation + * Alpha angle for top-down rotation. Positive to rotate to top. + * + * Which means camera rotation around x axis. + */ + getAlpha: function () { + return this._theta / Math.PI * 180; + }, + + /** + * Get beta rotation + * Beta angle for left-right rotation. Positive to rotate to right. + * + * Which means camera rotation around y axis. + */ + getBeta: function () { + return -this._phi / Math.PI * 180; + }, + + /** + * Get control center + * @return {Array.} + */ + getCenter: function () { + return this._center.toArray(); + }, + + /** + * Set alpha rotation angle + * @param {number} alpha + */ + setAlpha: function (alpha) { + alpha = Math.max(Math.min(this.maxAlpha, alpha), this.minAlpha); + + this._theta = alpha / 180 * Math.PI; + this._needsUpdate = true; + }, + + /** + * Set beta rotation angle + * @param {number} beta + */ + setBeta: function (beta) { + beta = Math.max(Math.min(this.maxBeta, beta), this.minBeta); + + this._phi = -beta / 180 * Math.PI; + this._needsUpdate = true; + }, + + /** + * Set control center + * @param {Array.} center + */ + setCenter: function (centerArr) { + this._center.setArray(centerArr); + }, + + /** + * @param {module:echarts-gl/core/ViewGL} viewGL + */ + setViewGL: function (viewGL) { + this.viewGL = viewGL; + }, + + /** + * @return {clay.Camera} + */ + getCamera: function () { + return this.viewGL.camera; + }, + + setFromViewControlModel: function (viewControlModel, extraOpts) { + extraOpts = extraOpts || {}; + var baseDistance = extraOpts.baseDistance || 0; + var baseOrthoSize = extraOpts.baseOrthoSize || 1; + + var projection = viewControlModel.get('projection'); + if (projection !== 'perspective' && projection !== 'orthographic' && projection !== 'isometric') { + if (true) { + console.error('Unkown projection type %s, use perspective projection instead.', projection); + } + projection = 'perspective'; + } + this._projection = projection; + this.viewGL.setProjection(projection); + + var targetDistance = viewControlModel.get('distance') + baseDistance; + var targetOrthographicSize = viewControlModel.get('orthographicSize') + baseOrthoSize; + + [ + ['damping', 0.8], + ['autoRotate', false], + ['autoRotateAfterStill', 3], + ['autoRotateDirection', 'cw'], + ['autoRotateSpeed', 10], + ['minDistance', 30], + ['maxDistance', 400], + ['minOrthographicSize', 30], + ['maxOrthographicSize', 300], + ['minAlpha', -90], + ['maxAlpha', 90], + ['minBeta', -Infinity], + ['maxBeta', Infinity], + ['rotateSensitivity', 1], + ['zoomSensitivity', 1], + ['panSensitivity', 1], + ['panMouseButton', 'left'], + ['rotateMouseButton', 'middle'], + ].forEach(function (prop) { + this[prop[0]] = firstNotNull(viewControlModel.get(prop[0]), prop[1]); + }, this); + + this.minDistance += baseDistance; + this.maxDistance += baseDistance; + this.minOrthographicSize += baseOrthoSize, + this.maxOrthographicSize += baseOrthoSize; + + var ecModel = viewControlModel.ecModel; + + var animationOpts = {}; + ['animation', 'animationDurationUpdate', 'animationEasingUpdate'].forEach(function (key) { + animationOpts[key] = firstNotNull( + viewControlModel.get(key), ecModel && ecModel.get(key) + ); + }); + + var alpha = firstNotNull(extraOpts.alpha, viewControlModel.get('alpha')) || 0; + var beta = firstNotNull(extraOpts.beta, viewControlModel.get('beta')) || 0; + var center = firstNotNull(extraOpts.center, viewControlModel.get('center')) || [0, 0, 0]; + if (animationOpts.animation && animationOpts.animationDurationUpdate > 0 && this._notFirst) { + this.animateTo({ + alpha: alpha, + beta: beta, + center: center, + distance: targetDistance, + targetOrthographicSize: targetOrthographicSize, + easing: animationOpts.animationEasingUpdate, + duration: animationOpts.animationDurationUpdate + }); + } + else { + this.setDistance(targetDistance); + this.setAlpha(alpha); + this.setBeta(beta); + this.setCenter(center); + this.setOrthographicSize(targetOrthographicSize); + } + + this._notFirst = true; + + this._validateProperties(); + }, + + _validateProperties: function () { + if (true) { + if (MOUSE_BUTTON_KEY_MAP[this.panMouseButton] == null) { + console.error('Unkown panMouseButton %s. It should be left|middle|right', this.panMouseButton); + } + if (MOUSE_BUTTON_KEY_MAP[this.rotateMouseButton] == null) { + console.error('Unkown rotateMouseButton %s. It should be left|middle|right', this.rotateMouseButton); + } + if (this.autoRotateDirection !== 'cw' && this.autoRotateDirection !== 'ccw') { + console.error('Unkown autoRotateDirection %s. It should be cw|ccw', this.autoRotateDirection); + } + } + }, + + /** + * @param {Object} opts + * @param {number} opts.distance + * @param {number} opts.alpha + * @param {number} opts.beta + * @param {number} opts.orthographicSize + * @param {number} [opts.duration=1000] + * @param {number} [opts.easing='linear'] + */ + animateTo: function (opts) { + var zr = this.zr; + var self = this; + + var obj = {}; + var target = {}; + + if (opts.distance != null) { + obj.distance = this.getDistance(); + target.distance = opts.distance; + } + if (opts.orthographicSize != null) { + obj.orthographicSize = this.getOrthographicSize(); + target.orthographicSize = opts.orthographicSize; + } + if (opts.alpha != null) { + obj.alpha = this.getAlpha(); + target.alpha = opts.alpha; + } + if (opts.beta != null) { + obj.beta = this.getBeta(); + target.beta = opts.beta; + } + if (opts.center != null) { + obj.center = this.getCenter(); + target.center = opts.center; + } + + return this._addAnimator( + zr.animation.animate(obj) + .when(opts.duration || 1000, target) + .during(function () { + if (obj.alpha != null) { + self.setAlpha(obj.alpha); + } + if (obj.beta != null) { + self.setBeta(obj.beta); + } + if (obj.distance != null) { + self.setDistance(obj.distance); + } + if (obj.center != null) { + self.setCenter(obj.center); + } + if (obj.orthographicSize != null) { + self.setOrthographicSize(obj.orthographicSize); + } + self._needsUpdate = true; + }) + ).start(opts.easing || 'linear'); + }, + + /** + * Stop all animation + */ + stopAllAnimation: function () { + for (var i = 0; i < this._animators.length; i++) { + this._animators[i].stop(); + } + this._animators.length = 0; + }, + + update: function () { + this._needsUpdate = true; + this._update(20); + }, + + _isAnimating: function () { + return this._animators.length > 0; + }, + /** + * Call update each frame + * @param {number} deltaTime Frame time + */ + _update: function (deltaTime) { + + if (this._rotating) { + var radian = (this.autoRotateDirection === 'cw' ? 1 : -1) + * this.autoRotateSpeed / 180 * Math.PI; + this._phi -= radian * deltaTime / 1000; + this._needsUpdate = true; + } + else if (this._rotateVelocity.len() > 0) { + this._needsUpdate = true; + } + + if (Math.abs(this._zoomSpeed) > 0.1 || this._panVelocity.len() > 0) { + this._needsUpdate = true; + } + + if (!this._needsUpdate) { + return; + } + + deltaTime = Math.min(deltaTime, 50); + + this._updateDistanceOrSize(deltaTime); + + this._updatePan(deltaTime); + + this._updateRotate(deltaTime); + + this._updateTransform(); + + this.getCamera().update(); + + this.zr && this.zr.refresh(); + + this.trigger('update'); + + this._needsUpdate = false; + }, + + _updateRotate: function (deltaTime) { + var velocity = this._rotateVelocity; + this._phi = velocity.y * deltaTime / 20 + this._phi; + this._theta = velocity.x * deltaTime / 20 + this._theta; + + this.setAlpha(this.getAlpha()); + this.setBeta(this.getBeta()); + + this._vectorDamping(velocity, Math.pow(this.damping, deltaTime / 16)); + }, + + _updateDistanceOrSize: function (deltaTime) { + if (this._projection === 'perspective') { + this._setDistance(this._distance + this._zoomSpeed * deltaTime / 20); + } + else { + this._setOrthoSize(this._orthoSize + this._zoomSpeed * deltaTime / 20); + } + + this._zoomSpeed *= Math.pow(this.damping, deltaTime / 16); + }, + + + _setDistance: function (distance) { + this._distance = Math.max(Math.min(distance, this.maxDistance), this.minDistance); + }, + + _setOrthoSize: function (size) { + this._orthoSize = Math.max(Math.min(size, this.maxOrthographicSize), this.minOrthographicSize); + var camera = this.getCamera(); + var cameraHeight = this._orthoSize; + var cameraWidth = cameraHeight / this.viewGL.viewport.height * this.viewGL.viewport.width; + camera.left = -cameraWidth / 2; + camera.right = cameraWidth / 2; + camera.top = cameraHeight / 2; + camera.bottom = -cameraHeight / 2; + }, + + _updatePan: function (deltaTime) { + + var velocity = this._panVelocity; + var len = this._distance; + + var target = this.getCamera(); + var yAxis = target.worldTransform.y; + var xAxis = target.worldTransform.x; + + // PENDING + this._center + .scaleAndAdd(xAxis, -velocity.x * len / 200) + .scaleAndAdd(yAxis, -velocity.y * len / 200); + + this._vectorDamping(velocity, 0); + }, + + _updateTransform: function () { + var camera = this.getCamera(); + + var dir = new __WEBPACK_IMPORTED_MODULE_2_claygl_src_math_Vector3__["a" /* default */](); + var theta = this._theta + Math.PI / 2; + var phi = this._phi + Math.PI / 2; + var r = Math.sin(theta); + + dir.x = r * Math.cos(phi); + dir.y = -Math.cos(theta); + dir.z = r * Math.sin(phi); + + camera.position.copy(this._center).scaleAndAdd(dir, this._distance); + camera.rotation.identity() + // First around y, then around x + .rotateY(-this._phi) + .rotateX(-this._theta); + }, + + _startCountingStill: function () { + clearTimeout(this._stillTimeout); + + var time = this.autoRotateAfterStill; + var self = this; + if (!isNaN(time) && time > 0) { + this._stillTimeout = setTimeout(function () { + self._rotating = true; + }, time * 1000); + } + }, + + _vectorDamping: function (v, damping) { + var speed = v.len(); + speed = speed * damping; + if (speed < 1e-4) { + speed = 0; + } + v.normalize().scale(speed); + }, + + _decomposeTransform: function () { + if (!this.getCamera()) { + return; + } + + this.getCamera().updateWorldTransform(); + + var forward = this.getCamera().worldTransform.z; + var alpha = Math.asin(forward.y); + var beta = Math.atan2(forward.x, forward.z); + + this._theta = alpha; + this._phi = -beta; + + this.setBeta(this.getBeta()); + this.setAlpha(this.getAlpha()); + + // Is perspective + if (this.getCamera().aspect) { + this._setDistance(this.getCamera().position.dist(this._center)); + } + else { + this._setOrthoSize(this.getCamera().top - this.getCamera().bottom); + } + }, + + _mouseDownHandler: function (e) { + if (e.target) { + // If mouseon some zrender element. + return; + } + if (this._isAnimating()) { + return; + } + + var x = e.offsetX; + var y = e.offsetY; + if (this.viewGL && !this.viewGL.containPoint(x, y)) { + return; + } + + this.zr.on('mousemove', this._mouseMoveHandler); + this.zr.on('mouseup', this._mouseUpHandler); + + if (e.event.targetTouches) { + if (e.event.targetTouches.length === 1) { + this._mode = 'rotate'; + } + } + else { + if (e.event.button === MOUSE_BUTTON_KEY_MAP[this.rotateMouseButton]) { + this._mode = 'rotate'; + } + else if (e.event.button === MOUSE_BUTTON_KEY_MAP[this.panMouseButton]) { + this._mode = 'pan'; + } + else { + this._mode = ''; + } + } + + // Reset rotate velocity + this._rotateVelocity.set(0, 0); + this._rotating = false; + if (this.autoRotate) { + this._startCountingStill(); + } + + this._mouseX = e.offsetX; + this._mouseY = e.offsetY; + }, + + _mouseMoveHandler: function (e) { + if (e.target && e.target.__isGLToZRProxy) { + return; + } + + if (this._isAnimating()) { + return; + } + + var panSensitivity = convertToArray(this.panSensitivity); + var rotateSensitivity = convertToArray(this.rotateSensitivity); + + if (this._mode === 'rotate') { + this._rotateVelocity.y = (e.offsetX - this._mouseX) / this.zr.getHeight() * 2 * rotateSensitivity[0]; + this._rotateVelocity.x = (e.offsetY - this._mouseY) / this.zr.getWidth() * 2 * rotateSensitivity[1]; + } + else if (this._mode === 'pan') { + this._panVelocity.x = (e.offsetX - this._mouseX) / this.zr.getWidth() * panSensitivity[0] * 400; + this._panVelocity.y = (-e.offsetY + this._mouseY) / this.zr.getHeight() * panSensitivity[1] * 400; + } + + + this._mouseX = e.offsetX; + this._mouseY = e.offsetY; + + e.event.preventDefault(); + }, + + _mouseWheelHandler: function (e) { + if (this._isAnimating()) { + return; + } + var delta = e.event.wheelDelta // Webkit + || -e.event.detail; // Firefox + this._zoomHandler(e, delta); + }, + + _pinchHandler: function (e) { + if (this._isAnimating()) { + return; + } + this._zoomHandler(e, e.pinchScale > 1 ? 1 : -1); + // Not rotate when pinch + this._mode = ''; + }, + + _zoomHandler: function (e, delta) { + if (delta === 0) { + return; + } + + var x = e.offsetX; + var y = e.offsetY; + if (this.viewGL && !this.viewGL.containPoint(x, y)) { + return; + } + + var speed; + if (this._projection === 'perspective') { + speed = Math.max(Math.max(Math.min( + this._distance - this.minDistance, + this.maxDistance - this._distance + )) / 20, 0.5); + } + else { + speed = Math.max(Math.max(Math.min( + this._orthoSize - this.minOrthographicSize, + this.maxOrthographicSize - this._orthoSize + )) / 20, 0.5); + } + this._zoomSpeed = (delta > 0 ? -1 : 1) * speed * this.zoomSensitivity; + + this._rotating = false; + + if (this.autoRotate && this._mode === 'rotate') { + this._startCountingStill(); + } + + e.event.preventDefault(); + }, + + _mouseUpHandler: function () { + this.zr.off('mousemove', this._mouseMoveHandler); + this.zr.off('mouseup', this._mouseUpHandler); + }, + + _isRightMouseButtonUsed: function () { + return this.rotateMouseButton === 'right' + || this.panMouseButton === 'right'; + }, + + _contextMenuHandler: function (e) { + if (this._isRightMouseButtonUsed()) { + e.preventDefault(); + } + }, + + _addAnimator: function (animator) { + var animators = this._animators; + animators.push(animator); + animator.done(function () { + var idx = animators.indexOf(animator); + if (idx >= 0) { + animators.splice(idx, 1); + } + }); + return animator; + } +}); + +/** + * If auto rotate the target + * @type {boolean} + * @default false + */ +Object.defineProperty(OrbitControl.prototype, 'autoRotate', { + get: function (val) { + return this._autoRotate; + }, + set: function (val) { + this._autoRotate = val; + this._rotating = val; + } +}); + + +/* harmony default export */ __webpack_exports__["a"] = (OrbitControl); + +/***/ }), +/* 46 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony default export */ __webpack_exports__["a"] = ("@export ecgl.lines3D.vertex\n\nuniform mat4 worldViewProjection : WORLDVIEWPROJECTION;\n\nattribute vec3 position: POSITION;\nattribute vec4 a_Color : COLOR;\nvarying vec4 v_Color;\n\nvoid main()\n{\n gl_Position = worldViewProjection * vec4(position, 1.0);\n v_Color = a_Color;\n}\n\n@end\n\n@export ecgl.lines3D.fragment\n\nuniform vec4 color : [1.0, 1.0, 1.0, 1.0];\n\nvarying vec4 v_Color;\n\n@import clay.util.srgb\n\nvoid main()\n{\n#ifdef SRGB_DECODE\n gl_FragColor = sRGBToLinear(color * v_Color);\n#else\n gl_FragColor = color * v_Color;\n#endif\n}\n@end\n\n\n\n@export ecgl.lines3D.clipNear\n\nvec4 clipNear(vec4 p1, vec4 p2) {\n float n = (p1.w - near) / (p1.w - p2.w);\n return vec4(mix(p1.xy, p2.xy, n), -near, near);\n}\n\n@end\n\n@export ecgl.lines3D.expandLine\n#ifdef VERTEX_ANIMATION\n vec4 prevProj = worldViewProjection * vec4(mix(prevPositionPrev, positionPrev, percent), 1.0);\n vec4 currProj = worldViewProjection * vec4(mix(prevPosition, position, percent), 1.0);\n vec4 nextProj = worldViewProjection * vec4(mix(prevPositionNext, positionNext, percent), 1.0);\n#else\n vec4 prevProj = worldViewProjection * vec4(positionPrev, 1.0);\n vec4 currProj = worldViewProjection * vec4(position, 1.0);\n vec4 nextProj = worldViewProjection * vec4(positionNext, 1.0);\n#endif\n\n if (currProj.w < 0.0) {\n if (nextProj.w > 0.0) {\n currProj = clipNear(currProj, nextProj);\n }\n else if (prevProj.w > 0.0) {\n currProj = clipNear(currProj, prevProj);\n }\n }\n\n vec2 prevScreen = (prevProj.xy / abs(prevProj.w) + 1.0) * 0.5 * viewport.zw;\n vec2 currScreen = (currProj.xy / abs(currProj.w) + 1.0) * 0.5 * viewport.zw;\n vec2 nextScreen = (nextProj.xy / abs(nextProj.w) + 1.0) * 0.5 * viewport.zw;\n\n vec2 dir;\n float len = offset;\n if (position == positionPrev) {\n dir = normalize(nextScreen - currScreen);\n }\n else if (position == positionNext) {\n dir = normalize(currScreen - prevScreen);\n }\n else {\n vec2 dirA = normalize(currScreen - prevScreen);\n vec2 dirB = normalize(nextScreen - currScreen);\n\n vec2 tanget = normalize(dirA + dirB);\n\n float miter = 1.0 / max(dot(tanget, dirA), 0.5);\n len *= miter;\n dir = tanget;\n }\n\n dir = vec2(-dir.y, dir.x) * len;\n currScreen += dir;\n\n currProj.xy = (currScreen / viewport.zw - 0.5) * 2.0 * abs(currProj.w);\n@end\n\n\n@export ecgl.meshLines3D.vertex\n\nattribute vec3 position: POSITION;\nattribute vec3 positionPrev;\nattribute vec3 positionNext;\nattribute float offset;\nattribute vec4 a_Color : COLOR;\n\n#ifdef VERTEX_ANIMATION\nattribute vec3 prevPosition;\nattribute vec3 prevPositionPrev;\nattribute vec3 prevPositionNext;\nuniform float percent : 1.0;\n#endif\n\nuniform mat4 worldViewProjection : WORLDVIEWPROJECTION;\nuniform vec4 viewport : VIEWPORT;\nuniform float near : NEAR;\n\nvarying vec4 v_Color;\n\n@import ecgl.common.wireframe.vertexHeader\n\n@import ecgl.lines3D.clipNear\n\nvoid main()\n{\n @import ecgl.lines3D.expandLine\n\n gl_Position = currProj;\n\n v_Color = a_Color;\n\n @import ecgl.common.wireframe.vertexMain\n}\n@end\n\n\n@export ecgl.meshLines3D.fragment\n\nuniform vec4 color : [1.0, 1.0, 1.0, 1.0];\n\nvarying vec4 v_Color;\n\n@import ecgl.common.wireframe.fragmentHeader\n\n@import clay.util.srgb\n\nvoid main()\n{\n#ifdef SRGB_DECODE\n gl_FragColor = sRGBToLinear(color * v_Color);\n#else\n gl_FragColor = color * v_Color;\n#endif\n\n @import ecgl.common.wireframe.fragmentMain\n}\n\n@end"); + + +/***/ }), +/* 47 */ +/***/ (function(module, exports, __webpack_require__) { + +var zrUtil = __webpack_require__(13); + +var BoundingRect = __webpack_require__(82); + +var _number = __webpack_require__(85); + +var parsePercent = _number.parsePercent; + +var formatUtil = __webpack_require__(171); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ +// Layout helpers for each component positioning +var each = zrUtil.each; +/** + * @public + */ + +var LOCATION_PARAMS = ['left', 'right', 'top', 'bottom', 'width', 'height']; +/** + * @public + */ + +var HV_NAMES = [['width', 'left', 'right'], ['height', 'top', 'bottom']]; + +function boxLayout(orient, group, gap, maxWidth, maxHeight) { + var x = 0; + var y = 0; + + if (maxWidth == null) { + maxWidth = Infinity; + } + + if (maxHeight == null) { + maxHeight = Infinity; + } + + var currentLineMaxSize = 0; + group.eachChild(function (child, idx) { + var position = child.position; + var rect = child.getBoundingRect(); + var nextChild = group.childAt(idx + 1); + var nextChildRect = nextChild && nextChild.getBoundingRect(); + var nextX; + var nextY; + + if (orient === 'horizontal') { + var moveX = rect.width + (nextChildRect ? -nextChildRect.x + rect.x : 0); + nextX = x + moveX; // Wrap when width exceeds maxWidth or meet a `newline` group + // FIXME compare before adding gap? + + if (nextX > maxWidth || child.newline) { + x = 0; + nextX = moveX; + y += currentLineMaxSize + gap; + currentLineMaxSize = rect.height; + } else { + // FIXME: consider rect.y is not `0`? + currentLineMaxSize = Math.max(currentLineMaxSize, rect.height); + } + } else { + var moveY = rect.height + (nextChildRect ? -nextChildRect.y + rect.y : 0); + nextY = y + moveY; // Wrap when width exceeds maxHeight or meet a `newline` group + + if (nextY > maxHeight || child.newline) { + x += currentLineMaxSize + gap; + y = 0; + nextY = moveY; + currentLineMaxSize = rect.width; + } else { + currentLineMaxSize = Math.max(currentLineMaxSize, rect.width); + } + } + + if (child.newline) { + return; + } + + position[0] = x; + position[1] = y; + orient === 'horizontal' ? x = nextX + gap : y = nextY + gap; + }); +} +/** + * VBox or HBox layouting + * @param {string} orient + * @param {module:zrender/container/Group} group + * @param {number} gap + * @param {number} [width=Infinity] + * @param {number} [height=Infinity] + */ + + +var box = boxLayout; +/** + * VBox layouting + * @param {module:zrender/container/Group} group + * @param {number} gap + * @param {number} [width=Infinity] + * @param {number} [height=Infinity] + */ + +var vbox = zrUtil.curry(boxLayout, 'vertical'); +/** + * HBox layouting + * @param {module:zrender/container/Group} group + * @param {number} gap + * @param {number} [width=Infinity] + * @param {number} [height=Infinity] + */ + +var hbox = zrUtil.curry(boxLayout, 'horizontal'); +/** + * If x or x2 is not specified or 'center' 'left' 'right', + * the width would be as long as possible. + * If y or y2 is not specified or 'middle' 'top' 'bottom', + * the height would be as long as possible. + * + * @param {Object} positionInfo + * @param {number|string} [positionInfo.x] + * @param {number|string} [positionInfo.y] + * @param {number|string} [positionInfo.x2] + * @param {number|string} [positionInfo.y2] + * @param {Object} containerRect {width, height} + * @param {string|number} margin + * @return {Object} {width, height} + */ + +function getAvailableSize(positionInfo, containerRect, margin) { + var containerWidth = containerRect.width; + var containerHeight = containerRect.height; + var x = parsePercent(positionInfo.x, containerWidth); + var y = parsePercent(positionInfo.y, containerHeight); + var x2 = parsePercent(positionInfo.x2, containerWidth); + var y2 = parsePercent(positionInfo.y2, containerHeight); + (isNaN(x) || isNaN(parseFloat(positionInfo.x))) && (x = 0); + (isNaN(x2) || isNaN(parseFloat(positionInfo.x2))) && (x2 = containerWidth); + (isNaN(y) || isNaN(parseFloat(positionInfo.y))) && (y = 0); + (isNaN(y2) || isNaN(parseFloat(positionInfo.y2))) && (y2 = containerHeight); + margin = formatUtil.normalizeCssArray(margin || 0); + return { + width: Math.max(x2 - x - margin[1] - margin[3], 0), + height: Math.max(y2 - y - margin[0] - margin[2], 0) + }; +} +/** + * Parse position info. + * + * @param {Object} positionInfo + * @param {number|string} [positionInfo.left] + * @param {number|string} [positionInfo.top] + * @param {number|string} [positionInfo.right] + * @param {number|string} [positionInfo.bottom] + * @param {number|string} [positionInfo.width] + * @param {number|string} [positionInfo.height] + * @param {number|string} [positionInfo.aspect] Aspect is width / height + * @param {Object} containerRect + * @param {string|number} [margin] + * + * @return {module:zrender/core/BoundingRect} + */ + + +function getLayoutRect(positionInfo, containerRect, margin) { + margin = formatUtil.normalizeCssArray(margin || 0); + var containerWidth = containerRect.width; + var containerHeight = containerRect.height; + var left = parsePercent(positionInfo.left, containerWidth); + var top = parsePercent(positionInfo.top, containerHeight); + var right = parsePercent(positionInfo.right, containerWidth); + var bottom = parsePercent(positionInfo.bottom, containerHeight); + var width = parsePercent(positionInfo.width, containerWidth); + var height = parsePercent(positionInfo.height, containerHeight); + var verticalMargin = margin[2] + margin[0]; + var horizontalMargin = margin[1] + margin[3]; + var aspect = positionInfo.aspect; // If width is not specified, calculate width from left and right + + if (isNaN(width)) { + width = containerWidth - right - horizontalMargin - left; + } + + if (isNaN(height)) { + height = containerHeight - bottom - verticalMargin - top; + } + + if (aspect != null) { + // If width and height are not given + // 1. Graph should not exceeds the container + // 2. Aspect must be keeped + // 3. Graph should take the space as more as possible + // FIXME + // Margin is not considered, because there is no case that both + // using margin and aspect so far. + if (isNaN(width) && isNaN(height)) { + if (aspect > containerWidth / containerHeight) { + width = containerWidth * 0.8; + } else { + height = containerHeight * 0.8; + } + } // Calculate width or height with given aspect + + + if (isNaN(width)) { + width = aspect * height; + } + + if (isNaN(height)) { + height = width / aspect; + } + } // If left is not specified, calculate left from right and width + + + if (isNaN(left)) { + left = containerWidth - right - width - horizontalMargin; + } + + if (isNaN(top)) { + top = containerHeight - bottom - height - verticalMargin; + } // Align left and top + + + switch (positionInfo.left || positionInfo.right) { + case 'center': + left = containerWidth / 2 - width / 2 - margin[3]; + break; + + case 'right': + left = containerWidth - width - horizontalMargin; + break; + } + + switch (positionInfo.top || positionInfo.bottom) { + case 'middle': + case 'center': + top = containerHeight / 2 - height / 2 - margin[0]; + break; + + case 'bottom': + top = containerHeight - height - verticalMargin; + break; + } // If something is wrong and left, top, width, height are calculated as NaN + + + left = left || 0; + top = top || 0; + + if (isNaN(width)) { + // Width may be NaN if only one value is given except width + width = containerWidth - horizontalMargin - left - (right || 0); + } + + if (isNaN(height)) { + // Height may be NaN if only one value is given except height + height = containerHeight - verticalMargin - top - (bottom || 0); + } + + var rect = new BoundingRect(left + margin[3], top + margin[0], width, height); + rect.margin = margin; + return rect; +} +/** + * Position a zr element in viewport + * Group position is specified by either + * {left, top}, {right, bottom} + * If all properties exists, right and bottom will be igonred. + * + * Logic: + * 1. Scale (against origin point in parent coord) + * 2. Rotate (against origin point in parent coord) + * 3. Traslate (with el.position by this method) + * So this method only fixes the last step 'Traslate', which does not affect + * scaling and rotating. + * + * If be called repeatly with the same input el, the same result will be gotten. + * + * @param {module:zrender/Element} el Should have `getBoundingRect` method. + * @param {Object} positionInfo + * @param {number|string} [positionInfo.left] + * @param {number|string} [positionInfo.top] + * @param {number|string} [positionInfo.right] + * @param {number|string} [positionInfo.bottom] + * @param {number|string} [positionInfo.width] Only for opt.boundingModel: 'raw' + * @param {number|string} [positionInfo.height] Only for opt.boundingModel: 'raw' + * @param {Object} containerRect + * @param {string|number} margin + * @param {Object} [opt] + * @param {Array.} [opt.hv=[1,1]] Only horizontal or only vertical. + * @param {Array.} [opt.boundingMode='all'] + * Specify how to calculate boundingRect when locating. + * 'all': Position the boundingRect that is transformed and uioned + * both itself and its descendants. + * This mode simplies confine the elements in the bounding + * of their container (e.g., using 'right: 0'). + * 'raw': Position the boundingRect that is not transformed and only itself. + * This mode is useful when you want a element can overflow its + * container. (Consider a rotated circle needs to be located in a corner.) + * In this mode positionInfo.width/height can only be number. + */ + + +function positionElement(el, positionInfo, containerRect, margin, opt) { + var h = !opt || !opt.hv || opt.hv[0]; + var v = !opt || !opt.hv || opt.hv[1]; + var boundingMode = opt && opt.boundingMode || 'all'; + + if (!h && !v) { + return; + } + + var rect; + + if (boundingMode === 'raw') { + rect = el.type === 'group' ? new BoundingRect(0, 0, +positionInfo.width || 0, +positionInfo.height || 0) : el.getBoundingRect(); + } else { + rect = el.getBoundingRect(); + + if (el.needLocalTransform()) { + var transform = el.getLocalTransform(); // Notice: raw rect may be inner object of el, + // which should not be modified. + + rect = rect.clone(); + rect.applyTransform(transform); + } + } // The real width and height can not be specified but calculated by the given el. + + + positionInfo = getLayoutRect(zrUtil.defaults({ + width: rect.width, + height: rect.height + }, positionInfo), containerRect, margin); // Because 'tranlate' is the last step in transform + // (see zrender/core/Transformable#getLocalTransform), + // we can just only modify el.position to get final result. + + var elPos = el.position; + var dx = h ? positionInfo.x - rect.x : 0; + var dy = v ? positionInfo.y - rect.y : 0; + el.attr('position', boundingMode === 'raw' ? [dx, dy] : [elPos[0] + dx, elPos[1] + dy]); +} +/** + * @param {Object} option Contains some of the properties in HV_NAMES. + * @param {number} hvIdx 0: horizontal; 1: vertical. + */ + + +function sizeCalculable(option, hvIdx) { + return option[HV_NAMES[hvIdx][0]] != null || option[HV_NAMES[hvIdx][1]] != null && option[HV_NAMES[hvIdx][2]] != null; +} +/** + * Consider Case: + * When defulat option has {left: 0, width: 100}, and we set {right: 0} + * through setOption or media query, using normal zrUtil.merge will cause + * {right: 0} does not take effect. + * + * @example + * ComponentModel.extend({ + * init: function () { + * ... + * var inputPositionParams = layout.getLayoutParams(option); + * this.mergeOption(inputPositionParams); + * }, + * mergeOption: function (newOption) { + * newOption && zrUtil.merge(thisOption, newOption, true); + * layout.mergeLayoutParam(thisOption, newOption); + * } + * }); + * + * @param {Object} targetOption + * @param {Object} newOption + * @param {Object|string} [opt] + * @param {boolean|Array.} [opt.ignoreSize=false] Used for the components + * that width (or height) should not be calculated by left and right (or top and bottom). + */ + + +function mergeLayoutParam(targetOption, newOption, opt) { + !zrUtil.isObject(opt) && (opt = {}); + var ignoreSize = opt.ignoreSize; + !zrUtil.isArray(ignoreSize) && (ignoreSize = [ignoreSize, ignoreSize]); + var hResult = merge(HV_NAMES[0], 0); + var vResult = merge(HV_NAMES[1], 1); + copy(HV_NAMES[0], targetOption, hResult); + copy(HV_NAMES[1], targetOption, vResult); + + function merge(names, hvIdx) { + var newParams = {}; + var newValueCount = 0; + var merged = {}; + var mergedValueCount = 0; + var enoughParamNumber = 2; + each(names, function (name) { + merged[name] = targetOption[name]; + }); + each(names, function (name) { + // Consider case: newOption.width is null, which is + // set by user for removing width setting. + hasProp(newOption, name) && (newParams[name] = merged[name] = newOption[name]); + hasValue(newParams, name) && newValueCount++; + hasValue(merged, name) && mergedValueCount++; + }); + + if (ignoreSize[hvIdx]) { + // Only one of left/right is premitted to exist. + if (hasValue(newOption, names[1])) { + merged[names[2]] = null; + } else if (hasValue(newOption, names[2])) { + merged[names[1]] = null; + } + + return merged; + } // Case: newOption: {width: ..., right: ...}, + // or targetOption: {right: ...} and newOption: {width: ...}, + // There is no conflict when merged only has params count + // little than enoughParamNumber. + + + if (mergedValueCount === enoughParamNumber || !newValueCount) { + return merged; + } // Case: newOption: {width: ..., right: ...}, + // Than we can make sure user only want those two, and ignore + // all origin params in targetOption. + else if (newValueCount >= enoughParamNumber) { + return newParams; + } else { + // Chose another param from targetOption by priority. + for (var i = 0; i < names.length; i++) { + var name = names[i]; + + if (!hasProp(newParams, name) && hasProp(targetOption, name)) { + newParams[name] = targetOption[name]; + break; + } + } + + return newParams; + } + } + + function hasProp(obj, name) { + return obj.hasOwnProperty(name); + } + + function hasValue(obj, name) { + return obj[name] != null && obj[name] !== 'auto'; + } + + function copy(names, target, source) { + each(names, function (name) { + target[name] = source[name]; + }); + } +} +/** + * Retrieve 'left', 'right', 'top', 'bottom', 'width', 'height' from object. + * @param {Object} source + * @return {Object} Result contains those props. + */ + + +function getLayoutParams(source) { + return copyLayoutParams({}, source); +} +/** + * Retrieve 'left', 'right', 'top', 'bottom', 'width', 'height' from object. + * @param {Object} source + * @return {Object} Result contains those props. + */ + + +function copyLayoutParams(target, source) { + source && target && each(LOCATION_PARAMS, function (name) { + source.hasOwnProperty(name) && (target[name] = source[name]); + }); + return target; +} + +exports.LOCATION_PARAMS = LOCATION_PARAMS; +exports.HV_NAMES = HV_NAMES; +exports.box = box; +exports.vbox = vbox; +exports.hbox = hbox; +exports.getAvailableSize = getAvailableSize; +exports.getLayoutRect = getLayoutRect; +exports.positionElement = positionElement; +exports.sizeCalculable = sizeCalculable; +exports.mergeLayoutParam = mergeLayoutParam; +exports.getLayoutParams = getLayoutParams; +exports.copyLayoutParams = copyLayoutParams; + +/***/ }), +/* 48 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__core_Base__ = __webpack_require__(7); + + +// PENDING +// Use topological sort ? + +/** + * Node of graph based post processing. + * + * @constructor clay.compositor.CompositorNode + * @extends clay.core.Base + * + */ +var CompositorNode = __WEBPACK_IMPORTED_MODULE_0__core_Base__["a" /* default */].extend(function () { + return /** @lends clay.compositor.CompositorNode# */ { + /** + * @type {string} + */ + name: '', + + /** + * Input links, will be updated by the graph + * @example: + * inputName: { + * node: someNode, + * pin: 'xxxx' + * } + * @type {Object} + */ + inputLinks: {}, + + /** + * Output links, will be updated by the graph + * @example: + * outputName: { + * node: someNode, + * pin: 'xxxx' + * } + * @type {Object} + */ + outputLinks: {}, + + // Save the output texture of previous frame + // Will be used when there exist a circular reference + _prevOutputTextures: {}, + _outputTextures: {}, + + // Example: { name: 2 } + _outputReferences: {}, + + _rendering: false, + // If rendered in this frame + _rendered: false, + + _compositor: null + }; +}, +/** @lends clay.compositor.CompositorNode.prototype */ +{ + + // TODO Remove parameter function callback + updateParameter: function (outputName, renderer) { + var outputInfo = this.outputs[outputName]; + var parameters = outputInfo.parameters; + var parametersCopy = outputInfo._parametersCopy; + if (!parametersCopy) { + parametersCopy = outputInfo._parametersCopy = {}; + } + if (parameters) { + for (var key in parameters) { + if (key !== 'width' && key !== 'height') { + parametersCopy[key] = parameters[key]; + } + } + } + var width, height; + if (parameters.width instanceof Function) { + width = parameters.width.call(this, renderer); + } + else { + width = parameters.width; + } + if (parameters.height instanceof Function) { + height = parameters.height.call(this, renderer); + } + else { + height = parameters.height; + } + if ( + parametersCopy.width !== width + || parametersCopy.height !== height + ) { + if (this._outputTextures[outputName]) { + this._outputTextures[outputName].dispose(renderer.gl); + } + } + parametersCopy.width = width; + parametersCopy.height = height; + + return parametersCopy; + }, + + /** + * Set parameter + * @param {string} name + * @param {} value + */ + setParameter: function (name, value) {}, + /** + * Get parameter value + * @param {string} name + * @return {} + */ + getParameter: function (name) {}, + /** + * Set parameters + * @param {Object} obj + */ + setParameters: function (obj) { + for (var name in obj) { + this.setParameter(name, obj[name]); + } + }, + + render: function () {}, + + getOutput: function (renderer /*optional*/, name) { + if (name == null) { + // Return the output texture without rendering + name = renderer; + return this._outputTextures[name]; + } + var outputInfo = this.outputs[name]; + if (!outputInfo) { + return ; + } + + // Already been rendered in this frame + if (this._rendered) { + // Force return texture in last frame + if (outputInfo.outputLastFrame) { + return this._prevOutputTextures[name]; + } + else { + return this._outputTextures[name]; + } + } + else if ( + // TODO + this._rendering // Solve Circular Reference + ) { + if (!this._prevOutputTextures[name]) { + // Create a blank texture at first pass + this._prevOutputTextures[name] = this._compositor.allocateTexture(outputInfo.parameters || {}); + } + return this._prevOutputTextures[name]; + } + + this.render(renderer); + + return this._outputTextures[name]; + }, + + removeReference: function (outputName) { + this._outputReferences[outputName]--; + if (this._outputReferences[outputName] === 0) { + var outputInfo = this.outputs[outputName]; + if (outputInfo.keepLastFrame) { + if (this._prevOutputTextures[outputName]) { + this._compositor.releaseTexture(this._prevOutputTextures[outputName]); + } + this._prevOutputTextures[outputName] = this._outputTextures[outputName]; + } + else { + // Output of this node have alreay been used by all other nodes + // Put the texture back to the pool. + this._compositor.releaseTexture(this._outputTextures[outputName]); + } + } + }, + + link: function (inputPinName, fromNode, fromPinName) { + + // The relationship from output pin to input pin is one-on-multiple + this.inputLinks[inputPinName] = { + node: fromNode, + pin: fromPinName + }; + if (!fromNode.outputLinks[fromPinName]) { + fromNode.outputLinks[fromPinName] = []; + } + fromNode.outputLinks[fromPinName].push({ + node: this, + pin: inputPinName + }); + + // Enabled the pin texture in shader + this.pass.material.enableTexture(inputPinName); + }, + + clear: function () { + this.inputLinks = {}; + this.outputLinks = {}; + }, + + updateReference: function (outputName) { + if (!this._rendering) { + this._rendering = true; + for (var inputName in this.inputLinks) { + var link = this.inputLinks[inputName]; + link.node.updateReference(link.pin); + } + this._rendering = false; + } + if (outputName) { + this._outputReferences[outputName] ++; + } + }, + + beforeFrame: function () { + this._rendered = false; + + for (var name in this.outputLinks) { + this._outputReferences[name] = 0; + } + }, + + afterFrame: function () { + // Put back all the textures to pool + for (var name in this.outputLinks) { + if (this._outputReferences[name] > 0) { + var outputInfo = this.outputs[name]; + if (outputInfo.keepLastFrame) { + if (this._prevOutputTextures[name]) { + this._compositor.releaseTexture(this._prevOutputTextures[name]); + } + this._prevOutputTextures[name] = this._outputTextures[name]; + } + else { + this._compositor.releaseTexture(this._outputTextures[name]); + } + } + } + } +}); + +/* harmony default export */ __webpack_exports__["a"] = (CompositorNode); + + +/***/ }), +/* 49 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; + +// Generate halton sequence +// https://en.wikipedia.org/wiki/Halton_sequence +function halton(index, base) { + + var result = 0; + var f = 1 / base; + var i = index; + while (i > 0) { + result = result + f * (i % base); + i = Math.floor(i / base); + f = f / base; + } + return result; +} + + +/* harmony default export */ __webpack_exports__["a"] = (halton); + +/***/ }), +/* 50 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__); + + +/* harmony default export */ __webpack_exports__["a"] = (function (seriesModel, dims, source) { + source = source || seriesModel.getSource(); + + var coordSysDimensions = dims || __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.getCoordinateSystemDimensions(seriesModel.get('coordinateSystem')) || ['x', 'y', 'z']; + + var dimensions = __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.helper.createDimensions(source, { + dimensionsDefine: source.dimensionsDefine || seriesModel.get('dimensions'), + encodeDefine: source.encodeDefine || seriesModel.get('encode'), + coordDimensions: coordSysDimensions.map(function (dim) { + var axis3DModel = seriesModel.getReferringComponents(dim + 'Axis3D')[0]; + return { + type: (axis3DModel && axis3DModel.get('type') === 'category') ? 'ordinal' : 'float', + name: dim + // Find stackable dimension. Which will represent value. + // stackable: dim === 'z' + }; + }) + }); + if (seriesModel.get('coordinateSystem') === 'cartesian3D') { + dimensions.forEach(function (dimInfo) { + if (coordSysDimensions.indexOf(dimInfo.coordDim) >= 0) { + var axis3DModel = seriesModel.getReferringComponents(dimInfo.coordDim + 'Axis3D')[0]; + if (axis3DModel && axis3DModel.get('type') === 'category') { + dimInfo.ordinalMeta = axis3DModel.getOrdinalMeta(); + } + } + }); + } + + var stackCalculationInfo = __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.helper.dataStack.enableDataStack( + // Only support 'z' and `byIndex` now. + seriesModel, dimensions, {byIndex: true, stackedCoordDimension: 'z'} + ); + + var data = new __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.List(dimensions, seriesModel); + + data.setCalculationInfo(stackCalculationInfo); + + data.initData(source); + + return data; +}); + +/***/ }), +/* 51 */ +/***/ (function(module, exports) { + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ +function _default(seriesType, defaultSymbolType, legendSymbol) { + // Encoding visual for all series include which is filtered for legend drawing + return { + seriesType: seriesType, + // For legend. + performRawSeries: true, + reset: function (seriesModel, ecModel, api) { + var data = seriesModel.getData(); + var symbolType = seriesModel.get('symbol') || defaultSymbolType; + var symbolSize = seriesModel.get('symbolSize'); + var keepAspect = seriesModel.get('symbolKeepAspect'); + data.setVisual({ + legendSymbol: legendSymbol || symbolType, + symbol: symbolType, + symbolSize: symbolSize, + symbolKeepAspect: keepAspect + }); // Only visible series has each data be visual encoded + + if (ecModel.isSeriesFiltered(seriesModel)) { + return; + } + + var hasCallback = typeof symbolSize === 'function'; + + function dataEach(data, idx) { + if (typeof symbolSize === 'function') { + var rawValue = seriesModel.getRawValue(idx); // FIXME + + var params = seriesModel.getDataParams(idx); + data.setItemVisual(idx, 'symbolSize', symbolSize(rawValue, params)); + } + + if (data.hasItemOption) { + var itemModel = data.getItemModel(idx); + var itemSymbolType = itemModel.getShallow('symbol', true); + var itemSymbolSize = itemModel.getShallow('symbolSize', true); + var itemSymbolKeepAspect = itemModel.getShallow('symbolKeepAspect', true); // If has item symbol + + if (itemSymbolType != null) { + data.setItemVisual(idx, 'symbol', itemSymbolType); + } + + if (itemSymbolSize != null) { + // PENDING Transform symbolSize ? + data.setItemVisual(idx, 'symbolSize', itemSymbolSize); + } + + if (itemSymbolKeepAspect != null) { + data.setItemVisual(idx, 'symbolKeepAspect', itemSymbolKeepAspect); + } + } + } + + return { + dataEach: data.hasItemOption || hasCallback ? dataEach : null + }; + } + }; +} + +module.exports = _default; + +/***/ }), +/* 52 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__core_Base__ = __webpack_require__(7); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__core_GLInfo__ = __webpack_require__(111); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__core_glenum__ = __webpack_require__(11); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__core_vendor__ = __webpack_require__(14); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4__Material__ = __webpack_require__(19); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_5__math_Vector2__ = __webpack_require__(26); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_6__gpu_ProgramManager__ = __webpack_require__(115); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_7__Shader__ = __webpack_require__(8); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_8__shader_source_prez_glsl_js__ = __webpack_require__(71); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_9__glmatrix_mat4__ = __webpack_require__(21); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_10__glmatrix_vec3__ = __webpack_require__(12); +// TODO Resources like shader, texture, geometry reference management +// Trace and find out which shader, texture, geometry can be destroyed + + + + + + + + + +// Light header + + + +__WEBPACK_IMPORTED_MODULE_7__Shader__["a" /* default */]['import'](__WEBPACK_IMPORTED_MODULE_8__shader_source_prez_glsl_js__["a" /* default */]); + + + + +var mat4Create = __WEBPACK_IMPORTED_MODULE_9__glmatrix_mat4__["a" /* default */].create; + +var errorShader = {}; + +function defaultGetMaterial(renderable) { + return renderable.material; +} +function defaultGetUniform(renderable, material, symbol) { + return material.uniforms[symbol].value; +} +function defaultIsMaterialChanged(renderabled, prevRenderable, material, prevMaterial) { + return material !== prevMaterial; +} +function defaultIfRender(renderable) { + return true; +} + +function noop() {} + +var attributeBufferTypeMap = { + float: __WEBPACK_IMPORTED_MODULE_2__core_glenum__["a" /* default */].FLOAT, + byte: __WEBPACK_IMPORTED_MODULE_2__core_glenum__["a" /* default */].BYTE, + ubyte: __WEBPACK_IMPORTED_MODULE_2__core_glenum__["a" /* default */].UNSIGNED_BYTE, + short: __WEBPACK_IMPORTED_MODULE_2__core_glenum__["a" /* default */].SHORT, + ushort: __WEBPACK_IMPORTED_MODULE_2__core_glenum__["a" /* default */].UNSIGNED_SHORT +}; + +function VertexArrayObject(availableAttributes, availableAttributeSymbols, indicesBuffer) { + this.availableAttributes = availableAttributes; + this.availableAttributeSymbols = availableAttributeSymbols; + this.indicesBuffer = indicesBuffer; + + this.vao = null; +} + +function PlaceHolderTexture(renderer) { + var blankCanvas; + var webglTexture; + this.bind = function (renderer) { + if (!blankCanvas) { + // TODO Environment not support createCanvas. + blankCanvas = __WEBPACK_IMPORTED_MODULE_3__core_vendor__["a" /* default */].createCanvas(); + blankCanvas.width = blankCanvas.height = 1; + blankCanvas.getContext('2d'); + } + + var gl = renderer.gl; + var firstBind = !webglTexture; + if (firstBind) { + webglTexture = gl.createTexture(); + } + gl.bindTexture(gl.TEXTURE_2D, webglTexture); + if (firstBind) { + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, blankCanvas); + } + }; + this.unbind = function (renderer) { + renderer.gl.bindTexture(renderer.gl.TEXTURE_2D, null); + }; + this.isRenderable = function () { + return true; + }; +} +/** + * @constructor clay.Renderer + * @extends clay.core.Base + */ +var Renderer = __WEBPACK_IMPORTED_MODULE_0__core_Base__["a" /* default */].extend(function () { + return /** @lends clay.Renderer# */ { + + /** + * @type {HTMLCanvasElement} + * @readonly + */ + canvas: null, + + /** + * Canvas width, set by resize method + * @type {number} + * @private + */ + _width: 100, + + /** + * Canvas width, set by resize method + * @type {number} + * @private + */ + _height: 100, + + /** + * Device pixel ratio, set by setDevicePixelRatio method + * Specially for high defination display + * @see http://www.khronos.org/webgl/wiki/HandlingHighDPI + * @type {number} + * @private + */ + devicePixelRatio: (typeof window !== 'undefined' && window.devicePixelRatio) || 1.0, + + /** + * Clear color + * @type {number[]} + */ + clearColor: [0.0, 0.0, 0.0, 0.0], + + /** + * Default: + * _gl.COLOR_BUFFER_BIT | _gl.DEPTH_BUFFER_BIT | _gl.STENCIL_BUFFER_BIT + * @type {number} + */ + clearBit: 17664, + + // Settings when getting context + // http://www.khronos.org/registry/webgl/specs/latest/#2.4 + + /** + * If enable alpha, default true + * @type {boolean} + */ + alpha: true, + /** + * If enable depth buffer, default true + * @type {boolean} + */ + depth: true, + /** + * If enable stencil buffer, default false + * @type {boolean} + */ + stencil: false, + /** + * If enable antialias, default true + * @type {boolean} + */ + antialias: true, + /** + * If enable premultiplied alpha, default true + * @type {boolean} + */ + premultipliedAlpha: true, + /** + * If preserve drawing buffer, default false + * @type {boolean} + */ + preserveDrawingBuffer: false, + /** + * If throw context error, usually turned on in debug mode + * @type {boolean} + */ + throwError: true, + /** + * WebGL Context created from given canvas + * @type {WebGLRenderingContext} + */ + gl: null, + /** + * Renderer viewport, read-only, can be set by setViewport method + * @type {Object} + */ + viewport: {}, + + // Set by FrameBuffer#bind + __currentFrameBuffer: null, + + _viewportStack: [], + _clearStack: [], + + _sceneRendering: null + }; +}, function () { + + if (!this.canvas) { + this.canvas = __WEBPACK_IMPORTED_MODULE_3__core_vendor__["a" /* default */].createCanvas(); + } + var canvas = this.canvas; + try { + var opts = { + alpha: this.alpha, + depth: this.depth, + stencil: this.stencil, + antialias: this.antialias, + premultipliedAlpha: this.premultipliedAlpha, + preserveDrawingBuffer: this.preserveDrawingBuffer + }; + + this.gl = canvas.getContext('webgl', opts) + || canvas.getContext('experimental-webgl', opts); + + if (!this.gl) { + throw new Error(); + } + + this._glinfo = new __WEBPACK_IMPORTED_MODULE_1__core_GLInfo__["a" /* default */](this.gl); + + if (this.gl.targetRenderer) { + console.error('Already created a renderer'); + } + this.gl.targetRenderer = this; + + this.resize(); + } + catch (e) { + throw 'Error creating WebGL Context ' + e; + } + + // Init managers + this._programMgr = new __WEBPACK_IMPORTED_MODULE_6__gpu_ProgramManager__["a" /* default */](this); + + this._placeholderTexture = new PlaceHolderTexture(this); +}, +/** @lends clay.Renderer.prototype. **/ +{ + /** + * Resize the canvas + * @param {number} width + * @param {number} height + */ + resize: function(width, height) { + var canvas = this.canvas; + // http://www.khronos.org/webgl/wiki/HandlingHighDPI + // set the display size of the canvas. + var dpr = this.devicePixelRatio; + if (width != null) { + canvas.style.width = width + 'px'; + canvas.style.height = height + 'px'; + // set the size of the drawingBuffer + canvas.width = width * dpr; + canvas.height = height * dpr; + + this._width = width; + this._height = height; + } + else { + this._width = canvas.width / dpr; + this._height = canvas.height / dpr; + } + + this.setViewport(0, 0, this._width, this._height); + }, + + /** + * Get renderer width + * @return {number} + */ + getWidth: function () { + return this._width; + }, + + /** + * Get renderer height + * @return {number} + */ + getHeight: function () { + return this._height; + }, + + /** + * Get viewport aspect, + * @return {number} + */ + getViewportAspect: function () { + var viewport = this.viewport; + return viewport.width / viewport.height; + }, + + /** + * Set devicePixelRatio + * @param {number} devicePixelRatio + */ + setDevicePixelRatio: function(devicePixelRatio) { + this.devicePixelRatio = devicePixelRatio; + this.resize(this._width, this._height); + }, + + /** + * Get devicePixelRatio + * @param {number} devicePixelRatio + */ + getDevicePixelRatio: function () { + return this.devicePixelRatio; + }, + + /** + * Get WebGL extension + * @param {string} name + * @return {object} + */ + getGLExtension: function (name) { + return this._glinfo.getExtension(name); + }, + + /** + * Get WebGL parameter + * @param {string} name + * @return {*} + */ + getGLParameter: function (name) { + return this._glinfo.getParameter(name); + }, + + /** + * Set rendering viewport + * @param {number|Object} x + * @param {number} [y] + * @param {number} [width] + * @param {number} [height] + * @param {number} [devicePixelRatio] + * Defaultly use the renderere devicePixelRatio + * It needs to be 1 when setViewport is called by frameBuffer + * + * @example + * setViewport(0,0,width,height,1) + * setViewport({ + * x: 0, + * y: 0, + * width: width, + * height: height, + * devicePixelRatio: 1 + * }) + */ + setViewport: function (x, y, width, height, dpr) { + + if (typeof x === 'object') { + var obj = x; + + x = obj.x; + y = obj.y; + width = obj.width; + height = obj.height; + dpr = obj.devicePixelRatio; + } + dpr = dpr || this.devicePixelRatio; + + this.gl.viewport( + x * dpr, y * dpr, width * dpr, height * dpr + ); + // Use a fresh new object, not write property. + this.viewport = { + x: x, + y: y, + width: width, + height: height, + devicePixelRatio: dpr + }; + }, + + /** + * Push current viewport into a stack + */ + saveViewport: function () { + this._viewportStack.push(this.viewport); + }, + + /** + * Pop viewport from stack, restore in the renderer + */ + restoreViewport: function () { + if (this._viewportStack.length > 0) { + this.setViewport(this._viewportStack.pop()); + } + }, + + /** + * Push current clear into a stack + */ + saveClear: function () { + this._clearStack.push({ + clearBit: this.clearBit, + clearColor: this.clearColor + }); + }, + + /** + * Pop clear from stack, restore in the renderer + */ + restoreClear: function () { + if (this._clearStack.length > 0) { + var opt = this._clearStack.pop(); + this.clearColor = opt.clearColor; + this.clearBit = opt.clearBit; + } + }, + + bindSceneRendering: function (scene) { + this._sceneRendering = scene; + }, + + /** + * Render the scene in camera to the screen or binded offline framebuffer + * @param {clay.Scene} scene + * @param {clay.Camera} camera + * @param {boolean} [notUpdateScene] If not call the scene.update methods in the rendering, default true + * @param {boolean} [preZ] If use preZ optimization, default false + * @return {IRenderInfo} + */ + render: function(scene, camera, notUpdateScene, preZ) { + var _gl = this.gl; + + var clearColor = this.clearColor; + + if (this.clearBit) { + + // Must set depth and color mask true before clear + _gl.colorMask(true, true, true, true); + _gl.depthMask(true); + var viewport = this.viewport; + var needsScissor = false; + var viewportDpr = viewport.devicePixelRatio; + if (viewport.width !== this._width || viewport.height !== this._height + || (viewportDpr && viewportDpr !== this.devicePixelRatio) + || viewport.x || viewport.y + ) { + needsScissor = true; + // http://stackoverflow.com/questions/11544608/how-to-clear-a-rectangle-area-in-webgl + // Only clear the viewport + _gl.enable(_gl.SCISSOR_TEST); + _gl.scissor(viewport.x * viewportDpr, viewport.y * viewportDpr, viewport.width * viewportDpr, viewport.height * viewportDpr); + } + _gl.clearColor(clearColor[0], clearColor[1], clearColor[2], clearColor[3]); + _gl.clear(this.clearBit); + if (needsScissor) { + _gl.disable(_gl.SCISSOR_TEST); + } + } + + // If the scene have been updated in the prepass like shadow map + // There is no need to update it again + if (!notUpdateScene) { + scene.update(false); + } + scene.updateLights(); + + camera = camera || scene.getMainCamera(); + if (!camera) { + console.error('Can\'t find camera in the scene.'); + return; + } + camera.update(); + var renderList = scene.updateRenderList(camera, true); + + this._sceneRendering = scene; + + var opaqueList = renderList.opaque; + var transparentList = renderList.transparent; + var sceneMaterial = scene.material; + + scene.trigger('beforerender', this, scene, camera, renderList); + + // Render pre z + if (preZ) { + this.renderPreZ(opaqueList, scene, camera); + _gl.depthFunc(_gl.LEQUAL); + } + else { + _gl.depthFunc(_gl.LESS); + } + + // Update the depth of transparent list. + var worldViewMat = mat4Create(); + var posViewSpace = __WEBPACK_IMPORTED_MODULE_10__glmatrix_vec3__["a" /* default */].create(); + for (var i = 0; i < transparentList.length; i++) { + var renderable = transparentList[i]; + __WEBPACK_IMPORTED_MODULE_9__glmatrix_mat4__["a" /* default */].multiplyAffine(worldViewMat, camera.viewMatrix.array, renderable.worldTransform.array); + __WEBPACK_IMPORTED_MODULE_10__glmatrix_vec3__["a" /* default */].transformMat4(posViewSpace, renderable.position.array, worldViewMat); + renderable.__depth = posViewSpace[2]; + } + + // Render opaque list + this.renderPass(opaqueList, camera, { + getMaterial: function (renderable) { + return sceneMaterial || renderable.material; + }, + sortCompare: this.opaqueSortCompare + }); + + this.renderPass(transparentList, camera, { + getMaterial: function (renderable) { + return sceneMaterial || renderable.material; + }, + sortCompare: this.transparentSortCompare + }); + + scene.trigger('afterrender', this, scene, camera, renderList); + + // Cleanup + this._sceneRendering = null; + }, + + getProgram: function (renderable, renderMaterial, scene) { + renderMaterial = renderMaterial || renderable.material; + return this._programMgr.getProgram(renderable, renderMaterial, scene); + }, + + validateProgram: function (program) { + if (program.__error) { + var errorMsg = program.__error; + if (errorShader[program.__uid__]) { + return; + } + errorShader[program.__uid__] = true; + + if (this.throwError) { + throw new Error(errorMsg); + } + else { + this.trigger('error', errorMsg); + } + } + + }, + + updatePrograms: function (list, scene, passConfig) { + var getMaterial = (passConfig && passConfig.getMaterial) || defaultGetMaterial; + scene = scene || null; + for (var i = 0; i < list.length; i++) { + var renderable = list[i]; + var renderMaterial = getMaterial.call(this, renderable); + if (i > 0) { + var prevRenderable = list[i - 1]; + var prevJointsLen = prevRenderable.joints ? prevRenderable.joints.length : 0; + var jointsLen = renderable.joints ? renderable.joints.length : 0; + // Keep program not change if joints, material, lightGroup are same of two renderables. + if (jointsLen === prevJointsLen + && renderable.material === prevRenderable.material + && renderable.lightGroup === prevRenderable.lightGroup + ) { + renderable.__program = prevRenderable.__program; + continue; + } + } + + var program = this._programMgr.getProgram(renderable, renderMaterial, scene); + + this.validateProgram(program); + + renderable.__program = program; + } + }, + + /** + * Render a single renderable list in camera in sequence + * @param {clay.Renderable[]} list List of all renderables. + * @param {clay.Camera} [camera] Camera provide view matrix and porjection matrix. It can be null. + * @param {Object} [passConfig] + * @param {Function} [passConfig.getMaterial] Get renderable material. + * @param {Function} [passConfig.getUniform] Get material uniform value. + * @param {Function} [passConfig.isMaterialChanged] If material changed. + * @param {Function} [passConfig.beforeRender] Before render each renderable. + * @param {Function} [passConfig.afterRender] After render each renderable + * @param {Function} [passConfig.ifRender] If render the renderable. + * @param {Function} [passConfig.sortCompare] Sort compare function. + * @return {IRenderInfo} + */ + renderPass: function(list, camera, passConfig) { + this.trigger('beforerenderpass', this, list, camera, passConfig); + + passConfig = passConfig || {}; + passConfig.getMaterial = passConfig.getMaterial || defaultGetMaterial; + passConfig.getUniform = passConfig.getUniform || defaultGetUniform; + // PENDING Better solution? + passConfig.isMaterialChanged = passConfig.isMaterialChanged || defaultIsMaterialChanged; + passConfig.beforeRender = passConfig.beforeRender || noop; + passConfig.afterRender = passConfig.afterRender || noop; + + var ifRenderObject = passConfig.ifRender || defaultIfRender; + + this.updatePrograms(list, this._sceneRendering, passConfig); + if (passConfig.sortCompare) { + list.sort(passConfig.sortCompare); + } + + // Some common builtin uniforms + var viewport = this.viewport; + var vDpr = viewport.devicePixelRatio; + var viewportUniform = [ + viewport.x * vDpr, viewport.y * vDpr, + viewport.width * vDpr, viewport.height * vDpr + ]; + var windowDpr = this.devicePixelRatio; + var windowSizeUniform = this.__currentFrameBuffer + ? [this.__currentFrameBuffer.getTextureWidth(), this.__currentFrameBuffer.getTextureHeight()] + : [this._width * windowDpr, this._height * windowDpr]; + // DEPRECATED + var viewportSizeUniform = [ + viewportUniform[2], viewportUniform[3] + ]; + var time = Date.now(); + + // Calculate view and projection matrix + if (camera) { + __WEBPACK_IMPORTED_MODULE_9__glmatrix_mat4__["a" /* default */].copy(matrices.VIEW, camera.viewMatrix.array); + __WEBPACK_IMPORTED_MODULE_9__glmatrix_mat4__["a" /* default */].copy(matrices.PROJECTION, camera.projectionMatrix.array); + __WEBPACK_IMPORTED_MODULE_9__glmatrix_mat4__["a" /* default */].copy(matrices.VIEWINVERSE, camera.worldTransform.array); + } + else { + __WEBPACK_IMPORTED_MODULE_9__glmatrix_mat4__["a" /* default */].identity(matrices.VIEW); + __WEBPACK_IMPORTED_MODULE_9__glmatrix_mat4__["a" /* default */].identity(matrices.PROJECTION); + __WEBPACK_IMPORTED_MODULE_9__glmatrix_mat4__["a" /* default */].identity(matrices.VIEWINVERSE); + } + __WEBPACK_IMPORTED_MODULE_9__glmatrix_mat4__["a" /* default */].multiply(matrices.VIEWPROJECTION, matrices.PROJECTION, matrices.VIEW); + __WEBPACK_IMPORTED_MODULE_9__glmatrix_mat4__["a" /* default */].invert(matrices.PROJECTIONINVERSE, matrices.PROJECTION); + __WEBPACK_IMPORTED_MODULE_9__glmatrix_mat4__["a" /* default */].invert(matrices.VIEWPROJECTIONINVERSE, matrices.VIEWPROJECTION); + + var _gl = this.gl; + var scene = this._sceneRendering; + + var prevMaterial; + var prevProgram; + var prevRenderable; + + // Status + var depthTest, depthMask; + var culling, cullFace, frontFace; + var transparent; + var drawID; + var currentVAO; + var materialTakesTextureSlot; + + var vaoExt = this.getGLExtension('OES_vertex_array_object'); + + for (var i = 0; i < list.length; i++) { + var renderable = list[i]; + var isSceneNode = renderable.worldTransform != null; + var worldM; + + if (!ifRenderObject(renderable)) { + continue; + } + + // Skinned mesh will transformed to joint space. Ignore the mesh transform + if (isSceneNode) { + worldM = (renderable.isSkinnedMesh && renderable.isSkinnedMesh()) + ? matrices.IDENTITY : renderable.worldTransform.array; + } + var geometry = renderable.geometry; + var material = passConfig.getMaterial.call(this, renderable); + + var program = renderable.__program; + var shader = material.shader; + + var currentDrawID = geometry.__uid__ + '-' + program.__uid__; + var drawIDChanged = currentDrawID !== drawID; + drawID = currentDrawID; + if (drawIDChanged && vaoExt) { + // TODO Seems need to be bound to null immediately (or before bind another program?) if vao is changed + vaoExt.bindVertexArrayOES(null); + } + if (isSceneNode) { + __WEBPACK_IMPORTED_MODULE_9__glmatrix_mat4__["a" /* default */].copy(matrices.WORLD, worldM); + __WEBPACK_IMPORTED_MODULE_9__glmatrix_mat4__["a" /* default */].multiply(matrices.WORLDVIEWPROJECTION, matrices.VIEWPROJECTION, worldM); + __WEBPACK_IMPORTED_MODULE_9__glmatrix_mat4__["a" /* default */].multiplyAffine(matrices.WORLDVIEW, matrices.VIEW, worldM); + if (shader.matrixSemantics.WORLDINVERSE || + shader.matrixSemantics.WORLDINVERSETRANSPOSE) { + __WEBPACK_IMPORTED_MODULE_9__glmatrix_mat4__["a" /* default */].invert(matrices.WORLDINVERSE, worldM); + } + if (shader.matrixSemantics.WORLDVIEWINVERSE || + shader.matrixSemantics.WORLDVIEWINVERSETRANSPOSE) { + __WEBPACK_IMPORTED_MODULE_9__glmatrix_mat4__["a" /* default */].invert(matrices.WORLDVIEWINVERSE, matrices.WORLDVIEW); + } + if (shader.matrixSemantics.WORLDVIEWPROJECTIONINVERSE || + shader.matrixSemantics.WORLDVIEWPROJECTIONINVERSETRANSPOSE) { + __WEBPACK_IMPORTED_MODULE_9__glmatrix_mat4__["a" /* default */].invert(matrices.WORLDVIEWPROJECTIONINVERSE, matrices.WORLDVIEWPROJECTION); + } + } + + // Before render hook + renderable.beforeRender && renderable.beforeRender(this); + passConfig.beforeRender.call(this, renderable, material, prevMaterial); + + var programChanged = program !== prevProgram; + if (programChanged) { + // Set lights number + program.bind(this); + // Set some common uniforms + program.setUniformOfSemantic(_gl, 'VIEWPORT', viewportUniform); + program.setUniformOfSemantic(_gl, 'WINDOW_SIZE', windowSizeUniform); + if (camera) { + program.setUniformOfSemantic(_gl, 'NEAR', camera.near); + program.setUniformOfSemantic(_gl, 'FAR', camera.far); + } + program.setUniformOfSemantic(_gl, 'DEVICEPIXELRATIO', vDpr); + program.setUniformOfSemantic(_gl, 'TIME', time); + // DEPRECATED + program.setUniformOfSemantic(_gl, 'VIEWPORT_SIZE', viewportSizeUniform); + + // Set lights uniforms + // TODO needs optimized + if (scene) { + scene.setLightUniforms(program, renderable.lightGroup, this); + } + } + else { + program = prevProgram; + } + + // Program changes also needs reset the materials. + if (programChanged || passConfig.isMaterialChanged( + renderable, prevRenderable, material, prevMaterial + )) { + if (material.depthTest !== depthTest) { + material.depthTest ? _gl.enable(_gl.DEPTH_TEST) : _gl.disable(_gl.DEPTH_TEST); + depthTest = material.depthTest; + } + if (material.depthMask !== depthMask) { + _gl.depthMask(material.depthMask); + depthMask = material.depthMask; + } + if (material.transparent !== transparent) { + material.transparent ? _gl.enable(_gl.BLEND) : _gl.disable(_gl.BLEND); + transparent = material.transparent; + } + // TODO cache blending + if (material.transparent) { + if (material.blend) { + material.blend(_gl); + } + else { + // Default blend function + _gl.blendEquationSeparate(_gl.FUNC_ADD, _gl.FUNC_ADD); + _gl.blendFuncSeparate(_gl.SRC_ALPHA, _gl.ONE_MINUS_SRC_ALPHA, _gl.ONE, _gl.ONE_MINUS_SRC_ALPHA); + } + } + + materialTakesTextureSlot = this._bindMaterial( + renderable, material, program, + prevRenderable || null, prevMaterial || null, prevProgram || null, + passConfig.getUniform + ); + prevMaterial = material; + } + + var matrixSemanticKeys = shader.matrixSemanticKeys; + + if (isSceneNode) { + for (var k = 0; k < matrixSemanticKeys.length; k++) { + var semantic = matrixSemanticKeys[k]; + var semanticInfo = shader.matrixSemantics[semantic]; + var matrix = matrices[semantic]; + if (semanticInfo.isTranspose) { + var matrixNoTranspose = matrices[semanticInfo.semanticNoTranspose]; + __WEBPACK_IMPORTED_MODULE_9__glmatrix_mat4__["a" /* default */].transpose(matrix, matrixNoTranspose); + } + program.setUniform(_gl, semanticInfo.type, semanticInfo.symbol, matrix); + } + } + + if (renderable.cullFace !== cullFace) { + cullFace = renderable.cullFace; + _gl.cullFace(cullFace); + } + if (renderable.frontFace !== frontFace) { + frontFace = renderable.frontFace; + _gl.frontFace(frontFace); + } + if (renderable.culling !== culling) { + culling = renderable.culling; + culling ? _gl.enable(_gl.CULL_FACE) : _gl.disable(_gl.CULL_FACE); + } + // TODO Not update skeleton in each renderable. + this._updateSkeleton(renderable, program, materialTakesTextureSlot); + if (drawIDChanged) { + currentVAO = this._bindVAO(vaoExt, shader, geometry, program); + } + this._renderObject(renderable, currentVAO); + + // After render hook + passConfig.afterRender(this, renderable); + renderable.afterRender && renderable.afterRender(this); + + prevProgram = program; + prevRenderable = renderable; + } + + // TODO Seems need to be bound to null immediately if vao is changed? + if (vaoExt) { + vaoExt.bindVertexArrayOES(null); + } + + this.trigger('afterrenderpass', this, list, camera, passConfig); + }, + + getMaxJointNumber: function () { + return this._glinfo.getMaxJointNumber(); + }, + + _updateSkeleton: function (object, program, slot) { + var _gl = this.gl; + var skeleton = object.skeleton; + // Set pose matrices of skinned mesh + if (skeleton) { + // TODO Update before culling. + skeleton.update(); + if (object.joints.length > this._glinfo.getMaxJointNumber()) { + var skinMatricesTexture = skeleton.getSubSkinMatricesTexture(object.__uid__, object.joints); + program.useTextureSlot(this, skinMatricesTexture, slot); + program.setUniform(_gl, '1i', 'skinMatricesTexture', slot); + program.setUniform(_gl, '1f', 'skinMatricesTextureSize', skinMatricesTexture.width); + } + else { + var skinMatricesArray = skeleton.getSubSkinMatrices(object.__uid__, object.joints); + program.setUniformOfSemantic(_gl, 'SKIN_MATRIX', skinMatricesArray); + } + } + }, + + _renderObject: function (renderable, vao) { + var _gl = this.gl; + var geometry = renderable.geometry; + + var glDrawMode = renderable.mode; + if (glDrawMode == null) { + glDrawMode = 0x0004; + } + + // if (glDrawMode === glenum.LINES || glDrawMode === glenum.LINE_STRIP || glDrawMode === glenum.LINE_LOOP) { + // _gl.lineWidth(this.lineWidth); + // } + + if (vao.indicesBuffer) { + var uintExt = this.getGLExtension('OES_element_index_uint'); + var useUintExt = uintExt && (geometry.indices instanceof Uint32Array); + var indicesType = useUintExt ? _gl.UNSIGNED_INT : _gl.UNSIGNED_SHORT; + + _gl.drawElements(glDrawMode, vao.indicesBuffer.count, indicesType, 0); + } + else { + // FIXME Use vertex number in buffer + // vertexCount may get the wrong value when geometry forget to mark dirty after update + _gl.drawArrays(glDrawMode, 0, geometry.vertexCount); + } + }, + + _bindMaterial: function (renderable, material, program, prevRenderable, prevMaterial, prevProgram, getUniformValue) { + var _gl = this.gl; + // PENDING Same texture in different material take different slot? + + // May use shader of other material if shader code are same + var sameProgram = prevProgram === program; + + var currentTextureSlot = program.currentTextureSlot(); + var enabledUniforms = material.getEnabledUniforms(); + var textureUniforms = material.getTextureUniforms(); + var placeholderTexture = this._placeholderTexture; + + for (var u = 0; u < textureUniforms.length; u++) { + var symbol = textureUniforms[u]; + var uniformValue = getUniformValue(renderable, material, symbol); + var uniformType = material.uniforms[symbol].type; + // Not use `instanceof` to determine if a value is texture in Material#bind. + // Use type instead, in some case texture may be in different namespaces. + // TODO Duck type validate. + if (uniformType === 't' && uniformValue) { + // Reset slot + uniformValue.__slot = -1; + } + else if (uniformType === 'tv') { + for (var i = 0; i < uniformValue.length; i++) { + if (uniformValue[i]) { + uniformValue[i].__slot = -1; + } + } + } + } + + placeholderTexture.__slot = -1; + + // Set uniforms + for (var u = 0; u < enabledUniforms.length; u++) { + var symbol = enabledUniforms[u]; + var uniform = material.uniforms[symbol]; + var uniformValue = getUniformValue(renderable, material, symbol); + var uniformType = uniform.type; + var isTexture = uniformType === 't'; + + if (isTexture) { + if (!uniformValue || !uniformValue.isRenderable()) { + uniformValue = placeholderTexture; + } + } + // PENDING + // When binding two materials with the same shader + // Many uniforms will be be set twice even if they have the same value + // So add a evaluation to see if the uniform is really needed to be set + if (prevMaterial && sameProgram) { + var prevUniformValue = getUniformValue(prevRenderable, prevMaterial, symbol); + if (isTexture) { + if (!prevUniformValue || !prevUniformValue.isRenderable()) { + prevUniformValue = placeholderTexture; + } + } + + if (prevUniformValue === uniformValue) { + if (isTexture) { + // Still take the slot to make sure same texture in different materials have same slot. + program.takeCurrentTextureSlot(this, null); + } + else if (uniformType === 'tv' && uniformValue) { + for (var i = 0; i < uniformValue.length; i++) { + program.takeCurrentTextureSlot(this, null); + } + } + continue; + } + } + + if (uniformValue == null) { + continue; + } + else if (isTexture) { + if (uniformValue.__slot < 0) { + var slot = program.currentTextureSlot(); + var res = program.setUniform(_gl, '1i', symbol, slot); + if (res) { // Texture uniform is enabled + program.takeCurrentTextureSlot(this, uniformValue); + uniformValue.__slot = slot; + } + } + // Multiple uniform use same texture.. + else { + program.setUniform(_gl, '1i', symbol, uniformValue.__slot); + } + } + else if (Array.isArray(uniformValue)) { + if (uniformValue.length === 0) { + continue; + } + // Texture Array + if (uniformType === 'tv') { + if (!program.hasUniform(symbol)) { + continue; + } + + var arr = []; + for (var i = 0; i < uniformValue.length; i++) { + var texture = uniformValue[i]; + + if (texture.__slot < 0) { + var slot = program.currentTextureSlot(); + arr.push(slot); + program.takeCurrentTextureSlot(this, texture); + texture.__slot = slot; + } + else { + arr.push(texture.__slot); + } + } + + program.setUniform(_gl, '1iv', symbol, arr); + } + else { + program.setUniform(_gl, uniform.type, symbol, uniformValue); + } + } + else{ + program.setUniform(_gl, uniform.type, symbol, uniformValue); + } + } + var newSlot = program.currentTextureSlot(); + // Texture slot maybe used out of material. + program.resetTextureSlot(currentTextureSlot); + return newSlot; + }, + + _bindVAO: function (vaoExt, shader, geometry, program) { + var isStatic = !geometry.dynamic; + var _gl = this.gl; + + var vaoId = this.__uid__ + '-' + program.__uid__; + var vao = geometry.__vaoCache[vaoId]; + if (!vao) { + var chunks = geometry.getBufferChunks(this); + if (!chunks || !chunks.length) { // Empty mesh + return; + } + var chunk = chunks[0]; + var attributeBuffers = chunk.attributeBuffers; + var indicesBuffer = chunk.indicesBuffer; + + var availableAttributes = []; + var availableAttributeSymbols = []; + for (var a = 0; a < attributeBuffers.length; a++) { + var attributeBufferInfo = attributeBuffers[a]; + var name = attributeBufferInfo.name; + var semantic = attributeBufferInfo.semantic; + var symbol; + if (semantic) { + var semanticInfo = shader.attributeSemantics[semantic]; + symbol = semanticInfo && semanticInfo.symbol; + } + else { + symbol = name; + } + if (symbol && program.attributes[symbol]) { + availableAttributes.push(attributeBufferInfo); + availableAttributeSymbols.push(symbol); + } + } + + vao = new VertexArrayObject( + availableAttributes, + availableAttributeSymbols, + indicesBuffer + ); + + if (isStatic) { + geometry.__vaoCache[vaoId] = vao; + } + } + + var needsBindAttributes = true; + + // Create vertex object array cost a lot + // So we don't use it on the dynamic object + if (vaoExt && isStatic) { + // Use vertex array object + // http://blog.tojicode.com/2012/10/oesvertexarrayobject-extension.html + if (vao.vao == null) { + vao.vao = vaoExt.createVertexArrayOES(); + } + else { + needsBindAttributes = false; + } + vaoExt.bindVertexArrayOES(vao.vao); + } + + var availableAttributes = vao.availableAttributes; + var indicesBuffer = vao.indicesBuffer; + + if (needsBindAttributes) { + var locationList = program.enableAttributes(this, vao.availableAttributeSymbols, (vaoExt && isStatic && vao)); + // Setting attributes; + for (var a = 0; a < availableAttributes.length; a++) { + var location = locationList[a]; + if (location === -1) { + continue; + } + var attributeBufferInfo = availableAttributes[a]; + var buffer = attributeBufferInfo.buffer; + var size = attributeBufferInfo.size; + var glType = attributeBufferTypeMap[attributeBufferInfo.type] || _gl.FLOAT; + + _gl.bindBuffer(_gl.ARRAY_BUFFER, buffer); + _gl.vertexAttribPointer(location, size, glType, false, 0, 0); + } + + if (geometry.isUseIndices()) { + _gl.bindBuffer(_gl.ELEMENT_ARRAY_BUFFER, indicesBuffer.buffer); + } + } + + return vao; + }, + + renderPreZ: function (list, scene, camera) { + var _gl = this.gl; + var preZPassMaterial = this._prezMaterial || new __WEBPACK_IMPORTED_MODULE_4__Material__["a" /* default */]({ + shader: new __WEBPACK_IMPORTED_MODULE_7__Shader__["a" /* default */](__WEBPACK_IMPORTED_MODULE_7__Shader__["a" /* default */].source('clay.prez.vertex'), __WEBPACK_IMPORTED_MODULE_7__Shader__["a" /* default */].source('clay.prez.fragment')) + }); + this._prezMaterial = preZPassMaterial; + + _gl.colorMask(false, false, false, false); + _gl.depthMask(true); + + // Status + this.renderPass(list, camera, { + ifRender: function (renderable) { + return !renderable.ignorePreZ; + }, + isMaterialChanged: function (renderable, prevRenderable) { + var matA = renderable.material; + var matB = prevRenderable.material; + return matA.get('diffuseMap') !== matB.get('diffuseMap') + || (matA.get('alphaCutoff') || 0) !== (matB.get('alphaCutoff') || 0); + }, + getUniform: function (renderable, depthMaterial, symbol) { + if (symbol === 'alphaMap') { + return renderable.material.get('diffuseMap'); + } + else if (symbol === 'alphaCutoff') { + if (renderable.material.isDefined('fragment', 'ALPHA_TEST') + && renderable.material.get('diffuseMap') + ) { + var alphaCutoff = renderable.material.get('alphaCutoff'); + return alphaCutoff || 0; + } + return 0; + } + else { + return depthMaterial.get(symbol); + } + }, + getMaterial: function () { + return preZPassMaterial; + }, + sort: this.opaqueSortCompare + }); + + _gl.colorMask(true, true, true, true); + _gl.depthMask(true); + }, + + /** + * Dispose given scene, including all geometris, textures and shaders in the scene + * @param {clay.Scene} scene + */ + disposeScene: function(scene) { + this.disposeNode(scene, true, true); + scene.dispose(); + }, + + /** + * Dispose given node, including all geometries, textures and shaders attached on it or its descendant + * @param {clay.Node} node + * @param {boolean} [disposeGeometry=false] If dispose the geometries used in the descendant mesh + * @param {boolean} [disposeTexture=false] If dispose the textures used in the descendant mesh + */ + disposeNode: function(root, disposeGeometry, disposeTexture) { + // Dettached from parent + if (root.getParent()) { + root.getParent().remove(root); + } + var disposedMap = {}; + root.traverse(function(node) { + var material = node.material; + if (node.geometry && disposeGeometry) { + node.geometry.dispose(this); + } + if (disposeTexture && material && !disposedMap[material.__uid__]) { + var textureUniforms = material.getTextureUniforms(); + for (var u = 0; u < textureUniforms.length; u++) { + var uniformName = textureUniforms[u]; + var val = material.uniforms[uniformName].value; + var uniformType = material.uniforms[uniformName].type; + if (!val) { + continue; + } + if (uniformType === 't') { + val.dispose && val.dispose(this); + } + else if (uniformType === 'tv') { + for (var k = 0; k < val.length; k++) { + if (val[k]) { + val[k].dispose && val[k].dispose(this); + } + } + } + } + disposedMap[material.__uid__] = true; + } + // Particle system and AmbientCubemap light need to dispose + if (node.dispose) { + node.dispose(this); + } + }, this); + }, + + /** + * Dispose given geometry + * @param {clay.Geometry} geometry + */ + disposeGeometry: function(geometry) { + geometry.dispose(this); + }, + + /** + * Dispose given texture + * @param {clay.Texture} texture + */ + disposeTexture: function(texture) { + texture.dispose(this); + }, + + /** + * Dispose given frame buffer + * @param {clay.FrameBuffer} frameBuffer + */ + disposeFrameBuffer: function(frameBuffer) { + frameBuffer.dispose(this); + }, + + /** + * Dispose renderer + */ + dispose: function () {}, + + /** + * Convert screen coords to normalized device coordinates(NDC) + * Screen coords can get from mouse event, it is positioned relative to canvas element + * NDC can be used in ray casting with Camera.prototype.castRay methods + * + * @param {number} x + * @param {number} y + * @param {clay.Vector2} [out] + * @return {clay.Vector2} + */ + screenToNDC: function(x, y, out) { + if (!out) { + out = new __WEBPACK_IMPORTED_MODULE_5__math_Vector2__["a" /* default */](); + } + // Invert y; + y = this._height - y; + + var viewport = this.viewport; + var arr = out.array; + arr[0] = (x - viewport.x) / viewport.width; + arr[0] = arr[0] * 2 - 1; + arr[1] = (y - viewport.y) / viewport.height; + arr[1] = arr[1] * 2 - 1; + + return out; + } +}); + +/** + * Opaque renderables compare function + * @param {clay.Renderable} x + * @param {clay.Renderable} y + * @return {boolean} + * @static + */ +Renderer.opaqueSortCompare = Renderer.prototype.opaqueSortCompare = function(x, y) { + // Priority renderOrder -> program -> material -> geometry + if (x.renderOrder === y.renderOrder) { + if (x.__program === y.__program) { + if (x.material === y.material) { + return x.geometry.__uid__ - y.geometry.__uid__; + } + return x.material.__uid__ - y.material.__uid__; + } + if (x.__program && y.__program) { + return x.__program.__uid__ - y.__program.__uid__; + } + return 0; + } + return x.renderOrder - y.renderOrder; +}; + +/** + * Transparent renderables compare function + * @param {clay.Renderable} a + * @param {clay.Renderable} b + * @return {boolean} + * @static + */ +Renderer.transparentSortCompare = Renderer.prototype.transparentSortCompare = function(x, y) { + // Priority renderOrder -> depth -> program -> material -> geometry + + if (x.renderOrder === y.renderOrder) { + if (x.__depth === y.__depth) { + if (x.__program === y.__program) { + if (x.material === y.material) { + return x.geometry.__uid__ - y.geometry.__uid__; + } + return x.material.__uid__ - y.material.__uid__; + } + if (x.__program && y.__program) { + return x.__program.__uid__ - y.__program.__uid__; + } + return 0; + } + // Depth is negative + // So farther object has smaller depth value + return x.__depth - y.__depth; + } + return x.renderOrder - y.renderOrder; +}; + +// Temporary variables +var matrices = { + IDENTITY: mat4Create(), + + WORLD: mat4Create(), + VIEW: mat4Create(), + PROJECTION: mat4Create(), + WORLDVIEW: mat4Create(), + VIEWPROJECTION: mat4Create(), + WORLDVIEWPROJECTION: mat4Create(), + + WORLDINVERSE: mat4Create(), + VIEWINVERSE: mat4Create(), + PROJECTIONINVERSE: mat4Create(), + WORLDVIEWINVERSE: mat4Create(), + VIEWPROJECTIONINVERSE: mat4Create(), + WORLDVIEWPROJECTIONINVERSE: mat4Create(), + + WORLDTRANSPOSE: mat4Create(), + VIEWTRANSPOSE: mat4Create(), + PROJECTIONTRANSPOSE: mat4Create(), + WORLDVIEWTRANSPOSE: mat4Create(), + VIEWPROJECTIONTRANSPOSE: mat4Create(), + WORLDVIEWPROJECTIONTRANSPOSE: mat4Create(), + WORLDINVERSETRANSPOSE: mat4Create(), + VIEWINVERSETRANSPOSE: mat4Create(), + PROJECTIONINVERSETRANSPOSE: mat4Create(), + WORLDVIEWINVERSETRANSPOSE: mat4Create(), + VIEWPROJECTIONINVERSETRANSPOSE: mat4Create(), + WORLDVIEWPROJECTIONINVERSETRANSPOSE: mat4Create() +}; + +/** + * @name clay.Renderer.COLOR_BUFFER_BIT + * @type {number} + */ +Renderer.COLOR_BUFFER_BIT = __WEBPACK_IMPORTED_MODULE_2__core_glenum__["a" /* default */].COLOR_BUFFER_BIT; +/** + * @name clay.Renderer.DEPTH_BUFFER_BIT + * @type {number} + */ +Renderer.DEPTH_BUFFER_BIT = __WEBPACK_IMPORTED_MODULE_2__core_glenum__["a" /* default */].DEPTH_BUFFER_BIT; +/** + * @name clay.Renderer.STENCIL_BUFFER_BIT + * @type {number} + */ +Renderer.STENCIL_BUFFER_BIT = __WEBPACK_IMPORTED_MODULE_2__core_glenum__["a" /* default */].STENCIL_BUFFER_BIT; + +/* harmony default export */ __webpack_exports__["a"] = (Renderer); + + +/***/ }), +/* 53 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +function Handler(action, context) { + this.action = action; + this.context = context; +} +/** + * @mixin + * @alias clay.core.mixin.notifier + */ +var notifier = { + /** + * Trigger event + * @param {string} name + */ + trigger: function(name) { + if (!this.hasOwnProperty('__handlers__')) { + return; + } + if (!this.__handlers__.hasOwnProperty(name)) { + return; + } + + var hdls = this.__handlers__[name]; + var l = hdls.length, i = -1, args = arguments; + // Optimize advise from backbone + switch (args.length) { + case 1: + while (++i < l) { + hdls[i].action.call(hdls[i].context); + } + return; + case 2: + while (++i < l) { + hdls[i].action.call(hdls[i].context, args[1]); + } + return; + case 3: + while (++i < l) { + hdls[i].action.call(hdls[i].context, args[1], args[2]); + } + return; + case 4: + while (++i < l) { + hdls[i].action.call(hdls[i].context, args[1], args[2], args[3]); + } + return; + case 5: + while (++i < l) { + hdls[i].action.call(hdls[i].context, args[1], args[2], args[3], args[4]); + } + return; + default: + while (++i < l) { + hdls[i].action.apply(hdls[i].context, Array.prototype.slice.call(args, 1)); + } + return; + } + }, + /** + * Register event handler + * @param {string} name + * @param {Function} action + * @param {Object} [context] + * @chainable + */ + on: function(name, action, context) { + if (!name || !action) { + return; + } + var handlers = this.__handlers__ || (this.__handlers__={}); + if (!handlers[name]) { + handlers[name] = []; + } + else { + if (this.has(name, action)) { + return; + } + } + var handler = new Handler(action, context || this); + handlers[name].push(handler); + + return this; + }, + + /** + * Register event, event will only be triggered once and then removed + * @param {string} name + * @param {Function} action + * @param {Object} [context] + * @chainable + */ + once: function(name, action, context) { + if (!name || !action) { + return; + } + var self = this; + function wrapper() { + self.off(name, wrapper); + action.apply(this, arguments); + } + return this.on(name, wrapper, context); + }, + + /** + * Alias of once('before' + name) + * @param {string} name + * @param {Function} action + * @param {Object} [context] + * @chainable + */ + before: function(name, action, context) { + if (!name || !action) { + return; + } + name = 'before' + name; + return this.on(name, action, context); + }, + + /** + * Alias of once('after' + name) + * @param {string} name + * @param {Function} action + * @param {Object} [context] + * @chainable + */ + after: function(name, action, context) { + if (!name || !action) { + return; + } + name = 'after' + name; + return this.on(name, action, context); + }, + + /** + * Alias of on('success') + * @param {Function} action + * @param {Object} [context] + * @chainable + */ + success: function(action, context) { + return this.once('success', action, context); + }, + + /** + * Alias of on('error') + * @param {Function} action + * @param {Object} [context] + * @chainable + */ + error: function(action, context) { + return this.once('error', action, context); + }, + + /** + * Remove event listener + * @param {Function} action + * @param {Object} [context] + * @chainable + */ + off: function(name, action) { + + var handlers = this.__handlers__ || (this.__handlers__={}); + + if (!action) { + handlers[name] = []; + return; + } + if (handlers[name]) { + var hdls = handlers[name]; + var retains = []; + for (var i = 0; i < hdls.length; i++) { + if (action && hdls[i].action !== action) { + retains.push(hdls[i]); + } + } + handlers[name] = retains; + } + + return this; + }, + + /** + * If registered the event handler + * @param {string} name + * @param {Function} action + * @return {boolean} + */ + has: function(name, action) { + var handlers = this.__handlers__; + + if (! handlers || + ! handlers[name]) { + return false; + } + var hdls = handlers[name]; + for (var i = 0; i < hdls.length; i++) { + if (hdls[i].action === action) { + return true; + } + } + } +}; + +/* harmony default export */ __webpack_exports__["a"] = (notifier); + +/***/ }), +/* 54 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__Vector3__ = __webpack_require__(3); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__glmatrix_vec3__ = __webpack_require__(12); + + + +var EPSILON = 1e-5; + +/** + * @constructor + * @alias clay.Ray + * @param {clay.Vector3} [origin] + * @param {clay.Vector3} [direction] + */ +var Ray = function (origin, direction) { + /** + * @type {clay.Vector3} + */ + this.origin = origin || new __WEBPACK_IMPORTED_MODULE_0__Vector3__["a" /* default */](); + /** + * @type {clay.Vector3} + */ + this.direction = direction || new __WEBPACK_IMPORTED_MODULE_0__Vector3__["a" /* default */](); +}; + +Ray.prototype = { + + constructor: Ray, + + // http://www.siggraph.org/education/materials/HyperGraph/raytrace/rayplane_intersection.htm + /** + * Calculate intersection point between ray and a give plane + * @param {clay.Plane} plane + * @param {clay.Vector3} [out] + * @return {clay.Vector3} + */ + intersectPlane: function (plane, out) { + var pn = plane.normal.array; + var d = plane.distance; + var ro = this.origin.array; + var rd = this.direction.array; + + var divider = __WEBPACK_IMPORTED_MODULE_1__glmatrix_vec3__["a" /* default */].dot(pn, rd); + // ray is parallel to the plane + if (divider === 0) { + return null; + } + if (!out) { + out = new __WEBPACK_IMPORTED_MODULE_0__Vector3__["a" /* default */](); + } + var t = (__WEBPACK_IMPORTED_MODULE_1__glmatrix_vec3__["a" /* default */].dot(pn, ro) - d) / divider; + __WEBPACK_IMPORTED_MODULE_1__glmatrix_vec3__["a" /* default */].scaleAndAdd(out.array, ro, rd, -t); + out._dirty = true; + return out; + }, + + /** + * Mirror the ray against plane + * @param {clay.Plane} plane + */ + mirrorAgainstPlane: function (plane) { + // Distance to plane + var d = __WEBPACK_IMPORTED_MODULE_1__glmatrix_vec3__["a" /* default */].dot(plane.normal.array, this.direction.array); + __WEBPACK_IMPORTED_MODULE_1__glmatrix_vec3__["a" /* default */].scaleAndAdd(this.direction.array, this.direction.array, plane.normal.array, -d * 2); + this.direction._dirty = true; + }, + + distanceToPoint: (function () { + var v = __WEBPACK_IMPORTED_MODULE_1__glmatrix_vec3__["a" /* default */].create(); + return function (point) { + __WEBPACK_IMPORTED_MODULE_1__glmatrix_vec3__["a" /* default */].sub(v, point, this.origin.array); + // Distance from projection point to origin + var b = __WEBPACK_IMPORTED_MODULE_1__glmatrix_vec3__["a" /* default */].dot(v, this.direction.array); + if (b < 0) { + return __WEBPACK_IMPORTED_MODULE_1__glmatrix_vec3__["a" /* default */].distance(this.origin.array, point); + } + // Squared distance from center to origin + var c2 = __WEBPACK_IMPORTED_MODULE_1__glmatrix_vec3__["a" /* default */].lenSquared(v); + // Squared distance from center to projection point + return Math.sqrt(c2 - b * b); + }; + })(), + + /** + * Calculate intersection point between ray and sphere + * @param {clay.Vector3} center + * @param {number} radius + * @param {clay.Vector3} out + * @return {clay.Vector3} + */ + intersectSphere: (function () { + var v = __WEBPACK_IMPORTED_MODULE_1__glmatrix_vec3__["a" /* default */].create(); + return function (center, radius, out) { + var origin = this.origin.array; + var direction = this.direction.array; + center = center.array; + __WEBPACK_IMPORTED_MODULE_1__glmatrix_vec3__["a" /* default */].sub(v, center, origin); + // Distance from projection point to origin + var b = __WEBPACK_IMPORTED_MODULE_1__glmatrix_vec3__["a" /* default */].dot(v, direction); + // Squared distance from center to origin + var c2 = __WEBPACK_IMPORTED_MODULE_1__glmatrix_vec3__["a" /* default */].squaredLength(v); + // Squared distance from center to projection point + var d2 = c2 - b * b; + + var r2 = radius * radius; + // No intersection + if (d2 > r2) { + return; + } + + var a = Math.sqrt(r2 - d2); + // First intersect point + var t0 = b - a; + // Second intersect point + var t1 = b + a; + + if (!out) { + out = new __WEBPACK_IMPORTED_MODULE_0__Vector3__["a" /* default */](); + } + if (t0 < 0) { + if (t1 < 0) { + return null; + } + else { + __WEBPACK_IMPORTED_MODULE_1__glmatrix_vec3__["a" /* default */].scaleAndAdd(out.array, origin, direction, t1); + return out; + } + } + else { + __WEBPACK_IMPORTED_MODULE_1__glmatrix_vec3__["a" /* default */].scaleAndAdd(out.array, origin, direction, t0); + return out; + } + }; + })(), + + // http://www.scratchapixel.com/lessons/3d-basic-lessons/lesson-7-intersecting-simple-shapes/ray-box-intersection/ + /** + * Calculate intersection point between ray and bounding box + * @param {clay.BoundingBox} bbox + * @param {clay.Vector3} + * @return {clay.Vector3} + */ + intersectBoundingBox: function (bbox, out) { + var dir = this.direction.array; + var origin = this.origin.array; + var min = bbox.min.array; + var max = bbox.max.array; + + var invdirx = 1 / dir[0]; + var invdiry = 1 / dir[1]; + var invdirz = 1 / dir[2]; + + var tmin, tmax, tymin, tymax, tzmin, tzmax; + if (invdirx >= 0) { + tmin = (min[0] - origin[0]) * invdirx; + tmax = (max[0] - origin[0]) * invdirx; + } + else { + tmax = (min[0] - origin[0]) * invdirx; + tmin = (max[0] - origin[0]) * invdirx; + } + if (invdiry >= 0) { + tymin = (min[1] - origin[1]) * invdiry; + tymax = (max[1] - origin[1]) * invdiry; + } + else { + tymax = (min[1] - origin[1]) * invdiry; + tymin = (max[1] - origin[1]) * invdiry; + } + + if ((tmin > tymax) || (tymin > tmax)) { + return null; + } + + if (tymin > tmin || tmin !== tmin) { + tmin = tymin; + } + if (tymax < tmax || tmax !== tmax) { + tmax = tymax; + } + + if (invdirz >= 0) { + tzmin = (min[2] - origin[2]) * invdirz; + tzmax = (max[2] - origin[2]) * invdirz; + } + else { + tzmax = (min[2] - origin[2]) * invdirz; + tzmin = (max[2] - origin[2]) * invdirz; + } + + if ((tmin > tzmax) || (tzmin > tmax)) { + return null; + } + + if (tzmin > tmin || tmin !== tmin) { + tmin = tzmin; + } + if (tzmax < tmax || tmax !== tmax) { + tmax = tzmax; + } + if (tmax < 0) { + return null; + } + + var t = tmin >= 0 ? tmin : tmax; + + if (!out) { + out = new __WEBPACK_IMPORTED_MODULE_0__Vector3__["a" /* default */](); + } + __WEBPACK_IMPORTED_MODULE_1__glmatrix_vec3__["a" /* default */].scaleAndAdd(out.array, origin, dir, t); + return out; + }, + + // http://en.wikipedia.org/wiki/M%C3%B6ller%E2%80%93Trumbore_intersection_algorithm + /** + * Calculate intersection point between ray and three triangle vertices + * @param {clay.Vector3} a + * @param {clay.Vector3} b + * @param {clay.Vector3} c + * @param {boolean} singleSided, CW triangle will be ignored + * @param {clay.Vector3} [out] + * @param {clay.Vector3} [barycenteric] barycentric coords + * @return {clay.Vector3} + */ + intersectTriangle: (function () { + + var eBA = __WEBPACK_IMPORTED_MODULE_1__glmatrix_vec3__["a" /* default */].create(); + var eCA = __WEBPACK_IMPORTED_MODULE_1__glmatrix_vec3__["a" /* default */].create(); + var AO = __WEBPACK_IMPORTED_MODULE_1__glmatrix_vec3__["a" /* default */].create(); + var vCross = __WEBPACK_IMPORTED_MODULE_1__glmatrix_vec3__["a" /* default */].create(); + + return function (a, b, c, singleSided, out, barycenteric) { + var dir = this.direction.array; + var origin = this.origin.array; + a = a.array; + b = b.array; + c = c.array; + + __WEBPACK_IMPORTED_MODULE_1__glmatrix_vec3__["a" /* default */].sub(eBA, b, a); + __WEBPACK_IMPORTED_MODULE_1__glmatrix_vec3__["a" /* default */].sub(eCA, c, a); + + __WEBPACK_IMPORTED_MODULE_1__glmatrix_vec3__["a" /* default */].cross(vCross, eCA, dir); + + var det = __WEBPACK_IMPORTED_MODULE_1__glmatrix_vec3__["a" /* default */].dot(eBA, vCross); + + if (singleSided) { + if (det > -EPSILON) { + return null; + } + } + else { + if (det > -EPSILON && det < EPSILON) { + return null; + } + } + + __WEBPACK_IMPORTED_MODULE_1__glmatrix_vec3__["a" /* default */].sub(AO, origin, a); + var u = __WEBPACK_IMPORTED_MODULE_1__glmatrix_vec3__["a" /* default */].dot(vCross, AO) / det; + if (u < 0 || u > 1) { + return null; + } + + __WEBPACK_IMPORTED_MODULE_1__glmatrix_vec3__["a" /* default */].cross(vCross, eBA, AO); + var v = __WEBPACK_IMPORTED_MODULE_1__glmatrix_vec3__["a" /* default */].dot(dir, vCross) / det; + + if (v < 0 || v > 1 || (u + v > 1)) { + return null; + } + + __WEBPACK_IMPORTED_MODULE_1__glmatrix_vec3__["a" /* default */].cross(vCross, eBA, eCA); + var t = -__WEBPACK_IMPORTED_MODULE_1__glmatrix_vec3__["a" /* default */].dot(AO, vCross) / det; + + if (t < 0) { + return null; + } + + if (!out) { + out = new __WEBPACK_IMPORTED_MODULE_0__Vector3__["a" /* default */](); + } + if (barycenteric) { + __WEBPACK_IMPORTED_MODULE_0__Vector3__["a" /* default */].set(barycenteric, (1 - u - v), u, v); + } + __WEBPACK_IMPORTED_MODULE_1__glmatrix_vec3__["a" /* default */].scaleAndAdd(out.array, origin, dir, t); + + return out; + }; + })(), + + /** + * Apply an affine transform matrix to the ray + * @return {clay.Matrix4} matrix + */ + applyTransform: function (matrix) { + __WEBPACK_IMPORTED_MODULE_0__Vector3__["a" /* default */].add(this.direction, this.direction, this.origin); + __WEBPACK_IMPORTED_MODULE_0__Vector3__["a" /* default */].transformMat4(this.origin, this.origin, matrix); + __WEBPACK_IMPORTED_MODULE_0__Vector3__["a" /* default */].transformMat4(this.direction, this.direction, matrix); + + __WEBPACK_IMPORTED_MODULE_0__Vector3__["a" /* default */].sub(this.direction, this.direction, this.origin); + __WEBPACK_IMPORTED_MODULE_0__Vector3__["a" /* default */].normalize(this.direction, this.direction); + }, + + /** + * Copy values from another ray + * @param {clay.Ray} ray + */ + copy: function (ray) { + __WEBPACK_IMPORTED_MODULE_0__Vector3__["a" /* default */].copy(this.origin, ray.origin); + __WEBPACK_IMPORTED_MODULE_0__Vector3__["a" /* default */].copy(this.direction, ray.direction); + }, + + /** + * Clone a new ray + * @return {clay.Ray} + */ + clone: function () { + var ray = new Ray(); + ray.copy(this); + return ray; + } +}; + +/* harmony default export */ __webpack_exports__["a"] = (Ray); + + +/***/ }), +/* 55 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__common__ = __webpack_require__(20); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__vec3__ = __webpack_require__(12); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__vec4__ = __webpack_require__(33); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__mat3__ = __webpack_require__(34); + + +/* Copyright (c) 2013, Brandon Jones, Colin MacKenzie IV. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + + + + + + + +/** + * @class Quaternion + * @name quat + */ + +var quat = {}; + +/** + * Creates a new identity quat + * + * @returns {quat} a new quaternion + */ +quat.create = function() { + var out = new __WEBPACK_IMPORTED_MODULE_0__common__["a" /* GLMAT_ARRAY_TYPE */](4); + out[0] = 0; + out[1] = 0; + out[2] = 0; + out[3] = 1; + return out; +}; + +/** + * Sets a quaternion to represent the shortest rotation from one + * vector to another. + * + * Both vectors are assumed to be unit length. + * + * @param {quat} out the receiving quaternion. + * @param {vec3} a the initial vector + * @param {vec3} b the destination vector + * @returns {quat} out + */ +quat.rotationTo = (function() { + var tmpvec3 = __WEBPACK_IMPORTED_MODULE_1__vec3__["a" /* default */].create(); + var xUnitVec3 = __WEBPACK_IMPORTED_MODULE_1__vec3__["a" /* default */].fromValues(1,0,0); + var yUnitVec3 = __WEBPACK_IMPORTED_MODULE_1__vec3__["a" /* default */].fromValues(0,1,0); + + return function(out, a, b) { + var dot = __WEBPACK_IMPORTED_MODULE_1__vec3__["a" /* default */].dot(a, b); + if (dot < -0.999999) { + __WEBPACK_IMPORTED_MODULE_1__vec3__["a" /* default */].cross(tmpvec3, xUnitVec3, a); + if (__WEBPACK_IMPORTED_MODULE_1__vec3__["a" /* default */].length(tmpvec3) < 0.000001) + __WEBPACK_IMPORTED_MODULE_1__vec3__["a" /* default */].cross(tmpvec3, yUnitVec3, a); + __WEBPACK_IMPORTED_MODULE_1__vec3__["a" /* default */].normalize(tmpvec3, tmpvec3); + quat.setAxisAngle(out, tmpvec3, Math.PI); + return out; + } else if (dot > 0.999999) { + out[0] = 0; + out[1] = 0; + out[2] = 0; + out[3] = 1; + return out; + } else { + __WEBPACK_IMPORTED_MODULE_1__vec3__["a" /* default */].cross(tmpvec3, a, b); + out[0] = tmpvec3[0]; + out[1] = tmpvec3[1]; + out[2] = tmpvec3[2]; + out[3] = 1 + dot; + return quat.normalize(out, out); + } + }; +})(); + +/** + * Sets the specified quaternion with values corresponding to the given + * axes. Each axis is a vec3 and is expected to be unit length and + * perpendicular to all other specified axes. + * + * @param {vec3} view the vector representing the viewing direction + * @param {vec3} right the vector representing the local "right" direction + * @param {vec3} up the vector representing the local "up" direction + * @returns {quat} out + */ +quat.setAxes = (function() { + var matr = __WEBPACK_IMPORTED_MODULE_3__mat3__["a" /* default */].create(); + + return function(out, view, right, up) { + matr[0] = right[0]; + matr[3] = right[1]; + matr[6] = right[2]; + + matr[1] = up[0]; + matr[4] = up[1]; + matr[7] = up[2]; + + matr[2] = -view[0]; + matr[5] = -view[1]; + matr[8] = -view[2]; + + return quat.normalize(out, quat.fromMat3(out, matr)); + }; +})(); + +/** + * Creates a new quat initialized with values from an existing quaternion + * + * @param {quat} a quaternion to clone + * @returns {quat} a new quaternion + * @function + */ +quat.clone = __WEBPACK_IMPORTED_MODULE_2__vec4__["a" /* default */].clone; + +/** + * Creates a new quat initialized with the given values + * + * @param {Number} x X component + * @param {Number} y Y component + * @param {Number} z Z component + * @param {Number} w W component + * @returns {quat} a new quaternion + * @function + */ +quat.fromValues = __WEBPACK_IMPORTED_MODULE_2__vec4__["a" /* default */].fromValues; + +/** + * Copy the values from one quat to another + * + * @param {quat} out the receiving quaternion + * @param {quat} a the source quaternion + * @returns {quat} out + * @function + */ +quat.copy = __WEBPACK_IMPORTED_MODULE_2__vec4__["a" /* default */].copy; + +/** + * Set the components of a quat to the given values + * + * @param {quat} out the receiving quaternion + * @param {Number} x X component + * @param {Number} y Y component + * @param {Number} z Z component + * @param {Number} w W component + * @returns {quat} out + * @function + */ +quat.set = __WEBPACK_IMPORTED_MODULE_2__vec4__["a" /* default */].set; + +/** + * Set a quat to the identity quaternion + * + * @param {quat} out the receiving quaternion + * @returns {quat} out + */ +quat.identity = function(out) { + out[0] = 0; + out[1] = 0; + out[2] = 0; + out[3] = 1; + return out; +}; + +/** + * Sets a quat from the given angle and rotation axis, + * then returns it. + * + * @param {quat} out the receiving quaternion + * @param {vec3} axis the axis around which to rotate + * @param {Number} rad the angle in radians + * @returns {quat} out + **/ +quat.setAxisAngle = function(out, axis, rad) { + rad = rad * 0.5; + var s = Math.sin(rad); + out[0] = s * axis[0]; + out[1] = s * axis[1]; + out[2] = s * axis[2]; + out[3] = Math.cos(rad); + return out; +}; + +/** + * Adds two quat's + * + * @param {quat} out the receiving quaternion + * @param {quat} a the first operand + * @param {quat} b the second operand + * @returns {quat} out + * @function + */ +quat.add = __WEBPACK_IMPORTED_MODULE_2__vec4__["a" /* default */].add; + +/** + * Multiplies two quat's + * + * @param {quat} out the receiving quaternion + * @param {quat} a the first operand + * @param {quat} b the second operand + * @returns {quat} out + */ +quat.multiply = function(out, a, b) { + var ax = a[0], ay = a[1], az = a[2], aw = a[3], + bx = b[0], by = b[1], bz = b[2], bw = b[3]; + + out[0] = ax * bw + aw * bx + ay * bz - az * by; + out[1] = ay * bw + aw * by + az * bx - ax * bz; + out[2] = az * bw + aw * bz + ax * by - ay * bx; + out[3] = aw * bw - ax * bx - ay * by - az * bz; + return out; +}; + +/** + * Alias for {@link quat.multiply} + * @function + */ +quat.mul = quat.multiply; + +/** + * Scales a quat by a scalar number + * + * @param {quat} out the receiving vector + * @param {quat} a the vector to scale + * @param {Number} b amount to scale the vector by + * @returns {quat} out + * @function + */ +quat.scale = __WEBPACK_IMPORTED_MODULE_2__vec4__["a" /* default */].scale; + +/** + * Rotates a quaternion by the given angle about the X axis + * + * @param {quat} out quat receiving operation result + * @param {quat} a quat to rotate + * @param {number} rad angle (in radians) to rotate + * @returns {quat} out + */ +quat.rotateX = function (out, a, rad) { + rad *= 0.5; + + var ax = a[0], ay = a[1], az = a[2], aw = a[3], + bx = Math.sin(rad), bw = Math.cos(rad); + + out[0] = ax * bw + aw * bx; + out[1] = ay * bw + az * bx; + out[2] = az * bw - ay * bx; + out[3] = aw * bw - ax * bx; + return out; +}; + +/** + * Rotates a quaternion by the given angle about the Y axis + * + * @param {quat} out quat receiving operation result + * @param {quat} a quat to rotate + * @param {number} rad angle (in radians) to rotate + * @returns {quat} out + */ +quat.rotateY = function (out, a, rad) { + rad *= 0.5; + + var ax = a[0], ay = a[1], az = a[2], aw = a[3], + by = Math.sin(rad), bw = Math.cos(rad); + + out[0] = ax * bw - az * by; + out[1] = ay * bw + aw * by; + out[2] = az * bw + ax * by; + out[3] = aw * bw - ay * by; + return out; +}; + +/** + * Rotates a quaternion by the given angle about the Z axis + * + * @param {quat} out quat receiving operation result + * @param {quat} a quat to rotate + * @param {number} rad angle (in radians) to rotate + * @returns {quat} out + */ +quat.rotateZ = function (out, a, rad) { + rad *= 0.5; + + var ax = a[0], ay = a[1], az = a[2], aw = a[3], + bz = Math.sin(rad), bw = Math.cos(rad); + + out[0] = ax * bw + ay * bz; + out[1] = ay * bw - ax * bz; + out[2] = az * bw + aw * bz; + out[3] = aw * bw - az * bz; + return out; +}; + +/** + * Calculates the W component of a quat from the X, Y, and Z components. + * Assumes that quaternion is 1 unit in length. + * Any existing W component will be ignored. + * + * @param {quat} out the receiving quaternion + * @param {quat} a quat to calculate W component of + * @returns {quat} out + */ +quat.calculateW = function (out, a) { + var x = a[0], y = a[1], z = a[2]; + + out[0] = x; + out[1] = y; + out[2] = z; + out[3] = Math.sqrt(Math.abs(1.0 - x * x - y * y - z * z)); + return out; +}; + +/** + * Calculates the dot product of two quat's + * + * @param {quat} a the first operand + * @param {quat} b the second operand + * @returns {Number} dot product of a and b + * @function + */ +quat.dot = __WEBPACK_IMPORTED_MODULE_2__vec4__["a" /* default */].dot; + +/** + * Performs a linear interpolation between two quat's + * + * @param {quat} out the receiving quaternion + * @param {quat} a the first operand + * @param {quat} b the second operand + * @param {Number} t interpolation amount between the two inputs + * @returns {quat} out + * @function + */ +quat.lerp = __WEBPACK_IMPORTED_MODULE_2__vec4__["a" /* default */].lerp; + +/** + * Performs a spherical linear interpolation between two quat + * + * @param {quat} out the receiving quaternion + * @param {quat} a the first operand + * @param {quat} b the second operand + * @param {Number} t interpolation amount between the two inputs + * @returns {quat} out + */ +quat.slerp = function (out, a, b, t) { + // benchmarks: + // http://jsperf.com/quaternion-slerp-implementations + + var ax = a[0], ay = a[1], az = a[2], aw = a[3], + bx = b[0], by = b[1], bz = b[2], bw = b[3]; + + var omega, cosom, sinom, scale0, scale1; + + // calc cosine + cosom = ax * bx + ay * by + az * bz + aw * bw; + // adjust signs (if necessary) + if ( cosom < 0.0 ) { + cosom = -cosom; + bx = - bx; + by = - by; + bz = - bz; + bw = - bw; + } + // calculate coefficients + if ( (1.0 - cosom) > 0.000001 ) { + // standard case (slerp) + omega = Math.acos(cosom); + sinom = Math.sin(omega); + scale0 = Math.sin((1.0 - t) * omega) / sinom; + scale1 = Math.sin(t * omega) / sinom; + } else { + // "from" and "to" quaternions are very close + // ... so we can do a linear interpolation + scale0 = 1.0 - t; + scale1 = t; + } + // calculate final values + out[0] = scale0 * ax + scale1 * bx; + out[1] = scale0 * ay + scale1 * by; + out[2] = scale0 * az + scale1 * bz; + out[3] = scale0 * aw + scale1 * bw; + + return out; +}; + +/** + * Calculates the inverse of a quat + * + * @param {quat} out the receiving quaternion + * @param {quat} a quat to calculate inverse of + * @returns {quat} out + */ +quat.invert = function(out, a) { + var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], + dot = a0*a0 + a1*a1 + a2*a2 + a3*a3, + invDot = dot ? 1.0/dot : 0; + + // TODO: Would be faster to return [0,0,0,0] immediately if dot == 0 + + out[0] = -a0*invDot; + out[1] = -a1*invDot; + out[2] = -a2*invDot; + out[3] = a3*invDot; + return out; +}; + +/** + * Calculates the conjugate of a quat + * If the quaternion is normalized, this function is faster than quat.inverse and produces the same result. + * + * @param {quat} out the receiving quaternion + * @param {quat} a quat to calculate conjugate of + * @returns {quat} out + */ +quat.conjugate = function (out, a) { + out[0] = -a[0]; + out[1] = -a[1]; + out[2] = -a[2]; + out[3] = a[3]; + return out; +}; + +/** + * Calculates the length of a quat + * + * @param {quat} a vector to calculate length of + * @returns {Number} length of a + * @function + */ +quat.length = __WEBPACK_IMPORTED_MODULE_2__vec4__["a" /* default */].length; + +/** + * Alias for {@link quat.length} + * @function + */ +quat.len = quat.length; + +/** + * Calculates the squared length of a quat + * + * @param {quat} a vector to calculate squared length of + * @returns {Number} squared length of a + * @function + */ +quat.squaredLength = __WEBPACK_IMPORTED_MODULE_2__vec4__["a" /* default */].squaredLength; + +/** + * Alias for {@link quat.squaredLength} + * @function + */ +quat.sqrLen = quat.squaredLength; + +/** + * Normalize a quat + * + * @param {quat} out the receiving quaternion + * @param {quat} a quaternion to normalize + * @returns {quat} out + * @function + */ +quat.normalize = __WEBPACK_IMPORTED_MODULE_2__vec4__["a" /* default */].normalize; + +/** + * Creates a quaternion from the given 3x3 rotation matrix. + * + * NOTE: The resultant quaternion is not normalized, so you should be sure + * to renormalize the quaternion yourself where necessary. + * + * @param {quat} out the receiving quaternion + * @param {mat3} m rotation matrix + * @returns {quat} out + * @function + */ +quat.fromMat3 = function(out, m) { + // Algorithm in Ken Shoemake's article in 1987 SIGGRAPH course notes + // article "Quaternion Calculus and Fast Animation". + var fTrace = m[0] + m[4] + m[8]; + var fRoot; + + if ( fTrace > 0.0 ) { + // |w| > 1/2, may as well choose w > 1/2 + fRoot = Math.sqrt(fTrace + 1.0); // 2w + out[3] = 0.5 * fRoot; + fRoot = 0.5/fRoot; // 1/(4w) + out[0] = (m[5]-m[7])*fRoot; + out[1] = (m[6]-m[2])*fRoot; + out[2] = (m[1]-m[3])*fRoot; + } else { + // |w| <= 1/2 + var i = 0; + if ( m[4] > m[0] ) + i = 1; + if ( m[8] > m[i*3+i] ) + i = 2; + var j = (i+1)%3; + var k = (i+2)%3; + + fRoot = Math.sqrt(m[i*3+i]-m[j*3+j]-m[k*3+k] + 1.0); + out[i] = 0.5 * fRoot; + fRoot = 0.5 / fRoot; + out[3] = (m[j*3+k] - m[k*3+j]) * fRoot; + out[j] = (m[j*3+i] + m[i*3+j]) * fRoot; + out[k] = (m[k*3+i] + m[i*3+k]) * fRoot; + } + + return out; +}; + +/* harmony default export */ __webpack_exports__["a"] = (quat); + +/***/ }), +/* 56 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__glmatrix_quat__ = __webpack_require__(55); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__glmatrix_mat3__ = __webpack_require__(34); + + + +/** + * @constructor + * @alias clay.Quaternion + * @param {number} x + * @param {number} y + * @param {number} z + * @param {number} w + */ +var Quaternion = function (x, y, z, w) { + + x = x || 0; + y = y || 0; + z = z || 0; + w = w === undefined ? 1 : w; + + /** + * Storage of Quaternion, read and write of x, y, z, w will change the values in array + * All methods also operate on the array instead of x, y, z, w components + * @name array + * @type {Float32Array} + * @memberOf clay.Quaternion# + */ + this.array = __WEBPACK_IMPORTED_MODULE_0__glmatrix_quat__["a" /* default */].fromValues(x, y, z, w); + + /** + * Dirty flag is used by the Node to determine + * if the matrix is updated to latest + * @name _dirty + * @type {boolean} + * @memberOf clay.Quaternion# + */ + this._dirty = true; +}; + +Quaternion.prototype = { + + constructor: Quaternion, + + /** + * Add b to self + * @param {clay.Quaternion} b + * @return {clay.Quaternion} + */ + add: function (b) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_quat__["a" /* default */].add(this.array, this.array, b.array); + this._dirty = true; + return this; + }, + + /** + * Calculate the w component from x, y, z component + * @return {clay.Quaternion} + */ + calculateW: function () { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_quat__["a" /* default */].calculateW(this.array, this.array); + this._dirty = true; + return this; + }, + + /** + * Set x, y and z components + * @param {number} x + * @param {number} y + * @param {number} z + * @param {number} w + * @return {clay.Quaternion} + */ + set: function (x, y, z, w) { + this.array[0] = x; + this.array[1] = y; + this.array[2] = z; + this.array[3] = w; + this._dirty = true; + return this; + }, + + /** + * Set x, y, z and w components from array + * @param {Float32Array|number[]} arr + * @return {clay.Quaternion} + */ + setArray: function (arr) { + this.array[0] = arr[0]; + this.array[1] = arr[1]; + this.array[2] = arr[2]; + this.array[3] = arr[3]; + + this._dirty = true; + return this; + }, + + /** + * Clone a new Quaternion + * @return {clay.Quaternion} + */ + clone: function () { + return new Quaternion(this.x, this.y, this.z, this.w); + }, + + /** + * Calculates the conjugate of self If the quaternion is normalized, + * this function is faster than invert and produces the same result. + * + * @return {clay.Quaternion} + */ + conjugate: function () { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_quat__["a" /* default */].conjugate(this.array, this.array); + this._dirty = true; + return this; + }, + + /** + * Copy from b + * @param {clay.Quaternion} b + * @return {clay.Quaternion} + */ + copy: function (b) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_quat__["a" /* default */].copy(this.array, b.array); + this._dirty = true; + return this; + }, + + /** + * Dot product of self and b + * @param {clay.Quaternion} b + * @return {number} + */ + dot: function (b) { + return __WEBPACK_IMPORTED_MODULE_0__glmatrix_quat__["a" /* default */].dot(this.array, b.array); + }, + + /** + * Set from the given 3x3 rotation matrix + * @param {clay.Matrix3} m + * @return {clay.Quaternion} + */ + fromMat3: function (m) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_quat__["a" /* default */].fromMat3(this.array, m.array); + this._dirty = true; + return this; + }, + + /** + * Set from the given 4x4 rotation matrix + * The 4th column and 4th row will be droped + * @param {clay.Matrix4} m + * @return {clay.Quaternion} + */ + fromMat4: (function () { + var m3 = __WEBPACK_IMPORTED_MODULE_1__glmatrix_mat3__["a" /* default */].create(); + return function (m) { + __WEBPACK_IMPORTED_MODULE_1__glmatrix_mat3__["a" /* default */].fromMat4(m3, m.array); + // TODO Not like mat4, mat3 in glmatrix seems to be row-based + __WEBPACK_IMPORTED_MODULE_1__glmatrix_mat3__["a" /* default */].transpose(m3, m3); + __WEBPACK_IMPORTED_MODULE_0__glmatrix_quat__["a" /* default */].fromMat3(this.array, m3); + this._dirty = true; + return this; + }; + })(), + + /** + * Set to identity quaternion + * @return {clay.Quaternion} + */ + identity: function () { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_quat__["a" /* default */].identity(this.array); + this._dirty = true; + return this; + }, + /** + * Invert self + * @return {clay.Quaternion} + */ + invert: function () { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_quat__["a" /* default */].invert(this.array, this.array); + this._dirty = true; + return this; + }, + /** + * Alias of length + * @return {number} + */ + len: function () { + return __WEBPACK_IMPORTED_MODULE_0__glmatrix_quat__["a" /* default */].len(this.array); + }, + + /** + * Calculate the length + * @return {number} + */ + length: function () { + return __WEBPACK_IMPORTED_MODULE_0__glmatrix_quat__["a" /* default */].length(this.array); + }, + + /** + * Linear interpolation between a and b + * @param {clay.Quaternion} a + * @param {clay.Quaternion} b + * @param {number} t + * @return {clay.Quaternion} + */ + lerp: function (a, b, t) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_quat__["a" /* default */].lerp(this.array, a.array, b.array, t); + this._dirty = true; + return this; + }, + + /** + * Alias for multiply + * @param {clay.Quaternion} b + * @return {clay.Quaternion} + */ + mul: function (b) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_quat__["a" /* default */].mul(this.array, this.array, b.array); + this._dirty = true; + return this; + }, + + /** + * Alias for multiplyLeft + * @param {clay.Quaternion} a + * @return {clay.Quaternion} + */ + mulLeft: function (a) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_quat__["a" /* default */].multiply(this.array, a.array, this.array); + this._dirty = true; + return this; + }, + + /** + * Mutiply self and b + * @param {clay.Quaternion} b + * @return {clay.Quaternion} + */ + multiply: function (b) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_quat__["a" /* default */].multiply(this.array, this.array, b.array); + this._dirty = true; + return this; + }, + + /** + * Mutiply a and self + * Quaternion mutiply is not commutative, so the result of mutiplyLeft is different with multiply. + * @param {clay.Quaternion} a + * @return {clay.Quaternion} + */ + multiplyLeft: function (a) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_quat__["a" /* default */].multiply(this.array, a.array, this.array); + this._dirty = true; + return this; + }, + + /** + * Normalize self + * @return {clay.Quaternion} + */ + normalize: function () { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_quat__["a" /* default */].normalize(this.array, this.array); + this._dirty = true; + return this; + }, + + /** + * Rotate self by a given radian about X axis + * @param {number} rad + * @return {clay.Quaternion} + */ + rotateX: function (rad) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_quat__["a" /* default */].rotateX(this.array, this.array, rad); + this._dirty = true; + return this; + }, + + /** + * Rotate self by a given radian about Y axis + * @param {number} rad + * @return {clay.Quaternion} + */ + rotateY: function (rad) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_quat__["a" /* default */].rotateY(this.array, this.array, rad); + this._dirty = true; + return this; + }, + + /** + * Rotate self by a given radian about Z axis + * @param {number} rad + * @return {clay.Quaternion} + */ + rotateZ: function (rad) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_quat__["a" /* default */].rotateZ(this.array, this.array, rad); + this._dirty = true; + return this; + }, + + /** + * Sets self to represent the shortest rotation from Vector3 a to Vector3 b. + * a and b needs to be normalized + * @param {clay.Vector3} a + * @param {clay.Vector3} b + * @return {clay.Quaternion} + */ + rotationTo: function (a, b) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_quat__["a" /* default */].rotationTo(this.array, a.array, b.array); + this._dirty = true; + return this; + }, + /** + * Sets self with values corresponding to the given axes + * @param {clay.Vector3} view + * @param {clay.Vector3} right + * @param {clay.Vector3} up + * @return {clay.Quaternion} + */ + setAxes: function (view, right, up) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_quat__["a" /* default */].setAxes(this.array, view.array, right.array, up.array); + this._dirty = true; + return this; + }, + + /** + * Sets self with a rotation axis and rotation angle + * @param {clay.Vector3} axis + * @param {number} rad + * @return {clay.Quaternion} + */ + setAxisAngle: function (axis, rad) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_quat__["a" /* default */].setAxisAngle(this.array, axis.array, rad); + this._dirty = true; + return this; + }, + /** + * Perform spherical linear interpolation between a and b + * @param {clay.Quaternion} a + * @param {clay.Quaternion} b + * @param {number} t + * @return {clay.Quaternion} + */ + slerp: function (a, b, t) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_quat__["a" /* default */].slerp(this.array, a.array, b.array, t); + this._dirty = true; + return this; + }, + + /** + * Alias for squaredLength + * @return {number} + */ + sqrLen: function () { + return __WEBPACK_IMPORTED_MODULE_0__glmatrix_quat__["a" /* default */].sqrLen(this.array); + }, + + /** + * Squared length of self + * @return {number} + */ + squaredLength: function () { + return __WEBPACK_IMPORTED_MODULE_0__glmatrix_quat__["a" /* default */].squaredLength(this.array); + }, + + /** + * Set from euler + * @param {clay.Vector3} v + * @param {String} order + */ + fromEuler: function (v, order) { + return Quaternion.fromEuler(this, v, order); + }, + + toString: function () { + return '[' + Array.prototype.join.call(this.array, ',') + ']'; + }, + + toArray: function () { + return Array.prototype.slice.call(this.array); + } +}; + +var defineProperty = Object.defineProperty; +// Getter and Setter +if (defineProperty) { + + var proto = Quaternion.prototype; + /** + * @name x + * @type {number} + * @memberOf clay.Quaternion + * @instance + */ + defineProperty(proto, 'x', { + get: function () { + return this.array[0]; + }, + set: function (value) { + this.array[0] = value; + this._dirty = true; + } + }); + + /** + * @name y + * @type {number} + * @memberOf clay.Quaternion + * @instance + */ + defineProperty(proto, 'y', { + get: function () { + return this.array[1]; + }, + set: function (value) { + this.array[1] = value; + this._dirty = true; + } + }); + + /** + * @name z + * @type {number} + * @memberOf clay.Quaternion + * @instance + */ + defineProperty(proto, 'z', { + get: function () { + return this.array[2]; + }, + set: function (value) { + this.array[2] = value; + this._dirty = true; + } + }); + + /** + * @name w + * @type {number} + * @memberOf clay.Quaternion + * @instance + */ + defineProperty(proto, 'w', { + get: function () { + return this.array[3]; + }, + set: function (value) { + this.array[3] = value; + this._dirty = true; + } + }); +} + +// Supply methods that are not in place + +/** + * @param {clay.Quaternion} out + * @param {clay.Quaternion} a + * @param {clay.Quaternion} b + * @return {clay.Quaternion} + */ +Quaternion.add = function (out, a, b) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_quat__["a" /* default */].add(out.array, a.array, b.array); + out._dirty = true; + return out; +}; + +/** + * @param {clay.Quaternion} out + * @param {number} x + * @param {number} y + * @param {number} z + * @param {number} w + * @return {clay.Quaternion} + */ +Quaternion.set = function (out, x, y, z, w) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_quat__["a" /* default */].set(out.array, x, y, z, w); + out._dirty = true; +}; + +/** + * @param {clay.Quaternion} out + * @param {clay.Quaternion} b + * @return {clay.Quaternion} + */ +Quaternion.copy = function (out, b) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_quat__["a" /* default */].copy(out.array, b.array); + out._dirty = true; + return out; +}; + +/** + * @param {clay.Quaternion} out + * @param {clay.Quaternion} a + * @return {clay.Quaternion} + */ +Quaternion.calculateW = function (out, a) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_quat__["a" /* default */].calculateW(out.array, a.array); + out._dirty = true; + return out; +}; + +/** + * @param {clay.Quaternion} out + * @param {clay.Quaternion} a + * @return {clay.Quaternion} + */ +Quaternion.conjugate = function (out, a) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_quat__["a" /* default */].conjugate(out.array, a.array); + out._dirty = true; + return out; +}; + +/** + * @param {clay.Quaternion} out + * @return {clay.Quaternion} + */ +Quaternion.identity = function (out) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_quat__["a" /* default */].identity(out.array); + out._dirty = true; + return out; +}; + +/** + * @param {clay.Quaternion} out + * @param {clay.Quaternion} a + * @return {clay.Quaternion} + */ +Quaternion.invert = function (out, a) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_quat__["a" /* default */].invert(out.array, a.array); + out._dirty = true; + return out; +}; + +/** + * @param {clay.Quaternion} a + * @param {clay.Quaternion} b + * @return {number} + */ +Quaternion.dot = function (a, b) { + return __WEBPACK_IMPORTED_MODULE_0__glmatrix_quat__["a" /* default */].dot(a.array, b.array); +}; + +/** + * @param {clay.Quaternion} a + * @return {number} + */ +Quaternion.len = function (a) { + return __WEBPACK_IMPORTED_MODULE_0__glmatrix_quat__["a" /* default */].length(a.array); +}; + +// Quaternion.length = Quaternion.len; + +/** + * @param {clay.Quaternion} out + * @param {clay.Quaternion} a + * @param {clay.Quaternion} b + * @param {number} t + * @return {clay.Quaternion} + */ +Quaternion.lerp = function (out, a, b, t) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_quat__["a" /* default */].lerp(out.array, a.array, b.array, t); + out._dirty = true; + return out; +}; + +/** + * @param {clay.Quaternion} out + * @param {clay.Quaternion} a + * @param {clay.Quaternion} b + * @param {number} t + * @return {clay.Quaternion} + */ +Quaternion.slerp = function (out, a, b, t) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_quat__["a" /* default */].slerp(out.array, a.array, b.array, t); + out._dirty = true; + return out; +}; + +/** + * @param {clay.Quaternion} out + * @param {clay.Quaternion} a + * @param {clay.Quaternion} b + * @return {clay.Quaternion} + */ +Quaternion.mul = function (out, a, b) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_quat__["a" /* default */].multiply(out.array, a.array, b.array); + out._dirty = true; + return out; +}; + +/** + * @function + * @param {clay.Quaternion} out + * @param {clay.Quaternion} a + * @param {clay.Quaternion} b + * @return {clay.Quaternion} + */ +Quaternion.multiply = Quaternion.mul; + +/** + * @param {clay.Quaternion} out + * @param {clay.Quaternion} a + * @param {number} rad + * @return {clay.Quaternion} + */ +Quaternion.rotateX = function (out, a, rad) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_quat__["a" /* default */].rotateX(out.array, a.array, rad); + out._dirty = true; + return out; +}; + +/** + * @param {clay.Quaternion} out + * @param {clay.Quaternion} a + * @param {number} rad + * @return {clay.Quaternion} + */ +Quaternion.rotateY = function (out, a, rad) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_quat__["a" /* default */].rotateY(out.array, a.array, rad); + out._dirty = true; + return out; +}; + +/** + * @param {clay.Quaternion} out + * @param {clay.Quaternion} a + * @param {number} rad + * @return {clay.Quaternion} + */ +Quaternion.rotateZ = function (out, a, rad) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_quat__["a" /* default */].rotateZ(out.array, a.array, rad); + out._dirty = true; + return out; +}; + +/** + * @param {clay.Quaternion} out + * @param {clay.Vector3} axis + * @param {number} rad + * @return {clay.Quaternion} + */ +Quaternion.setAxisAngle = function (out, axis, rad) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_quat__["a" /* default */].setAxisAngle(out.array, axis.array, rad); + out._dirty = true; + return out; +}; + +/** + * @param {clay.Quaternion} out + * @param {clay.Quaternion} a + * @return {clay.Quaternion} + */ +Quaternion.normalize = function (out, a) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_quat__["a" /* default */].normalize(out.array, a.array); + out._dirty = true; + return out; +}; + +/** + * @param {clay.Quaternion} a + * @return {number} + */ +Quaternion.sqrLen = function (a) { + return __WEBPACK_IMPORTED_MODULE_0__glmatrix_quat__["a" /* default */].sqrLen(a.array); +}; + +/** + * @function + * @param {clay.Quaternion} a + * @return {number} + */ +Quaternion.squaredLength = Quaternion.sqrLen; + +/** + * @param {clay.Quaternion} out + * @param {clay.Matrix3} m + * @return {clay.Quaternion} + */ +Quaternion.fromMat3 = function (out, m) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_quat__["a" /* default */].fromMat3(out.array, m.array); + out._dirty = true; + return out; +}; + +/** + * @param {clay.Quaternion} out + * @param {clay.Vector3} view + * @param {clay.Vector3} right + * @param {clay.Vector3} up + * @return {clay.Quaternion} + */ +Quaternion.setAxes = function (out, view, right, up) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_quat__["a" /* default */].setAxes(out.array, view.array, right.array, up.array); + out._dirty = true; + return out; +}; + +/** + * @param {clay.Quaternion} out + * @param {clay.Vector3} a + * @param {clay.Vector3} b + * @return {clay.Quaternion} + */ +Quaternion.rotationTo = function (out, a, b) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_quat__["a" /* default */].rotationTo(out.array, a.array, b.array); + out._dirty = true; + return out; +}; + +/** + * Set quaternion from euler + * @param {clay.Quaternion} out + * @param {clay.Vector3} v + * @param {String} order + */ +Quaternion.fromEuler = function (out, v, order) { + + out._dirty = true; + + v = v.array; + var target = out.array; + var c1 = Math.cos(v[0] / 2); + var c2 = Math.cos(v[1] / 2); + var c3 = Math.cos(v[2] / 2); + var s1 = Math.sin(v[0] / 2); + var s2 = Math.sin(v[1] / 2); + var s3 = Math.sin(v[2] / 2); + + var order = (order || 'XYZ').toUpperCase(); + + // http://www.mathworks.com/matlabcentral/fileexchange/ + // 20696-function-to-convert-between-dcm-euler-angles-quaternions-and-euler-vectors/ + // content/SpinCalc.m + + switch (order) { + case 'XYZ': + target[0] = s1 * c2 * c3 + c1 * s2 * s3; + target[1] = c1 * s2 * c3 - s1 * c2 * s3; + target[2] = c1 * c2 * s3 + s1 * s2 * c3; + target[3] = c1 * c2 * c3 - s1 * s2 * s3; + break; + case 'YXZ': + target[0] = s1 * c2 * c3 + c1 * s2 * s3; + target[1] = c1 * s2 * c3 - s1 * c2 * s3; + target[2] = c1 * c2 * s3 - s1 * s2 * c3; + target[3] = c1 * c2 * c3 + s1 * s2 * s3; + break; + case 'ZXY': + target[0] = s1 * c2 * c3 - c1 * s2 * s3; + target[1] = c1 * s2 * c3 + s1 * c2 * s3; + target[2] = c1 * c2 * s3 + s1 * s2 * c3; + target[3] = c1 * c2 * c3 - s1 * s2 * s3; + break; + case 'ZYX': + target[0] = s1 * c2 * c3 - c1 * s2 * s3; + target[1] = c1 * s2 * c3 + s1 * c2 * s3; + target[2] = c1 * c2 * s3 - s1 * s2 * c3; + target[3] = c1 * c2 * c3 + s1 * s2 * s3; + break; + case 'YZX': + target[0] = s1 * c2 * c3 + c1 * s2 * s3; + target[1] = c1 * s2 * c3 + s1 * c2 * s3; + target[2] = c1 * c2 * s3 - s1 * s2 * c3; + target[3] = c1 * c2 * c3 - s1 * s2 * s3; + break; + case 'XZY': + target[0] = s1 * c2 * c3 - c1 * s2 * s3; + target[1] = c1 * s2 * c3 - s1 * c2 * s3; + target[2] = c1 * c2 * s3 + s1 * s2 * c3; + target[3] = c1 * c2 * c3 + s1 * s2 * s3; + break; + } +}; + +/* harmony default export */ __webpack_exports__["a"] = (Quaternion); + + +/***/ }), +/* 57 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +var DIRTY_PREFIX = '__dt__'; + +var Cache = function () { + + this._contextId = 0; + + this._caches = []; + + this._context = {}; +}; + +Cache.prototype = { + + use: function (contextId, documentSchema) { + var caches = this._caches; + if (!caches[contextId]) { + caches[contextId] = {}; + + if (documentSchema) { + caches[contextId] = documentSchema(); + } + } + this._contextId = contextId; + + this._context = caches[contextId]; + }, + + put: function (key, value) { + this._context[key] = value; + }, + + get: function (key) { + return this._context[key]; + }, + + dirty: function (field) { + field = field || ''; + var key = DIRTY_PREFIX + field; + this.put(key, true); + }, + + dirtyAll: function (field) { + field = field || ''; + var key = DIRTY_PREFIX + field; + var caches = this._caches; + for (var i = 0; i < caches.length; i++) { + if (caches[i]) { + caches[i][key] = true; + } + } + }, + + fresh: function (field) { + field = field || ''; + var key = DIRTY_PREFIX + field; + this.put(key, false); + }, + + freshAll: function (field) { + field = field || ''; + var key = DIRTY_PREFIX + field; + var caches = this._caches; + for (var i = 0; i < caches.length; i++) { + if (caches[i]) { + caches[i][key] = false; + } + } + }, + + isDirty: function (field) { + field = field || ''; + var key = DIRTY_PREFIX + field; + var context = this._context; + return !context.hasOwnProperty(key) + || context[key] === true; + }, + + deleteContext: function (contextId) { + delete this._caches[contextId]; + this._context = {}; + }, + + delete: function (key) { + delete this._context[key]; + }, + + clearAll: function () { + this._caches = {}; + }, + + getContext: function () { + return this._context; + }, + + eachContext : function (cb, context) { + var keys = Object.keys(this._caches); + keys.forEach(function (key) { + cb && cb.call(context, key); + }); + }, + + miss: function (key) { + return ! this._context.hasOwnProperty(key); + } +}; + +Cache.prototype.constructor = Cache; + +/* harmony default export */ __webpack_exports__["a"] = (Cache); + + +/***/ }), +/* 58 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__Node__ = __webpack_require__(35); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__math_Matrix4__ = __webpack_require__(9); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__math_Frustum__ = __webpack_require__(59); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__math_Ray__ = __webpack_require__(54); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4__glmatrix_vec4__ = __webpack_require__(33); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_5__glmatrix_vec3__ = __webpack_require__(12); + + + + + + + + + +/** + * @constructor clay.Camera + * @extends clay.Node + */ +var Camera = __WEBPACK_IMPORTED_MODULE_0__Node__["a" /* default */].extend(function () { + return /** @lends clay.Camera# */ { + /** + * Camera projection matrix + * @type {clay.Matrix4} + */ + projectionMatrix: new __WEBPACK_IMPORTED_MODULE_1__math_Matrix4__["a" /* default */](), + + /** + * Inverse of camera projection matrix + * @type {clay.Matrix4} + */ + invProjectionMatrix: new __WEBPACK_IMPORTED_MODULE_1__math_Matrix4__["a" /* default */](), + + /** + * View matrix, equal to inverse of camera's world matrix + * @type {clay.Matrix4} + */ + viewMatrix: new __WEBPACK_IMPORTED_MODULE_1__math_Matrix4__["a" /* default */](), + + /** + * Camera frustum in view space + * @type {clay.Frustum} + */ + frustum: new __WEBPACK_IMPORTED_MODULE_2__math_Frustum__["a" /* default */]() + }; +}, function () { + this.update(true); +}, +/** @lends clay.Camera.prototype */ +{ + + update: function (force) { + __WEBPACK_IMPORTED_MODULE_0__Node__["a" /* default */].prototype.update.call(this, force); + __WEBPACK_IMPORTED_MODULE_1__math_Matrix4__["a" /* default */].invert(this.viewMatrix, this.worldTransform); + + this.updateProjectionMatrix(); + __WEBPACK_IMPORTED_MODULE_1__math_Matrix4__["a" /* default */].invert(this.invProjectionMatrix, this.projectionMatrix); + + this.frustum.setFromProjection(this.projectionMatrix); + }, + + /** + * Set camera view matrix + */ + setViewMatrix: function (viewMatrix) { + __WEBPACK_IMPORTED_MODULE_1__math_Matrix4__["a" /* default */].copy(this.viewMatrix, viewMatrix); + __WEBPACK_IMPORTED_MODULE_1__math_Matrix4__["a" /* default */].invert(this.worldTransform, viewMatrix); + this.decomposeWorldTransform(); + }, + + /** + * Decompose camera projection matrix + */ + decomposeProjectionMatrix: function () {}, + + /** + * Set camera projection matrix + * @param {clay.Matrix4} projectionMatrix + */ + setProjectionMatrix: function (projectionMatrix) { + __WEBPACK_IMPORTED_MODULE_1__math_Matrix4__["a" /* default */].copy(this.projectionMatrix, projectionMatrix); + __WEBPACK_IMPORTED_MODULE_1__math_Matrix4__["a" /* default */].invert(this.invProjectionMatrix, projectionMatrix); + this.decomposeProjectionMatrix(); + }, + /** + * Update projection matrix, called after update + */ + updateProjectionMatrix: function () {}, + + /** + * Cast a picking ray from camera near plane to far plane + * @function + * @param {clay.Vector2} ndc + * @param {clay.Ray} [out] + * @return {clay.Ray} + */ + castRay: (function () { + var v4 = __WEBPACK_IMPORTED_MODULE_4__glmatrix_vec4__["a" /* default */].create(); + return function (ndc, out) { + var ray = out !== undefined ? out : new __WEBPACK_IMPORTED_MODULE_3__math_Ray__["a" /* default */](); + var x = ndc.array[0]; + var y = ndc.array[1]; + __WEBPACK_IMPORTED_MODULE_4__glmatrix_vec4__["a" /* default */].set(v4, x, y, -1, 1); + __WEBPACK_IMPORTED_MODULE_4__glmatrix_vec4__["a" /* default */].transformMat4(v4, v4, this.invProjectionMatrix.array); + __WEBPACK_IMPORTED_MODULE_4__glmatrix_vec4__["a" /* default */].transformMat4(v4, v4, this.worldTransform.array); + __WEBPACK_IMPORTED_MODULE_5__glmatrix_vec3__["a" /* default */].scale(ray.origin.array, v4, 1 / v4[3]); + + __WEBPACK_IMPORTED_MODULE_4__glmatrix_vec4__["a" /* default */].set(v4, x, y, 1, 1); + __WEBPACK_IMPORTED_MODULE_4__glmatrix_vec4__["a" /* default */].transformMat4(v4, v4, this.invProjectionMatrix.array); + __WEBPACK_IMPORTED_MODULE_4__glmatrix_vec4__["a" /* default */].transformMat4(v4, v4, this.worldTransform.array); + __WEBPACK_IMPORTED_MODULE_5__glmatrix_vec3__["a" /* default */].scale(v4, v4, 1 / v4[3]); + __WEBPACK_IMPORTED_MODULE_5__glmatrix_vec3__["a" /* default */].sub(ray.direction.array, v4, ray.origin.array); + + __WEBPACK_IMPORTED_MODULE_5__glmatrix_vec3__["a" /* default */].normalize(ray.direction.array, ray.direction.array); + ray.direction._dirty = true; + ray.origin._dirty = true; + + return ray; + }; + })(), + + /** + * @function + * @name clone + * @return {clay.Camera} + * @memberOf clay.Camera.prototype + */ +}); + +/* harmony default export */ __webpack_exports__["a"] = (Camera); + + +/***/ }), +/* 59 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__BoundingBox__ = __webpack_require__(18); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__Plane__ = __webpack_require__(74); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__glmatrix_vec3__ = __webpack_require__(12); + + + + + +var vec3Set = __WEBPACK_IMPORTED_MODULE_2__glmatrix_vec3__["a" /* default */].set; +var vec3Copy = __WEBPACK_IMPORTED_MODULE_2__glmatrix_vec3__["a" /* default */].copy; +var vec3TranformMat4 = __WEBPACK_IMPORTED_MODULE_2__glmatrix_vec3__["a" /* default */].transformMat4; +var mathMin = Math.min; +var mathMax = Math.max; +/** + * @constructor + * @alias clay.Frustum + */ +var Frustum = function() { + + /** + * Eight planes to enclose the frustum + * @type {clay.Plane[]} + */ + this.planes = []; + + for (var i = 0; i < 6; i++) { + this.planes.push(new __WEBPACK_IMPORTED_MODULE_1__Plane__["a" /* default */]()); + } + + /** + * Bounding box of frustum + * @type {clay.BoundingBox} + */ + this.boundingBox = new __WEBPACK_IMPORTED_MODULE_0__BoundingBox__["a" /* default */](); + + /** + * Eight vertices of frustum + * @type {Float32Array[]} + */ + this.vertices = []; + for (var i = 0; i < 8; i++) { + this.vertices[i] = __WEBPACK_IMPORTED_MODULE_2__glmatrix_vec3__["a" /* default */].fromValues(0, 0, 0); + } +}; + +Frustum.prototype = { + + // http://web.archive.org/web/20120531231005/http://crazyjoke.free.fr/doc/3D/plane%20extraction.pdf + /** + * Set frustum from a projection matrix + * @param {clay.Matrix4} projectionMatrix + */ + setFromProjection: function(projectionMatrix) { + + var planes = this.planes; + var m = projectionMatrix.array; + var m0 = m[0], m1 = m[1], m2 = m[2], m3 = m[3]; + var m4 = m[4], m5 = m[5], m6 = m[6], m7 = m[7]; + var m8 = m[8], m9 = m[9], m10 = m[10], m11 = m[11]; + var m12 = m[12], m13 = m[13], m14 = m[14], m15 = m[15]; + + // Update planes + vec3Set(planes[0].normal.array, m3 - m0, m7 - m4, m11 - m8); + planes[0].distance = -(m15 - m12); + planes[0].normalize(); + + vec3Set(planes[1].normal.array, m3 + m0, m7 + m4, m11 + m8); + planes[1].distance = -(m15 + m12); + planes[1].normalize(); + + vec3Set(planes[2].normal.array, m3 + m1, m7 + m5, m11 + m9); + planes[2].distance = -(m15 + m13); + planes[2].normalize(); + + vec3Set(planes[3].normal.array, m3 - m1, m7 - m5, m11 - m9); + planes[3].distance = -(m15 - m13); + planes[3].normalize(); + + vec3Set(planes[4].normal.array, m3 - m2, m7 - m6, m11 - m10); + planes[4].distance = -(m15 - m14); + planes[4].normalize(); + + vec3Set(planes[5].normal.array, m3 + m2, m7 + m6, m11 + m10); + planes[5].distance = -(m15 + m14); + planes[5].normalize(); + + // Perspective projection + var boundingBox = this.boundingBox; + var vertices = this.vertices; + if (m15 === 0) { + var aspect = m5 / m0; + var zNear = -m14 / (m10 - 1); + var zFar = -m14 / (m10 + 1); + var farY = -zFar / m5; + var nearY = -zNear / m5; + // Update bounding box + boundingBox.min.set(-farY * aspect, -farY, zFar); + boundingBox.max.set(farY * aspect, farY, zNear); + // update vertices + //--- min z + // min x + vec3Set(vertices[0], -farY * aspect, -farY, zFar); + vec3Set(vertices[1], -farY * aspect, farY, zFar); + // max x + vec3Set(vertices[2], farY * aspect, -farY, zFar); + vec3Set(vertices[3], farY * aspect, farY, zFar); + //-- max z + vec3Set(vertices[4], -nearY * aspect, -nearY, zNear); + vec3Set(vertices[5], -nearY * aspect, nearY, zNear); + vec3Set(vertices[6], nearY * aspect, -nearY, zNear); + vec3Set(vertices[7], nearY * aspect, nearY, zNear); + } + else { // Orthographic projection + var left = (-1 - m12) / m0; + var right = (1 - m12) / m0; + var top = (1 - m13) / m5; + var bottom = (-1 - m13) / m5; + var near = (-1 - m14) / m10; + var far = (1 - m14) / m10; + + + boundingBox.min.set(Math.min(left, right), Math.min(bottom, top), Math.min(far, near)); + boundingBox.max.set(Math.max(right, left), Math.max(top, bottom), Math.max(near, far)); + + var min = boundingBox.min.array; + var max = boundingBox.max.array; + //--- min z + // min x + vec3Set(vertices[0], min[0], min[1], min[2]); + vec3Set(vertices[1], min[0], max[1], min[2]); + // max x + vec3Set(vertices[2], max[0], min[1], min[2]); + vec3Set(vertices[3], max[0], max[1], min[2]); + //-- max z + vec3Set(vertices[4], min[0], min[1], max[2]); + vec3Set(vertices[5], min[0], max[1], max[2]); + vec3Set(vertices[6], max[0], min[1], max[2]); + vec3Set(vertices[7], max[0], max[1], max[2]); + } + }, + + /** + * Apply a affine transform matrix and set to the given bounding box + * @function + * @param {clay.BoundingBox} + * @param {clay.Matrix4} + * @return {clay.BoundingBox} + */ + getTransformedBoundingBox: (function() { + + var tmpVec3 = __WEBPACK_IMPORTED_MODULE_2__glmatrix_vec3__["a" /* default */].create(); + + return function(bbox, matrix) { + var vertices = this.vertices; + + var m4 = matrix.array; + var min = bbox.min; + var max = bbox.max; + var minArr = min.array; + var maxArr = max.array; + var v = vertices[0]; + vec3TranformMat4(tmpVec3, v, m4); + vec3Copy(minArr, tmpVec3); + vec3Copy(maxArr, tmpVec3); + + for (var i = 1; i < 8; i++) { + v = vertices[i]; + vec3TranformMat4(tmpVec3, v, m4); + + minArr[0] = mathMin(tmpVec3[0], minArr[0]); + minArr[1] = mathMin(tmpVec3[1], minArr[1]); + minArr[2] = mathMin(tmpVec3[2], minArr[2]); + + maxArr[0] = mathMax(tmpVec3[0], maxArr[0]); + maxArr[1] = mathMax(tmpVec3[1], maxArr[1]); + maxArr[2] = mathMax(tmpVec3[2], maxArr[2]); + } + + min._dirty = true; + max._dirty = true; + + return bbox; + }; + }) () +}; +/* harmony default export */ __webpack_exports__["a"] = (Frustum); + + +/***/ }), +/* 60 */ +/***/ (function(module, exports) { + +// Simple LRU cache use doubly linked list +// @module zrender/core/LRU + +/** + * Simple double linked list. Compared with array, it has O(1) remove operation. + * @constructor + */ +var LinkedList = function () { + /** + * @type {module:zrender/core/LRU~Entry} + */ + this.head = null; + /** + * @type {module:zrender/core/LRU~Entry} + */ + + this.tail = null; + this._len = 0; +}; + +var linkedListProto = LinkedList.prototype; +/** + * Insert a new value at the tail + * @param {} val + * @return {module:zrender/core/LRU~Entry} + */ + +linkedListProto.insert = function (val) { + var entry = new Entry(val); + this.insertEntry(entry); + return entry; +}; +/** + * Insert an entry at the tail + * @param {module:zrender/core/LRU~Entry} entry + */ + + +linkedListProto.insertEntry = function (entry) { + if (!this.head) { + this.head = this.tail = entry; + } else { + this.tail.next = entry; + entry.prev = this.tail; + entry.next = null; + this.tail = entry; + } + + this._len++; +}; +/** + * Remove entry. + * @param {module:zrender/core/LRU~Entry} entry + */ + + +linkedListProto.remove = function (entry) { + var prev = entry.prev; + var next = entry.next; + + if (prev) { + prev.next = next; + } else { + // Is head + this.head = next; + } + + if (next) { + next.prev = prev; + } else { + // Is tail + this.tail = prev; + } + + entry.next = entry.prev = null; + this._len--; +}; +/** + * @return {number} + */ + + +linkedListProto.len = function () { + return this._len; +}; +/** + * Clear list + */ + + +linkedListProto.clear = function () { + this.head = this.tail = null; + this._len = 0; +}; +/** + * @constructor + * @param {} val + */ + + +var Entry = function (val) { + /** + * @type {} + */ + this.value = val; + /** + * @type {module:zrender/core/LRU~Entry} + */ + + this.next; + /** + * @type {module:zrender/core/LRU~Entry} + */ + + this.prev; +}; +/** + * LRU Cache + * @constructor + * @alias module:zrender/core/LRU + */ + + +var LRU = function (maxSize) { + this._list = new LinkedList(); + this._map = {}; + this._maxSize = maxSize || 10; + this._lastRemovedEntry = null; +}; + +var LRUProto = LRU.prototype; +/** + * @param {string} key + * @param {} value + * @return {} Removed value + */ + +LRUProto.put = function (key, value) { + var list = this._list; + var map = this._map; + var removed = null; + + if (map[key] == null) { + var len = list.len(); // Reuse last removed entry + + var entry = this._lastRemovedEntry; + + if (len >= this._maxSize && len > 0) { + // Remove the least recently used + var leastUsedEntry = list.head; + list.remove(leastUsedEntry); + delete map[leastUsedEntry.key]; + removed = leastUsedEntry.value; + this._lastRemovedEntry = leastUsedEntry; + } + + if (entry) { + entry.value = value; + } else { + entry = new Entry(value); + } + + entry.key = key; + list.insertEntry(entry); + map[key] = entry; + } + + return removed; +}; +/** + * @param {string} key + * @return {} + */ + + +LRUProto.get = function (key) { + var entry = this._map[key]; + var list = this._list; + + if (entry != null) { + // Put the latest used entry in the tail + if (entry !== list.tail) { + list.remove(entry); + list.insertEntry(entry); + } + + return entry.value; + } +}; +/** + * Clear the cache + */ + + +LRUProto.clear = function () { + this._list.clear(); + + this._map = {}; +}; + +var _default = LRU; +module.exports = _default; + +/***/ }), +/* 61 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__Texture2D__ = __webpack_require__(5); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__TextureCube__ = __webpack_require__(27); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__core_vendor__ = __webpack_require__(14); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__prePass_EnvironmentMap__ = __webpack_require__(62); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4__plugin_Skydome__ = __webpack_require__(75); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_5__Scene__ = __webpack_require__(36); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_6__dds__ = __webpack_require__(122); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_7__hdr__ = __webpack_require__(123); + + + + + + + + + + +/** + * @alias clay.util.texture + */ +var textureUtil = { + /** + * @param {string|object} path + * @param {object} [option] + * @param {Function} [onsuccess] + * @param {Function} [onerror] + * @return {clay.Texture} + */ + loadTexture: function (path, option, onsuccess, onerror) { + var texture; + if (typeof(option) === 'function') { + onsuccess = option; + onerror = onsuccess; + option = {}; + } + else { + option = option || {}; + } + if (typeof(path) === 'string') { + if (path.match(/.hdr$/) || option.fileType === 'hdr') { + texture = new __WEBPACK_IMPORTED_MODULE_0__Texture2D__["a" /* default */]({ + width: 0, + height: 0, + sRGB: false + }); + textureUtil._fetchTexture( + path, + function (data) { + __WEBPACK_IMPORTED_MODULE_7__hdr__["a" /* default */].parseRGBE(data, texture, option.exposure); + texture.dirty(); + onsuccess && onsuccess(texture); + }, + onerror + ); + return texture; + } + else if (path.match(/.dds$/) || option.fileType === 'dds') { + texture = new __WEBPACK_IMPORTED_MODULE_0__Texture2D__["a" /* default */]({ + width: 0, + height: 0 + }); + textureUtil._fetchTexture( + path, + function (data) { + __WEBPACK_IMPORTED_MODULE_6__dds__["a" /* default */].parse(data, texture); + texture.dirty(); + onsuccess && onsuccess(texture); + }, + onerror + ); + } + else { + texture = new __WEBPACK_IMPORTED_MODULE_0__Texture2D__["a" /* default */](); + texture.load(path); + texture.success(onsuccess); + texture.error(onerror); + } + } + else if (typeof path === 'object' && typeof(path.px) !== 'undefined') { + texture = new __WEBPACK_IMPORTED_MODULE_1__TextureCube__["a" /* default */](); + texture.load(path); + texture.success(onsuccess); + texture.error(onerror); + } + return texture; + }, + + /** + * Load a panorama texture and render it to a cube map + * @param {clay.Renderer} renderer + * @param {string} path + * @param {clay.TextureCube} cubeMap + * @param {object} [option] + * @param {boolean} [option.encodeRGBM] + * @param {number} [option.exposure] + * @param {Function} [onsuccess] + * @param {Function} [onerror] + */ + loadPanorama: function (renderer, path, cubeMap, option, onsuccess, onerror) { + var self = this; + + if (typeof(option) === 'function') { + onsuccess = option; + onerror = onsuccess; + option = {}; + } + else { + option = option || {}; + } + + textureUtil.loadTexture(path, option, function (texture) { + // PENDING + texture.flipY = option.flipY || false; + self.panoramaToCubeMap(renderer, texture, cubeMap, option); + texture.dispose(renderer); + onsuccess && onsuccess(cubeMap); + }, onerror); + }, + + /** + * Render a panorama texture to a cube map + * @param {clay.Renderer} renderer + * @param {clay.Texture2D} panoramaMap + * @param {clay.TextureCube} cubeMap + * @param {Object} option + * @param {boolean} [option.encodeRGBM] + */ + panoramaToCubeMap: function (renderer, panoramaMap, cubeMap, option) { + var environmentMapPass = new __WEBPACK_IMPORTED_MODULE_3__prePass_EnvironmentMap__["a" /* default */](); + var skydome = new __WEBPACK_IMPORTED_MODULE_4__plugin_Skydome__["a" /* default */]({ + scene: new __WEBPACK_IMPORTED_MODULE_5__Scene__["a" /* default */]() + }); + skydome.setEnvironmentMap(panoramaMap); + + option = option || {}; + if (option.encodeRGBM) { + skydome.material.define('fragment', 'RGBM_ENCODE'); + } + + // Share sRGB + cubeMap.sRGB = panoramaMap.sRGB; + + environmentMapPass.texture = cubeMap; + environmentMapPass.render(renderer, skydome.scene); + environmentMapPass.texture = null; + environmentMapPass.dispose(renderer); + return cubeMap; + }, + + /** + * Convert height map to normal map + * @param {HTMLImageElement|HTMLCanvasElement} image + * @param {boolean} [checkBump=false] + * @return {HTMLCanvasElement} + */ + heightToNormal: function (image, checkBump) { + var canvas = document.createElement('canvas'); + var width = canvas.width = image.width; + var height = canvas.height = image.height; + var ctx = canvas.getContext('2d'); + ctx.drawImage(image, 0, 0, width, height); + checkBump = checkBump || false; + var srcData = ctx.getImageData(0, 0, width, height); + var dstData = ctx.createImageData(width, height); + for (var i = 0; i < srcData.data.length; i += 4) { + if (checkBump) { + var r = srcData.data[i]; + var g = srcData.data[i + 1]; + var b = srcData.data[i + 2]; + var diff = Math.abs(r - g) + Math.abs(g - b); + if (diff > 20) { + console.warn('Given image is not a height map'); + return image; + } + } + // Modified from http://mrdoob.com/lab/javascript/height2normal/ + var x1, y1, x2, y2; + if (i % (width * 4) === 0) { + // left edge + x1 = srcData.data[i]; + x2 = srcData.data[i + 4]; + } + else if (i % (width * 4) === (width - 1) * 4) { + // right edge + x1 = srcData.data[i - 4]; + x2 = srcData.data[i]; + } + else { + x1 = srcData.data[i - 4]; + x2 = srcData.data[i + 4]; + } + + if (i < width * 4) { + // top edge + y1 = srcData.data[i]; + y2 = srcData.data[i + width * 4]; + } + else if (i > width * (height - 1) * 4) { + // bottom edge + y1 = srcData.data[i - width * 4]; + y2 = srcData.data[i]; + } + else { + y1 = srcData.data[i - width * 4]; + y2 = srcData.data[i + width * 4]; + } + + dstData.data[i] = (x1 - x2) + 127; + dstData.data[i + 1] = (y1 - y2) + 127; + dstData.data[i + 2] = 255; + dstData.data[i + 3] = 255; + } + ctx.putImageData(dstData, 0, 0); + return canvas; + }, + + /** + * Convert height map to normal map + * @param {HTMLImageElement|HTMLCanvasElement} image + * @param {boolean} [checkBump=false] + * @param {number} [threshold=20] + * @return {HTMLCanvasElement} + */ + isHeightImage: function (img, downScaleSize, threshold) { + if (!img || !img.width || !img.height) { + return false; + } + + var canvas = document.createElement('canvas'); + var ctx = canvas.getContext('2d'); + var size = downScaleSize || 32; + threshold = threshold || 20; + canvas.width = canvas.height = size; + ctx.drawImage(img, 0, 0, size, size); + var srcData = ctx.getImageData(0, 0, size, size); + for (var i = 0; i < srcData.data.length; i += 4) { + var r = srcData.data[i]; + var g = srcData.data[i + 1]; + var b = srcData.data[i + 2]; + var diff = Math.abs(r - g) + Math.abs(g - b); + if (diff > threshold) { + return false; + } + } + return true; + }, + + _fetchTexture: function (path, onsuccess, onerror) { + __WEBPACK_IMPORTED_MODULE_2__core_vendor__["a" /* default */].request.get({ + url: path, + responseType: 'arraybuffer', + onload: onsuccess, + onerror: onerror + }); + }, + + /** + * Create a chessboard texture + * @param {number} [size] + * @param {number} [unitSize] + * @param {string} [color1] + * @param {string} [color2] + * @return {clay.Texture2D} + */ + createChessboard: function (size, unitSize, color1, color2) { + size = size || 512; + unitSize = unitSize || 64; + color1 = color1 || 'black'; + color2 = color2 || 'white'; + + var repeat = Math.ceil(size / unitSize); + + var canvas = document.createElement('canvas'); + canvas.width = size; + canvas.height = size; + var ctx = canvas.getContext('2d'); + ctx.fillStyle = color2; + ctx.fillRect(0, 0, size, size); + + ctx.fillStyle = color1; + for (var i = 0; i < repeat; i++) { + for (var j = 0; j < repeat; j++) { + var isFill = j % 2 ? (i % 2) : (i % 2 - 1); + if (isFill) { + ctx.fillRect(i * unitSize, j * unitSize, unitSize, unitSize); + } + } + } + + var texture = new __WEBPACK_IMPORTED_MODULE_0__Texture2D__["a" /* default */]({ + image: canvas, + anisotropic: 8 + }); + + return texture; + }, + + /** + * Create a blank pure color 1x1 texture + * @param {string} color + * @return {clay.Texture2D} + */ + createBlank: function (color) { + var canvas = document.createElement('canvas'); + canvas.width = 1; + canvas.height = 1; + var ctx = canvas.getContext('2d'); + ctx.fillStyle = color; + ctx.fillRect(0, 0, 1, 1); + + var texture = new __WEBPACK_IMPORTED_MODULE_0__Texture2D__["a" /* default */]({ + image: canvas + }); + + return texture; + } +}; + +/* harmony default export */ __webpack_exports__["a"] = (textureUtil); + + +/***/ }), +/* 62 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__core_Base__ = __webpack_require__(7); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__math_Vector3__ = __webpack_require__(3); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__camera_Perspective__ = __webpack_require__(41); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__FrameBuffer__ = __webpack_require__(10); + + + + + +var targets = ['px', 'nx', 'py', 'ny', 'pz', 'nz']; + +/** + * Pass rendering scene to a environment cube map + * + * @constructor clay.prePass.EnvironmentMap + * @extends clay.core.Base + * @example + * // Example of car reflection + * var envMap = new clay.TextureCube({ + * width: 256, + * height: 256 + * }); + * var envPass = new clay.prePass.EnvironmentMap({ + * position: car.position, + * texture: envMap + * }); + * var carBody = car.getChildByName('body'); + * carBody.material.enableTexture('environmentMap'); + * carBody.material.set('environmentMap', envMap); + * ... + * animation.on('frame', function(frameTime) { + * envPass.render(renderer, scene); + * renderer.render(scene, camera); + * }); + */ +var EnvironmentMapPass = __WEBPACK_IMPORTED_MODULE_0__core_Base__["a" /* default */].extend(function() { + var ret = /** @lends clay.prePass.EnvironmentMap# */ { + /** + * Camera position + * @type {clay.Vector3} + * @memberOf clay.prePass.EnvironmentMap# + */ + position: new __WEBPACK_IMPORTED_MODULE_1__math_Vector3__["a" /* default */](), + /** + * Camera far plane + * @type {number} + * @memberOf clay.prePass.EnvironmentMap# + */ + far: 1000, + /** + * Camera near plane + * @type {number} + * @memberOf clay.prePass.EnvironmentMap# + */ + near: 0.1, + /** + * Environment cube map + * @type {clay.TextureCube} + * @memberOf clay.prePass.EnvironmentMap# + */ + texture: null, + + /** + * Used if you wan't have shadow in environment map + * @type {clay.prePass.ShadowMap} + */ + shadowMapPass: null, + }; + var cameras = ret._cameras = { + px: new __WEBPACK_IMPORTED_MODULE_2__camera_Perspective__["a" /* default */]({ fov: 90 }), + nx: new __WEBPACK_IMPORTED_MODULE_2__camera_Perspective__["a" /* default */]({ fov: 90 }), + py: new __WEBPACK_IMPORTED_MODULE_2__camera_Perspective__["a" /* default */]({ fov: 90 }), + ny: new __WEBPACK_IMPORTED_MODULE_2__camera_Perspective__["a" /* default */]({ fov: 90 }), + pz: new __WEBPACK_IMPORTED_MODULE_2__camera_Perspective__["a" /* default */]({ fov: 90 }), + nz: new __WEBPACK_IMPORTED_MODULE_2__camera_Perspective__["a" /* default */]({ fov: 90 }) + }; + cameras.px.lookAt(__WEBPACK_IMPORTED_MODULE_1__math_Vector3__["a" /* default */].POSITIVE_X, __WEBPACK_IMPORTED_MODULE_1__math_Vector3__["a" /* default */].NEGATIVE_Y); + cameras.nx.lookAt(__WEBPACK_IMPORTED_MODULE_1__math_Vector3__["a" /* default */].NEGATIVE_X, __WEBPACK_IMPORTED_MODULE_1__math_Vector3__["a" /* default */].NEGATIVE_Y); + cameras.py.lookAt(__WEBPACK_IMPORTED_MODULE_1__math_Vector3__["a" /* default */].POSITIVE_Y, __WEBPACK_IMPORTED_MODULE_1__math_Vector3__["a" /* default */].POSITIVE_Z); + cameras.ny.lookAt(__WEBPACK_IMPORTED_MODULE_1__math_Vector3__["a" /* default */].NEGATIVE_Y, __WEBPACK_IMPORTED_MODULE_1__math_Vector3__["a" /* default */].NEGATIVE_Z); + cameras.pz.lookAt(__WEBPACK_IMPORTED_MODULE_1__math_Vector3__["a" /* default */].POSITIVE_Z, __WEBPACK_IMPORTED_MODULE_1__math_Vector3__["a" /* default */].NEGATIVE_Y); + cameras.nz.lookAt(__WEBPACK_IMPORTED_MODULE_1__math_Vector3__["a" /* default */].NEGATIVE_Z, __WEBPACK_IMPORTED_MODULE_1__math_Vector3__["a" /* default */].NEGATIVE_Y); + + // FIXME In windows, use one framebuffer only renders one side of cubemap + ret._frameBuffer = new __WEBPACK_IMPORTED_MODULE_3__FrameBuffer__["a" /* default */](); + + return ret; +}, /** @lends clay.prePass.EnvironmentMap# */ { + /** + * @param {string} target + * @return {clay.Camera} + */ + getCamera: function (target) { + return this._cameras[target]; + }, + /** + * @param {clay.Renderer} renderer + * @param {clay.Scene} scene + * @param {boolean} [notUpdateScene=false] + */ + render: function(renderer, scene, notUpdateScene) { + var _gl = renderer.gl; + if (!notUpdateScene) { + scene.update(); + } + // Tweak fov + // http://the-witness.net/news/2012/02/seamless-cube-map-filtering/ + var n = this.texture.width; + var fov = 2 * Math.atan(n / (n - 0.5)) / Math.PI * 180; + + for (var i = 0; i < 6; i++) { + var target = targets[i]; + var camera = this._cameras[target]; + __WEBPACK_IMPORTED_MODULE_1__math_Vector3__["a" /* default */].copy(camera.position, this.position); + + camera.far = this.far; + camera.near = this.near; + camera.fov = fov; + + if (this.shadowMapPass) { + camera.update(); + + // update boundingBoxLastFrame + var bbox = scene.getBoundingBox(); + bbox.applyTransform(camera.viewMatrix); + scene.viewBoundingBoxLastFrame.copy(bbox); + + this.shadowMapPass.render(renderer, scene, camera, true); + } + this._frameBuffer.attach( + this.texture, _gl.COLOR_ATTACHMENT0, + _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i + ); + this._frameBuffer.bind(renderer); + renderer.render(scene, camera, true); + this._frameBuffer.unbind(renderer); + } + }, + /** + * @param {clay.Renderer} renderer + */ + dispose: function (renderer) { + this._frameBuffer.dispose(renderer); + } +}); + +/* harmony default export */ __webpack_exports__["a"] = (EnvironmentMapPass); + + +/***/ }), +/* 63 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__graphicGL__ = __webpack_require__(1); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__geometry_Sprites__ = __webpack_require__(165); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__shader_labels_glsl_js__ = __webpack_require__(166); + + + + +__WEBPACK_IMPORTED_MODULE_0__graphicGL__["a" /* default */].Shader.import(__WEBPACK_IMPORTED_MODULE_2__shader_labels_glsl_js__["a" /* default */]); + +/* harmony default export */ __webpack_exports__["a"] = (__WEBPACK_IMPORTED_MODULE_0__graphicGL__["a" /* default */].Mesh.extend(function () { + var geometry = new __WEBPACK_IMPORTED_MODULE_1__geometry_Sprites__["a" /* default */]({ + dynamic: true + }); + var material = new __WEBPACK_IMPORTED_MODULE_0__graphicGL__["a" /* default */].Material({ + shader: __WEBPACK_IMPORTED_MODULE_0__graphicGL__["a" /* default */].createShader('ecgl.labels'), + transparent: true, + depthMask: false + }); + + return { + geometry: geometry, + material: material, + culling: false, + castShadow: false, + ignorePicking: true + }; +})); + +/***/ }), +/* 64 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__ = __webpack_require__(1); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__util_earcut__ = __webpack_require__(204); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__util_geometry_Lines3D__ = __webpack_require__(25); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4__util_retrieve__ = __webpack_require__(2); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_5_claygl_src_dep_glmatrix__ = __webpack_require__(6); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_6__util_geometry_trianglesSortMixin__ = __webpack_require__(65); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_7__LabelsBuilder__ = __webpack_require__(66); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_8__util_shader_lines3D_glsl_js__ = __webpack_require__(46); + + + + + + + + + + +var vec3 = __WEBPACK_IMPORTED_MODULE_5_claygl_src_dep_glmatrix__["a" /* default */].vec3; + +__WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].Shader.import(__WEBPACK_IMPORTED_MODULE_8__util_shader_lines3D_glsl_js__["a" /* default */]); + +function Geo3DBuilder(api) { + + this.rootNode = new __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].Node(); + + // Cache triangulation result + this._triangulationResults = {}; + + this._shadersMap = __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].COMMON_SHADERS.reduce(function (obj, shaderName) { + obj[shaderName] = __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].createShader('ecgl.' + shaderName); + return obj; + }, {}); + + this._linesShader = __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].createShader('ecgl.meshLines3D'); + + var groundMaterials = {}; + __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].COMMON_SHADERS.forEach(function (shading) { + groundMaterials[shading] = new __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].Material({ + shader: __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].createShader('ecgl.' + shading) + }); + }); + this._groundMaterials = groundMaterials; + + this._groundMesh = new __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].Mesh({ + geometry: new __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].PlaneGeometry({ dynamic: true }), + castShadow: false, + renderNormal: true, + $ignorePicking: true + }); + this._groundMesh.rotation.rotateX(-Math.PI / 2); + + this._labelsBuilder = new __WEBPACK_IMPORTED_MODULE_7__LabelsBuilder__["a" /* default */](512, 512, api); + + // Give a large render order. + this._labelsBuilder.getMesh().renderOrder = 100; + this._labelsBuilder.getMesh().material.depthTest = false; + + this.rootNode.add(this._labelsBuilder.getMesh()); + + this._initMeshes(); + + this._api = api; +} + +Geo3DBuilder.prototype = { + + constructor: Geo3DBuilder, + + // Which dimension to extrude. Y or Z + extrudeY: true, + + update: function (componentModel, ecModel, api, start, end) { + + var data = componentModel.getData(); + + if (start == null) { + start = 0; + } + if (end == null) { + end = data.count(); + } + + this._startIndex = start; + this._endIndex = end - 1; + + this._triangulation(componentModel, start, end); + + var shader = this._getShader(componentModel.get('shading')); + + this._prepareMesh(componentModel, shader, api, start, end); + + this.rootNode.updateWorldTransform(); + + this._updateRegionMesh(componentModel, api, start, end); + + var coordSys = componentModel.coordinateSystem; + // PENDING + if (coordSys.type === 'geo3D') { + this._updateGroundPlane(componentModel, coordSys, api); + } + + var self = this; + this._labelsBuilder.updateData(data, start, end); + this._labelsBuilder.getLabelPosition = function (dataIndex, positionDesc, distance) { + var name = data.getName(dataIndex); + + var center; + var height = distance; + if (coordSys.type === 'geo3D') { + var region = coordSys.getRegion(name); + if (!region) { + return [NaN, NaN, NaN]; + } + center = region.center; + var pos = coordSys.dataToPoint([center[0], center[1], height]); + return pos; + } + else { + var tmp = self._triangulationResults[dataIndex - self._startIndex]; + var center = self.extrudeY ? [ + (tmp.max[0] + tmp.min[0]) / 2, + tmp.max[1] + height, + (tmp.max[2] + tmp.min[2]) / 2 + ] : [ + (tmp.max[0] + tmp.min[0]) / 2, + (tmp.max[1] + tmp.min[1]) / 2, + tmp.max[2] + height + ]; + } + }; + + this._data = data; + + this._labelsBuilder.updateLabels(); + + this._updateDebugWireframe(componentModel); + + // Reset some state. + this._lastHoverDataIndex = 0; + }, + + _initMeshes: function () { + var self = this; + function createPolygonMesh() { + var mesh = new __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].Mesh({ + name: 'Polygon', + material: new __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].Material({ + shader: self._shadersMap.lambert + }), + geometry: new __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].Geometry({ + sortTriangles: true, + dynamic: true + }), + // TODO Disable culling + culling: false, + ignorePicking: true, + // Render normal in normal pass + renderNormal: true + }); + __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.util.extend(mesh.geometry, __WEBPACK_IMPORTED_MODULE_6__util_geometry_trianglesSortMixin__["a" /* default */]); + return mesh; + } + + var polygonMesh = createPolygonMesh(); + + var linesMesh = new __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].Mesh({ + material: new __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].Material({ + shader: this._linesShader + }), + castShadow: false, + ignorePicking: true, + $ignorePicking: true, + geometry: new __WEBPACK_IMPORTED_MODULE_3__util_geometry_Lines3D__["a" /* default */]({ + useNativeLine: false + }) + }); + + this.rootNode.add(polygonMesh); + this.rootNode.add(linesMesh); + + polygonMesh.material.define('both', 'VERTEX_COLOR'); + polygonMesh.material.define('fragment', 'DOUBLE_SIDED'); + + this._polygonMesh = polygonMesh; + this._linesMesh = linesMesh; + + this.rootNode.add(this._groundMesh); + }, + + _getShader: function (shading) { + var shader = this._shadersMap[shading]; + if (!shader) { + if (true) { + console.warn('Unkown shading ' + shading); + } + // Default use lambert shader. + shader = this._shadersMap.lambert; + } + shader.__shading = shading; + return shader; + }, + + _prepareMesh: function (componentModel, shader, api, start, end) { + var polygonVertexCount = 0; + var polygonTriangleCount = 0; + var linesVertexCount = 0; + var linesTriangleCount = 0; + // TODO Lines + for (var idx = start; idx < end; idx++) { + var polyInfo = this._getRegionPolygonInfo(idx); + var lineInfo = this._getRegionLinesInfo(idx, componentModel, this._linesMesh.geometry); + polygonVertexCount += polyInfo.vertexCount; + polygonTriangleCount += polyInfo.triangleCount; + linesVertexCount += lineInfo.vertexCount; + linesTriangleCount += lineInfo.triangleCount; + } + + var polygonMesh = this._polygonMesh; + var polygonGeo = polygonMesh.geometry; + ['position', 'normal', 'texcoord0', 'color'].forEach(function (attrName) { + polygonGeo.attributes[attrName].init(polygonVertexCount); + }); + polygonGeo.indices = polygonVertexCount > 0xffff ? new Uint32Array(polygonTriangleCount * 3) : new Uint16Array(polygonTriangleCount * 3); + + if (polygonMesh.material.shader !== shader) { + polygonMesh.material.attachShader(shader, true); + } + __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].setMaterialFromModel(shader.__shading, polygonMesh.material, componentModel, api); + + if (linesVertexCount > 0) { + this._linesMesh.geometry.resetOffset(); + this._linesMesh.geometry.setVertexCount(linesVertexCount); + this._linesMesh.geometry.setTriangleCount(linesTriangleCount); + } + + // Indexing data index from vertex index. + this._dataIndexOfVertex = new Uint32Array(polygonVertexCount); + // Indexing vertex index range from data index + this._vertexRangeOfDataIndex = new Uint32Array((end - start) * 2); + }, + + _updateRegionMesh: function (componentModel, api, start, end) { + + var data = componentModel.getData(); + + var vertexOffset = 0; + var triangleOffset = 0; + + // Materials configurations. + var hasTranparentRegion = false; + + var polygonMesh = this._polygonMesh; + var linesMesh = this._linesMesh; + + for (var dataIndex = start; dataIndex < end; dataIndex++) { + // Get bunch of visual properties. + var regionModel = componentModel.getRegionModel(dataIndex); + var itemStyleModel = regionModel.getModel('itemStyle'); + var color = itemStyleModel.get('color'); + var opacity = __WEBPACK_IMPORTED_MODULE_4__util_retrieve__["a" /* default */].firstNotNull(itemStyleModel.get('opacity'), 1.0); + + // Use visual color if it is encoded by visualMap component + var visualColor = data.getItemVisual(dataIndex, 'color', true); + if (visualColor != null && data.hasValue(dataIndex)) { + color = visualColor; + } + // Set color, opacity to visual for label usage. + data.setItemVisual(dataIndex, 'color', color); + data.setItemVisual(dataIndex, 'opacity', opacity); + + color = __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].parseColor(color); + var borderColor = __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].parseColor(itemStyleModel.get('borderColor')); + + color[3] *= opacity; + borderColor[3] *= opacity; + + var isTransparent = color[3] < 0.99; + + polygonMesh.material.set('color', [1,1,1,1]); + hasTranparentRegion = hasTranparentRegion || isTransparent; + + var regionHeight = __WEBPACK_IMPORTED_MODULE_4__util_retrieve__["a" /* default */].firstNotNull(regionModel.get('height', true), componentModel.get('regionHeight')); + + var newOffsets = this._updatePolygonGeometry( + componentModel, polygonMesh.geometry, dataIndex, regionHeight, + vertexOffset, triangleOffset, color + ); + + for (var i = vertexOffset; i < newOffsets.vertexOffset; i++) { + this._dataIndexOfVertex[i] = dataIndex; + } + this._vertexRangeOfDataIndex[(dataIndex - start) * 2] = vertexOffset; + this._vertexRangeOfDataIndex[(dataIndex - start) * 2 + 1] = newOffsets.vertexOffset; + + vertexOffset = newOffsets.vertexOffset; + triangleOffset = newOffsets.triangleOffset; + + // Update lines. + var lineWidth = itemStyleModel.get('borderWidth'); + var hasLine = lineWidth > 0; + if (hasLine) { + lineWidth *= api.getDevicePixelRatio(); + this._updateLinesGeometry( + linesMesh.geometry, componentModel, dataIndex, regionHeight, lineWidth, + componentModel.coordinateSystem.transform + ); + } + linesMesh.invisible = !hasLine; + linesMesh.material.set({ + color: borderColor + }); + } + + var polygonMesh = this._polygonMesh; + polygonMesh.material.transparent = hasTranparentRegion; + polygonMesh.material.depthMask = !hasTranparentRegion; + polygonMesh.geometry.updateBoundingBox(); + + polygonMesh.frontFace = this.extrudeY ? __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].Mesh.CCW : __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].Mesh.CW; + + // Update tangents + if (polygonMesh.material.get('normalMap')) { + polygonMesh.geometry.generateTangents(); + } + + polygonMesh.seriesIndex = componentModel.seriesIndex; + + polygonMesh.on('mousemove', this._onmousemove, this); + polygonMesh.on('mouseout', this._onmouseout, this); + }, + + _updateDebugWireframe: function (componentModel) { + var debugWireframeModel = componentModel.getModel('debug.wireframe'); + + // TODO Unshow + if (debugWireframeModel.get('show')) { + var color = __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].parseColor( + debugWireframeModel.get('lineStyle.color') || 'rgba(0,0,0,0.5)' + ); + var width = __WEBPACK_IMPORTED_MODULE_4__util_retrieve__["a" /* default */].firstNotNull( + debugWireframeModel.get('lineStyle.width'), 1 + ); + + // TODO Will cause highlight wrong + var mesh = this._polygonMesh; + mesh.geometry.generateBarycentric(); + mesh.material.define('both', 'WIREFRAME_TRIANGLE'); + mesh.material.set('wireframeLineColor', color); + mesh.material.set('wireframeLineWidth', width); + } + }, + + _onmousemove: function (e) { + var dataIndex = this._dataIndexOfVertex[e.triangle[0]]; + if (dataIndex == null) { + dataIndex = -1; + } + if (dataIndex !== this._lastHoverDataIndex) { + this.downplay(this._lastHoverDataIndex); + this.highlight(dataIndex); + this._labelsBuilder.updateLabels([dataIndex]); + } + this._lastHoverDataIndex = dataIndex; + this._polygonMesh.dataIndex = dataIndex; + }, + + _onmouseout: function (e) { + if (e.target) { + this.downplay(this._lastHoverDataIndex); + this._lastHoverDataIndex = -1; + this._polygonMesh.dataIndex = -1; + } + + this._labelsBuilder.updateLabels([]); + }, + + _updateGroundPlane: function (componentModel, geo3D, api) { + var groundModel = componentModel.getModel('groundPlane', componentModel); + this._groundMesh.invisible = !groundModel.get('show', true); + if (this._groundMesh.invisible) { + return; + } + + var shading = componentModel.get('shading'); + var material = this._groundMaterials[shading]; + if (!material) { + if (true) { + console.warn('Unkown shading ' + shading); + } + material = this._groundMaterials.lambert; + } + + __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].setMaterialFromModel(shading, material, groundModel, api); + if (material.get('normalMap')) { + this._groundMesh.geometry.generateTangents(); + } + + this._groundMesh.material = material; + this._groundMesh.material.set('color', __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].parseColor(groundModel.get('color'))); + + this._groundMesh.scale.set(geo3D.size[0], geo3D.size[2], 1); + }, + + _triangulation: function (componentModel, start, end) { + this._triangulationResults = []; + + var minAll = [Infinity, Infinity, Infinity]; + var maxAll = [-Infinity, -Infinity, -Infinity]; + + var coordSys = componentModel.coordinateSystem; + + for (var idx = start; idx < end; idx++) { + var polygons = []; + var polygonCoords = componentModel.getRegionPolygonCoords(idx); + for (var i = 0; i < polygonCoords.length; i++) { + var exterior = polygonCoords[i].exterior; + var interiors = polygonCoords[i].interiors; + var points = []; + var holes = []; + if (exterior.length < 3) { + continue; + } + var offset = 0; + for (var j = 0; j < exterior.length; j++) { + var p = exterior[j]; + points[offset++] = p[0]; + points[offset++] = p[1]; + } + + for (var j = 0; j < interiors.length; j++) { + if (interiors[j].length < 3) { + continue; + } + var startIdx = points.length / 2; + for (var k = 0; k < interiors[j].length; k++) { + var p = interiors[j][k]; + points.push(p[0]); + points.push(p[1]); + } + + holes.push(startIdx); + } + var triangles = Object(__WEBPACK_IMPORTED_MODULE_2__util_earcut__["a" /* default */])(points, holes); + + var points3 = new Float64Array(points.length / 2 * 3); + var pos = []; + var min = [Infinity, Infinity, Infinity]; + var max = [-Infinity, -Infinity, -Infinity]; + var off3 = 0; + for (var j = 0; j < points.length;) { + vec3.set(pos, points[j++], 0, points[j++]); + if (coordSys && coordSys.transform) { + vec3.transformMat4(pos, pos, coordSys.transform); + } + vec3.min(min, min, pos); + vec3.max(max, max, pos); + points3[off3++] = pos[0]; + points3[off3++] = pos[1]; + points3[off3++] = pos[2]; + } + vec3.min(minAll, minAll, min); + vec3.max(maxAll, maxAll, max); + polygons.push({ + points: points3, + indices: triangles, + min: min, + max: max + }); + } + this._triangulationResults.push(polygons); + } + + this._geoBoundingBox = [minAll, maxAll]; + }, + + /** + * Get region vertex and triangle count + */ + _getRegionPolygonInfo: function (idx) { + + var polygons = this._triangulationResults[idx - this._startIndex]; + + var sideVertexCount = 0; + var sideTriangleCount = 0; + + for (var i = 0; i < polygons.length; i++) { + sideVertexCount += polygons[i].points.length / 3; + sideTriangleCount += polygons[i].indices.length / 3; + } + + var vertexCount = sideVertexCount * 2 + sideVertexCount * 4; + var triangleCount = sideTriangleCount * 2 + sideVertexCount * 2; + + return { + vertexCount: vertexCount, + triangleCount: triangleCount + }; + }, + + _updatePolygonGeometry: function ( + componentModel, geometry, dataIndex, regionHeight, + vertexOffset, triangleOffset, color + ) { + // FIXME + var projectUVOnGround = componentModel.get('projectUVOnGround'); + + var positionAttr = geometry.attributes.position; + var normalAttr = geometry.attributes.normal; + var texcoordAttr = geometry.attributes.texcoord0; + var colorAttr = geometry.attributes.color; + var polygons = this._triangulationResults[dataIndex - this._startIndex]; + + var hasColor = colorAttr.value && color; + + var indices = geometry.indices; + + var extrudeCoordIndex = this.extrudeY ? 1 : 2; + var sideCoordIndex = this.extrudeY ? 2 : 1; + + var scale = [ + this.rootNode.worldTransform.x.len(), + this.rootNode.worldTransform.y.len(), + this.rootNode.worldTransform.z.len() + ]; + + var min = vec3.mul([], this._geoBoundingBox[0], scale); + var max = vec3.mul([], this._geoBoundingBox[1], scale); + var maxDimSize = Math.max(max[0] - min[0], max[2] - min[2]); + + function addVertices(polygon, y, insideOffset) { + var points = polygon.points; + + var pointsLen = points.length; + var currentPosition = []; + var uv = []; + + for (var k = 0; k < pointsLen; k += 3) { + currentPosition[0] = points[k]; + currentPosition[extrudeCoordIndex] = y; + currentPosition[sideCoordIndex] = points[k + 2]; + + uv[0] = (points[k] * scale[0] - min[0]) / maxDimSize; + uv[1] = (points[k + 2] * scale[sideCoordIndex] - min[2]) / maxDimSize; + + positionAttr.set(vertexOffset, currentPosition); + if (hasColor) { + colorAttr.set(vertexOffset, color); + } + texcoordAttr.set(vertexOffset++, uv); + } + } + + function buildTopBottom(polygon, y, insideOffset) { + + var startVertexOffset = vertexOffset; + + addVertices(polygon, y, insideOffset); + + var len = polygon.indices.length; + for (var k = 0; k < len; k++) { + indices[triangleOffset * 3 + k] = polygon.indices[k] + startVertexOffset; + } + triangleOffset += polygon.indices.length / 3; + } + + var normalTop = this.extrudeY ? [0, 1, 0] : [0, 0, 1]; + var normalBottom = vec3.negate([], normalTop); + for (var p = 0; p < polygons.length; p++) { + var startVertexOffset = vertexOffset; + var polygon = polygons[p]; + // BOTTOM + buildTopBottom(polygon, 0, 0); + // TOP + buildTopBottom(polygon, regionHeight, 0); + + var ringVertexCount = polygon.points.length / 3; + for (var v = 0; v < ringVertexCount; v++) { + normalAttr.set(startVertexOffset + v, normalBottom); + normalAttr.set(startVertexOffset + v + ringVertexCount, normalTop); + } + + var quadToTriangle = [0, 3, 1, 1, 3, 2]; + + var quadPos = [[], [], [], []]; + var a = []; + var b = []; + var normal = []; + var uv = []; + var len = 0; + for (var v = 0; v < ringVertexCount; v++) { + var next = (v + 1) % ringVertexCount; + + var dx = (polygon.points[next * 3] - polygon.points[v * 3]) * scale[0]; + var dy = (polygon.points[next * 3 + 2] - polygon.points[v * 3 + 2]) * scale[sideCoordIndex]; + var sideLen = Math.sqrt(dx * dx + dy * dy); + + // 0----1 + // 3----2 + for (var k = 0; k < 4; k++) { + var isCurrent = (k === 0 || k === 3); + var idx3 = (isCurrent ? v : next) * 3; + quadPos[k][0] = polygon.points[idx3]; + quadPos[k][extrudeCoordIndex] = k > 1 ? regionHeight : 0; + quadPos[k][sideCoordIndex] = polygon.points[idx3 + 2]; + + positionAttr.set(vertexOffset + k, quadPos[k]); + + if (projectUVOnGround) { + uv[0] = (polygon.points[idx3] * scale[0] - min[0]) / maxDimSize; + uv[1] = (polygon.points[idx3 + 2] * scale[sideCoordIndex] - min[sideCoordIndex]) / maxDimSize; + } + else { + uv[0] = (isCurrent ? len : (len + sideLen)) / maxDimSize; + uv[1] = (quadPos[k][extrudeCoordIndex] * scale[extrudeCoordIndex] - min[extrudeCoordIndex]) / maxDimSize; + } + texcoordAttr.set(vertexOffset + k, uv); + } + vec3.sub(a, quadPos[1], quadPos[0]); + vec3.sub(b, quadPos[3], quadPos[0]); + vec3.cross(normal, a, b); + vec3.normalize(normal, normal); + + for (var k = 0; k < 4; k++) { + normalAttr.set(vertexOffset + k, normal); + if (hasColor) { + colorAttr.set(vertexOffset + k, color); + } + } + + for (var k = 0; k < 6; k++) { + indices[triangleOffset * 3 + k] = quadToTriangle[k] + vertexOffset; + } + + vertexOffset += 4; + triangleOffset += 2; + + len += sideLen; + } + } + + geometry.dirty(); + + return { + vertexOffset: vertexOffset, + triangleOffset: triangleOffset + }; + }, + + _getRegionLinesInfo: function (idx, componentModel, geometry) { + var vertexCount = 0; + var triangleCount = 0; + + var regionModel = componentModel.getRegionModel(idx); + var itemStyleModel = regionModel.getModel('itemStyle'); + + var lineWidth = itemStyleModel.get('borderWidth'); + if (lineWidth > 0) { + var polygonCoords = componentModel.getRegionPolygonCoords(idx); + polygonCoords.forEach(function (coords) { + var exterior = coords.exterior; + var interiors = coords.interiors; + vertexCount += geometry.getPolylineVertexCount(exterior); + triangleCount += geometry.getPolylineTriangleCount(exterior); + for (var i = 0; i < interiors.length; i++) { + vertexCount += geometry.getPolylineVertexCount(interiors[i]); + triangleCount += geometry.getPolylineTriangleCount(interiors[i]); + } + }, this); + } + + return { + vertexCount: vertexCount, + triangleCount: triangleCount + }; + + }, + + _updateLinesGeometry: function (geometry, componentModel, dataIndex, regionHeight, lineWidth, transform) { + function convertToPoints3(polygon) { + var points = new Float64Array(polygon.length * 3); + var offset = 0; + var pos = []; + for (var i = 0; i < polygon.length; i++) { + pos[0] = polygon[i][0]; + // Add a offset to avoid z-fighting + pos[1] = regionHeight + 0.1; + pos[2] = polygon[i][1]; + + if (transform) { + vec3.transformMat4(pos, pos, transform); + } + + points[offset++] = pos[0]; + points[offset++] = pos[1]; + points[offset++] = pos[2]; + } + return points; + } + + var whiteColor = [1, 1, 1, 1]; + var coords = componentModel.getRegionPolygonCoords(dataIndex); + coords.forEach(function (geo) { + var exterior = geo.exterior; + var interiors = geo.interiors; + + geometry.addPolyline(convertToPoints3(exterior), whiteColor, lineWidth); + + for (var i = 0; i < interiors.length; i++) { + geometry.addPolyline(convertToPoints3(interiors[i]), whiteColor, lineWidth); + } + }); + }, + + highlight: function (dataIndex) { + var data = this._data; + if (!data) { + return; + } + + var itemModel = data.getItemModel(dataIndex); + var emphasisItemStyleModel = itemModel.getModel('emphasis.itemStyle'); + var emphasisColor = emphasisItemStyleModel.get('color'); + var emphasisOpacity = __WEBPACK_IMPORTED_MODULE_4__util_retrieve__["a" /* default */].firstNotNull( + emphasisItemStyleModel.get('opacity'), + data.getItemVisual(dataIndex, 'opacity'), + 1 + ); + if (emphasisColor == null) { + var color = data.getItemVisual(dataIndex, 'color'); + emphasisColor = __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.color.lift(color, -0.4); + } + if (emphasisOpacity == null) { + emphasisOpacity = data.getItemVisual(dataIndex, 'opacity'); + } + var colorArr = __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].parseColor(emphasisColor); + colorArr[3] *= emphasisOpacity; + + this._setColorOfDataIndex(data, dataIndex, colorArr); + }, + + downplay: function (dataIndex) { + + var data = this._data; + if (!data) { + return; + } + + var color = data.getItemVisual(dataIndex, 'color'); + var opacity = __WEBPACK_IMPORTED_MODULE_4__util_retrieve__["a" /* default */].firstNotNull(data.getItemVisual(dataIndex, 'opacity'), 1); + + var colorArr = __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].parseColor(color); + colorArr[3] *= opacity; + + this._setColorOfDataIndex(data, dataIndex, colorArr); + }, + + _setColorOfDataIndex: function (data, dataIndex, colorArr) { + if (dataIndex < this._startIndex && dataIndex > this._endIndex) { + return; + } + dataIndex -= this._startIndex; + for (var i = this._vertexRangeOfDataIndex[dataIndex * 2]; i < this._vertexRangeOfDataIndex[dataIndex * 2 + 1]; i++) { + this._polygonMesh.geometry.attributes.color.set(i, colorArr); + } + this._polygonMesh.geometry.dirty(); + this._api.getZr().refresh(); + } +}; + +/* harmony default export */ __webpack_exports__["a"] = (Geo3DBuilder); + +/***/ }), +/* 65 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__ProgressiveQuickSort__ = __webpack_require__(97); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_claygl_src_dep_glmatrix__ = __webpack_require__(6); + + +var vec3 = __WEBPACK_IMPORTED_MODULE_1_claygl_src_dep_glmatrix__["a" /* default */].vec3; + +var p0 = vec3.create(); +var p1 = vec3.create(); +var p2 = vec3.create(); +// var cp = vec3.create(); + +/* harmony default export */ __webpack_exports__["a"] = ({ + + needsSortTriangles: function () { + return this.indices && this.sortTriangles; + }, + + needsSortTrianglesProgressively: function () { + return this.needsSortTriangles() && this.triangleCount >= 2e4; + }, + + doSortTriangles: function (cameraPos, frame) { + var indices = this.indices; + // Do progressive quick sort. + if (frame === 0) { + var posAttr = this.attributes.position; + var cameraPos = cameraPos.array; + + if (!this._triangleZList || this._triangleZList.length !== this.triangleCount) { + this._triangleZList = new Float32Array(this.triangleCount); + this._sortedTriangleIndices = new Uint32Array(this.triangleCount); + + this._indicesTmp = new indices.constructor(indices.length); + this._triangleZListTmp = new Float32Array(this.triangleCount); + } + + var cursor = 0; + var firstZ; + for (var i = 0; i < indices.length;) { + posAttr.get(indices[i++], p0); + posAttr.get(indices[i++], p1); + posAttr.get(indices[i++], p2); + + // FIXME If use center ? + // cp[0] = (p0[0] + p1[0] + p2[0]) / 3; + // cp[1] = (p0[1] + p1[1] + p2[1]) / 3; + // cp[2] = (p0[2] + p1[2] + p2[2]) / 3; + // Camera position is in object space + + // Use max of three points, PENDING + var z0 = vec3.sqrDist(p0, cameraPos); + var z1 = vec3.sqrDist(p1, cameraPos); + var z2 = vec3.sqrDist(p2, cameraPos); + var zMax = Math.min(z0, z1); + zMax = Math.min(zMax, z2); + if (i === 3) { + firstZ = zMax; + zMax = 0; + } + else { + // Only store the difference to avoid the precision issue. + zMax = zMax - firstZ; + } + this._triangleZList[cursor++] = zMax; + } + } + + + var sortedTriangleIndices = this._sortedTriangleIndices; + for (var i = 0; i < sortedTriangleIndices.length; i++) { + sortedTriangleIndices[i] = i; + } + + if (this.triangleCount < 2e4) { + // Use simple timsort for simple geometries. + if (frame === 0) { + // Use native sort temporary. + this._simpleSort(true); + } + } + else { + for (var i = 0; i < 3; i++) { + this._progressiveQuickSort(frame * 3 + i); + } + } + + var targetIndices = this._indicesTmp; + var targetTriangleZList = this._triangleZListTmp; + var faceZList = this._triangleZList; + for (var i = 0; i < this.triangleCount; i++) { + var fromIdx3 = sortedTriangleIndices[i] * 3; + var toIdx3 = i * 3; + targetIndices[toIdx3++] = indices[fromIdx3++]; + targetIndices[toIdx3++] = indices[fromIdx3++]; + targetIndices[toIdx3] = indices[fromIdx3]; + + targetTriangleZList[i] = faceZList[sortedTriangleIndices[i]]; + } + + // Swap indices. + var tmp = this._indicesTmp; + this._indicesTmp = this.indices; + this.indices = tmp; + var tmp = this._triangleZListTmp; + this._triangleZListTmp = this._triangleZList; + this._triangleZList = tmp; + + this.dirtyIndices(); + }, + + _simpleSort: function (useNativeQuickSort) { + var faceZList = this._triangleZList; + var sortedTriangleIndices = this._sortedTriangleIndices; + + function compare(a, b) { + // Sort from far to near. which is descending order + return faceZList[b] - faceZList[a]; + } + if (useNativeQuickSort) { + Array.prototype.sort.call(sortedTriangleIndices, compare); + } + else { + __WEBPACK_IMPORTED_MODULE_0__ProgressiveQuickSort__["a" /* default */].sort(sortedTriangleIndices, compare, 0, sortedTriangleIndices.length - 1); + } + }, + + _progressiveQuickSort: function (frame) { + var faceZList = this._triangleZList; + var sortedTriangleIndices = this._sortedTriangleIndices; + + this._quickSort = this._quickSort || new __WEBPACK_IMPORTED_MODULE_0__ProgressiveQuickSort__["a" /* default */](); + + this._quickSort.step(sortedTriangleIndices, function (a, b) { + return faceZList[b] - faceZList[a]; + }, frame); + } +}); + +/***/ }), +/* 66 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__util_ZRTextureAtlasSurface__ = __webpack_require__(81); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__util_mesh_LabelsMesh__ = __webpack_require__(63); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__util_retrieve__ = __webpack_require__(2); + + + + + +var LABEL_NORMAL_SHOW_BIT = 1; +var LABEL_EMPHASIS_SHOW_BIT = 2; + +function LabelsBuilder(width, height, api) { + + this._labelsMesh = new __WEBPACK_IMPORTED_MODULE_2__util_mesh_LabelsMesh__["a" /* default */](); + + this._labelTextureSurface = new __WEBPACK_IMPORTED_MODULE_1__util_ZRTextureAtlasSurface__["a" /* default */]({ + width: 512, + height: 512, + devicePixelRatio: api.getDevicePixelRatio(), + onupdate: function () { + api.getZr().refresh(); + } + }); + this._api = api; + + this._labelsMesh.material.set('textureAtlas', this._labelTextureSurface.getTexture()); +} + +LabelsBuilder.prototype.getLabelPosition = function (dataIndex, positionDesc, distance) { + return [0, 0, 0]; +}; + +LabelsBuilder.prototype.getLabelDistance = function (dataIndex, positionDesc, distance) { + return 0; +}; + +LabelsBuilder.prototype.getMesh = function () { + return this._labelsMesh; +}; + +LabelsBuilder.prototype.updateData = function (data, start, end) { + if (start == null) { + start = 0; + } + if (end == null) { + end = data.count(); + } + + if (!this._labelsVisibilitiesBits || this._labelsVisibilitiesBits.length !== (end - start)) { + this._labelsVisibilitiesBits = new Uint8Array(end - start); + } + var normalLabelVisibilityQuery = ['label', 'show']; + var emphasisLabelVisibilityQuery = ['emphasis', 'label', 'show']; + + for (var idx = start; idx < end; idx++) { + var itemModel = data.getItemModel(idx); + var normalVisibility = itemModel.get(normalLabelVisibilityQuery); + var emphasisVisibility = itemModel.get(emphasisLabelVisibilityQuery); + if (emphasisVisibility == null) { + emphasisVisibility = normalVisibility; + } + var bit = (normalVisibility ? LABEL_NORMAL_SHOW_BIT : 0) + | (emphasisVisibility ? LABEL_EMPHASIS_SHOW_BIT : 0); + this._labelsVisibilitiesBits[idx - start] = bit; + } + + this._start = start; + this._end = end; + + this._data = data; +}; + +LabelsBuilder.prototype.updateLabels = function (highlightDataIndices) { + + if (!this._data) { + return; + } + + highlightDataIndices = highlightDataIndices || []; + + var hasHighlightData = highlightDataIndices.length > 0; + var highlightDataIndicesMap = {}; + for (var i = 0; i < highlightDataIndices.length; i++) { + highlightDataIndicesMap[highlightDataIndices[i]] = true; + } + + this._labelsMesh.geometry.convertToDynamicArray(true); + this._labelTextureSurface.clear(); + + var normalLabelQuery = ['label']; + var emphasisLabelQuery = ['emphasis', 'label']; + var seriesModel = this._data.hostModel; + var data = this._data; + + var seriesLabelModel = seriesModel.getModel(normalLabelQuery); + var seriesLabelEmphasisModel = seriesModel.getModel(emphasisLabelQuery, seriesLabelModel); + + var textAlignMap = { + left: 'right', + right: 'left', + top: 'center', + bottom: 'center' + }; + var textVerticalAlignMap = { + left: 'middle', + right: 'middle', + top: 'bottom', + bottom: 'top' + }; + + for (var dataIndex = this._start; dataIndex < this._end; dataIndex++) { + var isEmphasis = false; + if (hasHighlightData && highlightDataIndicesMap[dataIndex]) { + isEmphasis = true; + } + var ifShow = this._labelsVisibilitiesBits[dataIndex - this._start] + & (isEmphasis ? LABEL_EMPHASIS_SHOW_BIT : LABEL_NORMAL_SHOW_BIT); + if (!ifShow) { + continue; + } + + var itemModel = data.getItemModel(dataIndex); + var labelModel = itemModel.getModel( + isEmphasis ? emphasisLabelQuery : normalLabelQuery, + isEmphasis ? seriesLabelEmphasisModel : seriesLabelModel + ); + var distance = labelModel.get('distance') || 0; + var position = labelModel.get('position'); + var textStyleModel = labelModel.getModel('textStyle'); + + var dpr = this._api.getDevicePixelRatio(); + var text = seriesModel.getFormattedLabel(dataIndex, isEmphasis ? 'emphasis' : 'normal'); + if (text == null || text === '') { + return; + } + + // TODO Background. + var textEl = new __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.graphic.Text(); + __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.graphic.setTextStyle(textEl.style, textStyleModel, { + text: text, + textFill: textStyleModel.get('color') || data.getItemVisual(dataIndex, 'color') || '#000', + textAlign: 'left', + textVerticalAlign: 'top', + opacity: __WEBPACK_IMPORTED_MODULE_3__util_retrieve__["a" /* default */].firstNotNull(textStyleModel.get('opacity'), data.getItemVisual(dataIndex, 'opacity'), 1) + }); + var rect = textEl.getBoundingRect(); + var lineHeight = 1.2; + rect.height *= lineHeight; + + var coords = this._labelTextureSurface.add(textEl); + + var textAlign = textAlignMap[position] || 'center'; + var textVerticalAlign = textVerticalAlignMap[position] || 'bottom'; + + this._labelsMesh.geometry.addSprite( + this.getLabelPosition(dataIndex, position, distance), + [rect.width * dpr, rect.height * dpr], coords, + textAlign, textVerticalAlign, + this.getLabelDistance(dataIndex, position, distance) * dpr + ); + } + + this._labelsMesh.material.set('uvScale', this._labelTextureSurface.getCoordsScale()); + + // var canvas = this._labelTextureSurface.getTexture().image; + // document.body.appendChild(canvas); + // canvas.style.cssText = 'position:absolute;z-index: 1000'; + + // Update image. + this._labelTextureSurface.getZr().refreshImmediately(); + this._labelsMesh.geometry.convertToTypedArray(); + this._labelsMesh.geometry.dirty(); +}; + +/* harmony default export */ __webpack_exports__["a"] = (LabelsBuilder); + +/***/ }), +/* 67 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__ = __webpack_require__(1); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__util_sprite__ = __webpack_require__(239); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__PointsMesh__ = __webpack_require__(240); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4__component_common_LabelsBuilder__ = __webpack_require__(66); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_5_claygl_src_math_Matrix4__ = __webpack_require__(9); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_6__util_retrieve__ = __webpack_require__(2); + + + + + + + + +var SDF_RANGE = 20; + +var Z_2D = -10; + +function isSymbolSizeSame(a, b) { + return a && b && a[0] === b[0] && a[1] === b[1]; +} +// TODO gl_PointSize has max value. +function PointsBuilder(is2D, api) { + this.rootNode = new __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].Node(); + + /** + * @type {boolean} + */ + this.is2D = is2D; + + this._labelsBuilder = new __WEBPACK_IMPORTED_MODULE_4__component_common_LabelsBuilder__["a" /* default */](256, 256, api); + + // Give a large render order. + this._labelsBuilder.getMesh().renderOrder = 100; + this.rootNode.add(this._labelsBuilder.getMesh()); + + this._api = api; + + this._spriteImageCanvas = document.createElement('canvas'); + + this._startDataIndex = 0; + this._endDataIndex = 0; + + this._sizeScale = 1; +} + +PointsBuilder.prototype = { + + constructor: PointsBuilder, + + /** + * If highlight on over + */ + highlightOnMouseover: true, + + update: function (seriesModel, ecModel, api, start, end) { + // Swap barMesh + var tmp = this._prevMesh; + this._prevMesh = this._mesh; + this._mesh = tmp; + + var data = seriesModel.getData(); + + if (start == null) { + start = 0; + } + if (end == null) { + end = data.count(); + } + this._startDataIndex = start; + this._endDataIndex = end - 1; + + if (!this._mesh) { + var material = this._prevMesh && this._prevMesh.material; + this._mesh = new __WEBPACK_IMPORTED_MODULE_3__PointsMesh__["a" /* default */]({ + // Render after axes + renderOrder: 10, + // FIXME + frustumCulling: false + }); + if (material) { + this._mesh.material = material; + } + } + var material = this._mesh.material; + var geometry = this._mesh.geometry; + var attributes = geometry.attributes; + + this.rootNode.remove(this._prevMesh); + this.rootNode.add(this._mesh); + + this._setPositionTextureToMesh(this._mesh, this._positionTexture); + + var symbolInfo = this._getSymbolInfo(seriesModel, start, end); + var dpr = api.getDevicePixelRatio(); + + // TODO image symbol + var itemStyle = seriesModel.getModel('itemStyle').getItemStyle(); + var largeMode = seriesModel.get('large'); + + var pointSizeScale = 1; + if (symbolInfo.maxSize > 2) { + pointSizeScale = this._updateSymbolSprite(seriesModel, itemStyle, symbolInfo, dpr); + material.enableTexture('sprite'); + } + else { + material.disableTexture('sprite'); + } + + attributes.position.init(end - start); + var rgbaArr = []; + if (largeMode) { + material.undefine('VERTEX_SIZE'); + material.undefine('VERTEX_COLOR'); + + var color = data.getVisual('color'); + var opacity = data.getVisual('opacity'); + __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].parseColor(color, rgbaArr); + rgbaArr[3] *= opacity; + + material.set({ + color: rgbaArr, + 'u_Size': symbolInfo.maxSize * this._sizeScale + }); + } + else { + material.set({ + color: [1, 1, 1, 1] + }); + material.define('VERTEX_SIZE'); + material.define('VERTEX_COLOR'); + attributes.size.init(end - start); + attributes.color.init(end - start); + this._originalOpacity = new Float32Array(end - start); + } + + var points = data.getLayout('points'); + + var positionArr = attributes.position.value; + + var hasTransparentPoint = false; + + for (var i = 0; i < end - start; i++) { + var i3 = i * 3; + var i2 = i * 2; + if (this.is2D) { + positionArr[i3] = points[i2]; + positionArr[i3 + 1] = points[i2 + 1]; + positionArr[i3 + 2] = Z_2D; + } + else { + positionArr[i3] = points[i3]; + positionArr[i3 + 1] = points[i3 + 1]; + positionArr[i3 + 2] = points[i3 + 2]; + } + + if (!largeMode) { + var color = data.getItemVisual(i, 'color'); + var opacity = data.getItemVisual(i, 'opacity'); + __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].parseColor(color, rgbaArr); + rgbaArr[3] *= opacity; + attributes.color.set(i, rgbaArr); + if (rgbaArr[3] < 0.99) { + hasTransparentPoint = true; + } + var symbolSize = data.getItemVisual(i, 'symbolSize'); + symbolSize = (symbolSize instanceof Array + ? Math.max(symbolSize[0], symbolSize[1]) : symbolSize); + + // NaN pointSize may have strange result. + if (isNaN(symbolSize)) { + symbolSize = 0; + } + // Scale point size because canvas has margin. + attributes.size.value[i] = symbolSize * pointSizeScale * this._sizeScale; + + // Save the original opacity for recover from fadeIn. + this._originalOpacity[i] = rgbaArr[3]; + } + + } + + this._mesh.sizeScale = pointSizeScale; + + geometry.updateBoundingBox(); + geometry.dirty(); + + // Update material. + this._updateMaterial(seriesModel, itemStyle); + + var coordSys = seriesModel.coordinateSystem; + if (coordSys && coordSys.viewGL) { + var methodName = coordSys.viewGL.isLinearSpace() ? 'define' : 'undefine'; + material[methodName]('fragment', 'SRGB_DECODE'); + } + + if (!largeMode) { + this._updateLabelBuilder(seriesModel, start, end); + } + + this._updateHandler(seriesModel, ecModel, api); + + this._updateAnimation(seriesModel); + + this._api = api; + }, + + getPointsMesh: function () { + return this._mesh; + }, + + updateLabels: function (highlightDataIndices) { + this._labelsBuilder.updateLabels(highlightDataIndices); + }, + + hideLabels: function () { + this.rootNode.remove(this._labelsBuilder.getMesh()); + }, + + showLabels: function () { + this.rootNode.add(this._labelsBuilder.getMesh()); + }, + + _updateSymbolSprite: function (seriesModel, itemStyle, symbolInfo, dpr) { + symbolInfo.maxSize = Math.min(symbolInfo.maxSize * 2, 200); + var symbolSize = []; + if (symbolInfo.aspect > 1) { + symbolSize[0] = symbolInfo.maxSize; + symbolSize[1] = symbolInfo.maxSize / symbolInfo.aspect; + } + else { + symbolSize[1] = symbolInfo.maxSize; + symbolSize[0] = symbolInfo.maxSize * symbolInfo.aspect; + } + + // In case invalid data. + symbolSize[0] = symbolSize[0] || 1; + symbolSize[1] = symbolSize[1] || 1; + + if (this._symbolType !== symbolInfo.type + || !isSymbolSizeSame(this._symbolSize, symbolSize) + || this._lineWidth !== itemStyle.lineWidth + ) { + __WEBPACK_IMPORTED_MODULE_2__util_sprite__["a" /* default */].createSymbolSprite(symbolInfo.type, symbolSize, { + fill: '#fff', + lineWidth: itemStyle.lineWidth, + stroke: 'transparent', + shadowColor: 'transparent', + minMargin: Math.min(symbolSize[0] / 2, 10) + }, this._spriteImageCanvas); + + __WEBPACK_IMPORTED_MODULE_2__util_sprite__["a" /* default */].createSDFFromCanvas( + this._spriteImageCanvas, Math.min(this._spriteImageCanvas.width, 32), SDF_RANGE, + this._mesh.material.get('sprite').image + ); + + this._symbolType = symbolInfo.type; + this._symbolSize = symbolSize; + this._lineWidth = itemStyle.lineWidth; + } + return this._spriteImageCanvas.width / symbolInfo.maxSize * dpr; + + }, + + _updateMaterial: function (seriesModel, itemStyle) { + var blendFunc = seriesModel.get('blendMode') === 'lighter' + ? __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].additiveBlend : null; + var material = this._mesh.material; + material.blend = blendFunc; + + material.set('lineWidth', itemStyle.lineWidth / SDF_RANGE); + + var strokeColor = __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].parseColor(itemStyle.stroke); + material.set('strokeColor', strokeColor); + + // Because of symbol texture, we always needs it be transparent. + material.transparent = true; + material.depthMask = false; + material.depthTest = !this.is2D; + material.sortVertices = !this.is2D; + }, + + _updateLabelBuilder: function (seriesModel, start, end) { + var data =seriesModel.getData(); + var geometry = this._mesh.geometry; + var positionArr = geometry.attributes.position.value; + var start = this._startDataIndex; + var pointSizeScale = this._mesh.sizeScale; + this._labelsBuilder.updateData(data, start, end); + + this._labelsBuilder.getLabelPosition = function (dataIndex, positionDesc, distance) { + var idx3 = (dataIndex - start) * 3; + return [positionArr[idx3], positionArr[idx3 + 1], positionArr[idx3 + 2]]; + }; + + this._labelsBuilder.getLabelDistance = function (dataIndex, positionDesc, distance) { + var size = geometry.attributes.size.get(dataIndex - start) / pointSizeScale; + return size / 2 + distance; + }; + this._labelsBuilder.updateLabels(); + + }, + + _updateAnimation: function (seriesModel) { + __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].updateVertexAnimation( + [['prevPosition', 'position'], + ['prevSize', 'size']], + this._prevMesh, + this._mesh, + seriesModel + ); + }, + + _updateHandler: function (seriesModel, ecModel, api) { + var data = seriesModel.getData(); + var pointsMesh = this._mesh; + var self = this; + + var lastDataIndex = -1; + var isCartesian3D = seriesModel.coordinateSystem + && seriesModel.coordinateSystem.type === 'cartesian3D'; + + var grid3DModel; + if (isCartesian3D) { + grid3DModel = seriesModel.coordinateSystem.model; + } + + pointsMesh.seriesIndex = seriesModel.seriesIndex; + + pointsMesh.off('mousemove'); + pointsMesh.off('mouseout'); + + pointsMesh.on('mousemove', function (e) { + var dataIndex = e.vertexIndex + self._startDataIndex; + if (dataIndex !== lastDataIndex) { + if (this.highlightOnMouseover) { + this.downplay(data, lastDataIndex); + this.highlight(data, dataIndex); + this._labelsBuilder.updateLabels([dataIndex]); + } + + if (isCartesian3D) { + api.dispatchAction({ + type: 'grid3DShowAxisPointer', + value: [ + data.get(seriesModel.coordDimToDataDim('x')[0], dataIndex), + data.get(seriesModel.coordDimToDataDim('y')[0], dataIndex), + data.get(seriesModel.coordDimToDataDim('z')[0], dataIndex) + ], + grid3DIndex: grid3DModel.componentIndex + }); + } + } + + pointsMesh.dataIndex = dataIndex; + lastDataIndex = dataIndex; + }, this); + pointsMesh.on('mouseout', function (e) { + var dataIndex = e.vertexIndex + self._startDataIndex; + if (this.highlightOnMouseover) { + this.downplay(data, dataIndex); + this._labelsBuilder.updateLabels(); + } + lastDataIndex = -1; + pointsMesh.dataIndex = -1; + + if (isCartesian3D) { + api.dispatchAction({ + type: 'grid3DHideAxisPointer', + grid3DIndex: grid3DModel.componentIndex + }); + } + }, this); + }, + + updateLayout: function (seriesModel, ecModel, api) { + var data = seriesModel.getData(); + if (!this._mesh) { + return; + } + + var positionArr = this._mesh.geometry.attributes.position.value; + var points = data.getLayout('points'); + if (this.is2D) { + for (var i = 0; i < points.length / 2; i++) { + var i3 = i * 3; + var i2 = i * 2; + positionArr[i3] = points[i2]; + positionArr[i3 + 1] = points[i2 + 1]; + positionArr[i3 + 2] = Z_2D; + } + } + else { + for (var i = 0; i < points.length; i++) { + positionArr[i] = points[i]; + } + } + this._mesh.geometry.dirty(); + + api.getZr().refresh(); + }, + + updateView: function (camera) { + if (!this._mesh) { + return; + } + + var worldViewProjection = new __WEBPACK_IMPORTED_MODULE_5_claygl_src_math_Matrix4__["a" /* default */](); + __WEBPACK_IMPORTED_MODULE_5_claygl_src_math_Matrix4__["a" /* default */].mul(worldViewProjection, camera.viewMatrix, this._mesh.worldTransform); + __WEBPACK_IMPORTED_MODULE_5_claygl_src_math_Matrix4__["a" /* default */].mul(worldViewProjection, camera.projectionMatrix, worldViewProjection); + + this._mesh.updateNDCPosition(worldViewProjection, this.is2D, this._api); + }, + + highlight: function (data, dataIndex) { + if (dataIndex > this._endDataIndex || dataIndex < this._startDataIndex) { + return; + } + var itemModel = data.getItemModel(dataIndex); + var emphasisItemStyleModel = itemModel.getModel('emphasis.itemStyle'); + var emphasisColor = emphasisItemStyleModel.get('color'); + var emphasisOpacity = emphasisItemStyleModel.get('opacity'); + if (emphasisColor == null) { + var color = data.getItemVisual(dataIndex, 'color'); + emphasisColor = __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.color.lift(color, -0.4); + } + if (emphasisOpacity == null) { + emphasisOpacity = data.getItemVisual(dataIndex, 'opacity'); + } + var colorArr = __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].parseColor(emphasisColor); + colorArr[3] *= emphasisOpacity; + + this._mesh.geometry.attributes.color.set(dataIndex - this._startDataIndex, colorArr); + this._mesh.geometry.dirtyAttribute('color'); + + this._api.getZr().refresh(); + }, + + downplay: function (data, dataIndex) { + if (dataIndex > this._endDataIndex || dataIndex < this._startDataIndex) { + return; + } + var color = data.getItemVisual(dataIndex, 'color'); + var opacity = data.getItemVisual(dataIndex, 'opacity'); + + var colorArr = __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].parseColor(color); + colorArr[3] *= opacity; + + this._mesh.geometry.attributes.color.set(dataIndex - this._startDataIndex, colorArr); + this._mesh.geometry.dirtyAttribute('color'); + + this._api.getZr().refresh(); + }, + + fadeOutAll: function (fadeOutPercent) { + if (this._originalOpacity) { + var geo = this._mesh.geometry; + for (var i = 0; i < geo.vertexCount; i++) { + var fadeOutOpacity = this._originalOpacity[i] * fadeOutPercent; + geo.attributes.color.value[i * 4 + 3] = fadeOutOpacity; + } + geo.dirtyAttribute('color'); + + this._api.getZr().refresh(); + } + }, + + fadeInAll: function () { + this.fadeOutAll(1); + }, + + setPositionTexture: function (texture) { + if (this._mesh) { + this._setPositionTextureToMesh(this._mesh, texture); + } + + this._positionTexture = texture; + }, + + removePositionTexture: function () { + this._positionTexture = null; + if (this._mesh) { + this._setPositionTextureToMesh(this._mesh, null); + } + }, + + setSizeScale: function (sizeScale) { + if (sizeScale !== this._sizeScale) { + if (this._mesh) { + var originalSize = this._mesh.material.get('u_Size'); + this._mesh.material.set('u_Size', originalSize / this._sizeScale * sizeScale); + + var attributes = this._mesh.geometry.attributes; + if (attributes.size.value) { + for (var i = 0; i < attributes.size.value.length; i++) { + attributes.size.value[i] = attributes.size.value[i] / this._sizeScale * sizeScale; + } + } + } + this._sizeScale = sizeScale; + } + }, + + _setPositionTextureToMesh: function (mesh, texture) { + if (texture) { + mesh.material.set('positionTexture', texture); + } + mesh.material[ + texture ? 'enableTexture' : 'disableTexture' + ]('positionTexture'); + }, + + _getSymbolInfo: function (seriesModel, start, end) { + if (seriesModel.get('large')) { + var symbolSize = __WEBPACK_IMPORTED_MODULE_6__util_retrieve__["a" /* default */].firstNotNull(seriesModel.get('symbolSize'), 1); + var maxSymbolSize; + var symbolAspect; + if (symbolSize instanceof Array) { + maxSymbolSize = Math.max(symbolSize[0], symbolSize[1]); + symbolAspect = symbolSize[0] / symbolSize[1]; + } + else { + maxSymbolSize = symbolSize; + symbolAspect = 1; + } + return { + maxSize: symbolSize, + type: seriesModel.get('symbol'), + aspect: symbolAspect + } + } + var data = seriesModel.getData(); + var symbolAspect; + var differentSymbolAspect = false; + var symbolType = data.getItemVisual(0, 'symbol') || 'circle'; + var differentSymbolType = false; + var maxSymbolSize = 0; + + for (var idx = start; idx < end; idx++) { + var symbolSize = data.getItemVisual(idx, 'symbolSize'); + var currentSymbolType = data.getItemVisual(idx, 'symbol'); + var currentSymbolAspect; + if (!(symbolSize instanceof Array)) { + // Ignore NaN value. + if (isNaN(symbolSize)) { + return; + } + + currentSymbolAspect = 1; + maxSymbolSize = Math.max(symbolSize, maxSymbolSize); + } + else { + currentSymbolAspect = symbolSize[0] / symbolSize[1]; + maxSymbolSize = Math.max(Math.max(symbolSize[0], symbolSize[1]), maxSymbolSize); + } + if (true) { + if (symbolAspect != null && Math.abs(currentSymbolAspect - symbolAspect) > 0.05) { + differentSymbolAspect = true; + } + if (currentSymbolType !== symbolType) { + differentSymbolType = true; + } + } + symbolType = currentSymbolType; + symbolAspect = currentSymbolAspect; + } + + if (true) { + if (differentSymbolAspect) { + console.warn('Different symbol width / height ratio will be ignored.'); + } + if (differentSymbolType) { + console.warn('Different symbol type will be ignored.'); + } + } + + return { + maxSize: maxSymbolSize, + type: symbolType, + aspect: symbolAspect + }; + } +}; + +/* harmony default export */ __webpack_exports__["a"] = (PointsBuilder); + + +/***/ }), +/* 68 */ +/***/ (function(module, exports) { + +var g; + +// This works in non-strict mode +g = (function() { + return this; +})(); + +try { + // This works if eval is allowed (see CSP) + g = g || Function("return this")() || (1,eval)("this"); +} catch(e) { + // This works if the window reference is available + if(typeof window === "object") + g = window; +} + +// g can still be undefined, but nothing to do about it... +// We return undefined, instead of nothing here, so it's +// easier to handle this case. if(!global) { ...} + +module.exports = g; + + +/***/ }), +/* 69 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__LinkedList__ = __webpack_require__(114); + + +/** + * LRU Cache + * @constructor + * @alias clay.core.LRU + */ +var LRU = function (maxSize) { + + this._list = new __WEBPACK_IMPORTED_MODULE_0__LinkedList__["a" /* default */](); + + this._map = {}; + + this._maxSize = maxSize || 10; +}; + +/** + * Set cache max size + * @param {number} size + */ +LRU.prototype.setMaxSize = function (size) { + this._maxSize = size; +}; + +/** + * @param {string} key + * @param {} value + */ +LRU.prototype.put = function (key, value) { + if (!this._map.hasOwnProperty(key)) { + var len = this._list.length(); + if (len >= this._maxSize && len > 0) { + // Remove the least recently used + var leastUsedEntry = this._list.head; + this._list.remove(leastUsedEntry); + delete this._map[leastUsedEntry.key]; + } + + var entry = this._list.insert(value); + entry.key = key; + this._map[key] = entry; + } +}; + +/** + * @param {string} key + * @return {} + */ +LRU.prototype.get = function (key) { + var entry = this._map[key]; + if (this._map.hasOwnProperty(key)) { + // Put the latest used entry in the tail + if (entry !== this._list.tail) { + this._list.remove(entry); + this._list.insertEntry(entry); + } + + return entry.value; + } +}; + +/** + * @param {string} key + */ +LRU.prototype.remove = function (key) { + var entry = this._map[key]; + if (typeof(entry) !== 'undefined') { + delete this._map[key]; + this._list.remove(entry); + } +}; + +/** + * Clear the cache + */ +LRU.prototype.clear = function () { + this._list.clear(); + this._map = {}; +}; + +/* harmony default export */ __webpack_exports__["a"] = (LRU); + + +/***/ }), +/* 70 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__common__ = __webpack_require__(20); + +/* Copyright (c) 2013, Brandon Jones, Colin MacKenzie IV. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + + + +/** + * @class 2 Dimensional Vector + * @name vec2 + */ + +var vec2 = {}; + +/** + * Creates a new, empty vec2 + * + * @returns {vec2} a new 2D vector + */ +vec2.create = function() { + var out = new __WEBPACK_IMPORTED_MODULE_0__common__["a" /* GLMAT_ARRAY_TYPE */](2); + out[0] = 0; + out[1] = 0; + return out; +}; + +/** + * Creates a new vec2 initialized with values from an existing vector + * + * @param {vec2} a vector to clone + * @returns {vec2} a new 2D vector + */ +vec2.clone = function(a) { + var out = new __WEBPACK_IMPORTED_MODULE_0__common__["a" /* GLMAT_ARRAY_TYPE */](2); + out[0] = a[0]; + out[1] = a[1]; + return out; +}; + +/** + * Creates a new vec2 initialized with the given values + * + * @param {Number} x X component + * @param {Number} y Y component + * @returns {vec2} a new 2D vector + */ +vec2.fromValues = function(x, y) { + var out = new __WEBPACK_IMPORTED_MODULE_0__common__["a" /* GLMAT_ARRAY_TYPE */](2); + out[0] = x; + out[1] = y; + return out; +}; + +/** + * Copy the values from one vec2 to another + * + * @param {vec2} out the receiving vector + * @param {vec2} a the source vector + * @returns {vec2} out + */ +vec2.copy = function(out, a) { + out[0] = a[0]; + out[1] = a[1]; + return out; +}; + +/** + * Set the components of a vec2 to the given values + * + * @param {vec2} out the receiving vector + * @param {Number} x X component + * @param {Number} y Y component + * @returns {vec2} out + */ +vec2.set = function(out, x, y) { + out[0] = x; + out[1] = y; + return out; +}; + +/** + * Adds two vec2's + * + * @param {vec2} out the receiving vector + * @param {vec2} a the first operand + * @param {vec2} b the second operand + * @returns {vec2} out + */ +vec2.add = function(out, a, b) { + out[0] = a[0] + b[0]; + out[1] = a[1] + b[1]; + return out; +}; + +/** + * Subtracts vector b from vector a + * + * @param {vec2} out the receiving vector + * @param {vec2} a the first operand + * @param {vec2} b the second operand + * @returns {vec2} out + */ +vec2.subtract = function(out, a, b) { + out[0] = a[0] - b[0]; + out[1] = a[1] - b[1]; + return out; +}; + +/** + * Alias for {@link vec2.subtract} + * @function + */ +vec2.sub = vec2.subtract; + +/** + * Multiplies two vec2's + * + * @param {vec2} out the receiving vector + * @param {vec2} a the first operand + * @param {vec2} b the second operand + * @returns {vec2} out + */ +vec2.multiply = function(out, a, b) { + out[0] = a[0] * b[0]; + out[1] = a[1] * b[1]; + return out; +}; + +/** + * Alias for {@link vec2.multiply} + * @function + */ +vec2.mul = vec2.multiply; + +/** + * Divides two vec2's + * + * @param {vec2} out the receiving vector + * @param {vec2} a the first operand + * @param {vec2} b the second operand + * @returns {vec2} out + */ +vec2.divide = function(out, a, b) { + out[0] = a[0] / b[0]; + out[1] = a[1] / b[1]; + return out; +}; + +/** + * Alias for {@link vec2.divide} + * @function + */ +vec2.div = vec2.divide; + +/** + * Returns the minimum of two vec2's + * + * @param {vec2} out the receiving vector + * @param {vec2} a the first operand + * @param {vec2} b the second operand + * @returns {vec2} out + */ +vec2.min = function(out, a, b) { + out[0] = Math.min(a[0], b[0]); + out[1] = Math.min(a[1], b[1]); + return out; +}; + +/** + * Returns the maximum of two vec2's + * + * @param {vec2} out the receiving vector + * @param {vec2} a the first operand + * @param {vec2} b the second operand + * @returns {vec2} out + */ +vec2.max = function(out, a, b) { + out[0] = Math.max(a[0], b[0]); + out[1] = Math.max(a[1], b[1]); + return out; +}; + +/** + * Scales a vec2 by a scalar number + * + * @param {vec2} out the receiving vector + * @param {vec2} a the vector to scale + * @param {Number} b amount to scale the vector by + * @returns {vec2} out + */ +vec2.scale = function(out, a, b) { + out[0] = a[0] * b; + out[1] = a[1] * b; + return out; +}; + +/** + * Adds two vec2's after scaling the second operand by a scalar value + * + * @param {vec2} out the receiving vector + * @param {vec2} a the first operand + * @param {vec2} b the second operand + * @param {Number} scale the amount to scale b by before adding + * @returns {vec2} out + */ +vec2.scaleAndAdd = function(out, a, b, scale) { + out[0] = a[0] + (b[0] * scale); + out[1] = a[1] + (b[1] * scale); + return out; +}; + +/** + * Calculates the euclidian distance between two vec2's + * + * @param {vec2} a the first operand + * @param {vec2} b the second operand + * @returns {Number} distance between a and b + */ +vec2.distance = function(a, b) { + var x = b[0] - a[0], + y = b[1] - a[1]; + return Math.sqrt(x*x + y*y); +}; + +/** + * Alias for {@link vec2.distance} + * @function + */ +vec2.dist = vec2.distance; + +/** + * Calculates the squared euclidian distance between two vec2's + * + * @param {vec2} a the first operand + * @param {vec2} b the second operand + * @returns {Number} squared distance between a and b + */ +vec2.squaredDistance = function(a, b) { + var x = b[0] - a[0], + y = b[1] - a[1]; + return x*x + y*y; +}; + +/** + * Alias for {@link vec2.squaredDistance} + * @function + */ +vec2.sqrDist = vec2.squaredDistance; + +/** + * Calculates the length of a vec2 + * + * @param {vec2} a vector to calculate length of + * @returns {Number} length of a + */ +vec2.length = function (a) { + var x = a[0], + y = a[1]; + return Math.sqrt(x*x + y*y); +}; + +/** + * Alias for {@link vec2.length} + * @function + */ +vec2.len = vec2.length; + +/** + * Calculates the squared length of a vec2 + * + * @param {vec2} a vector to calculate squared length of + * @returns {Number} squared length of a + */ +vec2.squaredLength = function (a) { + var x = a[0], + y = a[1]; + return x*x + y*y; +}; + +/** + * Alias for {@link vec2.squaredLength} + * @function + */ +vec2.sqrLen = vec2.squaredLength; + +/** + * Negates the components of a vec2 + * + * @param {vec2} out the receiving vector + * @param {vec2} a vector to negate + * @returns {vec2} out + */ +vec2.negate = function(out, a) { + out[0] = -a[0]; + out[1] = -a[1]; + return out; +}; + +/** + * Returns the inverse of the components of a vec2 + * + * @param {vec2} out the receiving vector + * @param {vec2} a vector to invert + * @returns {vec2} out + */ +vec2.inverse = function(out, a) { + out[0] = 1.0 / a[0]; + out[1] = 1.0 / a[1]; + return out; +}; + +/** + * Normalize a vec2 + * + * @param {vec2} out the receiving vector + * @param {vec2} a vector to normalize + * @returns {vec2} out + */ +vec2.normalize = function(out, a) { + var x = a[0], + y = a[1]; + var len = x*x + y*y; + if (len > 0) { + //TODO: evaluate use of glm_invsqrt here? + len = 1 / Math.sqrt(len); + out[0] = a[0] * len; + out[1] = a[1] * len; + } + return out; +}; + +/** + * Calculates the dot product of two vec2's + * + * @param {vec2} a the first operand + * @param {vec2} b the second operand + * @returns {Number} dot product of a and b + */ +vec2.dot = function (a, b) { + return a[0] * b[0] + a[1] * b[1]; +}; + +/** + * Computes the cross product of two vec2's + * Note that the cross product must by definition produce a 3D vector + * + * @param {vec3} out the receiving vector + * @param {vec2} a the first operand + * @param {vec2} b the second operand + * @returns {vec3} out + */ +vec2.cross = function(out, a, b) { + var z = a[0] * b[1] - a[1] * b[0]; + out[0] = out[1] = 0; + out[2] = z; + return out; +}; + +/** + * Performs a linear interpolation between two vec2's + * + * @param {vec2} out the receiving vector + * @param {vec2} a the first operand + * @param {vec2} b the second operand + * @param {Number} t interpolation amount between the two inputs + * @returns {vec2} out + */ +vec2.lerp = function (out, a, b, t) { + var ax = a[0], + ay = a[1]; + out[0] = ax + t * (b[0] - ax); + out[1] = ay + t * (b[1] - ay); + return out; +}; + +/** + * Generates a random vector with the given scale + * + * @param {vec2} out the receiving vector + * @param {Number} [scale] Length of the resulting vector. If ommitted, a unit vector will be returned + * @returns {vec2} out + */ +vec2.random = function (out, scale) { + scale = scale || 1.0; + var r = GLMAT_RANDOM() * 2.0 * Math.PI; + out[0] = Math.cos(r) * scale; + out[1] = Math.sin(r) * scale; + return out; +}; + +/** + * Transforms the vec2 with a mat2 + * + * @param {vec2} out the receiving vector + * @param {vec2} a the vector to transform + * @param {mat2} m matrix to transform with + * @returns {vec2} out + */ +vec2.transformMat2 = function(out, a, m) { + var x = a[0], + y = a[1]; + out[0] = m[0] * x + m[2] * y; + out[1] = m[1] * x + m[3] * y; + return out; +}; + +/** + * Transforms the vec2 with a mat2d + * + * @param {vec2} out the receiving vector + * @param {vec2} a the vector to transform + * @param {mat2d} m matrix to transform with + * @returns {vec2} out + */ +vec2.transformMat2d = function(out, a, m) { + var x = a[0], + y = a[1]; + out[0] = m[0] * x + m[2] * y + m[4]; + out[1] = m[1] * x + m[3] * y + m[5]; + return out; +}; + +/** + * Transforms the vec2 with a mat3 + * 3rd vector component is implicitly '1' + * + * @param {vec2} out the receiving vector + * @param {vec2} a the vector to transform + * @param {mat3} m matrix to transform with + * @returns {vec2} out + */ +vec2.transformMat3 = function(out, a, m) { + var x = a[0], + y = a[1]; + out[0] = m[0] * x + m[3] * y + m[6]; + out[1] = m[1] * x + m[4] * y + m[7]; + return out; +}; + +/** + * Transforms the vec2 with a mat4 + * 3rd vector component is implicitly '0' + * 4th vector component is implicitly '1' + * + * @param {vec2} out the receiving vector + * @param {vec2} a the vector to transform + * @param {mat4} m matrix to transform with + * @returns {vec2} out + */ +vec2.transformMat4 = function(out, a, m) { + var x = a[0], + y = a[1]; + out[0] = m[0] * x + m[4] * y + m[12]; + out[1] = m[1] * x + m[5] * y + m[13]; + return out; +}; + +/** + * Perform some operation over an array of vec2s. + * + * @param {Array} a the array of vectors to iterate over + * @param {Number} stride Number of elements between the start of each vec2. If 0 assumes tightly packed + * @param {Number} offset Number of elements to skip at the beginning of the array + * @param {Number} count Number of vec2s to iterate over. If 0 iterates over entire array + * @param {Function} fn Function to call for each vector in the array + * @param {Object} [arg] additional argument to pass to fn + * @returns {Array} a + * @function + */ +vec2.forEach = (function() { + var vec = vec2.create(); + + return function(a, stride, offset, count, fn, arg) { + var i, l; + if(!stride) { + stride = 2; + } + + if(!offset) { + offset = 0; + } + + if(count) { + l = Math.min((count * stride) + offset, a.length); + } else { + l = a.length; + } + + for(i = offset; i < l; i += stride) { + vec[0] = a[i]; vec[1] = a[i+1]; + fn(vec, vec, arg); + a[i] = vec[0]; a[i+1] = vec[1]; + } + + return a; + }; +})(); + +/* harmony default export */ __webpack_exports__["a"] = (vec2); + +/***/ }), +/* 71 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony default export */ __webpack_exports__["a"] = ("@export clay.prez.vertex\nuniform mat4 WVP : WORLDVIEWPROJECTION;\nattribute vec3 pos : POSITION;\nattribute vec2 uv : TEXCOORD_0;\n@import clay.chunk.skinning_header\nvarying vec2 v_Texcoord;\nvoid main()\n{\n vec3 P = pos;\n#ifdef SKINNING\n @import clay.chunk.skin_matrix\n P = (skinMatrixWS * vec4(pos, 1.0)).xyz;\n#endif\n gl_Position = WVP * vec4(P, 1.0);\n v_Texcoord = uv;\n}\n@end\n@export clay.prez.fragment\nuniform sampler2D alphaMap;\nuniform float alphaCutoff: 0.0;\nvarying vec2 v_Texcoord;\nvoid main()\n{\n if (alphaCutoff > 0.0) {\n if (texture2D(alphaMap, v_Texcoord).a <= alphaCutoff) {\n discard;\n }\n }\n gl_FragColor = vec4(0.0,0.0,0.0,1.0);\n}\n@end"); + + +/***/ }), +/* 72 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__Node__ = __webpack_require__(35); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__core_glenum__ = __webpack_require__(11); + + + +/** + * @constructor + * @alias clay.Renderable + * @extends clay.Node + */ +var Renderable = __WEBPACK_IMPORTED_MODULE_0__Node__["a" /* default */].extend(/** @lends clay.Renderable# */ { + /** + * @type {clay.Material} + */ + material: null, + + /** + * @type {clay.Geometry} + */ + geometry: null, + + /** + * @type {number} + */ + mode: __WEBPACK_IMPORTED_MODULE_1__core_glenum__["a" /* default */].TRIANGLES, + + _renderInfo: null +}, +/** @lends clay.Renderable.prototype */ +{ + + __program: null, + + /** + * Group of received light. + */ + lightGroup: 0, + /** + * Render order, Nodes with smaller value renders before nodes with larger values. + * @type {Number} + */ + renderOrder: 0, + + /** + * Used when mode is LINES, LINE_STRIP or LINE_LOOP + * @type {number} + */ + // lineWidth: 1, + + /** + * If enable culling + * @type {boolean} + */ + culling: true, + /** + * Specify which side of polygon will be culled. + * Possible values: + * + {@link clay.Renderable.BACK} + * + {@link clay.Renderable.FRONT} + * + {@link clay.Renderable.FRONT_AND_BACK} + * @see https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/cullFace + * @type {number} + */ + cullFace: __WEBPACK_IMPORTED_MODULE_1__core_glenum__["a" /* default */].BACK, + /** + * Specify which side is front face. + * Possible values: + * + {@link clay.Renderable.CW} + * + {@link clay.Renderable.CCW} + * @see https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/frontFace + * @type {number} + */ + frontFace: __WEBPACK_IMPORTED_MODULE_1__core_glenum__["a" /* default */].CCW, + + /** + * If enable software frustum culling + * @type {boolean} + */ + frustumCulling: true, + /** + * @type {boolean} + */ + receiveShadow: true, + /** + * @type {boolean} + */ + castShadow: true, + /** + * @type {boolean} + */ + ignorePicking: false, + /** + * @type {boolean} + */ + ignorePreZ: false, + + /** + * @type {boolean} + */ + ignoreGBuffer: false, + + /** + * @return {boolean} + */ + isRenderable: function() { + // TODO Shader ? + return this.geometry && this.material && this.material.shader && !this.invisible + && this.geometry.vertexCount > 0; + }, + + /** + * Before render hook + * @type {Function} + */ + beforeRender: function (_gl) {}, + + /** + * Before render hook + * @type {Function} + */ + afterRender: function (_gl, renderStat) {}, + + getBoundingBox: function (filter, out) { + out = __WEBPACK_IMPORTED_MODULE_0__Node__["a" /* default */].prototype.getBoundingBox.call(this, filter, out); + if (this.geometry && this.geometry.boundingBox) { + out.union(this.geometry.boundingBox); + } + + return out; + }, + + /** + * Clone a new renderable + * @function + * @return {clay.Renderable} + */ + clone: (function() { + var properties = [ + 'castShadow', 'receiveShadow', + 'mode', 'culling', 'cullFace', 'frontFace', + 'frustumCulling', + 'renderOrder', 'lineWidth', + 'ignorePicking', 'ignorePreZ', 'ignoreGBuffer' + ]; + return function() { + var renderable = __WEBPACK_IMPORTED_MODULE_0__Node__["a" /* default */].prototype.clone.call(this); + + renderable.geometry = this.geometry; + renderable.material = this.material; + + for (var i = 0; i < properties.length; i++) { + var name = properties[i]; + // Try not to overwrite the prototype property + if (renderable[name] !== this[name]) { + renderable[name] = this[name]; + } + } + + return renderable; + }; + })() +}); + +/** + * @type {number} + */ +Renderable.POINTS = __WEBPACK_IMPORTED_MODULE_1__core_glenum__["a" /* default */].POINTS; +/** + * @type {number} + */ +Renderable.LINES = __WEBPACK_IMPORTED_MODULE_1__core_glenum__["a" /* default */].LINES; +/** + * @type {number} + */ +Renderable.LINE_LOOP = __WEBPACK_IMPORTED_MODULE_1__core_glenum__["a" /* default */].LINE_LOOP; +/** + * @type {number} + */ +Renderable.LINE_STRIP = __WEBPACK_IMPORTED_MODULE_1__core_glenum__["a" /* default */].LINE_STRIP; +/** + * @type {number} + */ +Renderable.TRIANGLES = __WEBPACK_IMPORTED_MODULE_1__core_glenum__["a" /* default */].TRIANGLES; +/** + * @type {number} + */ +Renderable.TRIANGLE_STRIP = __WEBPACK_IMPORTED_MODULE_1__core_glenum__["a" /* default */].TRIANGLE_STRIP; +/** + * @type {number} + */ +Renderable.TRIANGLE_FAN = __WEBPACK_IMPORTED_MODULE_1__core_glenum__["a" /* default */].TRIANGLE_FAN; +/** + * @type {number} + */ +Renderable.BACK = __WEBPACK_IMPORTED_MODULE_1__core_glenum__["a" /* default */].BACK; +/** + * @type {number} + */ +Renderable.FRONT = __WEBPACK_IMPORTED_MODULE_1__core_glenum__["a" /* default */].FRONT; +/** + * @type {number} + */ +Renderable.FRONT_AND_BACK = __WEBPACK_IMPORTED_MODULE_1__core_glenum__["a" /* default */].FRONT_AND_BACK; +/** + * @type {number} + */ +Renderable.CW = __WEBPACK_IMPORTED_MODULE_1__core_glenum__["a" /* default */].CW; +/** + * @type {number} + */ +Renderable.CCW = __WEBPACK_IMPORTED_MODULE_1__core_glenum__["a" /* default */].CCW; + +/* harmony default export */ __webpack_exports__["a"] = (Renderable); + + +/***/ }), +/* 73 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +var mathUtil = {}; + +mathUtil.isPowerOfTwo = function (value) { + return (value & (value - 1)) === 0; +}; + +mathUtil.nextPowerOfTwo = function (value) { + value --; + value |= value >> 1; + value |= value >> 2; + value |= value >> 4; + value |= value >> 8; + value |= value >> 16; + value ++; + + return value; +}; + +mathUtil.nearestPowerOfTwo = function (value) { + return Math.pow( 2, Math.round( Math.log( value ) / Math.LN2 ) ); +}; + +/* harmony default export */ __webpack_exports__["a"] = (mathUtil); + + +/***/ }), +/* 74 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__Vector3__ = __webpack_require__(3); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__glmatrix_mat4__ = __webpack_require__(21); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__glmatrix_vec3__ = __webpack_require__(12); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__glmatrix_vec4__ = __webpack_require__(33); + + + + + +/** + * @constructor + * @alias clay.Plane + * @param {clay.Vector3} [normal] + * @param {number} [distance] + */ +var Plane = function(normal, distance) { + /** + * Normal of the plane + * @type {clay.Vector3} + */ + this.normal = normal || new __WEBPACK_IMPORTED_MODULE_0__Vector3__["a" /* default */](0, 1, 0); + + /** + * Constant of the plane equation, used as distance to the origin + * @type {number} + */ + this.distance = distance || 0; +}; + +Plane.prototype = { + + constructor: Plane, + + /** + * Distance from a given point to the plane + * @param {clay.Vector3} point + * @return {number} + */ + distanceToPoint: function(point) { + return __WEBPACK_IMPORTED_MODULE_2__glmatrix_vec3__["a" /* default */].dot(point.array, this.normal.array) - this.distance; + }, + + /** + * Calculate the projection point on the plane + * @param {clay.Vector3} point + * @param {clay.Vector3} out + * @return {clay.Vector3} + */ + projectPoint: function(point, out) { + if (!out) { + out = new __WEBPACK_IMPORTED_MODULE_0__Vector3__["a" /* default */](); + } + var d = this.distanceToPoint(point); + __WEBPACK_IMPORTED_MODULE_2__glmatrix_vec3__["a" /* default */].scaleAndAdd(out.array, point.array, this.normal.array, -d); + out._dirty = true; + return out; + }, + + /** + * Normalize the plane's normal and calculate the distance + */ + normalize: function() { + var invLen = 1 / __WEBPACK_IMPORTED_MODULE_2__glmatrix_vec3__["a" /* default */].len(this.normal.array); + __WEBPACK_IMPORTED_MODULE_2__glmatrix_vec3__["a" /* default */].scale(this.normal.array, invLen); + this.distance *= invLen; + }, + + /** + * If the plane intersect a frustum + * @param {clay.Frustum} Frustum + * @return {boolean} + */ + intersectFrustum: function(frustum) { + // Check if all coords of frustum is on plane all under plane + var coords = frustum.vertices; + var normal = this.normal.array; + var onPlane = __WEBPACK_IMPORTED_MODULE_2__glmatrix_vec3__["a" /* default */].dot(coords[0].array, normal) > this.distance; + for (var i = 1; i < 8; i++) { + if ((__WEBPACK_IMPORTED_MODULE_2__glmatrix_vec3__["a" /* default */].dot(coords[i].array, normal) > this.distance) != onPlane) { + return true; + } + } + }, + + /** + * Calculate the intersection point between plane and a given line + * @function + * @param {clay.Vector3} start start point of line + * @param {clay.Vector3} end end point of line + * @param {clay.Vector3} [out] + * @return {clay.Vector3} + */ + intersectLine: (function() { + var rd = __WEBPACK_IMPORTED_MODULE_2__glmatrix_vec3__["a" /* default */].create(); + return function(start, end, out) { + var d0 = this.distanceToPoint(start); + var d1 = this.distanceToPoint(end); + if ((d0 > 0 && d1 > 0) || (d0 < 0 && d1 < 0)) { + return null; + } + // Ray intersection + var pn = this.normal.array; + var d = this.distance; + var ro = start.array; + // direction + __WEBPACK_IMPORTED_MODULE_2__glmatrix_vec3__["a" /* default */].sub(rd, end.array, start.array); + __WEBPACK_IMPORTED_MODULE_2__glmatrix_vec3__["a" /* default */].normalize(rd, rd); + + var divider = __WEBPACK_IMPORTED_MODULE_2__glmatrix_vec3__["a" /* default */].dot(pn, rd); + // ray is parallel to the plane + if (divider === 0) { + return null; + } + if (!out) { + out = new __WEBPACK_IMPORTED_MODULE_0__Vector3__["a" /* default */](); + } + var t = (__WEBPACK_IMPORTED_MODULE_2__glmatrix_vec3__["a" /* default */].dot(pn, ro) - d) / divider; + __WEBPACK_IMPORTED_MODULE_2__glmatrix_vec3__["a" /* default */].scaleAndAdd(out.array, ro, rd, -t); + out._dirty = true; + return out; + }; + })(), + + /** + * Apply an affine transform matrix to plane + * @function + * @return {clay.Matrix4} + */ + applyTransform: (function() { + var inverseTranspose = __WEBPACK_IMPORTED_MODULE_1__glmatrix_mat4__["a" /* default */].create(); + var normalv4 = __WEBPACK_IMPORTED_MODULE_3__glmatrix_vec4__["a" /* default */].create(); + var pointv4 = __WEBPACK_IMPORTED_MODULE_3__glmatrix_vec4__["a" /* default */].create(); + pointv4[3] = 1; + return function(m4) { + m4 = m4.array; + // Transform point on plane + __WEBPACK_IMPORTED_MODULE_2__glmatrix_vec3__["a" /* default */].scale(pointv4, this.normal.array, this.distance); + __WEBPACK_IMPORTED_MODULE_3__glmatrix_vec4__["a" /* default */].transformMat4(pointv4, pointv4, m4); + this.distance = __WEBPACK_IMPORTED_MODULE_2__glmatrix_vec3__["a" /* default */].dot(pointv4, this.normal.array); + // Transform plane normal + __WEBPACK_IMPORTED_MODULE_1__glmatrix_mat4__["a" /* default */].invert(inverseTranspose, m4); + __WEBPACK_IMPORTED_MODULE_1__glmatrix_mat4__["a" /* default */].transpose(inverseTranspose, inverseTranspose); + normalv4[3] = 0; + __WEBPACK_IMPORTED_MODULE_2__glmatrix_vec3__["a" /* default */].copy(normalv4, this.normal.array); + __WEBPACK_IMPORTED_MODULE_3__glmatrix_vec4__["a" /* default */].transformMat4(normalv4, normalv4, inverseTranspose); + __WEBPACK_IMPORTED_MODULE_2__glmatrix_vec3__["a" /* default */].copy(this.normal.array, normalv4); + }; + })(), + + /** + * Copy from another plane + * @param {clay.Vector3} plane + */ + copy: function(plane) { + __WEBPACK_IMPORTED_MODULE_2__glmatrix_vec3__["a" /* default */].copy(this.normal.array, plane.normal.array); + this.normal._dirty = true; + this.distance = plane.distance; + }, + + /** + * Clone a new plane + * @return {clay.Plane} + */ + clone: function() { + var plane = new Plane(); + plane.copy(this); + return plane; + } +}; + +/* harmony default export */ __webpack_exports__["a"] = (Plane); + + +/***/ }), +/* 75 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__Skybox__ = __webpack_require__(42); + + +/* harmony default export */ __webpack_exports__["a"] = (__WEBPACK_IMPORTED_MODULE_0__Skybox__["a" /* default */]); + +/***/ }), +/* 76 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__Geometry__ = __webpack_require__(15); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__Plane__ = __webpack_require__(43); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__math_Matrix4__ = __webpack_require__(9); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__math_Vector3__ = __webpack_require__(3); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4__math_BoundingBox__ = __webpack_require__(18); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_5__core_vendor__ = __webpack_require__(14); + + + + + + + +var planeMatrix = new __WEBPACK_IMPORTED_MODULE_2__math_Matrix4__["a" /* default */](); + +/** + * @constructor clay.geometry.Cube + * @extends clay.Geometry + * @param {Object} [opt] + * @param {number} [opt.widthSegments] + * @param {number} [opt.heightSegments] + * @param {number} [opt.depthSegments] + * @param {boolean} [opt.inside] + */ +var Cube = __WEBPACK_IMPORTED_MODULE_0__Geometry__["a" /* default */].extend( +/**@lends clay.geometry.Cube# */ +{ + dynamic: false, + /** + * @type {number} + */ + widthSegments: 1, + /** + * @type {number} + */ + heightSegments: 1, + /** + * @type {number} + */ + depthSegments: 1, + /** + * @type {boolean} + */ + inside: false +}, function() { + this.build(); +}, +/** @lends clay.geometry.Cube.prototype */ +{ + /** + * Build cube geometry + */ + build: function() { + + var planes = { + 'px': createPlane('px', this.depthSegments, this.heightSegments), + 'nx': createPlane('nx', this.depthSegments, this.heightSegments), + 'py': createPlane('py', this.widthSegments, this.depthSegments), + 'ny': createPlane('ny', this.widthSegments, this.depthSegments), + 'pz': createPlane('pz', this.widthSegments, this.heightSegments), + 'nz': createPlane('nz', this.widthSegments, this.heightSegments), + }; + + var attrList = ['position', 'texcoord0', 'normal']; + var vertexNumber = 0; + var faceNumber = 0; + for (var pos in planes) { + vertexNumber += planes[pos].vertexCount; + faceNumber += planes[pos].indices.length; + } + for (var k = 0; k < attrList.length; k++) { + this.attributes[attrList[k]].init(vertexNumber); + } + this.indices = new __WEBPACK_IMPORTED_MODULE_5__core_vendor__["a" /* default */].Uint16Array(faceNumber); + var faceOffset = 0; + var vertexOffset = 0; + for (var pos in planes) { + var plane = planes[pos]; + for (var k = 0; k < attrList.length; k++) { + var attrName = attrList[k]; + var attrArray = plane.attributes[attrName].value; + var attrSize = plane.attributes[attrName].size; + var isNormal = attrName === 'normal'; + for (var i = 0; i < attrArray.length; i++) { + var value = attrArray[i]; + if (this.inside && isNormal) { + value = -value; + } + this.attributes[attrName].value[i + attrSize * vertexOffset] = value; + } + } + var len = plane.indices.length; + for (var i = 0; i < plane.indices.length; i++) { + this.indices[i + faceOffset] = vertexOffset + plane.indices[this.inside ? (len - i - 1) : i]; + } + faceOffset += plane.indices.length; + vertexOffset += plane.vertexCount; + } + + this.boundingBox = new __WEBPACK_IMPORTED_MODULE_4__math_BoundingBox__["a" /* default */](); + this.boundingBox.max.set(1, 1, 1); + this.boundingBox.min.set(-1, -1, -1); + } +}); + +function createPlane(pos, widthSegments, heightSegments) { + + planeMatrix.identity(); + + var plane = new __WEBPACK_IMPORTED_MODULE_1__Plane__["a" /* default */]({ + widthSegments: widthSegments, + heightSegments: heightSegments + }); + + switch(pos) { + case 'px': + __WEBPACK_IMPORTED_MODULE_2__math_Matrix4__["a" /* default */].translate(planeMatrix, planeMatrix, __WEBPACK_IMPORTED_MODULE_3__math_Vector3__["a" /* default */].POSITIVE_X); + __WEBPACK_IMPORTED_MODULE_2__math_Matrix4__["a" /* default */].rotateY(planeMatrix, planeMatrix, Math.PI / 2); + break; + case 'nx': + __WEBPACK_IMPORTED_MODULE_2__math_Matrix4__["a" /* default */].translate(planeMatrix, planeMatrix, __WEBPACK_IMPORTED_MODULE_3__math_Vector3__["a" /* default */].NEGATIVE_X); + __WEBPACK_IMPORTED_MODULE_2__math_Matrix4__["a" /* default */].rotateY(planeMatrix, planeMatrix, -Math.PI / 2); + break; + case 'py': + __WEBPACK_IMPORTED_MODULE_2__math_Matrix4__["a" /* default */].translate(planeMatrix, planeMatrix, __WEBPACK_IMPORTED_MODULE_3__math_Vector3__["a" /* default */].POSITIVE_Y); + __WEBPACK_IMPORTED_MODULE_2__math_Matrix4__["a" /* default */].rotateX(planeMatrix, planeMatrix, -Math.PI / 2); + break; + case 'ny': + __WEBPACK_IMPORTED_MODULE_2__math_Matrix4__["a" /* default */].translate(planeMatrix, planeMatrix, __WEBPACK_IMPORTED_MODULE_3__math_Vector3__["a" /* default */].NEGATIVE_Y); + __WEBPACK_IMPORTED_MODULE_2__math_Matrix4__["a" /* default */].rotateX(planeMatrix, planeMatrix, Math.PI / 2); + break; + case 'pz': + __WEBPACK_IMPORTED_MODULE_2__math_Matrix4__["a" /* default */].translate(planeMatrix, planeMatrix, __WEBPACK_IMPORTED_MODULE_3__math_Vector3__["a" /* default */].POSITIVE_Z); + break; + case 'nz': + __WEBPACK_IMPORTED_MODULE_2__math_Matrix4__["a" /* default */].translate(planeMatrix, planeMatrix, __WEBPACK_IMPORTED_MODULE_3__math_Vector3__["a" /* default */].NEGATIVE_Z); + __WEBPACK_IMPORTED_MODULE_2__math_Matrix4__["a" /* default */].rotateY(planeMatrix, planeMatrix, Math.PI); + break; + } + plane.applyTransform(planeMatrix); + return plane; +} + +/* harmony default export */ __webpack_exports__["a"] = (Cube); + + +/***/ }), +/* 77 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__Texture2D__ = __webpack_require__(5); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__TextureCube__ = __webpack_require__(27); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__Texture__ = __webpack_require__(4); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__FrameBuffer__ = __webpack_require__(10); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4__compositor_Pass__ = __webpack_require__(16); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_5__Material__ = __webpack_require__(19); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_6__Shader__ = __webpack_require__(8); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_7__plugin_Skybox__ = __webpack_require__(42); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_8__Scene__ = __webpack_require__(36); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_9__prePass_EnvironmentMap__ = __webpack_require__(62); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_10__core_vendor__ = __webpack_require__(14); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_11__texture__ = __webpack_require__(61); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_12__shader_integrateBRDF_glsl_js__ = __webpack_require__(127); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_13__shader_prefilter_glsl_js__ = __webpack_require__(128); +// Cubemap prefilter utility +// http://www.unrealengine.com/files/downloads/2013SiggraphPresentationsNotes.pdf +// http://http.developer.nvidia.com/GPUGems3/gpugems3_ch20.html + + + + + + + + + + + + + + + + +var cubemapUtil = {}; + +var targets = ['px', 'nx', 'py', 'ny', 'pz', 'nz']; + +// TODO Downsample +/** + * @name clay.util.cubemap.prefilterEnvironmentMap + * @param {clay.Renderer} renderer + * @param {clay.Texture} envMap + * @param {Object} [textureOpts] + * @param {number} [textureOpts.width=64] + * @param {number} [textureOpts.height=64] + * @param {number} [textureOpts.type] + * @param {boolean} [textureOpts.encodeRGBM=false] + * @param {boolean} [textureOpts.decodeRGBM=false] + * @param {clay.Texture2D} [normalDistribution] + * @param {clay.Texture2D} [brdfLookup] + */ +cubemapUtil.prefilterEnvironmentMap = function ( + renderer, envMap, textureOpts, normalDistribution, brdfLookup +) { + // Not create other renderer, it is easy having issue of cross reference of resources like framebuffer + // PENDING preserveDrawingBuffer? + if (!brdfLookup || !normalDistribution) { + normalDistribution = cubemapUtil.generateNormalDistribution(); + brdfLookup = cubemapUtil.integrateBRDF(renderer, normalDistribution); + } + textureOpts = textureOpts || {}; + + var width = textureOpts.width || 64; + var height = textureOpts.height || 64; + + var textureType = textureOpts.type || envMap.type; + + // Use same type with given envMap + var prefilteredCubeMap = new __WEBPACK_IMPORTED_MODULE_1__TextureCube__["a" /* default */]({ + width: width, + height: height, + type: textureType, + flipY: false, + mipmaps: [] + }); + + if (!prefilteredCubeMap.isPowerOfTwo()) { + console.warn('Width and height must be power of two to enable mipmap.'); + } + + var size = Math.min(width, height); + var mipmapNum = Math.log(size) / Math.log(2) + 1; + + var prefilterMaterial = new __WEBPACK_IMPORTED_MODULE_5__Material__["a" /* default */]({ + shader: new __WEBPACK_IMPORTED_MODULE_6__Shader__["a" /* default */]({ + vertex: __WEBPACK_IMPORTED_MODULE_6__Shader__["a" /* default */].source('clay.skybox.vertex'), + fragment: __WEBPACK_IMPORTED_MODULE_13__shader_prefilter_glsl_js__["a" /* default */] + }) + }); + prefilterMaterial.set('normalDistribution', normalDistribution); + + textureOpts.encodeRGBM && prefilterMaterial.define('fragment', 'RGBM_ENCODE'); + textureOpts.decodeRGBM && prefilterMaterial.define('fragment', 'RGBM_DECODE'); + + var dummyScene = new __WEBPACK_IMPORTED_MODULE_8__Scene__["a" /* default */](); + var skyEnv; + + if (envMap.textureType === 'texture2D') { + // Convert panorama to cubemap + var envCubemap = new __WEBPACK_IMPORTED_MODULE_1__TextureCube__["a" /* default */]({ + width: width, + height: height, + // FIXME FLOAT type will cause GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT error on iOS + type: textureType === __WEBPACK_IMPORTED_MODULE_2__Texture__["a" /* default */].FLOAT ? + __WEBPACK_IMPORTED_MODULE_2__Texture__["a" /* default */].HALF_FLOAT : textureType + }); + __WEBPACK_IMPORTED_MODULE_11__texture__["a" /* default */].panoramaToCubeMap(renderer, envMap, envCubemap, { + // PENDING encodeRGBM so it can be decoded as RGBM + encodeRGBM: textureOpts.decodeRGBM + }); + envMap = envCubemap; + } + skyEnv = new __WEBPACK_IMPORTED_MODULE_7__plugin_Skybox__["a" /* default */]({ + scene: dummyScene, + material: prefilterMaterial + }); + skyEnv.material.set('environmentMap', envMap); + + var envMapPass = new __WEBPACK_IMPORTED_MODULE_9__prePass_EnvironmentMap__["a" /* default */]({ + texture: prefilteredCubeMap + }); + + // Force to be UNSIGNED_BYTE + if (textureOpts.encodeRGBM) { + textureType = prefilteredCubeMap.type = __WEBPACK_IMPORTED_MODULE_2__Texture__["a" /* default */].UNSIGNED_BYTE; + } + + var renderTargetTmp = new __WEBPACK_IMPORTED_MODULE_0__Texture2D__["a" /* default */]({ + width: width, + height: height, + type: textureType + }); + var frameBuffer = new __WEBPACK_IMPORTED_MODULE_3__FrameBuffer__["a" /* default */]({ + depthBuffer: false + }); + var ArrayCtor = __WEBPACK_IMPORTED_MODULE_10__core_vendor__["a" /* default */][textureType === __WEBPACK_IMPORTED_MODULE_2__Texture__["a" /* default */].UNSIGNED_BYTE ? 'Uint8Array' : 'Float32Array']; + for (var i = 0; i < mipmapNum; i++) { + // console.time('prefilter'); + prefilteredCubeMap.mipmaps[i] = { + pixels: {} + }; + skyEnv.material.set('roughness', i / (mipmapNum - 1)); + + // Tweak fov + // http://the-witness.net/news/2012/02/seamless-cube-map-filtering/ + var n = renderTargetTmp.width; + var fov = 2 * Math.atan(n / (n - 0.5)) / Math.PI * 180; + + for (var j = 0; j < targets.length; j++) { + var pixels = new ArrayCtor(renderTargetTmp.width * renderTargetTmp.height * 4); + frameBuffer.attach(renderTargetTmp); + frameBuffer.bind(renderer); + + var camera = envMapPass.getCamera(targets[j]); + camera.fov = fov; + renderer.render(dummyScene, camera); + renderer.gl.readPixels( + 0, 0, renderTargetTmp.width, renderTargetTmp.height, + __WEBPACK_IMPORTED_MODULE_2__Texture__["a" /* default */].RGBA, textureType, pixels + ); + + // var canvas = document.createElement('canvas'); + // var ctx = canvas.getContext('2d'); + // canvas.width = renderTargetTmp.width; + // canvas.height = renderTargetTmp.height; + // var imageData = ctx.createImageData(renderTargetTmp.width, renderTargetTmp.height); + // for (var k = 0; k < pixels.length; k++) { + // imageData.data[k] = pixels[k]; + // } + // ctx.putImageData(imageData, 0, 0); + // document.body.appendChild(canvas); + + frameBuffer.unbind(renderer); + prefilteredCubeMap.mipmaps[i].pixels[targets[j]] = pixels; + } + + renderTargetTmp.width /= 2; + renderTargetTmp.height /= 2; + renderTargetTmp.dirty(); + // console.timeEnd('prefilter'); + } + + frameBuffer.dispose(renderer); + renderTargetTmp.dispose(renderer); + skyEnv.dispose(renderer); + // Remove gpu resource allucated in renderer + normalDistribution.dispose(renderer); + + // renderer.dispose(); + + return { + environmentMap: prefilteredCubeMap, + brdfLookup: brdfLookup, + normalDistribution: normalDistribution, + maxMipmapLevel: mipmapNum + }; +}; + +cubemapUtil.integrateBRDF = function (renderer, normalDistribution) { + normalDistribution = normalDistribution || cubemapUtil.generateNormalDistribution(); + var framebuffer = new __WEBPACK_IMPORTED_MODULE_3__FrameBuffer__["a" /* default */]({ + depthBuffer: false + }); + var pass = new __WEBPACK_IMPORTED_MODULE_4__compositor_Pass__["a" /* default */]({ + fragment: __WEBPACK_IMPORTED_MODULE_12__shader_integrateBRDF_glsl_js__["a" /* default */] + }); + + var texture = new __WEBPACK_IMPORTED_MODULE_0__Texture2D__["a" /* default */]({ + width: 512, + height: 256, + type: __WEBPACK_IMPORTED_MODULE_2__Texture__["a" /* default */].HALF_FLOAT, + wrapS: __WEBPACK_IMPORTED_MODULE_2__Texture__["a" /* default */].CLAMP_TO_EDGE, + wrapT: __WEBPACK_IMPORTED_MODULE_2__Texture__["a" /* default */].CLAMP_TO_EDGE, + minFilter: __WEBPACK_IMPORTED_MODULE_2__Texture__["a" /* default */].NEAREST, + magFilter: __WEBPACK_IMPORTED_MODULE_2__Texture__["a" /* default */].NEAREST, + useMipmap: false + }); + pass.setUniform('normalDistribution', normalDistribution); + pass.setUniform('viewportSize', [512, 256]); + pass.attachOutput(texture); + pass.render(renderer, framebuffer); + + // FIXME Only chrome and firefox can readPixels with float type. + // framebuffer.bind(renderer); + // var pixels = new Float32Array(512 * 256 * 4); + // renderer.gl.readPixels( + // 0, 0, texture.width, texture.height, + // Texture.RGBA, Texture.FLOAT, pixels + // ); + // texture.pixels = pixels; + // texture.flipY = false; + // texture.dirty(); + // framebuffer.unbind(renderer); + + framebuffer.dispose(renderer); + + return texture; +}; + +cubemapUtil.generateNormalDistribution = function (roughnessLevels, sampleSize) { + + // http://holger.dammertz.org/stuff/notes_HammersleyOnHemisphere.html + // GLSL not support bit operation, use lookup instead + // V -> i / N, U -> roughness + var roughnessLevels = roughnessLevels || 256; + var sampleSize = sampleSize || 1024; + + var normalDistribution = new __WEBPACK_IMPORTED_MODULE_0__Texture2D__["a" /* default */]({ + width: roughnessLevels, + height: sampleSize, + type: __WEBPACK_IMPORTED_MODULE_2__Texture__["a" /* default */].FLOAT, + minFilter: __WEBPACK_IMPORTED_MODULE_2__Texture__["a" /* default */].NEAREST, + magFilter: __WEBPACK_IMPORTED_MODULE_2__Texture__["a" /* default */].NEAREST, + wrapS: __WEBPACK_IMPORTED_MODULE_2__Texture__["a" /* default */].CLAMP_TO_EDGE, + wrapT: __WEBPACK_IMPORTED_MODULE_2__Texture__["a" /* default */].CLAMP_TO_EDGE, + useMipmap: false + }); + var pixels = new Float32Array(sampleSize * roughnessLevels * 4); + var tmp = []; + + // function sortFunc(a, b) { + // return Math.abs(b) - Math.abs(a); + // } + for (var j = 0; j < roughnessLevels; j++) { + var roughness = j / roughnessLevels; + var a = roughness * roughness; + + for (var i = 0; i < sampleSize; i++) { + // http://holger.dammertz.org/stuff/notes_HammersleyOnHemisphere.html + // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators + // http://stackoverflow.com/questions/1908492/unsigned-integer-in-javascript + // http://stackoverflow.com/questions/1822350/what-is-the-javascript-operator-and-how-do-you-use-it + var y = (i << 16 | i >>> 16) >>> 0; + y = ((y & 1431655765) << 1 | (y & 2863311530) >>> 1) >>> 0; + y = ((y & 858993459) << 2 | (y & 3435973836) >>> 2) >>> 0; + y = ((y & 252645135) << 4 | (y & 4042322160) >>> 4) >>> 0; + y = (((y & 16711935) << 8 | (y & 4278255360) >>> 8) >>> 0) / 4294967296; + + // CDF + var cosTheta = Math.sqrt((1 - y) / (1 + (a * a - 1.0) * y)); + tmp[i] = cosTheta; + } + + for (var i = 0; i < sampleSize; i++) { + var offset = (i * roughnessLevels + j) * 4; + var cosTheta = tmp[i]; + var sinTheta = Math.sqrt(1.0 - cosTheta * cosTheta); + var x = i / sampleSize; + var phi = 2.0 * Math.PI * x; + pixels[offset] = sinTheta * Math.cos(phi); + pixels[offset + 1] = cosTheta; + pixels[offset + 2] = sinTheta * Math.sin(phi); + pixels[offset + 3] = 1.0; + } + } + normalDistribution.pixels = pixels; + + return normalDistribution; +}; + +/* harmony default export */ __webpack_exports__["a"] = (cubemapUtil); + + +/***/ }), +/* 78 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__common__ = __webpack_require__(20); + + +/* Copyright (c) 2013, Brandon Jones, Colin MacKenzie IV. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + + + +/** + * @class 2x2 Matrix + * @name mat2 + */ + +var mat2 = {}; + +/** + * Creates a new identity mat2 + * + * @returns {mat2} a new 2x2 matrix + */ +mat2.create = function() { + var out = new __WEBPACK_IMPORTED_MODULE_0__common__["a" /* GLMAT_ARRAY_TYPE */](4); + out[0] = 1; + out[1] = 0; + out[2] = 0; + out[3] = 1; + return out; +}; + +/** + * Creates a new mat2 initialized with values from an existing matrix + * + * @param {mat2} a matrix to clone + * @returns {mat2} a new 2x2 matrix + */ +mat2.clone = function(a) { + var out = new __WEBPACK_IMPORTED_MODULE_0__common__["a" /* GLMAT_ARRAY_TYPE */](4); + out[0] = a[0]; + out[1] = a[1]; + out[2] = a[2]; + out[3] = a[3]; + return out; +}; + +/** + * Copy the values from one mat2 to another + * + * @param {mat2} out the receiving matrix + * @param {mat2} a the source matrix + * @returns {mat2} out + */ +mat2.copy = function(out, a) { + out[0] = a[0]; + out[1] = a[1]; + out[2] = a[2]; + out[3] = a[3]; + return out; +}; + +/** + * Set a mat2 to the identity matrix + * + * @param {mat2} out the receiving matrix + * @returns {mat2} out + */ +mat2.identity = function(out) { + out[0] = 1; + out[1] = 0; + out[2] = 0; + out[3] = 1; + return out; +}; + +/** + * Transpose the values of a mat2 + * + * @param {mat2} out the receiving matrix + * @param {mat2} a the source matrix + * @returns {mat2} out + */ +mat2.transpose = function(out, a) { + // If we are transposing ourselves we can skip a few steps but have to cache some values + if (out === a) { + var a1 = a[1]; + out[1] = a[2]; + out[2] = a1; + } else { + out[0] = a[0]; + out[1] = a[2]; + out[2] = a[1]; + out[3] = a[3]; + } + + return out; +}; + +/** + * Inverts a mat2 + * + * @param {mat2} out the receiving matrix + * @param {mat2} a the source matrix + * @returns {mat2} out + */ +mat2.invert = function(out, a) { + var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], + + // Calculate the determinant + det = a0 * a3 - a2 * a1; + + if (!det) { + return null; + } + det = 1.0 / det; + + out[0] = a3 * det; + out[1] = -a1 * det; + out[2] = -a2 * det; + out[3] = a0 * det; + + return out; +}; + +/** + * Calculates the adjugate of a mat2 + * + * @param {mat2} out the receiving matrix + * @param {mat2} a the source matrix + * @returns {mat2} out + */ +mat2.adjoint = function(out, a) { + // Caching this value is nessecary if out == a + var a0 = a[0]; + out[0] = a[3]; + out[1] = -a[1]; + out[2] = -a[2]; + out[3] = a0; + + return out; +}; + +/** + * Calculates the determinant of a mat2 + * + * @param {mat2} a the source matrix + * @returns {Number} determinant of a + */ +mat2.determinant = function (a) { + return a[0] * a[3] - a[2] * a[1]; +}; + +/** + * Multiplies two mat2's + * + * @param {mat2} out the receiving matrix + * @param {mat2} a the first operand + * @param {mat2} b the second operand + * @returns {mat2} out + */ +mat2.multiply = function (out, a, b) { + var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3]; + var b0 = b[0], b1 = b[1], b2 = b[2], b3 = b[3]; + out[0] = a0 * b0 + a2 * b1; + out[1] = a1 * b0 + a3 * b1; + out[2] = a0 * b2 + a2 * b3; + out[3] = a1 * b2 + a3 * b3; + return out; +}; + +/** + * Alias for {@link mat2.multiply} + * @function + */ +mat2.mul = mat2.multiply; + +/** + * Rotates a mat2 by the given angle + * + * @param {mat2} out the receiving matrix + * @param {mat2} a the matrix to rotate + * @param {Number} rad the angle to rotate the matrix by + * @returns {mat2} out + */ +mat2.rotate = function (out, a, rad) { + var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], + s = Math.sin(rad), + c = Math.cos(rad); + out[0] = a0 * c + a2 * s; + out[1] = a1 * c + a3 * s; + out[2] = a0 * -s + a2 * c; + out[3] = a1 * -s + a3 * c; + return out; +}; + +/** + * Scales the mat2 by the dimensions in the given vec2 + * + * @param {mat2} out the receiving matrix + * @param {mat2} a the matrix to rotate + * @param {vec2} v the vec2 to scale the matrix by + * @returns {mat2} out + **/ +mat2.scale = function(out, a, v) { + var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], + v0 = v[0], v1 = v[1]; + out[0] = a0 * v0; + out[1] = a1 * v0; + out[2] = a2 * v1; + out[3] = a3 * v1; + return out; +}; + +/** + * Returns Frobenius norm of a mat2 + * + * @param {mat2} a the matrix to calculate Frobenius norm of + * @returns {Number} Frobenius norm + */ +mat2.frob = function (a) { + return(Math.sqrt(Math.pow(a[0], 2) + Math.pow(a[1], 2) + Math.pow(a[2], 2) + Math.pow(a[3], 2))) +}; + +/** + * Returns L, D and U matrices (Lower triangular, Diagonal and Upper triangular) by factorizing the input matrix + * @param {mat2} L the lower triangular matrix + * @param {mat2} D the diagonal matrix + * @param {mat2} U the upper triangular matrix + * @param {mat2} a the input matrix to factorize + */ + +mat2.LDU = function (L, D, U, a) { + L[2] = a[2]/a[0]; + U[0] = a[0]; + U[1] = a[1]; + U[3] = a[3] - L[2] * U[1]; + return [L, D, U]; +}; + + +/* harmony default export */ __webpack_exports__["a"] = (mat2); + +/***/ }), +/* 79 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__common__ = __webpack_require__(20); + +/* Copyright (c) 2013, Brandon Jones, Colin MacKenzie IV. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + + + +/** + * @class 2x3 Matrix + * @name mat2d + * + * @description + * A mat2d contains six elements defined as: + *
+ * [a, c, tx,
+ *  b, d, ty]
+ * 
+ * This is a short form for the 3x3 matrix: + *
+ * [a, c, tx,
+ *  b, d, ty,
+ *  0, 0, 1]
+ * 
+ * The last row is ignored so the array is shorter and operations are faster. + */ + +var mat2d = {}; + +/** + * Creates a new identity mat2d + * + * @returns {mat2d} a new 2x3 matrix + */ +mat2d.create = function() { + var out = new __WEBPACK_IMPORTED_MODULE_0__common__["a" /* GLMAT_ARRAY_TYPE */](6); + out[0] = 1; + out[1] = 0; + out[2] = 0; + out[3] = 1; + out[4] = 0; + out[5] = 0; + return out; +}; + +/** + * Creates a new mat2d initialized with values from an existing matrix + * + * @param {mat2d} a matrix to clone + * @returns {mat2d} a new 2x3 matrix + */ +mat2d.clone = function(a) { + var out = new __WEBPACK_IMPORTED_MODULE_0__common__["a" /* GLMAT_ARRAY_TYPE */](6); + out[0] = a[0]; + out[1] = a[1]; + out[2] = a[2]; + out[3] = a[3]; + out[4] = a[4]; + out[5] = a[5]; + return out; +}; + +/** + * Copy the values from one mat2d to another + * + * @param {mat2d} out the receiving matrix + * @param {mat2d} a the source matrix + * @returns {mat2d} out + */ +mat2d.copy = function(out, a) { + out[0] = a[0]; + out[1] = a[1]; + out[2] = a[2]; + out[3] = a[3]; + out[4] = a[4]; + out[5] = a[5]; + return out; +}; + +/** + * Set a mat2d to the identity matrix + * + * @param {mat2d} out the receiving matrix + * @returns {mat2d} out + */ +mat2d.identity = function(out) { + out[0] = 1; + out[1] = 0; + out[2] = 0; + out[3] = 1; + out[4] = 0; + out[5] = 0; + return out; +}; + +/** + * Inverts a mat2d + * + * @param {mat2d} out the receiving matrix + * @param {mat2d} a the source matrix + * @returns {mat2d} out + */ +mat2d.invert = function(out, a) { + var aa = a[0], ab = a[1], ac = a[2], ad = a[3], + atx = a[4], aty = a[5]; + + var det = aa * ad - ab * ac; + if(!det){ + return null; + } + det = 1.0 / det; + + out[0] = ad * det; + out[1] = -ab * det; + out[2] = -ac * det; + out[3] = aa * det; + out[4] = (ac * aty - ad * atx) * det; + out[5] = (ab * atx - aa * aty) * det; + return out; +}; + +/** + * Calculates the determinant of a mat2d + * + * @param {mat2d} a the source matrix + * @returns {Number} determinant of a + */ +mat2d.determinant = function (a) { + return a[0] * a[3] - a[1] * a[2]; +}; + +/** + * Multiplies two mat2d's + * + * @param {mat2d} out the receiving matrix + * @param {mat2d} a the first operand + * @param {mat2d} b the second operand + * @returns {mat2d} out + */ +mat2d.multiply = function (out, a, b) { + var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], a4 = a[4], a5 = a[5], + b0 = b[0], b1 = b[1], b2 = b[2], b3 = b[3], b4 = b[4], b5 = b[5]; + out[0] = a0 * b0 + a2 * b1; + out[1] = a1 * b0 + a3 * b1; + out[2] = a0 * b2 + a2 * b3; + out[3] = a1 * b2 + a3 * b3; + out[4] = a0 * b4 + a2 * b5 + a4; + out[5] = a1 * b4 + a3 * b5 + a5; + return out; +}; + +/** + * Alias for {@link mat2d.multiply} + * @function + */ +mat2d.mul = mat2d.multiply; + + +/** + * Rotates a mat2d by the given angle + * + * @param {mat2d} out the receiving matrix + * @param {mat2d} a the matrix to rotate + * @param {Number} rad the angle to rotate the matrix by + * @returns {mat2d} out + */ +mat2d.rotate = function (out, a, rad) { + var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], a4 = a[4], a5 = a[5], + s = Math.sin(rad), + c = Math.cos(rad); + out[0] = a0 * c + a2 * s; + out[1] = a1 * c + a3 * s; + out[2] = a0 * -s + a2 * c; + out[3] = a1 * -s + a3 * c; + out[4] = a4; + out[5] = a5; + return out; +}; + +/** + * Scales the mat2d by the dimensions in the given vec2 + * + * @param {mat2d} out the receiving matrix + * @param {mat2d} a the matrix to translate + * @param {vec2} v the vec2 to scale the matrix by + * @returns {mat2d} out + **/ +mat2d.scale = function(out, a, v) { + var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], a4 = a[4], a5 = a[5], + v0 = v[0], v1 = v[1]; + out[0] = a0 * v0; + out[1] = a1 * v0; + out[2] = a2 * v1; + out[3] = a3 * v1; + out[4] = a4; + out[5] = a5; + return out; +}; + +/** + * Translates the mat2d by the dimensions in the given vec2 + * + * @param {mat2d} out the receiving matrix + * @param {mat2d} a the matrix to translate + * @param {vec2} v the vec2 to translate the matrix by + * @returns {mat2d} out + **/ +mat2d.translate = function(out, a, v) { + var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], a4 = a[4], a5 = a[5], + v0 = v[0], v1 = v[1]; + out[0] = a0; + out[1] = a1; + out[2] = a2; + out[3] = a3; + out[4] = a0 * v0 + a2 * v1 + a4; + out[5] = a1 * v0 + a3 * v1 + a5; + return out; +}; + +/** + * Returns Frobenius norm of a mat2d + * + * @param {mat2d} a the matrix to calculate Frobenius norm of + * @returns {Number} Frobenius norm + */ +mat2d.frob = function (a) { + return(Math.sqrt(Math.pow(a[0], 2) + Math.pow(a[1], 2) + Math.pow(a[2], 2) + Math.pow(a[3], 2) + Math.pow(a[4], 2) + Math.pow(a[5], 2) + 1)) +}; + + +/* harmony default export */ __webpack_exports__["a"] = (mat2d); + +/***/ }), +/* 80 */ +/***/ (function(module, exports) { + +var _default = typeof window !== 'undefined' && (window.requestAnimationFrame && window.requestAnimationFrame.bind(window) || // https://github.com/ecomfe/zrender/issues/189#issuecomment-224919809 +window.msRequestAnimationFrame && window.msRequestAnimationFrame.bind(window) || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame) || function (func) { + setTimeout(func, 16); +}; + +module.exports = _default; + +/***/ }), +/* 81 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_claygl_src_Texture2D__ = __webpack_require__(5); +/** + * Texture Atlas for the sprites. + * It uses zrender for 2d element management and rendering + * @module echarts-gl/util/ZRTextureAtlasSurface + */ + +// TODO Expand. + + + +function ZRTextureAtlasSurfaceNode(zr, offsetX, offsetY, width, height, gap, dpr) { + this._zr = zr; + + /** + * Current cursor x + * @type {number} + * @private + */ + this._x = 0; + + /** + * Current cursor y + * @type {number} + */ + this._y = 0; + + this._rowHeight = 0; + /** + * width without dpr. + * @type {number} + * @private + */ + this.width = width; + + /** + * height without dpr. + * @type {number} + * @private + */ + this.height = height; + + /** + * offsetX without dpr + * @type {number} + */ + this.offsetX = offsetX; + /** + * offsetY without dpr + * @type {number} + */ + this.offsetY = offsetY; + + this.dpr = dpr; + + this.gap = gap; +} + +ZRTextureAtlasSurfaceNode.prototype = { + + constructor: ZRTextureAtlasSurfaceNode, + + clear: function () { + this._x = 0; + this._y = 0; + this._rowHeight = 0; + }, + + /** + * Add shape to atlas + * @param {module:zrender/graphic/Displayable} shape + * @param {number} width + * @param {number} height + * @return {Array} + */ + add: function (el, width, height) { + // FIXME Text element not consider textAlign and textVerticalAlign. + + // TODO, inner text, shadow + var rect = el.getBoundingRect(); + + // FIXME aspect ratio + if (width == null) { + width = rect.width; + } + if (height == null) { + height = rect.height; + } + width *= this.dpr; + height *= this.dpr; + + this._fitElement(el, width, height); + + // var aspect = el.scale[1] / el.scale[0]; + // Adjust aspect ratio to make the text more clearly + // FIXME If height > width, width is useless ? + // width = height * aspect; + // el.position[0] *= aspect; + // el.scale[0] = el.scale[1]; + + var x = this._x; + var y = this._y; + + var canvasWidth = this.width * this.dpr; + var canvasHeight = this.height * this.dpr; + var gap = this.gap; + + if (x + width + gap > canvasWidth) { + // Change a new row + x = this._x = 0; + y += this._rowHeight + gap; + this._y = y; + // Reset row height + this._rowHeight = 0; + } + + this._x += width + gap; + + this._rowHeight = Math.max(this._rowHeight, height); + + if (y + height + gap > canvasHeight) { + // There is no space anymore + return null; + } + + // Shift the el + el.position[0] += this.offsetX * this.dpr + x; + el.position[1] += this.offsetY * this.dpr + y; + + this._zr.add(el); + + var coordsOffset = [ + this.offsetX / this.width, + this.offsetY / this.height + ]; + var coords = [ + [x / canvasWidth + coordsOffset[0], y / canvasHeight + coordsOffset[1]], + [(x + width) / canvasWidth + coordsOffset[0], (y + height) / canvasHeight + coordsOffset[1]] + ]; + + return coords; + }, + + /** + * Fit element size by correct its position and scaling + * @param {module:zrender/graphic/Displayable} el + * @param {number} spriteWidth + * @param {number} spriteHeight + */ + _fitElement: function (el, spriteWidth, spriteHeight) { + // TODO, inner text, shadow + var rect = el.getBoundingRect(); + + var scaleX = spriteWidth / rect.width; + var scaleY = spriteHeight / rect.height; + el.position = [-rect.x * scaleX, -rect.y * scaleY]; + el.scale = [scaleX, scaleY]; + el.update(); + } +} +/** + * constructor + * @alias module:echarts-gl/util/ZRTextureAtlasSurface + * @param {number} opt.width + * @param {number} opt.height + * @param {number} opt.devicePixelRatio + * @param {number} opt.gap Gap for safe. + * @param {Function} opt.onupdate + */ +function ZRTextureAtlasSurface (opt) { + + opt = opt || {}; + opt.width = opt.width || 512; + opt.height = opt.height || 512; + opt.devicePixelRatio = opt.devicePixelRatio || 1; + opt.gap = opt.gap == null ? 2 : opt.gap; + + var canvas = document.createElement('canvas'); + canvas.width = opt.width * opt.devicePixelRatio; + canvas.height = opt.height * opt.devicePixelRatio; + + this._canvas = canvas; + + this._texture = new __WEBPACK_IMPORTED_MODULE_1_claygl_src_Texture2D__["a" /* default */]({ + image: canvas, + flipY: false + }); + + var self = this; + /** + * zrender instance in the Chart + * @type {zrender~ZRender} + */ + this._zr = __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.zrender.init(canvas); + var oldRefreshImmediately = this._zr.refreshImmediately; + this._zr.refreshImmediately = function () { + oldRefreshImmediately.call(this); + self._texture.dirty(); + self.onupdate && self.onupdate(); + }; + + this._dpr = opt.devicePixelRatio; + + /** + * Texture coords map for each sprite image + * @type {Object} + */ + this._coords = {}; + + this.onupdate = opt.onupdate; + + this._gap = opt.gap; + + // Left sub atlas. + this._textureAtlasNodes = [new ZRTextureAtlasSurfaceNode( + this._zr, 0, 0, opt.width, opt.height, this._gap, this._dpr + )]; + + this._nodeWidth = opt.width; + this._nodeHeight = opt.height; + + this._currentNodeIdx = 0; +} + +ZRTextureAtlasSurface.prototype = { + + /** + * Clear the texture atlas + */ + clear: function () { + + for (var i = 0; i < this._textureAtlasNodes.length; i++) { + this._textureAtlasNodes[i].clear(); + } + + this._currentNodeIdx = 0; + + this._zr.clear(); + this._coords = {}; + }, + + /** + * @return {number} + */ + getWidth: function () { + return this._width; + }, + + /** + * @return {number} + */ + getHeight: function () { + return this._height; + }, + + /** + * @return {number} + */ + getTexture: function () { + return this._texture; + }, + + /** + * @return {number} + */ + getDevicePixelRatio: function () { + return this._dpr; + }, + + getZr: function () { + return this._zr; + }, + + _getCurrentNode: function () { + return this._textureAtlasNodes[this._currentNodeIdx]; + }, + + _expand: function () { + this._currentNodeIdx++; + if (this._textureAtlasNodes[this._currentNodeIdx]) { + // Use the node created previously. + return this._textureAtlasNodes[this._currentNodeIdx]; + } + + var maxSize = 4096 / this._dpr; + var textureAtlasNodes = this._textureAtlasNodes; + var nodeLen = textureAtlasNodes.length; + var offsetX = (nodeLen * this._nodeWidth) % maxSize; + var offsetY = Math.floor(nodeLen * this._nodeWidth / maxSize) * this._nodeHeight; + if (offsetY >= maxSize) { + // Failed if image is too large. + if (true) { + console.error('Too much labels. Some will be ignored.'); + } + return; + } + + var width = (offsetX + this._nodeWidth) * this._dpr; + var height = (offsetY + this._nodeHeight) * this._dpr; + try { + // Resize will error in node. + this._zr.resize({ + width: width, + height: height + }); + } + catch (e) { + this._canvas.width = width; + this._canvas.height = height; + } + + var newNode = new ZRTextureAtlasSurfaceNode( + this._zr, offsetX, offsetY, this._nodeWidth, this._nodeHeight, this._gap, this._dpr + ); + this._textureAtlasNodes.push(newNode); + + return newNode; + }, + + add: function (el, width, height) { + if (this._coords[el.id]) { + if (true) { + console.warn('Element already been add'); + } + return this._coords[el.id]; + } + var coords = this._getCurrentNode().add(el, width, height); + if (!coords) { + var newNode = this._expand(); + if (!newNode) { + // To maximum + return; + } + coords = newNode.add(el, width, height); + } + + this._coords[el.id] = coords; + + return coords; + }, + + /** + * Get coord scale after texture atlas is expanded. + * @return {Array.} + */ + getCoordsScale: function () { + var dpr = this._dpr; + return [this._nodeWidth / this._canvas.width * dpr, this._nodeHeight / this._canvas.height * dpr]; + }, + + /** + * Get texture coords of sprite image + * @param {string} id Image id + * @return {Array} + */ + getCoords: function (id) { + return this._coords[id]; + } +}; + +/* harmony default export */ __webpack_exports__["a"] = (ZRTextureAtlasSurface); + +/***/ }), +/* 82 */ +/***/ (function(module, exports, __webpack_require__) { + +var vec2 = __webpack_require__(83); + +var matrix = __webpack_require__(84); + +/** + * @module echarts/core/BoundingRect + */ +var v2ApplyTransform = vec2.applyTransform; +var mathMin = Math.min; +var mathMax = Math.max; +/** + * @alias module:echarts/core/BoundingRect + */ + +function BoundingRect(x, y, width, height) { + if (width < 0) { + x = x + width; + width = -width; + } + + if (height < 0) { + y = y + height; + height = -height; + } + /** + * @type {number} + */ + + + this.x = x; + /** + * @type {number} + */ + + this.y = y; + /** + * @type {number} + */ + + this.width = width; + /** + * @type {number} + */ + + this.height = height; +} + +BoundingRect.prototype = { + constructor: BoundingRect, + + /** + * @param {module:echarts/core/BoundingRect} other + */ + union: function (other) { + var x = mathMin(other.x, this.x); + var y = mathMin(other.y, this.y); + this.width = mathMax(other.x + other.width, this.x + this.width) - x; + this.height = mathMax(other.y + other.height, this.y + this.height) - y; + this.x = x; + this.y = y; + }, + + /** + * @param {Array.} m + * @methods + */ + applyTransform: function () { + var lt = []; + var rb = []; + var lb = []; + var rt = []; + return function (m) { + // In case usage like this + // el.getBoundingRect().applyTransform(el.transform) + // And element has no transform + if (!m) { + return; + } + + lt[0] = lb[0] = this.x; + lt[1] = rt[1] = this.y; + rb[0] = rt[0] = this.x + this.width; + rb[1] = lb[1] = this.y + this.height; + v2ApplyTransform(lt, lt, m); + v2ApplyTransform(rb, rb, m); + v2ApplyTransform(lb, lb, m); + v2ApplyTransform(rt, rt, m); + this.x = mathMin(lt[0], rb[0], lb[0], rt[0]); + this.y = mathMin(lt[1], rb[1], lb[1], rt[1]); + var maxX = mathMax(lt[0], rb[0], lb[0], rt[0]); + var maxY = mathMax(lt[1], rb[1], lb[1], rt[1]); + this.width = maxX - this.x; + this.height = maxY - this.y; + }; + }(), + + /** + * Calculate matrix of transforming from self to target rect + * @param {module:zrender/core/BoundingRect} b + * @return {Array.} + */ + calculateTransform: function (b) { + var a = this; + var sx = b.width / a.width; + var sy = b.height / a.height; + var m = matrix.create(); // 矩阵右乘 + + matrix.translate(m, m, [-a.x, -a.y]); + matrix.scale(m, m, [sx, sy]); + matrix.translate(m, m, [b.x, b.y]); + return m; + }, + + /** + * @param {(module:echarts/core/BoundingRect|Object)} b + * @return {boolean} + */ + intersect: function (b) { + if (!b) { + return false; + } + + if (!(b instanceof BoundingRect)) { + // Normalize negative width/height. + b = BoundingRect.create(b); + } + + var a = this; + var ax0 = a.x; + var ax1 = a.x + a.width; + var ay0 = a.y; + var ay1 = a.y + a.height; + var bx0 = b.x; + var bx1 = b.x + b.width; + var by0 = b.y; + var by1 = b.y + b.height; + return !(ax1 < bx0 || bx1 < ax0 || ay1 < by0 || by1 < ay0); + }, + contain: function (x, y) { + var rect = this; + return x >= rect.x && x <= rect.x + rect.width && y >= rect.y && y <= rect.y + rect.height; + }, + + /** + * @return {module:echarts/core/BoundingRect} + */ + clone: function () { + return new BoundingRect(this.x, this.y, this.width, this.height); + }, + + /** + * Copy from another rect + */ + copy: function (other) { + this.x = other.x; + this.y = other.y; + this.width = other.width; + this.height = other.height; + }, + plain: function () { + return { + x: this.x, + y: this.y, + width: this.width, + height: this.height + }; + } +}; +/** + * @param {Object|module:zrender/core/BoundingRect} rect + * @param {number} rect.x + * @param {number} rect.y + * @param {number} rect.width + * @param {number} rect.height + * @return {module:zrender/core/BoundingRect} + */ + +BoundingRect.create = function (rect) { + return new BoundingRect(rect.x, rect.y, rect.width, rect.height); +}; + +var _default = BoundingRect; +module.exports = _default; + +/***/ }), +/* 83 */ +/***/ (function(module, exports) { + +var ArrayCtor = typeof Float32Array === 'undefined' ? Array : Float32Array; +/** + * 创建一个向量 + * @param {number} [x=0] + * @param {number} [y=0] + * @return {Vector2} + */ + +function create(x, y) { + var out = new ArrayCtor(2); + + if (x == null) { + x = 0; + } + + if (y == null) { + y = 0; + } + + out[0] = x; + out[1] = y; + return out; +} +/** + * 复制向量数据 + * @param {Vector2} out + * @param {Vector2} v + * @return {Vector2} + */ + + +function copy(out, v) { + out[0] = v[0]; + out[1] = v[1]; + return out; +} +/** + * 克隆一个向量 + * @param {Vector2} v + * @return {Vector2} + */ + + +function clone(v) { + var out = new ArrayCtor(2); + out[0] = v[0]; + out[1] = v[1]; + return out; +} +/** + * 设置向量的两个项 + * @param {Vector2} out + * @param {number} a + * @param {number} b + * @return {Vector2} 结果 + */ + + +function set(out, a, b) { + out[0] = a; + out[1] = b; + return out; +} +/** + * 向量相加 + * @param {Vector2} out + * @param {Vector2} v1 + * @param {Vector2} v2 + */ + + +function add(out, v1, v2) { + out[0] = v1[0] + v2[0]; + out[1] = v1[1] + v2[1]; + return out; +} +/** + * 向量缩放后相加 + * @param {Vector2} out + * @param {Vector2} v1 + * @param {Vector2} v2 + * @param {number} a + */ + + +function scaleAndAdd(out, v1, v2, a) { + out[0] = v1[0] + v2[0] * a; + out[1] = v1[1] + v2[1] * a; + return out; +} +/** + * 向量相减 + * @param {Vector2} out + * @param {Vector2} v1 + * @param {Vector2} v2 + */ + + +function sub(out, v1, v2) { + out[0] = v1[0] - v2[0]; + out[1] = v1[1] - v2[1]; + return out; +} +/** + * 向量长度 + * @param {Vector2} v + * @return {number} + */ + + +function len(v) { + return Math.sqrt(lenSquare(v)); +} + +var length = len; // jshint ignore:line + +/** + * 向量长度平方 + * @param {Vector2} v + * @return {number} + */ + +function lenSquare(v) { + return v[0] * v[0] + v[1] * v[1]; +} + +var lengthSquare = lenSquare; +/** + * 向量乘法 + * @param {Vector2} out + * @param {Vector2} v1 + * @param {Vector2} v2 + */ + +function mul(out, v1, v2) { + out[0] = v1[0] * v2[0]; + out[1] = v1[1] * v2[1]; + return out; +} +/** + * 向量除法 + * @param {Vector2} out + * @param {Vector2} v1 + * @param {Vector2} v2 + */ + + +function div(out, v1, v2) { + out[0] = v1[0] / v2[0]; + out[1] = v1[1] / v2[1]; + return out; +} +/** + * 向量点乘 + * @param {Vector2} v1 + * @param {Vector2} v2 + * @return {number} + */ + + +function dot(v1, v2) { + return v1[0] * v2[0] + v1[1] * v2[1]; +} +/** + * 向量缩放 + * @param {Vector2} out + * @param {Vector2} v + * @param {number} s + */ + + +function scale(out, v, s) { + out[0] = v[0] * s; + out[1] = v[1] * s; + return out; +} +/** + * 向量归一化 + * @param {Vector2} out + * @param {Vector2} v + */ + + +function normalize(out, v) { + var d = len(v); + + if (d === 0) { + out[0] = 0; + out[1] = 0; + } else { + out[0] = v[0] / d; + out[1] = v[1] / d; + } + + return out; +} +/** + * 计算向量间距离 + * @param {Vector2} v1 + * @param {Vector2} v2 + * @return {number} + */ + + +function distance(v1, v2) { + return Math.sqrt((v1[0] - v2[0]) * (v1[0] - v2[0]) + (v1[1] - v2[1]) * (v1[1] - v2[1])); +} + +var dist = distance; +/** + * 向量距离平方 + * @param {Vector2} v1 + * @param {Vector2} v2 + * @return {number} + */ + +function distanceSquare(v1, v2) { + return (v1[0] - v2[0]) * (v1[0] - v2[0]) + (v1[1] - v2[1]) * (v1[1] - v2[1]); +} + +var distSquare = distanceSquare; +/** + * 求负向量 + * @param {Vector2} out + * @param {Vector2} v + */ + +function negate(out, v) { + out[0] = -v[0]; + out[1] = -v[1]; + return out; +} +/** + * 插值两个点 + * @param {Vector2} out + * @param {Vector2} v1 + * @param {Vector2} v2 + * @param {number} t + */ + + +function lerp(out, v1, v2, t) { + out[0] = v1[0] + t * (v2[0] - v1[0]); + out[1] = v1[1] + t * (v2[1] - v1[1]); + return out; +} +/** + * 矩阵左乘向量 + * @param {Vector2} out + * @param {Vector2} v + * @param {Vector2} m + */ + + +function applyTransform(out, v, m) { + var x = v[0]; + var y = v[1]; + out[0] = m[0] * x + m[2] * y + m[4]; + out[1] = m[1] * x + m[3] * y + m[5]; + return out; +} +/** + * 求两个向量最小值 + * @param {Vector2} out + * @param {Vector2} v1 + * @param {Vector2} v2 + */ + + +function min(out, v1, v2) { + out[0] = Math.min(v1[0], v2[0]); + out[1] = Math.min(v1[1], v2[1]); + return out; +} +/** + * 求两个向量最大值 + * @param {Vector2} out + * @param {Vector2} v1 + * @param {Vector2} v2 + */ + + +function max(out, v1, v2) { + out[0] = Math.max(v1[0], v2[0]); + out[1] = Math.max(v1[1], v2[1]); + return out; +} + +exports.create = create; +exports.copy = copy; +exports.clone = clone; +exports.set = set; +exports.add = add; +exports.scaleAndAdd = scaleAndAdd; +exports.sub = sub; +exports.len = len; +exports.length = length; +exports.lenSquare = lenSquare; +exports.lengthSquare = lengthSquare; +exports.mul = mul; +exports.div = div; +exports.dot = dot; +exports.scale = scale; +exports.normalize = normalize; +exports.distance = distance; +exports.dist = dist; +exports.distanceSquare = distanceSquare; +exports.distSquare = distSquare; +exports.negate = negate; +exports.lerp = lerp; +exports.applyTransform = applyTransform; +exports.min = min; +exports.max = max; + +/***/ }), +/* 84 */ +/***/ (function(module, exports) { + +/** + * 3x2矩阵操作类 + * @exports zrender/tool/matrix + */ +var ArrayCtor = typeof Float32Array === 'undefined' ? Array : Float32Array; +/** + * Create a identity matrix. + * @return {Float32Array|Array.} + */ + +function create() { + var out = new ArrayCtor(6); + identity(out); + return out; +} +/** + * 设置矩阵为单位矩阵 + * @param {Float32Array|Array.} out + */ + + +function identity(out) { + out[0] = 1; + out[1] = 0; + out[2] = 0; + out[3] = 1; + out[4] = 0; + out[5] = 0; + return out; +} +/** + * 复制矩阵 + * @param {Float32Array|Array.} out + * @param {Float32Array|Array.} m + */ + + +function copy(out, m) { + out[0] = m[0]; + out[1] = m[1]; + out[2] = m[2]; + out[3] = m[3]; + out[4] = m[4]; + out[5] = m[5]; + return out; +} +/** + * 矩阵相乘 + * @param {Float32Array|Array.} out + * @param {Float32Array|Array.} m1 + * @param {Float32Array|Array.} m2 + */ + + +function mul(out, m1, m2) { + // Consider matrix.mul(m, m2, m); + // where out is the same as m2. + // So use temp variable to escape error. + var out0 = m1[0] * m2[0] + m1[2] * m2[1]; + var out1 = m1[1] * m2[0] + m1[3] * m2[1]; + var out2 = m1[0] * m2[2] + m1[2] * m2[3]; + var out3 = m1[1] * m2[2] + m1[3] * m2[3]; + var out4 = m1[0] * m2[4] + m1[2] * m2[5] + m1[4]; + var out5 = m1[1] * m2[4] + m1[3] * m2[5] + m1[5]; + out[0] = out0; + out[1] = out1; + out[2] = out2; + out[3] = out3; + out[4] = out4; + out[5] = out5; + return out; +} +/** + * 平移变换 + * @param {Float32Array|Array.} out + * @param {Float32Array|Array.} a + * @param {Float32Array|Array.} v + */ + + +function translate(out, a, v) { + out[0] = a[0]; + out[1] = a[1]; + out[2] = a[2]; + out[3] = a[3]; + out[4] = a[4] + v[0]; + out[5] = a[5] + v[1]; + return out; +} +/** + * 旋转变换 + * @param {Float32Array|Array.} out + * @param {Float32Array|Array.} a + * @param {number} rad + */ + + +function rotate(out, a, rad) { + var aa = a[0]; + var ac = a[2]; + var atx = a[4]; + var ab = a[1]; + var ad = a[3]; + var aty = a[5]; + var st = Math.sin(rad); + var ct = Math.cos(rad); + out[0] = aa * ct + ab * st; + out[1] = -aa * st + ab * ct; + out[2] = ac * ct + ad * st; + out[3] = -ac * st + ct * ad; + out[4] = ct * atx + st * aty; + out[5] = ct * aty - st * atx; + return out; +} +/** + * 缩放变换 + * @param {Float32Array|Array.} out + * @param {Float32Array|Array.} a + * @param {Float32Array|Array.} v + */ + + +function scale(out, a, v) { + var vx = v[0]; + var vy = v[1]; + out[0] = a[0] * vx; + out[1] = a[1] * vy; + out[2] = a[2] * vx; + out[3] = a[3] * vy; + out[4] = a[4] * vx; + out[5] = a[5] * vy; + return out; +} +/** + * 求逆矩阵 + * @param {Float32Array|Array.} out + * @param {Float32Array|Array.} a + */ + + +function invert(out, a) { + var aa = a[0]; + var ac = a[2]; + var atx = a[4]; + var ab = a[1]; + var ad = a[3]; + var aty = a[5]; + var det = aa * ad - ab * ac; + + if (!det) { + return null; + } + + det = 1.0 / det; + out[0] = ad * det; + out[1] = -ab * det; + out[2] = -ac * det; + out[3] = aa * det; + out[4] = (ac * aty - ad * atx) * det; + out[5] = (ab * atx - aa * aty) * det; + return out; +} +/** + * Clone a new matrix. + * @param {Float32Array|Array.} a + */ + + +function clone(a) { + var b = create(); + copy(b, a); + return b; +} + +exports.create = create; +exports.identity = identity; +exports.copy = copy; +exports.mul = mul; +exports.translate = translate; +exports.rotate = rotate; +exports.scale = scale; +exports.invert = invert; +exports.clone = clone; + +/***/ }), +/* 85 */ +/***/ (function(module, exports, __webpack_require__) { + +var zrUtil = __webpack_require__(13); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ +var RADIAN_EPSILON = 1e-4; + +function _trim(str) { + return str.replace(/^\s+/, '').replace(/\s+$/, ''); +} +/** + * Linear mapping a value from domain to range + * @memberOf module:echarts/util/number + * @param {(number|Array.)} val + * @param {Array.} domain Domain extent domain[0] can be bigger than domain[1] + * @param {Array.} range Range extent range[0] can be bigger than range[1] + * @param {boolean} clamp + * @return {(number|Array.} + */ + + +function linearMap(val, domain, range, clamp) { + var subDomain = domain[1] - domain[0]; + var subRange = range[1] - range[0]; + + if (subDomain === 0) { + return subRange === 0 ? range[0] : (range[0] + range[1]) / 2; + } // Avoid accuracy problem in edge, such as + // 146.39 - 62.83 === 83.55999999999999. + // See echarts/test/ut/spec/util/number.js#linearMap#accuracyError + // It is a little verbose for efficiency considering this method + // is a hotspot. + + + if (clamp) { + if (subDomain > 0) { + if (val <= domain[0]) { + return range[0]; + } else if (val >= domain[1]) { + return range[1]; + } + } else { + if (val >= domain[0]) { + return range[0]; + } else if (val <= domain[1]) { + return range[1]; + } + } + } else { + if (val === domain[0]) { + return range[0]; + } + + if (val === domain[1]) { + return range[1]; + } + } + + return (val - domain[0]) / subDomain * subRange + range[0]; +} +/** + * Convert a percent string to absolute number. + * Returns NaN if percent is not a valid string or number + * @memberOf module:echarts/util/number + * @param {string|number} percent + * @param {number} all + * @return {number} + */ + + +function parsePercent(percent, all) { + switch (percent) { + case 'center': + case 'middle': + percent = '50%'; + break; + + case 'left': + case 'top': + percent = '0%'; + break; + + case 'right': + case 'bottom': + percent = '100%'; + break; + } + + if (typeof percent === 'string') { + if (_trim(percent).match(/%$/)) { + return parseFloat(percent) / 100 * all; + } + + return parseFloat(percent); + } + + return percent == null ? NaN : +percent; +} +/** + * (1) Fix rounding error of float numbers. + * (2) Support return string to avoid scientific notation like '3.5e-7'. + * + * @param {number} x + * @param {number} [precision] + * @param {boolean} [returnStr] + * @return {number|string} + */ + + +function round(x, precision, returnStr) { + if (precision == null) { + precision = 10; + } // Avoid range error + + + precision = Math.min(Math.max(0, precision), 20); + x = (+x).toFixed(precision); + return returnStr ? x : +x; +} + +function asc(arr) { + arr.sort(function (a, b) { + return a - b; + }); + return arr; +} +/** + * Get precision + * @param {number} val + */ + + +function getPrecision(val) { + val = +val; + + if (isNaN(val)) { + return 0; + } // It is much faster than methods converting number to string as follows + // var tmp = val.toString(); + // return tmp.length - 1 - tmp.indexOf('.'); + // especially when precision is low + + + var e = 1; + var count = 0; + + while (Math.round(val * e) / e !== val) { + e *= 10; + count++; + } + + return count; +} +/** + * @param {string|number} val + * @return {number} + */ + + +function getPrecisionSafe(val) { + var str = val.toString(); // Consider scientific notation: '3.4e-12' '3.4e+12' + + var eIndex = str.indexOf('e'); + + if (eIndex > 0) { + var precision = +str.slice(eIndex + 1); + return precision < 0 ? -precision : 0; + } else { + var dotIndex = str.indexOf('.'); + return dotIndex < 0 ? 0 : str.length - 1 - dotIndex; + } +} +/** + * Minimal dicernible data precisioin according to a single pixel. + * + * @param {Array.} dataExtent + * @param {Array.} pixelExtent + * @return {number} precision + */ + + +function getPixelPrecision(dataExtent, pixelExtent) { + var log = Math.log; + var LN10 = Math.LN10; + var dataQuantity = Math.floor(log(dataExtent[1] - dataExtent[0]) / LN10); + var sizeQuantity = Math.round(log(Math.abs(pixelExtent[1] - pixelExtent[0])) / LN10); // toFixed() digits argument must be between 0 and 20. + + var precision = Math.min(Math.max(-dataQuantity + sizeQuantity, 0), 20); + return !isFinite(precision) ? 20 : precision; +} +/** + * Get a data of given precision, assuring the sum of percentages + * in valueList is 1. + * The largest remainer method is used. + * https://en.wikipedia.org/wiki/Largest_remainder_method + * + * @param {Array.} valueList a list of all data + * @param {number} idx index of the data to be processed in valueList + * @param {number} precision integer number showing digits of precision + * @return {number} percent ranging from 0 to 100 + */ + + +function getPercentWithPrecision(valueList, idx, precision) { + if (!valueList[idx]) { + return 0; + } + + var sum = zrUtil.reduce(valueList, function (acc, val) { + return acc + (isNaN(val) ? 0 : val); + }, 0); + + if (sum === 0) { + return 0; + } + + var digits = Math.pow(10, precision); + var votesPerQuota = zrUtil.map(valueList, function (val) { + return (isNaN(val) ? 0 : val) / sum * digits * 100; + }); + var targetSeats = digits * 100; + var seats = zrUtil.map(votesPerQuota, function (votes) { + // Assign automatic seats. + return Math.floor(votes); + }); + var currentSum = zrUtil.reduce(seats, function (acc, val) { + return acc + val; + }, 0); + var remainder = zrUtil.map(votesPerQuota, function (votes, idx) { + return votes - seats[idx]; + }); // Has remainding votes. + + while (currentSum < targetSeats) { + // Find next largest remainder. + var max = Number.NEGATIVE_INFINITY; + var maxId = null; + + for (var i = 0, len = remainder.length; i < len; ++i) { + if (remainder[i] > max) { + max = remainder[i]; + maxId = i; + } + } // Add a vote to max remainder. + + + ++seats[maxId]; + remainder[maxId] = 0; + ++currentSum; + } + + return seats[idx] / digits; +} // Number.MAX_SAFE_INTEGER, ie do not support. + + +var MAX_SAFE_INTEGER = 9007199254740991; +/** + * To 0 - 2 * PI, considering negative radian. + * @param {number} radian + * @return {number} + */ + +function remRadian(radian) { + var pi2 = Math.PI * 2; + return (radian % pi2 + pi2) % pi2; +} +/** + * @param {type} radian + * @return {boolean} + */ + + +function isRadianAroundZero(val) { + return val > -RADIAN_EPSILON && val < RADIAN_EPSILON; +} + +var TIME_REG = /^(?:(\d{4})(?:[-\/](\d{1,2})(?:[-\/](\d{1,2})(?:[T ](\d{1,2})(?::(\d\d)(?::(\d\d)(?:[.,](\d+))?)?)?(Z|[\+\-]\d\d:?\d\d)?)?)?)?)?$/; // jshint ignore:line + +/** + * @param {string|Date|number} value These values can be accepted: + * + An instance of Date, represent a time in its own time zone. + * + Or string in a subset of ISO 8601, only including: + * + only year, month, date: '2012-03', '2012-03-01', '2012-03-01 05', '2012-03-01 05:06', + * + separated with T or space: '2012-03-01T12:22:33.123', '2012-03-01 12:22:33.123', + * + time zone: '2012-03-01T12:22:33Z', '2012-03-01T12:22:33+8000', '2012-03-01T12:22:33-05:00', + * all of which will be treated as local time if time zone is not specified + * (see ). + * + Or other string format, including (all of which will be treated as loacal time): + * '2012', '2012-3-1', '2012/3/1', '2012/03/01', + * '2009/6/12 2:00', '2009/6/12 2:05:08', '2009/6/12 2:05:08.123' + * + a timestamp, which represent a time in UTC. + * @return {Date} date + */ + +function parseDate(value) { + if (value instanceof Date) { + return value; + } else if (typeof value === 'string') { + // Different browsers parse date in different way, so we parse it manually. + // Some other issues: + // new Date('1970-01-01') is UTC, + // new Date('1970/01/01') and new Date('1970-1-01') is local. + // See issue #3623 + var match = TIME_REG.exec(value); + + if (!match) { + // return Invalid Date. + return new Date(NaN); + } // Use local time when no timezone offset specifed. + + + if (!match[8]) { + // match[n] can only be string or undefined. + // But take care of '12' + 1 => '121'. + return new Date(+match[1], +(match[2] || 1) - 1, +match[3] || 1, +match[4] || 0, +(match[5] || 0), +match[6] || 0, +match[7] || 0); + } // Timezoneoffset of Javascript Date has considered DST (Daylight Saving Time, + // https://tc39.github.io/ecma262/#sec-daylight-saving-time-adjustment). + // For example, system timezone is set as "Time Zone: America/Toronto", + // then these code will get different result: + // `new Date(1478411999999).getTimezoneOffset(); // get 240` + // `new Date(1478412000000).getTimezoneOffset(); // get 300` + // So we should not use `new Date`, but use `Date.UTC`. + else { + var hour = +match[4] || 0; + + if (match[8].toUpperCase() !== 'Z') { + hour -= match[8].slice(0, 3); + } + + return new Date(Date.UTC(+match[1], +(match[2] || 1) - 1, +match[3] || 1, hour, +(match[5] || 0), +match[6] || 0, +match[7] || 0)); + } + } else if (value == null) { + return new Date(NaN); + } + + return new Date(Math.round(value)); +} +/** + * Quantity of a number. e.g. 0.1, 1, 10, 100 + * + * @param {number} val + * @return {number} + */ + + +function quantity(val) { + return Math.pow(10, quantityExponent(val)); +} + +function quantityExponent(val) { + return Math.floor(Math.log(val) / Math.LN10); +} +/** + * find a “nice” number approximately equal to x. Round the number if round = true, + * take ceiling if round = false. The primary observation is that the “nicest” + * numbers in decimal are 1, 2, and 5, and all power-of-ten multiples of these numbers. + * + * See "Nice Numbers for Graph Labels" of Graphic Gems. + * + * @param {number} val Non-negative value. + * @param {boolean} round + * @return {number} + */ + + +function nice(val, round) { + var exponent = quantityExponent(val); + var exp10 = Math.pow(10, exponent); + var f = val / exp10; // 1 <= f < 10 + + var nf; + + if (round) { + if (f < 1.5) { + nf = 1; + } else if (f < 2.5) { + nf = 2; + } else if (f < 4) { + nf = 3; + } else if (f < 7) { + nf = 5; + } else { + nf = 10; + } + } else { + if (f < 1) { + nf = 1; + } else if (f < 2) { + nf = 2; + } else if (f < 3) { + nf = 3; + } else if (f < 5) { + nf = 5; + } else { + nf = 10; + } + } + + val = nf * exp10; // Fix 3 * 0.1 === 0.30000000000000004 issue (see IEEE 754). + // 20 is the uppper bound of toFixed. + + return exponent >= -20 ? +val.toFixed(exponent < 0 ? -exponent : 0) : val; +} +/** + * Order intervals asc, and split them when overlap. + * expect(numberUtil.reformIntervals([ + * {interval: [18, 62], close: [1, 1]}, + * {interval: [-Infinity, -70], close: [0, 0]}, + * {interval: [-70, -26], close: [1, 1]}, + * {interval: [-26, 18], close: [1, 1]}, + * {interval: [62, 150], close: [1, 1]}, + * {interval: [106, 150], close: [1, 1]}, + * {interval: [150, Infinity], close: [0, 0]} + * ])).toEqual([ + * {interval: [-Infinity, -70], close: [0, 0]}, + * {interval: [-70, -26], close: [1, 1]}, + * {interval: [-26, 18], close: [0, 1]}, + * {interval: [18, 62], close: [0, 1]}, + * {interval: [62, 150], close: [0, 1]}, + * {interval: [150, Infinity], close: [0, 0]} + * ]); + * @param {Array.} list, where `close` mean open or close + * of the interval, and Infinity can be used. + * @return {Array.} The origin list, which has been reformed. + */ + + +function reformIntervals(list) { + list.sort(function (a, b) { + return littleThan(a, b, 0) ? -1 : 1; + }); + var curr = -Infinity; + var currClose = 1; + + for (var i = 0; i < list.length;) { + var interval = list[i].interval; + var close = list[i].close; + + for (var lg = 0; lg < 2; lg++) { + if (interval[lg] <= curr) { + interval[lg] = curr; + close[lg] = !lg ? 1 - currClose : 1; + } + + curr = interval[lg]; + currClose = close[lg]; + } + + if (interval[0] === interval[1] && close[0] * close[1] !== 1) { + list.splice(i, 1); + } else { + i++; + } + } + + return list; + + function littleThan(a, b, lg) { + return a.interval[lg] < b.interval[lg] || a.interval[lg] === b.interval[lg] && (a.close[lg] - b.close[lg] === (!lg ? 1 : -1) || !lg && littleThan(a, b, 1)); + } +} +/** + * parseFloat NaNs numeric-cast false positives (null|true|false|"") + * ...but misinterprets leading-number strings, particularly hex literals ("0x...") + * subtraction forces infinities to NaN + * + * @param {*} v + * @return {boolean} + */ + + +function isNumeric(v) { + return v - parseFloat(v) >= 0; +} + +exports.linearMap = linearMap; +exports.parsePercent = parsePercent; +exports.round = round; +exports.asc = asc; +exports.getPrecision = getPrecision; +exports.getPrecisionSafe = getPrecisionSafe; +exports.getPixelPrecision = getPixelPrecision; +exports.getPercentWithPrecision = getPercentWithPrecision; +exports.MAX_SAFE_INTEGER = MAX_SAFE_INTEGER; +exports.remRadian = remRadian; +exports.isRadianAroundZero = isRadianAroundZero; +exports.parseDate = parseDate; +exports.quantity = quantity; +exports.nice = nice; +exports.reformIntervals = reformIntervals; +exports.isNumeric = isNumeric; + +/***/ }), +/* 86 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__Texture2D__ = __webpack_require__(5); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__core_glenum__ = __webpack_require__(11); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__core_util__ = __webpack_require__(23); + + + + +var TexturePool = function () { + + this._pool = {}; + + this._allocatedTextures = []; +}; + +TexturePool.prototype = { + + constructor: TexturePool, + + get: function (parameters) { + var key = generateKey(parameters); + if (!this._pool.hasOwnProperty(key)) { + this._pool[key] = []; + } + var list = this._pool[key]; + if (!list.length) { + var texture = new __WEBPACK_IMPORTED_MODULE_0__Texture2D__["a" /* default */](parameters); + this._allocatedTextures.push(texture); + return texture; + } + return list.pop(); + }, + + put: function (texture) { + var key = generateKey(texture); + if (!this._pool.hasOwnProperty(key)) { + this._pool[key] = []; + } + var list = this._pool[key]; + list.push(texture); + }, + + clear: function (renderer) { + for (var i = 0; i < this._allocatedTextures.length; i++) { + this._allocatedTextures[i].dispose(renderer); + } + this._pool = {}; + this._allocatedTextures = []; + } +}; + +var defaultParams = { + width: 512, + height: 512, + type: __WEBPACK_IMPORTED_MODULE_1__core_glenum__["a" /* default */].UNSIGNED_BYTE, + format: __WEBPACK_IMPORTED_MODULE_1__core_glenum__["a" /* default */].RGBA, + wrapS: __WEBPACK_IMPORTED_MODULE_1__core_glenum__["a" /* default */].CLAMP_TO_EDGE, + wrapT: __WEBPACK_IMPORTED_MODULE_1__core_glenum__["a" /* default */].CLAMP_TO_EDGE, + minFilter: __WEBPACK_IMPORTED_MODULE_1__core_glenum__["a" /* default */].LINEAR_MIPMAP_LINEAR, + magFilter: __WEBPACK_IMPORTED_MODULE_1__core_glenum__["a" /* default */].LINEAR, + useMipmap: true, + anisotropic: 1, + flipY: true, + unpackAlignment: 4, + premultiplyAlpha: false +}; + +var defaultParamPropList = Object.keys(defaultParams); + +function generateKey(parameters) { + __WEBPACK_IMPORTED_MODULE_2__core_util__["a" /* default */].defaultsWithPropList(parameters, defaultParams, defaultParamPropList); + fallBack(parameters); + + var key = ''; + for (var i = 0; i < defaultParamPropList.length; i++) { + var name = defaultParamPropList[i]; + var chunk = parameters[name].toString(); + key += chunk; + } + return key; +} + +function fallBack(target) { + + var IPOT = isPowerOfTwo(target.width, target.height); + + if (target.format === __WEBPACK_IMPORTED_MODULE_1__core_glenum__["a" /* default */].DEPTH_COMPONENT) { + target.useMipmap = false; + } + + if (!IPOT || !target.useMipmap) { + if (target.minFilter == __WEBPACK_IMPORTED_MODULE_1__core_glenum__["a" /* default */].NEAREST_MIPMAP_NEAREST || + target.minFilter == __WEBPACK_IMPORTED_MODULE_1__core_glenum__["a" /* default */].NEAREST_MIPMAP_LINEAR) { + target.minFilter = __WEBPACK_IMPORTED_MODULE_1__core_glenum__["a" /* default */].NEAREST; + } else if ( + target.minFilter == __WEBPACK_IMPORTED_MODULE_1__core_glenum__["a" /* default */].LINEAR_MIPMAP_LINEAR || + target.minFilter == __WEBPACK_IMPORTED_MODULE_1__core_glenum__["a" /* default */].LINEAR_MIPMAP_NEAREST + ) { + target.minFilter = __WEBPACK_IMPORTED_MODULE_1__core_glenum__["a" /* default */].LINEAR; + } + } + if (!IPOT) { + target.wrapS = __WEBPACK_IMPORTED_MODULE_1__core_glenum__["a" /* default */].CLAMP_TO_EDGE; + target.wrapT = __WEBPACK_IMPORTED_MODULE_1__core_glenum__["a" /* default */].CLAMP_TO_EDGE; + } +} + +function isPowerOfTwo(width, height) { + return (width & (width-1)) === 0 && + (height & (height-1)) === 0; +} + +/* harmony default export */ __webpack_exports__["a"] = (TexturePool); + + +/***/ }), +/* 87 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony default export */ __webpack_exports__["a"] = ("@export clay.compositor.kernel.gaussian_9\nfloat gaussianKernel[9];\ngaussianKernel[0] = 0.07;\ngaussianKernel[1] = 0.09;\ngaussianKernel[2] = 0.12;\ngaussianKernel[3] = 0.14;\ngaussianKernel[4] = 0.16;\ngaussianKernel[5] = 0.14;\ngaussianKernel[6] = 0.12;\ngaussianKernel[7] = 0.09;\ngaussianKernel[8] = 0.07;\n@end\n@export clay.compositor.kernel.gaussian_13\nfloat gaussianKernel[13];\ngaussianKernel[0] = 0.02;\ngaussianKernel[1] = 0.03;\ngaussianKernel[2] = 0.06;\ngaussianKernel[3] = 0.08;\ngaussianKernel[4] = 0.11;\ngaussianKernel[5] = 0.13;\ngaussianKernel[6] = 0.14;\ngaussianKernel[7] = 0.13;\ngaussianKernel[8] = 0.11;\ngaussianKernel[9] = 0.08;\ngaussianKernel[10] = 0.06;\ngaussianKernel[11] = 0.03;\ngaussianKernel[12] = 0.02;\n@end\n@export clay.compositor.gaussian_blur\n#define SHADER_NAME gaussian_blur\nuniform sampler2D texture;varying vec2 v_Texcoord;\nuniform float blurSize : 2.0;\nuniform vec2 textureSize : [512.0, 512.0];\nuniform float blurDir : 0.0;\n@import clay.util.rgbm\n@import clay.util.clamp_sample\nvoid main (void)\n{\n @import clay.compositor.kernel.gaussian_9\n vec2 off = blurSize / textureSize;\n off *= vec2(1.0 - blurDir, blurDir);\n vec4 sum = vec4(0.0);\n float weightAll = 0.0;\n for (int i = 0; i < 9; i++) {\n float w = gaussianKernel[i];\n vec4 texel = decodeHDR(clampSample(texture, v_Texcoord + float(i - 4) * off));\n sum += texel * w;\n weightAll += w;\n }\n gl_FragColor = encodeHDR(sum / max(weightAll, 0.01));\n}\n@end\n"); + + +/***/ }), +/* 88 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony default export */ __webpack_exports__["a"] = ("\n@export clay.compositor.lut\nvarying vec2 v_Texcoord;\nuniform sampler2D texture;\nuniform sampler2D lookup;\nvoid main()\n{\n vec4 tex = texture2D(texture, v_Texcoord);\n float blueColor = tex.b * 63.0;\n vec2 quad1;\n quad1.y = floor(floor(blueColor) / 8.0);\n quad1.x = floor(blueColor) - (quad1.y * 8.0);\n vec2 quad2;\n quad2.y = floor(ceil(blueColor) / 8.0);\n quad2.x = ceil(blueColor) - (quad2.y * 8.0);\n vec2 texPos1;\n texPos1.x = (quad1.x * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * tex.r);\n texPos1.y = (quad1.y * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * tex.g);\n vec2 texPos2;\n texPos2.x = (quad2.x * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * tex.r);\n texPos2.y = (quad2.y * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * tex.g);\n vec4 newColor1 = texture2D(lookup, texPos1);\n vec4 newColor2 = texture2D(lookup, texPos2);\n vec4 newColor = mix(newColor1, newColor2, fract(blueColor));\n gl_FragColor = vec4(newColor.rgb, tex.w);\n}\n@end"); + + +/***/ }), +/* 89 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony default export */ __webpack_exports__["a"] = ("@export clay.compositor.output\n#define OUTPUT_ALPHA\nvarying vec2 v_Texcoord;\nuniform sampler2D texture;\n@import clay.util.rgbm\nvoid main()\n{\n vec4 tex = decodeHDR(texture2D(texture, v_Texcoord));\n gl_FragColor.rgb = tex.rgb;\n#ifdef OUTPUT_ALPHA\n gl_FragColor.a = tex.a;\n#else\n gl_FragColor.a = 1.0;\n#endif\n gl_FragColor = encodeHDR(gl_FragColor);\n#ifdef PREMULTIPLY_ALPHA\n gl_FragColor.rgb *= gl_FragColor.a;\n#endif\n}\n@end"); + + +/***/ }), +/* 90 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony default export */ __webpack_exports__["a"] = ("@export clay.compositor.bright\nuniform sampler2D texture;\nuniform float threshold : 1;\nuniform float scale : 1.0;\nuniform vec2 textureSize: [512, 512];\nvarying vec2 v_Texcoord;\nconst vec3 lumWeight = vec3(0.2125, 0.7154, 0.0721);\n@import clay.util.rgbm\nvec4 median(vec4 a, vec4 b, vec4 c)\n{\n return a + b + c - min(min(a, b), c) - max(max(a, b), c);\n}\nvoid main()\n{\n vec4 texel = decodeHDR(texture2D(texture, v_Texcoord));\n#ifdef ANTI_FLICKER\n vec3 d = 1.0 / textureSize.xyx * vec3(1.0, 1.0, 0.0);\n vec4 s1 = decodeHDR(texture2D(texture, v_Texcoord - d.xz));\n vec4 s2 = decodeHDR(texture2D(texture, v_Texcoord + d.xz));\n vec4 s3 = decodeHDR(texture2D(texture, v_Texcoord - d.zy));\n vec4 s4 = decodeHDR(texture2D(texture, v_Texcoord + d.zy));\n texel = median(median(texel, s1, s2), s3, s4);\n#endif\n float lum = dot(texel.rgb , lumWeight);\n vec4 color;\n if (lum > threshold && texel.a > 0.0)\n {\n color = vec4(texel.rgb * scale, texel.a * scale);\n }\n else\n {\n color = vec4(0.0);\n }\n gl_FragColor = encodeHDR(color);\n}\n@end\n"); + + +/***/ }), +/* 91 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony default export */ __webpack_exports__["a"] = ("@export clay.compositor.downsample\nuniform sampler2D texture;\nuniform vec2 textureSize : [512, 512];\nvarying vec2 v_Texcoord;\n@import clay.util.rgbm\nfloat brightness(vec3 c)\n{\n return max(max(c.r, c.g), c.b);\n}\n@import clay.util.clamp_sample\nvoid main()\n{\n vec4 d = vec4(-1.0, -1.0, 1.0, 1.0) / textureSize.xyxy;\n#ifdef ANTI_FLICKER\n vec3 s1 = decodeHDR(clampSample(texture, v_Texcoord + d.xy)).rgb;\n vec3 s2 = decodeHDR(clampSample(texture, v_Texcoord + d.zy)).rgb;\n vec3 s3 = decodeHDR(clampSample(texture, v_Texcoord + d.xw)).rgb;\n vec3 s4 = decodeHDR(clampSample(texture, v_Texcoord + d.zw)).rgb;\n float s1w = 1.0 / (brightness(s1) + 1.0);\n float s2w = 1.0 / (brightness(s2) + 1.0);\n float s3w = 1.0 / (brightness(s3) + 1.0);\n float s4w = 1.0 / (brightness(s4) + 1.0);\n float oneDivideSum = 1.0 / (s1w + s2w + s3w + s4w);\n vec4 color = vec4(\n (s1 * s1w + s2 * s2w + s3 * s3w + s4 * s4w) * oneDivideSum,\n 1.0\n );\n#else\n vec4 color = decodeHDR(clampSample(texture, v_Texcoord + d.xy));\n color += decodeHDR(clampSample(texture, v_Texcoord + d.zy));\n color += decodeHDR(clampSample(texture, v_Texcoord + d.xw));\n color += decodeHDR(clampSample(texture, v_Texcoord + d.zw));\n color *= 0.25;\n#endif\n gl_FragColor = encodeHDR(color);\n}\n@end"); + + +/***/ }), +/* 92 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony default export */ __webpack_exports__["a"] = ("\n@export clay.compositor.upsample\n#define HIGH_QUALITY\nuniform sampler2D texture;\nuniform vec2 textureSize : [512, 512];\nuniform float sampleScale: 0.5;\nvarying vec2 v_Texcoord;\n@import clay.util.rgbm\n@import clay.util.clamp_sample\nvoid main()\n{\n#ifdef HIGH_QUALITY\n vec4 d = vec4(1.0, 1.0, -1.0, 0.0) / textureSize.xyxy * sampleScale;\n vec4 s;\n s = decodeHDR(clampSample(texture, v_Texcoord - d.xy));\n s += decodeHDR(clampSample(texture, v_Texcoord - d.wy)) * 2.0;\n s += decodeHDR(clampSample(texture, v_Texcoord - d.zy));\n s += decodeHDR(clampSample(texture, v_Texcoord + d.zw)) * 2.0;\n s += decodeHDR(clampSample(texture, v_Texcoord )) * 4.0;\n s += decodeHDR(clampSample(texture, v_Texcoord + d.xw)) * 2.0;\n s += decodeHDR(clampSample(texture, v_Texcoord + d.zy));\n s += decodeHDR(clampSample(texture, v_Texcoord + d.wy)) * 2.0;\n s += decodeHDR(clampSample(texture, v_Texcoord + d.xy));\n gl_FragColor = encodeHDR(s / 16.0);\n#else\n vec4 d = vec4(-1.0, -1.0, +1.0, +1.0) / textureSize.xyxy;\n vec4 s;\n s = decodeHDR(clampSample(texture, v_Texcoord + d.xy));\n s += decodeHDR(clampSample(texture, v_Texcoord + d.zy));\n s += decodeHDR(clampSample(texture, v_Texcoord + d.xw));\n s += decodeHDR(clampSample(texture, v_Texcoord + d.zw));\n gl_FragColor = encodeHDR(s / 4.0);\n#endif\n}\n@end"); + + +/***/ }), +/* 93 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony default export */ __webpack_exports__["a"] = ("@export clay.compositor.hdr.composite\n#define TONEMAPPING\nuniform sampler2D texture;\n#ifdef BLOOM_ENABLED\nuniform sampler2D bloom;\n#endif\n#ifdef LENSFLARE_ENABLED\nuniform sampler2D lensflare;\nuniform sampler2D lensdirt;\n#endif\n#ifdef LUM_ENABLED\nuniform sampler2D lum;\n#endif\n#ifdef LUT_ENABLED\nuniform sampler2D lut;\n#endif\n#ifdef COLOR_CORRECTION\nuniform float brightness : 0.0;\nuniform float contrast : 1.0;\nuniform float saturation : 1.0;\n#endif\n#ifdef VIGNETTE\nuniform float vignetteDarkness: 1.0;\nuniform float vignetteOffset: 1.0;\n#endif\nuniform float exposure : 1.0;\nuniform float bloomIntensity : 0.25;\nuniform float lensflareIntensity : 1;\nvarying vec2 v_Texcoord;\n@import clay.util.srgb\nvec3 ACESToneMapping(vec3 color)\n{\n const float A = 2.51;\n const float B = 0.03;\n const float C = 2.43;\n const float D = 0.59;\n const float E = 0.14;\n return (color * (A * color + B)) / (color * (C * color + D) + E);\n}\nfloat eyeAdaption(float fLum)\n{\n return mix(0.2, fLum, 0.5);\n}\n#ifdef LUT_ENABLED\nvec3 lutTransform(vec3 color) {\n float blueColor = color.b * 63.0;\n vec2 quad1;\n quad1.y = floor(floor(blueColor) / 8.0);\n quad1.x = floor(blueColor) - (quad1.y * 8.0);\n vec2 quad2;\n quad2.y = floor(ceil(blueColor) / 8.0);\n quad2.x = ceil(blueColor) - (quad2.y * 8.0);\n vec2 texPos1;\n texPos1.x = (quad1.x * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * color.r);\n texPos1.y = (quad1.y * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * color.g);\n vec2 texPos2;\n texPos2.x = (quad2.x * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * color.r);\n texPos2.y = (quad2.y * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * color.g);\n vec4 newColor1 = texture2D(lut, texPos1);\n vec4 newColor2 = texture2D(lut, texPos2);\n vec4 newColor = mix(newColor1, newColor2, fract(blueColor));\n return newColor.rgb;\n}\n#endif\n@import clay.util.rgbm\nvoid main()\n{\n vec4 texel = vec4(0.0);\n vec4 originalTexel = vec4(0.0);\n#ifdef TEXTURE_ENABLED\n texel = decodeHDR(texture2D(texture, v_Texcoord));\n originalTexel = texel;\n#endif\n#ifdef BLOOM_ENABLED\n vec4 bloomTexel = decodeHDR(texture2D(bloom, v_Texcoord));\n texel.rgb += bloomTexel.rgb * bloomIntensity;\n texel.a += bloomTexel.a * bloomIntensity;\n#endif\n#ifdef LENSFLARE_ENABLED\n texel += decodeHDR(texture2D(lensflare, v_Texcoord)) * texture2D(lensdirt, v_Texcoord) * lensflareIntensity;\n#endif\n texel.a = min(texel.a, 1.0);\n#ifdef LUM_ENABLED\n float fLum = texture2D(lum, vec2(0.5, 0.5)).r;\n float adaptedLumDest = 3.0 / (max(0.1, 1.0 + 10.0*eyeAdaption(fLum)));\n float exposureBias = adaptedLumDest * exposure;\n#else\n float exposureBias = exposure;\n#endif\n#ifdef TONEMAPPING\n texel.rgb *= exposureBias;\n texel.rgb = ACESToneMapping(texel.rgb);\n#endif\n texel = linearTosRGB(texel);\n#ifdef LUT_ENABLED\n texel.rgb = lutTransform(clamp(texel.rgb,vec3(0.0),vec3(1.0)));\n#endif\n#ifdef COLOR_CORRECTION\n texel.rgb = clamp(texel.rgb + vec3(brightness), 0.0, 1.0);\n texel.rgb = clamp((texel.rgb - vec3(0.5))*contrast+vec3(0.5), 0.0, 1.0);\n float lum = dot(texel.rgb, vec3(0.2125, 0.7154, 0.0721));\n texel.rgb = mix(vec3(lum), texel.rgb, saturation);\n#endif\n#ifdef VIGNETTE\n vec2 uv = (v_Texcoord - vec2(0.5)) * vec2(vignetteOffset);\n texel.rgb = mix(texel.rgb, vec3(1.0 - vignetteDarkness), dot(uv, uv));\n#endif\n gl_FragColor = encodeHDR(texel);\n#ifdef DEBUG\n #if DEBUG == 1\n gl_FragColor = encodeHDR(decodeHDR(texture2D(texture, v_Texcoord)));\n #elif DEBUG == 2\n gl_FragColor = encodeHDR(decodeHDR(texture2D(bloom, v_Texcoord)) * bloomIntensity);\n #elif DEBUG == 3\n gl_FragColor = encodeHDR(decodeHDR(texture2D(lensflare, v_Texcoord) * lensflareIntensity));\n #endif\n#endif\n if (originalTexel.a <= 0.01 && gl_FragColor.a > 1e-5) {\n gl_FragColor.a = dot(gl_FragColor.rgb, vec3(0.2125, 0.7154, 0.0721));\n }\n#ifdef PREMULTIPLY_ALPHA\n gl_FragColor.rgb *= gl_FragColor.a;\n#endif\n}\n@end"); + + +/***/ }), +/* 94 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony default export */ __webpack_exports__["a"] = ("@export clay.compositor.blend\n#define SHADER_NAME blend\n#ifdef TEXTURE1_ENABLED\nuniform sampler2D texture1;\nuniform float weight1 : 1.0;\n#endif\n#ifdef TEXTURE2_ENABLED\nuniform sampler2D texture2;\nuniform float weight2 : 1.0;\n#endif\n#ifdef TEXTURE3_ENABLED\nuniform sampler2D texture3;\nuniform float weight3 : 1.0;\n#endif\n#ifdef TEXTURE4_ENABLED\nuniform sampler2D texture4;\nuniform float weight4 : 1.0;\n#endif\n#ifdef TEXTURE5_ENABLED\nuniform sampler2D texture5;\nuniform float weight5 : 1.0;\n#endif\n#ifdef TEXTURE6_ENABLED\nuniform sampler2D texture6;\nuniform float weight6 : 1.0;\n#endif\nvarying vec2 v_Texcoord;\n@import clay.util.rgbm\nvoid main()\n{\n vec4 tex = vec4(0.0);\n#ifdef TEXTURE1_ENABLED\n tex += decodeHDR(texture2D(texture1, v_Texcoord)) * weight1;\n#endif\n#ifdef TEXTURE2_ENABLED\n tex += decodeHDR(texture2D(texture2, v_Texcoord)) * weight2;\n#endif\n#ifdef TEXTURE3_ENABLED\n tex += decodeHDR(texture2D(texture3, v_Texcoord)) * weight3;\n#endif\n#ifdef TEXTURE4_ENABLED\n tex += decodeHDR(texture2D(texture4, v_Texcoord)) * weight4;\n#endif\n#ifdef TEXTURE5_ENABLED\n tex += decodeHDR(texture2D(texture5, v_Texcoord)) * weight5;\n#endif\n#ifdef TEXTURE6_ENABLED\n tex += decodeHDR(texture2D(texture6, v_Texcoord)) * weight6;\n#endif\n gl_FragColor = encodeHDR(tex);\n}\n@end"); + + +/***/ }), +/* 95 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony default export */ __webpack_exports__["a"] = ("@export clay.compositor.fxaa\nuniform sampler2D texture;\nuniform vec4 viewport : VIEWPORT;\nvarying vec2 v_Texcoord;\n#define FXAA_REDUCE_MIN (1.0/128.0)\n#define FXAA_REDUCE_MUL (1.0/8.0)\n#define FXAA_SPAN_MAX 8.0\n@import clay.util.rgbm\nvoid main()\n{\n vec2 resolution = 1.0 / viewport.zw;\n vec3 rgbNW = decodeHDR( texture2D( texture, ( gl_FragCoord.xy + vec2( -1.0, -1.0 ) ) * resolution ) ).xyz;\n vec3 rgbNE = decodeHDR( texture2D( texture, ( gl_FragCoord.xy + vec2( 1.0, -1.0 ) ) * resolution ) ).xyz;\n vec3 rgbSW = decodeHDR( texture2D( texture, ( gl_FragCoord.xy + vec2( -1.0, 1.0 ) ) * resolution ) ).xyz;\n vec3 rgbSE = decodeHDR( texture2D( texture, ( gl_FragCoord.xy + vec2( 1.0, 1.0 ) ) * resolution ) ).xyz;\n vec4 rgbaM = decodeHDR( texture2D( texture, gl_FragCoord.xy * resolution ) );\n vec3 rgbM = rgbaM.xyz;\n float opacity = rgbaM.w;\n vec3 luma = vec3( 0.299, 0.587, 0.114 );\n float lumaNW = dot( rgbNW, luma );\n float lumaNE = dot( rgbNE, luma );\n float lumaSW = dot( rgbSW, luma );\n float lumaSE = dot( rgbSE, luma );\n float lumaM = dot( rgbM, luma );\n float lumaMin = min( lumaM, min( min( lumaNW, lumaNE ), min( lumaSW, lumaSE ) ) );\n float lumaMax = max( lumaM, max( max( lumaNW, lumaNE) , max( lumaSW, lumaSE ) ) );\n vec2 dir;\n dir.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE));\n dir.y = ((lumaNW + lumaSW) - (lumaNE + lumaSE));\n float dirReduce = max( ( lumaNW + lumaNE + lumaSW + lumaSE ) * ( 0.25 * FXAA_REDUCE_MUL ), FXAA_REDUCE_MIN );\n float rcpDirMin = 1.0 / ( min( abs( dir.x ), abs( dir.y ) ) + dirReduce );\n dir = min( vec2( FXAA_SPAN_MAX, FXAA_SPAN_MAX),\n max( vec2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX),\n dir * rcpDirMin)) * resolution;\n vec3 rgbA = decodeHDR( texture2D( texture, gl_FragCoord.xy * resolution + dir * ( 1.0 / 3.0 - 0.5 ) ) ).xyz;\n rgbA += decodeHDR( texture2D( texture, gl_FragCoord.xy * resolution + dir * ( 2.0 / 3.0 - 0.5 ) ) ).xyz;\n rgbA *= 0.5;\n vec3 rgbB = decodeHDR( texture2D( texture, gl_FragCoord.xy * resolution + dir * -0.5 ) ).xyz;\n rgbB += decodeHDR( texture2D( texture, gl_FragCoord.xy * resolution + dir * 0.5 ) ).xyz;\n rgbB *= 0.25;\n rgbB += rgbA * 0.5;\n float lumaB = dot( rgbB, luma );\n if ( ( lumaB < lumaMin ) || ( lumaB > lumaMax ) )\n {\n gl_FragColor = vec4( rgbA, opacity );\n }\n else {\n gl_FragColor = vec4( rgbB, opacity );\n }\n}\n@end"); + + +/***/ }), +/* 96 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__); + + +/* harmony default export */ __webpack_exports__["a"] = ({ + + getFilledRegions: function (regions, mapData) { + var regionsArr = (regions || []).slice(); + + var geoJson; + if (typeof mapData === 'string') { + mapData = __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.getMap(mapData); + geoJson = mapData && mapData.geoJson; + } + else { + if (mapData && mapData.features) { + geoJson = mapData; + } + } + if (!geoJson) { + if (true) { + console.error('Map ' + mapData + ' not exists. You can download map file on http://echarts.baidu.com/download-map.html'); + if (!geoJson.features) { + console.error('Invalid GeoJSON for map3D'); + } + } + return []; + } + + var dataNameMap = {}; + var features = geoJson.features; + for (var i = 0; i < regionsArr.length; i++) { + dataNameMap[regionsArr[i].name] = regionsArr[i]; + } + + for (var i = 0; i < features.length; i++) { + var name = features[i].properties.name; + if (!dataNameMap[name]) { + regionsArr.push({ + name: name + }); + } + } + + return regionsArr; + }, + + defaultOption: { + show: true, + + zlevel: -10, + + // geoJson used by geo3D + map: '', + + // Layout used for viewport + left: 0, + top: 0, + width: '100%', + height: '100%', + + boxWidth: 100, + boxHeight: 10, + boxDepth: 'auto', + + regionHeight: 3, + + environment: 'auto', + + groundPlane: { + show: false, + color: '#aaa' + }, + + shading: 'lambert', + + light: { + main: { + alpha: 40, + beta: 30 + } + }, + + viewControl: { + alpha: 40, + beta: 0, + distance: 100, + orthographicSize: 60, + + minAlpha: 5, + minBeta: -80, + maxBeta: 80 + }, + + label: { + show: false, + // Distance in 3d space. + distance: 2, + + textStyle: { + fontSize: 20, + color: '#000', + backgroundColor: 'rgba(255,255,255,0.7)', + padding: 3, + borderRadius: 4 + } + }, + + // TODO + // altitude: { + // min: 'auto', + // max: 'auto', + + // height: [] + // }, + + + // labelLine + + // light + // postEffect + // temporalSuperSampling + + itemStyle: { + color: '#fff', + borderWidth: 0, + borderColor: '#333' + }, + + emphasis: { + itemStyle: { + // color: '#f94b59' + color: '#639fc0' + }, + label: { + show: true + } + } + } +}); + +/***/ }), +/* 97 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; + +function swap(arr, a, b) { + var tmp = arr[a]; + arr[a] = arr[b]; + arr[b] = tmp; +} +function partition(arr, pivot, left, right, compare) { + var storeIndex = left; + var pivotValue = arr[pivot]; + + // put the pivot on the right + swap(arr, pivot, right); + + // go through the rest + for(var v = left; v < right; v++) { + if(compare(arr[v], pivotValue) < 0) { + swap(arr, v, storeIndex); + storeIndex++; + } + } + + // finally put the pivot in the correct place + swap(arr, right, storeIndex); + + return storeIndex; +} + +function quickSort(array, compare, left, right) { + if(left < right) { + var pivot = Math.floor((left + right) / 2); + var newPivot = partition(array, pivot, left, right, compare); + quickSort(array, compare, left, newPivot - 1); + quickSort(array, compare, newPivot + 1, right); + } +} + + +// TODO Test. +function ProgressiveQuickSort() { + + // this._pivotList = new LinkedList(); + this._parts = []; +} + +ProgressiveQuickSort.prototype.step = function (arr, compare, frame) { + + var len = arr.length; + if (frame === 0) { + this._parts = []; + this._sorted = false; + + // Pick a start pivot; + var pivot = Math.floor(len / 2); + this._parts.push({ + pivot: pivot, + left: 0, + right: len - 1 + }); + + this._currentSortPartIdx = 0; + } + + if (this._sorted) { + return; + } + + var parts = this._parts; + if (parts.length === 0) { + this._sorted = true; + // Already finished. + return true; + } + else if (parts.length < 512) { + // Sort large parts in about 10 frames. + for (var i = 0; i < parts.length; i++) { + // Partition and Modify the pivot index. + parts[i].pivot = partition( + arr, parts[i].pivot, parts[i].left, parts[i].right, compare + ); + } + + var subdividedParts = []; + for (var i = 0; i < parts.length; i++) { + // Subdivide left + var left = parts[i].left; + var right = parts[i].pivot - 1; + if (right > left) { + subdividedParts.push({ + pivot: Math.floor((right + left) / 2), + left: left, right: right + }); + } + // Subdivide right + var left = parts[i].pivot + 1; + var right = parts[i].right; + if (right > left) { + subdividedParts.push({ + pivot: Math.floor((right + left) / 2), + left: left, right: right + }); + } + } + parts = this._parts = subdividedParts; + } + else { + // console.time('sort'); + // Finally quick sort each parts in 10 frames. + for (var i = 0; i < Math.floor(parts.length / 10); i++) { + // Sort near parts first. + var idx = parts.length - 1 - this._currentSortPartIdx; + quickSort(arr, compare, parts[idx].left, parts[idx].right); + this._currentSortPartIdx++; + + // Finish sort + if (this._currentSortPartIdx === parts.length) { + this._sorted = true; + return true; + } + } + // console.timeEnd('sort'); + + } + + return false; +}; + +ProgressiveQuickSort.sort = quickSort; + +/* harmony default export */ __webpack_exports__["a"] = (ProgressiveQuickSort); + +/***/ }), +/* 98 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__geo3D_Geo3D__ = __webpack_require__(99); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_echarts_lib_echarts__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_echarts_lib_echarts___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_echarts_lib_echarts__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2_echarts_lib_util_layout__ = __webpack_require__(47); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2_echarts_lib_util_layout___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_2_echarts_lib_util_layout__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__core_ViewGL__ = __webpack_require__(22); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4__util_retrieve__ = __webpack_require__(2); + + + + + + +function resizeGeo3D(geo3DModel, api) { + // Use left/top/width/height + var boxLayoutOption = geo3DModel.getBoxLayoutParams(); + + var viewport = __WEBPACK_IMPORTED_MODULE_2_echarts_lib_util_layout___default.a.getLayoutRect(boxLayoutOption, { + width: api.getWidth(), + height: api.getHeight() + }); + + // Flip Y + viewport.y = api.getHeight() - viewport.y - viewport.height; + + this.viewGL.setViewport(viewport.x, viewport.y, viewport.width, viewport.height, api.getDevicePixelRatio()); + + var geoRect = this.getGeoBoundingRect(); + var aspect = geoRect.width / geoRect.height * (geo3DModel.get('aspectScale') || 0.75); + + var width = geo3DModel.get('boxWidth'); + var depth = geo3DModel.get('boxDepth'); + var height = geo3DModel.get('boxHeight'); + if (height == null) { + height = 5; + } + if (isNaN(width) && isNaN(depth)) { + // Default to have 100 width + width = 100; + } + if (isNaN(depth)) { + depth = width / aspect; + } + else if (isNaN(width)) { + width = depth / aspect; + } + + this.setSize(width, height, depth); + + this.regionHeight = geo3DModel.get('regionHeight'); + + if (this.altitudeAxis) { + this.altitudeAxis.setExtent(0, Math.max(height - this.regionHeight, 0)); + } +} + +function updateGeo3D(ecModel, api) { + + var altitudeDataExtent = [Infinity, -Infinity]; + + ecModel.eachSeries(function (seriesModel) { + if (seriesModel.coordinateSystem !== this) { + return; + } + if (seriesModel.type === 'series.map3D') { + return; + } + // Get altitude data extent. + var data = seriesModel.getData(); + var altDims = seriesModel.coordDimToDataDim('alt'); + var altDim = altDims && altDims[0]; + if (altDim) { + // TODO altitiude is in coords of lines. + var dataExtent = data.getDataExtent(altDim, true); + altitudeDataExtent[0] = Math.min( + altitudeDataExtent[0], dataExtent[0] + ); + altitudeDataExtent[1] = Math.max( + altitudeDataExtent[1], dataExtent[1] + ); + } + }, this); + // Create altitude axis + if (altitudeDataExtent && isFinite(altitudeDataExtent[1] - altitudeDataExtent[0])) { + var scale = __WEBPACK_IMPORTED_MODULE_1_echarts_lib_echarts___default.a.helper.createScale( + altitudeDataExtent, { + type: 'value', + // PENDING + min: 'dataMin', + max: 'dataMax' + } + ); + this.altitudeAxis = new __WEBPACK_IMPORTED_MODULE_1_echarts_lib_echarts___default.a.Axis('altitude', scale); + // Resize again + this.resize(this.model, api); + } +} + + +if (true) { + var mapNotExistsError = function (name) { + console.error('Map ' + name + ' not exists. You can download map file on http://echarts.baidu.com/download-map.html'); + }; +} + + +var idStart = 0; + +var geo3DCreator = { + + dimensions: __WEBPACK_IMPORTED_MODULE_0__geo3D_Geo3D__["a" /* default */].prototype.dimensions, + + create: function (ecModel, api) { + + var geo3DList = []; + + if (!__WEBPACK_IMPORTED_MODULE_1_echarts_lib_echarts___default.a.getMap) { + throw new Error('geo3D component depends on geo component'); + } + + function createGeo3D(componentModel, idx) { + + var geo3D = geo3DCreator.createGeo3D(componentModel); + + // FIXME + componentModel.__viewGL = componentModel.__viewGL || new __WEBPACK_IMPORTED_MODULE_3__core_ViewGL__["a" /* default */](); + + geo3D.viewGL = componentModel.__viewGL; + + componentModel.coordinateSystem = geo3D; + geo3D.model = componentModel; + + geo3DList.push(geo3D); + + // Inject resize + geo3D.resize = resizeGeo3D; + geo3D.resize(componentModel, api); + + geo3D.update = updateGeo3D; + } + + ecModel.eachComponent('geo3D', function (geo3DModel, idx) { + createGeo3D(geo3DModel, idx); + }); + + ecModel.eachSeriesByType('map3D', function (map3DModel, idx) { + var coordSys = map3DModel.get('coordinateSystem'); + if (coordSys == null) { + coordSys = 'geo3D'; + } + if (coordSys === 'geo3D') { + createGeo3D(map3DModel, idx); + } + }); + + ecModel.eachSeries(function (seriesModel) { + if (seriesModel.get('coordinateSystem') === 'geo3D') { + if (seriesModel.type === 'series.map3D') { + return; + } + var geo3DModel = seriesModel.getReferringComponents('geo3D')[0]; + if (!geo3DModel) { + geo3DModel = ecModel.getComponent('geo3D'); + } + + if (!geo3DModel) { + throw new Error('geo "' + __WEBPACK_IMPORTED_MODULE_4__util_retrieve__["a" /* default */].firstNotNull( + seriesModel.get('geo3DIndex'), + seriesModel.get('geo3DId'), + 0 + ) + '" not found'); + } + + seriesModel.coordinateSystem = geo3DModel.coordinateSystem; + } + }); + + return geo3DList; + }, + + createGeo3D: function (componentModel) { + + var mapData = componentModel.get('map'); + var name; + if (typeof mapData === 'string') { + name = mapData; + mapData = __WEBPACK_IMPORTED_MODULE_1_echarts_lib_echarts___default.a.getMap(mapData); + } + else { + if (mapData && mapData.features) { + mapData = { + geoJson: mapData + }; + } + } + if (true) { + if (!mapData) { + mapNotExistsError(mapData); + } + if (!mapData.geoJson.features) { + throw new Error('Invalid GeoJSON for map3D'); + } + } + if (name == null) { + name = 'GEO_ANONYMOUS_' + idStart++; + } + + return new __WEBPACK_IMPORTED_MODULE_0__geo3D_Geo3D__["a" /* default */]( + name + idStart++, name, + mapData && mapData.geoJson, mapData && mapData.specialAreas, + componentModel.get('nameMap') + ); + } +}; + +__WEBPACK_IMPORTED_MODULE_1_echarts_lib_echarts___default.a.registerCoordinateSystem('geo3D', geo3DCreator); + +/* harmony default export */ __webpack_exports__["a"] = (geo3DCreator); + +/***/ }), +/* 99 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_claygl_src_dep_glmatrix__ = __webpack_require__(6); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2_echarts_lib_coord_geo_fix_textCoord__ = __webpack_require__(205); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2_echarts_lib_coord_geo_fix_textCoord___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_2_echarts_lib_coord_geo_fix_textCoord__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3_echarts_lib_coord_geo_fix_geoCoord__ = __webpack_require__(206); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3_echarts_lib_coord_geo_fix_geoCoord___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_3_echarts_lib_coord_geo_fix_geoCoord__); + + +var vec3 = __WEBPACK_IMPORTED_MODULE_1_claygl_src_dep_glmatrix__["a" /* default */].vec3; +var mat4 = __WEBPACK_IMPORTED_MODULE_1_claygl_src_dep_glmatrix__["a" /* default */].mat4; + + + +// Geo fix functions +var geoFixFuncs = [__WEBPACK_IMPORTED_MODULE_2_echarts_lib_coord_geo_fix_textCoord___default.a, __WEBPACK_IMPORTED_MODULE_3_echarts_lib_coord_geo_fix_geoCoord___default.a]; + +function Geo3D(name, map, geoJson, specialAreas, nameMap) { + + this.name = name; + + this.map = map; + + this.regionHeight = 0; + + this.regions = []; + + this._nameCoordMap = {}; + + this.loadGeoJson(geoJson, specialAreas, nameMap); + + this.transform = mat4.identity(new Float64Array(16)); + + this.invTransform = mat4.identity(new Float64Array(16)); + + // Which dimension to extrude. Y or Z + this.extrudeY = true; + + this.altitudeAxis; +} + +Geo3D.prototype = { + + constructor: Geo3D, + + type: 'geo3D', + + dimensions: ['lng', 'lat', 'alt'], + + containPoint: function () {}, + + loadGeoJson: function (geoJson, specialAreas, nameMap) { + var parseGeoJSON = __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.parseGeoJSON || __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.parseGeoJson; + try { + this.regions = geoJson ? parseGeoJSON(geoJson) : []; + } + catch (e) { + throw 'Invalid geoJson format\n' + e; + } + specialAreas = specialAreas || {}; + nameMap = nameMap || {}; + var regions = this.regions; + var regionsMap = {}; + for (var i = 0; i < regions.length; i++) { + var regionName = regions[i].name; + // Try use the alias in nameMap + regionName = nameMap[regionName] || regionName; + regions[i].name = regionName; + + regionsMap[regionName] = regions[i]; + // Add geoJson + this.addGeoCoord(regionName, regions[i].center); + + // Some area like Alaska in USA map needs to be tansformed + // to look better + var specialArea = specialAreas[regionName]; + if (specialArea) { + regions[i].transformTo( + specialArea.left, specialArea.top, specialArea.width, specialArea.height + ); + } + } + + this._regionsMap = regionsMap; + + this._geoRect = null; + + geoFixFuncs.forEach(function (fixFunc) { + fixFunc(this); + }, this); + }, + + getGeoBoundingRect: function () { + if (this._geoRect) { + return this._geoRect; + } + var rect; + + var regions = this.regions; + for (var i = 0; i < regions.length; i++) { + var regionRect = regions[i].getBoundingRect(); + rect = rect || regionRect.clone(); + rect.union(regionRect); + } + // FIXME Always return new ? + return (this._geoRect = rect || new __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.graphic.BoundingRect(0, 0, 0, 0)); + }, + + /** + * Add geoCoord for indexing by name + * @param {string} name + * @param {Array.} geoCoord + */ + addGeoCoord: function (name, geoCoord) { + this._nameCoordMap[name] = geoCoord; + }, + + /** + * @param {string} name + * @return {module:echarts/coord/geo/Region} + */ + getRegion: function (name) { + return this._regionsMap[name]; + }, + + getRegionByCoord: function (coord) { + var regions = this.regions; + for (var i = 0; i < regions.length; i++) { + if (regions[i].contain(coord)) { + return regions[i]; + } + } + }, + + setSize: function (width, height, depth) { + this.size = [width, height, depth]; + + var rect = this.getGeoBoundingRect(); + + var scaleX = width / rect.width; + var scaleZ = -depth / rect.height; + var translateX = -width / 2 - rect.x * scaleX; + var translateZ = depth / 2 - rect.y * scaleZ; + + var position = this.extrudeY ? [translateX, 0, translateZ] : [translateX, translateZ, 0]; + var scale = this.extrudeY ? [scaleX, 1, scaleZ] : [scaleX, scaleZ, 1]; + + var m = this.transform; + mat4.identity(m); + mat4.translate(m, m, position); + mat4.scale(m, m, scale); + + mat4.invert(this.invTransform, m); + }, + + dataToPoint: function (data, out) { + out = out || []; + + var extrudeCoordIndex = this.extrudeY ? 1 : 2; + var sideCoordIndex = this.extrudeY ? 2 : 1; + + var altitudeVal = data[2]; + // PENDING. + if (isNaN(altitudeVal)) { + altitudeVal = 0; + } + // lng + out[0] = data[0]; + // lat + out[sideCoordIndex] = data[1]; + + if (this.altitudeAxis) { + out[extrudeCoordIndex] = this.altitudeAxis.dataToCoord(altitudeVal); + } + else { + out[extrudeCoordIndex] = 0; + } + // PENDING different region height. + out[extrudeCoordIndex] += this.regionHeight; + + vec3.transformMat4(out, out, this.transform); + + return out; + }, + + pointToData: function (point, out) { + // TODO + } +}; + +/* harmony default export */ __webpack_exports__["a"] = (Geo3D); + +/***/ }), +/* 100 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_claygl_src_dep_glmatrix__ = __webpack_require__(6); + +var mat4 = __WEBPACK_IMPORTED_MODULE_0_claygl_src_dep_glmatrix__["a" /* default */].mat4; + +var TILE_SIZE = 512; +var FOV = 0.6435011087932844; +var PI = Math.PI; + +var WORLD_SCALE = 1 / 10; + +function MapServiceCoordSys3D() { + /** + * Width of mapbox viewport + */ + this.width = 0; + /** + * Height of mapbox viewport + */ + this.height = 0; + + this.altitudeScale = 1; + + // TODO Change boxHeight won't have animation. + this.boxHeight = 'auto'; + + // Set by mapbox creator + this.altitudeExtent; + + this.bearing = 0; + this.pitch = 0; + this.center = [0, 0]; + + this._origin; + + this.zoom = 0; + this._initialZoom; + + // Some parameters for different map services. + this.maxPitch = 60; + this.zoomOffset = 0; +} + +MapServiceCoordSys3D.prototype = { + + constructor: MapServiceCoordSys3D, + + dimensions: ['lng', 'lat', 'alt'], + + containPoint: function () {}, + + setCameraOption: function (option) { + this.bearing = option.bearing; + this.pitch = option.pitch; + + this.center = option.center; + this.zoom = option.zoom; + + if (!this._origin) { + this._origin = this.projectOnTileWithScale(this.center, TILE_SIZE); + } + if (this._initialZoom == null) { + this._initialZoom = this.zoom; + } + + this.updateTransform(); + }, + + // https://github.com/mapbox/mapbox-gl-js/blob/master/src/geo/transform.js#L479 + updateTransform: function () { + if (!this.height) { return; } + + var cameraToCenterDistance = 0.5 / Math.tan(FOV / 2) * this.height * WORLD_SCALE; + // Convert to radian. + var pitch = Math.max(Math.min(this.pitch, this.maxPitch), 0) / 180 * Math.PI; + + // Find the distance from the center point [width/2, height/2] to the + // center top point [width/2, 0] in Z units, using the law of sines. + // 1 Z unit is equivalent to 1 horizontal px at the center of the map + // (the distance between[width/2, height/2] and [width/2 + 1, height/2]) + var halfFov = FOV / 2; + var groundAngle = Math.PI / 2 + pitch; + var topHalfSurfaceDistance = Math.sin(halfFov) * cameraToCenterDistance / Math.sin(Math.PI - groundAngle - halfFov); + + // Calculate z distance of the farthest fragment that should be rendered. + var furthestDistance = Math.cos(Math.PI / 2 - pitch) * topHalfSurfaceDistance + cameraToCenterDistance; + // Add a bit extra to avoid precision problems when a fragment's distance is exactly `furthestDistance` + var farZ = furthestDistance * 1.1; + // Forced to be 1000 + if (this.pitch > 50) { + farZ = 1000; + } + + // matrix for conversion from location to GL coordinates (-1 .. 1) + var m = []; + mat4.perspective(m, FOV, this.width / this.height, 1, farZ); + this.viewGL.camera.projectionMatrix.setArray(m); + this.viewGL.camera.decomposeProjectionMatrix(); + + var m = mat4.identity([]); + var pt = this.dataToPoint(this.center); + // Inverse + mat4.scale(m, m, [1, -1, 1]); + // Translate to altitude + mat4.translate(m, m, [0, 0, -cameraToCenterDistance]); + mat4.rotateX(m, m, pitch); + mat4.rotateZ(m, m, -this.bearing / 180 * Math.PI); + // Translate to center. + mat4.translate(m, m, [-pt[0] * this.getScale() * WORLD_SCALE, -pt[1] * this.getScale() * WORLD_SCALE, 0]); + + this.viewGL.camera.viewMatrix.array = m; + var invertM = []; + mat4.invert(invertM, m); + this.viewGL.camera.worldTransform.array = invertM; + this.viewGL.camera.decomposeWorldTransform(); + + // scale vertically to meters per pixel (inverse of ground resolution): + // worldSize / (circumferenceOfEarth * cos(lat * π / 180)) + var worldSize = TILE_SIZE * this.getScale(); + var verticalScale; + + if (this.altitudeExtent && !isNaN(this.boxHeight)) { + var range = this.altitudeExtent[1] - this.altitudeExtent[0]; + verticalScale = this.boxHeight / range * this.getScale() / Math.pow(2, this._initialZoom - this.zoomOffset); + } + else { + verticalScale = worldSize / (2 * Math.PI * 6378000 * Math.abs(Math.cos(this.center[1] * (Math.PI / 180)))) + * this.altitudeScale * WORLD_SCALE; + } + // Include scale to avoid relayout when zooming + // FIXME Camera scale may have problem in shadow + this.viewGL.rootNode.scale.set( + this.getScale() * WORLD_SCALE, this.getScale() * WORLD_SCALE, verticalScale + ); + }, + + getScale: function () { + return Math.pow(2, this.zoom - this.zoomOffset); + }, + + projectOnTile: function (data, out) { + return this.projectOnTileWithScale(data, this.getScale() * TILE_SIZE, out); + }, + + projectOnTileWithScale: function (data, scale, out) { + var lng = data[0]; + var lat = data[1]; + var lambda2 = lng * PI / 180; + var phi2 = lat * PI / 180; + var x = scale * (lambda2 + PI) / (2 * PI); + var y = scale * (PI - Math.log(Math.tan(PI / 4 + phi2 * 0.5))) / (2 * PI); + out = out || []; + out[0] = x; + out[1] = y; + return out; + }, + + unprojectFromTile: function (point, out) { + return this.unprojectOnTileWithScale(point, this.getScale() * TILE_SIZE, out); + }, + + unprojectOnTileWithScale: function (point, scale, out) { + var x = point[0]; + var y = point[1]; + var lambda2 = (x / scale) * (2 * PI) - PI; + var phi2 = 2 * (Math.atan(Math.exp(PI - (y / scale) * (2 * PI))) - PI / 4); + out = out || []; + out[0] = lambda2 * 180 / PI; + out[1] = phi2 * 180 / PI; + return out; + }, + + dataToPoint: function (data, out) { + out = this.projectOnTileWithScale(data, TILE_SIZE, out); + // Add a origin to avoid precision issue in WebGL. + out[0] -= this._origin[0]; + out[1] -= this._origin[1]; + // PENDING + out[2] = !isNaN(data[2]) ? data[2] : 0; + if (!isNaN(data[2])) { + out[2] = data[2]; + if (this.altitudeExtent) { + out[2] -= this.altitudeExtent[0]; + } + } + return out; + } +}; + +/* harmony default export */ __webpack_exports__["a"] = (MapServiceCoordSys3D); + +/***/ }), +/* 101 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__util_retrieve__ = __webpack_require__(2); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__ = __webpack_require__(1); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__core_ViewGL__ = __webpack_require__(22); + + + + +/* harmony default export */ __webpack_exports__["a"] = (function (serviceComponentType, ServiceCtor, afterCreate) { + + function resizeMapService3D(mapService3DModel, api) { + var width = api.getWidth(); + var height = api.getHeight(); + var dpr = api.getDevicePixelRatio(); + this.viewGL.setViewport(0, 0, width, height, dpr); + + this.width = width; + this.height = height; + + this.altitudeScale = mapService3DModel.get('altitudeScale'); + + this.boxHeight = mapService3DModel.get('boxHeight'); + // this.updateTransform(); + } + + + function updateService3D(ecModel, api) { + + if (this.model.get('boxHeight') === 'auto') { + return; + } + + var altitudeDataExtent = [Infinity, -Infinity] + + ecModel.eachSeries(function (seriesModel) { + if (seriesModel.coordinateSystem !== this) { + return; + } + + // Get altitude data extent. + var data = seriesModel.getData(); + var altDim = seriesModel.coordDimToDataDim('alt')[0]; + if (altDim) { + // TODO altitiude is in coords of lines. + var dataExtent = data.getDataExtent(altDim, true); + altitudeDataExtent[0] = Math.min( + altitudeDataExtent[0], dataExtent[0] + ); + altitudeDataExtent[1] = Math.max( + altitudeDataExtent[1], dataExtent[1] + ); + } + }, this); + if (altitudeDataExtent && isFinite(altitudeDataExtent[1] - altitudeDataExtent[0])) { + this.altitudeExtent = altitudeDataExtent; + } + } + + return { + + + dimensions: ServiceCtor.prototype.dimensions, + + create: function (ecModel, api) { + var mapService3DList = []; + + ecModel.eachComponent(serviceComponentType, function (mapService3DModel) { + var viewGL = mapService3DModel.__viewGL; + if (!viewGL) { + viewGL = mapService3DModel.__viewGL = new __WEBPACK_IMPORTED_MODULE_2__core_ViewGL__["a" /* default */](); + viewGL.setRootNode(new __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].Node()); + } + + var mapService3DCoordSys = new ServiceCtor(); + mapService3DCoordSys.viewGL = mapService3DModel.__viewGL; + // Inject resize + mapService3DCoordSys.resize = resizeMapService3D; + mapService3DCoordSys.resize(mapService3DModel, api); + + mapService3DList.push(mapService3DCoordSys); + + mapService3DModel.coordinateSystem = mapService3DCoordSys; + mapService3DCoordSys.model = mapService3DModel; + + mapService3DCoordSys.update = updateService3D; + }); + + ecModel.eachSeries(function (seriesModel) { + if (seriesModel.get('coordinateSystem') === serviceComponentType) { + var mapService3DModel = seriesModel.getReferringComponents(serviceComponentType)[0]; + if (!mapService3DModel) { + mapService3DModel = ecModel.getComponent(serviceComponentType); + } + + if (!mapService3DModel) { + throw new Error(serviceComponentType + ' "' + __WEBPACK_IMPORTED_MODULE_0__util_retrieve__["a" /* default */].firstNotNull( + seriesModel.get(serviceComponentType + 'Index'), + seriesModel.get(serviceComponentType + 'Id'), + 0 + ) + '" not found'); + } + + seriesModel.coordinateSystem = mapService3DModel.coordinateSystem; + } + }); + + afterCreate && afterCreate(mapService3DList, ecModel, api); + + return mapService3DList; + } + }; +}); + + +/***/ }), +/* 102 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony default export */ __webpack_exports__["a"] = ("\n@export ecgl.displayShadow.vertex\n\n@import ecgl.common.transformUniforms\n\n@import ecgl.common.uv.header\n\n@import ecgl.common.attributes\n\nvarying vec3 v_WorldPosition;\n\nvarying vec3 v_Normal;\n\nvoid main()\n{\n @import ecgl.common.uv.main\n v_Normal = normalize((worldInverseTranspose * vec4(normal, 0.0)).xyz);\n\n v_WorldPosition = (world * vec4(position, 1.0)).xyz;\n gl_Position = worldViewProjection * vec4(position, 1.0);\n}\n\n@end\n\n\n@export ecgl.displayShadow.fragment\n\n@import ecgl.common.uv.fragmentHeader\n\nvarying vec3 v_Normal;\nvarying vec3 v_WorldPosition;\n\nuniform float roughness: 0.2;\n\n#ifdef DIRECTIONAL_LIGHT_COUNT\n@import clay.header.directional_light\n#endif\n\n@import ecgl.common.ssaoMap.header\n\n@import clay.plugin.compute_shadow_map\n\nvoid main()\n{\n float shadow = 1.0;\n\n @import ecgl.common.ssaoMap.main\n\n#if defined(DIRECTIONAL_LIGHT_COUNT) && defined(DIRECTIONAL_LIGHT_SHADOWMAP_COUNT)\n float shadowContribsDir[DIRECTIONAL_LIGHT_COUNT];\n if(shadowEnabled)\n {\n computeShadowOfDirectionalLights(v_WorldPosition, shadowContribsDir);\n }\n for (int i = 0; i < DIRECTIONAL_LIGHT_COUNT; i++) {\n shadow = min(shadow, shadowContribsDir[i] * 0.5 + 0.5);\n }\n#endif\n\n shadow *= 0.5 + ao * 0.5;\n shadow = clamp(shadow, 0.0, 1.0);\n\n gl_FragColor = vec4(vec3(0.0), 1.0 - shadow);\n}\n\n@end"); + + +/***/ }), +/* 103 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_zrender_lib_core_matrix__ = __webpack_require__(84); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_zrender_lib_core_matrix___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_zrender_lib_core_matrix__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_zrender_lib_core_vector__ = __webpack_require__(83); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_zrender_lib_core_vector___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_zrender_lib_core_vector__); + + + + +function GLViewHelper(viewGL) { + this.viewGL = viewGL; +} + +GLViewHelper.prototype.reset = function (seriesModel, api) { + this._updateCamera(api.getWidth(), api.getHeight(), api.getDevicePixelRatio()); + this._viewTransform = __WEBPACK_IMPORTED_MODULE_0_zrender_lib_core_matrix___default.a.create(); + this.updateTransform(seriesModel, api); +}; + +GLViewHelper.prototype.updateTransform = function (seriesModel, api) { + var coordinateSystem = seriesModel.coordinateSystem; + + if (coordinateSystem.getRoamTransform) { + + __WEBPACK_IMPORTED_MODULE_0_zrender_lib_core_matrix___default.a.invert(this._viewTransform, coordinateSystem.getRoamTransform()); + + this._setCameraTransform(this._viewTransform); + + api.getZr().refresh(); + } +}; + +// Reimplement the dataToPoint of coordinate system. +// Remove the effect of pan/zoom transform +GLViewHelper.prototype.dataToPoint = function (coordSys, data, pt) { + pt = coordSys.dataToPoint(data, null, pt); + var viewTransform = this._viewTransform; + if (viewTransform) { + __WEBPACK_IMPORTED_MODULE_1_zrender_lib_core_vector___default.a.applyTransform(pt, pt, viewTransform); + } +}; + +/** + * Remove transform info in point. + */ +GLViewHelper.prototype.removeTransformInPoint = function (pt) { + if (this._viewTransform) { + __WEBPACK_IMPORTED_MODULE_1_zrender_lib_core_vector___default.a.applyTransform(pt, pt, this._viewTransform); + } + return pt; +}; + +/** + * Return number + */ +GLViewHelper.prototype.getZoom = function () { + if (this._viewTransform) { + var m = this._viewTransform; + return 1 / Math.max( + Math.sqrt(m[0] * m[0] + m[1] * m[1]), + Math.sqrt(m[2] * m[2] + m[3] * m[3]) + ); + } + return 1; +}; + +GLViewHelper.prototype._setCameraTransform = function (m) { + var camera = this.viewGL.camera; + camera.position.set(m[4], m[5], 0); + camera.scale.set( + Math.sqrt(m[0] * m[0] + m[1] * m[1]), + Math.sqrt(m[2] * m[2] + m[3] * m[3]), + 1 + ); +}; + +GLViewHelper.prototype._updateCamera = function (width, height, dpr) { + // TODO, left, top, right, bottom + this.viewGL.setViewport(0, 0, width, height, dpr); + var camera = this.viewGL.camera; + camera.left = camera.top = 0; + camera.bottom = height; + camera.right = width; + camera.near = 0; + camera.far = 100; +}; + +/* harmony default export */ __webpack_exports__["a"] = (GLViewHelper); + +/***/ }), +/* 104 */ +/***/ (function(module, exports, __webpack_require__) { + +/* WEBPACK VAR INJECTION */(function(global) {/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ +// (1) The code `if (__DEV__) ...` can be removed by build tool. +// (2) If intend to use `__DEV__`, this module should be imported. Use a global +// variable `__DEV__` may cause that miss the declaration (see #6535), or the +// declaration is behind of the using position (for example in `Model.extent`, +// And tools like rollup can not analysis the dependency if not import). +var dev; // In browser + +if (typeof window !== 'undefined') { + dev = window.__DEV__; +} // In node +else if (typeof global !== 'undefined') { + dev = global.__DEV__; + } + +if (typeof dev === 'undefined') { + dev = true; +} + +var __DEV__ = dev; +exports.__DEV__ = __DEV__; +/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(68))) + +/***/ }), +/* 105 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_claygl_src_Geometry__ = __webpack_require__(15); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_echarts_lib_echarts__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_echarts_lib_echarts___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_echarts_lib_echarts__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__dynamicConvertMixin__ = __webpack_require__(38); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3_claygl_src_dep_glmatrix__ = __webpack_require__(6); +/** + * Lines geometry + * Use screen space projected lines lineWidth > MAX_LINE_WIDTH + * https://mattdesl.svbtle.com/drawing-lines-is-hard + * @module echarts-gl/util/geometry/LinesGeometry + * @author Yi Shen(http://github.com/pissang) + */ + + + + + +var vec2 = __WEBPACK_IMPORTED_MODULE_3_claygl_src_dep_glmatrix__["a" /* default */].vec2; + +// var CURVE_RECURSION_LIMIT = 8; +// var CURVE_COLLINEAR_EPSILON = 40; + +var sampleLinePoints = [[0, 0], [1, 1]]; +/** + * @constructor + * @alias module:echarts-gl/util/geometry/LinesGeometry + * @extends clay.Geometry + */ + +var LinesGeometry = __WEBPACK_IMPORTED_MODULE_0_claygl_src_Geometry__["a" /* default */].extend(function () { + return { + + segmentScale: 4, + + dynamic: true, + /** + * Need to use mesh to expand lines if lineWidth > MAX_LINE_WIDTH + */ + useNativeLine: true, + + attributes: { + position: new __WEBPACK_IMPORTED_MODULE_0_claygl_src_Geometry__["a" /* default */].Attribute('position', 'float', 2, 'POSITION'), + normal: new __WEBPACK_IMPORTED_MODULE_0_claygl_src_Geometry__["a" /* default */].Attribute('normal', 'float', 2), + offset: new __WEBPACK_IMPORTED_MODULE_0_claygl_src_Geometry__["a" /* default */].Attribute('offset', 'float', 1), + color: new __WEBPACK_IMPORTED_MODULE_0_claygl_src_Geometry__["a" /* default */].Attribute('color', 'float', 4, 'COLOR') + } + }; +}, +/** @lends module: echarts-gl/util/geometry/LinesGeometry.prototype */ +{ + + /** + * Reset offset + */ + resetOffset: function () { + this._vertexOffset = 0; + this._faceOffset = 0; + + this._itemVertexOffsets = []; + }, + + /** + * @param {number} nVertex + */ + setVertexCount: function (nVertex) { + var attributes = this.attributes; + if (this.vertexCount !== nVertex) { + attributes.position.init(nVertex); + attributes.color.init(nVertex); + + if (!this.useNativeLine) { + attributes.offset.init(nVertex); + attributes.normal.init(nVertex); + } + + if (nVertex > 0xffff) { + if (this.indices instanceof Uint16Array) { + this.indices = new Uint32Array(this.indices); + } + } + else { + if (this.indices instanceof Uint32Array) { + this.indices = new Uint16Array(this.indices); + } + } + } + }, + + /** + * @param {number} nTriangle + */ + setTriangleCount: function (nTriangle) { + if (this.triangleCount !== nTriangle) { + if (nTriangle === 0) { + this.indices = null; + } + else { + this.indices = this.vertexCount > 0xffff ? new Uint32Array(nTriangle * 3) : new Uint16Array(nTriangle * 3); + } + } + }, + + _getCubicCurveApproxStep: function (p0, p1, p2, p3) { + var len = vec2.dist(p0, p1) + vec2.dist(p2, p1) + vec2.dist(p3, p2); + var step = 1 / (len + 1) * this.segmentScale; + return step; + }, + + /** + * Get vertex count of cubic curve + * @param {Array.} p0 + * @param {Array.} p1 + * @param {Array.} p2 + * @param {Array.} p3 + * @return number + */ + getCubicCurveVertexCount: function (p0, p1, p2, p3) { + var step = this._getCubicCurveApproxStep(p0, p1, p2, p3); + var segCount = Math.ceil(1 / step); + if (!this.useNativeLine) { + return segCount * 2 + 2; + } + else { + return segCount * 2; + } + }, + + /** + * Get face count of cubic curve + * @param {Array.} p0 + * @param {Array.} p1 + * @param {Array.} p2 + * @param {Array.} p3 + * @return number + */ + getCubicCurveTriangleCount: function (p0, p1, p2, p3) { + var step = this._getCubicCurveApproxStep(p0, p1, p2, p3); + var segCount = Math.ceil(1 / step); + if (!this.useNativeLine) { + return segCount * 2; + } + else { + return 0; + } + }, + + /** + * Get vertex count of line + * @return {number} + */ + getLineVertexCount: function () { + return this.getPolylineVertexCount(sampleLinePoints); + }, + + /** + * Get face count of line + * @return {number} + */ + getLineTriangleCount: function () { + return this.getPolylineTriangleCount(sampleLinePoints); + }, + + /** + * Get how many vertices will polyline take. + * @type {number|Array} points Can be a 1d/2d list of points, or a number of points amount. + * @return {number} + */ + getPolylineVertexCount: function (points) { + var pointsLen; + if (typeof points === 'number') { + pointsLen = points; + } + else { + var is2DArray = typeof points[0] !== 'number'; + pointsLen = is2DArray ? points.length : (points.length / 2); + } + return !this.useNativeLine ? ((pointsLen - 1) * 2 + 2) : (pointsLen - 1) * 2; + }, + + /** + * Get how many triangles will polyline take. + * @type {number|Array} points Can be a 1d/2d list of points, or a number of points amount. + * @return {number} + */ + getPolylineTriangleCount: function (points) { + var pointsLen; + if (typeof points === 'number') { + pointsLen = points; + } + else { + var is2DArray = typeof points[0] !== 'number'; + pointsLen = is2DArray ? points.length : (points.length / 2); + } + return !this.useNativeLine ? (pointsLen - 1) * 2 : 0; + }, + + /** + * Add a cubic curve + * @param {Array.} p0 + * @param {Array.} p1 + * @param {Array.} p2 + * @param {Array.} p3 + * @param {Array.} color + * @param {number} [lineWidth=1] + */ + addCubicCurve: function (p0, p1, p2, p3, color, lineWidth) { + if (lineWidth == null) { + lineWidth = 1; + } + // incremental interpolation + // http://antigrain.com/research/bezier_interpolation/index.html#PAGE_BEZIER_INTERPOLATION + var x0 = p0[0], y0 = p0[1]; + var x1 = p1[0], y1 = p1[1]; + var x2 = p2[0], y2 = p2[1]; + var x3 = p3[0], y3 = p3[1]; + + var step = this._getCubicCurveApproxStep(p0, p1, p2, p3); + + var step2 = step * step; + var step3 = step2 * step; + + var pre1 = 3.0 * step; + var pre2 = 3.0 * step2; + var pre4 = 6.0 * step2; + var pre5 = 6.0 * step3; + + var tmp1x = x0 - x1 * 2.0 + x2; + var tmp1y = y0 - y1 * 2.0 + y2; + + var tmp2x = (x1 - x2) * 3.0 - x0 + x3; + var tmp2y = (y1 - y2) * 3.0 - y0 + y3; + + var fx = x0; + var fy = y0; + + var dfx = (x1 - x0) * pre1 + tmp1x * pre2 + tmp2x * step3; + var dfy = (y1 - y0) * pre1 + tmp1y * pre2 + tmp2y * step3; + + var ddfx = tmp1x * pre4 + tmp2x * pre5; + var ddfy = tmp1y * pre4 + tmp2y * pre5; + + var dddfx = tmp2x * pre5; + var dddfy = tmp2y * pre5; + + var t = 0; + + var k = 0; + var segCount = Math.ceil(1 / step); + + var points = new Float32Array((segCount + 1) * 3); + var points = []; + var offset = 0; + for (var k = 0; k < segCount + 1; k++) { + points[offset++] = fx; + points[offset++] = fy; + + fx += dfx; fy += dfy; + dfx += ddfx; dfy += ddfy; + ddfx += dddfx; ddfy += dddfy; + t += step; + + if (t > 1) { + fx = dfx > 0 ? Math.min(fx, x3) : Math.max(fx, x3); + fy = dfy > 0 ? Math.min(fy, y3) : Math.max(fy, y3); + } + } + + this.addPolyline(points, color, lineWidth); + }, + + /** + * Add a straight line + * @param {Array.} p0 + * @param {Array.} p1 + * @param {Array.} color + * @param {number} [lineWidth=1] + */ + addLine: function (p0, p1, color, lineWidth) { + this.addPolyline([p0, p1], color, lineWidth); + }, + + /** + * Add a straight line + * @param {Array. | Array.} points + * @param {Array. | Array.} color + * @param {number} [lineWidth=1] + * @param {number} [arrayOffset=0] + * @param {number} [pointsCount] Default to be amount of points in the first argument + */ + addPolyline: (function () { + var dirA = vec2.create(); + var dirB = vec2.create(); + var normal = vec2.create(); + var tangent = vec2.create(); + var point = [], nextPoint = [], prevPoint = []; + return function (points, color, lineWidth, arrayOffset, pointsCount) { + if (!points.length) { + return; + } + var is2DArray = typeof points[0] !== 'number'; + if (pointsCount == null) { + pointsCount = is2DArray ? points.length : points.length / 2; + } + if (pointsCount < 2) { + return; + } + if (arrayOffset == null) { + arrayOffset = 0; + } + if (lineWidth == null) { + lineWidth = 1; + } + + this._itemVertexOffsets.push(this._vertexOffset); + + var notSharingColor = is2DArray + ? typeof color[0] !== 'number' + : color.length / 4 === pointsCount; + + var positionAttr = this.attributes.position; + var colorAttr = this.attributes.color; + var offsetAttr = this.attributes.offset; + var normalAttr = this.attributes.normal; + var indices = this.indices; + + var vertexOffset = this._vertexOffset; + var pointColor; + for (var k = 0; k < pointsCount; k++) { + if (is2DArray) { + point = points[k + arrayOffset]; + if (notSharingColor) { + pointColor = color[k + arrayOffset]; + } + else { + pointColor = color; + } + } + else { + var k2 = k * 2 + arrayOffset; + point = point || []; + point[0] = points[k2]; + point[1] = points[k2 + 1]; + + if (notSharingColor) { + var k4 = k * 4 + arrayOffset; + pointColor = pointColor || []; + pointColor[0] = color[k4]; + pointColor[1] = color[k4 + 1]; + pointColor[2] = color[k4 + 2]; + pointColor[3] = color[k4 + 3]; + } + else { + pointColor = color; + } + } + if (!this.useNativeLine) { + var offset; + if (k < pointsCount - 1) { + if (is2DArray) { + vec2.copy(nextPoint, points[k + 1]); + } + else { + var k2 = (k + 1) * 2 + arrayOffset; + nextPoint = nextPoint || []; + nextPoint[0] = points[k2]; + nextPoint[1] = points[k2 + 1]; + } + // TODO In case dir is (0, 0) + // TODO miterLimit + if (k > 0) { + vec2.sub(dirA, point, prevPoint); + vec2.sub(dirB, nextPoint, point); + vec2.normalize(dirA, dirA); + vec2.normalize(dirB, dirB); + vec2.add(tangent, dirA, dirB); + vec2.normalize(tangent, tangent); + var miter = lineWidth / 2 * Math.min(1 / vec2.dot(dirA, tangent), 2); + normal[0] = -tangent[1]; + normal[1] = tangent[0]; + + offset = miter; + } + else { + vec2.sub(dirA, nextPoint, point); + vec2.normalize(dirA, dirA); + + normal[0] = -dirA[1]; + normal[1] = dirA[0]; + + offset = lineWidth / 2; + } + + } + else { + vec2.sub(dirA, point, prevPoint); + vec2.normalize(dirA, dirA); + + normal[0] = -dirA[1]; + normal[1] = dirA[0]; + + offset = lineWidth / 2; + } + normalAttr.set(vertexOffset, normal); + normalAttr.set(vertexOffset + 1, normal); + offsetAttr.set(vertexOffset, offset); + offsetAttr.set(vertexOffset + 1, -offset); + + vec2.copy(prevPoint, point); + + positionAttr.set(vertexOffset, point); + positionAttr.set(vertexOffset + 1, point); + + colorAttr.set(vertexOffset, pointColor); + colorAttr.set(vertexOffset + 1, pointColor); + + vertexOffset += 2; + } + else { + if (k > 1) { + positionAttr.copy(vertexOffset, vertexOffset - 1); + colorAttr.copy(vertexOffset, vertexOffset - 1); + vertexOffset++; + } + } + + if (!this.useNativeLine) { + if (k > 0) { + var idx3 = this._faceOffset * 3; + var indices = this.indices; + // 0-----2 + // 1-----3 + // 0->1->2, 1->3->2 + indices[idx3] = vertexOffset - 4; + indices[idx3 + 1] = vertexOffset - 3; + indices[idx3 + 2] = vertexOffset - 2; + + indices[idx3 + 3] = vertexOffset - 3; + indices[idx3 + 4] = vertexOffset - 1; + indices[idx3 + 5] = vertexOffset - 2; + + this._faceOffset += 2; + } + } + else { + colorAttr.set(vertexOffset, pointColor); + positionAttr.set(vertexOffset, point); + vertexOffset++; + } + } + + this._vertexOffset = vertexOffset; + }; + })(), + + /** + * Set color of single line. + */ + setItemColor: function (idx, color) { + var startOffset = this._itemVertexOffsets[idx]; + var endOffset = idx < this._itemVertexOffsets.length - 1 ? this._itemVertexOffsets[idx + 1] : this._vertexOffset; + + for (var i = startOffset; i < endOffset; i++) { + this.attributes.color.set(i, color); + } + this.dirty('color'); + } +}); + +__WEBPACK_IMPORTED_MODULE_1_echarts_lib_echarts___default.a.util.defaults(LinesGeometry.prototype, __WEBPACK_IMPORTED_MODULE_2__dynamicConvertMixin__["a" /* default */]); + +/* harmony default export */ __webpack_exports__["a"] = (LinesGeometry); + +/***/ }), +/* 106 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +Object.defineProperty(__webpack_exports__, "__esModule", { value: true }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__src_echarts_gl__ = __webpack_require__(107); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__src_component_grid3D__ = __webpack_require__(154); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__src_component_geo3D__ = __webpack_require__(201); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__src_component_globe__ = __webpack_require__(207); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4__src_component_mapbox3D__ = __webpack_require__(213); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_5__src_component_maptalks3D__ = __webpack_require__(219); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_6__src_chart_bar3D__ = __webpack_require__(225); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_7__src_chart_line3D__ = __webpack_require__(232); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_8__src_chart_scatter3D__ = __webpack_require__(236); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_9__src_chart_lines3D__ = __webpack_require__(243); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_10__src_chart_polygons3D__ = __webpack_require__(249); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_11__src_chart_surface__ = __webpack_require__(252); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_12__src_chart_map3D__ = __webpack_require__(256); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_13__src_chart_scatterGL__ = __webpack_require__(259); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_14__src_chart_graphGL__ = __webpack_require__(262); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_15__src_chart_flowGL__ = __webpack_require__(275); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_16__src_chart_linesGL__ = __webpack_require__(281); + + + + + + + + + + + + + + + + + + + + + +/***/ }), +/* 107 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_claygl_src_version__ = __webpack_require__(108); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__core_LayerGL__ = __webpack_require__(109); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__preprocessor_backwardCompat__ = __webpack_require__(153); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4__util_graphicGL__ = __webpack_require__(1); +/** + * echarts-gl + * Extension pack of ECharts providing 3d plots and globe visualization + * + * Copyright (c) 2014, echarts-gl + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @module echarts-gl + * @author Yi Shen(http://github.com/pissang) + */ + +// PENDING Use a single canvas as layer or use image element? +var echartsGl = { + version: '1.1.1', + dependencies: { + echarts: '4.1.0', + claygl: '1.2.1' + } +}; + + + + + + +// Version checking +var deps = echartsGl.dependencies; +function versionTooOldMsg(name) { + throw new Error( + name + ' version is too old, needs ' + deps[name] + ' or higher' + ); +} +function checkVersion(version, name) { + if ((version.replace('.', '') - 0) < (deps[name].replace('.', '') - 0)) { + versionTooOldMsg(name); + } + console.log('Loaded ' + name + ', version ' + version); +} +checkVersion(__WEBPACK_IMPORTED_MODULE_1_claygl_src_version__["a" /* default */], 'claygl'); +checkVersion(__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.version, 'echarts'); + +function EChartsGL (zr) { + this._layers = {}; + + this._zr = zr; +} + +EChartsGL.prototype.update = function (ecModel, api) { + var self = this; + var zr = api.getZr(); + + if (!zr.getWidth() || !zr.getHeight()) { + console.warn('Dom has no width or height'); + return; + } + + function getLayerGL(model) { + var zlevel; + // Host on coordinate system. + if (model.coordinateSystem && model.coordinateSystem.model) { + zlevel = model.get('zlevel'); + } + else { + zlevel = model.get('zlevel'); + } + + var layers = self._layers; + var layerGL = layers[zlevel]; + if (!layerGL) { + layerGL = layers[zlevel] = new __WEBPACK_IMPORTED_MODULE_2__core_LayerGL__["a" /* default */]('gl-' + zlevel, zr); + + if (zr.painter.isSingleCanvas()) { + layerGL.virtual = true; + // If container is canvas, use image to represent LayerGL + // FIXME Performance + var img = new __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.graphic.Image({ + z: 1e4, + style: { + image: layerGL.renderer.canvas + }, + silent: true + }); + layerGL.__hostImage = img; + + zr.add(img); + } + + zr.painter.insertLayer(zlevel, layerGL); + } + if (layerGL.__hostImage) { + layerGL.__hostImage.setStyle({ + width: layerGL.renderer.getWidth(), + height: layerGL.renderer.getHeight() + }); + } + + return layerGL; + } + + function setSilent(groupGL, silent) { + if (groupGL) { + groupGL.traverse(function (mesh) { + if (mesh.isRenderable && mesh.isRenderable()) { + mesh.ignorePicking = mesh.$ignorePicking != null + ? mesh.$ignorePicking : silent; + } + }); + } + } + + for (var zlevel in this._layers) { + this._layers[zlevel].removeViewsAll(); + } + + ecModel.eachComponent(function (componentType, componentModel) { + if (componentType !== 'series') { + var view = api.getViewOfComponentModel(componentModel); + var coordSys = componentModel.coordinateSystem; + // View with __ecgl__ flag is a echarts-gl component. + if (view.__ecgl__) { + var viewGL; + if (coordSys) { + if (!coordSys.viewGL) { + console.error('Can\'t find viewGL in coordinateSystem of component ' + componentModel.id); + return; + } + viewGL = coordSys.viewGL; + } + else { + if (!componentModel.viewGL) { + console.error('Can\'t find viewGL of component ' + componentModel.id); + return; + } + viewGL = coordSys.viewGL; + } + + var viewGL = coordSys.viewGL; + var layerGL = getLayerGL(componentModel); + + layerGL.addView(viewGL); + + view.afterRender && view.afterRender( + componentModel, ecModel, api, layerGL + ); + + setSilent(view.groupGL, componentModel.get('silent')); + } + } + }); + + ecModel.eachSeries(function (seriesModel) { + var chartView = api.getViewOfSeriesModel(seriesModel); + var coordSys = seriesModel.coordinateSystem; + if (chartView.__ecgl__) { + if ((coordSys && !coordSys.viewGL) && !chartView.viewGL) { + console.error('Can\'t find viewGL of series ' + chartView.id); + return; + } + var viewGL = (coordSys && coordSys.viewGL) || chartView.viewGL; + // TODO Check zlevel not same with component of coordinate system ? + var layerGL = getLayerGL(seriesModel); + layerGL.addView(viewGL); + + chartView.afterRender && chartView.afterRender( + seriesModel, ecModel, api, layerGL + ); + + setSilent(chartView.groupGL, seriesModel.get('silent')); + } + }); +}; + +// Hack original getRenderedCanvas. Will removed after new echarts released +// TODO +var oldInit = __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.init; +__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.init = function () { + var chart = oldInit.apply(this, arguments); + chart.getZr().painter.getRenderedCanvas = function (opts) { + opts = opts || {}; + if (this._singleCanvas) { + return this._layers[0].dom; + } + + var canvas = document.createElement('canvas'); + var dpr = opts.pixelRatio || this.dpr; + canvas.width = this.getWidth() * dpr; + canvas.height = this.getHeight() * dpr; + var ctx = canvas.getContext('2d'); + ctx.dpr = dpr; + + ctx.clearRect(0, 0, canvas.width, canvas.height); + if (opts.backgroundColor) { + ctx.fillStyle = opts.backgroundColor; + ctx.fillRect(0, 0, canvas.width, canvas.height); + } + + var displayList = this.storage.getDisplayList(true); + + var scope = {}; + var zlevel; + + var self = this; + function findAndDrawOtherLayer(smaller, larger) { + var zlevelList = self._zlevelList; + if (smaller == null) { + smaller = -Infinity; + } + var intermediateLayer; + for (var i = 0; i < zlevelList.length; i++) { + var z = zlevelList[i]; + var layer = self._layers[z]; + if (!layer.__builtin__ && z > smaller && z < larger) { + intermediateLayer = layer; + break; + } + } + if (intermediateLayer && intermediateLayer.renderToCanvas) { + ctx.save(); + intermediateLayer.renderToCanvas(ctx); + ctx.restore(); + } + } + var layer = { + ctx: ctx + }; + for (var i = 0; i < displayList.length; i++) { + var el = displayList[i]; + + if (el.zlevel !== zlevel) { + findAndDrawOtherLayer(zlevel, el.zlevel); + zlevel = el.zlevel; + } + this._doPaintEl(el, layer, true, scope); + } + + findAndDrawOtherLayer(zlevel, Infinity); + + return canvas; + }; + return chart; +}; + + +__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.registerPostUpdate(function (ecModel, api) { + var zr = api.getZr(); + + var egl = zr.__egl = zr.__egl || new EChartsGL(zr); + + egl.update(ecModel, api); +}); + +__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.registerPreprocessor(__WEBPACK_IMPORTED_MODULE_3__preprocessor_backwardCompat__["a" /* default */]); + +__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.graphicGL = __WEBPACK_IMPORTED_MODULE_4__util_graphicGL__["a" /* default */]; + +/* unused harmony default export */ var _unused_webpack_default_export = (EChartsGL); + +/***/ }), +/* 108 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/** + * @name clay.version + */ +/* harmony default export */ __webpack_exports__["a"] = ('1.2.1'); + + +/***/ }), +/* 109 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_claygl_src_Renderer__ = __webpack_require__(52); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2_claygl_src_picking_RayPicking__ = __webpack_require__(117); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3_claygl_src_Texture__ = __webpack_require__(4); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4__util_graphicGL__ = __webpack_require__(1); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_5_claygl_src_core_mixin_notifier__ = __webpack_require__(53); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_6_zrender_lib_animation_requestAnimationFrame__ = __webpack_require__(80); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_6_zrender_lib_animation_requestAnimationFrame___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_6_zrender_lib_animation_requestAnimationFrame__); +/** + * Provide WebGL layer to zrender. Which is rendered on top of clay. + * + * + * Relationship between zrender, LayerGL(renderer) and ViewGL(Scene, Camera, Viewport) + * zrender + * / \ + * LayerGL LayerGL + * (renderer) (renderer) + * / \ + * ViewGL ViewGL + * + * @module echarts-gl/core/LayerGL + * @author Yi Shen(http://github.com/pissang) + */ + + + + + + + +// PENDING, clay. notifier is same with zrender Eventful + + + +/** + * @constructor + * @alias module:echarts-gl/core/LayerGL + * @param {string} id Layer ID + * @param {module:zrender/ZRender} zr + */ +var LayerGL = function (id, zr) { + + /** + * Layer ID + * @type {string} + */ + this.id = id; + + /** + * @type {module:zrender/ZRender} + */ + this.zr = zr; + + /** + * @type {clay.Renderer} + */ + try { + this.renderer = new __WEBPACK_IMPORTED_MODULE_1_claygl_src_Renderer__["a" /* default */]({ + clearBit: 0, + devicePixelRatio: zr.painter.dpr, + preserveDrawingBuffer: true, + // PENDING + premultipliedAlpha: true + }); + this.renderer.resize(zr.painter.getWidth(), zr.painter.getHeight()); + } + catch (e) { + this.renderer = null; + this.dom = document.createElement('div'); + this.dom.style.cssText = 'position:absolute; left: 0; top: 0; right: 0; bottom: 0;'; + this.dom.className = 'ecgl-nowebgl'; + this.dom.innerHTML = 'Sorry, your browser does not support WebGL'; + + console.error(e); + return; + } + + this.onglobalout = this.onglobalout.bind(this); + zr.on('globalout', this.onglobalout); + + /** + * Canvas dom for webgl rendering + * @type {HTMLCanvasElement} + */ + this.dom = this.renderer.canvas; + var style = this.dom.style; + style.position = 'absolute'; + style.left = '0'; + style.top = '0'; + + /** + * @type {Array.} + */ + this.views = []; + + this._picking = new __WEBPACK_IMPORTED_MODULE_2_claygl_src_picking_RayPicking__["a" /* default */]({ + renderer: this.renderer + }); + + this._viewsToDispose = []; + + /** + * Current accumulating id. + */ + this._accumulatingId = 0; + + this._zrEventProxy = new __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.graphic.Rect({ + shape: {x: -1, y: -1, width: 2, height: 2}, + // FIXME Better solution. + __isGLToZRProxy: true + }); + + this._backgroundColor = null; +}; + +/** + * @param {module:echarts-gl/core/ViewGL} view + */ +LayerGL.prototype.addView = function (view) { + if (view.layer === this) { + return; + } + // If needs to dispose in this layer. unmark it. + var idx = this._viewsToDispose.indexOf(view); + if (idx >= 0) { + this._viewsToDispose.splice(idx, 1); + } + + this.views.push(view); + + view.layer = this; + + var zr = this.zr; + view.scene.traverse(function (node) { + node.__zr = zr; + if (node.addAnimatorsToZr) { + node.addAnimatorsToZr(zr); + } + }); +}; + +function removeFromZr(node) { + var zr = node.__zr; + node.__zr = null; + if (zr && node.removeAnimatorsFromZr) { + node.removeAnimatorsFromZr(zr); + } +} +/** + * @param {module:echarts-gl/core/ViewGL} view + */ +LayerGL.prototype.removeView = function (view) { + if (view.layer !== this) { + return; + } + + var idx = this.views.indexOf(view); + if (idx >= 0) { + this.views.splice(idx, 1); + view.scene.traverse(removeFromZr, this); + view.layer = null; + + // Mark to dispose in this layer. + this._viewsToDispose.push(view); + } +}; + +/** + * Remove all views + */ +LayerGL.prototype.removeViewsAll = function () { + this.views.forEach(function (view) { + view.scene.traverse(removeFromZr, this); + view.layer = null; + + // Mark to dispose in this layer. + this._viewsToDispose.push(view); + }, this); + + this.views.length = 0; + +}; + +/** + * Resize the canvas and viewport, will be invoked by zrender + * @param {number} width + * @param {number} height + */ +LayerGL.prototype.resize = function (width, height) { + var renderer = this.renderer; + renderer.resize(width, height); +}; + +/** + * Clear color and depth + * @return {[type]} [description] + */ +LayerGL.prototype.clear = function () { + var gl = this.renderer.gl; + var clearColor = this._backgroundColor || [0, 0, 0, 0]; + gl.clearColor(clearColor[0], clearColor[1], clearColor[2], clearColor[3]); + gl.depthMask(true); + gl.colorMask(true, true, true, true); + gl.clear(gl.DEPTH_BUFFER_BIT | gl.COLOR_BUFFER_BIT); +}; + +/** + * Clear depth + */ +LayerGL.prototype.clearDepth = function () { + var gl = this.renderer.gl; + gl.clear(gl.DEPTH_BUFFER_BIT); +}; + +/** + * Clear color + */ +LayerGL.prototype.clearColor = function () { + var gl = this.renderer.gl; + gl.clearColor(0, 0, 0, 0); + gl.clear(gl.COLOR_BUFFER_BIT); +}; + +/** + * Mark layer to refresh next tick + */ +LayerGL.prototype.needsRefresh = function () { + this.zr.refresh(); +}; + +/** + * Refresh the layer, will be invoked by zrender + */ +LayerGL.prototype.refresh = function (bgColor) { + + this._backgroundColor = bgColor ? __WEBPACK_IMPORTED_MODULE_4__util_graphicGL__["a" /* default */].parseColor(bgColor) : [0, 0, 0, 0]; + this.renderer.clearColor = this._backgroundColor; + + for (var i = 0; i < this.views.length; i++) { + this.views[i].prepareRender(this.renderer); + } + + this._doRender(false); + + // Auto dispose unused resources on GPU, like program(shader), texture, geometry(buffers) + this._trackAndClean(); + + // Dispose trashed views + for (var i = 0; i < this._viewsToDispose.length; i++) { + this._viewsToDispose[i].dispose(this.renderer); + } + this._viewsToDispose.length = 0; + + this._startAccumulating(); +}; + + +LayerGL.prototype.renderToCanvas = function (ctx) { + // PENDING will block the page + this._startAccumulating(true); + ctx.drawImage(this.dom, 0, 0, ctx.canvas.width, ctx.canvas.height); +}; + +LayerGL.prototype._doRender = function (accumulating) { + this.clear(); + this.renderer.saveViewport(); + for (var i = 0; i < this.views.length; i++) { + this.views[i].render(this.renderer, accumulating); + } + this.renderer.restoreViewport(); +}; + +/** + * Stop accumulating + */ +LayerGL.prototype._stopAccumulating = function () { + this._accumulatingId = 0; + clearTimeout(this._accumulatingTimeout); +}; + +var accumulatingId = 1; +/** + * Start accumulating all the views. + * Accumulating is for antialising and have more sampling in SSAO + * @private + */ +LayerGL.prototype._startAccumulating = function (immediate) { + var self = this; + this._stopAccumulating(); + + var needsAccumulate = false; + for (var i = 0; i < this.views.length; i++) { + needsAccumulate = this.views[i].needsAccumulate() || needsAccumulate; + } + if (!needsAccumulate) { + return; + } + + function accumulate(id) { + if (!self._accumulatingId || id !== self._accumulatingId) { + return; + } + + var isFinished = true; + for (var i = 0; i < self.views.length; i++) { + isFinished = self.views[i].isAccumulateFinished() && needsAccumulate; + } + + if (!isFinished) { + self._doRender(true); + + if (immediate) { + accumulate(id); + } + else { + __WEBPACK_IMPORTED_MODULE_6_zrender_lib_animation_requestAnimationFrame___default()(function () { + accumulate(id); + }); + } + } + } + + this._accumulatingId = accumulatingId++; + + if (immediate) { + accumulate(self._accumulatingId); + } + else { + this._accumulatingTimeout = setTimeout(function () { + accumulate(self._accumulatingId); + }, 50); + } +}; + +LayerGL.prototype._trackAndClean = function () { + var textureList = []; + var geometriesList = []; + + // Mark all resources unused; + if (this._textureList) { + markUnused(this._textureList); + markUnused(this._geometriesList); + } + + for (var i = 0; i < this.views.length; i++) { + collectResources(this.views[i].scene, textureList, geometriesList); + } + + // Dispose those unsed resources. + if (this._textureList) { + checkAndDispose(this.renderer, this._textureList); + checkAndDispose(this.renderer, this._geometriesList); + } + + this._textureList = textureList; + this._geometriesList = geometriesList; +}; + +function markUnused(resourceList) { + for (var i = 0; i < resourceList.length; i++) { + resourceList[i].__used__ = 0; + } +} +function checkAndDispose(renderer, resourceList) { + for (var i = 0; i < resourceList.length; i++) { + if (!resourceList[i].__used__) { + resourceList[i].dispose(renderer); + } + } +} +function updateUsed(resource, list) { + resource.__used__ = resource.__used__ || 0; + resource.__used__++; + if (resource.__used__ === 1) { + // Don't push to the list twice. + list.push(resource); + } +} +function collectResources(scene, textureResourceList, geometryResourceList) { + var prevMaterial; + var prevGeometry; + scene.traverse(function (renderable) { + if (renderable.isRenderable()) { + var geometry = renderable.geometry; + var material = renderable.material; + + // TODO optimize!! + if (material !== prevMaterial) { + var textureUniforms = material.getTextureUniforms(); + for (var u = 0; u < textureUniforms.length; u++) { + var uniformName = textureUniforms[u]; + var val = material.uniforms[uniformName].value; + if (!val) { + continue; + } + if (val instanceof __WEBPACK_IMPORTED_MODULE_3_claygl_src_Texture__["a" /* default */]) { + updateUsed(val, textureResourceList); + } + else if (val instanceof Array) { + for (var k = 0; k < val.length; k++) { + if (val[k] instanceof __WEBPACK_IMPORTED_MODULE_3_claygl_src_Texture__["a" /* default */]) { + updateUsed(val[k], textureResourceList); + } + } + } + } + } + if (geometry !== prevGeometry) { + updateUsed(geometry, geometryResourceList); + } + + prevMaterial = material; + prevGeometry = geometry; + } + }); + + for (var k = 0; k < scene.lights.length; k++) { + // Track AmbientCubemap + if (scene.lights[k].cubemap) { + updateUsed(scene.lights[k].cubemap, textureResourceList); + } + } +} +/** + * Dispose the layer + */ +LayerGL.prototype.dispose = function () { + this._stopAccumulating(); + this.renderer.disposeScene(this.scene); + + this.zr.off('globalout', this.onglobalout); +}; + +// Event handlers +LayerGL.prototype.onmousedown = function (e) { + if (e.target && e.target.__isGLToZRProxy) { + return; + } + + e = e.event; + var obj = this.pickObject(e.offsetX, e.offsetY); + if (obj) { + this._dispatchEvent('mousedown', e, obj); + this._dispatchDataEvent('mousedown', e, obj); + } + + this._downX = e.offsetX; + this._downY = e.offsetY; +}; + +LayerGL.prototype.onmousemove = function (e) { + if (e.target && e.target.__isGLToZRProxy) { + return; + } + + e = e.event; + var obj = this.pickObject(e.offsetX, e.offsetY); + + var target = obj && obj.target; + var lastHovered = this._hovered; + this._hovered = obj; + + if (lastHovered && target !== lastHovered.target) { + lastHovered.relatedTarget = target; + this._dispatchEvent('mouseout', e, lastHovered); + // this._dispatchDataEvent('mouseout', e, lastHovered); + + this.zr.setCursorStyle('default'); + } + + this._dispatchEvent('mousemove', e, obj); + + if (obj) { + this.zr.setCursorStyle('pointer'); + + if (!lastHovered || (target !== lastHovered.target)) { + this._dispatchEvent('mouseover', e, obj); + // this._dispatchDataEvent('mouseover', e, obj); + } + } + + this._dispatchDataEvent('mousemove', e, obj); +}; + +LayerGL.prototype.onmouseup = function (e) { + if (e.target && e.target.__isGLToZRProxy) { + return; + } + + e = e.event; + var obj = this.pickObject(e.offsetX, e.offsetY); + + if (obj) { + this._dispatchEvent('mouseup', e, obj); + this._dispatchDataEvent('mouseup', e, obj); + } + + this._upX = e.offsetX; + this._upY = e.offsetY; +}; + +LayerGL.prototype.onclick = LayerGL.prototype.dblclick = function (e) { + if (e.target && e.target.__isGLToZRProxy) { + return; + } + + // Ignore click event if mouse moved + var dx = this._upX - this._downX; + var dy = this._upY - this._downY; + if (Math.sqrt(dx * dx + dy * dy) > 20) { + return; + } + + e = e.event; + var obj = this.pickObject(e.offsetX, e.offsetY); + + if (obj) { + this._dispatchEvent(e.type, e, obj); + this._dispatchDataEvent(e.type, e, obj); + } + + // Try set depth of field onclick + var result = this._clickToSetFocusPoint(e); + if (result) { + var success = result.view.setDOFFocusOnPoint(result.distance); + if (success) { + this.zr.refresh(); + } + } +}; + +LayerGL.prototype._clickToSetFocusPoint = function (e) { + var renderer = this.renderer; + var oldViewport = renderer.viewport; + for (var i = this.views.length - 1; i >= 0; i--) { + var viewGL = this.views[i]; + if (viewGL.hasDOF() && viewGL.containPoint(e.offsetX, e.offsetY)) { + this._picking.scene = viewGL.scene; + this._picking.camera = viewGL.camera; + // Only used for picking, renderer.setViewport will also invoke gl.viewport. + // Set directly, PENDING. + renderer.viewport = viewGL.viewport; + var result = this._picking.pick(e.offsetX, e.offsetY, true); + if (result) { + result.view = viewGL; + return result; + } + } + } + renderer.viewport = oldViewport; +}; + +LayerGL.prototype.onglobalout = function (e) { + var lastHovered = this._hovered; + if (lastHovered) { + this._dispatchEvent('mouseout', e, { + target: lastHovered.target + }); + } +}; + +LayerGL.prototype.pickObject = function (x, y) { + + var output = []; + var renderer = this.renderer; + var oldViewport = renderer.viewport; + for (var i = 0; i < this.views.length; i++) { + var viewGL = this.views[i]; + if (viewGL.containPoint(x, y)) { + this._picking.scene = viewGL.scene; + this._picking.camera = viewGL.camera; + // Only used for picking, renderer.setViewport will also invoke gl.viewport. + // Set directly, PENDING. + renderer.viewport = viewGL.viewport; + this._picking.pickAll(x, y, output); + } + } + renderer.viewport = oldViewport; + output.sort(function (a, b) { + return a.distance - b.distance; + }); + return output[0]; +}; + +LayerGL.prototype._dispatchEvent = function (eveName, originalEvent, newEvent) { + if (!newEvent) { + newEvent = {}; + } + var current = newEvent.target; + + newEvent.cancelBubble = false; + newEvent.event = originalEvent; + newEvent.type = eveName; + newEvent.offsetX = originalEvent.offsetX; + newEvent.offsetY = originalEvent.offsetY; + + while (current) { + current.trigger(eveName, newEvent); + current = current.getParent(); + + if (newEvent.cancelBubble) { + break; + } + } + + this._dispatchToView(eveName, newEvent); +}; + +LayerGL.prototype._dispatchDataEvent = function (eveName, originalEvent, newEvent) { + var mesh = newEvent && newEvent.target; + + var dataIndex = mesh && mesh.dataIndex; + var seriesIndex = mesh && mesh.seriesIndex; + // Custom event data + var eventData = mesh && mesh.eventData; + var elChangedInMouseMove = false; + + var eventProxy = this._zrEventProxy; + eventProxy.position = [originalEvent.offsetX, originalEvent.offsetY]; + eventProxy.update(); + + var targetInfo = { + target: eventProxy + }; + if (eveName === 'mousemove') { + if (dataIndex != null) { + if (dataIndex !== this._lastDataIndex) { + if (parseInt(this._lastDataIndex, 10) >= 0) { + eventProxy.dataIndex = this._lastDataIndex; + eventProxy.seriesIndex = this._lastSeriesIndex; + // FIXME May cause double events. + this.zr.handler.dispatchToElement(targetInfo, 'mouseout', originalEvent); + } + elChangedInMouseMove = true; + } + } + else if (eventData != null) { + if (eventData !== this._lastEventData) { + if (this._lastEventData != null) { + eventProxy.eventData = this._lastEventData; + // FIXME May cause double events. + this.zr.handler.dispatchToElement(targetInfo, 'mouseout', originalEvent); + } + elChangedInMouseMove = true; + } + } + this._lastEventData = eventData; + this._lastDataIndex = dataIndex; + this._lastSeriesIndex = seriesIndex; + } + + eventProxy.eventData = eventData; + eventProxy.dataIndex = dataIndex; + eventProxy.seriesIndex = seriesIndex; + + if (eventData != null || (parseInt(dataIndex, 10) >= 0 && parseInt(seriesIndex, 10) >= 0)) { + this.zr.handler.dispatchToElement(targetInfo, eveName, originalEvent); + + if (elChangedInMouseMove) { + this.zr.handler.dispatchToElement(targetInfo, 'mouseover', originalEvent); + } + } +}; + +LayerGL.prototype._dispatchToView = function (eventName, e) { + for (var i = 0; i < this.views.length; i++) { + if (this.views[i].containPoint(e.offsetX, e.offsetY)) { + this.views[i].trigger(eventName, e); + } + } +}; + +__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.util.extend(LayerGL.prototype, __WEBPACK_IMPORTED_MODULE_5_claygl_src_core_mixin_notifier__["a" /* default */]); + +/* harmony default export */ __webpack_exports__["a"] = (LayerGL); + +/***/ }), +/* 110 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/** + * Extend a sub class from base class + * @param {object|Function} makeDefaultOpt default option of this sub class, method of the sub can use this.xxx to access this option + * @param {Function} [initialize] Initialize after the sub class is instantiated + * @param {Object} [proto] Prototype methods/properties of the sub class + * @memberOf clay.core.mixin.extend + * @return {Function} + */ +function derive(makeDefaultOpt, initialize/*optional*/, proto/*optional*/) { + + if (typeof initialize == 'object') { + proto = initialize; + initialize = null; + } + + var _super = this; + + var propList; + if (!(makeDefaultOpt instanceof Function)) { + // Optimize the property iterate if it have been fixed + propList = []; + for (var propName in makeDefaultOpt) { + if (makeDefaultOpt.hasOwnProperty(propName)) { + propList.push(propName); + } + } + } + + var sub = function(options) { + + // call super constructor + _super.apply(this, arguments); + + if (makeDefaultOpt instanceof Function) { + // Invoke makeDefaultOpt each time if it is a function, So we can make sure each + // property in the object will not be shared by mutiple instances + extend(this, makeDefaultOpt.call(this, options)); + } + else { + extendWithPropList(this, makeDefaultOpt, propList); + } + + if (this.constructor === sub) { + // Initialize function will be called in the order of inherit + var initializers = sub.__initializers__; + for (var i = 0; i < initializers.length; i++) { + initializers[i].apply(this, arguments); + } + } + }; + // save super constructor + sub.__super__ = _super; + // Initialize function will be called after all the super constructor is called + if (!_super.__initializers__) { + sub.__initializers__ = []; + } else { + sub.__initializers__ = _super.__initializers__.slice(); + } + if (initialize) { + sub.__initializers__.push(initialize); + } + + var Ctor = function() {}; + Ctor.prototype = _super.prototype; + sub.prototype = new Ctor(); + sub.prototype.constructor = sub; + extend(sub.prototype, proto); + + // extend the derive method as a static method; + sub.extend = _super.extend; + + // DEPCRATED + sub.derive = _super.extend; + + return sub; +} + +function extend(target, source) { + if (!source) { + return; + } + for (var name in source) { + if (source.hasOwnProperty(name)) { + target[name] = source[name]; + } + } +} + +function extendWithPropList(target, source, propList) { + for (var i = 0; i < propList.length; i++) { + var propName = propList[i]; + target[propName] = source[propName]; + } +} + +/** + * @alias clay.core.mixin.extend + * @mixin + */ +/* harmony default export */ __webpack_exports__["a"] = ({ + + extend: derive, + + // DEPCRATED + derive: derive +}); + + +/***/ }), +/* 111 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +var EXTENSION_LIST = [ + 'OES_texture_float', + 'OES_texture_half_float', + 'OES_texture_float_linear', + 'OES_texture_half_float_linear', + 'OES_standard_derivatives', + 'OES_vertex_array_object', + 'OES_element_index_uint', + 'WEBGL_compressed_texture_s3tc', + 'WEBGL_depth_texture', + 'EXT_texture_filter_anisotropic', + 'EXT_shader_texture_lod', + 'WEBGL_draw_buffers', + 'EXT_frag_depth', + 'EXT_sRGB' +]; + +var PARAMETER_NAMES = [ + 'MAX_TEXTURE_SIZE', + 'MAX_CUBE_MAP_TEXTURE_SIZE' +]; + +function GLInfo(_gl) { + var extensions = {}; + var parameters = {}; + + // Get webgl extension + for (var i = 0; i < EXTENSION_LIST.length; i++) { + var extName = EXTENSION_LIST[i]; + createExtension(extName); + } + // Get parameters + for (var i = 0; i < PARAMETER_NAMES.length; i++) { + var name = PARAMETER_NAMES[i]; + parameters[name] = _gl.getParameter(_gl[name]); + } + + this.getExtension = function (name) { + if (!(name in extensions)) { + createExtension(name); + } + return extensions[name]; + }; + + this.getParameter = function (name) { + return parameters[name]; + }; + + this.getMaxJointNumber = function () { + return 15; + }; + + function createExtension(name) { + var ext = _gl.getExtension(name); + if (!ext) { + ext = _gl.getExtension('MOZ_' + name); + } + if (!ext) { + ext = _gl.getExtension('WEBKIT_' + name); + } + extensions[name] = ext; + } +} + +/* harmony default export */ __webpack_exports__["a"] = (GLInfo); + + +/***/ }), +/* 112 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +function get(options) { + + var xhr = new XMLHttpRequest(); + + xhr.open('get', options.url); + // With response type set browser can get and put binary data + // https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest/Sending_and_Receiving_Binary_Data + // Default is text, and it can be set + // arraybuffer, blob, document, json, text + xhr.responseType = options.responseType || 'text'; + + if (options.onprogress) { + //https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest/Using_XMLHttpRequest + xhr.onprogress = function(e) { + if (e.lengthComputable) { + var percent = e.loaded / e.total; + options.onprogress(percent, e.loaded, e.total); + } + else { + options.onprogress(null); + } + }; + } + xhr.onload = function(e) { + if (xhr.status >= 400) { + options.onerror && options.onerror(); + } + else { + options.onload && options.onload(xhr.response); + } + }; + if (options.onerror) { + xhr.onerror = options.onerror; + } + xhr.send(null); +} + +/* harmony default export */ __webpack_exports__["a"] = ({ + get: get +}); + + +/***/ }), +/* 113 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__core_LRU__ = __webpack_require__(69); +/** + * @namespace clay.core.color + */ + + +var colorUtil = {}; + +var kCSSColorTable = { + 'transparent': [0,0,0,0], 'aliceblue': [240,248,255,1], + 'antiquewhite': [250,235,215,1], 'aqua': [0,255,255,1], + 'aquamarine': [127,255,212,1], 'azure': [240,255,255,1], + 'beige': [245,245,220,1], 'bisque': [255,228,196,1], + 'black': [0,0,0,1], 'blanchedalmond': [255,235,205,1], + 'blue': [0,0,255,1], 'blueviolet': [138,43,226,1], + 'brown': [165,42,42,1], 'burlywood': [222,184,135,1], + 'cadetblue': [95,158,160,1], 'chartreuse': [127,255,0,1], + 'chocolate': [210,105,30,1], 'coral': [255,127,80,1], + 'cornflowerblue': [100,149,237,1], 'cornsilk': [255,248,220,1], + 'crimson': [220,20,60,1], 'cyan': [0,255,255,1], + 'darkblue': [0,0,139,1], 'darkcyan': [0,139,139,1], + 'darkgoldenrod': [184,134,11,1], 'darkgray': [169,169,169,1], + 'darkgreen': [0,100,0,1], 'darkgrey': [169,169,169,1], + 'darkkhaki': [189,183,107,1], 'darkmagenta': [139,0,139,1], + 'darkolivegreen': [85,107,47,1], 'darkorange': [255,140,0,1], + 'darkorchid': [153,50,204,1], 'darkred': [139,0,0,1], + 'darksalmon': [233,150,122,1], 'darkseagreen': [143,188,143,1], + 'darkslateblue': [72,61,139,1], 'darkslategray': [47,79,79,1], + 'darkslategrey': [47,79,79,1], 'darkturquoise': [0,206,209,1], + 'darkviolet': [148,0,211,1], 'deeppink': [255,20,147,1], + 'deepskyblue': [0,191,255,1], 'dimgray': [105,105,105,1], + 'dimgrey': [105,105,105,1], 'dodgerblue': [30,144,255,1], + 'firebrick': [178,34,34,1], 'floralwhite': [255,250,240,1], + 'forestgreen': [34,139,34,1], 'fuchsia': [255,0,255,1], + 'gainsboro': [220,220,220,1], 'ghostwhite': [248,248,255,1], + 'gold': [255,215,0,1], 'goldenrod': [218,165,32,1], + 'gray': [128,128,128,1], 'green': [0,128,0,1], + 'greenyellow': [173,255,47,1], 'grey': [128,128,128,1], + 'honeydew': [240,255,240,1], 'hotpink': [255,105,180,1], + 'indianred': [205,92,92,1], 'indigo': [75,0,130,1], + 'ivory': [255,255,240,1], 'khaki': [240,230,140,1], + 'lavender': [230,230,250,1], 'lavenderblush': [255,240,245,1], + 'lawngreen': [124,252,0,1], 'lemonchiffon': [255,250,205,1], + 'lightblue': [173,216,230,1], 'lightcoral': [240,128,128,1], + 'lightcyan': [224,255,255,1], 'lightgoldenrodyellow': [250,250,210,1], + 'lightgray': [211,211,211,1], 'lightgreen': [144,238,144,1], + 'lightgrey': [211,211,211,1], 'lightpink': [255,182,193,1], + 'lightsalmon': [255,160,122,1], 'lightseagreen': [32,178,170,1], + 'lightskyblue': [135,206,250,1], 'lightslategray': [119,136,153,1], + 'lightslategrey': [119,136,153,1], 'lightsteelblue': [176,196,222,1], + 'lightyellow': [255,255,224,1], 'lime': [0,255,0,1], + 'limegreen': [50,205,50,1], 'linen': [250,240,230,1], + 'magenta': [255,0,255,1], 'maroon': [128,0,0,1], + 'mediumaquamarine': [102,205,170,1], 'mediumblue': [0,0,205,1], + 'mediumorchid': [186,85,211,1], 'mediumpurple': [147,112,219,1], + 'mediumseagreen': [60,179,113,1], 'mediumslateblue': [123,104,238,1], + 'mediumspringgreen': [0,250,154,1], 'mediumturquoise': [72,209,204,1], + 'mediumvioletred': [199,21,133,1], 'midnightblue': [25,25,112,1], + 'mintcream': [245,255,250,1], 'mistyrose': [255,228,225,1], + 'moccasin': [255,228,181,1], 'navajowhite': [255,222,173,1], + 'navy': [0,0,128,1], 'oldlace': [253,245,230,1], + 'olive': [128,128,0,1], 'olivedrab': [107,142,35,1], + 'orange': [255,165,0,1], 'orangered': [255,69,0,1], + 'orchid': [218,112,214,1], 'palegoldenrod': [238,232,170,1], + 'palegreen': [152,251,152,1], 'paleturquoise': [175,238,238,1], + 'palevioletred': [219,112,147,1], 'papayawhip': [255,239,213,1], + 'peachpuff': [255,218,185,1], 'peru': [205,133,63,1], + 'pink': [255,192,203,1], 'plum': [221,160,221,1], + 'powderblue': [176,224,230,1], 'purple': [128,0,128,1], + 'red': [255,0,0,1], 'rosybrown': [188,143,143,1], + 'royalblue': [65,105,225,1], 'saddlebrown': [139,69,19,1], + 'salmon': [250,128,114,1], 'sandybrown': [244,164,96,1], + 'seagreen': [46,139,87,1], 'seashell': [255,245,238,1], + 'sienna': [160,82,45,1], 'silver': [192,192,192,1], + 'skyblue': [135,206,235,1], 'slateblue': [106,90,205,1], + 'slategray': [112,128,144,1], 'slategrey': [112,128,144,1], + 'snow': [255,250,250,1], 'springgreen': [0,255,127,1], + 'steelblue': [70,130,180,1], 'tan': [210,180,140,1], + 'teal': [0,128,128,1], 'thistle': [216,191,216,1], + 'tomato': [255,99,71,1], 'turquoise': [64,224,208,1], + 'violet': [238,130,238,1], 'wheat': [245,222,179,1], + 'white': [255,255,255,1], 'whitesmoke': [245,245,245,1], + 'yellow': [255,255,0,1], 'yellowgreen': [154,205,50,1] +}; + +function clampCssByte(i) { // Clamp to integer 0 .. 255. + i = Math.round(i); // Seems to be what Chrome does (vs truncation). + return i < 0 ? 0 : i > 255 ? 255 : i; +} + +function clampCssAngle(i) { // Clamp to integer 0 .. 360. + i = Math.round(i); // Seems to be what Chrome does (vs truncation). + return i < 0 ? 0 : i > 360 ? 360 : i; +} + +function clampCssFloat(f) { // Clamp to float 0.0 .. 1.0. + return f < 0 ? 0 : f > 1 ? 1 : f; +} + +function parseCssInt(str) { // int or percentage. + if (str.length && str.charAt(str.length - 1) === '%') { + return clampCssByte(parseFloat(str) / 100 * 255); + } + return clampCssByte(parseInt(str, 10)); +} + +function parseCssFloat(str) { // float or percentage. + if (str.length && str.charAt(str.length - 1) === '%') { + return clampCssFloat(parseFloat(str) / 100); + } + return clampCssFloat(parseFloat(str)); +} + +function cssHueToRgb(m1, m2, h) { + if (h < 0) { + h += 1; + } + else if (h > 1) { + h -= 1; + } + + if (h * 6 < 1) { + return m1 + (m2 - m1) * h * 6; + } + if (h * 2 < 1) { + return m2; + } + if (h * 3 < 2) { + return m1 + (m2 - m1) * (2/3 - h) * 6; + } + return m1; +} + +function lerpNumber(a, b, p) { + return a + (b - a) * p; +} + +function setRgba(out, r, g, b, a) { + out[0] = r; out[1] = g; out[2] = b; out[3] = a; + return out; +} +function copyRgba(out, a) { + out[0] = a[0]; out[1] = a[1]; out[2] = a[2]; out[3] = a[3]; + return out; +} + +var colorCache = new __WEBPACK_IMPORTED_MODULE_0__core_LRU__["a" /* default */](20); +var lastRemovedArr = null; + +function putToCache(colorStr, rgbaArr) { + // Reuse removed array + if (lastRemovedArr) { + copyRgba(lastRemovedArr, rgbaArr); + } + lastRemovedArr = colorCache.put(colorStr, lastRemovedArr || (rgbaArr.slice())); +} + +/** + * @name clay.core.color.parse + * @param {string} colorStr + * @param {Array.} out + * @return {Array.} + */ +colorUtil.parse = function (colorStr, rgbaArr) { + if (!colorStr) { + return; + } + rgbaArr = rgbaArr || []; + + var cached = colorCache.get(colorStr); + if (cached) { + return copyRgba(rgbaArr, cached); + } + + // colorStr may be not string + colorStr = colorStr + ''; + // Remove all whitespace, not compliant, but should just be more accepting. + var str = colorStr.replace(/ /g, '').toLowerCase(); + + // Color keywords (and transparent) lookup. + if (str in kCSSColorTable) { + copyRgba(rgbaArr, kCSSColorTable[str]); + putToCache(colorStr, rgbaArr); + return rgbaArr; + } + + // #abc and #abc123 syntax. + if (str.charAt(0) === '#') { + if (str.length === 4) { + var iv = parseInt(str.substr(1), 16); // TODO(deanm): Stricter parsing. + if (!(iv >= 0 && iv <= 0xfff)) { + setRgba(rgbaArr, 0, 0, 0, 1); + return; // Covers NaN. + } + setRgba(rgbaArr, + ((iv & 0xf00) >> 4) | ((iv & 0xf00) >> 8), + (iv & 0xf0) | ((iv & 0xf0) >> 4), + (iv & 0xf) | ((iv & 0xf) << 4), + 1 + ); + putToCache(colorStr, rgbaArr); + return rgbaArr; + } + else if (str.length === 7) { + var iv = parseInt(str.substr(1), 16); // TODO(deanm): Stricter parsing. + if (!(iv >= 0 && iv <= 0xffffff)) { + setRgba(rgbaArr, 0, 0, 0, 1); + return; // Covers NaN. + } + setRgba(rgbaArr, + (iv & 0xff0000) >> 16, + (iv & 0xff00) >> 8, + iv & 0xff, + 1 + ); + putToCache(colorStr, rgbaArr); + return rgbaArr; + } + + return; + } + var op = str.indexOf('('), ep = str.indexOf(')'); + if (op !== -1 && ep + 1 === str.length) { + var fname = str.substr(0, op); + var params = str.substr(op + 1, ep - (op + 1)).split(','); + var alpha = 1; // To allow case fallthrough. + switch (fname) { + case 'rgba': + if (params.length !== 4) { + setRgba(rgbaArr, 0, 0, 0, 1); + return; + } + alpha = parseCssFloat(params.pop()); // jshint ignore:line + // Fall through. + case 'rgb': + if (params.length !== 3) { + setRgba(rgbaArr, 0, 0, 0, 1); + return; + } + setRgba(rgbaArr, + parseCssInt(params[0]), + parseCssInt(params[1]), + parseCssInt(params[2]), + alpha + ); + putToCache(colorStr, rgbaArr); + return rgbaArr; + case 'hsla': + if (params.length !== 4) { + setRgba(rgbaArr, 0, 0, 0, 1); + return; + } + params[3] = parseCssFloat(params[3]); + hsla2rgba(params, rgbaArr); + putToCache(colorStr, rgbaArr); + return rgbaArr; + case 'hsl': + if (params.length !== 3) { + setRgba(rgbaArr, 0, 0, 0, 1); + return; + } + hsla2rgba(params, rgbaArr); + putToCache(colorStr, rgbaArr); + return rgbaArr; + default: + return; + } + } + + setRgba(rgbaArr, 0, 0, 0, 1); + return; +}; + +colorUtil.parseToFloat = function (colorStr, rgbaArr) { + rgbaArr = colorUtil.parse(colorStr, rgbaArr); + if (!rgbaArr) { + return; + } + rgbaArr[0] /= 255; + rgbaArr[1] /= 255; + rgbaArr[2] /= 255; + return rgbaArr; +} + +/** + * @name clay.core.color.hsla2rgba + * @param {Array.} hsla + * @param {Array.} rgba + * @return {Array.} rgba + */ +function hsla2rgba(hsla, rgba) { + var h = (((parseFloat(hsla[0]) % 360) + 360) % 360) / 360; // 0 .. 1 + // NOTE(deanm): According to the CSS spec s/l should only be + // percentages, but we don't bother and let float or percentage. + var s = parseCssFloat(hsla[1]); + var l = parseCssFloat(hsla[2]); + var m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s; + var m1 = l * 2 - m2; + + rgba = rgba || []; + setRgba(rgba, + clampCssByte(cssHueToRgb(m1, m2, h + 1 / 3) * 255), + clampCssByte(cssHueToRgb(m1, m2, h) * 255), + clampCssByte(cssHueToRgb(m1, m2, h - 1 / 3) * 255), + 1 + ); + + if (hsla.length === 4) { + rgba[3] = hsla[3]; + } + + return rgba; +} + +/** + * @name clay.core.color.rgba2hsla + * @param {Array.} rgba + * @return {Array.} hsla + */ +function rgba2hsla(rgba) { + if (!rgba) { + return; + } + + // RGB from 0 to 255 + var R = rgba[0] / 255; + var G = rgba[1] / 255; + var B = rgba[2] / 255; + + var vMin = Math.min(R, G, B); // Min. value of RGB + var vMax = Math.max(R, G, B); // Max. value of RGB + var delta = vMax - vMin; // Delta RGB value + + var L = (vMax + vMin) / 2; + var H; + var S; + // HSL results from 0 to 1 + if (delta === 0) { + H = 0; + S = 0; + } + else { + if (L < 0.5) { + S = delta / (vMax + vMin); + } + else { + S = delta / (2 - vMax - vMin); + } + + var deltaR = (((vMax - R) / 6) + (delta / 2)) / delta; + var deltaG = (((vMax - G) / 6) + (delta / 2)) / delta; + var deltaB = (((vMax - B) / 6) + (delta / 2)) / delta; + + if (R === vMax) { + H = deltaB - deltaG; + } + else if (G === vMax) { + H = (1 / 3) + deltaR - deltaB; + } + else if (B === vMax) { + H = (2 / 3) + deltaG - deltaR; + } + + if (H < 0) { + H += 1; + } + + if (H > 1) { + H -= 1; + } + } + + var hsla = [H * 360, S, L]; + + if (rgba[3] != null) { + hsla.push(rgba[3]); + } + + return hsla; +} + +/** + * @name clay.core.color.lift + * @param {string} color + * @param {number} level + * @return {string} + */ +colorUtil.lift = function (color, level) { + var colorArr = colorUtil.parse(color); + if (colorArr) { + for (var i = 0; i < 3; i++) { + if (level < 0) { + colorArr[i] = colorArr[i] * (1 - level) | 0; + } + else { + colorArr[i] = ((255 - colorArr[i]) * level + colorArr[i]) | 0; + } + } + return colorUtil.stringify(colorArr, colorArr.length === 4 ? 'rgba' : 'rgb'); + } +} + +/** + * @name clay.core.color.toHex + * @param {string} color + * @return {string} + */ +colorUtil.toHex = function (color) { + var colorArr = colorUtil.parse(color); + if (colorArr) { + return ((1 << 24) + (colorArr[0] << 16) + (colorArr[1] << 8) + (+colorArr[2])).toString(16).slice(1); + } +}; + +/** + * Map value to color. Faster than lerp methods because color is represented by rgba array. + * @name clay.core.color + * @param {number} normalizedValue A float between 0 and 1. + * @param {Array.>} colors List of rgba color array + * @param {Array.} [out] Mapped gba color array + * @return {Array.} will be null/undefined if input illegal. + */ +colorUtil.fastLerp = function (normalizedValue, colors, out) { + if (!(colors && colors.length) + || !(normalizedValue >= 0 && normalizedValue <= 1) + ) { + return; + } + + out = out || []; + + var value = normalizedValue * (colors.length - 1); + var leftIndex = Math.floor(value); + var rightIndex = Math.ceil(value); + var leftColor = colors[leftIndex]; + var rightColor = colors[rightIndex]; + var dv = value - leftIndex; + out[0] = clampCssByte(lerpNumber(leftColor[0], rightColor[0], dv)); + out[1] = clampCssByte(lerpNumber(leftColor[1], rightColor[1], dv)); + out[2] = clampCssByte(lerpNumber(leftColor[2], rightColor[2], dv)); + out[3] = clampCssFloat(lerpNumber(leftColor[3], rightColor[3], dv)); + + return out; +} + +colorUtil.fastMapToColor = colorUtil.fastLerp; + +/** + * @param {number} normalizedValue A float between 0 and 1. + * @param {Array.} colors Color list. + * @param {boolean=} fullOutput Default false. + * @return {(string|Object)} Result color. If fullOutput, + * return {color: ..., leftIndex: ..., rightIndex: ..., value: ...}, + */ +colorUtil.lerp = function (normalizedValue, colors, fullOutput) { + if (!(colors && colors.length) + || !(normalizedValue >= 0 && normalizedValue <= 1) + ) { + return; + } + + var value = normalizedValue * (colors.length - 1); + var leftIndex = Math.floor(value); + var rightIndex = Math.ceil(value); + var leftColor = colorUtil.parse(colors[leftIndex]); + var rightColor = colorUtil.parse(colors[rightIndex]); + var dv = value - leftIndex; + + var color = colorUtil.stringify( + [ + clampCssByte(lerpNumber(leftColor[0], rightColor[0], dv)), + clampCssByte(lerpNumber(leftColor[1], rightColor[1], dv)), + clampCssByte(lerpNumber(leftColor[2], rightColor[2], dv)), + clampCssFloat(lerpNumber(leftColor[3], rightColor[3], dv)) + ], + 'rgba' + ); + + return fullOutput + ? { + color: color, + leftIndex: leftIndex, + rightIndex: rightIndex, + value: value + } + : color; +} + +/** + * @deprecated + */ +colorUtil.mapToColor = colorUtil.lerp; + +/** + * @name clay.core.color + * @param {string} color + * @param {number=} h 0 ~ 360, ignore when null. + * @param {number=} s 0 ~ 1, ignore when null. + * @param {number=} l 0 ~ 1, ignore when null. + * @return {string} Color string in rgba format. + */ +colorUtil.modifyHSL = function (color, h, s, l) { + color = colorUtil.parse(color); + + if (color) { + color = rgba2hsla(color); + h != null && (color[0] = clampCssAngle(h)); + s != null && (color[1] = parseCssFloat(s)); + l != null && (color[2] = parseCssFloat(l)); + + return colorUtil.stringify(hsla2rgba(color), 'rgba'); + } +} + +/** + * @param {string} color + * @param {number=} alpha 0 ~ 1 + * @return {string} Color string in rgba format. + */ +colorUtil.modifyAlpha = function (color, alpha) { + color = colorUtil.parse(color); + + if (color && alpha != null) { + color[3] = clampCssFloat(alpha); + return colorUtil.stringify(color, 'rgba'); + } +} + +/** + * @param {Array.} arrColor like [12,33,44,0.4] + * @param {string} type 'rgba', 'hsva', ... + * @return {string} Result color. (If input illegal, return undefined). + */ +colorUtil.stringify = function (arrColor, type) { + if (!arrColor || !arrColor.length) { + return; + } + var colorStr = arrColor[0] + ',' + arrColor[1] + ',' + arrColor[2]; + if (type === 'rgba' || type === 'hsva' || type === 'hsla') { + colorStr += ',' + arrColor[3]; + } + return type + '(' + colorStr + ')'; +}; + + + +/* harmony default export */ __webpack_exports__["a"] = (colorUtil); + +/***/ }), +/* 114 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/** + * Simple double linked list. Compared with array, it has O(1) remove operation. + * @constructor + * @alias clay.core.LinkedList + */ +var LinkedList = function () { + + /** + * @type {clay.core.LinkedList.Entry} + */ + this.head = null; + + /** + * @type {clay.core.LinkedList.Entry} + */ + this.tail = null; + + this._length = 0; +}; + +/** + * Insert a new value at the tail + * @param {} val + * @return {clay.core.LinkedList.Entry} + */ +LinkedList.prototype.insert = function (val) { + var entry = new LinkedList.Entry(val); + this.insertEntry(entry); + return entry; +}; + +/** + * Insert a new value at idx + * @param {number} idx + * @param {} val + * @return {clay.core.LinkedList.Entry} + */ +LinkedList.prototype.insertAt = function (idx, val) { + if (idx < 0) { + return; + } + var next = this.head; + var cursor = 0; + while (next && cursor != idx) { + next = next.next; + cursor++; + } + if (next) { + var entry = new LinkedList.Entry(val); + var prev = next.prev; + if (!prev) { //next is head + this.head = entry; + } + else { + prev.next = entry; + entry.prev = prev; + } + entry.next = next; + next.prev = entry; + } + else { + this.insert(val); + } +}; + +LinkedList.prototype.insertBeforeEntry = function (val, next) { + var entry = new LinkedList.Entry(val); + var prev = next.prev; + if (!prev) { //next is head + this.head = entry; + } + else { + prev.next = entry; + entry.prev = prev; + } + entry.next = next; + next.prev = entry; + + this._length++; +}; + +/** + * Insert an entry at the tail + * @param {clay.core.LinkedList.Entry} entry + */ +LinkedList.prototype.insertEntry = function (entry) { + if (!this.head) { + this.head = this.tail = entry; + } + else { + this.tail.next = entry; + entry.prev = this.tail; + this.tail = entry; + } + this._length++; +}; + +/** + * Remove entry. + * @param {clay.core.LinkedList.Entry} entry + */ +LinkedList.prototype.remove = function (entry) { + var prev = entry.prev; + var next = entry.next; + if (prev) { + prev.next = next; + } + else { + // Is head + this.head = next; + } + if (next) { + next.prev = prev; + } + else { + // Is tail + this.tail = prev; + } + entry.next = entry.prev = null; + this._length--; +}; + +/** + * Remove entry at index. + * @param {number} idx + * @return {} + */ +LinkedList.prototype.removeAt = function (idx) { + if (idx < 0) { + return; + } + var curr = this.head; + var cursor = 0; + while (curr && cursor != idx) { + curr = curr.next; + cursor++; + } + if (curr) { + this.remove(curr); + return curr.value; + } +}; +/** + * Get head value + * @return {} + */ +LinkedList.prototype.getHead = function () { + if (this.head) { + return this.head.value; + } +}; +/** + * Get tail value + * @return {} + */ +LinkedList.prototype.getTail = function () { + if (this.tail) { + return this.tail.value; + } +}; +/** + * Get value at idx + * @param {number} idx + * @return {} + */ +LinkedList.prototype.getAt = function (idx) { + if (idx < 0) { + return; + } + var curr = this.head; + var cursor = 0; + while (curr && cursor != idx) { + curr = curr.next; + cursor++; + } + return curr.value; +}; + +/** + * @param {} value + * @return {number} + */ +LinkedList.prototype.indexOf = function (value) { + var curr = this.head; + var cursor = 0; + while (curr) { + if (curr.value === value) { + return cursor; + } + curr = curr.next; + cursor++; + } +}; + +/** + * @return {number} + */ +LinkedList.prototype.length = function () { + return this._length; +}; + +/** + * If list is empty + */ +LinkedList.prototype.isEmpty = function () { + return this._length === 0; +}; + +/** + * @param {Function} cb + * @param {} context + */ +LinkedList.prototype.forEach = function (cb, context) { + var curr = this.head; + var idx = 0; + var haveContext = typeof(context) != 'undefined'; + while (curr) { + if (haveContext) { + cb.call(context, curr.value, idx); + } + else { + cb(curr.value, idx); + } + curr = curr.next; + idx++; + } +}; + +/** + * Clear the list + */ +LinkedList.prototype.clear = function () { + this.tail = this.head = null; + this._length = 0; +}; + +/** + * @constructor + * @param {} val + */ +LinkedList.Entry = function (val) { + /** + * @type {} + */ + this.value = val; + + /** + * @type {clay.core.LinkedList.Entry} + */ + this.next = null; + + /** + * @type {clay.core.LinkedList.Entry} + */ + this.prev = null; +}; + +/* harmony default export */ __webpack_exports__["a"] = (LinkedList); + + +/***/ }), +/* 115 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__GLProgram__ = __webpack_require__(116); + + +var loopRegex = /for\s*?\(int\s*?_idx_\s*\=\s*([\w-]+)\;\s*_idx_\s*<\s*([\w-]+);\s*_idx_\s*\+\+\s*\)\s*\{\{([\s\S]+?)(?=\}\})\}\}/g; + +function unrollLoop(shaderStr, defines, lightsNumbers) { + // Loop unroll from three.js, https://github.com/mrdoob/three.js/blob/master/src/renderers/webgl/WebGLProgram.js#L175 + // In some case like shadowMap in loop use 'i' to index value much slower. + + // Loop use _idx_ and increased with _idx_++ will be unrolled + // Use {{ }} to match the pair so the if statement will not be affected + // Write like following + // for (int _idx_ = 0; _idx_ < 4; _idx_++) {{ + // vec3 color = texture2D(textures[_idx_], uv).rgb; + // }} + function replace(match, start, end, snippet) { + var unroll = ''; + // Try to treat as define + if (isNaN(start)) { + if (start in defines) { + start = defines[start]; + } + else { + start = lightNumberDefines[start]; + } + } + if (isNaN(end)) { + if (end in defines) { + end = defines[end]; + } + else { + end = lightNumberDefines[end]; + } + } + // TODO Error checking + + for (var idx = parseInt(start); idx < parseInt(end); idx++) { + // PENDING Add scope? + unroll += '{' + + snippet + .replace(/float\s*\(\s*_idx_\s*\)/g, idx.toFixed(1)) + .replace(/_idx_/g, idx) + + '}'; + } + + return unroll; + } + + var lightNumberDefines = {}; + for (var lightType in lightsNumbers) { + lightNumberDefines[lightType + '_COUNT'] = lightsNumbers[lightType]; + } + return shaderStr.replace(loopRegex, replace); +} + +function getDefineCode(defines, lightsNumbers, enabledTextures) { + var defineStr = []; + if (lightsNumbers) { + for (var lightType in lightsNumbers) { + var count = lightsNumbers[lightType]; + if (count > 0) { + defineStr.push('#define ' + lightType.toUpperCase() + '_COUNT ' + count); + } + } + } + if (enabledTextures) { + for (var i = 0; i < enabledTextures.length; i++) { + var symbol = enabledTextures[i]; + defineStr.push('#define ' + symbol.toUpperCase() + '_ENABLED'); + } + } + // Custom Defines + for (var symbol in defines) { + var value = defines[symbol]; + if (value === null) { + defineStr.push('#define ' + symbol); + } + else{ + defineStr.push('#define ' + symbol + ' ' + value.toString()); + } + } + return defineStr.join('\n'); +} + +function getExtensionCode(exts) { + // Extension declaration must before all non-preprocessor codes + // TODO vertex ? extension enum ? + var extensionStr = []; + for (var i = 0; i < exts.length; i++) { + extensionStr.push('#extension GL_' + exts[i] + ' : enable'); + } + return extensionStr.join('\n'); +} + +function getPrecisionCode(precision) { + return ['precision', precision, 'float'].join(' ') + ';\n' + + ['precision', precision, 'int'].join(' ') + ';\n' + // depth texture may have precision problem on iOS device. + + ['precision', precision, 'sampler2D'].join(' ') + ';\n'; +} + +function ProgramManager(renderer) { + this._renderer = renderer; + this._cache = {}; +} + +ProgramManager.prototype.getProgram = function (renderable, material, scene) { + var cache = this._cache; + + var isSkinnedMesh = renderable.isSkinnedMesh && renderable.isSkinnedMesh(); + var key = 's' + material.shader.shaderID + 'm' + material.getProgramKey(); + if (scene) { + key += 'se' + scene.getProgramKey(renderable.lightGroup); + } + if (isSkinnedMesh) { + key += ',' + renderable.joints.length; + } + var program = cache[key]; + + if (program) { + return program; + } + + var lightsNumbers = scene ? scene.getLightsNumbers(renderable.lightGroup) : {}; + var renderer = this._renderer; + var _gl = renderer.gl; + var enabledTextures = material.getEnabledTextures(); + var skinDefineCode = ''; + if (isSkinnedMesh) { + var skinDefines = { + SKINNING: null, + JOINT_COUNT: renderable.joints.length + }; + if (renderable.joints.length > renderer.getMaxJointNumber()) { + skinDefines.USE_SKIN_MATRICES_TEXTURE = null; + } + // TODO Add skinning code? + skinDefineCode = '\n' + getDefineCode(skinDefines) + '\n'; + } + // TODO Optimize key generation + // VERTEX + var vertexDefineStr = skinDefineCode + getDefineCode(material.vertexDefines, lightsNumbers, enabledTextures); + // FRAGMENT + var fragmentDefineStr = skinDefineCode + getDefineCode(material.fragmentDefines, lightsNumbers, enabledTextures); + + var vertexCode = vertexDefineStr + '\n' + material.shader.vertex; + + var extensions = [ + 'OES_standard_derivatives', + 'EXT_shader_texture_lod' + ].filter(function (ext) { + return renderer.getGLExtension(ext) != null; + }); + + if (extensions.indexOf('EXT_shader_texture_lod') >= 0) { + fragmentDefineStr += '\n#define SUPPORT_TEXTURE_LOD'; + } + if (extensions.indexOf('OES_standard_derivatives') >= 0) { + fragmentDefineStr += '\n#define SUPPORT_STANDARD_DERIVATIVES'; + } + + var fragmentCode = getExtensionCode(extensions) + '\n' + + getPrecisionCode(material.precision) + '\n' + + fragmentDefineStr + '\n' + + material.shader.fragment; + + var finalVertexCode = unrollLoop(vertexCode, material.vertexDefines, lightsNumbers); + var finalFragmentCode = unrollLoop(fragmentCode, material.fragmentDefines, lightsNumbers); + + var program = new __WEBPACK_IMPORTED_MODULE_0__GLProgram__["a" /* default */](); + program.uniformSemantics = material.shader.uniformSemantics; + program.attributes = material.shader.attributes; + var errorMsg = program.buildProgram(_gl, material.shader, finalVertexCode, finalFragmentCode); + program.__error = errorMsg; + + cache[key] = program; + + return program; +}; + +/* harmony default export */ __webpack_exports__["a"] = (ProgramManager); + +/***/ }), +/* 116 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__core_vendor__ = __webpack_require__(14); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__core_Base__ = __webpack_require__(7); + + + +var SHADER_STATE_TO_ENABLE = 1; +var SHADER_STATE_KEEP_ENABLE = 2; +var SHADER_STATE_PENDING = 3; + +// Enable attribute operation is global to all programs +// Here saved the list of all enabled attribute index +// http://www.mjbshaw.com/2013/03/webgl-fixing-invalidoperation.html +var enabledAttributeList = {}; + +// some util functions +function addLineNumbers(string) { + var chunks = string.split('\n'); + for (var i = 0, il = chunks.length; i < il; i ++) { + // Chrome reports shader errors on lines + // starting counting from 1 + chunks[i] = (i + 1) + ': ' + chunks[i]; + } + return chunks.join('\n'); +} + +// Return true or error msg if error happened +function checkShaderErrorMsg(_gl, shader, shaderString) { + if (!_gl.getShaderParameter(shader, _gl.COMPILE_STATUS)) { + return [_gl.getShaderInfoLog(shader), addLineNumbers(shaderString)].join('\n'); + } +} + +var tmpFloat32Array16 = new __WEBPACK_IMPORTED_MODULE_0__core_vendor__["a" /* default */].Float32Array(16); + +var GLProgram = __WEBPACK_IMPORTED_MODULE_1__core_Base__["a" /* default */].extend({ + + uniformSemantics: {}, + attributes: {} + +}, function () { + this._locations = {}; + + this._textureSlot = 0; + + this._program = null; +}, { + + bind: function (renderer) { + this._textureSlot = 0; + renderer.gl.useProgram(this._program); + }, + + hasUniform: function (symbol) { + var location = this._locations[symbol]; + return location !== null && location !== undefined; + }, + + useTextureSlot: function (renderer, texture, slot) { + if (texture) { + renderer.gl.activeTexture(renderer.gl.TEXTURE0 + slot); + // Maybe texture is not loaded yet; + if (texture.isRenderable()) { + texture.bind(renderer); + } + else { + // Bind texture to null + texture.unbind(renderer); + } + } + }, + + currentTextureSlot: function () { + return this._textureSlot; + }, + + resetTextureSlot: function (slot) { + this._textureSlot = slot || 0; + }, + + takeCurrentTextureSlot: function (renderer, texture) { + var textureSlot = this._textureSlot; + + this.useTextureSlot(renderer, texture, textureSlot); + + this._textureSlot++; + + return textureSlot; + }, + + setUniform: function (_gl, type, symbol, value) { + var locationMap = this._locations; + var location = locationMap[symbol]; + // Uniform is not existed in the shader + if (location === null || location === undefined) { + return false; + } + + switch (type) { + case 'm4': + if (!(value instanceof Float32Array)) { + // Use Float32Array is much faster than array when uniformMatrix4fv. + for (var i = 0; i < value.length; i++) { + tmpFloat32Array16[i] = value[i]; + } + value = tmpFloat32Array16; + } + _gl.uniformMatrix4fv(location, false, value); + break; + case '2i': + _gl.uniform2i(location, value[0], value[1]); + break; + case '2f': + _gl.uniform2f(location, value[0], value[1]); + break; + case '3i': + _gl.uniform3i(location, value[0], value[1], value[2]); + break; + case '3f': + _gl.uniform3f(location, value[0], value[1], value[2]); + break; + case '4i': + _gl.uniform4i(location, value[0], value[1], value[2], value[3]); + break; + case '4f': + _gl.uniform4f(location, value[0], value[1], value[2], value[3]); + break; + case '1i': + _gl.uniform1i(location, value); + break; + case '1f': + _gl.uniform1f(location, value); + break; + case '1fv': + _gl.uniform1fv(location, value); + break; + case '1iv': + _gl.uniform1iv(location, value); + break; + case '2iv': + _gl.uniform2iv(location, value); + break; + case '2fv': + _gl.uniform2fv(location, value); + break; + case '3iv': + _gl.uniform3iv(location, value); + break; + case '3fv': + _gl.uniform3fv(location, value); + break; + case '4iv': + _gl.uniform4iv(location, value); + break; + case '4fv': + _gl.uniform4fv(location, value); + break; + case 'm2': + case 'm2v': + _gl.uniformMatrix2fv(location, false, value); + break; + case 'm3': + case 'm3v': + _gl.uniformMatrix3fv(location, false, value); + break; + case 'm4v': + // Raw value + if (Array.isArray(value) && Array.isArray(value[0])) { + var array = new __WEBPACK_IMPORTED_MODULE_0__core_vendor__["a" /* default */].Float32Array(value.length * 16); + var cursor = 0; + for (var i = 0; i < value.length; i++) { + var item = value[i]; + for (var j = 0; j < 16; j++) { + array[cursor++] = item[j]; + } + } + _gl.uniformMatrix4fv(location, false, array); + } + else { // ArrayBufferView + _gl.uniformMatrix4fv(location, false, value); + } + break; + } + return true; + }, + + setUniformOfSemantic: function (_gl, semantic, val) { + var semanticInfo = this.uniformSemantics[semantic]; + if (semanticInfo) { + return this.setUniform(_gl, semanticInfo.type, semanticInfo.symbol, val); + } + return false; + }, + + // Used for creating VAO + // Enable the attributes passed in and disable the rest + // Example Usage: + // enableAttributes(renderer, ["position", "texcoords"]) + enableAttributes: function (renderer, attribList, vao) { + var _gl = renderer.gl; + var program = this._program; + + var locationMap = this._locations; + + var enabledAttributeListInContext; + if (vao) { + enabledAttributeListInContext = vao.__enabledAttributeList; + } + else { + enabledAttributeListInContext = enabledAttributeList[renderer.__uid__]; + } + if (!enabledAttributeListInContext) { + // In vertex array object context + // PENDING Each vao object needs to enable attributes again? + if (vao) { + enabledAttributeListInContext + = vao.__enabledAttributeList + = []; + } + else { + enabledAttributeListInContext + = enabledAttributeList[renderer.__uid__] + = []; + } + } + var locationList = []; + for (var i = 0; i < attribList.length; i++) { + var symbol = attribList[i]; + if (!this.attributes[symbol]) { + locationList[i] = -1; + continue; + } + var location = locationMap[symbol]; + if (location == null) { + location = _gl.getAttribLocation(program, symbol); + // Attrib location is a number from 0 to ... + if (location === -1) { + locationList[i] = -1; + continue; + } + locationMap[symbol] = location; + } + locationList[i] = location; + + if (!enabledAttributeListInContext[location]) { + enabledAttributeListInContext[location] = SHADER_STATE_TO_ENABLE; + } + else { + enabledAttributeListInContext[location] = SHADER_STATE_KEEP_ENABLE; + } + } + + for (var i = 0; i < enabledAttributeListInContext.length; i++) { + switch(enabledAttributeListInContext[i]){ + case SHADER_STATE_TO_ENABLE: + _gl.enableVertexAttribArray(i); + enabledAttributeListInContext[i] = SHADER_STATE_PENDING; + break; + case SHADER_STATE_KEEP_ENABLE: + enabledAttributeListInContext[i] = SHADER_STATE_PENDING; + break; + // Expired + case SHADER_STATE_PENDING: + _gl.disableVertexAttribArray(i); + enabledAttributeListInContext[i] = 0; + break; + } + } + + return locationList; + }, + + buildProgram: function (_gl, shader, vertexShaderCode, fragmentShaderCode) { + var vertexShader = _gl.createShader(_gl.VERTEX_SHADER); + var program = _gl.createProgram(); + + _gl.shaderSource(vertexShader, vertexShaderCode); + _gl.compileShader(vertexShader); + + var fragmentShader = _gl.createShader(_gl.FRAGMENT_SHADER); + _gl.shaderSource(fragmentShader, fragmentShaderCode); + _gl.compileShader(fragmentShader); + + var msg = checkShaderErrorMsg(_gl, vertexShader, vertexShaderCode); + if (msg) { + return msg; + } + msg = checkShaderErrorMsg(_gl, fragmentShader, fragmentShaderCode); + if (msg) { + return msg; + } + + _gl.attachShader(program, vertexShader); + _gl.attachShader(program, fragmentShader); + // Force the position bind to location 0; + if (shader.attributeSemantics['POSITION']) { + _gl.bindAttribLocation(program, 0, shader.attributeSemantics['POSITION'].symbol); + } + else { + // Else choose an attribute and bind to location 0; + var keys = Object.keys(this.attributes); + _gl.bindAttribLocation(program, 0, keys[0]); + } + + _gl.linkProgram(program); + + if (!_gl.getProgramParameter(program, _gl.LINK_STATUS)) { + return 'Could not link program\n' + _gl.getProgramInfoLog(program); + } + + // Cache uniform locations + for (var i = 0; i < shader.uniforms.length; i++) { + var uniformSymbol = shader.uniforms[i]; + this._locations[uniformSymbol] = _gl.getUniformLocation(program, uniformSymbol); + } + + _gl.deleteShader(vertexShader); + _gl.deleteShader(fragmentShader); + + this._program = program; + + // Save code. + this.vertexCode = vertexShaderCode; + this.fragmentCode = fragmentShaderCode; + } +}); + +/* harmony default export */ __webpack_exports__["a"] = (GLProgram); + +/***/ }), +/* 117 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__core_Base__ = __webpack_require__(7); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__math_Ray__ = __webpack_require__(54); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__math_Vector2__ = __webpack_require__(26); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__math_Vector3__ = __webpack_require__(3); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4__math_Matrix4__ = __webpack_require__(9); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_5__Renderable__ = __webpack_require__(72); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_6__core_glenum__ = __webpack_require__(11); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_7__glmatrix_vec3__ = __webpack_require__(12); + + + + + + + + + +/** + * @constructor clay.picking.RayPicking + * @extends clay.core.Base + */ +var RayPicking = __WEBPACK_IMPORTED_MODULE_0__core_Base__["a" /* default */].extend(/** @lends clay.picking.RayPicking# */{ + /** + * Target scene + * @type {clay.Scene} + */ + scene: null, + /** + * Target camera + * @type {clay.Camera} + */ + camera: null, + /** + * Target renderer + * @type {clay.Renderer} + */ + renderer: null +}, function () { + this._ray = new __WEBPACK_IMPORTED_MODULE_1__math_Ray__["a" /* default */](); + this._ndc = new __WEBPACK_IMPORTED_MODULE_2__math_Vector2__["a" /* default */](); +}, +/** @lends clay.picking.RayPicking.prototype */ +{ + + /** + * Pick the nearest intersection object in the scene + * @param {number} x Mouse position x + * @param {number} y Mouse position y + * @param {boolean} [forcePickAll=false] ignore ignorePicking + * @return {clay.picking.RayPicking~Intersection} + */ + pick: function (x, y, forcePickAll) { + var out = this.pickAll(x, y, [], forcePickAll); + return out[0] || null; + }, + + /** + * Pick all intersection objects, wich will be sorted from near to far + * @param {number} x Mouse position x + * @param {number} y Mouse position y + * @param {Array} [output] + * @param {boolean} [forcePickAll=false] ignore ignorePicking + * @return {Array.} + */ + pickAll: function (x, y, output, forcePickAll) { + this.renderer.screenToNDC(x, y, this._ndc); + this.camera.castRay(this._ndc, this._ray); + + output = output || []; + + this._intersectNode(this.scene, output, forcePickAll || false); + + output.sort(this._intersectionCompareFunc); + + return output; + }, + + _intersectNode: function (node, out, forcePickAll) { + if ((node instanceof __WEBPACK_IMPORTED_MODULE_5__Renderable__["a" /* default */]) && node.isRenderable()) { + if ((!node.ignorePicking || forcePickAll) + && ( + // Only triangle mesh support ray picking + (node.mode === __WEBPACK_IMPORTED_MODULE_6__core_glenum__["a" /* default */].TRIANGLES && node.geometry.isUseIndices()) + // Or if geometry has it's own pickByRay, pick, implementation + || node.geometry.pickByRay + || node.geometry.pick + ) + ) { + this._intersectRenderable(node, out); + } + } + for (var i = 0; i < node._children.length; i++) { + this._intersectNode(node._children[i], out, forcePickAll); + } + }, + + _intersectRenderable: (function () { + + var v1 = new __WEBPACK_IMPORTED_MODULE_3__math_Vector3__["a" /* default */](); + var v2 = new __WEBPACK_IMPORTED_MODULE_3__math_Vector3__["a" /* default */](); + var v3 = new __WEBPACK_IMPORTED_MODULE_3__math_Vector3__["a" /* default */](); + var ray = new __WEBPACK_IMPORTED_MODULE_1__math_Ray__["a" /* default */](); + var worldInverse = new __WEBPACK_IMPORTED_MODULE_4__math_Matrix4__["a" /* default */](); + + return function (renderable, out) { + + var isSkinnedMesh = renderable.isSkinnedMesh(); + ray.copy(this._ray); + __WEBPACK_IMPORTED_MODULE_4__math_Matrix4__["a" /* default */].invert(worldInverse, renderable.worldTransform); + + // Skinned mesh will ignore the world transform. + if (!isSkinnedMesh) { + ray.applyTransform(worldInverse); + } + + var geometry = renderable.geometry; + + var bbox = isSkinnedMesh ? renderable.skeleton.boundingBox : geometry.boundingBox; + + if (bbox && !ray.intersectBoundingBox(bbox)) { + return; + } + // Use user defined picking algorithm + if (geometry.pick) { + geometry.pick( + this._ndc.x, this._ndc.y, + this.renderer, + this.camera, + renderable, out + ); + return; + } + // Use user defined ray picking algorithm + else if (geometry.pickByRay) { + geometry.pickByRay(ray, renderable, out); + return; + } + + var cullBack = (renderable.cullFace === __WEBPACK_IMPORTED_MODULE_6__core_glenum__["a" /* default */].BACK && renderable.frontFace === __WEBPACK_IMPORTED_MODULE_6__core_glenum__["a" /* default */].CCW) + || (renderable.cullFace === __WEBPACK_IMPORTED_MODULE_6__core_glenum__["a" /* default */].FRONT && renderable.frontFace === __WEBPACK_IMPORTED_MODULE_6__core_glenum__["a" /* default */].CW); + + var point; + var indices = geometry.indices; + var positionAttr = geometry.attributes.position; + var weightAttr = geometry.attributes.weight; + var jointAttr = geometry.attributes.joint; + var skinMatricesArray; + var skinMatrices = []; + // Check if valid. + if (!positionAttr || !positionAttr.value || !indices) { + return; + } + if (isSkinnedMesh) { + skinMatricesArray = renderable.skeleton.getSubSkinMatrices(renderable.__uid__, renderable.joints); + for (var i = 0; i < renderable.joints.length; i++) { + skinMatrices[i] = skinMatrices[i] || []; + for (var k = 0; k < 16; k++) { + skinMatrices[i][k] = skinMatricesArray[i * 16 + k]; + } + } + var pos = []; + var weight = []; + var joint = []; + var skinnedPos = []; + var tmp = []; + var skinnedPositionAttr = geometry.attributes.skinnedPosition; + if (!skinnedPositionAttr || !skinnedPositionAttr.value) { + geometry.createAttribute('skinnedPosition', 'f', 3); + skinnedPositionAttr = geometry.attributes.skinnedPosition; + skinnedPositionAttr.init(geometry.vertexCount); + } + for (var i = 0; i < geometry.vertexCount; i++) { + positionAttr.get(i, pos); + weightAttr.get(i, weight); + jointAttr.get(i, joint); + weight[3] = 1 - weight[0] - weight[1] - weight[2]; + __WEBPACK_IMPORTED_MODULE_7__glmatrix_vec3__["a" /* default */].set(skinnedPos, 0, 0, 0); + for (var k = 0; k < 4; k++) { + if (joint[k] >= 0 && weight[k] > 1e-4) { + __WEBPACK_IMPORTED_MODULE_7__glmatrix_vec3__["a" /* default */].transformMat4(tmp, pos, skinMatrices[joint[k]]); + __WEBPACK_IMPORTED_MODULE_7__glmatrix_vec3__["a" /* default */].scaleAndAdd(skinnedPos, skinnedPos, tmp, weight[k]); + } + } + skinnedPositionAttr.set(i, skinnedPos); + } + } + + for (var i = 0; i < indices.length; i += 3) { + var i1 = indices[i]; + var i2 = indices[i + 1]; + var i3 = indices[i + 2]; + var finalPosAttr = isSkinnedMesh + ? geometry.attributes.skinnedPosition + : positionAttr; + finalPosAttr.get(i1, v1.array); + finalPosAttr.get(i2, v2.array); + finalPosAttr.get(i3, v3.array); + + if (cullBack) { + point = ray.intersectTriangle(v1, v2, v3, renderable.culling); + } + else { + point = ray.intersectTriangle(v1, v3, v2, renderable.culling); + } + if (point) { + var pointW = new __WEBPACK_IMPORTED_MODULE_3__math_Vector3__["a" /* default */](); + if (!isSkinnedMesh) { + __WEBPACK_IMPORTED_MODULE_3__math_Vector3__["a" /* default */].transformMat4(pointW, point, renderable.worldTransform); + } + else { + // TODO point maybe not right. + __WEBPACK_IMPORTED_MODULE_3__math_Vector3__["a" /* default */].copy(pointW, point); + } + out.push(new RayPicking.Intersection( + point, pointW, renderable, [i1, i2, i3], i / 3, + __WEBPACK_IMPORTED_MODULE_3__math_Vector3__["a" /* default */].dist(pointW, this._ray.origin) + )); + } + } + }; + })(), + + _intersectionCompareFunc: function (a, b) { + return a.distance - b.distance; + } +}); + +/** + * @constructor clay.picking.RayPicking~Intersection + * @param {clay.Vector3} point + * @param {clay.Vector3} pointWorld + * @param {clay.Node} target + * @param {Array.} triangle + * @param {number} triangleIndex + * @param {number} distance + */ +RayPicking.Intersection = function (point, pointWorld, target, triangle, triangleIndex, distance) { + /** + * Intersection point in local transform coordinates + * @type {clay.Vector3} + */ + this.point = point; + /** + * Intersection point in world transform coordinates + * @type {clay.Vector3} + */ + this.pointWorld = pointWorld; + /** + * Intersection scene node + * @type {clay.Node} + */ + this.target = target; + /** + * Intersection triangle, which is an array of vertex index + * @type {Array.} + */ + this.triangle = triangle; + /** + * Index of intersection triangle. + */ + this.triangleIndex = triangleIndex; + /** + * Distance from intersection point to ray origin + * @type {number} + */ + this.distance = distance; +}; + +/* harmony default export */ __webpack_exports__["a"] = (RayPicking); + + +/***/ }), +/* 118 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__core_Base__ = __webpack_require__(7); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__core_glenum__ = __webpack_require__(11); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__core_Cache__ = __webpack_require__(57); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__core_vendor__ = __webpack_require__(14); + + + + + +function getArrayCtorByType (type) { + return ({ + 'byte': __WEBPACK_IMPORTED_MODULE_3__core_vendor__["a" /* default */].Int8Array, + 'ubyte': __WEBPACK_IMPORTED_MODULE_3__core_vendor__["a" /* default */].Uint8Array, + 'short': __WEBPACK_IMPORTED_MODULE_3__core_vendor__["a" /* default */].Int16Array, + 'ushort': __WEBPACK_IMPORTED_MODULE_3__core_vendor__["a" /* default */].Uint16Array + })[type] || __WEBPACK_IMPORTED_MODULE_3__core_vendor__["a" /* default */].Float32Array; +} + +function makeAttrKey(attrName) { + return 'attr_' + attrName; +} +/** + * GeometryBase attribute + * @alias clay.GeometryBase.Attribute + * @constructor + */ +function Attribute(name, type, size, semantic) { + /** + * Attribute name + * @type {string} + */ + this.name = name; + /** + * Attribute type + * Possible values: + * + `'byte'` + * + `'ubyte'` + * + `'short'` + * + `'ushort'` + * + `'float'` Most commonly used. + * @type {string} + */ + this.type = type; + /** + * Size of attribute component. 1 - 4. + * @type {number} + */ + this.size = size; + /** + * Semantic of this attribute. + * Possible values: + * + `'POSITION'` + * + `'NORMAL'` + * + `'BINORMAL'` + * + `'TANGENT'` + * + `'TEXCOORD'` + * + `'TEXCOORD_0'` + * + `'TEXCOORD_1'` + * + `'COLOR'` + * + `'JOINT'` + * + `'WEIGHT'` + * + * In shader, attribute with same semantic will be automatically mapped. For example: + * ```glsl + * attribute vec3 pos: POSITION + * ``` + * will use the attribute value with semantic POSITION in geometry, no matter what name it used. + * @type {string} + */ + this.semantic = semantic || ''; + + /** + * Value of the attribute. + * @type {TypedArray} + */ + this.value = null; + + // Init getter setter + switch (size) { + case 1: + this.get = function (idx) { + return this.value[idx]; + }; + this.set = function (idx, value) { + this.value[idx] = value; + }; + // Copy from source to target + this.copy = function (target, source) { + this.value[target] = this.value[target]; + }; + break; + case 2: + this.get = function (idx, out) { + var arr = this.value; + out[0] = arr[idx * 2]; + out[1] = arr[idx * 2 + 1]; + return out; + }; + this.set = function (idx, val) { + var arr = this.value; + arr[idx * 2] = val[0]; + arr[idx * 2 + 1] = val[1]; + }; + this.copy = function (target, source) { + var arr = this.value; + source *= 2; + target *= 2; + arr[target] = arr[source]; + arr[target + 1] = arr[source + 1]; + }; + break; + case 3: + this.get = function (idx, out) { + var idx3 = idx * 3; + var arr = this.value; + out[0] = arr[idx3]; + out[1] = arr[idx3 + 1]; + out[2] = arr[idx3 + 2]; + return out; + }; + this.set = function (idx, val) { + var idx3 = idx * 3; + var arr = this.value; + arr[idx3] = val[0]; + arr[idx3 + 1] = val[1]; + arr[idx3 + 2] = val[2]; + }; + this.copy = function (target, source) { + var arr = this.value; + source *= 3; + target *= 3; + arr[target] = arr[source]; + arr[target + 1] = arr[source + 1]; + arr[target + 2] = arr[source + 2]; + }; + break; + case 4: + this.get = function (idx, out) { + var arr = this.value; + var idx4 = idx * 4; + out[0] = arr[idx4]; + out[1] = arr[idx4 + 1]; + out[2] = arr[idx4 + 2]; + out[3] = arr[idx4 + 3]; + return out; + }; + this.set = function (idx, val) { + var arr = this.value; + var idx4 = idx * 4; + arr[idx4] = val[0]; + arr[idx4 + 1] = val[1]; + arr[idx4 + 2] = val[2]; + arr[idx4 + 3] = val[3]; + }; + this.copy = function (target, source) { + var arr = this.value; + source *= 4; + target *= 4; + // copyWithin is extremely slow + arr[target] = arr[source]; + arr[target + 1] = arr[source + 1]; + arr[target + 2] = arr[source + 2]; + arr[target + 3] = arr[source + 3]; + }; + } +} + +/** + * Set item value at give index. Second parameter val is number if size is 1 + * @function + * @name clay.GeometryBase.Attribute#set + * @param {number} idx + * @param {number[]|number} val + * @example + * geometry.getAttribute('position').set(0, [1, 1, 1]); + */ + +/** + * Get item value at give index. Second parameter out is no need if size is 1 + * @function + * @name clay.GeometryBase.Attribute#set + * @param {number} idx + * @param {number[]} [out] + * @example + * geometry.getAttribute('position').get(0, out); + */ + +/** + * Initialize attribute with given vertex count + * @param {number} nVertex + */ +Attribute.prototype.init = function (nVertex) { + if (!this.value || this.value.length != nVertex * this.size) { + var ArrayConstructor = getArrayCtorByType(this.type); + this.value = new ArrayConstructor(nVertex * this.size); + } +}; + +/** + * Initialize attribute with given array. Which can be 1 dimensional or 2 dimensional + * @param {Array} array + * @example + * geometry.getAttribute('position').fromArray( + * [-1, 0, 0, 1, 0, 0, 0, 1, 0] + * ); + * geometry.getAttribute('position').fromArray( + * [ [-1, 0, 0], [1, 0, 0], [0, 1, 0] ] + * ); + */ +Attribute.prototype.fromArray = function (array) { + var ArrayConstructor = getArrayCtorByType(this.type); + var value; + // Convert 2d array to flat + if (array[0] && (array[0].length)) { + var n = 0; + var size = this.size; + value = new ArrayConstructor(array.length * size); + for (var i = 0; i < array.length; i++) { + for (var j = 0; j < size; j++) { + value[n++] = array[i][j]; + } + } + } + else { + value = new ArrayConstructor(array); + } + this.value = value; +}; + +Attribute.prototype.clone = function(copyValue) { + var ret = new Attribute(this.name, this.type, this.size, this.semantic); + // FIXME + if (copyValue) { + console.warn('todo'); + } + return ret; +}; + +function AttributeBuffer(name, type, buffer, size, semantic) { + this.name = name; + this.type = type; + this.buffer = buffer; + this.size = size; + this.semantic = semantic; + + // To be set in mesh + // symbol in the shader + this.symbol = ''; + + // Needs remove flag + this.needsRemove = false; +} + +function IndicesBuffer(buffer) { + this.buffer = buffer; + this.count = 0; +} + +/** + * Base of all geometry. Use {@link clay.Geometry} for common 3D usage. + * @constructor clay.GeometryBase + * @extends clay.core.Base + */ +var GeometryBase = __WEBPACK_IMPORTED_MODULE_0__core_Base__["a" /* default */].extend(function () { + return /** @lends clay.GeometryBase# */ { + /** + * Attributes of geometry. + * @type {Object.} + */ + attributes: {}, + + /** + * Indices of geometry. + * @type {Uint16Array|Uint32Array} + */ + indices: null, + + /** + * Is vertices data dynamically updated. + * Attributes value can't be changed after first render if dyanmic is false. + * @type {boolean} + */ + dynamic: true, + + _enabledAttributes: null, + + // PENDING + // Init it here to avoid deoptimization when it's assigned in application dynamically + __used: 0 + }; +}, function() { + // Use cache + this._cache = new __WEBPACK_IMPORTED_MODULE_2__core_Cache__["a" /* default */](); + + this._attributeList = Object.keys(this.attributes); + + this.__vaoCache = {}; +}, +/** @lends clay.GeometryBase.prototype */ +{ + /** + * Main attribute will be used to count vertex number + * @type {string} + */ + mainAttribute: '', + /** + * User defined picking algorithm instead of default + * triangle ray intersection + * x, y are NDC. + * ```typescript + * (x, y, renderer, camera, renderable, out) => boolean + * ``` + * @type {?Function} + */ + pick: null, + + /** + * User defined ray picking algorithm instead of default + * triangle ray intersection + * ```typescript + * (ray: clay.Ray, renderable: clay.Renderable, out: Array) => boolean + * ``` + * @type {?Function} + */ + pickByRay: null, + + /** + * Mark attributes and indices in geometry needs to update. + * Usually called after you change the data in attributes. + */ + dirty: function () { + var enabledAttributes = this.getEnabledAttributes(); + for (var i = 0; i < enabledAttributes.length; i++) { + this.dirtyAttribute(enabledAttributes[i]); + } + this.dirtyIndices(); + this._enabledAttributes = null; + + this._cache.dirty('any'); + }, + /** + * Mark the indices needs to update. + */ + dirtyIndices: function () { + this._cache.dirtyAll('indices'); + }, + /** + * Mark the attributes needs to update. + * @param {string} [attrName] + */ + dirtyAttribute: function (attrName) { + this._cache.dirtyAll(makeAttrKey(attrName)); + this._cache.dirtyAll('attributes'); + }, + /** + * Get indices of triangle at given index. + * @param {number} idx + * @param {Array.} out + * @return {Array.} + */ + getTriangleIndices: function (idx, out) { + if (idx < this.triangleCount && idx >= 0) { + if (!out) { + out = []; + } + var indices = this.indices; + out[0] = indices[idx * 3]; + out[1] = indices[idx * 3 + 1]; + out[2] = indices[idx * 3 + 2]; + return out; + } + }, + + /** + * Set indices of triangle at given index. + * @param {number} idx + * @param {Array.} arr + */ + setTriangleIndices: function (idx, arr) { + var indices = this.indices; + indices[idx * 3] = arr[0]; + indices[idx * 3 + 1] = arr[1]; + indices[idx * 3 + 2] = arr[2]; + }, + + isUseIndices: function () { + return !!this.indices; + }, + + /** + * Initialize indices from an array. + * @param {Array} array + */ + initIndicesFromArray: function (array) { + var value; + var ArrayConstructor = this.vertexCount > 0xffff + ? __WEBPACK_IMPORTED_MODULE_3__core_vendor__["a" /* default */].Uint32Array : __WEBPACK_IMPORTED_MODULE_3__core_vendor__["a" /* default */].Uint16Array; + // Convert 2d array to flat + if (array[0] && (array[0].length)) { + var n = 0; + var size = 3; + + value = new ArrayConstructor(array.length * size); + for (var i = 0; i < array.length; i++) { + for (var j = 0; j < size; j++) { + value[n++] = array[i][j]; + } + } + } + else { + value = new ArrayConstructor(array); + } + + this.indices = value; + }, + /** + * Create a new attribute + * @param {string} name + * @param {string} type + * @param {number} size + * @param {string} [semantic] + */ + createAttribute: function (name, type, size, semantic) { + var attrib = new Attribute(name, type, size, semantic); + if (this.attributes[name]) { + this.removeAttribute(name); + } + this.attributes[name] = attrib; + this._attributeList.push(name); + return attrib; + }, + /** + * Remove attribute + * @param {string} name + */ + removeAttribute: function (name) { + var attributeList = this._attributeList; + var idx = attributeList.indexOf(name); + if (idx >= 0) { + attributeList.splice(idx, 1); + delete this.attributes[name]; + return true; + } + return false; + }, + + /** + * Get attribute + * @param {string} name + * @return {clay.GeometryBase.Attribute} + */ + getAttribute: function (name) { + return this.attributes[name]; + }, + + /** + * Get enabled attributes name list + * Attribute which has the same vertex number with position is treated as a enabled attribute + * @return {string[]} + */ + getEnabledAttributes: function () { + var enabledAttributes = this._enabledAttributes; + var attributeList = this._attributeList; + // Cache + if (enabledAttributes) { + return enabledAttributes; + } + + var result = []; + var nVertex = this.vertexCount; + + for (var i = 0; i < attributeList.length; i++) { + var name = attributeList[i]; + var attrib = this.attributes[name]; + if (attrib.value) { + if (attrib.value.length === nVertex * attrib.size) { + result.push(name); + } + } + } + + this._enabledAttributes = result; + + return result; + }, + + getBufferChunks: function (renderer) { + var cache = this._cache; + cache.use(renderer.__uid__); + var isAttributesDirty = cache.isDirty('attributes'); + var isIndicesDirty = cache.isDirty('indices'); + if (isAttributesDirty || isIndicesDirty) { + this._updateBuffer(renderer.gl, isAttributesDirty, isIndicesDirty); + var enabledAttributes = this.getEnabledAttributes(); + for (var i = 0; i < enabledAttributes.length; i++) { + cache.fresh(makeAttrKey(enabledAttributes[i])); + } + cache.fresh('attributes'); + cache.fresh('indices'); + } + cache.fresh('any'); + return cache.get('chunks'); + }, + + _updateBuffer: function (_gl, isAttributesDirty, isIndicesDirty) { + var cache = this._cache; + var chunks = cache.get('chunks'); + var firstUpdate = false; + if (!chunks) { + chunks = []; + // Intialize + chunks[0] = { + attributeBuffers: [], + indicesBuffer: null + }; + cache.put('chunks', chunks); + firstUpdate = true; + } + + var chunk = chunks[0]; + var attributeBuffers = chunk.attributeBuffers; + var indicesBuffer = chunk.indicesBuffer; + + if (isAttributesDirty || firstUpdate) { + var attributeList = this.getEnabledAttributes(); + + var attributeBufferMap = {}; + if (!firstUpdate) { + for (var i = 0; i < attributeBuffers.length; i++) { + attributeBufferMap[attributeBuffers[i].name] = attributeBuffers[i]; + } + } + // FIXME If some attributes removed + for (var k = 0; k < attributeList.length; k++) { + var name = attributeList[k]; + var attribute = this.attributes[name]; + + var bufferInfo; + + if (!firstUpdate) { + bufferInfo = attributeBufferMap[name]; + } + var buffer; + if (bufferInfo) { + buffer = bufferInfo.buffer; + } + else { + buffer = _gl.createBuffer(); + } + if (cache.isDirty(makeAttrKey(name))) { + // Only update when they are dirty. + // TODO: Use BufferSubData? + _gl.bindBuffer(_gl.ARRAY_BUFFER, buffer); + _gl.bufferData(_gl.ARRAY_BUFFER, attribute.value, this.dynamic ? __WEBPACK_IMPORTED_MODULE_1__core_glenum__["a" /* default */].DYNAMIC_DRAW : __WEBPACK_IMPORTED_MODULE_1__core_glenum__["a" /* default */].STATIC_DRAW); + } + + attributeBuffers[k] = new AttributeBuffer(name, attribute.type, buffer, attribute.size, attribute.semantic); + } + // Remove unused attributes buffers. + // PENDING + for (var i = k; i < attributeBuffers.length; i++) { + _gl.deleteBuffer(attributeBuffers[i].buffer); + } + attributeBuffers.length = k; + + } + + if (this.isUseIndices() && (isIndicesDirty || firstUpdate)) { + if (!indicesBuffer) { + indicesBuffer = new IndicesBuffer(_gl.createBuffer()); + chunk.indicesBuffer = indicesBuffer; + } + indicesBuffer.count = this.indices.length; + _gl.bindBuffer(_gl.ELEMENT_ARRAY_BUFFER, indicesBuffer.buffer); + _gl.bufferData(_gl.ELEMENT_ARRAY_BUFFER, this.indices, this.dynamic ? __WEBPACK_IMPORTED_MODULE_1__core_glenum__["a" /* default */].DYNAMIC_DRAW : __WEBPACK_IMPORTED_MODULE_1__core_glenum__["a" /* default */].STATIC_DRAW); + } + }, + + /** + * Dispose geometry data in GL context. + * @param {clay.Renderer} renderer + */ + dispose: function (renderer) { + + var cache = this._cache; + + cache.use(renderer.__uid__); + var chunks = cache.get('chunks'); + if (chunks) { + for (var c = 0; c < chunks.length; c++) { + var chunk = chunks[c]; + + for (var k = 0; k < chunk.attributeBuffers.length; k++) { + var attribs = chunk.attributeBuffers[k]; + renderer.gl.deleteBuffer(attribs.buffer); + } + + if (chunk.indicesBuffer) { + renderer.gl.deleteBuffer(chunk.indicesBuffer.buffer); + } + } + } + if (this.__vaoCache) { + var vaoExt = renderer.getGLExtension('OES_vertex_array_object'); + for (var id in this.__vaoCache) { + var vao = this.__vaoCache[id].vao; + if (vao) { + vaoExt.deleteVertexArrayOES(vao); + } + } + } + this.__vaoCache = {}; + cache.deleteContext(renderer.__uid__); + } + +}); + +if (Object.defineProperty) { + /** + * @name clay.GeometryBase#vertexCount + * @type {number} + * @readOnly + */ + Object.defineProperty(GeometryBase.prototype, 'vertexCount', { + + enumerable: false, + + get: function () { + + var mainAttribute = this.attributes[this.mainAttribute]; + + if (!mainAttribute) { + mainAttribute = this.attributes[this._attributeList[0]]; + } + + if (!mainAttribute || !mainAttribute.value) { + return 0; + } + return mainAttribute.value.length / mainAttribute.size; + } + }); + /** + * @name clay.GeometryBase#triangleCount + * @type {number} + * @readOnly + */ + Object.defineProperty(GeometryBase.prototype, 'triangleCount', { + + enumerable: false, + + get: function () { + var indices = this.indices; + if (!indices) { + return 0; + } + else { + return indices.length / 3; + } + } + }); +} + +GeometryBase.STATIC_DRAW = __WEBPACK_IMPORTED_MODULE_1__core_glenum__["a" /* default */].STATIC_DRAW; +GeometryBase.DYNAMIC_DRAW = __WEBPACK_IMPORTED_MODULE_1__core_glenum__["a" /* default */].DYNAMIC_DRAW; +GeometryBase.STREAM_DRAW = __WEBPACK_IMPORTED_MODULE_1__core_glenum__["a" /* default */].STREAM_DRAW; + +GeometryBase.AttributeBuffer = AttributeBuffer; +GeometryBase.IndicesBuffer = IndicesBuffer; + +GeometryBase.Attribute = Attribute; + +/* harmony default export */ __webpack_exports__["a"] = (GeometryBase); + + +/***/ }), +/* 119 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__calcAmbientSHLight_glsl_js__ = __webpack_require__(120); + + +var uniformVec3Prefix = 'uniform vec3 '; +var uniformFloatPrefix = 'uniform float '; +var exportHeaderPrefix = '@export clay.header.'; +var exportEnd = '@end'; +var unconfigurable = ':unconfigurable;'; +/* harmony default export */ __webpack_exports__["a"] = ([ + exportHeaderPrefix + 'directional_light', + uniformVec3Prefix + 'directionalLightDirection[DIRECTIONAL_LIGHT_COUNT]' + unconfigurable, + uniformVec3Prefix + 'directionalLightColor[DIRECTIONAL_LIGHT_COUNT]' + unconfigurable, + exportEnd, + + exportHeaderPrefix + 'ambient_light', + uniformVec3Prefix + 'ambientLightColor[AMBIENT_LIGHT_COUNT]' + unconfigurable, + exportEnd, + + exportHeaderPrefix + 'ambient_sh_light', + uniformVec3Prefix + 'ambientSHLightColor[AMBIENT_SH_LIGHT_COUNT]' + unconfigurable, + uniformVec3Prefix + 'ambientSHLightCoefficients[AMBIENT_SH_LIGHT_COUNT * 9]' + unconfigurable, + __WEBPACK_IMPORTED_MODULE_0__calcAmbientSHLight_glsl_js__["a" /* default */], + exportEnd, + + exportHeaderPrefix + 'ambient_cubemap_light', + uniformVec3Prefix + 'ambientCubemapLightColor[AMBIENT_CUBEMAP_LIGHT_COUNT]' + unconfigurable, + 'uniform samplerCube ambientCubemapLightCubemap[AMBIENT_CUBEMAP_LIGHT_COUNT]' + unconfigurable, + 'uniform sampler2D ambientCubemapLightBRDFLookup[AMBIENT_CUBEMAP_LIGHT_COUNT]' + unconfigurable, + exportEnd, + + exportHeaderPrefix + 'point_light', + uniformVec3Prefix + 'pointLightPosition[POINT_LIGHT_COUNT]' + unconfigurable, + uniformFloatPrefix + 'pointLightRange[POINT_LIGHT_COUNT]' + unconfigurable, + uniformVec3Prefix + 'pointLightColor[POINT_LIGHT_COUNT]' + unconfigurable, + exportEnd, + + exportHeaderPrefix + 'spot_light', + uniformVec3Prefix + 'spotLightPosition[SPOT_LIGHT_COUNT]' + unconfigurable, + uniformVec3Prefix + 'spotLightDirection[SPOT_LIGHT_COUNT]' + unconfigurable, + uniformFloatPrefix + 'spotLightRange[SPOT_LIGHT_COUNT]' + unconfigurable, + uniformFloatPrefix + 'spotLightUmbraAngleCosine[SPOT_LIGHT_COUNT]' + unconfigurable, + uniformFloatPrefix + 'spotLightPenumbraAngleCosine[SPOT_LIGHT_COUNT]' + unconfigurable, + uniformFloatPrefix + 'spotLightFalloffFactor[SPOT_LIGHT_COUNT]' + unconfigurable, + uniformVec3Prefix + 'spotLightColor[SPOT_LIGHT_COUNT]' + unconfigurable, + exportEnd +].join('\n')); + + +/***/ }), +/* 120 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony default export */ __webpack_exports__["a"] = ("vec3 calcAmbientSHLight(int idx, vec3 N) {\n int offset = 9 * idx;\n return ambientSHLightCoefficients[0]\n + ambientSHLightCoefficients[1] * N.x\n + ambientSHLightCoefficients[2] * N.y\n + ambientSHLightCoefficients[3] * N.z\n + ambientSHLightCoefficients[4] * N.x * N.z\n + ambientSHLightCoefficients[5] * N.z * N.y\n + ambientSHLightCoefficients[6] * N.y * N.x\n + ambientSHLightCoefficients[7] * (3.0 * N.z * N.z - 1.0)\n + ambientSHLightCoefficients[8] * (N.x * N.x - N.y * N.y);\n}"); + + +/***/ }), +/* 121 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony default export */ __webpack_exports__["a"] = ("@export clay.skybox.vertex\n#define SHADER_NAME skybox\nuniform mat4 world : WORLD;\nuniform mat4 worldViewProjection : WORLDVIEWPROJECTION;\nattribute vec3 position : POSITION;\nvarying vec3 v_WorldPosition;\nvoid main()\n{\n v_WorldPosition = (world * vec4(position, 1.0)).xyz;\n gl_Position = worldViewProjection * vec4(position, 1.0);\n}\n@end\n@export clay.skybox.fragment\n#define PI 3.1415926\nuniform mat4 viewInverse : VIEWINVERSE;\n#ifdef EQUIRECTANGULAR\nuniform sampler2D environmentMap;\n#else\nuniform samplerCube environmentMap;\n#endif\nuniform float lod: 0.0;\nvarying vec3 v_WorldPosition;\n@import clay.util.rgbm\n@import clay.util.srgb\n@import clay.util.ACES\nvoid main()\n{\n vec3 eyePos = viewInverse[3].xyz;\n vec3 V = normalize(v_WorldPosition - eyePos);\n#ifdef EQUIRECTANGULAR\n float phi = acos(V.y);\n float theta = atan(-V.x, V.z) + PI * 0.5;\n vec2 uv = vec2(theta / 2.0 / PI, phi / PI);\n vec4 texel = decodeHDR(texture2D(environmentMap, fract(uv)));\n#else\n #if defined(LOD) || defined(SUPPORT_TEXTURE_LOD)\n vec4 texel = decodeHDR(textureCubeLodEXT(environmentMap, V, lod));\n #else\n vec4 texel = decodeHDR(textureCube(environmentMap, V));\n #endif\n#endif\n#ifdef SRGB_DECODE\n texel = sRGBToLinear(texel);\n#endif\n#ifdef TONEMAPPING\n texel.rgb = ACESToneMapping(texel.rgb);\n#endif\n#ifdef SRGB_ENCODE\n texel = linearTosRGB(texel);\n#endif\n gl_FragColor = encodeHDR(vec4(texel.rgb, 1.0));\n}\n@end"); + + +/***/ }), +/* 122 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__Texture__ = __webpack_require__(4); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__Texture2D__ = __webpack_require__(5); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__TextureCube__ = __webpack_require__(27); + + + + +// http://msdn.microsoft.com/en-us/library/windows/desktop/bb943991(v=vs.85).aspx +// https://github.com/toji/webgl-texture-utils/blob/master/texture-util/dds.js +var DDS_MAGIC = 0x20534444; + +var DDSD_CAPS = 0x1; +var DDSD_HEIGHT = 0x2; +var DDSD_WIDTH = 0x4; +var DDSD_PITCH = 0x8; +var DDSD_PIXELFORMAT = 0x1000; +var DDSD_MIPMAPCOUNT = 0x20000; +var DDSD_LINEARSIZE = 0x80000; +var DDSD_DEPTH = 0x800000; + +var DDSCAPS_COMPLEX = 0x8; +var DDSCAPS_MIPMAP = 0x400000; +var DDSCAPS_TEXTURE = 0x1000; + +var DDSCAPS2_CUBEMAP = 0x200; +var DDSCAPS2_CUBEMAP_POSITIVEX = 0x400; +var DDSCAPS2_CUBEMAP_NEGATIVEX = 0x800; +var DDSCAPS2_CUBEMAP_POSITIVEY = 0x1000; +var DDSCAPS2_CUBEMAP_NEGATIVEY = 0x2000; +var DDSCAPS2_CUBEMAP_POSITIVEZ = 0x4000; +var DDSCAPS2_CUBEMAP_NEGATIVEZ = 0x8000; +var DDSCAPS2_VOLUME = 0x200000; + +var DDPF_ALPHAPIXELS = 0x1; +var DDPF_ALPHA = 0x2; +var DDPF_FOURCC = 0x4; +var DDPF_RGB = 0x40; +var DDPF_YUV = 0x200; +var DDPF_LUMINANCE = 0x20000; + +function fourCCToInt32(value) { + return value.charCodeAt(0) + + (value.charCodeAt(1) << 8) + + (value.charCodeAt(2) << 16) + + (value.charCodeAt(3) << 24); +} + +function int32ToFourCC(value) { + return String.fromCharCode( + value & 0xff, + (value >> 8) & 0xff, + (value >> 16) & 0xff, + (value >> 24) & 0xff + ); +} + +var headerLengthInt = 31; // The header length in 32 bit ints + +var FOURCC_DXT1 = fourCCToInt32('DXT1'); +var FOURCC_DXT3 = fourCCToInt32('DXT3'); +var FOURCC_DXT5 = fourCCToInt32('DXT5'); +// Offsets into the header array +var off_magic = 0; + +var off_size = 1; +var off_flags = 2; +var off_height = 3; +var off_width = 4; + +var off_mipmapCount = 7; + +var off_pfFlags = 20; +var off_pfFourCC = 21; + +var off_caps = 27; +var off_caps2 = 28; +var off_caps3 = 29; +var off_caps4 = 30; + +var ret = { + parse: function(arrayBuffer, out) { + var header = new Int32Array(arrayBuffer, 0, headerLengthInt); + if (header[off_magic] !== DDS_MAGIC) { + return null; + } + if (!header(off_pfFlags) & DDPF_FOURCC) { + return null; + } + + var fourCC = header(off_pfFourCC); + var width = header[off_width]; + var height = header[off_height]; + var isCubeMap = header[off_caps2] & DDSCAPS2_CUBEMAP; + var hasMipmap = header[off_flags] & DDSD_MIPMAPCOUNT; + var blockBytes, internalFormat; + switch(fourCC) { + case FOURCC_DXT1: + blockBytes = 8; + internalFormat = __WEBPACK_IMPORTED_MODULE_0__Texture__["a" /* default */].COMPRESSED_RGB_S3TC_DXT1_EXT; + break; + case FOURCC_DXT3: + blockBytes = 16; + internalFormat = __WEBPACK_IMPORTED_MODULE_0__Texture__["a" /* default */].COMPRESSED_RGBA_S3TC_DXT3_EXT; + break; + case FOURCC_DXT5: + blockBytes = 16; + internalFormat = __WEBPACK_IMPORTED_MODULE_0__Texture__["a" /* default */].COMPRESSED_RGBA_S3TC_DXT5_EXT; + break; + default: + return null; + } + var dataOffset = header[off_size] + 4; + // TODO: Suppose all face are existed + var faceNumber = isCubeMap ? 6 : 1; + var mipmapCount = 1; + if (hasMipmap) { + mipmapCount = Math.max(1, header[off_mipmapCount]); + } + + var textures = []; + for (var f = 0; f < faceNumber; f++) { + var _width = width; + var _height = height; + textures[f] = new __WEBPACK_IMPORTED_MODULE_1__Texture2D__["a" /* default */]({ + width: _width, + height: _height, + format: internalFormat + }); + var mipmaps = []; + for (var i = 0; i < mipmapCount; i++) { + var dataLength = Math.max(4, _width) / 4 * Math.max(4, _height) / 4 * blockBytes; + var byteArray = new Uint8Array(arrayBuffer, dataOffset, dataLength); + + dataOffset += dataLength; + _width *= 0.5; + _height *= 0.5; + mipmaps[i] = byteArray; + } + textures[f].pixels = mipmaps[0]; + if (hasMipmap) { + textures[f].mipmaps = mipmaps; + } + } + // TODO + // return isCubeMap ? textures : textures[0]; + if (out) { + out.width = textures[0].width; + out.height = textures[0].height; + out.format = textures[0].format; + out.pixels = textures[0].pixels; + out.mipmaps = textures[0].mipmaps; + } + else { + return textures[0]; + } + } +}; + +/* harmony default export */ __webpack_exports__["a"] = (ret); + + +/***/ }), +/* 123 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__Texture__ = __webpack_require__(4); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__Texture2D__ = __webpack_require__(5); + + +var toChar = String.fromCharCode; + +var MINELEN = 8; +var MAXELEN = 0x7fff; +function rgbe2float(rgbe, buffer, offset, exposure) { + if (rgbe[3] > 0) { + var f = Math.pow(2.0, rgbe[3] - 128 - 8 + exposure); + buffer[offset + 0] = rgbe[0] * f; + buffer[offset + 1] = rgbe[1] * f; + buffer[offset + 2] = rgbe[2] * f; + } + else { + buffer[offset + 0] = 0; + buffer[offset + 1] = 0; + buffer[offset + 2] = 0; + } + buffer[offset + 3] = 1.0; + return buffer; +} + +function uint82string(array, offset, size) { + var str = ''; + for (var i = offset; i < size; i++) { + str += toChar(array[i]); + } + return str; +} + +function copyrgbe(s, t) { + t[0] = s[0]; + t[1] = s[1]; + t[2] = s[2]; + t[3] = s[3]; +} + +// TODO : check +function oldReadColors(scan, buffer, offset, xmax) { + var rshift = 0, x = 0, len = xmax; + while (len > 0) { + scan[x][0] = buffer[offset++]; + scan[x][1] = buffer[offset++]; + scan[x][2] = buffer[offset++]; + scan[x][3] = buffer[offset++]; + if (scan[x][0] === 1 && scan[x][1] === 1 && scan[x][2] === 1) { + // exp is count of repeated pixels + for (var i = (scan[x][3] << rshift) >>> 0; i > 0; i--) { + copyrgbe(scan[x-1], scan[x]); + x++; + len--; + } + rshift += 8; + } else { + x++; + len--; + rshift = 0; + } + } + return offset; +} + +function readColors(scan, buffer, offset, xmax) { + if ((xmax < MINELEN) | (xmax > MAXELEN)) { + return oldReadColors(scan, buffer, offset, xmax); + } + var i = buffer[offset++]; + if (i != 2) { + return oldReadColors(scan, buffer, offset - 1, xmax); + } + scan[0][1] = buffer[offset++]; + scan[0][2] = buffer[offset++]; + + i = buffer[offset++]; + if ((((scan[0][2] << 8) >>> 0) | i) >>> 0 !== xmax) { + return null; + } + for (var i = 0; i < 4; i++) { + for (var x = 0; x < xmax;) { + var code = buffer[offset++]; + if (code > 128) { + code = (code & 127) >>> 0; + var val = buffer[offset++]; + while (code--) { + scan[x++][i] = val; + } + } else { + while (code--) { + scan[x++][i] = buffer[offset++]; + } + } + } + } + return offset; +} + + +var ret = { + // http://www.graphics.cornell.edu/~bjw/rgbe.html + // Blender source + // http://radsite.lbl.gov/radiance/refer/Notes/picture_format.html + parseRGBE: function(arrayBuffer, texture, exposure) { + if (exposure == null) { + exposure = 0; + } + var data = new Uint8Array(arrayBuffer); + var size = data.length; + if (uint82string(data, 0, 2) !== '#?') { + return; + } + // find empty line, next line is resolution info + for (var i = 2; i < size; i++) { + if (toChar(data[i]) === '\n' && toChar(data[i+1]) === '\n') { + break; + } + } + if (i >= size) { // not found + return; + } + // find resolution info line + i += 2; + var str = ''; + for (; i < size; i++) { + var _char = toChar(data[i]); + if (_char === '\n') { + break; + } + str += _char; + } + // -Y M +X N + var tmp = str.split(' '); + var height = parseInt(tmp[1]); + var width = parseInt(tmp[3]); + if (!width || !height) { + return; + } + + // read and decode actual data + var offset = i+1; + var scanline = []; + // memzero + for (var x = 0; x < width; x++) { + scanline[x] = []; + for (var j = 0; j < 4; j++) { + scanline[x][j] = 0; + } + } + var pixels = new Float32Array(width * height * 4); + var offset2 = 0; + for (var y = 0; y < height; y++) { + var offset = readColors(scanline, data, offset, width); + if (!offset) { + return null; + } + for (var x = 0; x < width; x++) { + rgbe2float(scanline[x], pixels, offset2, exposure); + offset2 += 4; + } + } + + if (!texture) { + texture = new __WEBPACK_IMPORTED_MODULE_1__Texture2D__["a" /* default */](); + } + texture.width = width; + texture.height = height; + texture.pixels = pixels; + // HALF_FLOAT can't use Float32Array + texture.type = __WEBPACK_IMPORTED_MODULE_0__Texture__["a" /* default */].FLOAT; + return texture; + }, + + parseRGBEFromPNG: function(png) { + + } +}; + +/* harmony default export */ __webpack_exports__["a"] = (ret); + + +/***/ }), +/* 124 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_claygl_src_Texture2D__ = __webpack_require__(5); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_claygl_src_math_Vector3__ = __webpack_require__(3); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2_claygl_src_math_Vector2__ = __webpack_require__(26); +/** + * Surface texture in the 3D scene. + * Provide management and rendering of zrender shapes and groups + * + * @module echarts-gl/util/EChartsSurface + * @author Yi Shen(http://github.com/pissang) + */ + + + + + +var events = ['mousedown', 'mouseup', 'mousemove', 'mouseover', 'mouseout', 'click', 'dblclick', 'contextmenu']; + +function makeHandlerName(eventName) { + return '_on' + eventName; +} +/** + * @constructor + * @alias echarts-gl/util/EChartsSurface + * @param {module:echarts~ECharts} chart + */ +var EChartsSurface = function (chart) { + var self = this; + this._texture = new __WEBPACK_IMPORTED_MODULE_0_claygl_src_Texture2D__["a" /* default */]({ + anisotropic: 32, + flipY: false, + + surface: this, + + dispose: function (renderer) { + self.dispose(); + __WEBPACK_IMPORTED_MODULE_0_claygl_src_Texture2D__["a" /* default */].prototype.dispose.call(this, renderer); + } + }); + + events.forEach(function (eventName) { + this[makeHandlerName(eventName)] = function (eveObj) { + if (!eveObj.triangle) { + return; + } + this._meshes.forEach(function (mesh) { + this.dispatchEvent(eventName, mesh, eveObj.triangle, eveObj.point); + }, this); + }; + }, this); + + this._meshes = []; + + if (chart) { + this.setECharts(chart); + } + + // Texture updated callback; + this.onupdate = null; +}; + +EChartsSurface.prototype = { + + constructor: EChartsSurface, + + getTexture: function () { + return this._texture; + }, + + setECharts: function (chart) { + this._chart = chart; + + var canvas = chart.getDom(); + if (!(canvas instanceof HTMLCanvasElement)) { + console.error('ECharts must init on canvas if it is used as texture.'); + // Use an empty canvas + canvas = document.createElement('canvas'); + } + else { + var self = this; + // Wrap refreshImmediately + var zr = chart.getZr(); + var oldRefreshImmediately = zr.__oldRefreshImmediately || zr.refreshImmediately; + zr.refreshImmediately = function () { + oldRefreshImmediately.call(this); + self._texture.dirty(); + + self.onupdate && self.onupdate(); + }; + zr.__oldRefreshImmediately = oldRefreshImmediately; + } + + this._texture.image = canvas; + this._texture.dirty(); + this.onupdate && this.onupdate(); + }, + + /** + * @method + * @param {clay.Mesh} attachedMesh + * @param {Array.} triangle Triangle indices + * @param {clay.math.Vector3} point + */ + dispatchEvent: (function () { + + var p0 = new __WEBPACK_IMPORTED_MODULE_1_claygl_src_math_Vector3__["a" /* default */](); + var p1 = new __WEBPACK_IMPORTED_MODULE_1_claygl_src_math_Vector3__["a" /* default */](); + var p2 = new __WEBPACK_IMPORTED_MODULE_1_claygl_src_math_Vector3__["a" /* default */](); + var uv0 = new __WEBPACK_IMPORTED_MODULE_2_claygl_src_math_Vector2__["a" /* default */](); + var uv1 = new __WEBPACK_IMPORTED_MODULE_2_claygl_src_math_Vector2__["a" /* default */](); + var uv2 = new __WEBPACK_IMPORTED_MODULE_2_claygl_src_math_Vector2__["a" /* default */](); + var uv = new __WEBPACK_IMPORTED_MODULE_2_claygl_src_math_Vector2__["a" /* default */](); + + var vCross = new __WEBPACK_IMPORTED_MODULE_1_claygl_src_math_Vector3__["a" /* default */](); + + return function (eventName, attachedMesh, triangle, point) { + var geo = attachedMesh.geometry; + var position = geo.attributes.position; + var texcoord = geo.attributes.texcoord0; + var dot = __WEBPACK_IMPORTED_MODULE_1_claygl_src_math_Vector3__["a" /* default */].dot; + var cross = __WEBPACK_IMPORTED_MODULE_1_claygl_src_math_Vector3__["a" /* default */].cross; + + position.get(triangle[0], p0.array); + position.get(triangle[1], p1.array); + position.get(triangle[2], p2.array); + texcoord.get(triangle[0], uv0.array); + texcoord.get(triangle[1], uv1.array); + texcoord.get(triangle[2], uv2.array); + + cross(vCross, p1, p2); + var det = dot(p0, vCross); + var t = dot(point, vCross) / det; + cross(vCross, p2, p0); + var u = dot(point, vCross) / det; + cross(vCross, p0, p1); + var v = dot(point, vCross) / det; + + __WEBPACK_IMPORTED_MODULE_2_claygl_src_math_Vector2__["a" /* default */].scale(uv, uv0, t); + __WEBPACK_IMPORTED_MODULE_2_claygl_src_math_Vector2__["a" /* default */].scaleAndAdd(uv, uv, uv1, u); + __WEBPACK_IMPORTED_MODULE_2_claygl_src_math_Vector2__["a" /* default */].scaleAndAdd(uv, uv, uv2, v); + + var x = uv.x * this._chart.getWidth(); + var y = uv.y * this._chart.getHeight(); + this._chart.getZr().handler.dispatch(eventName, { + zrX: x, + zrY: y + }); + }; + })(), + + attachToMesh: function (mesh) { + if (this._meshes.indexOf(mesh) >= 0) { + return; + } + + events.forEach(function (eventName) { + mesh.on(eventName, this[makeHandlerName(eventName)], this); + }, this); + + this._meshes.push(mesh); + }, + + detachFromMesh: function (mesh) { + var idx = this._meshes.indexOf(mesh); + if (idx >= 0) { + this._meshes.splice(idx, 1); + } + + events.forEach(function (eventName) { + mesh.off(eventName, this[makeHandlerName(eventName)]); + }, this); + }, + + dispose: function () { + this._meshes.forEach(function (mesh) { + this.detachFromMesh(mesh); + }, this); + } +}; + +/* harmony default export */ __webpack_exports__["a"] = (EChartsSurface); + +/***/ }), +/* 125 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__Light__ = __webpack_require__(24); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__util_cubemap__ = __webpack_require__(77); +// https://docs.unrealengine.com/latest/INT/Engine/Rendering/LightingAndShadows/AmbientCubemap/ + + + +/** + * Ambient cubemap light provides specular parts of Image Based Lighting. + * Which is a basic requirement for Physically Based Rendering + * @constructor clay.light.AmbientCubemap + * @extends clay.Light + */ +var AmbientCubemapLight = __WEBPACK_IMPORTED_MODULE_0__Light__["a" /* default */].extend({ + + /** + * @type {clay.TextureCube} + * @memberOf clay.light.AmbientCubemap# + */ + cubemap: null, + + // TODO + // range: 100, + + castShadow: false, + + _normalDistribution: null, + _brdfLookup: null + +}, /** @lends clay.light.AmbientCubemap# */ { + + type: 'AMBIENT_CUBEMAP_LIGHT', + + /** + * Do prefitering the cubemap + * @param {clay.Renderer} renderer + * @param {number} [size=32] + */ + prefilter: function (renderer, size) { + if (!renderer.getGLExtension('EXT_shader_texture_lod')) { + console.warn('Device not support textureCubeLodEXT'); + return; + } + if (!this._brdfLookup) { + this._normalDistribution = __WEBPACK_IMPORTED_MODULE_1__util_cubemap__["a" /* default */].generateNormalDistribution(); + this._brdfLookup = __WEBPACK_IMPORTED_MODULE_1__util_cubemap__["a" /* default */].integrateBRDF(renderer, this._normalDistribution); + } + var cubemap = this.cubemap; + if (cubemap.__prefiltered) { + return; + } + + var result = __WEBPACK_IMPORTED_MODULE_1__util_cubemap__["a" /* default */].prefilterEnvironmentMap( + renderer, cubemap, { + encodeRGBM: true, + width: size, + height: size + }, this._normalDistribution, this._brdfLookup + ); + this.cubemap = result.environmentMap; + this.cubemap.__prefiltered = true; + + cubemap.dispose(renderer); + }, + + getBRDFLookup: function () { + return this._brdfLookup; + }, + + uniformTemplates: { + ambientCubemapLightColor: { + type: '3f', + value: function (instance) { + var color = instance.color; + var intensity = instance.intensity; + return [color[0]*intensity, color[1]*intensity, color[2]*intensity]; + } + }, + + ambientCubemapLightCubemap: { + type: 't', + value: function (instance) { + return instance.cubemap; + } + }, + + ambientCubemapLightBRDFLookup: { + type: 't', + value: function (instance) { + return instance._brdfLookup; + } + } + } + /** + * @function + * @name clone + * @return {clay.light.AmbientCubemap} + * @memberOf clay.light.AmbientCubemap.prototype + */ +}); + +/* harmony default export */ __webpack_exports__["a"] = (AmbientCubemapLight); + + +/***/ }), +/* 126 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony default export */ __webpack_exports__["a"] = ("\n@export clay.compositor.vertex\nuniform mat4 worldViewProjection : WORLDVIEWPROJECTION;\nattribute vec3 position : POSITION;\nattribute vec2 texcoord : TEXCOORD_0;\nvarying vec2 v_Texcoord;\nvoid main()\n{\n v_Texcoord = texcoord;\n gl_Position = worldViewProjection * vec4(position, 1.0);\n}\n@end"); + + +/***/ }), +/* 127 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony default export */ __webpack_exports__["a"] = ("#define SAMPLE_NUMBER 1024\n#define PI 3.14159265358979\nuniform sampler2D normalDistribution;\nuniform vec2 viewportSize : [512, 256];\nconst vec3 N = vec3(0.0, 0.0, 1.0);\nconst float fSampleNumber = float(SAMPLE_NUMBER);\nvec3 importanceSampleNormal(float i, float roughness, vec3 N) {\n vec3 H = texture2D(normalDistribution, vec2(roughness, i)).rgb;\n vec3 upVector = abs(N.y) > 0.999 ? vec3(1.0, 0.0, 0.0) : vec3(0.0, 1.0, 0.0);\n vec3 tangentX = normalize(cross(N, upVector));\n vec3 tangentZ = cross(N, tangentX);\n return normalize(tangentX * H.x + N * H.y + tangentZ * H.z);\n}\nfloat G_Smith(float roughness, float NoV, float NoL) {\n float k = roughness * roughness / 2.0;\n float G1V = NoV / (NoV * (1.0 - k) + k);\n float G1L = NoL / (NoL * (1.0 - k) + k);\n return G1L * G1V;\n}\nvoid main() {\n vec2 uv = gl_FragCoord.xy / viewportSize;\n float NoV = uv.x;\n float roughness = uv.y;\n vec3 V;\n V.x = sqrt(1.0 - NoV * NoV);\n V.y = 0.0;\n V.z = NoV;\n float A = 0.0;\n float B = 0.0;\n for (int i = 0; i < SAMPLE_NUMBER; i++) {\n vec3 H = importanceSampleNormal(float(i) / fSampleNumber, roughness, N);\n vec3 L = reflect(-V, H);\n float NoL = clamp(L.z, 0.0, 1.0);\n float NoH = clamp(H.z, 0.0, 1.0);\n float VoH = clamp(dot(V, H), 0.0, 1.0);\n if (NoL > 0.0) {\n float G = G_Smith(roughness, NoV, NoL);\n float G_Vis = G * VoH / (NoH * NoV);\n float Fc = pow(1.0 - VoH, 5.0);\n A += (1.0 - Fc) * G_Vis;\n B += Fc * G_Vis;\n }\n }\n gl_FragColor = vec4(vec2(A, B) / fSampleNumber, 0.0, 1.0);\n}\n"); + + +/***/ }), +/* 128 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony default export */ __webpack_exports__["a"] = ("#define SHADER_NAME prefilter\n#define SAMPLE_NUMBER 1024\n#define PI 3.14159265358979\nuniform mat4 viewInverse : VIEWINVERSE;\nuniform samplerCube environmentMap;\nuniform sampler2D normalDistribution;\nuniform float roughness : 0.5;\nvarying vec2 v_Texcoord;\nvarying vec3 v_WorldPosition;\n@import clay.util.rgbm\nvec3 importanceSampleNormal(float i, float roughness, vec3 N) {\n vec3 H = texture2D(normalDistribution, vec2(roughness, i)).rgb;\n vec3 upVector = abs(N.y) > 0.999 ? vec3(1.0, 0.0, 0.0) : vec3(0.0, 1.0, 0.0);\n vec3 tangentX = normalize(cross(N, upVector));\n vec3 tangentZ = cross(N, tangentX);\n return normalize(tangentX * H.x + N * H.y + tangentZ * H.z);\n}\nvoid main() {\n vec3 eyePos = viewInverse[3].xyz;\n vec3 V = normalize(v_WorldPosition - eyePos);\n vec3 N = V;\n vec3 prefilteredColor = vec3(0.0);\n float totalWeight = 0.0;\n float fMaxSampleNumber = float(SAMPLE_NUMBER);\n for (int i = 0; i < SAMPLE_NUMBER; i++) {\n vec3 H = importanceSampleNormal(float(i) / fMaxSampleNumber, roughness, N);\n vec3 L = reflect(-V, H);\n float NoL = clamp(dot(N, L), 0.0, 1.0);\n if (NoL > 0.0) {\n prefilteredColor += decodeHDR(textureCube(environmentMap, L)).rgb * NoL;\n totalWeight += NoL;\n }\n }\n gl_FragColor = encodeHDR(vec4(prefilteredColor / totalWeight, 1.0));\n}\n"); + + +/***/ }), +/* 129 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__Light__ = __webpack_require__(24); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__core_vendor__ = __webpack_require__(14); + + + +/** + * Spherical Harmonic Ambient Light + * @constructor clay.light.AmbientSH + * @extends clay.Light + */ +var AmbientSHLight = __WEBPACK_IMPORTED_MODULE_0__Light__["a" /* default */].extend({ + + castShadow: false, + + /** + * Spherical Harmonic Coefficients + * @type {Array.} + * @memberOf clay.light.AmbientSH# + */ + coefficients: [], + +}, function () { + this._coefficientsTmpArr = new __WEBPACK_IMPORTED_MODULE_1__core_vendor__["a" /* default */].Float32Array(9 * 3); +}, { + + type: 'AMBIENT_SH_LIGHT', + + uniformTemplates: { + ambientSHLightColor: { + type: '3f', + value: function (instance) { + var color = instance.color; + var intensity = instance.intensity; + return [color[0] * intensity, color[1] * intensity, color[2] * intensity]; + } + }, + + ambientSHLightCoefficients: { + type: '3f', + value: function (instance) { + var coefficientsTmpArr = instance._coefficientsTmpArr; + for (var i = 0; i < instance.coefficients.length; i++) { + coefficientsTmpArr[i] = instance.coefficients[i]; + } + return coefficientsTmpArr; + } + } + } + /** + * @function + * @name clone + * @return {clay.light.Ambient} + * @memberOf clay.light.Ambient.prototype + */ +}); + +/* harmony default export */ __webpack_exports__["a"] = (AmbientSHLight); + + +/***/ }), +/* 130 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__Texture__ = __webpack_require__(4); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__FrameBuffer__ = __webpack_require__(10); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__Texture2D__ = __webpack_require__(5); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__compositor_Pass__ = __webpack_require__(16); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4__core_vendor__ = __webpack_require__(14); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_5__plugin_Skybox__ = __webpack_require__(42); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_6__plugin_Skydome__ = __webpack_require__(75); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_7__prePass_EnvironmentMap__ = __webpack_require__(62); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_8__Scene__ = __webpack_require__(36); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_9__glmatrix_vec3__ = __webpack_require__(12); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_10__shader_projectEnvMap_glsl_js__ = __webpack_require__(131); +// Spherical Harmonic Helpers + + + + + + + + + + +var sh = {}; + + + +var targets = ['px', 'nx', 'py', 'ny', 'pz', 'nz']; + +// Project on gpu, but needs browser to support readPixels as Float32Array. +function projectEnvironmentMapGPU(renderer, envMap) { + var shTexture = new __WEBPACK_IMPORTED_MODULE_2__Texture2D__["a" /* default */]({ + width: 9, + height: 1, + type: __WEBPACK_IMPORTED_MODULE_0__Texture__["a" /* default */].FLOAT + }); + var pass = new __WEBPACK_IMPORTED_MODULE_3__compositor_Pass__["a" /* default */]({ + fragment: __WEBPACK_IMPORTED_MODULE_10__shader_projectEnvMap_glsl_js__["a" /* default */] + }); + pass.material.define('fragment', 'TEXTURE_SIZE', envMap.width); + pass.setUniform('environmentMap', envMap); + + var framebuffer = new __WEBPACK_IMPORTED_MODULE_1__FrameBuffer__["a" /* default */](); + framebuffer.attach(shTexture); + pass.render(renderer, framebuffer); + + framebuffer.bind(renderer); + // TODO Only chrome and firefox support Float32Array + var pixels = new __WEBPACK_IMPORTED_MODULE_4__core_vendor__["a" /* default */].Float32Array(9 * 4); + renderer.gl.readPixels(0, 0, 9, 1, __WEBPACK_IMPORTED_MODULE_0__Texture__["a" /* default */].RGBA, __WEBPACK_IMPORTED_MODULE_0__Texture__["a" /* default */].FLOAT, pixels); + + var coeff = new __WEBPACK_IMPORTED_MODULE_4__core_vendor__["a" /* default */].Float32Array(9 * 3); + for (var i = 0; i < 9; i++) { + coeff[i * 3] = pixels[i * 4]; + coeff[i * 3 + 1] = pixels[i * 4 + 1]; + coeff[i * 3 + 2] = pixels[i * 4 + 2]; + } + framebuffer.unbind(renderer); + + framebuffer.dispose(renderer); + pass.dispose(renderer); + return coeff; +} + +function harmonics(normal, index){ + var x = normal[0]; + var y = normal[1]; + var z = normal[2]; + + if (index === 0) { + return 1.0; + } + else if (index === 1) { + return x; + } + else if (index === 2) { + return y; + } + else if (index === 3) { + return z; + } + else if (index === 4) { + return x * z; + } + else if (index === 5) { + return y * z; + } + else if (index === 6) { + return x * y; + } + else if (index === 7) { + return 3.0 * z * z - 1.0; + } + else { + return x * x - y * y; + } +} + +var normalTransform = { + px: [2, 1, 0, -1, -1, 1], + nx: [2, 1, 0, 1, -1, -1], + py: [0, 2, 1, 1, -1, -1], + ny: [0, 2, 1, 1, 1, 1], + pz: [0, 1, 2, -1, -1, -1], + nz: [0, 1, 2, 1, -1, 1] +}; + +// Project on cpu. +function projectEnvironmentMapCPU(renderer, cubePixels, width, height) { + var coeff = new __WEBPACK_IMPORTED_MODULE_4__core_vendor__["a" /* default */].Float32Array(9 * 3); + var normal = __WEBPACK_IMPORTED_MODULE_9__glmatrix_vec3__["a" /* default */].create(); + var texel = __WEBPACK_IMPORTED_MODULE_9__glmatrix_vec3__["a" /* default */].create(); + var fetchNormal = __WEBPACK_IMPORTED_MODULE_9__glmatrix_vec3__["a" /* default */].create(); + for (var m = 0; m < 9; m++) { + var result = __WEBPACK_IMPORTED_MODULE_9__glmatrix_vec3__["a" /* default */].create(); + for (var k = 0; k < targets.length; k++) { + var pixels = cubePixels[targets[k]]; + + var sideResult = __WEBPACK_IMPORTED_MODULE_9__glmatrix_vec3__["a" /* default */].create(); + var divider = 0; + var i = 0; + var transform = normalTransform[targets[k]]; + for (var y = 0; y < height; y++) { + for (var x = 0; x < width; x++) { + + normal[0] = x / (width - 1.0) * 2.0 - 1.0; + // TODO Flip y? + normal[1] = y / (height - 1.0) * 2.0 - 1.0; + normal[2] = -1.0; + __WEBPACK_IMPORTED_MODULE_9__glmatrix_vec3__["a" /* default */].normalize(normal, normal); + + fetchNormal[0] = normal[transform[0]] * transform[3]; + fetchNormal[1] = normal[transform[1]] * transform[4]; + fetchNormal[2] = normal[transform[2]] * transform[5]; + + texel[0] = pixels[i++] / 255; + texel[1] = pixels[i++] / 255; + texel[2] = pixels[i++] / 255; + // RGBM Decode + var scale = pixels[i++] / 255 * 8.12; + texel[0] *= scale; + texel[1] *= scale; + texel[2] *= scale; + + __WEBPACK_IMPORTED_MODULE_9__glmatrix_vec3__["a" /* default */].scaleAndAdd(sideResult, sideResult, texel, harmonics(fetchNormal, m) * -normal[2]); + // -normal.z equals cos(theta) of Lambertian + divider += -normal[2]; + } + } + __WEBPACK_IMPORTED_MODULE_9__glmatrix_vec3__["a" /* default */].scaleAndAdd(result, result, sideResult, 1 / divider); + } + + coeff[m * 3] = result[0] / 6.0; + coeff[m * 3 + 1] = result[1] / 6.0; + coeff[m * 3 + 2] = result[2] / 6.0; + } + return coeff; +} + +/** + * @param {clay.Renderer} renderer + * @param {clay.Texture} envMap + * @param {Object} [textureOpts] + * @param {Object} [textureOpts.lod] + * @param {boolean} [textureOpts.decodeRGBM] + */ +sh.projectEnvironmentMap = function (renderer, envMap, opts) { + + // TODO sRGB + + opts = opts || {}; + opts.lod = opts.lod || 0; + + var skybox; + var dummyScene = new __WEBPACK_IMPORTED_MODULE_8__Scene__["a" /* default */](); + var size = 64; + if (envMap.textureType === 'texture2D') { + skybox = new __WEBPACK_IMPORTED_MODULE_6__plugin_Skydome__["a" /* default */]({ + scene: dummyScene, + environmentMap: envMap + }); + } + else { + size = (envMap.image && envMap.image.px) ? envMap.image.px.width : envMap.width; + skybox = new __WEBPACK_IMPORTED_MODULE_5__plugin_Skybox__["a" /* default */]({ + scene: dummyScene, + environmentMap: envMap + }); + } + // Convert to rgbm + var width = Math.ceil(size / Math.pow(2, opts.lod)); + var height = Math.ceil(size / Math.pow(2, opts.lod)); + var rgbmTexture = new __WEBPACK_IMPORTED_MODULE_2__Texture2D__["a" /* default */]({ + width: width, + height: height + }); + var framebuffer = new __WEBPACK_IMPORTED_MODULE_1__FrameBuffer__["a" /* default */](); + skybox.material.define('fragment', 'RGBM_ENCODE'); + if (opts.decodeRGBM) { + skybox.material.define('fragment', 'RGBM_DECODE'); + } + skybox.material.set('lod', opts.lod); + var envMapPass = new __WEBPACK_IMPORTED_MODULE_7__prePass_EnvironmentMap__["a" /* default */]({ + texture: rgbmTexture + }); + var cubePixels = {}; + for (var i = 0; i < targets.length; i++) { + cubePixels[targets[i]] = new Uint8Array(width * height * 4); + var camera = envMapPass.getCamera(targets[i]); + camera.fov = 90; + framebuffer.attach(rgbmTexture); + framebuffer.bind(renderer); + renderer.render(dummyScene, camera); + renderer.gl.readPixels( + 0, 0, width, height, + __WEBPACK_IMPORTED_MODULE_0__Texture__["a" /* default */].RGBA, __WEBPACK_IMPORTED_MODULE_0__Texture__["a" /* default */].UNSIGNED_BYTE, cubePixels[targets[i]] + ); + framebuffer.unbind(renderer); + } + + skybox.dispose(renderer); + framebuffer.dispose(renderer); + rgbmTexture.dispose(renderer); + + return projectEnvironmentMapCPU(renderer, cubePixels, width, height); +}; + +/* harmony default export */ __webpack_exports__["a"] = (sh); + + +/***/ }), +/* 131 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony default export */ __webpack_exports__["a"] = ("uniform samplerCube environmentMap;\nvarying vec2 v_Texcoord;\n#define TEXTURE_SIZE 16\nmat3 front = mat3(\n 1.0, 0.0, 0.0,\n 0.0, 1.0, 0.0,\n 0.0, 0.0, 1.0\n);\nmat3 back = mat3(\n -1.0, 0.0, 0.0,\n 0.0, 1.0, 0.0,\n 0.0, 0.0, -1.0\n);\nmat3 left = mat3(\n 0.0, 0.0, -1.0,\n 0.0, 1.0, 0.0,\n 1.0, 0.0, 0.0\n);\nmat3 right = mat3(\n 0.0, 0.0, 1.0,\n 0.0, 1.0, 0.0,\n -1.0, 0.0, 0.0\n);\nmat3 up = mat3(\n 1.0, 0.0, 0.0,\n 0.0, 0.0, 1.0,\n 0.0, -1.0, 0.0\n);\nmat3 down = mat3(\n 1.0, 0.0, 0.0,\n 0.0, 0.0, -1.0,\n 0.0, 1.0, 0.0\n);\nfloat harmonics(vec3 normal){\n int index = int(gl_FragCoord.x);\n float x = normal.x;\n float y = normal.y;\n float z = normal.z;\n if(index==0){\n return 1.0;\n }\n else if(index==1){\n return x;\n }\n else if(index==2){\n return y;\n }\n else if(index==3){\n return z;\n }\n else if(index==4){\n return x*z;\n }\n else if(index==5){\n return y*z;\n }\n else if(index==6){\n return x*y;\n }\n else if(index==7){\n return 3.0*z*z - 1.0;\n }\n else{\n return x*x - y*y;\n }\n}\nvec3 sampleSide(mat3 rot)\n{\n vec3 result = vec3(0.0);\n float divider = 0.0;\n for (int i = 0; i < TEXTURE_SIZE * TEXTURE_SIZE; i++) {\n float x = mod(float(i), float(TEXTURE_SIZE));\n float y = float(i / TEXTURE_SIZE);\n vec2 sidecoord = ((vec2(x, y) + vec2(0.5, 0.5)) / vec2(TEXTURE_SIZE)) * 2.0 - 1.0;\n vec3 normal = normalize(vec3(sidecoord, -1.0));\n vec3 fetchNormal = rot * normal;\n vec3 texel = textureCube(environmentMap, fetchNormal).rgb;\n result += harmonics(fetchNormal) * texel * -normal.z;\n divider += -normal.z;\n }\n return result / divider;\n}\nvoid main()\n{\n vec3 result = (\n sampleSide(front) +\n sampleSide(back) +\n sampleSide(left) +\n sampleSide(right) +\n sampleSide(up) +\n sampleSide(down)\n ) / 6.0;\n gl_FragColor = vec4(result, 1.0);\n}"); + + +/***/ }), +/* 132 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__Geometry__ = __webpack_require__(15); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__math_BoundingBox__ = __webpack_require__(18); + + + +/** + * @constructor clay.geometry.Sphere + * @extends clay.Geometry + * @param {Object} [opt] + * @param {number} [widthSegments] + * @param {number} [heightSegments] + * @param {number} [phiStart] + * @param {number} [phiLength] + * @param {number} [thetaStart] + * @param {number} [thetaLength] + * @param {number} [radius] + */ +var Sphere = __WEBPACK_IMPORTED_MODULE_0__Geometry__["a" /* default */].extend(/** @lends clay.geometry.Sphere# */ { + dynamic: false, + /** + * @type {number} + */ + widthSegments: 40, + /** + * @type {number} + */ + heightSegments: 20, + + /** + * @type {number} + */ + phiStart: 0, + /** + * @type {number} + */ + phiLength: Math.PI * 2, + + /** + * @type {number} + */ + thetaStart: 0, + /** + * @type {number} + */ + thetaLength: Math.PI, + + /** + * @type {number} + */ + radius: 1 + +}, function() { + this.build(); +}, +/** @lends clay.geometry.Sphere.prototype */ +{ + /** + * Build sphere geometry + */ + build: function() { + var heightSegments = this.heightSegments; + var widthSegments = this.widthSegments; + + var positionAttr = this.attributes.position; + var texcoordAttr = this.attributes.texcoord0; + var normalAttr = this.attributes.normal; + + var vertexCount = (widthSegments + 1) * (heightSegments + 1); + positionAttr.init(vertexCount); + texcoordAttr.init(vertexCount); + normalAttr.init(vertexCount); + + var IndicesCtor = vertexCount > 0xffff ? Uint32Array : Uint16Array; + var indices = this.indices = new IndicesCtor(widthSegments * heightSegments * 6); + + var x, y, z, + u, v, + i, j; + + var radius = this.radius; + var phiStart = this.phiStart; + var phiLength = this.phiLength; + var thetaStart = this.thetaStart; + var thetaLength = this.thetaLength; + var radius = this.radius; + + var pos = []; + var uv = []; + var offset = 0; + var divider = 1 / radius; + for (j = 0; j <= heightSegments; j ++) { + for (i = 0; i <= widthSegments; i ++) { + u = i / widthSegments; + v = j / heightSegments; + + // X axis is inverted so texture can be mapped from left to right + x = -radius * Math.cos(phiStart + u * phiLength) * Math.sin(thetaStart + v * thetaLength); + y = radius * Math.cos(thetaStart + v * thetaLength); + z = radius * Math.sin(phiStart + u * phiLength) * Math.sin(thetaStart + v * thetaLength); + + pos[0] = x; pos[1] = y; pos[2] = z; + uv[0] = u; uv[1] = v; + positionAttr.set(offset, pos); + texcoordAttr.set(offset, uv); + pos[0] *= divider; + pos[1] *= divider; + pos[2] *= divider; + normalAttr.set(offset, pos); + offset++; + } + } + + var i1, i2, i3, i4; + + var len = widthSegments + 1; + + var n = 0; + for (j = 0; j < heightSegments; j ++) { + for (i = 0; i < widthSegments; i ++) { + i2 = j * len + i; + i1 = (j * len + i + 1); + i4 = (j + 1) * len + i + 1; + i3 = (j + 1) * len + i; + + indices[n++] = i1; + indices[n++] = i2; + indices[n++] = i4; + + indices[n++] = i2; + indices[n++] = i3; + indices[n++] = i4; + } + } + + this.boundingBox = new __WEBPACK_IMPORTED_MODULE_1__math_BoundingBox__["a" /* default */](); + this.boundingBox.max.set(radius, radius, radius); + this.boundingBox.min.set(-radius, -radius, -radius); + } +}); + +/* harmony default export */ __webpack_exports__["a"] = (Sphere); + + +/***/ }), +/* 133 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__Light__ = __webpack_require__(24); + + +/** + * @constructor clay.light.Ambient + * @extends clay.Light + */ +var AmbientLight = __WEBPACK_IMPORTED_MODULE_0__Light__["a" /* default */].extend({ + + castShadow: false + +}, { + + type: 'AMBIENT_LIGHT', + + uniformTemplates: { + ambientLightColor: { + type: '3f', + value: function(instance) { + var color = instance.color; + var intensity = instance.intensity; + return [color[0]*intensity, color[1]*intensity, color[2]*intensity]; + } + } + } + /** + * @function + * @name clone + * @return {clay.light.Ambient} + * @memberOf clay.light.Ambient.prototype + */ +}); + +/* harmony default export */ __webpack_exports__["a"] = (AmbientLight); + + +/***/ }), +/* 134 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__Light__ = __webpack_require__(24); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__math_Vector3__ = __webpack_require__(3); + + + +/** + * @constructor clay.light.Directional + * @extends clay.Light + * + * @example + * var light = new clay.light.Directional({ + * intensity: 0.5, + * color: [1.0, 0.0, 0.0] + * }); + * light.position.set(10, 10, 10); + * light.lookAt(clay.Vector3.ZERO); + * scene.add(light); + */ +var DirectionalLight = __WEBPACK_IMPORTED_MODULE_0__Light__["a" /* default */].extend(/** @lends clay.light.Directional# */ { + /** + * @type {number} + */ + shadowBias: 0.001, + /** + * @type {number} + */ + shadowSlopeScale: 2.0, + /** + * Shadow cascade. + * Use PSSM technique when it is larger than 1 and have a unique directional light in scene. + * @type {number} + */ + shadowCascade: 1, + + /** + * Available when shadowCascade is larger than 1 and have a unique directional light in scene. + * @type {number} + */ + cascadeSplitLogFactor: 0.2 +}, { + + type: 'DIRECTIONAL_LIGHT', + + uniformTemplates: { + directionalLightDirection: { + type: '3f', + value: function (instance) { + instance.__dir = instance.__dir || new __WEBPACK_IMPORTED_MODULE_1__math_Vector3__["a" /* default */](); + // Direction is target to eye + return instance.__dir.copy(instance.worldTransform.z).normalize().negate().array; + } + }, + directionalLightColor: { + type: '3f', + value: function (instance) { + var color = instance.color; + var intensity = instance.intensity; + return [color[0] * intensity, color[1] * intensity, color[2] * intensity]; + } + } + }, + /** + * @return {clay.light.Directional} + * @memberOf clay.light.Directional.prototype + */ + clone: function () { + var light = __WEBPACK_IMPORTED_MODULE_0__Light__["a" /* default */].prototype.clone.call(this); + light.shadowBias = this.shadowBias; + light.shadowSlopeScale = this.shadowSlopeScale; + return light; + } +}); + +/* harmony default export */ __webpack_exports__["a"] = (DirectionalLight); + + +/***/ }), +/* 135 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__Light__ = __webpack_require__(24); + + +/** + * @constructor clay.light.Point + * @extends clay.Light + */ +var PointLight = __WEBPACK_IMPORTED_MODULE_0__Light__["a" /* default */].extend(/** @lends clay.light.Point# */ { + /** + * @type {number} + */ + range: 100, + + /** + * @type {number} + */ + castShadow: false +}, { + + type: 'POINT_LIGHT', + + uniformTemplates: { + pointLightPosition: { + type: '3f', + value: function(instance) { + return instance.getWorldPosition().array; + } + }, + pointLightRange: { + type: '1f', + value: function(instance) { + return instance.range; + } + }, + pointLightColor: { + type: '3f', + value: function(instance) { + var color = instance.color; + var intensity = instance.intensity; + return [color[0] * intensity, color[1] * intensity, color[2] * intensity]; + } + } + }, + /** + * @return {clay.light.Point} + * @memberOf clay.light.Point.prototype + */ + clone: function() { + var light = __WEBPACK_IMPORTED_MODULE_0__Light__["a" /* default */].prototype.clone.call(this); + light.range = this.range; + return light; + } +}); + +/* harmony default export */ __webpack_exports__["a"] = (PointLight); + + +/***/ }), +/* 136 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__Light__ = __webpack_require__(24); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__math_Vector3__ = __webpack_require__(3); + + + +/** + * @constructor clay.light.Spot + * @extends clay.Light + */ +var SpotLight = __WEBPACK_IMPORTED_MODULE_0__Light__["a" /* default */].extend(/**@lends clay.light.Spot */ { + /** + * @type {number} + */ + range: 20, + /** + * @type {number} + */ + umbraAngle: 30, + /** + * @type {number} + */ + penumbraAngle: 45, + /** + * @type {number} + */ + falloffFactor: 2.0, + /** + * @type {number} + */ + shadowBias: 0.001, + /** + * @type {number} + */ + shadowSlopeScale: 2.0 +}, { + + type: 'SPOT_LIGHT', + + uniformTemplates: { + spotLightPosition: { + type: '3f', + value: function (instance) { + return instance.getWorldPosition().array; + } + }, + spotLightRange: { + type: '1f', + value: function (instance) { + return instance.range; + } + }, + spotLightUmbraAngleCosine: { + type: '1f', + value: function (instance) { + return Math.cos(instance.umbraAngle * Math.PI / 180); + } + }, + spotLightPenumbraAngleCosine: { + type: '1f', + value: function (instance) { + return Math.cos(instance.penumbraAngle * Math.PI / 180); + } + }, + spotLightFalloffFactor: { + type: '1f', + value: function (instance) { + return instance.falloffFactor; + } + }, + spotLightDirection: { + type: '3f', + value: function (instance) { + instance.__dir = instance.__dir || new __WEBPACK_IMPORTED_MODULE_1__math_Vector3__["a" /* default */](); + // Direction is target to eye + return instance.__dir.copy(instance.worldTransform.z).negate().array; + } + }, + spotLightColor: { + type: '3f', + value: function (instance) { + var color = instance.color; + var intensity = instance.intensity; + return [color[0] * intensity, color[1] * intensity, color[2] * intensity]; + } + } + }, + /** + * @return {clay.light.Spot} + * @memberOf clay.light.Spot.prototype + */ + clone: function () { + var light = __WEBPACK_IMPORTED_MODULE_0__Light__["a" /* default */].prototype.clone.call(this); + light.range = this.range; + light.umbraAngle = this.umbraAngle; + light.penumbraAngle = this.penumbraAngle; + light.falloffFactor = this.falloffFactor; + light.shadowBias = this.shadowBias; + light.shadowSlopeScale = this.shadowSlopeScale; + return light; + } +}); + +/* harmony default export */ __webpack_exports__["a"] = (SpotLight); + + +/***/ }), +/* 137 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec4__ = __webpack_require__(33); + + +/** + * @constructor + * @alias clay.Vector4 + * @param {number} x + * @param {number} y + * @param {number} z + * @param {number} w + */ +var Vector4 = function(x, y, z, w) { + + x = x || 0; + y = y || 0; + z = z || 0; + w = w || 0; + + /** + * Storage of Vector4, read and write of x, y, z, w will change the values in array + * All methods also operate on the array instead of x, y, z, w components + * @name array + * @type {Float32Array} + * @memberOf clay.Vector4# + */ + this.array = __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec4__["a" /* default */].fromValues(x, y, z, w); + + /** + * Dirty flag is used by the Node to determine + * if the matrix is updated to latest + * @name _dirty + * @type {boolean} + * @memberOf clay.Vector4# + */ + this._dirty = true; +}; + +Vector4.prototype = { + + constructor: Vector4, + + /** + * Add b to self + * @param {clay.Vector4} b + * @return {clay.Vector4} + */ + add: function(b) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec4__["a" /* default */].add(this.array, this.array, b.array); + this._dirty = true; + return this; + }, + + /** + * Set x, y and z components + * @param {number} x + * @param {number} y + * @param {number} z + * @param {number} w + * @return {clay.Vector4} + */ + set: function(x, y, z, w) { + this.array[0] = x; + this.array[1] = y; + this.array[2] = z; + this.array[3] = w; + this._dirty = true; + return this; + }, + + /** + * Set x, y, z and w components from array + * @param {Float32Array|number[]} arr + * @return {clay.Vector4} + */ + setArray: function(arr) { + this.array[0] = arr[0]; + this.array[1] = arr[1]; + this.array[2] = arr[2]; + this.array[3] = arr[3]; + + this._dirty = true; + return this; + }, + + /** + * Clone a new Vector4 + * @return {clay.Vector4} + */ + clone: function() { + return new Vector4(this.x, this.y, this.z, this.w); + }, + + /** + * Copy from b + * @param {clay.Vector4} b + * @return {clay.Vector4} + */ + copy: function(b) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec4__["a" /* default */].copy(this.array, b.array); + this._dirty = true; + return this; + }, + + /** + * Alias for distance + * @param {clay.Vector4} b + * @return {number} + */ + dist: function(b) { + return __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec4__["a" /* default */].dist(this.array, b.array); + }, + + /** + * Distance between self and b + * @param {clay.Vector4} b + * @return {number} + */ + distance: function(b) { + return __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec4__["a" /* default */].distance(this.array, b.array); + }, + + /** + * Alias for divide + * @param {clay.Vector4} b + * @return {clay.Vector4} + */ + div: function(b) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec4__["a" /* default */].div(this.array, this.array, b.array); + this._dirty = true; + return this; + }, + + /** + * Divide self by b + * @param {clay.Vector4} b + * @return {clay.Vector4} + */ + divide: function(b) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec4__["a" /* default */].divide(this.array, this.array, b.array); + this._dirty = true; + return this; + }, + + /** + * Dot product of self and b + * @param {clay.Vector4} b + * @return {number} + */ + dot: function(b) { + return __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec4__["a" /* default */].dot(this.array, b.array); + }, + + /** + * Alias of length + * @return {number} + */ + len: function() { + return __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec4__["a" /* default */].len(this.array); + }, + + /** + * Calculate the length + * @return {number} + */ + length: function() { + return __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec4__["a" /* default */].length(this.array); + }, + /** + * Linear interpolation between a and b + * @param {clay.Vector4} a + * @param {clay.Vector4} b + * @param {number} t + * @return {clay.Vector4} + */ + lerp: function(a, b, t) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec4__["a" /* default */].lerp(this.array, a.array, b.array, t); + this._dirty = true; + return this; + }, + + /** + * Minimum of self and b + * @param {clay.Vector4} b + * @return {clay.Vector4} + */ + min: function(b) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec4__["a" /* default */].min(this.array, this.array, b.array); + this._dirty = true; + return this; + }, + + /** + * Maximum of self and b + * @param {clay.Vector4} b + * @return {clay.Vector4} + */ + max: function(b) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec4__["a" /* default */].max(this.array, this.array, b.array); + this._dirty = true; + return this; + }, + + /** + * Alias for multiply + * @param {clay.Vector4} b + * @return {clay.Vector4} + */ + mul: function(b) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec4__["a" /* default */].mul(this.array, this.array, b.array); + this._dirty = true; + return this; + }, + + /** + * Mutiply self and b + * @param {clay.Vector4} b + * @return {clay.Vector4} + */ + multiply: function(b) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec4__["a" /* default */].multiply(this.array, this.array, b.array); + this._dirty = true; + return this; + }, + + /** + * Negate self + * @return {clay.Vector4} + */ + negate: function() { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec4__["a" /* default */].negate(this.array, this.array); + this._dirty = true; + return this; + }, + + /** + * Normalize self + * @return {clay.Vector4} + */ + normalize: function() { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec4__["a" /* default */].normalize(this.array, this.array); + this._dirty = true; + return this; + }, + + /** + * Generate random x, y, z, w components with a given scale + * @param {number} scale + * @return {clay.Vector4} + */ + random: function(scale) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec4__["a" /* default */].random(this.array, scale); + this._dirty = true; + return this; + }, + + /** + * Scale self + * @param {number} scale + * @return {clay.Vector4} + */ + scale: function(s) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec4__["a" /* default */].scale(this.array, this.array, s); + this._dirty = true; + return this; + }, + /** + * Scale b and add to self + * @param {clay.Vector4} b + * @param {number} scale + * @return {clay.Vector4} + */ + scaleAndAdd: function(b, s) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec4__["a" /* default */].scaleAndAdd(this.array, this.array, b.array, s); + this._dirty = true; + return this; + }, + + /** + * Alias for squaredDistance + * @param {clay.Vector4} b + * @return {number} + */ + sqrDist: function(b) { + return __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec4__["a" /* default */].sqrDist(this.array, b.array); + }, + + /** + * Squared distance between self and b + * @param {clay.Vector4} b + * @return {number} + */ + squaredDistance: function(b) { + return __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec4__["a" /* default */].squaredDistance(this.array, b.array); + }, + + /** + * Alias for squaredLength + * @return {number} + */ + sqrLen: function() { + return __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec4__["a" /* default */].sqrLen(this.array); + }, + + /** + * Squared length of self + * @return {number} + */ + squaredLength: function() { + return __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec4__["a" /* default */].squaredLength(this.array); + }, + + /** + * Alias for subtract + * @param {clay.Vector4} b + * @return {clay.Vector4} + */ + sub: function(b) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec4__["a" /* default */].sub(this.array, this.array, b.array); + this._dirty = true; + return this; + }, + + /** + * Subtract b from self + * @param {clay.Vector4} b + * @return {clay.Vector4} + */ + subtract: function(b) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec4__["a" /* default */].subtract(this.array, this.array, b.array); + this._dirty = true; + return this; + }, + + /** + * Transform self with a Matrix4 m + * @param {clay.Matrix4} m + * @return {clay.Vector4} + */ + transformMat4: function(m) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec4__["a" /* default */].transformMat4(this.array, this.array, m.array); + this._dirty = true; + return this; + }, + + /** + * Transform self with a Quaternion q + * @param {clay.Quaternion} q + * @return {clay.Vector4} + */ + transformQuat: function(q) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec4__["a" /* default */].transformQuat(this.array, this.array, q.array); + this._dirty = true; + return this; + }, + + toString: function() { + return '[' + Array.prototype.join.call(this.array, ',') + ']'; + }, + + toArray: function () { + return Array.prototype.slice.call(this.array); + } +}; + +var defineProperty = Object.defineProperty; +// Getter and Setter +if (defineProperty) { + + var proto = Vector4.prototype; + /** + * @name x + * @type {number} + * @memberOf clay.Vector4 + * @instance + */ + defineProperty(proto, 'x', { + get: function () { + return this.array[0]; + }, + set: function (value) { + this.array[0] = value; + this._dirty = true; + } + }); + + /** + * @name y + * @type {number} + * @memberOf clay.Vector4 + * @instance + */ + defineProperty(proto, 'y', { + get: function () { + return this.array[1]; + }, + set: function (value) { + this.array[1] = value; + this._dirty = true; + } + }); + + /** + * @name z + * @type {number} + * @memberOf clay.Vector4 + * @instance + */ + defineProperty(proto, 'z', { + get: function () { + return this.array[2]; + }, + set: function (value) { + this.array[2] = value; + this._dirty = true; + } + }); + + /** + * @name w + * @type {number} + * @memberOf clay.Vector4 + * @instance + */ + defineProperty(proto, 'w', { + get: function () { + return this.array[3]; + }, + set: function (value) { + this.array[3] = value; + this._dirty = true; + } + }); +} + +// Supply methods that are not in place + +/** + * @param {clay.Vector4} out + * @param {clay.Vector4} a + * @param {clay.Vector4} b + * @return {clay.Vector4} + */ +Vector4.add = function(out, a, b) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec4__["a" /* default */].add(out.array, a.array, b.array); + out._dirty = true; + return out; +}; + +/** + * @param {clay.Vector4} out + * @param {number} x + * @param {number} y + * @param {number} z + * @return {clay.Vector4} + */ +Vector4.set = function(out, x, y, z, w) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec4__["a" /* default */].set(out.array, x, y, z, w); + out._dirty = true; +}; + +/** + * @param {clay.Vector4} out + * @param {clay.Vector4} b + * @return {clay.Vector4} + */ +Vector4.copy = function(out, b) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec4__["a" /* default */].copy(out.array, b.array); + out._dirty = true; + return out; +}; + +/** + * @param {clay.Vector4} a + * @param {clay.Vector4} b + * @return {number} + */ +Vector4.dist = function(a, b) { + return __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec4__["a" /* default */].distance(a.array, b.array); +}; + +/** + * @function + * @param {clay.Vector4} a + * @param {clay.Vector4} b + * @return {number} + */ +Vector4.distance = Vector4.dist; + +/** + * @param {clay.Vector4} out + * @param {clay.Vector4} a + * @param {clay.Vector4} b + * @return {clay.Vector4} + */ +Vector4.div = function(out, a, b) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec4__["a" /* default */].divide(out.array, a.array, b.array); + out._dirty = true; + return out; +}; + +/** + * @function + * @param {clay.Vector4} out + * @param {clay.Vector4} a + * @param {clay.Vector4} b + * @return {clay.Vector4} + */ +Vector4.divide = Vector4.div; + +/** + * @param {clay.Vector4} a + * @param {clay.Vector4} b + * @return {number} + */ +Vector4.dot = function(a, b) { + return __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec4__["a" /* default */].dot(a.array, b.array); +}; + +/** + * @param {clay.Vector4} a + * @return {number} + */ +Vector4.len = function(b) { + return __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec4__["a" /* default */].length(b.array); +}; + +// Vector4.length = Vector4.len; + +/** + * @param {clay.Vector4} out + * @param {clay.Vector4} a + * @param {clay.Vector4} b + * @param {number} t + * @return {clay.Vector4} + */ +Vector4.lerp = function(out, a, b, t) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec4__["a" /* default */].lerp(out.array, a.array, b.array, t); + out._dirty = true; + return out; +}; + +/** + * @param {clay.Vector4} out + * @param {clay.Vector4} a + * @param {clay.Vector4} b + * @return {clay.Vector4} + */ +Vector4.min = function(out, a, b) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec4__["a" /* default */].min(out.array, a.array, b.array); + out._dirty = true; + return out; +}; + +/** + * @param {clay.Vector4} out + * @param {clay.Vector4} a + * @param {clay.Vector4} b + * @return {clay.Vector4} + */ +Vector4.max = function(out, a, b) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec4__["a" /* default */].max(out.array, a.array, b.array); + out._dirty = true; + return out; +}; + +/** + * @param {clay.Vector4} out + * @param {clay.Vector4} a + * @param {clay.Vector4} b + * @return {clay.Vector4} + */ +Vector4.mul = function(out, a, b) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec4__["a" /* default */].multiply(out.array, a.array, b.array); + out._dirty = true; + return out; +}; + +/** + * @function + * @param {clay.Vector4} out + * @param {clay.Vector4} a + * @param {clay.Vector4} b + * @return {clay.Vector4} + */ +Vector4.multiply = Vector4.mul; + +/** + * @param {clay.Vector4} out + * @param {clay.Vector4} a + * @return {clay.Vector4} + */ +Vector4.negate = function(out, a) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec4__["a" /* default */].negate(out.array, a.array); + out._dirty = true; + return out; +}; + +/** + * @param {clay.Vector4} out + * @param {clay.Vector4} a + * @return {clay.Vector4} + */ +Vector4.normalize = function(out, a) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec4__["a" /* default */].normalize(out.array, a.array); + out._dirty = true; + return out; +}; + +/** + * @param {clay.Vector4} out + * @param {number} scale + * @return {clay.Vector4} + */ +Vector4.random = function(out, scale) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec4__["a" /* default */].random(out.array, scale); + out._dirty = true; + return out; +}; + +/** + * @param {clay.Vector4} out + * @param {clay.Vector4} a + * @param {number} scale + * @return {clay.Vector4} + */ +Vector4.scale = function(out, a, scale) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec4__["a" /* default */].scale(out.array, a.array, scale); + out._dirty = true; + return out; +}; + +/** + * @param {clay.Vector4} out + * @param {clay.Vector4} a + * @param {clay.Vector4} b + * @param {number} scale + * @return {clay.Vector4} + */ +Vector4.scaleAndAdd = function(out, a, b, scale) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec4__["a" /* default */].scaleAndAdd(out.array, a.array, b.array, scale); + out._dirty = true; + return out; +}; + +/** + * @param {clay.Vector4} a + * @param {clay.Vector4} b + * @return {number} + */ +Vector4.sqrDist = function(a, b) { + return __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec4__["a" /* default */].sqrDist(a.array, b.array); +}; + +/** + * @function + * @param {clay.Vector4} a + * @param {clay.Vector4} b + * @return {number} + */ +Vector4.squaredDistance = Vector4.sqrDist; + +/** + * @param {clay.Vector4} a + * @return {number} + */ +Vector4.sqrLen = function(a) { + return __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec4__["a" /* default */].sqrLen(a.array); +}; +/** + * @function + * @param {clay.Vector4} a + * @return {number} + */ +Vector4.squaredLength = Vector4.sqrLen; + +/** + * @param {clay.Vector4} out + * @param {clay.Vector4} a + * @param {clay.Vector4} b + * @return {clay.Vector4} + */ +Vector4.sub = function(out, a, b) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec4__["a" /* default */].subtract(out.array, a.array, b.array); + out._dirty = true; + return out; +}; +/** + * @function + * @param {clay.Vector4} out + * @param {clay.Vector4} a + * @param {clay.Vector4} b + * @return {clay.Vector4} + */ +Vector4.subtract = Vector4.sub; + +/** + * @param {clay.Vector4} out + * @param {clay.Vector4} a + * @param {clay.Matrix4} m + * @return {clay.Vector4} + */ +Vector4.transformMat4 = function(out, a, m) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec4__["a" /* default */].transformMat4(out.array, a.array, m.array); + out._dirty = true; + return out; +}; + +/** + * @param {clay.Vector4} out + * @param {clay.Vector4} a + * @param {clay.Quaternion} q + * @return {clay.Vector4} + */ +Vector4.transformQuat = function(out, a, q) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_vec4__["a" /* default */].transformQuat(out.array, a.array, q.array); + out._dirty = true; + return out; +}; + +/* harmony default export */ __webpack_exports__["a"] = (Vector4); + + +/***/ }), +/* 138 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat2__ = __webpack_require__(78); + + +/** + * @constructor + * @alias clay.Matrix2 + */ +var Matrix2 = function() { + + /** + * Storage of Matrix2 + * @name array + * @type {Float32Array} + * @memberOf clay.Matrix2# + */ + this.array = __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat2__["a" /* default */].create(); + + /** + * @name _dirty + * @type {boolean} + * @memberOf clay.Matrix2# + */ + this._dirty = true; +}; + +Matrix2.prototype = { + + constructor: Matrix2, + + /** + * Set components from array + * @param {Float32Array|number[]} arr + */ + setArray: function (arr) { + for (var i = 0; i < this.array.length; i++) { + this.array[i] = arr[i]; + } + this._dirty = true; + return this; + }, + /** + * Clone a new Matrix2 + * @return {clay.Matrix2} + */ + clone: function() { + return (new Matrix2()).copy(this); + }, + + /** + * Copy from b + * @param {clay.Matrix2} b + * @return {clay.Matrix2} + */ + copy: function(b) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat2__["a" /* default */].copy(this.array, b.array); + this._dirty = true; + return this; + }, + + /** + * Calculate the adjugate of self, in-place + * @return {clay.Matrix2} + */ + adjoint: function() { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat2__["a" /* default */].adjoint(this.array, this.array); + this._dirty = true; + return this; + }, + + /** + * Calculate matrix determinant + * @return {number} + */ + determinant: function() { + return __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat2__["a" /* default */].determinant(this.array); + }, + + /** + * Set to a identity matrix + * @return {clay.Matrix2} + */ + identity: function() { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat2__["a" /* default */].identity(this.array); + this._dirty = true; + return this; + }, + + /** + * Invert self + * @return {clay.Matrix2} + */ + invert: function() { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat2__["a" /* default */].invert(this.array, this.array); + this._dirty = true; + return this; + }, + + /** + * Alias for mutiply + * @param {clay.Matrix2} b + * @return {clay.Matrix2} + */ + mul: function(b) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat2__["a" /* default */].mul(this.array, this.array, b.array); + this._dirty = true; + return this; + }, + + /** + * Alias for multiplyLeft + * @param {clay.Matrix2} a + * @return {clay.Matrix2} + */ + mulLeft: function(a) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat2__["a" /* default */].mul(this.array, a.array, this.array); + this._dirty = true; + return this; + }, + + /** + * Multiply self and b + * @param {clay.Matrix2} b + * @return {clay.Matrix2} + */ + multiply: function(b) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat2__["a" /* default */].multiply(this.array, this.array, b.array); + this._dirty = true; + return this; + }, + + /** + * Multiply a and self, a is on the left + * @param {clay.Matrix2} a + * @return {clay.Matrix2} + */ + multiplyLeft: function(a) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat2__["a" /* default */].multiply(this.array, a.array, this.array); + this._dirty = true; + return this; + }, + + /** + * Rotate self by a given radian + * @param {number} rad + * @return {clay.Matrix2} + */ + rotate: function(rad) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat2__["a" /* default */].rotate(this.array, this.array, rad); + this._dirty = true; + return this; + }, + + /** + * Scale self by s + * @param {clay.Vector2} s + * @return {clay.Matrix2} + */ + scale: function(v) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat2__["a" /* default */].scale(this.array, this.array, v.array); + this._dirty = true; + return this; + }, + /** + * Transpose self, in-place. + * @return {clay.Matrix2} + */ + transpose: function() { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat2__["a" /* default */].transpose(this.array, this.array); + this._dirty = true; + return this; + }, + + toString: function() { + return '[' + Array.prototype.join.call(this.array, ',') + ']'; + }, + + toArray: function () { + return Array.prototype.slice.call(this.array); + } +}; + +/** + * @param {Matrix2} out + * @param {Matrix2} a + * @return {Matrix2} + */ +Matrix2.adjoint = function(out, a) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat2__["a" /* default */].adjoint(out.array, a.array); + out._dirty = true; + return out; +}; + +/** + * @param {clay.Matrix2} out + * @param {clay.Matrix2} a + * @return {clay.Matrix2} + */ +Matrix2.copy = function(out, a) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat2__["a" /* default */].copy(out.array, a.array); + out._dirty = true; + return out; +}; + +/** + * @param {clay.Matrix2} a + * @return {number} + */ +Matrix2.determinant = function(a) { + return __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat2__["a" /* default */].determinant(a.array); +}; + +/** + * @param {clay.Matrix2} out + * @return {clay.Matrix2} + */ +Matrix2.identity = function(out) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat2__["a" /* default */].identity(out.array); + out._dirty = true; + return out; +}; + +/** + * @param {clay.Matrix2} out + * @param {clay.Matrix2} a + * @return {clay.Matrix2} + */ +Matrix2.invert = function(out, a) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat2__["a" /* default */].invert(out.array, a.array); + out._dirty = true; + return out; +}; + +/** + * @param {clay.Matrix2} out + * @param {clay.Matrix2} a + * @param {clay.Matrix2} b + * @return {clay.Matrix2} + */ +Matrix2.mul = function(out, a, b) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat2__["a" /* default */].mul(out.array, a.array, b.array); + out._dirty = true; + return out; +}; + +/** + * @function + * @param {clay.Matrix2} out + * @param {clay.Matrix2} a + * @param {clay.Matrix2} b + * @return {clay.Matrix2} + */ +Matrix2.multiply = Matrix2.mul; + +/** + * @param {clay.Matrix2} out + * @param {clay.Matrix2} a + * @param {number} rad + * @return {clay.Matrix2} + */ +Matrix2.rotate = function(out, a, rad) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat2__["a" /* default */].rotate(out.array, a.array, rad); + out._dirty = true; + return out; +}; + +/** + * @param {clay.Matrix2} out + * @param {clay.Matrix2} a + * @param {clay.Vector2} v + * @return {clay.Matrix2} + */ +Matrix2.scale = function(out, a, v) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat2__["a" /* default */].scale(out.array, a.array, v.array); + out._dirty = true; + return out; +}; +/** + * @param {Matrix2} out + * @param {Matrix2} a + * @return {Matrix2} + */ +Matrix2.transpose = function(out, a) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat2__["a" /* default */].transpose(out.array, a.array); + out._dirty = true; + return out; +}; + +/* harmony default export */ __webpack_exports__["a"] = (Matrix2); + + +/***/ }), +/* 139 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat2d__ = __webpack_require__(79); + + +/** + * @constructor + * @alias clay.Matrix2d + */ +var Matrix2d = function() { + /** + * Storage of Matrix2d + * @name array + * @type {Float32Array} + * @memberOf clay.Matrix2d# + */ + this.array = __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat2d__["a" /* default */].create(); + + /** + * @name _dirty + * @type {boolean} + * @memberOf clay.Matrix2d# + */ + this._dirty = true; +}; + +Matrix2d.prototype = { + + constructor: Matrix2d, + + /** + * Set components from array + * @param {Float32Array|number[]} arr + */ + setArray: function (arr) { + for (var i = 0; i < this.array.length; i++) { + this.array[i] = arr[i]; + } + this._dirty = true; + return this; + }, + /** + * Clone a new Matrix2d + * @return {clay.Matrix2d} + */ + clone: function() { + return (new Matrix2d()).copy(this); + }, + + /** + * Copy from b + * @param {clay.Matrix2d} b + * @return {clay.Matrix2d} + */ + copy: function(b) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat2d__["a" /* default */].copy(this.array, b.array); + this._dirty = true; + return this; + }, + + /** + * Calculate matrix determinant + * @return {number} + */ + determinant: function() { + return __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat2d__["a" /* default */].determinant(this.array); + }, + + /** + * Set to a identity matrix + * @return {clay.Matrix2d} + */ + identity: function() { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat2d__["a" /* default */].identity(this.array); + this._dirty = true; + return this; + }, + + /** + * Invert self + * @return {clay.Matrix2d} + */ + invert: function() { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat2d__["a" /* default */].invert(this.array, this.array); + this._dirty = true; + return this; + }, + + /** + * Alias for mutiply + * @param {clay.Matrix2d} b + * @return {clay.Matrix2d} + */ + mul: function(b) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat2d__["a" /* default */].mul(this.array, this.array, b.array); + this._dirty = true; + return this; + }, + + /** + * Alias for multiplyLeft + * @param {clay.Matrix2d} a + * @return {clay.Matrix2d} + */ + mulLeft: function(b) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat2d__["a" /* default */].mul(this.array, b.array, this.array); + this._dirty = true; + return this; + }, + + /** + * Multiply self and b + * @param {clay.Matrix2d} b + * @return {clay.Matrix2d} + */ + multiply: function(b) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat2d__["a" /* default */].multiply(this.array, this.array, b.array); + this._dirty = true; + return this; + }, + + /** + * Multiply a and self, a is on the left + * @param {clay.Matrix2d} a + * @return {clay.Matrix2d} + */ + multiplyLeft: function(b) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat2d__["a" /* default */].multiply(this.array, b.array, this.array); + this._dirty = true; + return this; + }, + + /** + * Rotate self by a given radian + * @param {number} rad + * @return {clay.Matrix2d} + */ + rotate: function(rad) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat2d__["a" /* default */].rotate(this.array, this.array, rad); + this._dirty = true; + return this; + }, + + /** + * Scale self by s + * @param {clay.Vector2} s + * @return {clay.Matrix2d} + */ + scale: function(s) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat2d__["a" /* default */].scale(this.array, this.array, s.array); + this._dirty = true; + return this; + }, + + /** + * Translate self by v + * @param {clay.Vector2} v + * @return {clay.Matrix2d} + */ + translate: function(v) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat2d__["a" /* default */].translate(this.array, this.array, v.array); + this._dirty = true; + return this; + }, + + toString: function() { + return '[' + Array.prototype.join.call(this.array, ',') + ']'; + }, + + toArray: function () { + return Array.prototype.slice.call(this.array); + } +}; + +/** + * @param {clay.Matrix2d} out + * @param {clay.Matrix2d} a + * @return {clay.Matrix2d} + */ +Matrix2d.copy = function(out, a) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat2d__["a" /* default */].copy(out.array, a.array); + out._dirty = true; + return out; +}; + +/** + * @param {clay.Matrix2d} a + * @return {number} + */ +Matrix2d.determinant = function(a) { + return __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat2d__["a" /* default */].determinant(a.array); +}; + +/** + * @param {clay.Matrix2d} out + * @return {clay.Matrix2d} + */ +Matrix2d.identity = function(out) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat2d__["a" /* default */].identity(out.array); + out._dirty = true; + return out; +}; + +/** + * @param {clay.Matrix2d} out + * @param {clay.Matrix2d} a + * @return {clay.Matrix2d} + */ +Matrix2d.invert = function(out, a) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat2d__["a" /* default */].invert(out.array, a.array); + out._dirty = true; + return out; +}; + +/** + * @param {clay.Matrix2d} out + * @param {clay.Matrix2d} a + * @param {clay.Matrix2d} b + * @return {clay.Matrix2d} + */ +Matrix2d.mul = function(out, a, b) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat2d__["a" /* default */].mul(out.array, a.array, b.array); + out._dirty = true; + return out; +}; + +/** + * @function + * @param {clay.Matrix2d} out + * @param {clay.Matrix2d} a + * @param {clay.Matrix2d} b + * @return {clay.Matrix2d} + */ +Matrix2d.multiply = Matrix2d.mul; + +/** + * @param {clay.Matrix2d} out + * @param {clay.Matrix2d} a + * @param {number} rad + * @return {clay.Matrix2d} + */ +Matrix2d.rotate = function(out, a, rad) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat2d__["a" /* default */].rotate(out.array, a.array, rad); + out._dirty = true; + return out; +}; + +/** + * @param {clay.Matrix2d} out + * @param {clay.Matrix2d} a + * @param {clay.Vector2} v + * @return {clay.Matrix2d} + */ +Matrix2d.scale = function(out, a, v) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat2d__["a" /* default */].scale(out.array, a.array, v.array); + out._dirty = true; + return out; +}; + +/** + * @param {clay.Matrix2d} out + * @param {clay.Matrix2d} a + * @param {clay.Vector2} v + * @return {clay.Matrix2d} + */ +Matrix2d.translate = function(out, a, v) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat2d__["a" /* default */].translate(out.array, a.array, v.array); + out._dirty = true; + return out; +}; + +/* harmony default export */ __webpack_exports__["a"] = (Matrix2d); + + +/***/ }), +/* 140 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat3__ = __webpack_require__(34); + + +/** + * @constructor + * @alias clay.Matrix3 + */ +var Matrix3 = function () { + + /** + * Storage of Matrix3 + * @name array + * @type {Float32Array} + * @memberOf clay.Matrix3# + */ + this.array = __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat3__["a" /* default */].create(); + + /** + * @name _dirty + * @type {boolean} + * @memberOf clay.Matrix3# + */ + this._dirty = true; +}; + +Matrix3.prototype = { + + constructor: Matrix3, + + /** + * Set components from array + * @param {Float32Array|number[]} arr + */ + setArray: function (arr) { + for (var i = 0; i < this.array.length; i++) { + this.array[i] = arr[i]; + } + this._dirty = true; + return this; + }, + /** + * Calculate the adjugate of self, in-place + * @return {clay.Matrix3} + */ + adjoint: function () { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat3__["a" /* default */].adjoint(this.array, this.array); + this._dirty = true; + return this; + }, + + /** + * Clone a new Matrix3 + * @return {clay.Matrix3} + */ + clone: function () { + return (new Matrix3()).copy(this); + }, + + /** + * Copy from b + * @param {clay.Matrix3} b + * @return {clay.Matrix3} + */ + copy: function (b) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat3__["a" /* default */].copy(this.array, b.array); + this._dirty = true; + return this; + }, + + /** + * Calculate matrix determinant + * @return {number} + */ + determinant: function () { + return __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat3__["a" /* default */].determinant(this.array); + }, + + /** + * Copy the values from Matrix2d a + * @param {clay.Matrix2d} a + * @return {clay.Matrix3} + */ + fromMat2d: function (a) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat3__["a" /* default */].fromMat2d(this.array, a.array); + this._dirty = true; + return this; + }, + + /** + * Copies the upper-left 3x3 values of Matrix4 + * @param {clay.Matrix4} a + * @return {clay.Matrix3} + */ + fromMat4: function (a) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat3__["a" /* default */].fromMat4(this.array, a.array); + this._dirty = true; + return this; + }, + + /** + * Calculates a rotation matrix from the given quaternion + * @param {clay.Quaternion} q + * @return {clay.Matrix3} + */ + fromQuat: function (q) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat3__["a" /* default */].fromQuat(this.array, q.array); + this._dirty = true; + return this; + }, + + /** + * Set to a identity matrix + * @return {clay.Matrix3} + */ + identity: function () { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat3__["a" /* default */].identity(this.array); + this._dirty = true; + return this; + }, + + /** + * Invert self + * @return {clay.Matrix3} + */ + invert: function () { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat3__["a" /* default */].invert(this.array, this.array); + this._dirty = true; + return this; + }, + + /** + * Alias for mutiply + * @param {clay.Matrix3} b + * @return {clay.Matrix3} + */ + mul: function (b) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat3__["a" /* default */].mul(this.array, this.array, b.array); + this._dirty = true; + return this; + }, + + /** + * Alias for multiplyLeft + * @param {clay.Matrix3} a + * @return {clay.Matrix3} + */ + mulLeft: function (a) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat3__["a" /* default */].mul(this.array, a.array, this.array); + this._dirty = true; + return this; + }, + + /** + * Multiply self and b + * @param {clay.Matrix3} b + * @return {clay.Matrix3} + */ + multiply: function (b) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat3__["a" /* default */].multiply(this.array, this.array, b.array); + this._dirty = true; + return this; + }, + + /** + * Multiply a and self, a is on the left + * @param {clay.Matrix3} a + * @return {clay.Matrix3} + */ + multiplyLeft: function (a) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat3__["a" /* default */].multiply(this.array, a.array, this.array); + this._dirty = true; + return this; + }, + + /** + * Rotate self by a given radian + * @param {number} rad + * @return {clay.Matrix3} + */ + rotate: function (rad) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat3__["a" /* default */].rotate(this.array, this.array, rad); + this._dirty = true; + return this; + }, + + /** + * Scale self by s + * @param {clay.Vector2} s + * @return {clay.Matrix3} + */ + scale: function (v) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat3__["a" /* default */].scale(this.array, this.array, v.array); + this._dirty = true; + return this; + }, + + /** + * Translate self by v + * @param {clay.Vector2} v + * @return {clay.Matrix3} + */ + translate: function (v) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat3__["a" /* default */].translate(this.array, this.array, v.array); + this._dirty = true; + return this; + }, + /** + * Calculates a 3x3 normal matrix (transpose inverse) from the 4x4 matrix + * @param {clay.Matrix4} a + */ + normalFromMat4: function (a) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat3__["a" /* default */].normalFromMat4(this.array, a.array); + this._dirty = true; + return this; + }, + + /** + * Transpose self, in-place. + * @return {clay.Matrix2} + */ + transpose: function () { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat3__["a" /* default */].transpose(this.array, this.array); + this._dirty = true; + return this; + }, + + toString: function () { + return '[' + Array.prototype.join.call(this.array, ',') + ']'; + }, + + toArray: function () { + return Array.prototype.slice.call(this.array); + } +}; +/** + * @param {clay.Matrix3} out + * @param {clay.Matrix3} a + * @return {clay.Matrix3} + */ +Matrix3.adjoint = function (out, a) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat3__["a" /* default */].adjoint(out.array, a.array); + out._dirty = true; + return out; +}; + +/** + * @param {clay.Matrix3} out + * @param {clay.Matrix3} a + * @return {clay.Matrix3} + */ +Matrix3.copy = function (out, a) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat3__["a" /* default */].copy(out.array, a.array); + out._dirty = true; + return out; +}; + +/** + * @param {clay.Matrix3} a + * @return {number} + */ +Matrix3.determinant = function (a) { + return __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat3__["a" /* default */].determinant(a.array); +}; + +/** + * @param {clay.Matrix3} out + * @return {clay.Matrix3} + */ +Matrix3.identity = function (out) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat3__["a" /* default */].identity(out.array); + out._dirty = true; + return out; +}; + +/** + * @param {clay.Matrix3} out + * @param {clay.Matrix3} a + * @return {clay.Matrix3} + */ +Matrix3.invert = function (out, a) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat3__["a" /* default */].invert(out.array, a.array); + return out; +}; + +/** + * @param {clay.Matrix3} out + * @param {clay.Matrix3} a + * @param {clay.Matrix3} b + * @return {clay.Matrix3} + */ +Matrix3.mul = function (out, a, b) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat3__["a" /* default */].mul(out.array, a.array, b.array); + out._dirty = true; + return out; +}; + +/** + * @function + * @param {clay.Matrix3} out + * @param {clay.Matrix3} a + * @param {clay.Matrix3} b + * @return {clay.Matrix3} + */ +Matrix3.multiply = Matrix3.mul; + +/** + * @param {clay.Matrix3} out + * @param {clay.Matrix2d} a + * @return {clay.Matrix3} + */ +Matrix3.fromMat2d = function (out, a) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat3__["a" /* default */].fromMat2d(out.array, a.array); + out._dirty = true; + return out; +}; + +/** + * @param {clay.Matrix3} out + * @param {clay.Matrix4} a + * @return {clay.Matrix3} + */ +Matrix3.fromMat4 = function (out, a) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat3__["a" /* default */].fromMat4(out.array, a.array); + out._dirty = true; + return out; +}; + +/** + * @param {clay.Matrix3} out + * @param {clay.Quaternion} a + * @return {clay.Matrix3} + */ +Matrix3.fromQuat = function (out, q) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat3__["a" /* default */].fromQuat(out.array, q.array); + out._dirty = true; + return out; +}; + +/** + * @param {clay.Matrix3} out + * @param {clay.Matrix4} a + * @return {clay.Matrix3} + */ +Matrix3.normalFromMat4 = function (out, a) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat3__["a" /* default */].normalFromMat4(out.array, a.array); + out._dirty = true; + return out; +}; + +/** + * @param {clay.Matrix3} out + * @param {clay.Matrix3} a + * @param {number} rad + * @return {clay.Matrix3} + */ +Matrix3.rotate = function (out, a, rad) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat3__["a" /* default */].rotate(out.array, a.array, rad); + out._dirty = true; + return out; +}; + +/** + * @param {clay.Matrix3} out + * @param {clay.Matrix3} a + * @param {clay.Vector2} v + * @return {clay.Matrix3} + */ +Matrix3.scale = function (out, a, v) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat3__["a" /* default */].scale(out.array, a.array, v.array); + out._dirty = true; + return out; +}; + +/** + * @param {clay.Matrix3} out + * @param {clay.Matrix3} a + * @return {clay.Matrix3} + */ +Matrix3.transpose = function (out, a) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat3__["a" /* default */].transpose(out.array, a.array); + out._dirty = true; + return out; +}; + +/** + * @param {clay.Matrix3} out + * @param {clay.Matrix3} a + * @param {clay.Vector2} v + * @return {clay.Matrix3} + */ +Matrix3.translate = function (out, a, v) { + __WEBPACK_IMPORTED_MODULE_0__glmatrix_mat3__["a" /* default */].translate(out.array, a.array, v.array); + out._dirty = true; + return out; +}; + +/* harmony default export */ __webpack_exports__["a"] = (Matrix3); + + +/***/ }), +/* 141 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_zrender_lib_animation_Animator__ = __webpack_require__(142); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_zrender_lib_animation_Animator___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_zrender_lib_animation_Animator__); + + +var animatableMixin = { + + _animators: null, + + getAnimators: function () { + this._animators = this._animators || []; + + return this._animators; + }, + + animate: function (path, opts) { + this._animators = this._animators || []; + + var el = this; + + var target; + + if (path) { + var pathSplitted = path.split('.'); + var prop = el; + for (var i = 0, l = pathSplitted.length; i < l; i++) { + if (!prop) { + continue; + } + prop = prop[pathSplitted[i]]; + } + if (prop) { + target = prop; + } + } + else { + target = el; + } + if (target == null) { + throw new Error('Target ' + path + ' not exists'); + } + + var animators = this._animators; + + var animator = new __WEBPACK_IMPORTED_MODULE_0_zrender_lib_animation_Animator___default.a(target, opts); + var self = this; + animator.during(function () { + if (self.__zr) { + self.__zr.refresh(); + } + }).done(function () { + var idx = animators.indexOf(animator); + if (idx >= 0) { + animators.splice(idx, 1); + } + }); + animators.push(animator); + + if (this.__zr) { + this.__zr.animation.addAnimator(animator); + } + + return animator; + }, + + stopAnimation: function (forwardToLast) { + this._animators = this._animators || []; + + var animators = this._animators; + var len = animators.length; + for (var i = 0; i < len; i++) { + animators[i].stop(forwardToLast); + } + animators.length = 0; + + return this; + }, + + addAnimatorsToZr: function (zr) { + if (this._animators) { + for (var i = 0; i < this._animators.length; i++) { + zr.animation.addAnimator(this._animators[i]); + } + } + }, + + removeAnimatorsFromZr: function (zr) { + if (this._animators) { + for (var i = 0; i < this._animators.length; i++) { + zr.animation.removeAnimator(this._animators[i]); + } + } + } +}; + +/* harmony default export */ __webpack_exports__["a"] = (animatableMixin); + +/***/ }), +/* 142 */ +/***/ (function(module, exports, __webpack_require__) { + +var Clip = __webpack_require__(143); + +var color = __webpack_require__(145); + +var _util = __webpack_require__(13); + +var isArrayLike = _util.isArrayLike; + +/** + * @module echarts/animation/Animator + */ +var arraySlice = Array.prototype.slice; + +function defaultGetter(target, key) { + return target[key]; +} + +function defaultSetter(target, key, value) { + target[key] = value; +} +/** + * @param {number} p0 + * @param {number} p1 + * @param {number} percent + * @return {number} + */ + + +function interpolateNumber(p0, p1, percent) { + return (p1 - p0) * percent + p0; +} +/** + * @param {string} p0 + * @param {string} p1 + * @param {number} percent + * @return {string} + */ + + +function interpolateString(p0, p1, percent) { + return percent > 0.5 ? p1 : p0; +} +/** + * @param {Array} p0 + * @param {Array} p1 + * @param {number} percent + * @param {Array} out + * @param {number} arrDim + */ + + +function interpolateArray(p0, p1, percent, out, arrDim) { + var len = p0.length; + + if (arrDim == 1) { + for (var i = 0; i < len; i++) { + out[i] = interpolateNumber(p0[i], p1[i], percent); + } + } else { + var len2 = len && p0[0].length; + + for (var i = 0; i < len; i++) { + for (var j = 0; j < len2; j++) { + out[i][j] = interpolateNumber(p0[i][j], p1[i][j], percent); + } + } + } +} // arr0 is source array, arr1 is target array. +// Do some preprocess to avoid error happened when interpolating from arr0 to arr1 + + +function fillArr(arr0, arr1, arrDim) { + var arr0Len = arr0.length; + var arr1Len = arr1.length; + + if (arr0Len !== arr1Len) { + // FIXME Not work for TypedArray + var isPreviousLarger = arr0Len > arr1Len; + + if (isPreviousLarger) { + // Cut the previous + arr0.length = arr1Len; + } else { + // Fill the previous + for (var i = arr0Len; i < arr1Len; i++) { + arr0.push(arrDim === 1 ? arr1[i] : arraySlice.call(arr1[i])); + } + } + } // Handling NaN value + + + var len2 = arr0[0] && arr0[0].length; + + for (var i = 0; i < arr0.length; i++) { + if (arrDim === 1) { + if (isNaN(arr0[i])) { + arr0[i] = arr1[i]; + } + } else { + for (var j = 0; j < len2; j++) { + if (isNaN(arr0[i][j])) { + arr0[i][j] = arr1[i][j]; + } + } + } + } +} +/** + * @param {Array} arr0 + * @param {Array} arr1 + * @param {number} arrDim + * @return {boolean} + */ + + +function isArraySame(arr0, arr1, arrDim) { + if (arr0 === arr1) { + return true; + } + + var len = arr0.length; + + if (len !== arr1.length) { + return false; + } + + if (arrDim === 1) { + for (var i = 0; i < len; i++) { + if (arr0[i] !== arr1[i]) { + return false; + } + } + } else { + var len2 = arr0[0].length; + + for (var i = 0; i < len; i++) { + for (var j = 0; j < len2; j++) { + if (arr0[i][j] !== arr1[i][j]) { + return false; + } + } + } + } + + return true; +} +/** + * Catmull Rom interpolate array + * @param {Array} p0 + * @param {Array} p1 + * @param {Array} p2 + * @param {Array} p3 + * @param {number} t + * @param {number} t2 + * @param {number} t3 + * @param {Array} out + * @param {number} arrDim + */ + + +function catmullRomInterpolateArray(p0, p1, p2, p3, t, t2, t3, out, arrDim) { + var len = p0.length; + + if (arrDim == 1) { + for (var i = 0; i < len; i++) { + out[i] = catmullRomInterpolate(p0[i], p1[i], p2[i], p3[i], t, t2, t3); + } + } else { + var len2 = p0[0].length; + + for (var i = 0; i < len; i++) { + for (var j = 0; j < len2; j++) { + out[i][j] = catmullRomInterpolate(p0[i][j], p1[i][j], p2[i][j], p3[i][j], t, t2, t3); + } + } + } +} +/** + * Catmull Rom interpolate number + * @param {number} p0 + * @param {number} p1 + * @param {number} p2 + * @param {number} p3 + * @param {number} t + * @param {number} t2 + * @param {number} t3 + * @return {number} + */ + + +function catmullRomInterpolate(p0, p1, p2, p3, t, t2, t3) { + var v0 = (p2 - p0) * 0.5; + var v1 = (p3 - p1) * 0.5; + return (2 * (p1 - p2) + v0 + v1) * t3 + (-3 * (p1 - p2) - 2 * v0 - v1) * t2 + v0 * t + p1; +} + +function cloneValue(value) { + if (isArrayLike(value)) { + var len = value.length; + + if (isArrayLike(value[0])) { + var ret = []; + + for (var i = 0; i < len; i++) { + ret.push(arraySlice.call(value[i])); + } + + return ret; + } + + return arraySlice.call(value); + } + + return value; +} + +function rgba2String(rgba) { + rgba[0] = Math.floor(rgba[0]); + rgba[1] = Math.floor(rgba[1]); + rgba[2] = Math.floor(rgba[2]); + return 'rgba(' + rgba.join(',') + ')'; +} + +function getArrayDim(keyframes) { + var lastValue = keyframes[keyframes.length - 1].value; + return isArrayLike(lastValue && lastValue[0]) ? 2 : 1; +} + +function createTrackClip(animator, easing, oneTrackDone, keyframes, propName, forceAnimate) { + var getter = animator._getter; + var setter = animator._setter; + var useSpline = easing === 'spline'; + var trackLen = keyframes.length; + + if (!trackLen) { + return; + } // Guess data type + + + var firstVal = keyframes[0].value; + var isValueArray = isArrayLike(firstVal); + var isValueColor = false; + var isValueString = false; // For vertices morphing + + var arrDim = isValueArray ? getArrayDim(keyframes) : 0; + var trackMaxTime; // Sort keyframe as ascending + + keyframes.sort(function (a, b) { + return a.time - b.time; + }); + trackMaxTime = keyframes[trackLen - 1].time; // Percents of each keyframe + + var kfPercents = []; // Value of each keyframe + + var kfValues = []; + var prevValue = keyframes[0].value; + var isAllValueEqual = true; + + for (var i = 0; i < trackLen; i++) { + kfPercents.push(keyframes[i].time / trackMaxTime); // Assume value is a color when it is a string + + var value = keyframes[i].value; // Check if value is equal, deep check if value is array + + if (!(isValueArray && isArraySame(value, prevValue, arrDim) || !isValueArray && value === prevValue)) { + isAllValueEqual = false; + } + + prevValue = value; // Try converting a string to a color array + + if (typeof value == 'string') { + var colorArray = color.parse(value); + + if (colorArray) { + value = colorArray; + isValueColor = true; + } else { + isValueString = true; + } + } + + kfValues.push(value); + } + + if (!forceAnimate && isAllValueEqual) { + return; + } + + var lastValue = kfValues[trackLen - 1]; // Polyfill array and NaN value + + for (var i = 0; i < trackLen - 1; i++) { + if (isValueArray) { + fillArr(kfValues[i], lastValue, arrDim); + } else { + if (isNaN(kfValues[i]) && !isNaN(lastValue) && !isValueString && !isValueColor) { + kfValues[i] = lastValue; + } + } + } + + isValueArray && fillArr(getter(animator._target, propName), lastValue, arrDim); // Cache the key of last frame to speed up when + // animation playback is sequency + + var lastFrame = 0; + var lastFramePercent = 0; + var start; + var w; + var p0; + var p1; + var p2; + var p3; + + if (isValueColor) { + var rgba = [0, 0, 0, 0]; + } + + var onframe = function (target, percent) { + // Find the range keyframes + // kf1-----kf2---------current--------kf3 + // find kf2 and kf3 and do interpolation + var frame; // In the easing function like elasticOut, percent may less than 0 + + if (percent < 0) { + frame = 0; + } else if (percent < lastFramePercent) { + // Start from next key + // PENDING start from lastFrame ? + start = Math.min(lastFrame + 1, trackLen - 1); + + for (frame = start; frame >= 0; frame--) { + if (kfPercents[frame] <= percent) { + break; + } + } // PENDING really need to do this ? + + + frame = Math.min(frame, trackLen - 2); + } else { + for (frame = lastFrame; frame < trackLen; frame++) { + if (kfPercents[frame] > percent) { + break; + } + } + + frame = Math.min(frame - 1, trackLen - 2); + } + + lastFrame = frame; + lastFramePercent = percent; + var range = kfPercents[frame + 1] - kfPercents[frame]; + + if (range === 0) { + return; + } else { + w = (percent - kfPercents[frame]) / range; + } + + if (useSpline) { + p1 = kfValues[frame]; + p0 = kfValues[frame === 0 ? frame : frame - 1]; + p2 = kfValues[frame > trackLen - 2 ? trackLen - 1 : frame + 1]; + p3 = kfValues[frame > trackLen - 3 ? trackLen - 1 : frame + 2]; + + if (isValueArray) { + catmullRomInterpolateArray(p0, p1, p2, p3, w, w * w, w * w * w, getter(target, propName), arrDim); + } else { + var value; + + if (isValueColor) { + value = catmullRomInterpolateArray(p0, p1, p2, p3, w, w * w, w * w * w, rgba, 1); + value = rgba2String(rgba); + } else if (isValueString) { + // String is step(0.5) + return interpolateString(p1, p2, w); + } else { + value = catmullRomInterpolate(p0, p1, p2, p3, w, w * w, w * w * w); + } + + setter(target, propName, value); + } + } else { + if (isValueArray) { + interpolateArray(kfValues[frame], kfValues[frame + 1], w, getter(target, propName), arrDim); + } else { + var value; + + if (isValueColor) { + interpolateArray(kfValues[frame], kfValues[frame + 1], w, rgba, 1); + value = rgba2String(rgba); + } else if (isValueString) { + // String is step(0.5) + return interpolateString(kfValues[frame], kfValues[frame + 1], w); + } else { + value = interpolateNumber(kfValues[frame], kfValues[frame + 1], w); + } + + setter(target, propName, value); + } + } + }; + + var clip = new Clip({ + target: animator._target, + life: trackMaxTime, + loop: animator._loop, + delay: animator._delay, + onframe: onframe, + ondestroy: oneTrackDone + }); + + if (easing && easing !== 'spline') { + clip.easing = easing; + } + + return clip; +} +/** + * @alias module:zrender/animation/Animator + * @constructor + * @param {Object} target + * @param {boolean} loop + * @param {Function} getter + * @param {Function} setter + */ + + +var Animator = function (target, loop, getter, setter) { + this._tracks = {}; + this._target = target; + this._loop = loop || false; + this._getter = getter || defaultGetter; + this._setter = setter || defaultSetter; + this._clipCount = 0; + this._delay = 0; + this._doneList = []; + this._onframeList = []; + this._clipList = []; +}; + +Animator.prototype = { + /** + * 设置动画关键帧 + * @param {number} time 关键帧时间,单位是ms + * @param {Object} props 关键帧的属性值,key-value表示 + * @return {module:zrender/animation/Animator} + */ + when: function (time + /* ms */ + , props) { + var tracks = this._tracks; + + for (var propName in props) { + if (!props.hasOwnProperty(propName)) { + continue; + } + + if (!tracks[propName]) { + tracks[propName] = []; // Invalid value + + var value = this._getter(this._target, propName); + + if (value == null) { + // zrLog('Invalid property ' + propName); + continue; + } // If time is 0 + // Then props is given initialize value + // Else + // Initialize value from current prop value + + + if (time !== 0) { + tracks[propName].push({ + time: 0, + value: cloneValue(value) + }); + } + } + + tracks[propName].push({ + time: time, + value: props[propName] + }); + } + + return this; + }, + + /** + * 添加动画每一帧的回调函数 + * @param {Function} callback + * @return {module:zrender/animation/Animator} + */ + during: function (callback) { + this._onframeList.push(callback); + + return this; + }, + pause: function () { + for (var i = 0; i < this._clipList.length; i++) { + this._clipList[i].pause(); + } + + this._paused = true; + }, + resume: function () { + for (var i = 0; i < this._clipList.length; i++) { + this._clipList[i].resume(); + } + + this._paused = false; + }, + isPaused: function () { + return !!this._paused; + }, + _doneCallback: function () { + // Clear all tracks + this._tracks = {}; // Clear all clips + + this._clipList.length = 0; + var doneList = this._doneList; + var len = doneList.length; + + for (var i = 0; i < len; i++) { + doneList[i].call(this); + } + }, + + /** + * 开始执行动画 + * @param {string|Function} [easing] + * 动画缓动函数,详见{@link module:zrender/animation/easing} + * @param {boolean} forceAnimate + * @return {module:zrender/animation/Animator} + */ + start: function (easing, forceAnimate) { + var self = this; + var clipCount = 0; + + var oneTrackDone = function () { + clipCount--; + + if (!clipCount) { + self._doneCallback(); + } + }; + + var lastClip; + + for (var propName in this._tracks) { + if (!this._tracks.hasOwnProperty(propName)) { + continue; + } + + var clip = createTrackClip(this, easing, oneTrackDone, this._tracks[propName], propName, forceAnimate); + + if (clip) { + this._clipList.push(clip); + + clipCount++; // If start after added to animation + + if (this.animation) { + this.animation.addClip(clip); + } + + lastClip = clip; + } + } // Add during callback on the last clip + + + if (lastClip) { + var oldOnFrame = lastClip.onframe; + + lastClip.onframe = function (target, percent) { + oldOnFrame(target, percent); + + for (var i = 0; i < self._onframeList.length; i++) { + self._onframeList[i](target, percent); + } + }; + } // This optimization will help the case that in the upper application + // the view may be refreshed frequently, where animation will be + // called repeatly but nothing changed. + + + if (!clipCount) { + this._doneCallback(); + } + + return this; + }, + + /** + * 停止动画 + * @param {boolean} forwardToLast If move to last frame before stop + */ + stop: function (forwardToLast) { + var clipList = this._clipList; + var animation = this.animation; + + for (var i = 0; i < clipList.length; i++) { + var clip = clipList[i]; + + if (forwardToLast) { + // Move to last frame before stop + clip.onframe(this._target, 1); + } + + animation && animation.removeClip(clip); + } + + clipList.length = 0; + }, + + /** + * 设置动画延迟开始的时间 + * @param {number} time 单位ms + * @return {module:zrender/animation/Animator} + */ + delay: function (time) { + this._delay = time; + return this; + }, + + /** + * 添加动画结束的回调 + * @param {Function} cb + * @return {module:zrender/animation/Animator} + */ + done: function (cb) { + if (cb) { + this._doneList.push(cb); + } + + return this; + }, + + /** + * @return {Array.} + */ + getClips: function () { + return this._clipList; + } +}; +var _default = Animator; +module.exports = _default; + +/***/ }), +/* 143 */ +/***/ (function(module, exports, __webpack_require__) { + +var easingFuncs = __webpack_require__(144); + +/** + * 动画主控制器 + * @config target 动画对象,可以是数组,如果是数组的话会批量分发onframe等事件 + * @config life(1000) 动画时长 + * @config delay(0) 动画延迟时间 + * @config loop(true) + * @config gap(0) 循环的间隔时间 + * @config onframe + * @config easing(optional) + * @config ondestroy(optional) + * @config onrestart(optional) + * + * TODO pause + */ +function Clip(options) { + this._target = options.target; // 生命周期 + + this._life = options.life || 1000; // 延时 + + this._delay = options.delay || 0; // 开始时间 + // this._startTime = new Date().getTime() + this._delay;// 单位毫秒 + + this._initialized = false; // 是否循环 + + this.loop = options.loop == null ? false : options.loop; + this.gap = options.gap || 0; + this.easing = options.easing || 'Linear'; + this.onframe = options.onframe; + this.ondestroy = options.ondestroy; + this.onrestart = options.onrestart; + this._pausedTime = 0; + this._paused = false; +} + +Clip.prototype = { + constructor: Clip, + step: function (globalTime, deltaTime) { + // Set startTime on first step, or _startTime may has milleseconds different between clips + // PENDING + if (!this._initialized) { + this._startTime = globalTime + this._delay; + this._initialized = true; + } + + if (this._paused) { + this._pausedTime += deltaTime; + return; + } + + var percent = (globalTime - this._startTime - this._pausedTime) / this._life; // 还没开始 + + if (percent < 0) { + return; + } + + percent = Math.min(percent, 1); + var easing = this.easing; + var easingFunc = typeof easing == 'string' ? easingFuncs[easing] : easing; + var schedule = typeof easingFunc === 'function' ? easingFunc(percent) : percent; + this.fire('frame', schedule); // 结束 + + if (percent == 1) { + if (this.loop) { + this.restart(globalTime); // 重新开始周期 + // 抛出而不是直接调用事件直到 stage.update 后再统一调用这些事件 + + return 'restart'; + } // 动画完成将这个控制器标识为待删除 + // 在Animation.update中进行批量删除 + + + this._needsRemove = true; + return 'destroy'; + } + + return null; + }, + restart: function (globalTime) { + var remainder = (globalTime - this._startTime - this._pausedTime) % this._life; + this._startTime = globalTime - remainder + this.gap; + this._pausedTime = 0; + this._needsRemove = false; + }, + fire: function (eventType, arg) { + eventType = 'on' + eventType; + + if (this[eventType]) { + this[eventType](this._target, arg); + } + }, + pause: function () { + this._paused = true; + }, + resume: function () { + this._paused = false; + } +}; +var _default = Clip; +module.exports = _default; + +/***/ }), +/* 144 */ +/***/ (function(module, exports) { + +/** + * 缓动代码来自 https://github.com/sole/tween.js/blob/master/src/Tween.js + * @see http://sole.github.io/tween.js/examples/03_graphs.html + * @exports zrender/animation/easing + */ +var easing = { + /** + * @param {number} k + * @return {number} + */ + linear: function (k) { + return k; + }, + + /** + * @param {number} k + * @return {number} + */ + quadraticIn: function (k) { + return k * k; + }, + + /** + * @param {number} k + * @return {number} + */ + quadraticOut: function (k) { + return k * (2 - k); + }, + + /** + * @param {number} k + * @return {number} + */ + quadraticInOut: function (k) { + if ((k *= 2) < 1) { + return 0.5 * k * k; + } + + return -0.5 * (--k * (k - 2) - 1); + }, + // 三次方的缓动(t^3) + + /** + * @param {number} k + * @return {number} + */ + cubicIn: function (k) { + return k * k * k; + }, + + /** + * @param {number} k + * @return {number} + */ + cubicOut: function (k) { + return --k * k * k + 1; + }, + + /** + * @param {number} k + * @return {number} + */ + cubicInOut: function (k) { + if ((k *= 2) < 1) { + return 0.5 * k * k * k; + } + + return 0.5 * ((k -= 2) * k * k + 2); + }, + // 四次方的缓动(t^4) + + /** + * @param {number} k + * @return {number} + */ + quarticIn: function (k) { + return k * k * k * k; + }, + + /** + * @param {number} k + * @return {number} + */ + quarticOut: function (k) { + return 1 - --k * k * k * k; + }, + + /** + * @param {number} k + * @return {number} + */ + quarticInOut: function (k) { + if ((k *= 2) < 1) { + return 0.5 * k * k * k * k; + } + + return -0.5 * ((k -= 2) * k * k * k - 2); + }, + // 五次方的缓动(t^5) + + /** + * @param {number} k + * @return {number} + */ + quinticIn: function (k) { + return k * k * k * k * k; + }, + + /** + * @param {number} k + * @return {number} + */ + quinticOut: function (k) { + return --k * k * k * k * k + 1; + }, + + /** + * @param {number} k + * @return {number} + */ + quinticInOut: function (k) { + if ((k *= 2) < 1) { + return 0.5 * k * k * k * k * k; + } + + return 0.5 * ((k -= 2) * k * k * k * k + 2); + }, + // 正弦曲线的缓动(sin(t)) + + /** + * @param {number} k + * @return {number} + */ + sinusoidalIn: function (k) { + return 1 - Math.cos(k * Math.PI / 2); + }, + + /** + * @param {number} k + * @return {number} + */ + sinusoidalOut: function (k) { + return Math.sin(k * Math.PI / 2); + }, + + /** + * @param {number} k + * @return {number} + */ + sinusoidalInOut: function (k) { + return 0.5 * (1 - Math.cos(Math.PI * k)); + }, + // 指数曲线的缓动(2^t) + + /** + * @param {number} k + * @return {number} + */ + exponentialIn: function (k) { + return k === 0 ? 0 : Math.pow(1024, k - 1); + }, + + /** + * @param {number} k + * @return {number} + */ + exponentialOut: function (k) { + return k === 1 ? 1 : 1 - Math.pow(2, -10 * k); + }, + + /** + * @param {number} k + * @return {number} + */ + exponentialInOut: function (k) { + if (k === 0) { + return 0; + } + + if (k === 1) { + return 1; + } + + if ((k *= 2) < 1) { + return 0.5 * Math.pow(1024, k - 1); + } + + return 0.5 * (-Math.pow(2, -10 * (k - 1)) + 2); + }, + // 圆形曲线的缓动(sqrt(1-t^2)) + + /** + * @param {number} k + * @return {number} + */ + circularIn: function (k) { + return 1 - Math.sqrt(1 - k * k); + }, + + /** + * @param {number} k + * @return {number} + */ + circularOut: function (k) { + return Math.sqrt(1 - --k * k); + }, + + /** + * @param {number} k + * @return {number} + */ + circularInOut: function (k) { + if ((k *= 2) < 1) { + return -0.5 * (Math.sqrt(1 - k * k) - 1); + } + + return 0.5 * (Math.sqrt(1 - (k -= 2) * k) + 1); + }, + // 创建类似于弹簧在停止前来回振荡的动画 + + /** + * @param {number} k + * @return {number} + */ + elasticIn: function (k) { + var s; + var a = 0.1; + var p = 0.4; + + if (k === 0) { + return 0; + } + + if (k === 1) { + return 1; + } + + if (!a || a < 1) { + a = 1; + s = p / 4; + } else { + s = p * Math.asin(1 / a) / (2 * Math.PI); + } + + return -(a * Math.pow(2, 10 * (k -= 1)) * Math.sin((k - s) * (2 * Math.PI) / p)); + }, + + /** + * @param {number} k + * @return {number} + */ + elasticOut: function (k) { + var s; + var a = 0.1; + var p = 0.4; + + if (k === 0) { + return 0; + } + + if (k === 1) { + return 1; + } + + if (!a || a < 1) { + a = 1; + s = p / 4; + } else { + s = p * Math.asin(1 / a) / (2 * Math.PI); + } + + return a * Math.pow(2, -10 * k) * Math.sin((k - s) * (2 * Math.PI) / p) + 1; + }, + + /** + * @param {number} k + * @return {number} + */ + elasticInOut: function (k) { + var s; + var a = 0.1; + var p = 0.4; + + if (k === 0) { + return 0; + } + + if (k === 1) { + return 1; + } + + if (!a || a < 1) { + a = 1; + s = p / 4; + } else { + s = p * Math.asin(1 / a) / (2 * Math.PI); + } + + if ((k *= 2) < 1) { + return -0.5 * (a * Math.pow(2, 10 * (k -= 1)) * Math.sin((k - s) * (2 * Math.PI) / p)); + } + + return a * Math.pow(2, -10 * (k -= 1)) * Math.sin((k - s) * (2 * Math.PI) / p) * 0.5 + 1; + }, + // 在某一动画开始沿指示的路径进行动画处理前稍稍收回该动画的移动 + + /** + * @param {number} k + * @return {number} + */ + backIn: function (k) { + var s = 1.70158; + return k * k * ((s + 1) * k - s); + }, + + /** + * @param {number} k + * @return {number} + */ + backOut: function (k) { + var s = 1.70158; + return --k * k * ((s + 1) * k + s) + 1; + }, + + /** + * @param {number} k + * @return {number} + */ + backInOut: function (k) { + var s = 1.70158 * 1.525; + + if ((k *= 2) < 1) { + return 0.5 * (k * k * ((s + 1) * k - s)); + } + + return 0.5 * ((k -= 2) * k * ((s + 1) * k + s) + 2); + }, + // 创建弹跳效果 + + /** + * @param {number} k + * @return {number} + */ + bounceIn: function (k) { + return 1 - easing.bounceOut(1 - k); + }, + + /** + * @param {number} k + * @return {number} + */ + bounceOut: function (k) { + if (k < 1 / 2.75) { + return 7.5625 * k * k; + } else if (k < 2 / 2.75) { + return 7.5625 * (k -= 1.5 / 2.75) * k + 0.75; + } else if (k < 2.5 / 2.75) { + return 7.5625 * (k -= 2.25 / 2.75) * k + 0.9375; + } else { + return 7.5625 * (k -= 2.625 / 2.75) * k + 0.984375; + } + }, + + /** + * @param {number} k + * @return {number} + */ + bounceInOut: function (k) { + if (k < 0.5) { + return easing.bounceIn(k * 2) * 0.5; + } + + return easing.bounceOut(k * 2 - 1) * 0.5 + 0.5; + } +}; +var _default = easing; +module.exports = _default; + +/***/ }), +/* 145 */ +/***/ (function(module, exports, __webpack_require__) { + +var LRU = __webpack_require__(60); + +var kCSSColorTable = { + 'transparent': [0, 0, 0, 0], + 'aliceblue': [240, 248, 255, 1], + 'antiquewhite': [250, 235, 215, 1], + 'aqua': [0, 255, 255, 1], + 'aquamarine': [127, 255, 212, 1], + 'azure': [240, 255, 255, 1], + 'beige': [245, 245, 220, 1], + 'bisque': [255, 228, 196, 1], + 'black': [0, 0, 0, 1], + 'blanchedalmond': [255, 235, 205, 1], + 'blue': [0, 0, 255, 1], + 'blueviolet': [138, 43, 226, 1], + 'brown': [165, 42, 42, 1], + 'burlywood': [222, 184, 135, 1], + 'cadetblue': [95, 158, 160, 1], + 'chartreuse': [127, 255, 0, 1], + 'chocolate': [210, 105, 30, 1], + 'coral': [255, 127, 80, 1], + 'cornflowerblue': [100, 149, 237, 1], + 'cornsilk': [255, 248, 220, 1], + 'crimson': [220, 20, 60, 1], + 'cyan': [0, 255, 255, 1], + 'darkblue': [0, 0, 139, 1], + 'darkcyan': [0, 139, 139, 1], + 'darkgoldenrod': [184, 134, 11, 1], + 'darkgray': [169, 169, 169, 1], + 'darkgreen': [0, 100, 0, 1], + 'darkgrey': [169, 169, 169, 1], + 'darkkhaki': [189, 183, 107, 1], + 'darkmagenta': [139, 0, 139, 1], + 'darkolivegreen': [85, 107, 47, 1], + 'darkorange': [255, 140, 0, 1], + 'darkorchid': [153, 50, 204, 1], + 'darkred': [139, 0, 0, 1], + 'darksalmon': [233, 150, 122, 1], + 'darkseagreen': [143, 188, 143, 1], + 'darkslateblue': [72, 61, 139, 1], + 'darkslategray': [47, 79, 79, 1], + 'darkslategrey': [47, 79, 79, 1], + 'darkturquoise': [0, 206, 209, 1], + 'darkviolet': [148, 0, 211, 1], + 'deeppink': [255, 20, 147, 1], + 'deepskyblue': [0, 191, 255, 1], + 'dimgray': [105, 105, 105, 1], + 'dimgrey': [105, 105, 105, 1], + 'dodgerblue': [30, 144, 255, 1], + 'firebrick': [178, 34, 34, 1], + 'floralwhite': [255, 250, 240, 1], + 'forestgreen': [34, 139, 34, 1], + 'fuchsia': [255, 0, 255, 1], + 'gainsboro': [220, 220, 220, 1], + 'ghostwhite': [248, 248, 255, 1], + 'gold': [255, 215, 0, 1], + 'goldenrod': [218, 165, 32, 1], + 'gray': [128, 128, 128, 1], + 'green': [0, 128, 0, 1], + 'greenyellow': [173, 255, 47, 1], + 'grey': [128, 128, 128, 1], + 'honeydew': [240, 255, 240, 1], + 'hotpink': [255, 105, 180, 1], + 'indianred': [205, 92, 92, 1], + 'indigo': [75, 0, 130, 1], + 'ivory': [255, 255, 240, 1], + 'khaki': [240, 230, 140, 1], + 'lavender': [230, 230, 250, 1], + 'lavenderblush': [255, 240, 245, 1], + 'lawngreen': [124, 252, 0, 1], + 'lemonchiffon': [255, 250, 205, 1], + 'lightblue': [173, 216, 230, 1], + 'lightcoral': [240, 128, 128, 1], + 'lightcyan': [224, 255, 255, 1], + 'lightgoldenrodyellow': [250, 250, 210, 1], + 'lightgray': [211, 211, 211, 1], + 'lightgreen': [144, 238, 144, 1], + 'lightgrey': [211, 211, 211, 1], + 'lightpink': [255, 182, 193, 1], + 'lightsalmon': [255, 160, 122, 1], + 'lightseagreen': [32, 178, 170, 1], + 'lightskyblue': [135, 206, 250, 1], + 'lightslategray': [119, 136, 153, 1], + 'lightslategrey': [119, 136, 153, 1], + 'lightsteelblue': [176, 196, 222, 1], + 'lightyellow': [255, 255, 224, 1], + 'lime': [0, 255, 0, 1], + 'limegreen': [50, 205, 50, 1], + 'linen': [250, 240, 230, 1], + 'magenta': [255, 0, 255, 1], + 'maroon': [128, 0, 0, 1], + 'mediumaquamarine': [102, 205, 170, 1], + 'mediumblue': [0, 0, 205, 1], + 'mediumorchid': [186, 85, 211, 1], + 'mediumpurple': [147, 112, 219, 1], + 'mediumseagreen': [60, 179, 113, 1], + 'mediumslateblue': [123, 104, 238, 1], + 'mediumspringgreen': [0, 250, 154, 1], + 'mediumturquoise': [72, 209, 204, 1], + 'mediumvioletred': [199, 21, 133, 1], + 'midnightblue': [25, 25, 112, 1], + 'mintcream': [245, 255, 250, 1], + 'mistyrose': [255, 228, 225, 1], + 'moccasin': [255, 228, 181, 1], + 'navajowhite': [255, 222, 173, 1], + 'navy': [0, 0, 128, 1], + 'oldlace': [253, 245, 230, 1], + 'olive': [128, 128, 0, 1], + 'olivedrab': [107, 142, 35, 1], + 'orange': [255, 165, 0, 1], + 'orangered': [255, 69, 0, 1], + 'orchid': [218, 112, 214, 1], + 'palegoldenrod': [238, 232, 170, 1], + 'palegreen': [152, 251, 152, 1], + 'paleturquoise': [175, 238, 238, 1], + 'palevioletred': [219, 112, 147, 1], + 'papayawhip': [255, 239, 213, 1], + 'peachpuff': [255, 218, 185, 1], + 'peru': [205, 133, 63, 1], + 'pink': [255, 192, 203, 1], + 'plum': [221, 160, 221, 1], + 'powderblue': [176, 224, 230, 1], + 'purple': [128, 0, 128, 1], + 'red': [255, 0, 0, 1], + 'rosybrown': [188, 143, 143, 1], + 'royalblue': [65, 105, 225, 1], + 'saddlebrown': [139, 69, 19, 1], + 'salmon': [250, 128, 114, 1], + 'sandybrown': [244, 164, 96, 1], + 'seagreen': [46, 139, 87, 1], + 'seashell': [255, 245, 238, 1], + 'sienna': [160, 82, 45, 1], + 'silver': [192, 192, 192, 1], + 'skyblue': [135, 206, 235, 1], + 'slateblue': [106, 90, 205, 1], + 'slategray': [112, 128, 144, 1], + 'slategrey': [112, 128, 144, 1], + 'snow': [255, 250, 250, 1], + 'springgreen': [0, 255, 127, 1], + 'steelblue': [70, 130, 180, 1], + 'tan': [210, 180, 140, 1], + 'teal': [0, 128, 128, 1], + 'thistle': [216, 191, 216, 1], + 'tomato': [255, 99, 71, 1], + 'turquoise': [64, 224, 208, 1], + 'violet': [238, 130, 238, 1], + 'wheat': [245, 222, 179, 1], + 'white': [255, 255, 255, 1], + 'whitesmoke': [245, 245, 245, 1], + 'yellow': [255, 255, 0, 1], + 'yellowgreen': [154, 205, 50, 1] +}; + +function clampCssByte(i) { + // Clamp to integer 0 .. 255. + i = Math.round(i); // Seems to be what Chrome does (vs truncation). + + return i < 0 ? 0 : i > 255 ? 255 : i; +} + +function clampCssAngle(i) { + // Clamp to integer 0 .. 360. + i = Math.round(i); // Seems to be what Chrome does (vs truncation). + + return i < 0 ? 0 : i > 360 ? 360 : i; +} + +function clampCssFloat(f) { + // Clamp to float 0.0 .. 1.0. + return f < 0 ? 0 : f > 1 ? 1 : f; +} + +function parseCssInt(str) { + // int or percentage. + if (str.length && str.charAt(str.length - 1) === '%') { + return clampCssByte(parseFloat(str) / 100 * 255); + } + + return clampCssByte(parseInt(str, 10)); +} + +function parseCssFloat(str) { + // float or percentage. + if (str.length && str.charAt(str.length - 1) === '%') { + return clampCssFloat(parseFloat(str) / 100); + } + + return clampCssFloat(parseFloat(str)); +} + +function cssHueToRgb(m1, m2, h) { + if (h < 0) { + h += 1; + } else if (h > 1) { + h -= 1; + } + + if (h * 6 < 1) { + return m1 + (m2 - m1) * h * 6; + } + + if (h * 2 < 1) { + return m2; + } + + if (h * 3 < 2) { + return m1 + (m2 - m1) * (2 / 3 - h) * 6; + } + + return m1; +} + +function lerpNumber(a, b, p) { + return a + (b - a) * p; +} + +function setRgba(out, r, g, b, a) { + out[0] = r; + out[1] = g; + out[2] = b; + out[3] = a; + return out; +} + +function copyRgba(out, a) { + out[0] = a[0]; + out[1] = a[1]; + out[2] = a[2]; + out[3] = a[3]; + return out; +} + +var colorCache = new LRU(20); +var lastRemovedArr = null; + +function putToCache(colorStr, rgbaArr) { + // Reuse removed array + if (lastRemovedArr) { + copyRgba(lastRemovedArr, rgbaArr); + } + + lastRemovedArr = colorCache.put(colorStr, lastRemovedArr || rgbaArr.slice()); +} +/** + * @param {string} colorStr + * @param {Array.} out + * @return {Array.} + * @memberOf module:zrender/util/color + */ + + +function parse(colorStr, rgbaArr) { + if (!colorStr) { + return; + } + + rgbaArr = rgbaArr || []; + var cached = colorCache.get(colorStr); + + if (cached) { + return copyRgba(rgbaArr, cached); + } // colorStr may be not string + + + colorStr = colorStr + ''; // Remove all whitespace, not compliant, but should just be more accepting. + + var str = colorStr.replace(/ /g, '').toLowerCase(); // Color keywords (and transparent) lookup. + + if (str in kCSSColorTable) { + copyRgba(rgbaArr, kCSSColorTable[str]); + putToCache(colorStr, rgbaArr); + return rgbaArr; + } // #abc and #abc123 syntax. + + + if (str.charAt(0) === '#') { + if (str.length === 4) { + var iv = parseInt(str.substr(1), 16); // TODO(deanm): Stricter parsing. + + if (!(iv >= 0 && iv <= 0xfff)) { + setRgba(rgbaArr, 0, 0, 0, 1); + return; // Covers NaN. + } + + setRgba(rgbaArr, (iv & 0xf00) >> 4 | (iv & 0xf00) >> 8, iv & 0xf0 | (iv & 0xf0) >> 4, iv & 0xf | (iv & 0xf) << 4, 1); + putToCache(colorStr, rgbaArr); + return rgbaArr; + } else if (str.length === 7) { + var iv = parseInt(str.substr(1), 16); // TODO(deanm): Stricter parsing. + + if (!(iv >= 0 && iv <= 0xffffff)) { + setRgba(rgbaArr, 0, 0, 0, 1); + return; // Covers NaN. + } + + setRgba(rgbaArr, (iv & 0xff0000) >> 16, (iv & 0xff00) >> 8, iv & 0xff, 1); + putToCache(colorStr, rgbaArr); + return rgbaArr; + } + + return; + } + + var op = str.indexOf('('), + ep = str.indexOf(')'); + + if (op !== -1 && ep + 1 === str.length) { + var fname = str.substr(0, op); + var params = str.substr(op + 1, ep - (op + 1)).split(','); + var alpha = 1; // To allow case fallthrough. + + switch (fname) { + case 'rgba': + if (params.length !== 4) { + setRgba(rgbaArr, 0, 0, 0, 1); + return; + } + + alpha = parseCssFloat(params.pop()); + // jshint ignore:line + // Fall through. + + case 'rgb': + if (params.length !== 3) { + setRgba(rgbaArr, 0, 0, 0, 1); + return; + } + + setRgba(rgbaArr, parseCssInt(params[0]), parseCssInt(params[1]), parseCssInt(params[2]), alpha); + putToCache(colorStr, rgbaArr); + return rgbaArr; + + case 'hsla': + if (params.length !== 4) { + setRgba(rgbaArr, 0, 0, 0, 1); + return; + } + + params[3] = parseCssFloat(params[3]); + hsla2rgba(params, rgbaArr); + putToCache(colorStr, rgbaArr); + return rgbaArr; + + case 'hsl': + if (params.length !== 3) { + setRgba(rgbaArr, 0, 0, 0, 1); + return; + } + + hsla2rgba(params, rgbaArr); + putToCache(colorStr, rgbaArr); + return rgbaArr; + + default: + return; + } + } + + setRgba(rgbaArr, 0, 0, 0, 1); + return; +} +/** + * @param {Array.} hsla + * @param {Array.} rgba + * @return {Array.} rgba + */ + + +function hsla2rgba(hsla, rgba) { + var h = (parseFloat(hsla[0]) % 360 + 360) % 360 / 360; // 0 .. 1 + // NOTE(deanm): According to the CSS spec s/l should only be + // percentages, but we don't bother and let float or percentage. + + var s = parseCssFloat(hsla[1]); + var l = parseCssFloat(hsla[2]); + var m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s; + var m1 = l * 2 - m2; + rgba = rgba || []; + setRgba(rgba, clampCssByte(cssHueToRgb(m1, m2, h + 1 / 3) * 255), clampCssByte(cssHueToRgb(m1, m2, h) * 255), clampCssByte(cssHueToRgb(m1, m2, h - 1 / 3) * 255), 1); + + if (hsla.length === 4) { + rgba[3] = hsla[3]; + } + + return rgba; +} +/** + * @param {Array.} rgba + * @return {Array.} hsla + */ + + +function rgba2hsla(rgba) { + if (!rgba) { + return; + } // RGB from 0 to 255 + + + var R = rgba[0] / 255; + var G = rgba[1] / 255; + var B = rgba[2] / 255; + var vMin = Math.min(R, G, B); // Min. value of RGB + + var vMax = Math.max(R, G, B); // Max. value of RGB + + var delta = vMax - vMin; // Delta RGB value + + var L = (vMax + vMin) / 2; + var H; + var S; // HSL results from 0 to 1 + + if (delta === 0) { + H = 0; + S = 0; + } else { + if (L < 0.5) { + S = delta / (vMax + vMin); + } else { + S = delta / (2 - vMax - vMin); + } + + var deltaR = ((vMax - R) / 6 + delta / 2) / delta; + var deltaG = ((vMax - G) / 6 + delta / 2) / delta; + var deltaB = ((vMax - B) / 6 + delta / 2) / delta; + + if (R === vMax) { + H = deltaB - deltaG; + } else if (G === vMax) { + H = 1 / 3 + deltaR - deltaB; + } else if (B === vMax) { + H = 2 / 3 + deltaG - deltaR; + } + + if (H < 0) { + H += 1; + } + + if (H > 1) { + H -= 1; + } + } + + var hsla = [H * 360, S, L]; + + if (rgba[3] != null) { + hsla.push(rgba[3]); + } + + return hsla; +} +/** + * @param {string} color + * @param {number} level + * @return {string} + * @memberOf module:zrender/util/color + */ + + +function lift(color, level) { + var colorArr = parse(color); + + if (colorArr) { + for (var i = 0; i < 3; i++) { + if (level < 0) { + colorArr[i] = colorArr[i] * (1 - level) | 0; + } else { + colorArr[i] = (255 - colorArr[i]) * level + colorArr[i] | 0; + } + + if (colorArr[i] > 255) { + colorArr[i] = 255; + } else if (color[i] < 0) { + colorArr[i] = 0; + } + } + + return stringify(colorArr, colorArr.length === 4 ? 'rgba' : 'rgb'); + } +} +/** + * @param {string} color + * @return {string} + * @memberOf module:zrender/util/color + */ + + +function toHex(color) { + var colorArr = parse(color); + + if (colorArr) { + return ((1 << 24) + (colorArr[0] << 16) + (colorArr[1] << 8) + +colorArr[2]).toString(16).slice(1); + } +} +/** + * Map value to color. Faster than lerp methods because color is represented by rgba array. + * @param {number} normalizedValue A float between 0 and 1. + * @param {Array.>} colors List of rgba color array + * @param {Array.} [out] Mapped gba color array + * @return {Array.} will be null/undefined if input illegal. + */ + + +function fastLerp(normalizedValue, colors, out) { + if (!(colors && colors.length) || !(normalizedValue >= 0 && normalizedValue <= 1)) { + return; + } + + out = out || []; + var value = normalizedValue * (colors.length - 1); + var leftIndex = Math.floor(value); + var rightIndex = Math.ceil(value); + var leftColor = colors[leftIndex]; + var rightColor = colors[rightIndex]; + var dv = value - leftIndex; + out[0] = clampCssByte(lerpNumber(leftColor[0], rightColor[0], dv)); + out[1] = clampCssByte(lerpNumber(leftColor[1], rightColor[1], dv)); + out[2] = clampCssByte(lerpNumber(leftColor[2], rightColor[2], dv)); + out[3] = clampCssFloat(lerpNumber(leftColor[3], rightColor[3], dv)); + return out; +} +/** + * @deprecated + */ + + +var fastMapToColor = fastLerp; +/** + * @param {number} normalizedValue A float between 0 and 1. + * @param {Array.} colors Color list. + * @param {boolean=} fullOutput Default false. + * @return {(string|Object)} Result color. If fullOutput, + * return {color: ..., leftIndex: ..., rightIndex: ..., value: ...}, + * @memberOf module:zrender/util/color + */ + +function lerp(normalizedValue, colors, fullOutput) { + if (!(colors && colors.length) || !(normalizedValue >= 0 && normalizedValue <= 1)) { + return; + } + + var value = normalizedValue * (colors.length - 1); + var leftIndex = Math.floor(value); + var rightIndex = Math.ceil(value); + var leftColor = parse(colors[leftIndex]); + var rightColor = parse(colors[rightIndex]); + var dv = value - leftIndex; + var color = stringify([clampCssByte(lerpNumber(leftColor[0], rightColor[0], dv)), clampCssByte(lerpNumber(leftColor[1], rightColor[1], dv)), clampCssByte(lerpNumber(leftColor[2], rightColor[2], dv)), clampCssFloat(lerpNumber(leftColor[3], rightColor[3], dv))], 'rgba'); + return fullOutput ? { + color: color, + leftIndex: leftIndex, + rightIndex: rightIndex, + value: value + } : color; +} +/** + * @deprecated + */ + + +var mapToColor = lerp; +/** + * @param {string} color + * @param {number=} h 0 ~ 360, ignore when null. + * @param {number=} s 0 ~ 1, ignore when null. + * @param {number=} l 0 ~ 1, ignore when null. + * @return {string} Color string in rgba format. + * @memberOf module:zrender/util/color + */ + +function modifyHSL(color, h, s, l) { + color = parse(color); + + if (color) { + color = rgba2hsla(color); + h != null && (color[0] = clampCssAngle(h)); + s != null && (color[1] = parseCssFloat(s)); + l != null && (color[2] = parseCssFloat(l)); + return stringify(hsla2rgba(color), 'rgba'); + } +} +/** + * @param {string} color + * @param {number=} alpha 0 ~ 1 + * @return {string} Color string in rgba format. + * @memberOf module:zrender/util/color + */ + + +function modifyAlpha(color, alpha) { + color = parse(color); + + if (color && alpha != null) { + color[3] = clampCssFloat(alpha); + return stringify(color, 'rgba'); + } +} +/** + * @param {Array.} arrColor like [12,33,44,0.4] + * @param {string} type 'rgba', 'hsva', ... + * @return {string} Result color. (If input illegal, return undefined). + */ + + +function stringify(arrColor, type) { + if (!arrColor || !arrColor.length) { + return; + } + + var colorStr = arrColor[0] + ',' + arrColor[1] + ',' + arrColor[2]; + + if (type === 'rgba' || type === 'hsva' || type === 'hsla') { + colorStr += ',' + arrColor[3]; + } + + return type + '(' + colorStr + ')'; +} + +exports.parse = parse; +exports.lift = lift; +exports.toHex = toHex; +exports.fastLerp = fastLerp; +exports.fastMapToColor = fastMapToColor; +exports.lerp = lerp; +exports.mapToColor = mapToColor; +exports.modifyHSL = modifyHSL; +exports.modifyAlpha = modifyAlpha; +exports.stringify = stringify; + +/***/ }), +/* 146 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony default export */ __webpack_exports__["a"] = ("\n@export clay.util.rand\nhighp float rand(vec2 uv) {\n const highp float a = 12.9898, b = 78.233, c = 43758.5453;\n highp float dt = dot(uv.xy, vec2(a,b)), sn = mod(dt, 3.141592653589793);\n return fract(sin(sn) * c);\n}\n@end\n@export clay.util.calculate_attenuation\nuniform float attenuationFactor : 5.0;\nfloat lightAttenuation(float dist, float range)\n{\n float attenuation = 1.0;\n attenuation = dist*dist/(range*range+1.0);\n float att_s = attenuationFactor;\n attenuation = 1.0/(attenuation*att_s+1.0);\n att_s = 1.0/(att_s+1.0);\n attenuation = attenuation - att_s;\n attenuation /= 1.0 - att_s;\n return clamp(attenuation, 0.0, 1.0);\n}\n@end\n@export clay.util.edge_factor\n#ifdef SUPPORT_STANDARD_DERIVATIVES\nfloat edgeFactor(float width)\n{\n vec3 d = fwidth(v_Barycentric);\n vec3 a3 = smoothstep(vec3(0.0), d * width, v_Barycentric);\n return min(min(a3.x, a3.y), a3.z);\n}\n#else\nfloat edgeFactor(float width)\n{\n return 1.0;\n}\n#endif\n@end\n@export clay.util.encode_float\nvec4 encodeFloat(const in float depth)\n{\n const vec4 bitShifts = vec4(256.0*256.0*256.0, 256.0*256.0, 256.0, 1.0);\n const vec4 bit_mask = vec4(0.0, 1.0/256.0, 1.0/256.0, 1.0/256.0);\n vec4 res = fract(depth * bitShifts);\n res -= res.xxyz * bit_mask;\n return res;\n}\n@end\n@export clay.util.decode_float\nfloat decodeFloat(const in vec4 color)\n{\n const vec4 bitShifts = vec4(1.0/(256.0*256.0*256.0), 1.0/(256.0*256.0), 1.0/256.0, 1.0);\n return dot(color, bitShifts);\n}\n@end\n@export clay.util.float\n@import clay.util.encode_float\n@import clay.util.decode_float\n@end\n@export clay.util.rgbm_decode\nvec3 RGBMDecode(vec4 rgbm, float range) {\n return range * rgbm.rgb * rgbm.a;\n}\n@end\n@export clay.util.rgbm_encode\nvec4 RGBMEncode(vec3 color, float range) {\n if (dot(color, color) == 0.0) {\n return vec4(0.0);\n }\n vec4 rgbm;\n color /= range;\n rgbm.a = clamp(max(max(color.r, color.g), max(color.b, 1e-6)), 0.0, 1.0);\n rgbm.a = ceil(rgbm.a * 255.0) / 255.0;\n rgbm.rgb = color / rgbm.a;\n return rgbm;\n}\n@end\n@export clay.util.rgbm\n@import clay.util.rgbm_decode\n@import clay.util.rgbm_encode\nvec4 decodeHDR(vec4 color)\n{\n#if defined(RGBM_DECODE) || defined(RGBM)\n return vec4(RGBMDecode(color, 8.12), 1.0);\n#else\n return color;\n#endif\n}\nvec4 encodeHDR(vec4 color)\n{\n#if defined(RGBM_ENCODE) || defined(RGBM)\n return RGBMEncode(color.xyz, 8.12);\n#else\n return color;\n#endif\n}\n@end\n@export clay.util.srgb\nvec4 sRGBToLinear(in vec4 value) {\n return vec4(mix(pow(value.rgb * 0.9478672986 + vec3(0.0521327014), vec3(2.4)), value.rgb * 0.0773993808, vec3(lessThanEqual(value.rgb, vec3(0.04045)))), value.w);\n}\nvec4 linearTosRGB(in vec4 value) {\n return vec4(mix(pow(value.rgb, vec3(0.41666)) * 1.055 - vec3(0.055), value.rgb * 12.92, vec3(lessThanEqual(value.rgb, vec3(0.0031308)))), value.w);\n}\n@end\n@export clay.chunk.skinning_header\n#ifdef SKINNING\nattribute vec3 weight : WEIGHT;\nattribute vec4 joint : JOINT;\n#ifdef USE_SKIN_MATRICES_TEXTURE\nuniform sampler2D skinMatricesTexture : ignore;\nuniform float skinMatricesTextureSize: ignore;\nmat4 getSkinMatrix(sampler2D tex, float idx) {\n float j = idx * 4.0;\n float x = mod(j, skinMatricesTextureSize);\n float y = floor(j / skinMatricesTextureSize) + 0.5;\n vec2 scale = vec2(skinMatricesTextureSize);\n return mat4(\n texture2D(tex, vec2(x + 0.5, y) / scale),\n texture2D(tex, vec2(x + 1.5, y) / scale),\n texture2D(tex, vec2(x + 2.5, y) / scale),\n texture2D(tex, vec2(x + 3.5, y) / scale)\n );\n}\nmat4 getSkinMatrix(float idx) {\n return getSkinMatrix(skinMatricesTexture, idx);\n}\n#else\nuniform mat4 skinMatrix[JOINT_COUNT] : SKIN_MATRIX;\nmat4 getSkinMatrix(float idx) {\n return skinMatrix[int(idx)];\n}\n#endif\n#endif\n@end\n@export clay.chunk.skin_matrix\nmat4 skinMatrixWS = getSkinMatrix(joint.x) * weight.x;\nif (weight.y > 1e-4)\n{\n skinMatrixWS += getSkinMatrix(joint.y) * weight.y;\n}\nif (weight.z > 1e-4)\n{\n skinMatrixWS += getSkinMatrix(joint.z) * weight.z;\n}\nfloat weightW = 1.0-weight.x-weight.y-weight.z;\nif (weightW > 1e-4)\n{\n skinMatrixWS += getSkinMatrix(joint.w) * weightW;\n}\n@end\n@export clay.util.parallax_correct\nvec3 parallaxCorrect(in vec3 dir, in vec3 pos, in vec3 boxMin, in vec3 boxMax) {\n vec3 first = (boxMax - pos) / dir;\n vec3 second = (boxMin - pos) / dir;\n vec3 further = max(first, second);\n float dist = min(further.x, min(further.y, further.z));\n vec3 fixedPos = pos + dir * dist;\n vec3 boxCenter = (boxMax + boxMin) * 0.5;\n return normalize(fixedPos - boxCenter);\n}\n@end\n@export clay.util.clamp_sample\nvec4 clampSample(const in sampler2D texture, const in vec2 coord)\n{\n#ifdef STEREO\n float eye = step(0.5, coord.x) * 0.5;\n vec2 coordClamped = clamp(coord, vec2(eye, 0.0), vec2(0.5 + eye, 1.0));\n#else\n vec2 coordClamped = clamp(coord, vec2(0.0), vec2(1.0));\n#endif\n return texture2D(texture, coordClamped);\n}\n@end\n@export clay.util.ACES\nvec3 ACESToneMapping(vec3 color)\n{\n const float A = 2.51;\n const float B = 0.03;\n const float C = 2.43;\n const float D = 0.59;\n const float E = 0.14;\n return (color * (A * color + B)) / (color * (C * color + D) + E);\n}\n@end"); + + +/***/ }), +/* 147 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony default export */ __webpack_exports__["a"] = ("\n@export ecgl.common.transformUniforms\nuniform mat4 worldViewProjection : WORLDVIEWPROJECTION;\nuniform mat4 worldInverseTranspose : WORLDINVERSETRANSPOSE;\nuniform mat4 world : WORLD;\n@end\n\n@export ecgl.common.attributes\nattribute vec3 position : POSITION;\nattribute vec2 texcoord : TEXCOORD_0;\nattribute vec3 normal : NORMAL;\n@end\n\n@export ecgl.common.uv.header\nuniform vec2 uvRepeat : [1.0, 1.0];\nuniform vec2 uvOffset : [0.0, 0.0];\nuniform vec2 detailUvRepeat : [1.0, 1.0];\nuniform vec2 detailUvOffset : [0.0, 0.0];\n\nvarying vec2 v_Texcoord;\nvarying vec2 v_DetailTexcoord;\n@end\n\n@export ecgl.common.uv.main\nv_Texcoord = texcoord * uvRepeat + uvOffset;\nv_DetailTexcoord = texcoord * detailUvRepeat + detailUvOffset;\n@end\n\n@export ecgl.common.uv.fragmentHeader\nvarying vec2 v_Texcoord;\nvarying vec2 v_DetailTexcoord;\n@end\n\n\n@export ecgl.common.albedo.main\n\n vec4 albedoTexel = vec4(1.0);\n#ifdef DIFFUSEMAP_ENABLED\n albedoTexel = texture2D(diffuseMap, v_Texcoord);\n #ifdef SRGB_DECODE\n albedoTexel = sRGBToLinear(albedoTexel);\n #endif\n#endif\n\n#ifdef DETAILMAP_ENABLED\n vec4 detailTexel = texture2D(detailMap, v_DetailTexcoord);\n #ifdef SRGB_DECODE\n detailTexel = sRGBToLinear(detailTexel);\n #endif\n albedoTexel.rgb = mix(albedoTexel.rgb, detailTexel.rgb, detailTexel.a);\n albedoTexel.a = detailTexel.a + (1.0 - detailTexel.a) * albedoTexel.a;\n#endif\n\n@end\n\n@export ecgl.common.wireframe.vertexHeader\n\n#ifdef WIREFRAME_QUAD\nattribute vec4 barycentric;\nvarying vec4 v_Barycentric;\n#elif defined(WIREFRAME_TRIANGLE)\nattribute vec3 barycentric;\nvarying vec3 v_Barycentric;\n#endif\n\n@end\n\n@export ecgl.common.wireframe.vertexMain\n\n#if defined(WIREFRAME_QUAD) || defined(WIREFRAME_TRIANGLE)\n v_Barycentric = barycentric;\n#endif\n\n@end\n\n\n@export ecgl.common.wireframe.fragmentHeader\n\nuniform float wireframeLineWidth : 1;\nuniform vec4 wireframeLineColor: [0, 0, 0, 0.5];\n\n#ifdef WIREFRAME_QUAD\nvarying vec4 v_Barycentric;\nfloat edgeFactor () {\n vec4 d = fwidth(v_Barycentric);\n vec4 a4 = smoothstep(vec4(0.0), d * wireframeLineWidth, v_Barycentric);\n return min(min(min(a4.x, a4.y), a4.z), a4.w);\n}\n#elif defined(WIREFRAME_TRIANGLE)\nvarying vec3 v_Barycentric;\nfloat edgeFactor () {\n vec3 d = fwidth(v_Barycentric);\n vec3 a3 = smoothstep(vec3(0.0), d * wireframeLineWidth, v_Barycentric);\n return min(min(a3.x, a3.y), a3.z);\n}\n#endif\n\n@end\n\n\n@export ecgl.common.wireframe.fragmentMain\n\n#if defined(WIREFRAME_QUAD) || defined(WIREFRAME_TRIANGLE)\n if (wireframeLineWidth > 0.) {\n vec4 lineColor = wireframeLineColor;\n#ifdef SRGB_DECODE\n lineColor = sRGBToLinear(lineColor);\n#endif\n\n gl_FragColor.rgb = mix(gl_FragColor.rgb, lineColor.rgb, (1.0 - edgeFactor()) * lineColor.a);\n }\n#endif\n@end\n\n\n\n\n@export ecgl.common.bumpMap.header\n\n#ifdef BUMPMAP_ENABLED\nuniform sampler2D bumpMap;\nuniform float bumpScale : 1.0;\n\n\nvec3 bumpNormal(vec3 surfPos, vec3 surfNormal, vec3 baseNormal)\n{\n vec2 dSTdx = dFdx(v_Texcoord);\n vec2 dSTdy = dFdy(v_Texcoord);\n\n float Hll = bumpScale * texture2D(bumpMap, v_Texcoord).x;\n float dHx = bumpScale * texture2D(bumpMap, v_Texcoord + dSTdx).x - Hll;\n float dHy = bumpScale * texture2D(bumpMap, v_Texcoord + dSTdy).x - Hll;\n\n vec3 vSigmaX = dFdx(surfPos);\n vec3 vSigmaY = dFdy(surfPos);\n vec3 vN = surfNormal;\n\n vec3 R1 = cross(vSigmaY, vN);\n vec3 R2 = cross(vN, vSigmaX);\n\n float fDet = dot(vSigmaX, R1);\n\n vec3 vGrad = sign(fDet) * (dHx * R1 + dHy * R2);\n return normalize(abs(fDet) * baseNormal - vGrad);\n\n}\n#endif\n\n@end\n\n@export ecgl.common.normalMap.vertexHeader\n\n#ifdef NORMALMAP_ENABLED\nattribute vec4 tangent : TANGENT;\nvarying vec3 v_Tangent;\nvarying vec3 v_Bitangent;\n#endif\n\n@end\n\n@export ecgl.common.normalMap.vertexMain\n\n#ifdef NORMALMAP_ENABLED\n if (dot(tangent, tangent) > 0.0) {\n v_Tangent = normalize((worldInverseTranspose * vec4(tangent.xyz, 0.0)).xyz);\n v_Bitangent = normalize(cross(v_Normal, v_Tangent) * tangent.w);\n }\n#endif\n\n@end\n\n\n@export ecgl.common.normalMap.fragmentHeader\n\n#ifdef NORMALMAP_ENABLED\nuniform sampler2D normalMap;\nvarying vec3 v_Tangent;\nvarying vec3 v_Bitangent;\n#endif\n\n@end\n\n@export ecgl.common.normalMap.fragmentMain\n#ifdef NORMALMAP_ENABLED\n if (dot(v_Tangent, v_Tangent) > 0.0) {\n vec3 normalTexel = texture2D(normalMap, v_DetailTexcoord).xyz;\n if (dot(normalTexel, normalTexel) > 0.0) { N = normalTexel * 2.0 - 1.0;\n mat3 tbn = mat3(v_Tangent, v_Bitangent, v_Normal);\n N = normalize(tbn * N);\n }\n }\n#endif\n@end\n\n\n\n@export ecgl.common.vertexAnimation.header\n\n#ifdef VERTEX_ANIMATION\nattribute vec3 prevPosition;\nattribute vec3 prevNormal;\nuniform float percent;\n#endif\n\n@end\n\n@export ecgl.common.vertexAnimation.main\n\n#ifdef VERTEX_ANIMATION\n vec3 pos = mix(prevPosition, position, percent);\n vec3 norm = mix(prevNormal, normal, percent);\n#else\n vec3 pos = position;\n vec3 norm = normal;\n#endif\n\n@end\n\n\n@export ecgl.common.ssaoMap.header\n#ifdef SSAOMAP_ENABLED\nuniform sampler2D ssaoMap;\nuniform vec4 viewport : VIEWPORT;\n#endif\n@end\n\n@export ecgl.common.ssaoMap.main\n float ao = 1.0;\n#ifdef SSAOMAP_ENABLED\n ao = texture2D(ssaoMap, (gl_FragCoord.xy - viewport.xy) / viewport.zw).r;\n#endif\n@end\n\n\n\n\n@export ecgl.common.diffuseLayer.header\n\n#if (LAYER_DIFFUSEMAP_COUNT > 0)\nuniform float layerDiffuseIntensity[LAYER_DIFFUSEMAP_COUNT];\nuniform sampler2D layerDiffuseMap[LAYER_DIFFUSEMAP_COUNT];\n#endif\n\n@end\n\n@export ecgl.common.emissiveLayer.header\n\n#if (LAYER_EMISSIVEMAP_COUNT > 0)\nuniform float layerEmissionIntensity[LAYER_EMISSIVEMAP_COUNT];\nuniform sampler2D layerEmissiveMap[LAYER_EMISSIVEMAP_COUNT];\n#endif\n\n@end\n\n@export ecgl.common.layers.header\n@import ecgl.common.diffuseLayer.header\n@import ecgl.common.emissiveLayer.header\n@end\n\n@export ecgl.common.diffuseLayer.main\n\n#if (LAYER_DIFFUSEMAP_COUNT > 0)\n for (int _idx_ = 0; _idx_ < LAYER_DIFFUSEMAP_COUNT; _idx_++) {{\n float intensity = layerDiffuseIntensity[_idx_];\n vec4 texel2 = texture2D(layerDiffuseMap[_idx_], v_Texcoord);\n #ifdef SRGB_DECODE\n texel2 = sRGBToLinear(texel2);\n #endif\n albedoTexel.rgb = mix(albedoTexel.rgb, texel2.rgb * intensity, texel2.a);\n albedoTexel.a = texel2.a + (1.0 - texel2.a) * albedoTexel.a;\n }}\n#endif\n\n@end\n\n@export ecgl.common.emissiveLayer.main\n\n#if (LAYER_EMISSIVEMAP_COUNT > 0)\n for (int _idx_ = 0; _idx_ < LAYER_EMISSIVEMAP_COUNT; _idx_++)\n {{\n vec4 texel2 = texture2D(layerEmissiveMap[_idx_], v_Texcoord) * layerEmissionIntensity[_idx_];\n #ifdef SRGB_DECODE\n texel2 = sRGBToLinear(texel2);\n #endif\n float intensity = layerEmissionIntensity[_idx_];\n gl_FragColor.rgb += texel2.rgb * texel2.a * intensity;\n }}\n#endif\n\n@end\n"); + + +/***/ }), +/* 148 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony default export */ __webpack_exports__["a"] = ("@export ecgl.color.vertex\n\nuniform mat4 worldViewProjection : WORLDVIEWPROJECTION;\n\n@import ecgl.common.uv.header\n\nattribute vec2 texcoord : TEXCOORD_0;\nattribute vec3 position: POSITION;\n\n@import ecgl.common.wireframe.vertexHeader\n\n#ifdef VERTEX_COLOR\nattribute vec4 a_Color : COLOR;\nvarying vec4 v_Color;\n#endif\n\n#ifdef VERTEX_ANIMATION\nattribute vec3 prevPosition;\nuniform float percent : 1.0;\n#endif\n\nvoid main()\n{\n#ifdef VERTEX_ANIMATION\n vec3 pos = mix(prevPosition, position, percent);\n#else\n vec3 pos = position;\n#endif\n\n gl_Position = worldViewProjection * vec4(pos, 1.0);\n\n @import ecgl.common.uv.main\n\n#ifdef VERTEX_COLOR\n v_Color = a_Color;\n#endif\n\n @import ecgl.common.wireframe.vertexMain\n\n}\n\n@end\n\n@export ecgl.color.fragment\n\n#define LAYER_DIFFUSEMAP_COUNT 0\n#define LAYER_EMISSIVEMAP_COUNT 0\n\nuniform sampler2D diffuseMap;\nuniform sampler2D detailMap;\n\nuniform vec4 color : [1.0, 1.0, 1.0, 1.0];\n\n#ifdef VERTEX_COLOR\nvarying vec4 v_Color;\n#endif\n\n@import ecgl.common.layers.header\n\n@import ecgl.common.uv.fragmentHeader\n\n@import ecgl.common.wireframe.fragmentHeader\n\n@import clay.util.srgb\n\nvoid main()\n{\n#ifdef SRGB_DECODE\n gl_FragColor = sRGBToLinear(color);\n#else\n gl_FragColor = color;\n#endif\n\n#ifdef VERTEX_COLOR\n gl_FragColor *= v_Color;\n#endif\n\n @import ecgl.common.albedo.main\n\n @import ecgl.common.diffuseLayer.main\n\n gl_FragColor *= albedoTexel;\n\n @import ecgl.common.emissiveLayer.main\n\n @import ecgl.common.wireframe.fragmentMain\n\n}\n@end"); + + +/***/ }), +/* 149 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony default export */ __webpack_exports__["a"] = ("/**\n * http: */\n\n@export ecgl.lambert.vertex\n\n@import ecgl.common.transformUniforms\n\n@import ecgl.common.uv.header\n\n\n@import ecgl.common.attributes\n\n@import ecgl.common.wireframe.vertexHeader\n\n#ifdef VERTEX_COLOR\nattribute vec4 a_Color : COLOR;\nvarying vec4 v_Color;\n#endif\n\n\n@import ecgl.common.vertexAnimation.header\n\n\nvarying vec3 v_Normal;\nvarying vec3 v_WorldPosition;\n\nvoid main()\n{\n @import ecgl.common.uv.main\n\n @import ecgl.common.vertexAnimation.main\n\n\n gl_Position = worldViewProjection * vec4(pos, 1.0);\n\n v_Normal = normalize((worldInverseTranspose * vec4(norm, 0.0)).xyz);\n v_WorldPosition = (world * vec4(pos, 1.0)).xyz;\n\n#ifdef VERTEX_COLOR\n v_Color = a_Color;\n#endif\n\n @import ecgl.common.wireframe.vertexMain\n}\n\n@end\n\n\n@export ecgl.lambert.fragment\n\n#define LAYER_DIFFUSEMAP_COUNT 0\n#define LAYER_EMISSIVEMAP_COUNT 0\n\n#define NORMAL_UP_AXIS 1\n#define NORMAL_FRONT_AXIS 2\n\n@import ecgl.common.uv.fragmentHeader\n\nvarying vec3 v_Normal;\nvarying vec3 v_WorldPosition;\n\nuniform sampler2D diffuseMap;\nuniform sampler2D detailMap;\n\n@import ecgl.common.layers.header\n\nuniform float emissionIntensity: 1.0;\n\nuniform vec4 color : [1.0, 1.0, 1.0, 1.0];\n\nuniform mat4 viewInverse : VIEWINVERSE;\n\n#ifdef AMBIENT_LIGHT_COUNT\n@import clay.header.ambient_light\n#endif\n#ifdef AMBIENT_SH_LIGHT_COUNT\n@import clay.header.ambient_sh_light\n#endif\n\n#ifdef DIRECTIONAL_LIGHT_COUNT\n@import clay.header.directional_light\n#endif\n\n#ifdef VERTEX_COLOR\nvarying vec4 v_Color;\n#endif\n\n\n@import ecgl.common.ssaoMap.header\n\n@import ecgl.common.bumpMap.header\n\n@import clay.util.srgb\n\n@import ecgl.common.wireframe.fragmentHeader\n\n@import clay.plugin.compute_shadow_map\n\nvoid main()\n{\n#ifdef SRGB_DECODE\n gl_FragColor = sRGBToLinear(color);\n#else\n gl_FragColor = color;\n#endif\n\n#ifdef VERTEX_COLOR\n #ifdef SRGB_DECODE\n gl_FragColor *= sRGBToLinear(v_Color);\n #else\n gl_FragColor *= v_Color;\n #endif\n#endif\n\n @import ecgl.common.albedo.main\n\n @import ecgl.common.diffuseLayer.main\n\n gl_FragColor *= albedoTexel;\n\n vec3 N = v_Normal;\n#ifdef DOUBLE_SIDED\n vec3 eyePos = viewInverse[3].xyz;\n vec3 V = normalize(eyePos - v_WorldPosition);\n\n if (dot(N, V) < 0.0) {\n N = -N;\n }\n#endif\n\n float ambientFactor = 1.0;\n\n#ifdef BUMPMAP_ENABLED\n N = bumpNormal(v_WorldPosition, v_Normal, N);\n ambientFactor = dot(v_Normal, N);\n#endif\n\n vec3 N2 = vec3(N.x, N[NORMAL_UP_AXIS], N[NORMAL_FRONT_AXIS]);\n\n vec3 diffuseColor = vec3(0.0, 0.0, 0.0);\n\n @import ecgl.common.ssaoMap.main\n\n#ifdef AMBIENT_LIGHT_COUNT\n for(int i = 0; i < AMBIENT_LIGHT_COUNT; i++)\n {\n diffuseColor += ambientLightColor[i] * ambientFactor * ao;\n }\n#endif\n#ifdef AMBIENT_SH_LIGHT_COUNT\n for(int _idx_ = 0; _idx_ < AMBIENT_SH_LIGHT_COUNT; _idx_++)\n {{\n diffuseColor += calcAmbientSHLight(_idx_, N2) * ambientSHLightColor[_idx_] * ao;\n }}\n#endif\n#ifdef DIRECTIONAL_LIGHT_COUNT\n#if defined(DIRECTIONAL_LIGHT_SHADOWMAP_COUNT)\n float shadowContribsDir[DIRECTIONAL_LIGHT_COUNT];\n if(shadowEnabled)\n {\n computeShadowOfDirectionalLights(v_WorldPosition, shadowContribsDir);\n }\n#endif\n for(int i = 0; i < DIRECTIONAL_LIGHT_COUNT; i++)\n {\n vec3 lightDirection = -directionalLightDirection[i];\n vec3 lightColor = directionalLightColor[i];\n\n float shadowContrib = 1.0;\n#if defined(DIRECTIONAL_LIGHT_SHADOWMAP_COUNT)\n if (shadowEnabled)\n {\n shadowContrib = shadowContribsDir[i];\n }\n#endif\n\n float ndl = dot(N, normalize(lightDirection)) * shadowContrib;\n\n diffuseColor += lightColor * clamp(ndl, 0.0, 1.0);\n }\n#endif\n\n gl_FragColor.rgb *= diffuseColor;\n\n @import ecgl.common.emissiveLayer.main\n\n @import ecgl.common.wireframe.fragmentMain\n}\n\n@end"); + + +/***/ }), +/* 150 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony default export */ __webpack_exports__["a"] = ("@export ecgl.realistic.vertex\n\n@import ecgl.common.transformUniforms\n\n@import ecgl.common.uv.header\n\n@import ecgl.common.attributes\n\n\n@import ecgl.common.wireframe.vertexHeader\n\n#ifdef VERTEX_COLOR\nattribute vec4 a_Color : COLOR;\nvarying vec4 v_Color;\n#endif\n\n#ifdef NORMALMAP_ENABLED\nattribute vec4 tangent : TANGENT;\nvarying vec3 v_Tangent;\nvarying vec3 v_Bitangent;\n#endif\n\n@import ecgl.common.vertexAnimation.header\n\nvarying vec3 v_Normal;\nvarying vec3 v_WorldPosition;\n\nvoid main()\n{\n\n @import ecgl.common.uv.main\n\n @import ecgl.common.vertexAnimation.main\n\n gl_Position = worldViewProjection * vec4(pos, 1.0);\n\n v_Normal = normalize((worldInverseTranspose * vec4(norm, 0.0)).xyz);\n v_WorldPosition = (world * vec4(pos, 1.0)).xyz;\n\n#ifdef VERTEX_COLOR\n v_Color = a_Color;\n#endif\n\n#ifdef NORMALMAP_ENABLED\n v_Tangent = normalize((worldInverseTranspose * vec4(tangent.xyz, 0.0)).xyz);\n v_Bitangent = normalize(cross(v_Normal, v_Tangent) * tangent.w);\n#endif\n\n @import ecgl.common.wireframe.vertexMain\n\n}\n\n@end\n\n\n\n@export ecgl.realistic.fragment\n\n#define LAYER_DIFFUSEMAP_COUNT 0\n#define LAYER_EMISSIVEMAP_COUNT 0\n#define PI 3.14159265358979\n#define ROUGHNESS_CHANEL 0\n#define METALNESS_CHANEL 1\n\n#define NORMAL_UP_AXIS 1\n#define NORMAL_FRONT_AXIS 2\n\n#ifdef VERTEX_COLOR\nvarying vec4 v_Color;\n#endif\n\n@import ecgl.common.uv.fragmentHeader\n\nvarying vec3 v_Normal;\nvarying vec3 v_WorldPosition;\n\nuniform sampler2D diffuseMap;\n\nuniform sampler2D detailMap;\nuniform sampler2D metalnessMap;\nuniform sampler2D roughnessMap;\n\n@import ecgl.common.layers.header\n\nuniform float emissionIntensity: 1.0;\n\nuniform vec4 color : [1.0, 1.0, 1.0, 1.0];\n\nuniform float metalness : 0.0;\nuniform float roughness : 0.5;\n\nuniform mat4 viewInverse : VIEWINVERSE;\n\n#ifdef AMBIENT_LIGHT_COUNT\n@import clay.header.ambient_light\n#endif\n\n#ifdef AMBIENT_SH_LIGHT_COUNT\n@import clay.header.ambient_sh_light\n#endif\n\n#ifdef AMBIENT_CUBEMAP_LIGHT_COUNT\n@import clay.header.ambient_cubemap_light\n#endif\n\n#ifdef DIRECTIONAL_LIGHT_COUNT\n@import clay.header.directional_light\n#endif\n\n@import ecgl.common.normalMap.fragmentHeader\n\n@import ecgl.common.ssaoMap.header\n\n@import ecgl.common.bumpMap.header\n\n@import clay.util.srgb\n\n@import clay.util.rgbm\n\n@import ecgl.common.wireframe.fragmentHeader\n\n@import clay.plugin.compute_shadow_map\n\nvec3 F_Schlick(float ndv, vec3 spec) {\n return spec + (1.0 - spec) * pow(1.0 - ndv, 5.0);\n}\n\nfloat D_Phong(float g, float ndh) {\n float a = pow(8192.0, g);\n return (a + 2.0) / 8.0 * pow(ndh, a);\n}\n\nvoid main()\n{\n vec4 albedoColor = color;\n\n vec3 eyePos = viewInverse[3].xyz;\n vec3 V = normalize(eyePos - v_WorldPosition);\n#ifdef VERTEX_COLOR\n #ifdef SRGB_DECODE\n albedoColor *= sRGBToLinear(v_Color);\n #else\n albedoColor *= v_Color;\n #endif\n#endif\n\n @import ecgl.common.albedo.main\n\n @import ecgl.common.diffuseLayer.main\n\n albedoColor *= albedoTexel;\n\n float m = metalness;\n\n#ifdef METALNESSMAP_ENABLED\n float m2 = texture2D(metalnessMap, v_DetailTexcoord)[METALNESS_CHANEL];\n m = clamp(m2 + (m - 0.5) * 2.0, 0.0, 1.0);\n#endif\n\n vec3 baseColor = albedoColor.rgb;\n albedoColor.rgb = baseColor * (1.0 - m);\n vec3 specFactor = mix(vec3(0.04), baseColor, m);\n\n float g = 1.0 - roughness;\n\n#ifdef ROUGHNESSMAP_ENABLED\n float g2 = 1.0 - texture2D(roughnessMap, v_DetailTexcoord)[ROUGHNESS_CHANEL];\n g = clamp(g2 + (g - 0.5) * 2.0, 0.0, 1.0);\n#endif\n\n vec3 N = v_Normal;\n\n#ifdef DOUBLE_SIDED\n if (dot(N, V) < 0.0) {\n N = -N;\n }\n#endif\n\n float ambientFactor = 1.0;\n\n#ifdef BUMPMAP_ENABLED\n N = bumpNormal(v_WorldPosition, v_Normal, N);\n ambientFactor = dot(v_Normal, N);\n#endif\n\n@import ecgl.common.normalMap.fragmentMain\n\n vec3 N2 = vec3(N.x, N[NORMAL_UP_AXIS], N[NORMAL_FRONT_AXIS]);\n\n vec3 diffuseTerm = vec3(0.0);\n vec3 specularTerm = vec3(0.0);\n\n float ndv = clamp(dot(N, V), 0.0, 1.0);\n vec3 fresnelTerm = F_Schlick(ndv, specFactor);\n\n @import ecgl.common.ssaoMap.main\n\n#ifdef AMBIENT_LIGHT_COUNT\n for(int _idx_ = 0; _idx_ < AMBIENT_LIGHT_COUNT; _idx_++)\n {{\n diffuseTerm += ambientLightColor[_idx_] * ambientFactor * ao;\n }}\n#endif\n\n#ifdef AMBIENT_SH_LIGHT_COUNT\n for(int _idx_ = 0; _idx_ < AMBIENT_SH_LIGHT_COUNT; _idx_++)\n {{\n diffuseTerm += calcAmbientSHLight(_idx_, N2) * ambientSHLightColor[_idx_] * ao;\n }}\n#endif\n\n#ifdef DIRECTIONAL_LIGHT_COUNT\n#if defined(DIRECTIONAL_LIGHT_SHADOWMAP_COUNT)\n float shadowContribsDir[DIRECTIONAL_LIGHT_COUNT];\n if(shadowEnabled)\n {\n computeShadowOfDirectionalLights(v_WorldPosition, shadowContribsDir);\n }\n#endif\n for(int _idx_ = 0; _idx_ < DIRECTIONAL_LIGHT_COUNT; _idx_++)\n {{\n vec3 L = -directionalLightDirection[_idx_];\n vec3 lc = directionalLightColor[_idx_];\n\n vec3 H = normalize(L + V);\n float ndl = clamp(dot(N, normalize(L)), 0.0, 1.0);\n float ndh = clamp(dot(N, H), 0.0, 1.0);\n\n float shadowContrib = 1.0;\n#if defined(DIRECTIONAL_LIGHT_SHADOWMAP_COUNT)\n if (shadowEnabled)\n {\n shadowContrib = shadowContribsDir[_idx_];\n }\n#endif\n\n vec3 li = lc * ndl * shadowContrib;\n\n diffuseTerm += li;\n specularTerm += li * fresnelTerm * D_Phong(g, ndh);\n }}\n#endif\n\n\n#ifdef AMBIENT_CUBEMAP_LIGHT_COUNT\n vec3 L = reflect(-V, N);\n L = vec3(L.x, L[NORMAL_UP_AXIS], L[NORMAL_FRONT_AXIS]);\n float rough2 = clamp(1.0 - g, 0.0, 1.0);\n float bias2 = rough2 * 5.0;\n vec2 brdfParam2 = texture2D(ambientCubemapLightBRDFLookup[0], vec2(rough2, ndv)).xy;\n vec3 envWeight2 = specFactor * brdfParam2.x + brdfParam2.y;\n vec3 envTexel2;\n for(int _idx_ = 0; _idx_ < AMBIENT_CUBEMAP_LIGHT_COUNT; _idx_++)\n {{\n envTexel2 = RGBMDecode(textureCubeLodEXT(ambientCubemapLightCubemap[_idx_], L, bias2), 8.12);\n specularTerm += ambientCubemapLightColor[_idx_] * envTexel2 * envWeight2 * ao;\n }}\n#endif\n\n gl_FragColor.rgb = albedoColor.rgb * diffuseTerm + specularTerm;\n gl_FragColor.a = albedoColor.a;\n\n#ifdef SRGB_ENCODE\n gl_FragColor = linearTosRGB(gl_FragColor);\n#endif\n\n @import ecgl.common.emissiveLayer.main\n\n @import ecgl.common.wireframe.fragmentMain\n}\n\n@end"); + + +/***/ }), +/* 151 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony default export */ __webpack_exports__["a"] = ("@export ecgl.hatching.vertex\n\n@import ecgl.realistic.vertex\n\n@end\n\n\n@export ecgl.hatching.fragment\n\n#define NORMAL_UP_AXIS 1\n#define NORMAL_FRONT_AXIS 2\n\n@import ecgl.common.uv.fragmentHeader\n\nvarying vec3 v_Normal;\nvarying vec3 v_WorldPosition;\n\nuniform vec4 color : [0.0, 0.0, 0.0, 1.0];\nuniform vec4 paperColor : [1.0, 1.0, 1.0, 1.0];\n\nuniform mat4 viewInverse : VIEWINVERSE;\n\n#ifdef AMBIENT_LIGHT_COUNT\n@import clay.header.ambient_light\n#endif\n#ifdef AMBIENT_SH_LIGHT_COUNT\n@import clay.header.ambient_sh_light\n#endif\n\n#ifdef DIRECTIONAL_LIGHT_COUNT\n@import clay.header.directional_light\n#endif\n\n#ifdef VERTEX_COLOR\nvarying vec4 v_Color;\n#endif\n\n\n@import ecgl.common.ssaoMap.header\n\n@import ecgl.common.bumpMap.header\n\n@import clay.util.srgb\n\n@import ecgl.common.wireframe.fragmentHeader\n\n@import clay.plugin.compute_shadow_map\n\nuniform sampler2D hatch1;\nuniform sampler2D hatch2;\nuniform sampler2D hatch3;\nuniform sampler2D hatch4;\nuniform sampler2D hatch5;\nuniform sampler2D hatch6;\n\nfloat shade(in float tone) {\n vec4 c = vec4(1. ,1., 1., 1.);\n float step = 1. / 6.;\n vec2 uv = v_DetailTexcoord;\n if (tone <= step / 2.0) {\n c = mix(vec4(0.), texture2D(hatch6, uv), 12. * tone);\n }\n else if (tone <= step) {\n c = mix(texture2D(hatch6, uv), texture2D(hatch5, uv), 6. * tone);\n }\n if(tone > step && tone <= 2. * step){\n c = mix(texture2D(hatch5, uv), texture2D(hatch4, uv) , 6. * (tone - step));\n }\n if(tone > 2. * step && tone <= 3. * step){\n c = mix(texture2D(hatch4, uv), texture2D(hatch3, uv), 6. * (tone - 2. * step));\n }\n if(tone > 3. * step && tone <= 4. * step){\n c = mix(texture2D(hatch3, uv), texture2D(hatch2, uv), 6. * (tone - 3. * step));\n }\n if(tone > 4. * step && tone <= 5. * step){\n c = mix(texture2D(hatch2, uv), texture2D(hatch1, uv), 6. * (tone - 4. * step));\n }\n if(tone > 5. * step){\n c = mix(texture2D(hatch1, uv), vec4(1.), 6. * (tone - 5. * step));\n }\n\n return c.r;\n}\n\nconst vec3 w = vec3(0.2125, 0.7154, 0.0721);\n\nvoid main()\n{\n#ifdef SRGB_DECODE\n vec4 inkColor = sRGBToLinear(color);\n#else\n vec4 inkColor = color;\n#endif\n\n#ifdef VERTEX_COLOR\n #ifdef SRGB_DECODE\n inkColor *= sRGBToLinear(v_Color);\n #else\n inkColor *= v_Color;\n #endif\n#endif\n\n vec3 N = v_Normal;\n#ifdef DOUBLE_SIDED\n vec3 eyePos = viewInverse[3].xyz;\n vec3 V = normalize(eyePos - v_WorldPosition);\n\n if (dot(N, V) < 0.0) {\n N = -N;\n }\n#endif\n\n float tone = 0.0;\n\n float ambientFactor = 1.0;\n\n#ifdef BUMPMAP_ENABLED\n N = bumpNormal(v_WorldPosition, v_Normal, N);\n ambientFactor = dot(v_Normal, N);\n#endif\n\n vec3 N2 = vec3(N.x, N[NORMAL_UP_AXIS], N[NORMAL_FRONT_AXIS]);\n\n @import ecgl.common.ssaoMap.main\n\n#ifdef AMBIENT_LIGHT_COUNT\n for(int i = 0; i < AMBIENT_LIGHT_COUNT; i++)\n {\n tone += dot(ambientLightColor[i], w) * ambientFactor * ao;\n }\n#endif\n#ifdef AMBIENT_SH_LIGHT_COUNT\n for(int _idx_ = 0; _idx_ < AMBIENT_SH_LIGHT_COUNT; _idx_++)\n {{\n tone += dot(calcAmbientSHLight(_idx_, N2) * ambientSHLightColor[_idx_], w) * ao;\n }}\n#endif\n#ifdef DIRECTIONAL_LIGHT_COUNT\n#if defined(DIRECTIONAL_LIGHT_SHADOWMAP_COUNT)\n float shadowContribsDir[DIRECTIONAL_LIGHT_COUNT];\n if(shadowEnabled)\n {\n computeShadowOfDirectionalLights(v_WorldPosition, shadowContribsDir);\n }\n#endif\n for(int i = 0; i < DIRECTIONAL_LIGHT_COUNT; i++)\n {\n vec3 lightDirection = -directionalLightDirection[i];\n float lightTone = dot(directionalLightColor[i], w);\n\n float shadowContrib = 1.0;\n#if defined(DIRECTIONAL_LIGHT_SHADOWMAP_COUNT)\n if (shadowEnabled)\n {\n shadowContrib = shadowContribsDir[i];\n }\n#endif\n\n float ndl = dot(N, normalize(lightDirection)) * shadowContrib;\n\n tone += lightTone * clamp(ndl, 0.0, 1.0);\n }\n#endif\n\n gl_FragColor = mix(inkColor, paperColor, shade(clamp(tone, 0.0, 1.0)));\n }\n@end\n"); + + +/***/ }), +/* 152 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony default export */ __webpack_exports__["a"] = ("@export ecgl.sm.depth.vertex\n\nuniform mat4 worldViewProjection : WORLDVIEWPROJECTION;\n\nattribute vec3 position : POSITION;\nattribute vec2 texcoord : TEXCOORD_0;\n\n#ifdef VERTEX_ANIMATION\nattribute vec3 prevPosition;\nuniform float percent : 1.0;\n#endif\n\nvarying vec4 v_ViewPosition;\nvarying vec2 v_Texcoord;\n\nvoid main(){\n\n#ifdef VERTEX_ANIMATION\n vec3 pos = mix(prevPosition, position, percent);\n#else\n vec3 pos = position;\n#endif\n\n v_ViewPosition = worldViewProjection * vec4(pos, 1.0);\n gl_Position = v_ViewPosition;\n\n v_Texcoord = texcoord;\n\n}\n@end\n\n\n\n@export ecgl.sm.depth.fragment\n\n@import clay.sm.depth.fragment\n\n@end"); + + +/***/ }), +/* 153 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__); + + +var GL_SERIES = ['bar3D', 'line3D', 'map3D', 'scatter3D', 'surface', 'lines3D', 'scatterGL', 'scatter3D']; + +function convertNormalEmphasis(option, optType) { + if (option && option[optType] && (option[optType].normal || option[optType].emphasis)) { + var normalOpt = option[optType].normal; + var emphasisOpt = option[optType].emphasis; + + if (normalOpt) { + option[optType] = normalOpt; + } + if (emphasisOpt) { + option.emphasis = option.emphasis || {}; + option.emphasis[optType] = emphasisOpt; + } + } +} + +function convertNormalEmphasisForEach(option) { + convertNormalEmphasis(option, 'itemStyle'); + convertNormalEmphasis(option, 'lineStyle'); + convertNormalEmphasis(option, 'areaStyle'); + convertNormalEmphasis(option, 'label'); +} + +function removeTextStyleInAxis(axesOpt) { + if (!axesOpt) { + return; + } + if (!(axesOpt instanceof Array)) { + axesOpt = [axesOpt]; + } + __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.util.each(axesOpt, function (axisOpt) { + if (axisOpt.axisLabel) { + var labelOpt = axisOpt.axisLabel; + __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.util.extend(labelOpt, labelOpt.textStyle); + labelOpt.textStyle = null; + } + }); +} + +/* harmony default export */ __webpack_exports__["a"] = (function (option) { + __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.util.each(option.series, function (series) { + if (__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.util.indexOf(GL_SERIES, series.type) >= 0) { + convertNormalEmphasisForEach(series); + + // Compatitable with original mapbox + if (series.coordinateSystem === 'mapbox') { + series.coordinateSystem = 'mapbox3D'; + option.mapbox3D = option.mapbox; + } + } + }); + + removeTextStyleInAxis(option.xAxis3D); + removeTextStyleInAxis(option.yAxis3D); + removeTextStyleInAxis(option.zAxis3D); + removeTextStyleInAxis(option.grid3D); + + convertNormalEmphasis(option.geo3D); +});; + +/***/ }), +/* 154 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__grid3D_Axis3DModel__ = __webpack_require__(155); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__grid3D_Grid3DModel__ = __webpack_require__(159); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__grid3D_Grid3DView__ = __webpack_require__(160); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__coord_grid3DCreator__ = __webpack_require__(167); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4_echarts_lib_echarts__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4_echarts_lib_echarts___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_4_echarts_lib_echarts__); + + + + + + + +__WEBPACK_IMPORTED_MODULE_4_echarts_lib_echarts___default.a.registerAction({ + type: 'grid3DChangeCamera', + event: 'grid3dcamerachanged', + update: 'series:updateCamera' +}, function (payload, ecModel) { + ecModel.eachComponent({ + mainType: 'grid3D', query: payload + }, function (componentModel) { + componentModel.setView(payload); + }); +}); + +__WEBPACK_IMPORTED_MODULE_4_echarts_lib_echarts___default.a.registerAction({ + type: 'grid3DShowAxisPointer', + event: 'grid3dshowaxispointer', + update: 'grid3D:showAxisPointer' +}, function (payload, ecModel) { +}); + +__WEBPACK_IMPORTED_MODULE_4_echarts_lib_echarts___default.a.registerAction({ + type: 'grid3DHideAxisPointer', + event: 'grid3dhideaxispointer', + update: 'grid3D:hideAxisPointer' +}, function (payload, ecModel) { +}); + +/***/ }), +/* 155 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__createAxis3DModel__ = __webpack_require__(156); + + + +var Axis3DModel = __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.extendComponentModel({ + + type: 'cartesian3DAxis', + + axis: null, + + /** + * @override + */ + getCoordSysModel: function () { + return this.ecModel.queryComponents({ + mainType: 'grid3D', + index: this.option.gridIndex, + id: this.option.gridId + })[0]; + } +}); + +__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.helper.mixinAxisModelCommonMethods(Axis3DModel); + +function getAxisType(axisDim, option) { + // Default axis with data is category axis + return option.type || (option.data ? 'category' : 'value'); +} + +Object(__WEBPACK_IMPORTED_MODULE_1__createAxis3DModel__["a" /* default */])('x', Axis3DModel, getAxisType, { + name: 'X' +}); +Object(__WEBPACK_IMPORTED_MODULE_1__createAxis3DModel__["a" /* default */])('y', Axis3DModel, getAxisType, { + name: 'Y' +}); +Object(__WEBPACK_IMPORTED_MODULE_1__createAxis3DModel__["a" /* default */])('z', Axis3DModel, getAxisType, { + name: 'Z' +}); + +/***/ }), +/* 156 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__axis3DDefault__ = __webpack_require__(157); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2_echarts_lib_data_OrdinalMeta__ = __webpack_require__(158); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2_echarts_lib_data_OrdinalMeta___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_2_echarts_lib_data_OrdinalMeta__); + + + + + +var AXIS_TYPES = ['value', 'category', 'time', 'log']; +/** + * Generate sub axis model class + * @param {string} dim 'x' 'y' 'radius' 'angle' 'parallel' + * @param {module:echarts/model/Component} BaseAxisModelClass + * @param {Function} axisTypeDefaulter + * @param {Object} [extraDefaultOption] + */ +/* harmony default export */ __webpack_exports__["a"] = (function (dim, BaseAxisModelClass, axisTypeDefaulter, extraDefaultOption) { + + __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.util.each(AXIS_TYPES, function (axisType) { + + BaseAxisModelClass.extend({ + + type: dim + 'Axis3D.' + axisType, + + /** + * @type readOnly + */ + __ordinalMeta: null, + + mergeDefaultAndTheme: function (option, ecModel) { + + var themeModel = ecModel.getTheme(); + __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.util.merge(option, themeModel.get(axisType + 'Axis3D')); + __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.util.merge(option, this.getDefaultOption()); + + option.type = axisTypeDefaulter(dim, option); + }, + + /** + * @override + */ + optionUpdated: function () { + var thisOption = this.option; + + if (thisOption.type === 'category') { + this.__ordinalMeta = __WEBPACK_IMPORTED_MODULE_2_echarts_lib_data_OrdinalMeta___default.a.createByAxisModel(this); + } + }, + + getCategories: function () { + if (this.option.type === 'category') { + return this.__ordinalMeta.categories; + } + }, + + getOrdinalMeta: function () { + return this.__ordinalMeta; + }, + + defaultOption: __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.util.merge( + __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.util.clone(__WEBPACK_IMPORTED_MODULE_1__axis3DDefault__["a" /* default */][axisType + 'Axis3D']), + extraDefaultOption || {}, + true + ) + }); + }); + + // TODO + BaseAxisModelClass.superClass.registerSubTypeDefaulter( + dim + 'Axis3D', + __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.util.curry(axisTypeDefaulter, dim) + ); +});; + +/***/ }), +/* 157 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__); + + +var defaultOption = { + show: true, + + grid3DIndex: 0, + // 反向坐标轴 + inverse: false, + + // 坐标轴名字 + name: '', + // 坐标轴名字位置 + nameLocation: 'middle', + + nameTextStyle: { + fontSize: 16 + }, + // 文字与轴线距离 + nameGap: 20, + + axisPointer: {}, + + axisLine: {}, + // 坐标轴小标记 + axisTick: {}, + axisLabel: {}, + // 分隔区域 + splitArea: {} +}; + +var categoryAxis = __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.util.merge({ + // 类目起始和结束两端空白策略 + boundaryGap: true, + // splitArea: { + // show: false + // }, + // 坐标轴小标记 + axisTick: { + // If tick is align with label when boundaryGap is true + // Default with axisTick + alignWithLabel: false, + interval: 'auto' + }, + // 坐标轴文本标签,详见axis.axisLabel + axisLabel: { + interval: 'auto' + }, + axisPointer: { + label: { + show: false + } + } +}, defaultOption); + +var valueAxis = __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.util.merge({ + // 数值起始和结束两端空白策略 + boundaryGap: [0, 0], + // 最小值, 设置成 'dataMin' 则从数据中计算最小值 + // min: null, + // 最大值,设置成 'dataMax' 则从数据中计算最大值 + // max: null, + // 脱离0值比例,放大聚焦到最终_min,_max区间 + // scale: false, + // 分割段数,默认为5 + splitNumber: 5, + // Minimum interval + // minInterval: null + + axisPointer: { + label: { + } + } +}, defaultOption); + +// FIXME +var timeAxis = __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.util.defaults({ + scale: true, + min: 'dataMin', + max: 'dataMax' +}, valueAxis); +var logAxis = __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.util.defaults({ + logBase: 10 +}, valueAxis); +logAxis.scale = true; + +/* harmony default export */ __webpack_exports__["a"] = ({ + categoryAxis3D: categoryAxis, + valueAxis3D: valueAxis, + timeAxis3D: timeAxis, + logAxis3D: logAxis +}); + +/***/ }), +/* 158 */ +/***/ (function(module, exports, __webpack_require__) { + +var _util = __webpack_require__(13); + +var createHashMap = _util.createHashMap; +var isObject = _util.isObject; +var map = _util.map; + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/** + * @constructor + * @param {Object} [opt] + * @param {Object} [opt.categories=[]] + * @param {Object} [opt.needCollect=false] + * @param {Object} [opt.deduplication=false] + */ +function OrdinalMeta(opt) { + /** + * @readOnly + * @type {Array.} + */ + this.categories = opt.categories || []; + /** + * @private + * @type {boolean} + */ + + this._needCollect = opt.needCollect; + /** + * @private + * @type {boolean} + */ + + this._deduplication = opt.deduplication; + /** + * @private + * @type {boolean} + */ + + this._map; +} +/** + * @param {module:echarts/model/Model} axisModel + * @return {module:echarts/data/OrdinalMeta} + */ + + +OrdinalMeta.createByAxisModel = function (axisModel) { + var option = axisModel.option; + var data = option.data; + var categories = data && map(data, getName); + return new OrdinalMeta({ + categories: categories, + needCollect: !categories, + // deduplication is default in axis. + deduplication: option.dedplication !== false + }); +}; + +var proto = OrdinalMeta.prototype; +/** + * @param {string} category + * @return {number} ordinal + */ + +proto.getOrdinal = function (category) { + return getOrCreateMap(this).get(category); +}; +/** + * @param {*} category + * @return {number} The ordinal. If not found, return NaN. + */ + + +proto.parseAndCollect = function (category) { + var index; + var needCollect = this._needCollect; // The value of category dim can be the index of the given category set. + // This feature is only supported when !needCollect, because we should + // consider a common case: a value is 2017, which is a number but is + // expected to be tread as a category. This case usually happen in dataset, + // where it happent to be no need of the index feature. + + if (typeof category !== 'string' && !needCollect) { + return category; + } // Optimize for the scenario: + // category is ['2012-01-01', '2012-01-02', ...], where the input + // data has been ensured not duplicate and is large data. + // Notice, if a dataset dimension provide categroies, usually echarts + // should remove duplication except user tell echarts dont do that + // (set axis.deduplication = false), because echarts do not know whether + // the values in the category dimension has duplication (consider the + // parallel-aqi example) + + + if (needCollect && !this._deduplication) { + index = this.categories.length; + this.categories[index] = category; + return index; + } + + var map = getOrCreateMap(this); + index = map.get(category); + + if (index == null) { + if (needCollect) { + index = this.categories.length; + this.categories[index] = category; + map.set(category, index); + } else { + index = NaN; + } + } + + return index; +}; // Consider big data, do not create map until needed. + + +function getOrCreateMap(ordinalMeta) { + return ordinalMeta._map || (ordinalMeta._map = createHashMap(ordinalMeta.categories)); +} + +function getName(obj) { + if (isObject(obj) && obj.value != null) { + return obj.value; + } else { + return obj + ''; + } +} + +var _default = OrdinalMeta; +module.exports = _default; + +/***/ }), +/* 159 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__common_componentViewControlMixin__ = __webpack_require__(44); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__common_componentPostEffectMixin__ = __webpack_require__(28); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__common_componentLightMixin__ = __webpack_require__(29); + + + + + +var Grid3DModel = __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.extendComponentModel({ + + type: 'grid3D', + + dependencies: ['xAxis3D', 'yAxis3D', 'zAxis3D'], + + defaultOption: { + + show: true, + + zlevel: -10, + + // Layout used for viewport + left: 0, + top: 0, + width: '100%', + height: '100%', + + environment: 'auto', + + // Dimension of grid3D + boxWidth: 100, + boxHeight: 100, + boxDepth: 100, + + // Common axis options. + axisPointer: { + show: true, + lineStyle: { + color: 'rgba(0, 0, 0, 0.8)', + width: 1 + }, + + label: { + show: true, + // (dimValue: number, value: Array) => string + formatter: null, + + // TODO, Consider boxWidth + margin: 8, + // backgroundColor: '#ffbd67', + // borderColor: '#000', + // borderWidth: 0, + + textStyle: { + fontSize: 14, + color: '#fff', + backgroundColor: 'rgba(0,0,0,0.5)', + padding: 3, + borderRadius: 3 + } + } + }, + + axisLine: { + show: true, + lineStyle: { + color: '#333', + width: 2, + type: 'solid' + } + }, + + axisTick: { + show: true, + inside: false, + length: 3, + lineStyle: { + width: 1 + } + }, + axisLabel: { + show: true, + inside: false, + rotate: 0, + margin: 8, + textStyle: { + fontSize: 12 + } + }, + splitLine: { + show: true, + lineStyle: { + color: ['#ccc'], + width: 1, + type: 'solid' + } + }, + splitArea: { + show: false, + areaStyle: { + color: ['rgba(250,250,250,0.3)','rgba(200,200,200,0.3)'] + } + }, + + // Light options + light: { + main: { + // Alpha angle for top-down rotation + // Positive to rotate to top. + alpha: 30, + // beta angle for left-right rotation + // Positive to rotate to right. + beta: 40 + }, + ambient: { + intensity: 0.4 + } + }, + + viewControl: { + // Small damping for precise control. + // damping: 0.1, + + // Alpha angle for top-down rotation + // Positive to rotate to top. + alpha: 20, + // beta angle for left-right rotation + // Positive to rotate to right. + beta: 40, + + autoRotate: false, + + // Distance to the surface of grid3D. + distance: 200, + + // Min distance to the surface of grid3D + minDistance: 40, + // Max distance to the surface of grid3D + maxDistance: 400 + } + } +}); + +__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.util.merge(Grid3DModel.prototype, __WEBPACK_IMPORTED_MODULE_1__common_componentViewControlMixin__["a" /* default */]); +__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.util.merge(Grid3DModel.prototype, __WEBPACK_IMPORTED_MODULE_2__common_componentPostEffectMixin__["a" /* default */]); +__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.util.merge(Grid3DModel.prototype, __WEBPACK_IMPORTED_MODULE_3__common_componentLightMixin__["a" /* default */]); + +/* unused harmony default export */ var _unused_webpack_default_export = (Grid3DModel); + + + +/***/ }), +/* 160 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__ = __webpack_require__(1); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__util_OrbitControl__ = __webpack_require__(45); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__util_geometry_Lines3D__ = __webpack_require__(25); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4__util_retrieve__ = __webpack_require__(2); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_5__util_ZRTextureAtlasSurface__ = __webpack_require__(81); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_6__common_SceneHelper__ = __webpack_require__(30); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_7__Grid3DFace__ = __webpack_require__(162); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_8__Grid3DAxis__ = __webpack_require__(164); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_9__util_mesh_LabelsMesh__ = __webpack_require__(63); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_10__util_shader_lines3D_glsl_js__ = __webpack_require__(46); +// TODO orthographic camera + + + + + + +var firstNotNull = __WEBPACK_IMPORTED_MODULE_4__util_retrieve__["a" /* default */].firstNotNull; + + + + + + + +__WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].Shader.import(__WEBPACK_IMPORTED_MODULE_10__util_shader_lines3D_glsl_js__["a" /* default */]); + +['x', 'y', 'z'].forEach(function (dim) { + __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.extendComponentView({ + type: dim + 'Axis3D' + }); +}); + +var dimIndicesMap = { + // Left to right + x: 0, + // Far to near + y: 2, + // Bottom to up + z: 1 +}; + +/* unused harmony default export */ var _unused_webpack_default_export = (__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.extendComponentView({ + + type: 'grid3D', + + __ecgl__: true, + + init: function (ecModel, api) { + + var FACES = [ + // planeDim0, planeDim1, offsetDim, dir on dim3 axis(gl), plane. + ['y', 'z', 'x', -1, 'left'], + ['y', 'z', 'x', 1, 'right'], + ['x', 'y', 'z', -1, 'bottom'], + ['x', 'y','z', 1, 'top'], + ['x', 'z', 'y', -1, 'far'], + ['x', 'z','y', 1, 'near'] + ]; + + var DIMS = ['x', 'y', 'z']; + + var quadsMaterial = new __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].Material({ + // transparent: true, + shader: __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].createShader('ecgl.color'), + depthMask: false, + transparent: true + }); + var linesMaterial = new __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].Material({ + // transparent: true, + shader: __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].createShader('ecgl.meshLines3D'), + depthMask: false, + transparent: true + }); + quadsMaterial.define('fragment', 'DOUBLE_SIDED'); + quadsMaterial.define('both', 'VERTEX_COLOR'); + + this.groupGL = new __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].Node(); + + this._control = new __WEBPACK_IMPORTED_MODULE_2__util_OrbitControl__["a" /* default */]({ + zr: api.getZr() + }); + this._control.init(); + + // Save mesh and other infos for each face. + this._faces = FACES.map(function (faceInfo) { + var face = new __WEBPACK_IMPORTED_MODULE_7__Grid3DFace__["a" /* default */](faceInfo, linesMaterial, quadsMaterial); + this.groupGL.add(face.rootNode); + return face; + }, this); + + // Save mesh and other infos for each axis. + this._axes = DIMS.map(function (dim) { + var axis = new __WEBPACK_IMPORTED_MODULE_8__Grid3DAxis__["a" /* default */](dim, linesMaterial); + this.groupGL.add(axis.rootNode); + return axis; + }, this); + + var dpr = api.getDevicePixelRatio(); + // Texture surface for label. + this._axisLabelSurface = new __WEBPACK_IMPORTED_MODULE_5__util_ZRTextureAtlasSurface__["a" /* default */]({ + width: 256, height: 256, + devicePixelRatio: dpr + }); + this._axisLabelSurface.onupdate = function () { + api.getZr().refresh(); + }; + + this._axisPointerLineMesh = new __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].Mesh({ + geometry: new __WEBPACK_IMPORTED_MODULE_3__util_geometry_Lines3D__["a" /* default */]({ useNativeLine: false }), + material: linesMaterial, + castShadow: false, + // PENDING + ignorePicking: true, + renderOrder: 3 + }); + this.groupGL.add(this._axisPointerLineMesh); + + this._axisPointerLabelsSurface = new __WEBPACK_IMPORTED_MODULE_5__util_ZRTextureAtlasSurface__["a" /* default */]({ + width: 128, height: 128, + devicePixelRatio: dpr + }); + this._axisPointerLabelsMesh = new __WEBPACK_IMPORTED_MODULE_9__util_mesh_LabelsMesh__["a" /* default */]({ + ignorePicking: true, renderOrder: 4, + castShadow: false + }); + this._axisPointerLabelsMesh.material.set('textureAtlas', this._axisPointerLabelsSurface.getTexture()); + this.groupGL.add(this._axisPointerLabelsMesh); + + this._lightRoot = new __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].Node(); + this._sceneHelper = new __WEBPACK_IMPORTED_MODULE_6__common_SceneHelper__["a" /* default */](); + this._sceneHelper.initLight(this._lightRoot); + }, + + render: function (grid3DModel, ecModel, api) { + + this._model = grid3DModel; + this._api = api; + + var cartesian = grid3DModel.coordinateSystem; + + // Always have light. + cartesian.viewGL.add(this._lightRoot); + + if (grid3DModel.get('show')) { + cartesian.viewGL.add(this.groupGL); + } + else { + cartesian.viewGL.remove(this.groupGL); + } + + // cartesian.viewGL.setCameraType(grid3DModel.get('viewControl.projection')); + + var control = this._control; + control.setViewGL(cartesian.viewGL); + + var viewControlModel = grid3DModel.getModel('viewControl'); + control.setFromViewControlModel(viewControlModel, 0); + + this._axisLabelSurface.clear(); + + control.off('update'); + if (grid3DModel.get('show')) { + this._faces.forEach(function (face) { + face.update(grid3DModel, ecModel, api); + }, this); + this._axes.forEach(function (axis) { + axis.update(grid3DModel, this._axisLabelSurface, api); + }, this); + } + + control.on('update', this._onCameraChange.bind(this, grid3DModel, api), this); + + this._sceneHelper.setScene(cartesian.viewGL.scene); + this._sceneHelper.updateLight(grid3DModel); + + // Set post effect + cartesian.viewGL.setPostEffect(grid3DModel.getModel('postEffect'), api); + cartesian.viewGL.setTemporalSuperSampling(grid3DModel.getModel('temporalSuperSampling')); + + this._initMouseHandler(grid3DModel); + }, + + afterRender: function (grid3DModel, ecModel, api, layerGL) { + // Create ambient cubemap after render because we need to know the renderer. + // TODO + var renderer = layerGL.renderer; + + this._sceneHelper.updateAmbientCubemap(renderer, grid3DModel, api); + + this._sceneHelper.updateSkybox(renderer, grid3DModel, api); + }, + + /** + * showAxisPointer will be triggered by action. + */ + showAxisPointer: function (grid3dModel, ecModel, api, payload) { + this._doShowAxisPointer(); + this._updateAxisPointer(payload.value); + }, + + /** + * hideAxisPointer will be triggered by action. + */ + hideAxisPointer: function (grid3dModel, ecModel, api, payload) { + this._doHideAxisPointer(); + }, + + _initMouseHandler: function (grid3DModel) { + var cartesian = grid3DModel.coordinateSystem; + var viewGL = cartesian.viewGL; + + // TODO xAxis3D.axisPointer.show ? + if (grid3DModel.get('show') && grid3DModel.get('axisPointer.show')) { + viewGL.on('mousemove', this._updateAxisPointerOnMousePosition, this); + } + else { + viewGL.off('mousemove', this._updateAxisPointerOnMousePosition); + } + }, + + /** + * Try find and show axisPointer on the intersect point + * of mouse ray with grid plane. + */ + _updateAxisPointerOnMousePosition: function (e) { + // Ignore if mouse is on the element. + if (e.target) { + return; + } + var grid3DModel = this._model; + var cartesian = grid3DModel.coordinateSystem; + var viewGL = cartesian.viewGL; + + var ray = viewGL.castRay(e.offsetX, e.offsetY, new __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].Ray()); + + var nearestIntersectPoint; + for (var i = 0; i < this._faces.length; i++) { + var face = this._faces[i]; + if (face.rootNode.invisible) { + continue; + } + + // Plane is not face the camera. flip it + if (face.plane.normal.dot(viewGL.camera.worldTransform.z) < 0) { + face.plane.normal.negate(); + } + + var point = ray.intersectPlane(face.plane); + if (!point) { + continue; + } + var axis0 = cartesian.getAxis(face.faceInfo[0]); + var axis1 = cartesian.getAxis(face.faceInfo[1]); + var idx0 = dimIndicesMap[face.faceInfo[0]]; + var idx1 = dimIndicesMap[face.faceInfo[1]]; + if (axis0.contain(point.array[idx0]) && axis1.contain(point.array[idx1])) { + nearestIntersectPoint = point; + } + } + + if (nearestIntersectPoint) { + var data = cartesian.pointToData(nearestIntersectPoint.array, [], true); + this._updateAxisPointer(data); + + this._doShowAxisPointer(); + } + else { + this._doHideAxisPointer(); + } + }, + + _onCameraChange: function (grid3DModel, api) { + + if (grid3DModel.get('show')) { + this._updateFaceVisibility(); + this._updateAxisLinePosition(); + } + + var control = this._control; + + api.dispatchAction({ + type: 'grid3DChangeCamera', + alpha: control.getAlpha(), + beta: control.getBeta(), + distance: control.getDistance(), + center: control.getCenter(), + from: this.uid, + grid3DId: grid3DModel.id + }); + }, + + /** + * Update visibility of each face when camera view changed, front face will be invisible. + * @private + */ + _updateFaceVisibility: function () { + var camera = this._control.getCamera(); + var viewSpacePos = new __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].Vector3(); + camera.update(); + for (var idx = 0; idx < this._faces.length / 2; idx++) { + var depths = []; + for (var k = 0; k < 2; k++) { + var face = this._faces[idx * 2 + k]; + face.rootNode.getWorldPosition(viewSpacePos); + viewSpacePos.transformMat4(camera.viewMatrix); + depths[k] = viewSpacePos.z; + } + // Set the front face invisible + var frontIndex = depths[0] > depths[1] ? 0 : 1; + var frontFace = this._faces[idx * 2 + frontIndex]; + var backFace = this._faces[idx * 2 + 1 - frontIndex]; + // Update rotation. + frontFace.rootNode.invisible = true; + backFace.rootNode.invisible = false; + } + }, + + /** + * Update axis line position when camera view changed. + * @private + */ + _updateAxisLinePosition: function () { + // Put xAxis, yAxis on x, y visible plane. + // Put zAxis on the left. + // TODO + var cartesian = this._model.coordinateSystem; + var xAxis = cartesian.getAxis('x'); + var yAxis = cartesian.getAxis('y'); + var zAxis = cartesian.getAxis('z'); + var top = zAxis.getExtentMax(); + var bottom = zAxis.getExtentMin(); + var left = xAxis.getExtentMin(); + var right = xAxis.getExtentMax(); + var near = yAxis.getExtentMax(); + var far = yAxis.getExtentMin(); + + var xAxisNode = this._axes[0].rootNode; + var yAxisNode = this._axes[1].rootNode; + var zAxisNode = this._axes[2].rootNode; + + var faces = this._faces; + // Notice: in cartesian up axis is z, but in webgl up axis is y. + var xAxisZOffset = (faces[4].rootNode.invisible ? far : near); + var xAxisYOffset = (faces[2].rootNode.invisible ? top : bottom); + var yAxisXOffset = (faces[0].rootNode.invisible ? left : right); + var yAxisYOffset = (faces[2].rootNode.invisible ? top : bottom); + var zAxisXOffset = (faces[0].rootNode.invisible ? right : left); + var zAxisZOffset = (faces[4].rootNode.invisible ? far : near); + + xAxisNode.rotation.identity(); + yAxisNode.rotation.identity(); + zAxisNode.rotation.identity(); + if (faces[4].rootNode.invisible) { + this._axes[0].flipped = true; + xAxisNode.rotation.rotateX(Math.PI); + } + if (faces[0].rootNode.invisible) { + this._axes[1].flipped = true; + yAxisNode.rotation.rotateZ(Math.PI); + } + if (faces[4].rootNode.invisible) { + this._axes[2].flipped = true; + zAxisNode.rotation.rotateY(Math.PI); + } + + xAxisNode.position.set(0, xAxisYOffset, xAxisZOffset); + yAxisNode.position.set(yAxisXOffset, yAxisYOffset, 0); // Actually z + zAxisNode.position.set(zAxisXOffset, 0, zAxisZOffset); // Actually y + + xAxisNode.update(); + yAxisNode.update(); + zAxisNode.update(); + + this._updateAxisLabelAlign(); + }, + + /** + * Update label align on axis when axisLine position changed. + * @private + */ + _updateAxisLabelAlign: function () { + // var cartesian = this._model.coordinateSystem; + var camera = this._control.getCamera(); + var coords = [new __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].Vector4(), new __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].Vector4()]; + var center = new __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].Vector4(); + this.groupGL.getWorldPosition(center); + center.w = 1.0; + center.transformMat4(camera.viewMatrix) + .transformMat4(camera.projectionMatrix); + center.x /= center.w; + center.y /= center.w; + this._axes.forEach(function (axisInfo) { + var lineCoords = axisInfo.axisLineCoords; + var labelGeo = axisInfo.labelsMesh.geometry; + for (var i = 0; i < coords.length; i++) { + coords[i].setArray(lineCoords[i]); + coords[i].w = 1.0; + coords[i].transformMat4(axisInfo.rootNode.worldTransform) + .transformMat4(camera.viewMatrix) + .transformMat4(camera.projectionMatrix); + coords[i].x /= coords[i].w; + coords[i].y /= coords[i].w; + } + var dx = coords[1].x - coords[0].x; + var dy = coords[1].y - coords[0].y; + var cx = (coords[1].x + coords[0].x) / 2; + var cy = (coords[1].y + coords[0].y) / 2; + var textAlign; + var verticalAlign; + if (Math.abs(dy / dx) < 0.5) { + textAlign = 'center'; + verticalAlign = cy > center.y ? 'bottom' : 'top'; + } + else { + verticalAlign = 'middle'; + textAlign = cx > center.x ? 'left' : 'right'; + } + + // axis labels + axisInfo.setSpriteAlign(textAlign, verticalAlign, this._api); + }, this); + }, + + _doShowAxisPointer: function () { + if (!this._axisPointerLineMesh.invisible) { + return; + } + + this._axisPointerLineMesh.invisible = false; + this._axisPointerLabelsMesh.invisible = false; + this._api.getZr().refresh(); + }, + + _doHideAxisPointer: function () { + if (this._axisPointerLineMesh.invisible) { + return; + } + + this._axisPointerLineMesh.invisible = true; + this._axisPointerLabelsMesh.invisible = true; + this._api.getZr().refresh(); + }, + /** + * @private updateAxisPointer. + */ + _updateAxisPointer: function (data) { + var cartesian = this._model.coordinateSystem; + var point = cartesian.dataToPoint(data); + + var axisPointerLineMesh = this._axisPointerLineMesh; + var linesGeo = axisPointerLineMesh.geometry; + + var axisPointerParentModel = this._model.getModel('axisPointer'); + + var dpr = this._api.getDevicePixelRatio(); + linesGeo.convertToDynamicArray(true); + + + function ifShowAxisPointer(axis) { + return __WEBPACK_IMPORTED_MODULE_4__util_retrieve__["a" /* default */].firstNotNull( + axis.model.get('axisPointer.show'), + axisPointerParentModel.get('show') + ); + } + function getAxisColorAndLineWidth(axis) { + var axisPointerModel = axis.model.getModel('axisPointer', axisPointerParentModel); + var lineStyleModel = axisPointerModel.getModel('lineStyle'); + + var color = __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].parseColor(lineStyleModel.get('color')); + var lineWidth = firstNotNull(lineStyleModel.get('width'), 1); + var opacity = firstNotNull(lineStyleModel.get('opacity'), 1); + color[3] *= opacity; + + return { + color: color, + lineWidth: lineWidth + }; + } + for (var k = 0; k < this._faces.length; k++) { + var face = this._faces[k]; + if (face.rootNode.invisible) { + continue; + } + + var faceInfo = face.faceInfo; + var otherCoord = faceInfo[3] < 0 + ? cartesian.getAxis(faceInfo[2]).getExtentMin() + : cartesian.getAxis(faceInfo[2]).getExtentMax(); + var otherDimIdx = dimIndicesMap[faceInfo[2]]; + + // Line on face. + for (var i = 0; i < 2; i++) { + var dim = faceInfo[i]; + var faceOtherDim = faceInfo[1 - i]; + var axis = cartesian.getAxis(dim); + var faceOtherAxis = cartesian.getAxis(faceOtherDim); + + if (!ifShowAxisPointer(axis)) { + continue; + } + + var p0 = [0, 0, 0]; var p1 = [0, 0, 0]; + var dimIdx = dimIndicesMap[dim]; + var faceOtherDimIdx = dimIndicesMap[faceOtherDim]; + p0[dimIdx] = p1[dimIdx] = point[dimIdx]; + + p0[otherDimIdx] = p1[otherDimIdx] = otherCoord; + p0[faceOtherDimIdx] = faceOtherAxis.getExtentMin(); + p1[faceOtherDimIdx] = faceOtherAxis.getExtentMax(); + + var colorAndLineWidth = getAxisColorAndLineWidth(axis); + linesGeo.addLine(p0, p1, colorAndLineWidth.color, colorAndLineWidth.lineWidth * dpr); + } + + // Project line. + if (ifShowAxisPointer(cartesian.getAxis(faceInfo[2]))) { + var p0 = point.slice(); + var p1 = point.slice(); + p1[otherDimIdx] = otherCoord; + var colorAndLineWidth = getAxisColorAndLineWidth(cartesian.getAxis(faceInfo[2])); + linesGeo.addLine(p0, p1, colorAndLineWidth.color, colorAndLineWidth.lineWidth * dpr); + } + } + linesGeo.convertToTypedArray(); + + this._updateAxisPointerLabelsMesh(data); + + this._api.getZr().refresh(); + }, + + _updateAxisPointerLabelsMesh: function (data) { + var grid3dModel = this._model; + var axisPointerLabelsMesh = this._axisPointerLabelsMesh; + var axisPointerLabelsSurface = this._axisPointerLabelsSurface; + var cartesian = grid3dModel.coordinateSystem; + + var axisPointerParentModel = grid3dModel.getModel('axisPointer'); + + axisPointerLabelsMesh.geometry.convertToDynamicArray(true); + axisPointerLabelsSurface.clear(); + + var otherDim = { + x: 'y', y: 'x', z: 'y' + }; + this._axes.forEach(function (axisInfo, idx) { + var axis = cartesian.getAxis(axisInfo.dim); + var axisModel = axis.model; + var axisPointerModel = axisModel.getModel('axisPointer', axisPointerParentModel); + var labelModel = axisPointerModel.getModel('label'); + var lineColor = axisPointerModel.get('lineStyle.color'); + if (!labelModel.get('show') || !axisPointerModel.get('show')) { + return; + } + var val = data[idx]; + var formatter = labelModel.get('formatter'); + var text = axis.scale.getLabel(val); + if (formatter != null) { + text = formatter(text, data); + } + else { + if (axis.scale.type === 'interval' || axis.scale.type === 'log') { + var precision = __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.number.getPrecisionSafe(axis.scale.getTicks()[0]); + text = val.toFixed(precision + 2); + } + } + + var textStyleModel = labelModel.getModel('textStyle'); + var labelColor = textStyleModel.get('color'); + var textEl = new __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.graphic.Text(); + __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.graphic.setTextStyle(textEl.style, textStyleModel, { + text: text, + textFill: labelColor || lineColor, + textAlign: 'left', + textVerticalAlign: 'top' + }); + var coords = axisPointerLabelsSurface.add(textEl); + var rect = textEl.getBoundingRect(); + var dpr = this._api.getDevicePixelRatio(); + var pos = axisInfo.rootNode.position.toArray(); + var otherIdx = dimIndicesMap[otherDim[axisInfo.dim]]; + pos[otherIdx] += (axisInfo.flipped ? -1 : 1) * labelModel.get('margin'); + pos[dimIndicesMap[axisInfo.dim]] = axis.dataToCoord(data[idx]); + + axisPointerLabelsMesh.geometry.addSprite( + pos, [rect.width * dpr, rect.height * dpr], coords, + axisInfo.textAlign, axisInfo.textVerticalAlign + ); + }, this); + axisPointerLabelsSurface.getZr().refreshImmediately(); + axisPointerLabelsMesh.material.set('uvScale', axisPointerLabelsSurface.getCoordsScale()); + axisPointerLabelsMesh.geometry.convertToTypedArray(); + }, + + dispose: function () { + this.groupGL.removeAll(); + this._control.dispose(); + } +})); + +/***/ }), +/* 161 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__vec2__ = __webpack_require__(70); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__vec3__ = __webpack_require__(12); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__vec4__ = __webpack_require__(33); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__mat2__ = __webpack_require__(78); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4__mat2d__ = __webpack_require__(79); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_5__mat3__ = __webpack_require__(34); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_6__mat4__ = __webpack_require__(21); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_7__quat__ = __webpack_require__(55); +/** + * @fileoverview gl-matrix - High performance matrix and vector operations + * @author Brandon Jones + * @author Colin MacKenzie IV + * @version 2.2.2 + */ + +/* Copyright (c) 2013, Brandon Jones, Colin MacKenzie IV. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + + + + + + + + + + +/* harmony default export */ __webpack_exports__["a"] = ({ + vec2: __WEBPACK_IMPORTED_MODULE_0__vec2__["a" /* default */], + vec3: __WEBPACK_IMPORTED_MODULE_1__vec3__["a" /* default */], + vec4: __WEBPACK_IMPORTED_MODULE_2__vec4__["a" /* default */], + mat2: __WEBPACK_IMPORTED_MODULE_3__mat2__["a" /* default */], + mat2d: __WEBPACK_IMPORTED_MODULE_4__mat2d__["a" /* default */], + mat3: __WEBPACK_IMPORTED_MODULE_5__mat3__["a" /* default */], + mat4: __WEBPACK_IMPORTED_MODULE_6__mat4__["a" /* default */], + quat: __WEBPACK_IMPORTED_MODULE_7__quat__["a" /* default */] +}); + + +/***/ }), +/* 162 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__ = __webpack_require__(1); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__util_retrieve__ = __webpack_require__(2); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__util_geometry_Lines3D__ = __webpack_require__(25); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4__util_geometry_Quads__ = __webpack_require__(163); + + + + + +var firstNotNull = __WEBPACK_IMPORTED_MODULE_2__util_retrieve__["a" /* default */].firstNotNull; + +var dimIndicesMap = { + // Left to right + x: 0, + // Far to near + y: 2, + // Bottom to up + z: 1 +}; + +function updateFacePlane(node, plane, otherAxis, dir) { + var coord = [0, 0, 0]; + var distance = dir < 0 ? otherAxis.getExtentMin() : otherAxis.getExtentMax(); + coord[dimIndicesMap[otherAxis.dim]] = distance; + node.position.setArray(coord); + node.rotation.identity(); + + // Negative distance because on the opposite of normal direction. + plane.distance = -Math.abs(distance); + plane.normal.set(0, 0, 0); + if (otherAxis.dim === 'x') { + node.rotation.rotateY(dir * Math.PI / 2); + plane.normal.x = -dir; + } + else if (otherAxis.dim === 'z') { + node.rotation.rotateX(-dir * Math.PI / 2); + plane.normal.y = -dir; + } + else { + if (dir > 0) { + node.rotation.rotateY(Math.PI); + } + plane.normal.z = -dir; + } +} + + +function Grid3DFace(faceInfo, linesMaterial, quadsMaterial) { + this.rootNode = new __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].Node(); + + var linesMesh = new __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].Mesh({ + geometry: new __WEBPACK_IMPORTED_MODULE_3__util_geometry_Lines3D__["a" /* default */]({ useNativeLine: false }), + material: linesMaterial, + castShadow: false, + ignorePicking: true, + $ignorePicking: true, + renderOrder: 1 + }); + var quadsMesh = new __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].Mesh({ + geometry: new __WEBPACK_IMPORTED_MODULE_4__util_geometry_Quads__["a" /* default */](), + material: quadsMaterial, + castShadow: false, + culling: false, + ignorePicking: true, + $ignorePicking: true, + renderOrder: 0 + }); + // Quads are behind lines. + this.rootNode.add(quadsMesh); + this.rootNode.add(linesMesh); + + this.faceInfo = faceInfo; + this.plane =new __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].Plane(); + this.linesMesh =linesMesh; + this.quadsMesh =quadsMesh; +} + +Grid3DFace.prototype.update = function (grid3DModel, ecModel, api) { + var cartesian = grid3DModel.coordinateSystem; + var axes = [ + cartesian.getAxis(this.faceInfo[0]), + cartesian.getAxis(this.faceInfo[1]) + ]; + var lineGeometry = this.linesMesh.geometry; + var quadsGeometry = this.quadsMesh.geometry; + + lineGeometry.convertToDynamicArray(true); + quadsGeometry.convertToDynamicArray(true); + this._updateSplitLines(lineGeometry, axes, grid3DModel, api); + this._udpateSplitAreas(quadsGeometry, axes, grid3DModel, api); + lineGeometry.convertToTypedArray(); + quadsGeometry.convertToTypedArray(); + + + var otherAxis = cartesian.getAxis(this.faceInfo[2]); + updateFacePlane(this.rootNode, this.plane, otherAxis, this.faceInfo[3]); +}; + +Grid3DFace.prototype._updateSplitLines = function (geometry, axes, grid3DModel, api) { + var dpr = api.getDevicePixelRatio(); + axes.forEach(function (axis, idx) { + var axisModel = axis.model; + var otherExtent = axes[1 - idx].getExtent(); + + if (axis.scale.isBlank()) { + return; + } + + var splitLineModel = axisModel.getModel('splitLine', grid3DModel.getModel('splitLine')); + // Render splitLines + if (splitLineModel.get('show')) { + var lineStyleModel = splitLineModel.getModel('lineStyle'); + var lineColors = lineStyleModel.get('color'); + var opacity = firstNotNull(lineStyleModel.get('opacity'), 1.0); + var lineWidth = firstNotNull(lineStyleModel.get('width'), 1.0); + + lineColors = __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.util.isArray(lineColors) ? lineColors : [lineColors]; + + var ticksCoords = axis.getTicksCoords({ + tickModel: splitLineModel + }); + + var count = 0; + for (var i = 0; i < ticksCoords.length; i++) { + var tickCoord = ticksCoords[i].coord; + var lineColor = __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].parseColor(lineColors[count % lineColors.length]); + lineColor[3] *= opacity; + + var p0 = [0, 0, 0]; var p1 = [0, 0, 0]; + // 0 - x, 1 - y + p0[idx] = p1[idx] = tickCoord; + p0[1 - idx] = otherExtent[0]; + p1[1 - idx] = otherExtent[1]; + + geometry.addLine(p0, p1, lineColor, lineWidth * dpr); + + count++; + } + } + }); +}; + +Grid3DFace.prototype._udpateSplitAreas = function (geometry, axes, grid3DModel, api) { + axes.forEach(function (axis, idx) { + var axisModel = axis.model; + var otherExtent = axes[1 - idx].getExtent(); + + if (axis.scale.isBlank()) { + return; + } + + var splitAreaModel = axisModel.getModel('splitArea', grid3DModel.getModel('splitArea')); + // Render splitAreas + if (splitAreaModel.get('show')) { + var areaStyleModel = splitAreaModel.getModel('areaStyle'); + var colors = areaStyleModel.get('color'); + var opacity = firstNotNull(areaStyleModel.get('opacity'), 1.0); + + colors = __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.util.isArray(colors) ? colors : [colors]; + + var ticksCoords = axis.getTicksCoords({ + tickModel: splitAreaModel, + clamp: true + }); + + var count = 0; + var prevP0 = [0, 0, 0]; + var prevP1 = [0, 0, 0]; + // 0 - x, 1 - y + for (var i = 0; i < ticksCoords.length; i++) { + var tickCoord = ticksCoords[i].coord; + + var p0 = [0, 0, 0]; var p1 = [0, 0, 0]; + // 0 - x, 1 - y + p0[idx] = p1[idx] = tickCoord; + p0[1 - idx] = otherExtent[0]; + p1[1 - idx] = otherExtent[1]; + + if (i === 0) { + prevP0 = p0; + prevP1 = p1; + continue; + } + + var color = __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].parseColor(colors[count % colors.length]); + color[3] *= opacity; + geometry.addQuad([prevP0, p0, p1, prevP1], color); + + prevP0 = p0; + prevP1 = p1; + + count++; + } + } + }); +}; + +/* harmony default export */ __webpack_exports__["a"] = (Grid3DFace); + +/***/ }), +/* 163 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_claygl_src_Geometry__ = __webpack_require__(15); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_echarts_lib_echarts__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_echarts_lib_echarts___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_echarts_lib_echarts__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__dynamicConvertMixin__ = __webpack_require__(38); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3_claygl_src_dep_glmatrix__ = __webpack_require__(6); +/** + * @module echarts-gl/util/geometry/QuadsGeometry + * @author Yi Shen(http://github.com/pissang) + */ + + + + + +var vec3 = __WEBPACK_IMPORTED_MODULE_3_claygl_src_dep_glmatrix__["a" /* default */].vec3; + +/** + * @constructor + * @alias module:echarts-gl/util/geometry/QuadsGeometry + * @extends clay.Geometry + */ + +var QuadsGeometry = __WEBPACK_IMPORTED_MODULE_0_claygl_src_Geometry__["a" /* default */].extend(function () { + return { + + segmentScale: 1, + + /** + * Need to use mesh to expand lines if lineWidth > MAX_LINE_WIDTH + */ + useNativeLine: true, + + attributes: { + position: new __WEBPACK_IMPORTED_MODULE_0_claygl_src_Geometry__["a" /* default */].Attribute('position', 'float', 3, 'POSITION'), + normal: new __WEBPACK_IMPORTED_MODULE_0_claygl_src_Geometry__["a" /* default */].Attribute('normal', 'float', 3, 'NORMAL'), + color: new __WEBPACK_IMPORTED_MODULE_0_claygl_src_Geometry__["a" /* default */].Attribute('color', 'float', 4, 'COLOR') + } + }; +}, +/** @lends module: echarts-gl/util/geometry/QuadsGeometry.prototype */ +{ + + /** + * Reset offset + */ + resetOffset: function () { + this._vertexOffset = 0; + this._faceOffset = 0; + }, + + /** + * @param {number} nQuad + */ + setQuadCount: function (nQuad) { + var attributes = this.attributes; + var vertexCount = this.getQuadVertexCount() * nQuad; + var triangleCount = this.getQuadTriangleCount() * nQuad; + if (this.vertexCount !== vertexCount) { + attributes.position.init(vertexCount); + attributes.normal.init(vertexCount); + attributes.color.init(vertexCount); + } + if (this.triangleCount !== triangleCount) { + this.indices = vertexCount > 0xffff ? new Uint32Array(triangleCount * 3) : new Uint16Array(triangleCount * 3); + } + }, + + getQuadVertexCount: function () { + return 4; + }, + + getQuadTriangleCount: function () { + return 2; + }, + + /** + * Add a quad, which in following order: + * 0-----1 + * 3-----2 + */ + addQuad: (function () { + var a = vec3.create(); + var b = vec3.create(); + var normal = vec3.create(); + var indices = [0, 3, 1, 3, 2, 1]; + return function (coords, color) { + var positionAttr = this.attributes.position; + var normalAttr = this.attributes.normal; + var colorAttr = this.attributes.color; + + vec3.sub(a, coords[1], coords[0]); + vec3.sub(b, coords[2], coords[1]); + vec3.cross(normal, a, b); + vec3.normalize(normal, normal); + + for (var i = 0; i < 4; i++) { + positionAttr.set(this._vertexOffset + i, coords[i]); + colorAttr.set(this._vertexOffset + i, color); + normalAttr.set(this._vertexOffset + i, normal); + } + var idx = this._faceOffset * 3; + for (var i = 0; i < 6; i++) { + this.indices[idx + i] = indices[i] + this._vertexOffset; + } + this._vertexOffset += 4; + this._faceOffset += 2; + }; + })() +}); + +__WEBPACK_IMPORTED_MODULE_1_echarts_lib_echarts___default.a.util.defaults(QuadsGeometry.prototype, __WEBPACK_IMPORTED_MODULE_2__dynamicConvertMixin__["a" /* default */]); + +/* harmony default export */ __webpack_exports__["a"] = (QuadsGeometry); + +/***/ }), +/* 164 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__ = __webpack_require__(1); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__util_geometry_Lines3D__ = __webpack_require__(25); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__util_retrieve__ = __webpack_require__(2); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4__util_mesh_LabelsMesh__ = __webpack_require__(63); + + + + + +var firstNotNull = __WEBPACK_IMPORTED_MODULE_3__util_retrieve__["a" /* default */].firstNotNull; + +var dimIndicesMap = { + // Left to right + x: 0, + // Far to near + y: 2, + // Bottom to up + z: 1 +}; + +function Grid3DAxis(dim, linesMaterial) { + var linesMesh = new __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].Mesh({ + geometry: new __WEBPACK_IMPORTED_MODULE_2__util_geometry_Lines3D__["a" /* default */]({ useNativeLine: false }), + material: linesMaterial, + castShadow: false, + ignorePicking: true, renderOrder: 2 + }); + var axisLabelsMesh = new __WEBPACK_IMPORTED_MODULE_4__util_mesh_LabelsMesh__["a" /* default */](); + axisLabelsMesh.material.depthMask = false; + + var rootNode = new __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].Node(); + rootNode.add(linesMesh); + rootNode.add(axisLabelsMesh); + + this.rootNode = rootNode; + this.dim = dim; + + this.linesMesh = linesMesh; + this.labelsMesh = axisLabelsMesh; + this.axisLineCoords = null; + this.labelElements = []; +} + +var otherDim = { + x: 'y', y: 'x', z: 'y' +}; +Grid3DAxis.prototype.update = function ( + grid3DModel, axisLabelSurface, api +) { + var cartesian = grid3DModel.coordinateSystem; + var axis = cartesian.getAxis(this.dim); + + var linesGeo = this.linesMesh.geometry; + var labelsGeo = this.labelsMesh.geometry; + linesGeo.convertToDynamicArray(true); + labelsGeo.convertToDynamicArray(true); + var axisModel = axis.model; + var extent = axis.getExtent(); + + var dpr = api.getDevicePixelRatio(); + var axisLineModel = axisModel.getModel('axisLine', grid3DModel.getModel('axisLine')); + var axisTickModel = axisModel.getModel('axisTick', grid3DModel.getModel('axisTick')); + var axisLabelModel = axisModel.getModel('axisLabel', grid3DModel.getModel('axisLabel')); + var axisLineColor = axisLineModel.get('lineStyle.color'); + // Render axisLine + if (axisLineModel.get('show')) { + var axisLineStyleModel = axisLineModel.getModel('lineStyle'); + var p0 = [0, 0, 0]; var p1 = [0, 0, 0]; + var idx = dimIndicesMap[axis.dim]; + p0[idx] = extent[0]; + p1[idx] = extent[1]; + + // Save some useful info. + this.axisLineCoords =[p0, p1]; + + var color = __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].parseColor(axisLineColor); + var lineWidth = firstNotNull(axisLineStyleModel.get('width'), 1.0); + var opacity = firstNotNull(axisLineStyleModel.get('opacity'), 1.0); + color[3] *= opacity; + linesGeo.addLine(p0, p1, color, lineWidth * dpr); + } + // Render axis ticksCoords + if (axisTickModel.get('show')) { + var lineStyleModel = axisTickModel.getModel('lineStyle'); + var lineColor = __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].parseColor( + firstNotNull(lineStyleModel.get('color'), axisLineColor) + ); + var lineWidth = firstNotNull(lineStyleModel.get('width'), 1.0); + lineColor[3] *= firstNotNull(lineStyleModel.get('opacity'), 1.0); + var ticksCoords = axis.getTicksCoords(); + var tickLength = axisTickModel.get('length'); + + for (var i = 0; i < ticksCoords.length; i++) { + var tickCoord = ticksCoords[i].coord; + + var p0 = [0, 0, 0]; var p1 = [0, 0, 0]; + var idx = dimIndicesMap[axis.dim]; + var otherIdx = dimIndicesMap[otherDim[axis.dim]]; + // 0 : x, 1 : y + p0[idx] = p1[idx] = tickCoord; + p1[otherIdx] = tickLength; + + linesGeo.addLine(p0, p1, lineColor, lineWidth * dpr); + } + } + + this.labelElements = []; + var dpr = api.getDevicePixelRatio(); + if (axisLabelModel.get('show')) { + var ticksCoords = axis.getTicksCoords(); + var categoryData = axisModel.get('data'); + + var labelMargin = axisLabelModel.get('margin'); + var labels = axis.getViewLabels(); + + for (var i = 0; i < labels.length; i++) { + var tickValue = labels[i].tickValue; + var formattedLabel = labels[i].formattedLabel; + var rawLabel = labels[i].rawLabel; + + var tickCoord = axis.dataToCoord(tickValue); + + var p = [0, 0, 0]; + var idx = dimIndicesMap[axis.dim]; + var otherIdx = dimIndicesMap[otherDim[axis.dim]]; + // 0 : x, 1 : y + p[idx] = p[idx] = tickCoord; + p[otherIdx] = labelMargin; + + var itemTextStyleModel = axisLabelModel; + if (categoryData && categoryData[tickValue] && categoryData[tickValue].textStyle) { + itemTextStyleModel = new __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.Model( + categoryData[tickValue].textStyle, axisLabelModel, axisModel.ecModel + ); + } + var textColor = firstNotNull(itemTextStyleModel.get('color'), axisLineColor); + + var textEl = new __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.graphic.Text(); + __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.graphic.setTextStyle(textEl.style, itemTextStyleModel, { + text: formattedLabel, + textFill: typeof textColor === 'function' + ? textColor( + // (1) In category axis with data zoom, tick is not the original + // index of axis.data. So tick should not be exposed to user + // in category axis. + // (2) Compatible with previous version, which always returns labelStr. + // But in interval scale labelStr is like '223,445', which maked + // user repalce ','. So we modify it to return original val but remain + // it as 'string' to avoid error in replacing. + axis.type === 'category' ? rawLabel : axis.type === 'value' ? tickValue + '' : tickValue, + i + ) + : textColor, + textVerticalAlign: 'top', + textAlign: 'left' + }); + var coords = axisLabelSurface.add(textEl); + var rect = textEl.getBoundingRect(); + labelsGeo.addSprite(p, [rect.width * dpr, rect.height * dpr], coords); + + this.labelElements.push(textEl); + } + } + + if (axisModel.get('name')) { + var nameTextStyleModel = axisModel.getModel('nameTextStyle'); + var p = [0, 0, 0]; + var idx = dimIndicesMap[axis.dim]; + var otherIdx = dimIndicesMap[otherDim[axis.dim]]; + var labelColor = firstNotNull(nameTextStyleModel.get('color'), axisLineColor); + var strokeColor = nameTextStyleModel.get('borderColor'); + var lineWidth = nameTextStyleModel.get('borderWidth'); + // TODO start and end + p[idx] = p[idx] = (extent[0] + extent[1]) / 2; + p[otherIdx] = axisModel.get('nameGap'); + + var textEl = new __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.graphic.Text(); + __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.graphic.setTextStyle(textEl.style, nameTextStyleModel, { + text: axisModel.get('name'), + textFill: labelColor, + textStroke: strokeColor, + lineWidth: lineWidth + }); + var coords = axisLabelSurface.add(textEl); + var rect = textEl.getBoundingRect(); + labelsGeo.addSprite(p, [rect.width * dpr, rect.height * dpr], coords); + + textEl.__idx = this.labelElements.length; + this.nameLabelElement = textEl; + } + + this.labelsMesh.material.set('textureAtlas', axisLabelSurface.getTexture()); + this.labelsMesh.material.set('uvScale', axisLabelSurface.getCoordsScale()); + + linesGeo.convertToTypedArray(); + labelsGeo.convertToTypedArray(); +}; + +Grid3DAxis.prototype.setSpriteAlign = function (textAlign, textVerticalAlign, api) { + var dpr = api.getDevicePixelRatio(); + var labelGeo = this.labelsMesh.geometry; + for (var i = 0; i < this.labelElements.length; i++) { + var labelEl = this.labelElements[i]; + var rect = labelEl.getBoundingRect(); + + labelGeo.setSpriteAlign(i, [rect.width * dpr, rect.height * dpr], textAlign, textVerticalAlign); + } + // name label + var nameLabelEl = this.nameLabelElement; + if (nameLabelEl) { + var rect = nameLabelEl.getBoundingRect(); + labelGeo.setSpriteAlign(nameLabelEl.__idx, [rect.width * dpr, rect.height * dpr], textAlign, textVerticalAlign); + labelGeo.dirty(); + } + + this.textAlign = textAlign; + this.textVerticalAlign = textVerticalAlign; +}; + +/* harmony default export */ __webpack_exports__["a"] = (Grid3DAxis); + +/***/ }), +/* 165 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_claygl_src_Geometry__ = __webpack_require__(15); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__dynamicConvertMixin__ = __webpack_require__(38); +/** + * Geometry collecting sprites + * + * @module echarts-gl/util/geometry/Sprites + * @author Yi Shen(https://github.com/pissang) + */ + + + + +var squareTriangles = [ + 0, 1, 2, 0, 2, 3 +]; + +var SpritesGeometry = __WEBPACK_IMPORTED_MODULE_1_claygl_src_Geometry__["a" /* default */].extend(function () { + return { + attributes: { + position: new __WEBPACK_IMPORTED_MODULE_1_claygl_src_Geometry__["a" /* default */].Attribute('position', 'float', 3, 'POSITION'), + texcoord: new __WEBPACK_IMPORTED_MODULE_1_claygl_src_Geometry__["a" /* default */].Attribute('texcoord', 'float', 2, 'TEXCOORD_0'), + offset: new __WEBPACK_IMPORTED_MODULE_1_claygl_src_Geometry__["a" /* default */].Attribute('offset', 'float', 2), + color: new __WEBPACK_IMPORTED_MODULE_1_claygl_src_Geometry__["a" /* default */].Attribute('color', 'float', 4, 'COLOR') + } + }; +}, { + resetOffset: function () { + this._vertexOffset = 0; + this._faceOffset = 0; + }, + setSpriteCount: function (spriteCount) { + this._spriteCount = spriteCount; + + var vertexCount = spriteCount * 4; + var triangleCount = spriteCount * 2; + + if (this.vertexCount !== vertexCount) { + this.attributes.position.init(vertexCount); + this.attributes.offset.init(vertexCount); + this.attributes.color.init(vertexCount); + } + if (this.triangleCount !== triangleCount) { + this.indices = vertexCount > 0xffff ? new Uint32Array(triangleCount * 3) : new Uint16Array(triangleCount * 3); + } + }, + + setSpriteAlign: function (spriteOffset, size, align, verticalAlign, margin) { + if (align == null) { + align = 'left'; + } + if (verticalAlign == null) { + verticalAlign = 'top'; + } + + var leftOffset, topOffset, rightOffset, bottomOffset; + margin = margin || 0; + switch (align) { + case 'left': + leftOffset = margin; + rightOffset = size[0] + margin; + break; + case 'center': + case 'middle': + leftOffset = -size[0] / 2; + rightOffset = size[0] / 2; + break; + case 'right': + leftOffset = -size[0] - margin; + rightOffset = -margin; + break; + } + switch (verticalAlign) { + case 'bottom': + topOffset = margin; + bottomOffset = size[1] + margin; + break; + case 'middle': + topOffset = -size[1] / 2; + bottomOffset = size[1] / 2; + break; + case 'top': + topOffset = -size[1] - margin; + bottomOffset = -margin; + break; + } + // 3----2 + // 0----1 + var vertexOffset = spriteOffset * 4; + var offsetAttr = this.attributes.offset; + offsetAttr.set(vertexOffset, [leftOffset, bottomOffset]); + offsetAttr.set(vertexOffset + 1, [rightOffset, bottomOffset]); + offsetAttr.set(vertexOffset + 2, [rightOffset, topOffset]); + offsetAttr.set(vertexOffset + 3, [leftOffset, topOffset]); + }, + /** + * Add sprite + * @param {Array.} position + * @param {Array.} size [width, height] + * @param {Array.} coords [leftBottom, rightTop] + * @param {string} [align='left'] 'left' 'center' 'right' + * @param {string} [verticalAlign='top'] 'top' 'middle' 'bottom' + * @param {number} [screenMargin=0] + */ + addSprite: function (position, size, coords, align, verticalAlign, screenMargin) { + var vertexOffset = this._vertexOffset; + this.setSprite( + this._vertexOffset / 4, position, size, coords, align, verticalAlign, screenMargin + ) + for (var i = 0; i < squareTriangles.length; i++) { + this.indices[this._faceOffset * 3 + i] = squareTriangles[i] + vertexOffset; + } + this._faceOffset += 2; + this._vertexOffset += 4; + + return vertexOffset / 4; + }, + + setSprite: function (spriteOffset, position, size, coords, align, verticalAlign, screenMargin) { + var vertexOffset = spriteOffset * 4; + + var attributes = this.attributes; + for (var i = 0; i < 4; i++) { + attributes.position.set(vertexOffset + i, position); + } + // 3----2 + // 0----1 + var texcoordAttr = attributes.texcoord; + + texcoordAttr.set(vertexOffset, [coords[0][0], coords[0][1]]); + texcoordAttr.set(vertexOffset + 1, [coords[1][0], coords[0][1]]); + texcoordAttr.set(vertexOffset + 2, [coords[1][0], coords[1][1]]); + texcoordAttr.set(vertexOffset + 3, [coords[0][0], coords[1][1]]); + + this.setSpriteAlign(spriteOffset, size, align, verticalAlign, screenMargin); + } +}); + +__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.util.defaults(SpritesGeometry.prototype, __WEBPACK_IMPORTED_MODULE_2__dynamicConvertMixin__["a" /* default */]); + +/* harmony default export */ __webpack_exports__["a"] = (SpritesGeometry); + +/***/ }), +/* 166 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony default export */ __webpack_exports__["a"] = ("@export ecgl.labels.vertex\n\nattribute vec3 position: POSITION;\nattribute vec2 texcoord: TEXCOORD_0;\nattribute vec2 offset;\n#ifdef VERTEX_COLOR\nattribute vec4 a_Color : COLOR;\nvarying vec4 v_Color;\n#endif\n\nuniform mat4 worldViewProjection : WORLDVIEWPROJECTION;\nuniform vec4 viewport : VIEWPORT;\n\nvarying vec2 v_Texcoord;\n\nvoid main()\n{\n vec4 proj = worldViewProjection * vec4(position, 1.0);\n\n vec2 screen = (proj.xy / abs(proj.w) + 1.0) * 0.5 * viewport.zw;\n\n screen += offset;\n\n proj.xy = (screen / viewport.zw - 0.5) * 2.0 * abs(proj.w);\n gl_Position = proj;\n#ifdef VERTEX_COLOR\n v_Color = a_Color;\n#endif\n v_Texcoord = texcoord;\n}\n@end\n\n\n@export ecgl.labels.fragment\n\nuniform vec3 color : [1.0, 1.0, 1.0];\nuniform float alpha : 1.0;\nuniform sampler2D textureAtlas;\nuniform vec2 uvScale: [1.0, 1.0];\n\n#ifdef VERTEX_COLOR\nvarying vec4 v_Color;\n#endif\nvarying float v_Miter;\n\nvarying vec2 v_Texcoord;\n\nvoid main()\n{\n gl_FragColor = vec4(color, alpha) * texture2D(textureAtlas, v_Texcoord * uvScale);\n#ifdef VERTEX_COLOR\n gl_FragColor *= v_Color;\n#endif\n}\n\n@end"); + + +/***/ }), +/* 167 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__grid3D_Cartesian3D__ = __webpack_require__(168); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__grid3D_Axis3D__ = __webpack_require__(170); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2_echarts_lib_echarts__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2_echarts_lib_echarts___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_2_echarts_lib_echarts__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3_echarts_lib_util_layout__ = __webpack_require__(47); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3_echarts_lib_util_layout___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_3_echarts_lib_util_layout__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4__core_ViewGL__ = __webpack_require__(22); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_5__util_retrieve__ = __webpack_require__(2); + + + + + + + +function resizeCartesian3D(grid3DModel, api) { + // Use left/top/width/height + var boxLayoutOption = grid3DModel.getBoxLayoutParams(); + + var viewport = __WEBPACK_IMPORTED_MODULE_3_echarts_lib_util_layout___default.a.getLayoutRect(boxLayoutOption, { + width: api.getWidth(), + height: api.getHeight() + }); + + // Flip Y + viewport.y = api.getHeight() - viewport.y - viewport.height; + + this.viewGL.setViewport(viewport.x, viewport.y, viewport.width, viewport.height, api.getDevicePixelRatio()); + + var boxWidth = grid3DModel.get('boxWidth'); + var boxHeight = grid3DModel.get('boxHeight'); + var boxDepth = grid3DModel.get('boxDepth'); + + if (true) { + ['x', 'y', 'z'].forEach(function (dim) { + if (!this.getAxis(dim)) { + throw new Error('Grid' + grid3DModel.id + ' don\'t have ' + dim + 'Axis'); + } + }, this); + } + this.getAxis('x').setExtent(-boxWidth / 2, boxWidth / 2); + // From near to far + this.getAxis('y').setExtent(boxDepth / 2, -boxDepth / 2); + this.getAxis('z').setExtent(-boxHeight / 2, boxHeight / 2); + + this.size = [boxWidth, boxHeight, boxDepth]; +} + +function updateCartesian3D(ecModel, api) { + var dataExtents = {}; + function unionDataExtents(dim, extent) { + dataExtents[dim] = dataExtents[dim] || [Infinity, -Infinity]; + dataExtents[dim][0] = Math.min(extent[0], dataExtents[dim][0]); + dataExtents[dim][1] = Math.max(extent[1], dataExtents[dim][1]); + } + // Get data extents for scale. + ecModel.eachSeries(function (seriesModel) { + if (seriesModel.coordinateSystem !== this) { + return; + } + var data = seriesModel.getData(); + ['x', 'y', 'z'].forEach(function (coordDim) { + data.mapDimension(coordDim, true).forEach(function (dataDim) { + unionDataExtents( + coordDim, data.getDataExtent(dataDim, true) + ); + }); + }); + }, this); + + ['xAxis3D', 'yAxis3D', 'zAxis3D'].forEach(function (axisType) { + ecModel.eachComponent(axisType, function (axisModel) { + var dim = axisType.charAt(0); + var grid3DModel = axisModel.getReferringComponents('grid3D')[0]; + + var cartesian3D = grid3DModel.coordinateSystem; + if (cartesian3D !== this) { + return; + } + + var axis = cartesian3D.getAxis(dim); + if (axis) { + if (true) { + console.warn('Can\'t have two %s in one grid3D', axisType); + } + return; + } + var scale = __WEBPACK_IMPORTED_MODULE_2_echarts_lib_echarts___default.a.helper.createScale( + dataExtents[dim] || [Infinity, -Infinity], axisModel + ); + axis = new __WEBPACK_IMPORTED_MODULE_1__grid3D_Axis3D__["a" /* default */](dim, scale); + axis.type = axisModel.get('type'); + var isCategory = axis.type === 'category'; + axis.onBand = isCategory && axisModel.get('boundaryGap'); + axis.inverse = axisModel.get('inverse'); + + axisModel.axis = axis; + axis.model = axisModel; + + // override `echarts/coord/Axis#getLabelModel` + axis.getLabelModel = function () { + return axisModel.getModel('axisLabel', grid3DModel.getModel('axisLabel')); + }; + // override `echarts/coord/Axis#getTickModel` + axis.getTickModel = function () { + return axisModel.getModel('axisTick', grid3DModel.getModel('axisTick')); + }; + + cartesian3D.addAxis(axis); + }, this); + }, this); + + this.resize(this.model, api); +} + +var grid3DCreator = { + + dimensions: __WEBPACK_IMPORTED_MODULE_0__grid3D_Cartesian3D__["a" /* default */].prototype.dimensions, + + create: function (ecModel, api) { + + var cartesian3DList = []; + + ecModel.eachComponent('grid3D', function (grid3DModel) { + // FIXME + grid3DModel.__viewGL = grid3DModel.__viewGL || new __WEBPACK_IMPORTED_MODULE_4__core_ViewGL__["a" /* default */](); + + var cartesian3D = new __WEBPACK_IMPORTED_MODULE_0__grid3D_Cartesian3D__["a" /* default */](); + cartesian3D.model = grid3DModel; + cartesian3D.viewGL = grid3DModel.__viewGL; + + grid3DModel.coordinateSystem = cartesian3D; + cartesian3DList.push(cartesian3D); + + // Inject resize and update + cartesian3D.resize = resizeCartesian3D; + + cartesian3D.update = updateCartesian3D; + }); + + var axesTypes = ['xAxis3D', 'yAxis3D', 'zAxis3D']; + function findAxesModels(seriesModel, ecModel) { + return axesTypes.map(function (axisType) { + var axisModel = seriesModel.getReferringComponents(axisType)[0]; + if (axisModel == null) { + axisModel = ecModel.getComponent(axisType); + } + if (true) { + if (!axisModel) { + throw new Error(axisType + ' "' + __WEBPACK_IMPORTED_MODULE_5__util_retrieve__["a" /* default */].firstNotNull( + seriesModel.get(axisType + 'Index'), + seriesModel.get(axisType + 'Id'), + 0 + ) + '" not found'); + } + } + return axisModel; + }); + } + + ecModel.eachSeries(function (seriesModel) { + if (seriesModel.get('coordinateSystem') !== 'cartesian3D') { + return; + } + var firstGridModel = seriesModel.getReferringComponents('grid3D')[0]; + + if (firstGridModel == null) { + var axesModels = findAxesModels(seriesModel, ecModel); + var firstGridModel = axesModels[0].getCoordSysModel(); + axesModels.forEach(function (axisModel) { + var grid3DModel = axisModel.getCoordSysModel(); + if (true) { + if (!grid3DModel) { + throw new Error( + 'grid3D "' + __WEBPACK_IMPORTED_MODULE_5__util_retrieve__["a" /* default */].firstNotNull( + axisModel.get('gridIndex'), + axisModel.get('gridId'), + 0 + ) + '" not found' + ); + } + if (grid3DModel !== firstGridModel) { + throw new Error('xAxis3D, yAxis3D, zAxis3D must use the same grid'); + } + } + }); + } + + var coordSys = firstGridModel.coordinateSystem; + seriesModel.coordinateSystem = coordSys; + }); + + return cartesian3DList; + } +}; + +__WEBPACK_IMPORTED_MODULE_2_echarts_lib_echarts___default.a.registerCoordinateSystem('grid3D', grid3DCreator); + +/* unused harmony default export */ var _unused_webpack_default_export = (grid3DCreator); + +/***/ }), +/* 168 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_echarts_lib_coord_cartesian_Cartesian__ = __webpack_require__(169); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_echarts_lib_coord_cartesian_Cartesian___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_echarts_lib_coord_cartesian_Cartesian__); + + + +function Cartesian3D(name) { + + __WEBPACK_IMPORTED_MODULE_1_echarts_lib_coord_cartesian_Cartesian___default.a.call(this, name); + + this.size = [0, 0, 0]; +} + +Cartesian3D.prototype = { + + constructor: Cartesian3D, + + type: 'cartesian3D', + + dimensions: ['x', 'y', 'z'], + + model: null, + + containPoint: function (point) { + return this.getAxis('x').contain(point[0]) + && this.getAxis('y').contain(point[2]) + && this.getAxis('z').contain(point[1]); + }, + + containData: function (data) { + return this.getAxis('x').containData(data[0]) + && this.getAxis('y').containData(data[1]) + && this.getAxis('z').containData(data[2]); + }, + + dataToPoint: function (data, out, clamp) { + out = out || []; + out[0] = this.getAxis('x').dataToCoord(data[0], clamp); + out[2] = this.getAxis('y').dataToCoord(data[1], clamp); + out[1] = this.getAxis('z').dataToCoord(data[2], clamp); + return out; + }, + + pointToData: function (point, out, clamp) { + out = out || []; + out[0] = this.getAxis('x').coordToData(point[0], clamp); + out[1] = this.getAxis('y').coordToData(point[2], clamp); + out[2] = this.getAxis('z').coordToData(point[1], clamp); + return out; + } +}; + +__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.util.inherits(Cartesian3D, __WEBPACK_IMPORTED_MODULE_1_echarts_lib_coord_cartesian_Cartesian___default.a); + +/* harmony default export */ __webpack_exports__["a"] = (Cartesian3D); + +/***/ }), +/* 169 */ +/***/ (function(module, exports, __webpack_require__) { + +var zrUtil = __webpack_require__(13); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/** + * Cartesian coordinate system + * @module echarts/coord/Cartesian + * + */ +function dimAxisMapper(dim) { + return this._axes[dim]; +} +/** + * @alias module:echarts/coord/Cartesian + * @constructor + */ + + +var Cartesian = function (name) { + this._axes = {}; + this._dimList = []; + /** + * @type {string} + */ + + this.name = name || ''; +}; + +Cartesian.prototype = { + constructor: Cartesian, + type: 'cartesian', + + /** + * Get axis + * @param {number|string} dim + * @return {module:echarts/coord/Cartesian~Axis} + */ + getAxis: function (dim) { + return this._axes[dim]; + }, + + /** + * Get axes list + * @return {Array.} + */ + getAxes: function () { + return zrUtil.map(this._dimList, dimAxisMapper, this); + }, + + /** + * Get axes list by given scale type + */ + getAxesByScale: function (scaleType) { + scaleType = scaleType.toLowerCase(); + return zrUtil.filter(this.getAxes(), function (axis) { + return axis.scale.type === scaleType; + }); + }, + + /** + * Add axis + * @param {module:echarts/coord/Cartesian.Axis} + */ + addAxis: function (axis) { + var dim = axis.dim; + this._axes[dim] = axis; + + this._dimList.push(dim); + }, + + /** + * Convert data to coord in nd space + * @param {Array.|Object.} val + * @return {Array.|Object.} + */ + dataToCoord: function (val) { + return this._dataCoordConvert(val, 'dataToCoord'); + }, + + /** + * Convert coord in nd space to data + * @param {Array.|Object.} val + * @return {Array.|Object.} + */ + coordToData: function (val) { + return this._dataCoordConvert(val, 'coordToData'); + }, + _dataCoordConvert: function (input, method) { + var dimList = this._dimList; + var output = input instanceof Array ? [] : {}; + + for (var i = 0; i < dimList.length; i++) { + var dim = dimList[i]; + var axis = this._axes[dim]; + output[dim] = axis[method](input[dim]); + } + + return output; + } +}; +var _default = Cartesian; +module.exports = _default; + +/***/ }), +/* 170 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__); + + +function Axis3D(dim, scale, extent) { + + __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.Axis.call(this, dim, scale, extent); +} + +Axis3D.prototype = { + constructor: Axis3D, + + getExtentMin: function () { + var extent = this._extent; + return Math.min(extent[0], extent[1]); + }, + + getExtentMax: function () { + var extent = this._extent; + return Math.max(extent[0], extent[1]); + }, + + calculateCategoryInterval: function () { + // TODO consider label length + return Math.floor(this.scale.count() / 8); + } +}; + +__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.util.inherits(Axis3D, __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.Axis); + +/* harmony default export */ __webpack_exports__["a"] = (Axis3D); + +/***/ }), +/* 171 */ +/***/ (function(module, exports, __webpack_require__) { + +var zrUtil = __webpack_require__(13); + +var textContain = __webpack_require__(172); + +var numberUtil = __webpack_require__(85); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/** + * 每三位默认加,格式化 + * @param {string|number} x + * @return {string} + */ +function addCommas(x) { + if (isNaN(x)) { + return '-'; + } + + x = (x + '').split('.'); + return x[0].replace(/(\d{1,3})(?=(?:\d{3})+(?!\d))/g, '$1,') + (x.length > 1 ? '.' + x[1] : ''); +} +/** + * @param {string} str + * @param {boolean} [upperCaseFirst=false] + * @return {string} str + */ + + +function toCamelCase(str, upperCaseFirst) { + str = (str || '').toLowerCase().replace(/-(.)/g, function (match, group1) { + return group1.toUpperCase(); + }); + + if (upperCaseFirst && str) { + str = str.charAt(0).toUpperCase() + str.slice(1); + } + + return str; +} + +var normalizeCssArray = zrUtil.normalizeCssArray; +var replaceReg = /([&<>"'])/g; +var replaceMap = { + '&': '&', + '<': '<', + '>': '>', + '"': '"', + '\'': ''' +}; + +function encodeHTML(source) { + return source == null ? '' : (source + '').replace(replaceReg, function (str, c) { + return replaceMap[c]; + }); +} + +var TPL_VAR_ALIAS = ['a', 'b', 'c', 'd', 'e', 'f', 'g']; + +var wrapVar = function (varName, seriesIdx) { + return '{' + varName + (seriesIdx == null ? '' : seriesIdx) + '}'; +}; +/** + * Template formatter + * @param {string} tpl + * @param {Array.|Object} paramsList + * @param {boolean} [encode=false] + * @return {string} + */ + + +function formatTpl(tpl, paramsList, encode) { + if (!zrUtil.isArray(paramsList)) { + paramsList = [paramsList]; + } + + var seriesLen = paramsList.length; + + if (!seriesLen) { + return ''; + } + + var $vars = paramsList[0].$vars || []; + + for (var i = 0; i < $vars.length; i++) { + var alias = TPL_VAR_ALIAS[i]; + tpl = tpl.replace(wrapVar(alias), wrapVar(alias, 0)); + } + + for (var seriesIdx = 0; seriesIdx < seriesLen; seriesIdx++) { + for (var k = 0; k < $vars.length; k++) { + var val = paramsList[seriesIdx][$vars[k]]; + tpl = tpl.replace(wrapVar(TPL_VAR_ALIAS[k], seriesIdx), encode ? encodeHTML(val) : val); + } + } + + return tpl; +} +/** + * simple Template formatter + * + * @param {string} tpl + * @param {Object} param + * @param {boolean} [encode=false] + * @return {string} + */ + + +function formatTplSimple(tpl, param, encode) { + zrUtil.each(param, function (value, key) { + tpl = tpl.replace('{' + key + '}', encode ? encodeHTML(value) : value); + }); + return tpl; +} +/** + * @param {Object|string} [opt] If string, means color. + * @param {string} [opt.color] + * @param {string} [opt.extraCssText] + * @param {string} [opt.type='item'] 'item' or 'subItem' + * @return {string} + */ + + +function getTooltipMarker(opt, extraCssText) { + opt = zrUtil.isString(opt) ? { + color: opt, + extraCssText: extraCssText + } : opt || {}; + var color = opt.color; + var type = opt.type; + var extraCssText = opt.extraCssText; + + if (!color) { + return ''; + } + + return type === 'subItem' ? '' : ''; +} + +function pad(str, len) { + str += ''; + return '0000'.substr(0, len - str.length) + str; +} +/** + * ISO Date format + * @param {string} tpl + * @param {number} value + * @param {boolean} [isUTC=false] Default in local time. + * see `module:echarts/scale/Time` + * and `module:echarts/util/number#parseDate`. + * @inner + */ + + +function formatTime(tpl, value, isUTC) { + if (tpl === 'week' || tpl === 'month' || tpl === 'quarter' || tpl === 'half-year' || tpl === 'year') { + tpl = 'MM-dd\nyyyy'; + } + + var date = numberUtil.parseDate(value); + var utc = isUTC ? 'UTC' : ''; + var y = date['get' + utc + 'FullYear'](); + var M = date['get' + utc + 'Month']() + 1; + var d = date['get' + utc + 'Date'](); + var h = date['get' + utc + 'Hours'](); + var m = date['get' + utc + 'Minutes'](); + var s = date['get' + utc + 'Seconds'](); + var S = date['get' + utc + 'Milliseconds'](); + tpl = tpl.replace('MM', pad(M, 2)).replace('M', M).replace('yyyy', y).replace('yy', y % 100).replace('dd', pad(d, 2)).replace('d', d).replace('hh', pad(h, 2)).replace('h', h).replace('mm', pad(m, 2)).replace('m', m).replace('ss', pad(s, 2)).replace('s', s).replace('SSS', pad(S, 3)); + return tpl; +} +/** + * Capital first + * @param {string} str + * @return {string} + */ + + +function capitalFirst(str) { + return str ? str.charAt(0).toUpperCase() + str.substr(1) : str; +} + +var truncateText = textContain.truncateText; +var getTextRect = textContain.getBoundingRect; +exports.addCommas = addCommas; +exports.toCamelCase = toCamelCase; +exports.normalizeCssArray = normalizeCssArray; +exports.encodeHTML = encodeHTML; +exports.formatTpl = formatTpl; +exports.formatTplSimple = formatTplSimple; +exports.getTooltipMarker = getTooltipMarker; +exports.formatTime = formatTime; +exports.capitalFirst = capitalFirst; +exports.truncateText = truncateText; +exports.getTextRect = getTextRect; + +/***/ }), +/* 172 */ +/***/ (function(module, exports, __webpack_require__) { + +var BoundingRect = __webpack_require__(82); + +var imageHelper = __webpack_require__(173); + +var _util = __webpack_require__(13); + +var getContext = _util.getContext; +var extend = _util.extend; +var retrieve2 = _util.retrieve2; +var retrieve3 = _util.retrieve3; +var trim = _util.trim; +var textWidthCache = {}; +var textWidthCacheCounter = 0; +var TEXT_CACHE_MAX = 5000; +var STYLE_REG = /\{([a-zA-Z0-9_]+)\|([^}]*)\}/g; +var DEFAULT_FONT = '12px sans-serif'; // Avoid assign to an exported variable, for transforming to cjs. + +var methods = {}; + +function $override(name, fn) { + methods[name] = fn; +} +/** + * @public + * @param {string} text + * @param {string} font + * @return {number} width + */ + + +function getWidth(text, font) { + font = font || DEFAULT_FONT; + var key = text + ':' + font; + + if (textWidthCache[key]) { + return textWidthCache[key]; + } + + var textLines = (text + '').split('\n'); + var width = 0; + + for (var i = 0, l = textLines.length; i < l; i++) { + // textContain.measureText may be overrided in SVG or VML + width = Math.max(measureText(textLines[i], font).width, width); + } + + if (textWidthCacheCounter > TEXT_CACHE_MAX) { + textWidthCacheCounter = 0; + textWidthCache = {}; + } + + textWidthCacheCounter++; + textWidthCache[key] = width; + return width; +} +/** + * @public + * @param {string} text + * @param {string} font + * @param {string} [textAlign='left'] + * @param {string} [textVerticalAlign='top'] + * @param {Array.} [textPadding] + * @param {Object} [rich] + * @param {Object} [truncate] + * @return {Object} {x, y, width, height, lineHeight} + */ + + +function getBoundingRect(text, font, textAlign, textVerticalAlign, textPadding, rich, truncate) { + return rich ? getRichTextRect(text, font, textAlign, textVerticalAlign, textPadding, rich, truncate) : getPlainTextRect(text, font, textAlign, textVerticalAlign, textPadding, truncate); +} + +function getPlainTextRect(text, font, textAlign, textVerticalAlign, textPadding, truncate) { + var contentBlock = parsePlainText(text, font, textPadding, truncate); + var outerWidth = getWidth(text, font); + + if (textPadding) { + outerWidth += textPadding[1] + textPadding[3]; + } + + var outerHeight = contentBlock.outerHeight; + var x = adjustTextX(0, outerWidth, textAlign); + var y = adjustTextY(0, outerHeight, textVerticalAlign); + var rect = new BoundingRect(x, y, outerWidth, outerHeight); + rect.lineHeight = contentBlock.lineHeight; + return rect; +} + +function getRichTextRect(text, font, textAlign, textVerticalAlign, textPadding, rich, truncate) { + var contentBlock = parseRichText(text, { + rich: rich, + truncate: truncate, + font: font, + textAlign: textAlign, + textPadding: textPadding + }); + var outerWidth = contentBlock.outerWidth; + var outerHeight = contentBlock.outerHeight; + var x = adjustTextX(0, outerWidth, textAlign); + var y = adjustTextY(0, outerHeight, textVerticalAlign); + return new BoundingRect(x, y, outerWidth, outerHeight); +} +/** + * @public + * @param {number} x + * @param {number} width + * @param {string} [textAlign='left'] + * @return {number} Adjusted x. + */ + + +function adjustTextX(x, width, textAlign) { + // FIXME Right to left language + if (textAlign === 'right') { + x -= width; + } else if (textAlign === 'center') { + x -= width / 2; + } + + return x; +} +/** + * @public + * @param {number} y + * @param {number} height + * @param {string} [textVerticalAlign='top'] + * @return {number} Adjusted y. + */ + + +function adjustTextY(y, height, textVerticalAlign) { + if (textVerticalAlign === 'middle') { + y -= height / 2; + } else if (textVerticalAlign === 'bottom') { + y -= height; + } + + return y; +} +/** + * @public + * @param {stirng} textPosition + * @param {Object} rect {x, y, width, height} + * @param {number} distance + * @return {Object} {x, y, textAlign, textVerticalAlign} + */ + + +function adjustTextPositionOnRect(textPosition, rect, distance) { + var x = rect.x; + var y = rect.y; + var height = rect.height; + var width = rect.width; + var halfHeight = height / 2; + var textAlign = 'left'; + var textVerticalAlign = 'top'; + + switch (textPosition) { + case 'left': + x -= distance; + y += halfHeight; + textAlign = 'right'; + textVerticalAlign = 'middle'; + break; + + case 'right': + x += distance + width; + y += halfHeight; + textVerticalAlign = 'middle'; + break; + + case 'top': + x += width / 2; + y -= distance; + textAlign = 'center'; + textVerticalAlign = 'bottom'; + break; + + case 'bottom': + x += width / 2; + y += height + distance; + textAlign = 'center'; + break; + + case 'inside': + x += width / 2; + y += halfHeight; + textAlign = 'center'; + textVerticalAlign = 'middle'; + break; + + case 'insideLeft': + x += distance; + y += halfHeight; + textVerticalAlign = 'middle'; + break; + + case 'insideRight': + x += width - distance; + y += halfHeight; + textAlign = 'right'; + textVerticalAlign = 'middle'; + break; + + case 'insideTop': + x += width / 2; + y += distance; + textAlign = 'center'; + break; + + case 'insideBottom': + x += width / 2; + y += height - distance; + textAlign = 'center'; + textVerticalAlign = 'bottom'; + break; + + case 'insideTopLeft': + x += distance; + y += distance; + break; + + case 'insideTopRight': + x += width - distance; + y += distance; + textAlign = 'right'; + break; + + case 'insideBottomLeft': + x += distance; + y += height - distance; + textVerticalAlign = 'bottom'; + break; + + case 'insideBottomRight': + x += width - distance; + y += height - distance; + textAlign = 'right'; + textVerticalAlign = 'bottom'; + break; + } + + return { + x: x, + y: y, + textAlign: textAlign, + textVerticalAlign: textVerticalAlign + }; +} +/** + * Show ellipsis if overflow. + * + * @public + * @param {string} text + * @param {string} containerWidth + * @param {string} font + * @param {number} [ellipsis='...'] + * @param {Object} [options] + * @param {number} [options.maxIterations=3] + * @param {number} [options.minChar=0] If truncate result are less + * then minChar, ellipsis will not show, which is + * better for user hint in some cases. + * @param {number} [options.placeholder=''] When all truncated, use the placeholder. + * @return {string} + */ + + +function truncateText(text, containerWidth, font, ellipsis, options) { + if (!containerWidth) { + return ''; + } + + var textLines = (text + '').split('\n'); + options = prepareTruncateOptions(containerWidth, font, ellipsis, options); // FIXME + // It is not appropriate that every line has '...' when truncate multiple lines. + + for (var i = 0, len = textLines.length; i < len; i++) { + textLines[i] = truncateSingleLine(textLines[i], options); + } + + return textLines.join('\n'); +} + +function prepareTruncateOptions(containerWidth, font, ellipsis, options) { + options = extend({}, options); + options.font = font; + var ellipsis = retrieve2(ellipsis, '...'); + options.maxIterations = retrieve2(options.maxIterations, 2); + var minChar = options.minChar = retrieve2(options.minChar, 0); // FIXME + // Other languages? + + options.cnCharWidth = getWidth('国', font); // FIXME + // Consider proportional font? + + var ascCharWidth = options.ascCharWidth = getWidth('a', font); + options.placeholder = retrieve2(options.placeholder, ''); // Example 1: minChar: 3, text: 'asdfzxcv', truncate result: 'asdf', but not: 'a...'. + // Example 2: minChar: 3, text: '维度', truncate result: '维', but not: '...'. + + var contentWidth = containerWidth = Math.max(0, containerWidth - 1); // Reserve some gap. + + for (var i = 0; i < minChar && contentWidth >= ascCharWidth; i++) { + contentWidth -= ascCharWidth; + } + + var ellipsisWidth = getWidth(ellipsis); + + if (ellipsisWidth > contentWidth) { + ellipsis = ''; + ellipsisWidth = 0; + } + + contentWidth = containerWidth - ellipsisWidth; + options.ellipsis = ellipsis; + options.ellipsisWidth = ellipsisWidth; + options.contentWidth = contentWidth; + options.containerWidth = containerWidth; + return options; +} + +function truncateSingleLine(textLine, options) { + var containerWidth = options.containerWidth; + var font = options.font; + var contentWidth = options.contentWidth; + + if (!containerWidth) { + return ''; + } + + var lineWidth = getWidth(textLine, font); + + if (lineWidth <= containerWidth) { + return textLine; + } + + for (var j = 0;; j++) { + if (lineWidth <= contentWidth || j >= options.maxIterations) { + textLine += options.ellipsis; + break; + } + + var subLength = j === 0 ? estimateLength(textLine, contentWidth, options.ascCharWidth, options.cnCharWidth) : lineWidth > 0 ? Math.floor(textLine.length * contentWidth / lineWidth) : 0; + textLine = textLine.substr(0, subLength); + lineWidth = getWidth(textLine, font); + } + + if (textLine === '') { + textLine = options.placeholder; + } + + return textLine; +} + +function estimateLength(text, contentWidth, ascCharWidth, cnCharWidth) { + var width = 0; + var i = 0; + + for (var len = text.length; i < len && width < contentWidth; i++) { + var charCode = text.charCodeAt(i); + width += 0 <= charCode && charCode <= 127 ? ascCharWidth : cnCharWidth; + } + + return i; +} +/** + * @public + * @param {string} font + * @return {number} line height + */ + + +function getLineHeight(font) { + // FIXME A rough approach. + return getWidth('国', font); +} +/** + * @public + * @param {string} text + * @param {string} font + * @return {Object} width + */ + + +function measureText(text, font) { + return methods.measureText(text, font); +} // Avoid assign to an exported variable, for transforming to cjs. + + +methods.measureText = function (text, font) { + var ctx = getContext(); + ctx.font = font || DEFAULT_FONT; + return ctx.measureText(text); +}; +/** + * @public + * @param {string} text + * @param {string} font + * @param {Object} [truncate] + * @return {Object} block: {lineHeight, lines, height, outerHeight} + * Notice: for performance, do not calculate outerWidth util needed. + */ + + +function parsePlainText(text, font, padding, truncate) { + text != null && (text += ''); + var lineHeight = getLineHeight(font); + var lines = text ? text.split('\n') : []; + var height = lines.length * lineHeight; + var outerHeight = height; + + if (padding) { + outerHeight += padding[0] + padding[2]; + } + + if (text && truncate) { + var truncOuterHeight = truncate.outerHeight; + var truncOuterWidth = truncate.outerWidth; + + if (truncOuterHeight != null && outerHeight > truncOuterHeight) { + text = ''; + lines = []; + } else if (truncOuterWidth != null) { + var options = prepareTruncateOptions(truncOuterWidth - (padding ? padding[1] + padding[3] : 0), font, truncate.ellipsis, { + minChar: truncate.minChar, + placeholder: truncate.placeholder + }); // FIXME + // It is not appropriate that every line has '...' when truncate multiple lines. + + for (var i = 0, len = lines.length; i < len; i++) { + lines[i] = truncateSingleLine(lines[i], options); + } + } + } + + return { + lines: lines, + height: height, + outerHeight: outerHeight, + lineHeight: lineHeight + }; +} +/** + * For example: 'some text {a|some text}other text{b|some text}xxx{c|}xxx' + * Also consider 'bbbb{a|xxx\nzzz}xxxx\naaaa'. + * + * @public + * @param {string} text + * @param {Object} style + * @return {Object} block + * { + * width, + * height, + * lines: [{ + * lineHeight, + * width, + * tokens: [[{ + * styleName, + * text, + * width, // include textPadding + * height, // include textPadding + * textWidth, // pure text width + * textHeight, // pure text height + * lineHeihgt, + * font, + * textAlign, + * textVerticalAlign + * }], [...], ...] + * }, ...] + * } + * If styleName is undefined, it is plain text. + */ + + +function parseRichText(text, style) { + var contentBlock = { + lines: [], + width: 0, + height: 0 + }; + text != null && (text += ''); + + if (!text) { + return contentBlock; + } + + var lastIndex = STYLE_REG.lastIndex = 0; + var result; + + while ((result = STYLE_REG.exec(text)) != null) { + var matchedIndex = result.index; + + if (matchedIndex > lastIndex) { + pushTokens(contentBlock, text.substring(lastIndex, matchedIndex)); + } + + pushTokens(contentBlock, result[2], result[1]); + lastIndex = STYLE_REG.lastIndex; + } + + if (lastIndex < text.length) { + pushTokens(contentBlock, text.substring(lastIndex, text.length)); + } + + var lines = contentBlock.lines; + var contentHeight = 0; + var contentWidth = 0; // For `textWidth: 100%` + + var pendingList = []; + var stlPadding = style.textPadding; + var truncate = style.truncate; + var truncateWidth = truncate && truncate.outerWidth; + var truncateHeight = truncate && truncate.outerHeight; + + if (stlPadding) { + truncateWidth != null && (truncateWidth -= stlPadding[1] + stlPadding[3]); + truncateHeight != null && (truncateHeight -= stlPadding[0] + stlPadding[2]); + } // Calculate layout info of tokens. + + + for (var i = 0; i < lines.length; i++) { + var line = lines[i]; + var lineHeight = 0; + var lineWidth = 0; + + for (var j = 0; j < line.tokens.length; j++) { + var token = line.tokens[j]; + var tokenStyle = token.styleName && style.rich[token.styleName] || {}; // textPadding should not inherit from style. + + var textPadding = token.textPadding = tokenStyle.textPadding; // textFont has been asigned to font by `normalizeStyle`. + + var font = token.font = tokenStyle.font || style.font; // textHeight can be used when textVerticalAlign is specified in token. + + var tokenHeight = token.textHeight = retrieve2( // textHeight should not be inherited, consider it can be specified + // as box height of the block. + tokenStyle.textHeight, getLineHeight(font)); + textPadding && (tokenHeight += textPadding[0] + textPadding[2]); + token.height = tokenHeight; + token.lineHeight = retrieve3(tokenStyle.textLineHeight, style.textLineHeight, tokenHeight); + token.textAlign = tokenStyle && tokenStyle.textAlign || style.textAlign; + token.textVerticalAlign = tokenStyle && tokenStyle.textVerticalAlign || 'middle'; + + if (truncateHeight != null && contentHeight + token.lineHeight > truncateHeight) { + return { + lines: [], + width: 0, + height: 0 + }; + } + + token.textWidth = getWidth(token.text, font); + var tokenWidth = tokenStyle.textWidth; + var tokenWidthNotSpecified = tokenWidth == null || tokenWidth === 'auto'; // Percent width, can be `100%`, can be used in drawing separate + // line when box width is needed to be auto. + + if (typeof tokenWidth === 'string' && tokenWidth.charAt(tokenWidth.length - 1) === '%') { + token.percentWidth = tokenWidth; + pendingList.push(token); + tokenWidth = 0; // Do not truncate in this case, because there is no user case + // and it is too complicated. + } else { + if (tokenWidthNotSpecified) { + tokenWidth = token.textWidth; // FIXME: If image is not loaded and textWidth is not specified, calling + // `getBoundingRect()` will not get correct result. + + var textBackgroundColor = tokenStyle.textBackgroundColor; + var bgImg = textBackgroundColor && textBackgroundColor.image; // Use cases: + // (1) If image is not loaded, it will be loaded at render phase and call + // `dirty()` and `textBackgroundColor.image` will be replaced with the loaded + // image, and then the right size will be calculated here at the next tick. + // See `graphic/helper/text.js`. + // (2) If image loaded, and `textBackgroundColor.image` is image src string, + // use `imageHelper.findExistImage` to find cached image. + // `imageHelper.findExistImage` will always be called here before + // `imageHelper.createOrUpdateImage` in `graphic/helper/text.js#renderRichText` + // which ensures that image will not be rendered before correct size calcualted. + + if (bgImg) { + bgImg = imageHelper.findExistImage(bgImg); + + if (imageHelper.isImageReady(bgImg)) { + tokenWidth = Math.max(tokenWidth, bgImg.width * tokenHeight / bgImg.height); + } + } + } + + var paddingW = textPadding ? textPadding[1] + textPadding[3] : 0; + tokenWidth += paddingW; + var remianTruncWidth = truncateWidth != null ? truncateWidth - lineWidth : null; + + if (remianTruncWidth != null && remianTruncWidth < tokenWidth) { + if (!tokenWidthNotSpecified || remianTruncWidth < paddingW) { + token.text = ''; + token.textWidth = tokenWidth = 0; + } else { + token.text = truncateText(token.text, remianTruncWidth - paddingW, font, truncate.ellipsis, { + minChar: truncate.minChar + }); + token.textWidth = getWidth(token.text, font); + tokenWidth = token.textWidth + paddingW; + } + } + } + + lineWidth += token.width = tokenWidth; + tokenStyle && (lineHeight = Math.max(lineHeight, token.lineHeight)); + } + + line.width = lineWidth; + line.lineHeight = lineHeight; + contentHeight += lineHeight; + contentWidth = Math.max(contentWidth, lineWidth); + } + + contentBlock.outerWidth = contentBlock.width = retrieve2(style.textWidth, contentWidth); + contentBlock.outerHeight = contentBlock.height = retrieve2(style.textHeight, contentHeight); + + if (stlPadding) { + contentBlock.outerWidth += stlPadding[1] + stlPadding[3]; + contentBlock.outerHeight += stlPadding[0] + stlPadding[2]; + } + + for (var i = 0; i < pendingList.length; i++) { + var token = pendingList[i]; + var percentWidth = token.percentWidth; // Should not base on outerWidth, because token can not be placed out of padding. + + token.width = parseInt(percentWidth, 10) / 100 * contentWidth; + } + + return contentBlock; +} + +function pushTokens(block, str, styleName) { + var isEmptyStr = str === ''; + var strs = str.split('\n'); + var lines = block.lines; + + for (var i = 0; i < strs.length; i++) { + var text = strs[i]; + var token = { + styleName: styleName, + text: text, + isLineHolder: !text && !isEmptyStr + }; // The first token should be appended to the last line. + + if (!i) { + var tokens = (lines[lines.length - 1] || (lines[0] = { + tokens: [] + })).tokens; // Consider cases: + // (1) ''.split('\n') => ['', '\n', ''], the '' at the first item + // (which is a placeholder) should be replaced by new token. + // (2) A image backage, where token likes {a|}. + // (3) A redundant '' will affect textAlign in line. + // (4) tokens with the same tplName should not be merged, because + // they should be displayed in different box (with border and padding). + + var tokensLen = tokens.length; + tokensLen === 1 && tokens[0].isLineHolder ? tokens[0] = token : // Consider text is '', only insert when it is the "lineHolder" or + // "emptyStr". Otherwise a redundant '' will affect textAlign in line. + (text || !tokensLen || isEmptyStr) && tokens.push(token); + } // Other tokens always start a new line. + else { + // If there is '', insert it as a placeholder. + lines.push({ + tokens: [token] + }); + } + } +} + +function makeFont(style) { + // FIXME in node-canvas fontWeight is before fontStyle + // Use `fontSize` `fontFamily` to check whether font properties are defined. + var font = (style.fontSize || style.fontFamily) && [style.fontStyle, style.fontWeight, (style.fontSize || 12) + 'px', // If font properties are defined, `fontFamily` should not be ignored. + style.fontFamily || 'sans-serif'].join(' '); + return font && trim(font) || style.textFont || style.font; +} + +exports.DEFAULT_FONT = DEFAULT_FONT; +exports.$override = $override; +exports.getWidth = getWidth; +exports.getBoundingRect = getBoundingRect; +exports.adjustTextX = adjustTextX; +exports.adjustTextY = adjustTextY; +exports.adjustTextPositionOnRect = adjustTextPositionOnRect; +exports.truncateText = truncateText; +exports.getLineHeight = getLineHeight; +exports.measureText = measureText; +exports.parsePlainText = parsePlainText; +exports.parseRichText = parseRichText; +exports.makeFont = makeFont; + +/***/ }), +/* 173 */ +/***/ (function(module, exports, __webpack_require__) { + +var LRU = __webpack_require__(60); + +var globalImageCache = new LRU(50); +/** + * @param {string|HTMLImageElement|HTMLCanvasElement|Canvas} newImageOrSrc + * @return {HTMLImageElement|HTMLCanvasElement|Canvas} image + */ + +function findExistImage(newImageOrSrc) { + if (typeof newImageOrSrc === 'string') { + var cachedImgObj = globalImageCache.get(newImageOrSrc); + return cachedImgObj && cachedImgObj.image; + } else { + return newImageOrSrc; + } +} +/** + * Caution: User should cache loaded images, but not just count on LRU. + * Consider if required images more than LRU size, will dead loop occur? + * + * @param {string|HTMLImageElement|HTMLCanvasElement|Canvas} newImageOrSrc + * @param {HTMLImageElement|HTMLCanvasElement|Canvas} image Existent image. + * @param {module:zrender/Element} [hostEl] For calling `dirty`. + * @param {Function} [cb] params: (image, cbPayload) + * @param {Object} [cbPayload] Payload on cb calling. + * @return {HTMLImageElement|HTMLCanvasElement|Canvas} image + */ + + +function createOrUpdateImage(newImageOrSrc, image, hostEl, cb, cbPayload) { + if (!newImageOrSrc) { + return image; + } else if (typeof newImageOrSrc === 'string') { + // Image should not be loaded repeatly. + if (image && image.__zrImageSrc === newImageOrSrc || !hostEl) { + return image; + } // Only when there is no existent image or existent image src + // is different, this method is responsible for load. + + + var cachedImgObj = globalImageCache.get(newImageOrSrc); + var pendingWrap = { + hostEl: hostEl, + cb: cb, + cbPayload: cbPayload + }; + + if (cachedImgObj) { + image = cachedImgObj.image; + !isImageReady(image) && cachedImgObj.pending.push(pendingWrap); + } else { + !image && (image = new Image()); + image.onload = imageOnLoad; + globalImageCache.put(newImageOrSrc, image.__cachedImgObj = { + image: image, + pending: [pendingWrap] + }); + image.src = image.__zrImageSrc = newImageOrSrc; + } + + return image; + } // newImageOrSrc is an HTMLImageElement or HTMLCanvasElement or Canvas + else { + return newImageOrSrc; + } +} + +function imageOnLoad() { + var cachedImgObj = this.__cachedImgObj; + this.onload = this.__cachedImgObj = null; + + for (var i = 0; i < cachedImgObj.pending.length; i++) { + var pendingWrap = cachedImgObj.pending[i]; + var cb = pendingWrap.cb; + cb && cb(this, pendingWrap.cbPayload); + pendingWrap.hostEl.dirty(); + } + + cachedImgObj.pending.length = 0; +} + +function isImageReady(image) { + return image && image.width && image.height; +} + +exports.findExistImage = findExistImage; +exports.createOrUpdateImage = createOrUpdateImage; +exports.isImageReady = isImageReady; + +/***/ }), +/* 174 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__core_Base__ = __webpack_require__(7); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__core_glenum__ = __webpack_require__(11); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__math_Vector3__ = __webpack_require__(3); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__math_BoundingBox__ = __webpack_require__(18); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4__math_Frustum__ = __webpack_require__(59); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_5__math_Matrix4__ = __webpack_require__(9); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_6__Renderer__ = __webpack_require__(52); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_7__Shader__ = __webpack_require__(8); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_8__Material__ = __webpack_require__(19); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_9__FrameBuffer__ = __webpack_require__(10); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_10__Texture__ = __webpack_require__(4); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_11__Texture2D__ = __webpack_require__(5); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_12__TextureCube__ = __webpack_require__(27); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_13__camera_Perspective__ = __webpack_require__(41); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_14__camera_Orthographic__ = __webpack_require__(37); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_15__compositor_Pass__ = __webpack_require__(16); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_16__compositor_TexturePool__ = __webpack_require__(86); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_17__glmatrix_mat4__ = __webpack_require__(21); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_18__shader_source_shadowmap_glsl_js__ = __webpack_require__(175); + + + + + + + + + + + + + + + + + + + + + +var targets = ['px', 'nx', 'py', 'ny', 'pz', 'nz']; + + +__WEBPACK_IMPORTED_MODULE_7__Shader__["a" /* default */]['import'](__WEBPACK_IMPORTED_MODULE_18__shader_source_shadowmap_glsl_js__["a" /* default */]); + +function getDepthMaterialUniform(renderable, depthMaterial, symbol) { + if (symbol === 'alphaMap') { + return renderable.material.get('diffuseMap'); + } + else if (symbol === 'alphaCutoff') { + if (renderable.material.isDefined('fragment', 'ALPHA_TEST') + && renderable.material.get('diffuseMap') + ) { + var alphaCutoff = renderable.material.get('alphaCutoff'); + return alphaCutoff || 0; + } + return 0; + } + else { + return depthMaterial.get(symbol); + } +} + +function isDepthMaterialChanged(renderable, prevRenderable) { + var matA = renderable.material; + var matB = prevRenderable.material; + return matA.get('diffuseMap') !== matB.get('diffuseMap') + || (matA.get('alphaCutoff') || 0) !== (matB.get('alphaCutoff') || 0); +} + +/** + * Pass rendering shadow map. + * + * @constructor clay.prePass.ShadowMap + * @extends clay.core.Base + * @example + * var shadowMapPass = new clay.prePass.ShadowMap({ + * softShadow: clay.prePass.ShadowMap.VSM + * }); + * ... + * animation.on('frame', function (frameTime) { + * shadowMapPass.render(renderer, scene, camera); + * renderer.render(scene, camera); + * }); + */ +var ShadowMapPass = __WEBPACK_IMPORTED_MODULE_0__core_Base__["a" /* default */].extend(function () { + return /** @lends clay.prePass.ShadowMap# */ { + /** + * Soft shadow technique. + * Can be {@link clay.prePass.ShadowMap.PCF} or {@link clay.prePass.ShadowMap.VSM} + * @type {number} + */ + softShadow: ShadowMapPass.PCF, + + /** + * Soft shadow blur size + * @type {number} + */ + shadowBlur: 1.0, + + lightFrustumBias: 'auto', + + kernelPCF: new Float32Array([ + 1, 0, + 1, 1, + -1, 1, + 0, 1, + -1, 0, + -1, -1, + 1, -1, + 0, -1 + ]), + + precision: 'highp', + + _lastRenderNotCastShadow: false, + + _frameBuffer: new __WEBPACK_IMPORTED_MODULE_9__FrameBuffer__["a" /* default */](), + + _textures: {}, + _shadowMapNumber: { + 'POINT_LIGHT': 0, + 'DIRECTIONAL_LIGHT': 0, + 'SPOT_LIGHT': 0 + }, + + _depthMaterials: {}, + _distanceMaterials: {}, + + _receivers: [], + _lightsCastShadow: [], + + _lightCameras: {}, + _lightMaterials: {}, + + _texturePool: new __WEBPACK_IMPORTED_MODULE_16__compositor_TexturePool__["a" /* default */]() + }; +}, function () { + // Gaussian filter pass for VSM + this._gaussianPassH = new __WEBPACK_IMPORTED_MODULE_15__compositor_Pass__["a" /* default */]({ + fragment: __WEBPACK_IMPORTED_MODULE_7__Shader__["a" /* default */].source('clay.compositor.gaussian_blur') + }); + this._gaussianPassV = new __WEBPACK_IMPORTED_MODULE_15__compositor_Pass__["a" /* default */]({ + fragment: __WEBPACK_IMPORTED_MODULE_7__Shader__["a" /* default */].source('clay.compositor.gaussian_blur') + }); + this._gaussianPassH.setUniform('blurSize', this.shadowBlur); + this._gaussianPassH.setUniform('blurDir', 0.0); + this._gaussianPassV.setUniform('blurSize', this.shadowBlur); + this._gaussianPassV.setUniform('blurDir', 1.0); + + this._outputDepthPass = new __WEBPACK_IMPORTED_MODULE_15__compositor_Pass__["a" /* default */]({ + fragment: __WEBPACK_IMPORTED_MODULE_7__Shader__["a" /* default */].source('clay.sm.debug_depth') + }); +}, { + /** + * Render scene to shadow textures + * @param {clay.Renderer} renderer + * @param {clay.Scene} scene + * @param {clay.Camera} sceneCamera + * @param {boolean} [notUpdateScene=false] + * @memberOf clay.prePass.ShadowMap.prototype + */ + render: function (renderer, scene, sceneCamera, notUpdateScene) { + if (!sceneCamera) { + sceneCamera = scene.getMainCamera(); + } + this.trigger('beforerender', this, renderer, scene, sceneCamera); + this._renderShadowPass(renderer, scene, sceneCamera, notUpdateScene); + this.trigger('afterrender', this, renderer, scene, sceneCamera); + }, + + /** + * Debug rendering of shadow textures + * @param {clay.Renderer} renderer + * @param {number} size + * @memberOf clay.prePass.ShadowMap.prototype + */ + renderDebug: function (renderer, size) { + renderer.saveClear(); + var viewport = renderer.viewport; + var x = 0, y = 0; + var width = size || viewport.width / 4; + var height = width; + if (this.softShadow === ShadowMapPass.VSM) { + this._outputDepthPass.material.define('fragment', 'USE_VSM'); + } + else { + this._outputDepthPass.material.undefine('fragment', 'USE_VSM'); + } + for (var name in this._textures) { + var texture = this._textures[name]; + renderer.setViewport(x, y, width * texture.width / texture.height, height); + this._outputDepthPass.setUniform('depthMap', texture); + this._outputDepthPass.render(renderer); + x += width * texture.width / texture.height; + } + renderer.setViewport(viewport); + renderer.restoreClear(); + }, + + _updateReceivers: function (renderer, mesh) { + if (mesh.receiveShadow) { + this._receivers.push(mesh); + mesh.material.set('shadowEnabled', 1); + + mesh.material.set('pcfKernel', this.kernelPCF); + } + else { + mesh.material.set('shadowEnabled', 0); + } + + if (this.softShadow === ShadowMapPass.VSM) { + mesh.material.define('fragment', 'USE_VSM'); + mesh.material.undefine('fragment', 'PCF_KERNEL_SIZE'); + } + else { + mesh.material.undefine('fragment', 'USE_VSM'); + var kernelPCF = this.kernelPCF; + if (kernelPCF && kernelPCF.length) { + mesh.material.define('fragment', 'PCF_KERNEL_SIZE', kernelPCF.length / 2); + } + else { + mesh.material.undefine('fragment', 'PCF_KERNEL_SIZE'); + } + } + }, + + _update: function (renderer, scene) { + var self = this; + scene.traverse(function (renderable) { + if (renderable.isRenderable()) { + self._updateReceivers(renderer, renderable); + } + }); + + for (var i = 0; i < scene.lights.length; i++) { + var light = scene.lights[i]; + if (light.castShadow && !light.invisible) { + this._lightsCastShadow.push(light); + } + } + }, + + _renderShadowPass: function (renderer, scene, sceneCamera, notUpdateScene) { + // reset + for (var name in this._shadowMapNumber) { + this._shadowMapNumber[name] = 0; + } + this._lightsCastShadow.length = 0; + this._receivers.length = 0; + + var _gl = renderer.gl; + + if (!notUpdateScene) { + scene.update(); + } + if (sceneCamera) { + sceneCamera.update(); + } + + scene.updateLights(); + this._update(renderer, scene); + + // Needs to update the receivers again if shadows come from 1 to 0. + if (!this._lightsCastShadow.length && this._lastRenderNotCastShadow) { + return; + } + + this._lastRenderNotCastShadow = this._lightsCastShadow === 0; + + _gl.enable(_gl.DEPTH_TEST); + _gl.depthMask(true); + _gl.disable(_gl.BLEND); + + // Clear with high-z, so the part not rendered will not been shadowed + // TODO + // TODO restore + _gl.clearColor(1.0, 1.0, 1.0, 1.0); + + // Shadow uniforms + var spotLightShadowMaps = []; + var spotLightMatrices = []; + var directionalLightShadowMaps = []; + var directionalLightMatrices = []; + var shadowCascadeClips = []; + var pointLightShadowMaps = []; + + var dirLightHasCascade; + // Create textures for shadow map + for (var i = 0; i < this._lightsCastShadow.length; i++) { + var light = this._lightsCastShadow[i]; + if (light.type === 'DIRECTIONAL_LIGHT') { + + if (dirLightHasCascade) { + console.warn('Only one direectional light supported with shadow cascade'); + continue; + } + if (light.shadowCascade > 4) { + console.warn('Support at most 4 cascade'); + continue; + } + if (light.shadowCascade > 1) { + dirLightHasCascade = light; + } + + this.renderDirectionalLightShadow( + renderer, + scene, + sceneCamera, + light, + shadowCascadeClips, + directionalLightMatrices, + directionalLightShadowMaps + ); + } + else if (light.type === 'SPOT_LIGHT') { + this.renderSpotLightShadow( + renderer, + scene, + light, + spotLightMatrices, + spotLightShadowMaps + ); + } + else if (light.type === 'POINT_LIGHT') { + this.renderPointLightShadow( + renderer, + scene, + light, + pointLightShadowMaps + ); + } + + this._shadowMapNumber[light.type]++; + } + + for (var lightType in this._shadowMapNumber) { + var number = this._shadowMapNumber[lightType]; + var key = lightType + '_SHADOWMAP_COUNT'; + for (var i = 0; i < this._receivers.length; i++) { + var mesh = this._receivers[i]; + var material = mesh.material; + if (material.fragmentDefines[key] !== number) { + if (number > 0) { + material.define('fragment', key, number); + } + else if (material.isDefined('fragment', key)) { + material.undefine('fragment', key); + } + } + } + } + for (var i = 0; i < this._receivers.length; i++) { + var mesh = this._receivers[i]; + var material = mesh.material; + if (dirLightHasCascade) { + material.define('fragment', 'SHADOW_CASCADE', dirLightHasCascade.shadowCascade); + } + else { + material.undefine('fragment', 'SHADOW_CASCADE'); + } + } + + var shadowUniforms = scene.shadowUniforms; + + function getSize(texture) { + return texture.height; + } + if (directionalLightShadowMaps.length > 0) { + var directionalLightShadowMapSizes = directionalLightShadowMaps.map(getSize); + shadowUniforms.directionalLightShadowMaps = { value: directionalLightShadowMaps, type: 'tv' }; + shadowUniforms.directionalLightMatrices = { value: directionalLightMatrices, type: 'm4v' }; + shadowUniforms.directionalLightShadowMapSizes = { value: directionalLightShadowMapSizes, type: '1fv' }; + if (dirLightHasCascade) { + var shadowCascadeClipsNear = shadowCascadeClips.slice(); + var shadowCascadeClipsFar = shadowCascadeClips.slice(); + shadowCascadeClipsNear.pop(); + shadowCascadeClipsFar.shift(); + + // Iterate from far to near + shadowCascadeClipsNear.reverse(); + shadowCascadeClipsFar.reverse(); + // directionalLightShadowMaps.reverse(); + directionalLightMatrices.reverse(); + shadowUniforms.shadowCascadeClipsNear = { value: shadowCascadeClipsNear, type: '1fv' }; + shadowUniforms.shadowCascadeClipsFar = { value: shadowCascadeClipsFar, type: '1fv' }; + } + } + + if (spotLightShadowMaps.length > 0) { + var spotLightShadowMapSizes = spotLightShadowMaps.map(getSize); + var shadowUniforms = scene.shadowUniforms; + shadowUniforms.spotLightShadowMaps = { value: spotLightShadowMaps, type: 'tv' }; + shadowUniforms.spotLightMatrices = { value: spotLightMatrices, type: 'm4v' }; + shadowUniforms.spotLightShadowMapSizes = { value: spotLightShadowMapSizes, type: '1fv' }; + } + + if (pointLightShadowMaps.length > 0) { + shadowUniforms.pointLightShadowMaps = { value: pointLightShadowMaps, type: 'tv' }; + } + }, + + renderDirectionalLightShadow: (function () { + + var splitFrustum = new __WEBPACK_IMPORTED_MODULE_4__math_Frustum__["a" /* default */](); + var splitProjMatrix = new __WEBPACK_IMPORTED_MODULE_5__math_Matrix4__["a" /* default */](); + var cropBBox = new __WEBPACK_IMPORTED_MODULE_3__math_BoundingBox__["a" /* default */](); + var cropMatrix = new __WEBPACK_IMPORTED_MODULE_5__math_Matrix4__["a" /* default */](); + var lightViewMatrix = new __WEBPACK_IMPORTED_MODULE_5__math_Matrix4__["a" /* default */](); + var lightViewProjMatrix = new __WEBPACK_IMPORTED_MODULE_5__math_Matrix4__["a" /* default */](); + var lightProjMatrix = new __WEBPACK_IMPORTED_MODULE_5__math_Matrix4__["a" /* default */](); + + return function (renderer, scene, sceneCamera, light, shadowCascadeClips, directionalLightMatrices, directionalLightShadowMaps) { + + var defaultShadowMaterial = this._getDepthMaterial(light); + var passConfig = { + getMaterial: function (renderable) { + return renderable.shadowDepthMaterial || defaultShadowMaterial; + }, + isMaterialChanged: isDepthMaterialChanged, + getUniform: getDepthMaterialUniform, + ifRender: function (renderable) { + return renderable.castShadow; + }, + sortCompare: __WEBPACK_IMPORTED_MODULE_6__Renderer__["a" /* default */].opaqueSortCompare + }; + + // First frame + if (!scene.viewBoundingBoxLastFrame.isFinite()) { + var boundingBox = scene.getBoundingBox(); + scene.viewBoundingBoxLastFrame + .copy(boundingBox).applyTransform(sceneCamera.viewMatrix); + } + // Considering moving speed since the bounding box is from last frame + // TODO: add a bias + var clippedFar = Math.min(-scene.viewBoundingBoxLastFrame.min.z, sceneCamera.far); + var clippedNear = Math.max(-scene.viewBoundingBoxLastFrame.max.z, sceneCamera.near); + + var lightCamera = this._getDirectionalLightCamera(light, scene, sceneCamera); + + var lvpMat4Arr = lightViewProjMatrix.array; + lightProjMatrix.copy(lightCamera.projectionMatrix); + __WEBPACK_IMPORTED_MODULE_17__glmatrix_mat4__["a" /* default */].invert(lightViewMatrix.array, lightCamera.worldTransform.array); + __WEBPACK_IMPORTED_MODULE_17__glmatrix_mat4__["a" /* default */].multiply(lightViewMatrix.array, lightViewMatrix.array, sceneCamera.worldTransform.array); + __WEBPACK_IMPORTED_MODULE_17__glmatrix_mat4__["a" /* default */].multiply(lvpMat4Arr, lightProjMatrix.array, lightViewMatrix.array); + + var clipPlanes = []; + var isPerspective = sceneCamera instanceof __WEBPACK_IMPORTED_MODULE_13__camera_Perspective__["a" /* default */]; + + var scaleZ = (sceneCamera.near + sceneCamera.far) / (sceneCamera.near - sceneCamera.far); + var offsetZ = 2 * sceneCamera.near * sceneCamera.far / (sceneCamera.near - sceneCamera.far); + for (var i = 0; i <= light.shadowCascade; i++) { + var clog = clippedNear * Math.pow(clippedFar / clippedNear, i / light.shadowCascade); + var cuni = clippedNear + (clippedFar - clippedNear) * i / light.shadowCascade; + var c = clog * light.cascadeSplitLogFactor + cuni * (1 - light.cascadeSplitLogFactor); + clipPlanes.push(c); + shadowCascadeClips.push(-(-c * scaleZ + offsetZ) / -c); + } + var texture = this._getTexture(light, light.shadowCascade); + directionalLightShadowMaps.push(texture); + + var viewport = renderer.viewport; + + var _gl = renderer.gl; + this._frameBuffer.attach(texture); + this._frameBuffer.bind(renderer); + _gl.clear(_gl.COLOR_BUFFER_BIT | _gl.DEPTH_BUFFER_BIT); + + for (var i = 0; i < light.shadowCascade; i++) { + // Get the splitted frustum + var nearPlane = clipPlanes[i]; + var farPlane = clipPlanes[i + 1]; + if (isPerspective) { + __WEBPACK_IMPORTED_MODULE_17__glmatrix_mat4__["a" /* default */].perspective(splitProjMatrix.array, sceneCamera.fov / 180 * Math.PI, sceneCamera.aspect, nearPlane, farPlane); + } + else { + __WEBPACK_IMPORTED_MODULE_17__glmatrix_mat4__["a" /* default */].ortho( + splitProjMatrix.array, + sceneCamera.left, sceneCamera.right, sceneCamera.bottom, sceneCamera.top, + nearPlane, farPlane + ); + } + splitFrustum.setFromProjection(splitProjMatrix); + splitFrustum.getTransformedBoundingBox(cropBBox, lightViewMatrix); + cropBBox.applyProjection(lightProjMatrix); + var _min = cropBBox.min.array; + var _max = cropBBox.max.array; + _min[0] = Math.max(_min[0], -1); + _min[1] = Math.max(_min[1], -1); + _max[0] = Math.min(_max[0], 1); + _max[1] = Math.min(_max[1], 1); + cropMatrix.ortho(_min[0], _max[0], _min[1], _max[1], 1, -1); + lightCamera.projectionMatrix.multiplyLeft(cropMatrix); + + var shadowSize = light.shadowResolution || 512; + + // Reversed, left to right => far to near + renderer.setViewport((light.shadowCascade - i - 1) * shadowSize, 0, shadowSize, shadowSize, 1); + + var renderList = scene.updateRenderList(lightCamera); + renderer.renderPass(renderList.opaque, lightCamera, passConfig); + + // Filter for VSM + if (this.softShadow === ShadowMapPass.VSM) { + this._gaussianFilter(renderer, texture, texture.width); + } + + var matrix = new __WEBPACK_IMPORTED_MODULE_5__math_Matrix4__["a" /* default */](); + matrix.copy(lightCamera.viewMatrix) + .multiplyLeft(lightCamera.projectionMatrix); + + directionalLightMatrices.push(matrix.array); + + lightCamera.projectionMatrix.copy(lightProjMatrix); + } + + this._frameBuffer.unbind(renderer); + + renderer.setViewport(viewport); + }; + })(), + + renderSpotLightShadow: function (renderer, scene, light, spotLightMatrices, spotLightShadowMaps) { + + var texture = this._getTexture(light); + var lightCamera = this._getSpotLightCamera(light); + var _gl = renderer.gl; + + this._frameBuffer.attach(texture); + this._frameBuffer.bind(renderer); + + _gl.clear(_gl.COLOR_BUFFER_BIT | _gl.DEPTH_BUFFER_BIT); + + var defaultShadowMaterial = this._getDepthMaterial(light); + var passConfig = { + getMaterial: function (renderable) { + return renderable.shadowDepthMaterial || defaultShadowMaterial; + }, + isMaterialChanged: isDepthMaterialChanged, + getUniform: getDepthMaterialUniform, + ifRender: function (renderable) { + return renderable.castShadow; + }, + sortCompare: __WEBPACK_IMPORTED_MODULE_6__Renderer__["a" /* default */].opaqueSortCompare + }; + + var renderList = scene.updateRenderList(lightCamera); + renderer.renderPass(renderList.opaque, lightCamera, passConfig); + + this._frameBuffer.unbind(renderer); + + // Filter for VSM + if (this.softShadow === ShadowMapPass.VSM) { + this._gaussianFilter(renderer, texture, texture.width); + } + + var matrix = new __WEBPACK_IMPORTED_MODULE_5__math_Matrix4__["a" /* default */](); + matrix.copy(lightCamera.worldTransform) + .invert() + .multiplyLeft(lightCamera.projectionMatrix); + + spotLightShadowMaps.push(texture); + spotLightMatrices.push(matrix.array); + }, + + renderPointLightShadow: function (renderer, scene, light, pointLightShadowMaps) { + var texture = this._getTexture(light); + var _gl = renderer.gl; + pointLightShadowMaps.push(texture); + + var defaultShadowMaterial = this._getDepthMaterial(light); + var passConfig = { + getMaterial: function (renderable) { + return renderable.shadowDepthMaterial || defaultShadowMaterial; + }, + getUniform: getDepthMaterialUniform, + sortCompare: __WEBPACK_IMPORTED_MODULE_6__Renderer__["a" /* default */].opaqueSortCompare + }; + + var renderListEachSide = { + px: [], py: [], pz: [], nx: [], ny: [], nz: [] + }; + var bbox = new __WEBPACK_IMPORTED_MODULE_3__math_BoundingBox__["a" /* default */](); + var lightWorldPosition = light.getWorldPosition().array; + var lightBBox = new __WEBPACK_IMPORTED_MODULE_3__math_BoundingBox__["a" /* default */](); + var range = light.range; + lightBBox.min.setArray(lightWorldPosition); + lightBBox.max.setArray(lightWorldPosition); + var extent = new __WEBPACK_IMPORTED_MODULE_2__math_Vector3__["a" /* default */](range, range, range); + lightBBox.max.add(extent); + lightBBox.min.sub(extent); + + var targetsNeedRender = { px: false, py: false, pz: false, nx: false, ny: false, nz: false }; + scene.traverse(function (renderable) { + if (renderable.isRenderable() && renderable.castShadow) { + var geometry = renderable.geometry; + if (!geometry.boundingBox) { + for (var i = 0; i < targets.length; i++) { + renderListEachSide[targets[i]].push(renderable); + } + return; + } + bbox.transformFrom(geometry.boundingBox, renderable.worldTransform); + if (!bbox.intersectBoundingBox(lightBBox)) { + return; + } + + bbox.updateVertices(); + for (var i = 0; i < targets.length; i++) { + targetsNeedRender[targets[i]] = false; + } + for (var i = 0; i < 8; i++) { + var vtx = bbox.vertices[i]; + var x = vtx[0] - lightWorldPosition[0]; + var y = vtx[1] - lightWorldPosition[1]; + var z = vtx[2] - lightWorldPosition[2]; + var absx = Math.abs(x); + var absy = Math.abs(y); + var absz = Math.abs(z); + if (absx > absy) { + if (absx > absz) { + targetsNeedRender[x > 0 ? 'px' : 'nx'] = true; + } + else { + targetsNeedRender[z > 0 ? 'pz' : 'nz'] = true; + } + } + else { + if (absy > absz) { + targetsNeedRender[y > 0 ? 'py' : 'ny'] = true; + } + else { + targetsNeedRender[z > 0 ? 'pz' : 'nz'] = true; + } + } + } + for (var i = 0; i < targets.length; i++) { + if (targetsNeedRender[targets[i]]) { + renderListEachSide[targets[i]].push(renderable); + } + } + } + }); + + for (var i = 0; i < 6; i++) { + var target = targets[i]; + var camera = this._getPointLightCamera(light, target); + + this._frameBuffer.attach(texture, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i); + this._frameBuffer.bind(renderer); + _gl.clear(_gl.COLOR_BUFFER_BIT | _gl.DEPTH_BUFFER_BIT); + + renderer.renderPass(renderListEachSide[target], camera, passConfig); + } + + this._frameBuffer.unbind(renderer); + }, + + _getDepthMaterial: function (light) { + var shadowMaterial = this._lightMaterials[light.__uid__]; + var isPointLight = light.type === 'POINT_LIGHT'; + if (!shadowMaterial) { + var shaderPrefix = isPointLight ? 'clay.sm.distance.' : 'clay.sm.depth.'; + shadowMaterial = new __WEBPACK_IMPORTED_MODULE_8__Material__["a" /* default */]({ + precision: this.precision, + shader: new __WEBPACK_IMPORTED_MODULE_7__Shader__["a" /* default */](__WEBPACK_IMPORTED_MODULE_7__Shader__["a" /* default */].source(shaderPrefix + 'vertex'), __WEBPACK_IMPORTED_MODULE_7__Shader__["a" /* default */].source(shaderPrefix + 'fragment')) + }); + + this._lightMaterials[light.__uid__] = shadowMaterial; + } + if (light.shadowSlopeScale != null) { + shadowMaterial.setUniform('slopeScale', light.shadowSlopeScale); + } + if (light.shadowBias != null) { + shadowMaterial.setUniform('bias', light.shadowBias); + } + if (this.softShadow === ShadowMapPass.VSM) { + shadowMaterial.define('fragment', 'USE_VSM'); + } + else { + shadowMaterial.undefine('fragment', 'USE_VSM'); + } + + if (isPointLight) { + shadowMaterial.set('lightPosition', light.getWorldPosition().array); + shadowMaterial.set('range', light.range); + } + + return shadowMaterial; + }, + + _gaussianFilter: function (renderer, texture, size) { + var parameter = { + width: size, + height: size, + type: __WEBPACK_IMPORTED_MODULE_10__Texture__["a" /* default */].FLOAT + }; + var tmpTexture = this._texturePool.get(parameter); + + this._frameBuffer.attach(tmpTexture); + this._frameBuffer.bind(renderer); + this._gaussianPassH.setUniform('texture', texture); + this._gaussianPassH.setUniform('textureWidth', size); + this._gaussianPassH.render(renderer); + + this._frameBuffer.attach(texture); + this._gaussianPassV.setUniform('texture', tmpTexture); + this._gaussianPassV.setUniform('textureHeight', size); + this._gaussianPassV.render(renderer); + this._frameBuffer.unbind(renderer); + + this._texturePool.put(tmpTexture); + }, + + _getTexture: function (light, cascade) { + var key = light.__uid__; + var texture = this._textures[key]; + var resolution = light.shadowResolution || 512; + cascade = cascade || 1; + if (!texture) { + if (light.type === 'POINT_LIGHT') { + texture = new __WEBPACK_IMPORTED_MODULE_12__TextureCube__["a" /* default */](); + } + else { + texture = new __WEBPACK_IMPORTED_MODULE_11__Texture2D__["a" /* default */](); + } + // At most 4 cascade + // TODO share with height ? + texture.width = resolution * cascade; + texture.height = resolution; + if (this.softShadow === ShadowMapPass.VSM) { + texture.type = __WEBPACK_IMPORTED_MODULE_10__Texture__["a" /* default */].FLOAT; + texture.anisotropic = 4; + } + else { + texture.minFilter = __WEBPACK_IMPORTED_MODULE_1__core_glenum__["a" /* default */].NEAREST; + texture.magFilter = __WEBPACK_IMPORTED_MODULE_1__core_glenum__["a" /* default */].NEAREST; + texture.useMipmap = false; + } + this._textures[key] = texture; + } + + return texture; + }, + + _getPointLightCamera: function (light, target) { + if (!this._lightCameras.point) { + this._lightCameras.point = { + px: new __WEBPACK_IMPORTED_MODULE_13__camera_Perspective__["a" /* default */](), + nx: new __WEBPACK_IMPORTED_MODULE_13__camera_Perspective__["a" /* default */](), + py: new __WEBPACK_IMPORTED_MODULE_13__camera_Perspective__["a" /* default */](), + ny: new __WEBPACK_IMPORTED_MODULE_13__camera_Perspective__["a" /* default */](), + pz: new __WEBPACK_IMPORTED_MODULE_13__camera_Perspective__["a" /* default */](), + nz: new __WEBPACK_IMPORTED_MODULE_13__camera_Perspective__["a" /* default */]() + }; + } + var camera = this._lightCameras.point[target]; + + camera.far = light.range; + camera.fov = 90; + camera.position.set(0, 0, 0); + switch (target) { + case 'px': + camera.lookAt(__WEBPACK_IMPORTED_MODULE_2__math_Vector3__["a" /* default */].POSITIVE_X, __WEBPACK_IMPORTED_MODULE_2__math_Vector3__["a" /* default */].NEGATIVE_Y); + break; + case 'nx': + camera.lookAt(__WEBPACK_IMPORTED_MODULE_2__math_Vector3__["a" /* default */].NEGATIVE_X, __WEBPACK_IMPORTED_MODULE_2__math_Vector3__["a" /* default */].NEGATIVE_Y); + break; + case 'py': + camera.lookAt(__WEBPACK_IMPORTED_MODULE_2__math_Vector3__["a" /* default */].POSITIVE_Y, __WEBPACK_IMPORTED_MODULE_2__math_Vector3__["a" /* default */].POSITIVE_Z); + break; + case 'ny': + camera.lookAt(__WEBPACK_IMPORTED_MODULE_2__math_Vector3__["a" /* default */].NEGATIVE_Y, __WEBPACK_IMPORTED_MODULE_2__math_Vector3__["a" /* default */].NEGATIVE_Z); + break; + case 'pz': + camera.lookAt(__WEBPACK_IMPORTED_MODULE_2__math_Vector3__["a" /* default */].POSITIVE_Z, __WEBPACK_IMPORTED_MODULE_2__math_Vector3__["a" /* default */].NEGATIVE_Y); + break; + case 'nz': + camera.lookAt(__WEBPACK_IMPORTED_MODULE_2__math_Vector3__["a" /* default */].NEGATIVE_Z, __WEBPACK_IMPORTED_MODULE_2__math_Vector3__["a" /* default */].NEGATIVE_Y); + break; + } + light.getWorldPosition(camera.position); + camera.update(); + + return camera; + }, + + _getDirectionalLightCamera: (function () { + var lightViewMatrix = new __WEBPACK_IMPORTED_MODULE_5__math_Matrix4__["a" /* default */](); + var sceneViewBoundingBox = new __WEBPACK_IMPORTED_MODULE_3__math_BoundingBox__["a" /* default */](); + var lightViewBBox = new __WEBPACK_IMPORTED_MODULE_3__math_BoundingBox__["a" /* default */](); + // Camera of directional light will be adjusted + // to contain the view frustum and scene bounding box as tightly as possible + return function (light, scene, sceneCamera) { + if (!this._lightCameras.directional) { + this._lightCameras.directional = new __WEBPACK_IMPORTED_MODULE_14__camera_Orthographic__["a" /* default */](); + } + var camera = this._lightCameras.directional; + + sceneViewBoundingBox.copy(scene.viewBoundingBoxLastFrame); + sceneViewBoundingBox.intersection(sceneCamera.frustum.boundingBox); + // Move to the center of frustum(in world space) + camera.position + .copy(sceneViewBoundingBox.min) + .add(sceneViewBoundingBox.max) + .scale(0.5) + .transformMat4(sceneCamera.worldTransform); + camera.rotation.copy(light.rotation); + camera.scale.copy(light.scale); + camera.updateWorldTransform(); + + // Transform to light view space + __WEBPACK_IMPORTED_MODULE_5__math_Matrix4__["a" /* default */].invert(lightViewMatrix, camera.worldTransform); + __WEBPACK_IMPORTED_MODULE_5__math_Matrix4__["a" /* default */].multiply(lightViewMatrix, lightViewMatrix, sceneCamera.worldTransform); + + lightViewBBox.copy(sceneViewBoundingBox).applyTransform(lightViewMatrix); + + var min = lightViewBBox.min.array; + var max = lightViewBBox.max.array; + + // Move camera to adjust the near to 0 + camera.position.set((min[0] + max[0]) / 2, (min[1] + max[1]) / 2, max[2]) + .transformMat4(camera.worldTransform); + camera.near = 0; + camera.far = -min[2] + max[2]; + // Make sure receivers not in the frustum will stil receive the shadow. + if (isNaN(this.lightFrustumBias)) { + camera.far *= 4; + } + else { + camera.far += this.lightFrustumBias; + } + camera.left = min[0]; + camera.right = max[0]; + camera.top = max[1]; + camera.bottom = min[1]; + camera.update(true); + + return camera; + }; + })(), + + _getSpotLightCamera: function (light) { + if (!this._lightCameras.spot) { + this._lightCameras.spot = new __WEBPACK_IMPORTED_MODULE_13__camera_Perspective__["a" /* default */](); + } + var camera = this._lightCameras.spot; + // Update properties + camera.fov = light.penumbraAngle * 2; + camera.far = light.range; + camera.worldTransform.copy(light.worldTransform); + camera.updateProjectionMatrix(); + __WEBPACK_IMPORTED_MODULE_17__glmatrix_mat4__["a" /* default */].invert(camera.viewMatrix.array, camera.worldTransform.array); + + return camera; + }, + + /** + * @param {clay.Renderer|WebGLRenderingContext} [renderer] + * @memberOf clay.prePass.ShadowMap.prototype + */ + // PENDING Renderer or WebGLRenderingContext + dispose: function (renderer) { + var _gl = renderer.gl || renderer; + + if (this._frameBuffer) { + this._frameBuffer.dispose(_gl); + } + + for (var name in this._textures) { + this._textures[name].dispose(_gl); + } + + this._texturePool.clear(renderer.gl); + + this._depthMaterials = {}; + this._distanceMaterials = {}; + this._textures = {}; + this._lightCameras = {}; + this._shadowMapNumber = { + 'POINT_LIGHT': 0, + 'DIRECTIONAL_LIGHT': 0, + 'SPOT_LIGHT': 0 + }; + this._meshMaterials = {}; + + for (var i = 0; i < this._receivers.length; i++) { + var mesh = this._receivers[i]; + // Mesh may be disposed + if (mesh.material) { + var material = mesh.material; + material.undefine('fragment', 'POINT_LIGHT_SHADOW_COUNT'); + material.undefine('fragment', 'DIRECTIONAL_LIGHT_SHADOW_COUNT'); + material.undefine('fragment', 'AMBIENT_LIGHT_SHADOW_COUNT'); + material.set('shadowEnabled', 0); + } + } + + this._receivers = []; + this._lightsCastShadow = []; + } +}); + +/** + * @name clay.prePass.ShadowMap.VSM + * @type {number} + */ +ShadowMapPass.VSM = 1; + +/** + * @name clay.prePass.ShadowMap.PCF + * @type {number} + */ +ShadowMapPass.PCF = 2; + +/* harmony default export */ __webpack_exports__["a"] = (ShadowMapPass); + + +/***/ }), +/* 175 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony default export */ __webpack_exports__["a"] = ("@export clay.sm.depth.vertex\nuniform mat4 worldViewProjection : WORLDVIEWPROJECTION;\nattribute vec3 position : POSITION;\nattribute vec2 texcoord : TEXCOORD_0;\n@import clay.chunk.skinning_header\nvarying vec4 v_ViewPosition;\nvarying vec2 v_Texcoord;\nvoid main(){\n vec3 skinnedPosition = position;\n#ifdef SKINNING\n @import clay.chunk.skin_matrix\n skinnedPosition = (skinMatrixWS * vec4(position, 1.0)).xyz;\n#endif\n v_ViewPosition = worldViewProjection * vec4(skinnedPosition, 1.0);\n gl_Position = v_ViewPosition;\n v_Texcoord = texcoord;\n}\n@end\n@export clay.sm.depth.fragment\nvarying vec4 v_ViewPosition;\nvarying vec2 v_Texcoord;\nuniform float bias : 0.001;\nuniform float slopeScale : 1.0;\nuniform sampler2D alphaMap;\nuniform float alphaCutoff: 0.0;\n@import clay.util.encode_float\nvoid main(){\n float depth = v_ViewPosition.z / v_ViewPosition.w;\n if (alphaCutoff > 0.0) {\n if (texture2D(alphaMap, v_Texcoord).a <= alphaCutoff) {\n discard;\n }\n }\n#ifdef USE_VSM\n depth = depth * 0.5 + 0.5;\n float moment1 = depth;\n float moment2 = depth * depth;\n float dx = dFdx(depth);\n float dy = dFdy(depth);\n moment2 += 0.25*(dx*dx+dy*dy);\n gl_FragColor = vec4(moment1, moment2, 0.0, 1.0);\n#else\n float dx = dFdx(depth);\n float dy = dFdy(depth);\n depth += sqrt(dx*dx + dy*dy) * slopeScale + bias;\n gl_FragColor = encodeFloat(depth * 0.5 + 0.5);\n#endif\n}\n@end\n@export clay.sm.debug_depth\nuniform sampler2D depthMap;\nvarying vec2 v_Texcoord;\n@import clay.util.decode_float\nvoid main() {\n vec4 tex = texture2D(depthMap, v_Texcoord);\n#ifdef USE_VSM\n gl_FragColor = vec4(tex.rgb, 1.0);\n#else\n float depth = decodeFloat(tex);\n gl_FragColor = vec4(depth, depth, depth, 1.0);\n#endif\n}\n@end\n@export clay.sm.distance.vertex\nuniform mat4 worldViewProjection : WORLDVIEWPROJECTION;\nuniform mat4 world : WORLD;\nattribute vec3 position : POSITION;\n@import clay.chunk.skinning_header\nvarying vec3 v_WorldPosition;\nvoid main (){\n vec3 skinnedPosition = position;\n#ifdef SKINNING\n @import clay.chunk.skin_matrix\n skinnedPosition = (skinMatrixWS * vec4(position, 1.0)).xyz;\n#endif\n gl_Position = worldViewProjection * vec4(skinnedPosition , 1.0);\n v_WorldPosition = (world * vec4(skinnedPosition, 1.0)).xyz;\n}\n@end\n@export clay.sm.distance.fragment\nuniform vec3 lightPosition;\nuniform float range : 100;\nvarying vec3 v_WorldPosition;\n@import clay.util.encode_float\nvoid main(){\n float dist = distance(lightPosition, v_WorldPosition);\n#ifdef USE_VSM\n gl_FragColor = vec4(dist, dist * dist, 0.0, 0.0);\n#else\n dist = dist / range;\n gl_FragColor = encodeFloat(dist);\n#endif\n}\n@end\n@export clay.plugin.shadow_map_common\n@import clay.util.decode_float\nfloat tapShadowMap(sampler2D map, vec2 uv, float z){\n vec4 tex = texture2D(map, uv);\n return step(z, decodeFloat(tex) * 2.0 - 1.0);\n}\nfloat pcf(sampler2D map, vec2 uv, float z, float textureSize, vec2 scale) {\n float shadowContrib = tapShadowMap(map, uv, z);\n vec2 offset = vec2(1.0 / textureSize) * scale;\n#ifdef PCF_KERNEL_SIZE\n for (int _idx_ = 0; _idx_ < PCF_KERNEL_SIZE; _idx_++) {{\n shadowContrib += tapShadowMap(map, uv + offset * pcfKernel[_idx_], z);\n }}\n return shadowContrib / float(PCF_KERNEL_SIZE + 1);\n#else\n shadowContrib += tapShadowMap(map, uv+vec2(offset.x, 0.0), z);\n shadowContrib += tapShadowMap(map, uv+vec2(offset.x, offset.y), z);\n shadowContrib += tapShadowMap(map, uv+vec2(-offset.x, offset.y), z);\n shadowContrib += tapShadowMap(map, uv+vec2(0.0, offset.y), z);\n shadowContrib += tapShadowMap(map, uv+vec2(-offset.x, 0.0), z);\n shadowContrib += tapShadowMap(map, uv+vec2(-offset.x, -offset.y), z);\n shadowContrib += tapShadowMap(map, uv+vec2(offset.x, -offset.y), z);\n shadowContrib += tapShadowMap(map, uv+vec2(0.0, -offset.y), z);\n return shadowContrib / 9.0;\n#endif\n}\nfloat pcf(sampler2D map, vec2 uv, float z, float textureSize) {\n return pcf(map, uv, z, textureSize, vec2(1.0));\n}\nfloat chebyshevUpperBound(vec2 moments, float z){\n float p = 0.0;\n z = z * 0.5 + 0.5;\n if (z <= moments.x) {\n p = 1.0;\n }\n float variance = moments.y - moments.x * moments.x;\n variance = max(variance, 0.0000001);\n float mD = moments.x - z;\n float pMax = variance / (variance + mD * mD);\n pMax = clamp((pMax-0.4)/(1.0-0.4), 0.0, 1.0);\n return max(p, pMax);\n}\nfloat computeShadowContrib(\n sampler2D map, mat4 lightVPM, vec3 position, float textureSize, vec2 scale, vec2 offset\n) {\n vec4 posInLightSpace = lightVPM * vec4(position, 1.0);\n posInLightSpace.xyz /= posInLightSpace.w;\n float z = posInLightSpace.z;\n if(all(greaterThan(posInLightSpace.xyz, vec3(-0.99, -0.99, -1.0))) &&\n all(lessThan(posInLightSpace.xyz, vec3(0.99, 0.99, 1.0)))){\n vec2 uv = (posInLightSpace.xy+1.0) / 2.0;\n #ifdef USE_VSM\n vec2 moments = texture2D(map, uv * scale + offset).xy;\n return chebyshevUpperBound(moments, z);\n #else\n return pcf(map, uv * scale + offset, z, textureSize, scale);\n #endif\n }\n return 1.0;\n}\nfloat computeShadowContrib(sampler2D map, mat4 lightVPM, vec3 position, float textureSize) {\n return computeShadowContrib(map, lightVPM, position, textureSize, vec2(1.0), vec2(0.0));\n}\nfloat computeShadowContribOmni(samplerCube map, vec3 direction, float range)\n{\n float dist = length(direction);\n vec4 shadowTex = textureCube(map, direction);\n#ifdef USE_VSM\n vec2 moments = shadowTex.xy;\n float variance = moments.y - moments.x * moments.x;\n float mD = moments.x - dist;\n float p = variance / (variance + mD * mD);\n if(moments.x + 0.001 < dist){\n return clamp(p, 0.0, 1.0);\n }else{\n return 1.0;\n }\n#else\n return step(dist, (decodeFloat(shadowTex) + 0.0002) * range);\n#endif\n}\n@end\n@export clay.plugin.compute_shadow_map\n#if defined(SPOT_LIGHT_SHADOWMAP_COUNT) || defined(DIRECTIONAL_LIGHT_SHADOWMAP_COUNT) || defined(POINT_LIGHT_SHADOWMAP_COUNT)\n#ifdef SPOT_LIGHT_SHADOWMAP_COUNT\nuniform sampler2D spotLightShadowMaps[SPOT_LIGHT_SHADOWMAP_COUNT]:unconfigurable;\nuniform mat4 spotLightMatrices[SPOT_LIGHT_SHADOWMAP_COUNT]:unconfigurable;\nuniform float spotLightShadowMapSizes[SPOT_LIGHT_SHADOWMAP_COUNT]:unconfigurable;\n#endif\n#ifdef DIRECTIONAL_LIGHT_SHADOWMAP_COUNT\n#if defined(SHADOW_CASCADE)\nuniform sampler2D directionalLightShadowMaps[1]:unconfigurable;\nuniform mat4 directionalLightMatrices[SHADOW_CASCADE]:unconfigurable;\nuniform float directionalLightShadowMapSizes[1]:unconfigurable;\nuniform float shadowCascadeClipsNear[SHADOW_CASCADE]:unconfigurable;\nuniform float shadowCascadeClipsFar[SHADOW_CASCADE]:unconfigurable;\n#else\nuniform sampler2D directionalLightShadowMaps[DIRECTIONAL_LIGHT_SHADOWMAP_COUNT]:unconfigurable;\nuniform mat4 directionalLightMatrices[DIRECTIONAL_LIGHT_SHADOWMAP_COUNT]:unconfigurable;\nuniform float directionalLightShadowMapSizes[DIRECTIONAL_LIGHT_SHADOWMAP_COUNT]:unconfigurable;\n#endif\n#endif\n#ifdef POINT_LIGHT_SHADOWMAP_COUNT\nuniform samplerCube pointLightShadowMaps[POINT_LIGHT_SHADOWMAP_COUNT]:unconfigurable;\n#endif\nuniform bool shadowEnabled : true;\n#ifdef PCF_KERNEL_SIZE\nuniform vec2 pcfKernel[PCF_KERNEL_SIZE];\n#endif\n@import clay.plugin.shadow_map_common\n#if defined(SPOT_LIGHT_SHADOWMAP_COUNT)\nvoid computeShadowOfSpotLights(vec3 position, inout float shadowContribs[SPOT_LIGHT_COUNT] ) {\n float shadowContrib;\n for(int _idx_ = 0; _idx_ < SPOT_LIGHT_SHADOWMAP_COUNT; _idx_++) {{\n shadowContrib = computeShadowContrib(\n spotLightShadowMaps[_idx_], spotLightMatrices[_idx_], position,\n spotLightShadowMapSizes[_idx_]\n );\n shadowContribs[_idx_] = shadowContrib;\n }}\n for(int _idx_ = SPOT_LIGHT_SHADOWMAP_COUNT; _idx_ < SPOT_LIGHT_COUNT; _idx_++){{\n shadowContribs[_idx_] = 1.0;\n }}\n}\n#endif\n#if defined(DIRECTIONAL_LIGHT_SHADOWMAP_COUNT)\n#ifdef SHADOW_CASCADE\nvoid computeShadowOfDirectionalLights(vec3 position, inout float shadowContribs[DIRECTIONAL_LIGHT_COUNT]){\n float depth = (2.0 * gl_FragCoord.z - gl_DepthRange.near - gl_DepthRange.far)\n / (gl_DepthRange.far - gl_DepthRange.near);\n float shadowContrib;\n shadowContribs[0] = 1.0;\n for (int _idx_ = 0; _idx_ < SHADOW_CASCADE; _idx_++) {{\n if (\n depth >= shadowCascadeClipsNear[_idx_] &&\n depth <= shadowCascadeClipsFar[_idx_]\n ) {\n shadowContrib = computeShadowContrib(\n directionalLightShadowMaps[0], directionalLightMatrices[_idx_], position,\n directionalLightShadowMapSizes[0],\n vec2(1.0 / float(SHADOW_CASCADE), 1.0),\n vec2(float(_idx_) / float(SHADOW_CASCADE), 0.0)\n );\n shadowContribs[0] = shadowContrib;\n }\n }}\n for(int _idx_ = DIRECTIONAL_LIGHT_SHADOWMAP_COUNT; _idx_ < DIRECTIONAL_LIGHT_COUNT; _idx_++) {{\n shadowContribs[_idx_] = 1.0;\n }}\n}\n#else\nvoid computeShadowOfDirectionalLights(vec3 position, inout float shadowContribs[DIRECTIONAL_LIGHT_COUNT]){\n float shadowContrib;\n for(int _idx_ = 0; _idx_ < DIRECTIONAL_LIGHT_SHADOWMAP_COUNT; _idx_++) {{\n shadowContrib = computeShadowContrib(\n directionalLightShadowMaps[_idx_], directionalLightMatrices[_idx_], position,\n directionalLightShadowMapSizes[_idx_]\n );\n shadowContribs[_idx_] = shadowContrib;\n }}\n for(int _idx_ = DIRECTIONAL_LIGHT_SHADOWMAP_COUNT; _idx_ < DIRECTIONAL_LIGHT_COUNT; _idx_++) {{\n shadowContribs[_idx_] = 1.0;\n }}\n}\n#endif\n#endif\n#if defined(POINT_LIGHT_SHADOWMAP_COUNT)\nvoid computeShadowOfPointLights(vec3 position, inout float shadowContribs[POINT_LIGHT_COUNT] ){\n vec3 lightPosition;\n vec3 direction;\n for(int _idx_ = 0; _idx_ < POINT_LIGHT_SHADOWMAP_COUNT; _idx_++) {{\n lightPosition = pointLightPosition[_idx_];\n direction = position - lightPosition;\n shadowContribs[_idx_] = computeShadowContribOmni(pointLightShadowMaps[_idx_], direction, pointLightRange[_idx_]);\n }}\n for(int _idx_ = POINT_LIGHT_SHADOWMAP_COUNT; _idx_ < POINT_LIGHT_COUNT; _idx_++) {{\n shadowContribs[_idx_] = 1.0;\n }}\n}\n#endif\n#endif\n@end"); + + +/***/ }), +/* 176 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_claygl_src_Shader__ = __webpack_require__(8); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_claygl_src_Texture2D__ = __webpack_require__(5); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2_claygl_src_Texture__ = __webpack_require__(4); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3_claygl_src_FrameBuffer__ = __webpack_require__(10); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4_claygl_src_compositor_createCompositor__ = __webpack_require__(177); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_5__SSAOPass__ = __webpack_require__(189); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_6__SSRPass__ = __webpack_require__(191); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_7__poissonKernel__ = __webpack_require__(193); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_8__util_graphicGL__ = __webpack_require__(1); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_9__NormalPass__ = __webpack_require__(194); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_10__EdgePass__ = __webpack_require__(196); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_11_claygl_src_math_Matrix4__ = __webpack_require__(9); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_12__composite_js__ = __webpack_require__(197); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_13_claygl_src_shader_source_compositor_blur_glsl_js__ = __webpack_require__(87); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_14_claygl_src_shader_source_compositor_lut_glsl_js__ = __webpack_require__(88); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_15_claygl_src_shader_source_compositor_output_glsl_js__ = __webpack_require__(89); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_16_claygl_src_shader_source_compositor_bright_glsl_js__ = __webpack_require__(90); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_17_claygl_src_shader_source_compositor_downsample_glsl_js__ = __webpack_require__(91); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_18_claygl_src_shader_source_compositor_upsample_glsl_js__ = __webpack_require__(92); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_19_claygl_src_shader_source_compositor_hdr_glsl_js__ = __webpack_require__(93); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_20_claygl_src_shader_source_compositor_blend_glsl_js__ = __webpack_require__(94); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_21_claygl_src_shader_source_compositor_fxaa_glsl_js__ = __webpack_require__(95); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_22__DOF_glsl_js__ = __webpack_require__(198); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_23__edge_glsl_js__ = __webpack_require__(199); + + + + + + + + + + + + + + + + + + + + + + + + + + + +__WEBPACK_IMPORTED_MODULE_0_claygl_src_Shader__["a" /* default */]['import'](__WEBPACK_IMPORTED_MODULE_13_claygl_src_shader_source_compositor_blur_glsl_js__["a" /* default */]); +__WEBPACK_IMPORTED_MODULE_0_claygl_src_Shader__["a" /* default */]['import'](__WEBPACK_IMPORTED_MODULE_14_claygl_src_shader_source_compositor_lut_glsl_js__["a" /* default */]); +__WEBPACK_IMPORTED_MODULE_0_claygl_src_Shader__["a" /* default */]['import'](__WEBPACK_IMPORTED_MODULE_15_claygl_src_shader_source_compositor_output_glsl_js__["a" /* default */]); +__WEBPACK_IMPORTED_MODULE_0_claygl_src_Shader__["a" /* default */]['import'](__WEBPACK_IMPORTED_MODULE_16_claygl_src_shader_source_compositor_bright_glsl_js__["a" /* default */]); +__WEBPACK_IMPORTED_MODULE_0_claygl_src_Shader__["a" /* default */]['import'](__WEBPACK_IMPORTED_MODULE_17_claygl_src_shader_source_compositor_downsample_glsl_js__["a" /* default */]); +__WEBPACK_IMPORTED_MODULE_0_claygl_src_Shader__["a" /* default */]['import'](__WEBPACK_IMPORTED_MODULE_18_claygl_src_shader_source_compositor_upsample_glsl_js__["a" /* default */]); +__WEBPACK_IMPORTED_MODULE_0_claygl_src_Shader__["a" /* default */]['import'](__WEBPACK_IMPORTED_MODULE_19_claygl_src_shader_source_compositor_hdr_glsl_js__["a" /* default */]); +__WEBPACK_IMPORTED_MODULE_0_claygl_src_Shader__["a" /* default */]['import'](__WEBPACK_IMPORTED_MODULE_20_claygl_src_shader_source_compositor_blend_glsl_js__["a" /* default */]); +__WEBPACK_IMPORTED_MODULE_0_claygl_src_Shader__["a" /* default */]['import'](__WEBPACK_IMPORTED_MODULE_21_claygl_src_shader_source_compositor_fxaa_glsl_js__["a" /* default */]); +__WEBPACK_IMPORTED_MODULE_0_claygl_src_Shader__["a" /* default */]['import'](__WEBPACK_IMPORTED_MODULE_22__DOF_glsl_js__["a" /* default */]); +__WEBPACK_IMPORTED_MODULE_0_claygl_src_Shader__["a" /* default */]['import'](__WEBPACK_IMPORTED_MODULE_23__edge_glsl_js__["a" /* default */]); + + +var commonOutputs = { + color : { + parameters : { + width : function (renderer) { + return renderer.getWidth(); + }, + height : function (renderer) { + return renderer.getHeight(); + } + } + } +} + +var FINAL_NODES_CHAIN = ['composite', 'FXAA']; + +function EffectCompositor() { + this._sourceTexture = new __WEBPACK_IMPORTED_MODULE_1_claygl_src_Texture2D__["a" /* default */]({ + type: __WEBPACK_IMPORTED_MODULE_2_claygl_src_Texture__["a" /* default */].HALF_FLOAT + }); + this._depthTexture = new __WEBPACK_IMPORTED_MODULE_1_claygl_src_Texture2D__["a" /* default */]({ + format: __WEBPACK_IMPORTED_MODULE_2_claygl_src_Texture__["a" /* default */].DEPTH_COMPONENT, + type: __WEBPACK_IMPORTED_MODULE_2_claygl_src_Texture__["a" /* default */].UNSIGNED_INT + }); + + this._framebuffer = new __WEBPACK_IMPORTED_MODULE_3_claygl_src_FrameBuffer__["a" /* default */](); + this._framebuffer.attach(this._sourceTexture); + this._framebuffer.attach(this._depthTexture, __WEBPACK_IMPORTED_MODULE_3_claygl_src_FrameBuffer__["a" /* default */].DEPTH_ATTACHMENT); + + this._normalPass = new __WEBPACK_IMPORTED_MODULE_9__NormalPass__["a" /* default */](); + + this._compositor = Object(__WEBPACK_IMPORTED_MODULE_4_claygl_src_compositor_createCompositor__["a" /* default */])(__WEBPACK_IMPORTED_MODULE_12__composite_js__["a" /* default */]); + + var sourceNode = this._compositor.getNodeByName('source'); + sourceNode.texture = this._sourceTexture; + var cocNode = this._compositor.getNodeByName('coc'); + + this._sourceNode = sourceNode; + this._cocNode = cocNode; + this._compositeNode = this._compositor.getNodeByName('composite'); + this._fxaaNode = this._compositor.getNodeByName('FXAA'); + + this._dofBlurNodes = ['dof_far_blur', 'dof_near_blur', 'dof_coc_blur'].map(function (name) { + return this._compositor.getNodeByName(name); + }, this); + + this._dofBlurKernel = 0; + this._dofBlurKernelSize = new Float32Array(0); + + this._finalNodesChain = FINAL_NODES_CHAIN.map(function (name) { + return this._compositor.getNodeByName(name); + }, this); + + var gBufferObj = { + normalTexture: this._normalPass.getNormalTexture(), + depthTexture: this._normalPass.getDepthTexture() + }; + this._ssaoPass = new __WEBPACK_IMPORTED_MODULE_5__SSAOPass__["a" /* default */](gBufferObj); + this._ssrPass = new __WEBPACK_IMPORTED_MODULE_6__SSRPass__["a" /* default */](gBufferObj); + this._edgePass = new __WEBPACK_IMPORTED_MODULE_10__EdgePass__["a" /* default */](gBufferObj); +} + +EffectCompositor.prototype.resize = function (width, height, dpr) { + dpr = dpr || 1; + var width = width * dpr; + var height = height * dpr; + var sourceTexture = this._sourceTexture; + var depthTexture = this._depthTexture; + + sourceTexture.width = width; + sourceTexture.height = height; + depthTexture.width = width; + depthTexture.height = height; +}; + +EffectCompositor.prototype._ifRenderNormalPass = function () { + return this._enableSSAO || this._enableEdge || this._enableSSR; +}; + +EffectCompositor.prototype._getPrevNode = function (node) { + var idx = FINAL_NODES_CHAIN.indexOf(node.name) - 1; + var prevNode = this._finalNodesChain[idx]; + while (prevNode && !this._compositor.getNodeByName(prevNode.name)) { + idx -= 1; + prevNode = this._finalNodesChain[idx]; + } + return prevNode; +}; +EffectCompositor.prototype._getNextNode = function (node) { + var idx = FINAL_NODES_CHAIN.indexOf(node.name) + 1; + var nextNode = this._finalNodesChain[idx]; + while (nextNode && !this._compositor.getNodeByName(nextNode.name)) { + idx += 1; + nextNode = this._finalNodesChain[idx]; + } + return nextNode; +}; +EffectCompositor.prototype._addChainNode = function (node) { + var prevNode = this._getPrevNode(node); + var nextNode = this._getNextNode(node); + if (!prevNode) { + return; + } + + prevNode.outputs = commonOutputs; + node.inputs.texture = prevNode.name; + if (nextNode) { + node.outputs = commonOutputs; + nextNode.inputs.texture = node.name; + } + else { + node.outputs = null; + } + this._compositor.addNode(node); +}; +EffectCompositor.prototype._removeChainNode = function (node) { + var prevNode = this._getPrevNode(node); + var nextNode = this._getNextNode(node); + if (!prevNode) { + return; + } + + if (nextNode) { + prevNode.outputs = commonOutputs; + nextNode.inputs.texture = prevNode.name; + } + else { + prevNode.outputs = null; + } + this._compositor.removeNode(node); +}; +/** + * Update normal + */ +EffectCompositor.prototype.updateNormal = function (renderer, scene, camera, frame) { + if (this._ifRenderNormalPass()) { + this._normalPass.update(renderer, scene, camera); + } +}; + +/** + * Render SSAO after render the scene, before compositing + */ +EffectCompositor.prototype.updateSSAO = function (renderer, scene, camera, frame) { + this._ssaoPass.update(renderer, camera, frame); +}; + +/** + * Enable SSAO effect + */ +EffectCompositor.prototype.enableSSAO = function () { + this._enableSSAO = true; +}; + +/** + * Disable SSAO effect + */ +EffectCompositor.prototype.disableSSAO = function () { + this._enableSSAO = false; +}; + +/** + * Enable SSR effect + */ +EffectCompositor.prototype.enableSSR = function () { + this._enableSSR = true; + // this._normalPass.enableTargetTexture3 = true; +}; +/** + * Disable SSR effect + */ +EffectCompositor.prototype.disableSSR = function () { + this._enableSSR = false; + // this._normalPass.enableTargetTexture3 = false; +}; + +/** + * Render SSAO after render the scene, before compositing + */ +EffectCompositor.prototype.getSSAOTexture = function () { + return this._ssaoPass.getTargetTexture(); +}; + +/** + * @return {clay.FrameBuffer} + */ +EffectCompositor.prototype.getSourceFrameBuffer = function () { + return this._framebuffer; +}; + +/** + * @return {clay.Texture2D} + */ +EffectCompositor.prototype.getSourceTexture = function () { + return this._sourceTexture; +}; + +/** + * Disable fxaa effect + */ +EffectCompositor.prototype.disableFXAA = function () { + this._removeChainNode(this._fxaaNode); +}; + +/** + * Enable fxaa effect + */ +EffectCompositor.prototype.enableFXAA = function () { + this._addChainNode(this._fxaaNode); +}; + +/** + * Enable bloom effect + */ +EffectCompositor.prototype.enableBloom = function () { + this._compositeNode.inputs.bloom = 'bloom_composite'; + this._compositor.dirty(); +}; + +/** + * Disable bloom effect + */ +EffectCompositor.prototype.disableBloom = function () { + this._compositeNode.inputs.bloom = null; + this._compositor.dirty(); +}; + +/** + * Enable depth of field effect + */ +EffectCompositor.prototype.enableDOF = function () { + this._compositeNode.inputs.texture = 'dof_composite'; + this._compositor.dirty(); +}; +/** + * Disable depth of field effect + */ +EffectCompositor.prototype.disableDOF = function () { + this._compositeNode.inputs.texture = 'source'; + this._compositor.dirty(); +}; + +/** + * Enable color correction + */ +EffectCompositor.prototype.enableColorCorrection = function () { + this._compositeNode.define('COLOR_CORRECTION'); + this._enableColorCorrection = true; +}; +/** + * Disable color correction + */ +EffectCompositor.prototype.disableColorCorrection = function () { + this._compositeNode.undefine('COLOR_CORRECTION'); + this._enableColorCorrection = false; +}; + +/** + * Enable edge detection + */ +EffectCompositor.prototype.enableEdge = function () { + this._enableEdge = true; +}; + +/** + * Disable edge detection + */ +EffectCompositor.prototype.disableEdge = function () { + this._enableEdge = false; +}; + +/** + * Set bloom intensity + * @param {number} value + */ +EffectCompositor.prototype.setBloomIntensity = function (value) { + this._compositeNode.setParameter('bloomIntensity', value); +}; + +EffectCompositor.prototype.setSSAOParameter = function (name, value) { + switch (name) { + case 'quality': + // PENDING + var kernelSize = ({ + low: 6, + medium: 12, + high: 32, + ultra: 62 + })[value] || 12; + this._ssaoPass.setParameter('kernelSize', kernelSize); + break; + case 'radius': + this._ssaoPass.setParameter(name, value); + this._ssaoPass.setParameter('bias', value / 200); + break; + case 'intensity': + this._ssaoPass.setParameter(name, value); + break; + default: + if (true) { + console.warn('Unkown SSAO parameter ' + name); + } + } +}; + +EffectCompositor.prototype.setDOFParameter = function (name, value) { + switch (name) { + case 'focalDistance': + case 'focalRange': + case 'fstop': + this._cocNode.setParameter(name, value); + break; + case 'blurRadius': + for (var i = 0; i < this._dofBlurNodes.length; i++) { + this._dofBlurNodes[i].setParameter('blurRadius', value); + } + break; + case 'quality': + var kernelSize = ({ + low: 4, medium: 8, high: 16, ultra: 32 + })[value] || 8; + this._dofBlurKernelSize = kernelSize; + for (var i = 0; i < this._dofBlurNodes.length; i++) { + this._dofBlurNodes[i].pass.material.define('POISSON_KERNEL_SIZE', kernelSize); + } + this._dofBlurKernel = new Float32Array(kernelSize * 2); + break; + default: + if (true) { + console.warn('Unkown DOF parameter ' + name); + } + } +}; + +EffectCompositor.prototype.setSSRParameter = function (name, value) { + if (value == null) { + return; + } + switch (name) { + case 'quality': + // PENDING + var maxIteration = ({ + low: 10, + medium: 15, + high: 30, + ultra: 80 + })[value] || 20; + var pixelStride = ({ + low: 32, + medium: 16, + high: 8, + ultra: 4 + })[value] || 16; + this._ssrPass.setParameter('maxIteration', maxIteration); + this._ssrPass.setParameter('pixelStride', pixelStride); + break; + case 'maxRoughness': + this._ssrPass.setParameter('minGlossiness', Math.max(Math.min(1.0 - value, 1.0), 0.0)); + break; + case 'physical': + this.setPhysicallyCorrectSSR(value); + break; + default: + console.warn('Unkown SSR parameter ' + name); + } +}; + +EffectCompositor.prototype.setPhysicallyCorrectSSR = function (physical) { + this._ssrPass.setPhysicallyCorrect(physical); +}; + +/** + * Set color of edge + */ +EffectCompositor.prototype.setEdgeColor = function (value) { + var color = __WEBPACK_IMPORTED_MODULE_8__util_graphicGL__["a" /* default */].parseColor(value); + this._edgePass.setParameter('edgeColor', color); +}; + +EffectCompositor.prototype.setExposure = function (value) { + this._compositeNode.setParameter('exposure', Math.pow(2, value)); +}; + +EffectCompositor.prototype.setColorLookupTexture = function (image, api) { + this._compositeNode.pass.material.setTextureImage('lut', this._enableColorCorrection ? image : 'none', api, { + minFilter: __WEBPACK_IMPORTED_MODULE_8__util_graphicGL__["a" /* default */].Texture.NEAREST, + magFilter: __WEBPACK_IMPORTED_MODULE_8__util_graphicGL__["a" /* default */].Texture.NEAREST, + flipY: false + }); +}; +EffectCompositor.prototype.setColorCorrection = function (type, value) { + this._compositeNode.setParameter(type, value); +}; + +EffectCompositor.prototype.isSSREnabled = function () { + return this._enableSSR; +}; + +EffectCompositor.prototype.composite = function (renderer, scene, camera, framebuffer, frame) { + + var sourceTexture = this._sourceTexture; + var targetTexture = sourceTexture; + if (this._enableEdge) { + this._edgePass.update(renderer, camera, sourceTexture, frame); + sourceTexture = targetTexture = this._edgePass.getTargetTexture(); + } + if (this._enableSSR) { + this._ssrPass.update(renderer, camera, sourceTexture, frame); + targetTexture = this._ssrPass.getTargetTexture(); + + this._ssrPass.setSSAOTexture( + this._enableSSAO ? this._ssaoPass.getTargetTexture() : null + ); + // var lights = scene.getLights(); + // for (var i = 0; i < lights.length; i++) { + // if (lights[i].cubemap) { + // this._ssrPass.setAmbientCubemap(lights[i].cubemap, lights[i].intensity); + // } + // } + } + this._sourceNode.texture = targetTexture; + + this._cocNode.setParameter('depth', this._depthTexture); + + var blurKernel = this._dofBlurKernel; + var blurKernelSize = this._dofBlurKernelSize; + var frameAll = Math.floor(__WEBPACK_IMPORTED_MODULE_7__poissonKernel__["a" /* default */].length / 2 / blurKernelSize); + var kernelOffset = frame % frameAll; + + for (var i = 0; i < blurKernelSize * 2; i++) { + blurKernel[i] = __WEBPACK_IMPORTED_MODULE_7__poissonKernel__["a" /* default */][i + kernelOffset * blurKernelSize * 2]; + } + + for (var i = 0; i < this._dofBlurNodes.length; i++) { + this._dofBlurNodes[i].setParameter('percent', frame / 30.0); + this._dofBlurNodes[i].setParameter('poissonKernel', blurKernel); + } + + this._cocNode.setParameter('zNear', camera.near); + this._cocNode.setParameter('zFar', camera.far); + + this._compositor.render(renderer, framebuffer); +}; + +EffectCompositor.prototype.dispose = function (renderer) { + this._sourceTexture.dispose(renderer); + this._depthTexture.dispose(renderer); + this._framebuffer.dispose(renderer); + this._compositor.dispose(renderer); + + this._normalPass.dispose(renderer); + this._ssaoPass.dispose(renderer); +}; + +/* harmony default export */ __webpack_exports__["a"] = (EffectCompositor); + +/***/ }), +/* 177 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__createCompositor__ = __webpack_require__(178); +// DEPRECATED + +/* harmony default export */ __webpack_exports__["a"] = (__WEBPACK_IMPORTED_MODULE_0__createCompositor__["a" /* default */]); + +/***/ }), +/* 178 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__core_util__ = __webpack_require__(23); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__compositor_Compositor__ = __webpack_require__(179); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__compositor_SceneNode__ = __webpack_require__(181); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__compositor_TextureNode__ = __webpack_require__(182); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4__compositor_FilterNode__ = __webpack_require__(183); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_5__Shader__ = __webpack_require__(8); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_6__Texture__ = __webpack_require__(4); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_7__Texture2D__ = __webpack_require__(5); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_8__TextureCube__ = __webpack_require__(27); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_9__shader_registerBuiltinCompositor__ = __webpack_require__(184); + + + + + + + + + + + + +Object(__WEBPACK_IMPORTED_MODULE_9__shader_registerBuiltinCompositor__["a" /* default */])(__WEBPACK_IMPORTED_MODULE_5__Shader__["a" /* default */]); + +var shaderSourceReg = /^#source\((.*?)\)/; + +/** + * @name clay.createCompositor + * @function + * @param {Object} json + * @param {Object} [opts] + * @return {clay.compositor.Compositor} + */ +function createCompositor(json, opts) { + var compositor = new __WEBPACK_IMPORTED_MODULE_1__compositor_Compositor__["a" /* default */](); + opts = opts || {}; + + var lib = { + textures: {}, + parameters: {} + }; + var afterLoad = function(shaderLib, textureLib) { + for (var i = 0; i < json.nodes.length; i++) { + var nodeInfo = json.nodes[i]; + var node = createNode(nodeInfo, lib, opts); + if (node) { + compositor.addNode(node); + } + } + }; + + for (var name in json.parameters) { + var paramInfo = json.parameters[name]; + lib.parameters[name] = convertParameter(paramInfo); + } + // TODO load texture asynchronous + loadTextures(json, lib, opts, function(textureLib) { + lib.textures = textureLib; + afterLoad(); + }); + + return compositor; +} + +function createNode(nodeInfo, lib, opts) { + var type = nodeInfo.type || 'filter'; + var shaderSource; + var inputs; + var outputs; + + if (type === 'filter') { + var shaderExp = nodeInfo.shader.trim(); + var res = shaderSourceReg.exec(shaderExp); + if (res) { + shaderSource = __WEBPACK_IMPORTED_MODULE_5__Shader__["a" /* default */].source(res[1].trim()); + } + else if (shaderExp.charAt(0) === '#') { + shaderSource = lib.shaders[shaderExp.substr(1)]; + } + if (!shaderSource) { + shaderSource = shaderExp; + } + if (!shaderSource) { + return; + } + } + + if (nodeInfo.inputs) { + inputs = {}; + for (var name in nodeInfo.inputs) { + if (typeof nodeInfo.inputs[name] === 'string') { + inputs[name] = nodeInfo.inputs[name]; + } + else { + inputs[name] = { + node: nodeInfo.inputs[name].node, + pin: nodeInfo.inputs[name].pin + }; + } + } + } + if (nodeInfo.outputs) { + outputs = {}; + for (var name in nodeInfo.outputs) { + var outputInfo = nodeInfo.outputs[name]; + outputs[name] = {}; + if (outputInfo.attachment != null) { + outputs[name].attachment = outputInfo.attachment; + } + if (outputInfo.keepLastFrame != null) { + outputs[name].keepLastFrame = outputInfo.keepLastFrame; + } + if (outputInfo.outputLastFrame != null) { + outputs[name].outputLastFrame = outputInfo.outputLastFrame; + } + if (outputInfo.parameters) { + outputs[name].parameters = convertParameter(outputInfo.parameters); + } + } + } + var node; + if (type === 'scene') { + node = new __WEBPACK_IMPORTED_MODULE_2__compositor_SceneNode__["a" /* default */]({ + name: nodeInfo.name, + scene: opts.scene, + camera: opts.camera, + outputs: outputs + }); + } + else if (type === 'texture') { + node = new __WEBPACK_IMPORTED_MODULE_3__compositor_TextureNode__["a" /* default */]({ + name: nodeInfo.name, + outputs: outputs + }); + } + // Default is filter + else { + node = new __WEBPACK_IMPORTED_MODULE_4__compositor_FilterNode__["a" /* default */]({ + name: nodeInfo.name, + shader: shaderSource, + inputs: inputs, + outputs: outputs + }); + } + if (node) { + if (nodeInfo.parameters) { + for (var name in nodeInfo.parameters) { + var val = nodeInfo.parameters[name]; + if (typeof(val) === 'string') { + val = val.trim(); + if (val.charAt(0) === '#') { + val = lib.textures[val.substr(1)]; + } + else { + node.on( + 'beforerender', createSizeSetHandler( + name, tryConvertExpr(val) + ) + ); + } + } + node.setParameter(name, val); + } + } + if (nodeInfo.defines && node.pass) { + for (var name in nodeInfo.defines) { + var val = nodeInfo.defines[name]; + node.pass.material.define('fragment', name, val); + } + } + } + return node; +} + +function defaultWidthFunc(width, height) { + return width; +} +function defaultHeightFunc(width, height) { + return height; +} + +function convertParameter(paramInfo) { + var param = {}; + if (!paramInfo) { + return param; + } + ['type', 'minFilter', 'magFilter', 'wrapS', 'wrapT', 'flipY', 'useMipmap'] + .forEach(function(name) { + var val = paramInfo[name]; + if (val != null) { + // Convert string to enum + if (typeof val === 'string') { + val = __WEBPACK_IMPORTED_MODULE_6__Texture__["a" /* default */][val]; + } + param[name] = val; + } + }); + + var sizeScale = paramInfo.scale || 1; + ['width', 'height'] + .forEach(function(name) { + if (paramInfo[name] != null) { + var val = paramInfo[name]; + if (typeof val === 'string') { + val = val.trim(); + param[name] = createSizeParser( + name, tryConvertExpr(val), sizeScale + ); + } + else { + param[name] = val; + } + } + }); + if (!param.width) { + param.width = defaultWidthFunc; + } + if (!param.height) { + param.height = defaultHeightFunc; + } + + if (paramInfo.useMipmap != null) { + param.useMipmap = paramInfo.useMipmap; + } + return param; +} + +function loadTextures(json, lib, opts, callback) { + if (!json.textures) { + callback({}); + return; + } + var textures = {}; + var loading = 0; + + var cbd = false; + var textureRootPath = opts.textureRootPath; + __WEBPACK_IMPORTED_MODULE_0__core_util__["a" /* default */].each(json.textures, function(textureInfo, name) { + var texture; + var path = textureInfo.path; + var parameters = convertParameter(textureInfo.parameters); + if (Array.isArray(path) && path.length === 6) { + if (textureRootPath) { + path = path.map(function(item) { + return __WEBPACK_IMPORTED_MODULE_0__core_util__["a" /* default */].relative2absolute(item, textureRootPath); + }); + } + texture = new __WEBPACK_IMPORTED_MODULE_8__TextureCube__["a" /* default */](parameters); + } + else if(typeof path === 'string') { + if (textureRootPath) { + path = __WEBPACK_IMPORTED_MODULE_0__core_util__["a" /* default */].relative2absolute(path, textureRootPath); + } + texture = new __WEBPACK_IMPORTED_MODULE_7__Texture2D__["a" /* default */](parameters); + } + else { + return; + } + + texture.load(path); + loading++; + texture.once('success', function() { + textures[name] = texture; + loading--; + if (loading === 0) { + callback(textures); + cbd = true; + } + }); + }); + + if (loading === 0 && !cbd) { + callback(textures); + } +} + +function createSizeSetHandler(name, exprFunc) { + return function (renderer) { + // PENDING viewport size or window size + var dpr = renderer.getDevicePixelRatio(); + // PENDING If multiply dpr ? + var width = renderer.getWidth(); + var height = renderer.getHeight(); + var result = exprFunc(width, height, dpr); + this.setParameter(name, result); + }; +} + +function createSizeParser(name, exprFunc, scale) { + scale = scale || 1; + return function (renderer) { + var dpr = renderer.getDevicePixelRatio(); + var width = renderer.getWidth() * scale; + var height = renderer.getHeight() * scale; + return exprFunc(width, height, dpr); + }; +} + +function tryConvertExpr(string) { + // PENDING + var exprRes = /^expr\((.*)\)$/.exec(string); + if (exprRes) { + try { + var func = new Function('width', 'height', 'dpr', 'return ' + exprRes[1]); + // Try run t + func(1, 1); + + return func; + } + catch (e) { + throw new Error('Invalid expression.'); + } + } +} + +/* harmony default export */ __webpack_exports__["a"] = (createCompositor); + + +/***/ }), +/* 179 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__Graph__ = __webpack_require__(180); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__TexturePool__ = __webpack_require__(86); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__FrameBuffer__ = __webpack_require__(10); + + + + +/** + * Compositor provide graph based post processing + * + * @constructor clay.compositor.Compositor + * @extends clay.compositor.Graph + * + */ +var Compositor = __WEBPACK_IMPORTED_MODULE_0__Graph__["a" /* default */].extend(function() { + return { + // Output node + _outputs: [], + + _texturePool: new __WEBPACK_IMPORTED_MODULE_1__TexturePool__["a" /* default */](), + + _frameBuffer: new __WEBPACK_IMPORTED_MODULE_2__FrameBuffer__["a" /* default */]({ + depthBuffer: false + }) + }; +}, +/** @lends clay.compositor.Compositor.prototype */ +{ + addNode: function(node) { + __WEBPACK_IMPORTED_MODULE_0__Graph__["a" /* default */].prototype.addNode.call(this, node); + node._compositor = this; + }, + /** + * @param {clay.Renderer} renderer + */ + render: function(renderer, frameBuffer) { + if (this._dirty) { + this.update(); + this._dirty = false; + + this._outputs.length = 0; + for (var i = 0; i < this.nodes.length; i++) { + if (!this.nodes[i].outputs) { + this._outputs.push(this.nodes[i]); + } + } + } + + for (var i = 0; i < this.nodes.length; i++) { + // Update the reference number of each output texture + this.nodes[i].beforeFrame(); + } + + for (var i = 0; i < this._outputs.length; i++) { + this._outputs[i].updateReference(); + } + + for (var i = 0; i < this._outputs.length; i++) { + this._outputs[i].render(renderer, frameBuffer); + } + + for (var i = 0; i < this.nodes.length; i++) { + // Clear up + this.nodes[i].afterFrame(); + } + }, + + allocateTexture: function (parameters) { + return this._texturePool.get(parameters); + }, + + releaseTexture: function (parameters) { + this._texturePool.put(parameters); + }, + + getFrameBuffer: function () { + return this._frameBuffer; + }, + + /** + * Dispose compositor + * @param {clay.Renderer} renderer + */ + dispose: function (renderer) { + this._texturePool.clear(renderer); + } +}); + +/* harmony default export */ __webpack_exports__["a"] = (Compositor); + + +/***/ }), +/* 180 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__core_Base__ = __webpack_require__(7); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__CompositorNode__ = __webpack_require__(48); + + + +/** + * @constructor clay.compositor.Graph + * @extends clay.core.Base + */ +var Graph = __WEBPACK_IMPORTED_MODULE_0__core_Base__["a" /* default */].extend(function () { + return /** @lends clay.compositor.Graph# */ { + /** + * @type {Array.} + */ + nodes: [] + }; +}, +/** @lends clay.compositor.Graph.prototype */ +{ + + /** + * Mark to update + */ + dirty: function () { + this._dirty = true; + }, + /** + * @param {clay.compositor.CompositorNode} node + */ + addNode: function (node) { + + if (this.nodes.indexOf(node) >= 0) { + return; + } + + this.nodes.push(node); + + this._dirty = true; + }, + /** + * @param {clay.compositor.CompositorNode|string} node + */ + removeNode: function (node) { + if (typeof node === 'string') { + node = this.getNodeByName(node); + } + var idx = this.nodes.indexOf(node); + if (idx >= 0) { + this.nodes.splice(idx, 1); + this._dirty = true; + } + }, + /** + * @param {string} name + * @return {clay.compositor.CompositorNode} + */ + getNodeByName: function (name) { + for (var i = 0; i < this.nodes.length; i++) { + if (this.nodes[i].name === name) { + return this.nodes[i]; + } + } + }, + /** + * Update links of graph + */ + update: function () { + for (var i = 0; i < this.nodes.length; i++) { + this.nodes[i].clear(); + } + // Traverse all the nodes and build the graph + for (var i = 0; i < this.nodes.length; i++) { + var node = this.nodes[i]; + + if (!node.inputs) { + continue; + } + for (var inputName in node.inputs) { + if (!node.inputs[inputName]) { + continue; + } + if (node.pass && !node.pass.material.isUniformEnabled(inputName)) { + console.warn('Pin ' + node.name + '.' + inputName + ' not used.'); + continue; + } + var fromPinInfo = node.inputs[inputName]; + + var fromPin = this.findPin(fromPinInfo); + if (fromPin) { + node.link(inputName, fromPin.node, fromPin.pin); + } + else { + if (typeof fromPinInfo === 'string') { + console.warn('Node ' + fromPinInfo + ' not exist'); + } + else { + console.warn('Pin of ' + fromPinInfo.node + '.' + fromPinInfo.pin + ' not exist'); + } + } + } + } + }, + + findPin: function (input) { + var node; + // Try to take input as a directly a node + if (typeof input === 'string' || input instanceof __WEBPACK_IMPORTED_MODULE_1__CompositorNode__["a" /* default */]) { + input = { + node: input + }; + } + + if (typeof input.node === 'string') { + for (var i = 0; i < this.nodes.length; i++) { + var tmp = this.nodes[i]; + if (tmp.name === input.node) { + node = tmp; + } + } + } + else { + node = input.node; + } + if (node) { + var inputPin = input.pin; + if (!inputPin) { + // Use first pin defaultly + if (node.outputs) { + inputPin = Object.keys(node.outputs)[0]; + } + } + if (node.outputs[inputPin]) { + return { + node: node, + pin: inputPin + }; + } + } + } +}); + +/* harmony default export */ __webpack_exports__["a"] = (Graph); + + +/***/ }), +/* 181 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__CompositorNode__ = __webpack_require__(48); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__core_glenum__ = __webpack_require__(11); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__FrameBuffer__ = __webpack_require__(10); + + + + +/** + * @constructor clay.compositor.SceneNode + * @extends clay.compositor.CompositorNode + */ +var SceneNode = __WEBPACK_IMPORTED_MODULE_0__CompositorNode__["a" /* default */].extend( +/** @lends clay.compositor.SceneNode# */ +{ + name: 'scene', + /** + * @type {clay.Scene} + */ + scene: null, + /** + * @type {clay.Camera} + */ + camera: null, + /** + * @type {boolean} + */ + autoUpdateScene: true, + /** + * @type {boolean} + */ + preZ: false + +}, function() { + this.frameBuffer = new __WEBPACK_IMPORTED_MODULE_2__FrameBuffer__["a" /* default */](); +}, { + render: function(renderer) { + + this._rendering = true; + var _gl = renderer.gl; + + this.trigger('beforerender'); + + var renderInfo; + + if (!this.outputs) { + + renderInfo = renderer.render(this.scene, this.camera, !this.autoUpdateScene, this.preZ); + + } + else { + + var frameBuffer = this.frameBuffer; + for (var name in this.outputs) { + var parameters = this.updateParameter(name, renderer); + var outputInfo = this.outputs[name]; + var texture = this._compositor.allocateTexture(parameters); + this._outputTextures[name] = texture; + + var attachment = outputInfo.attachment || _gl.COLOR_ATTACHMENT0; + if (typeof(attachment) == 'string') { + attachment = _gl[attachment]; + } + frameBuffer.attach(texture, attachment); + } + frameBuffer.bind(renderer); + + // MRT Support in chrome + // https://www.khronos.org/registry/webgl/sdk/tests/conformance/extensions/ext-draw-buffers.html + var ext = renderer.getGLExtension('EXT_draw_buffers'); + if (ext) { + var bufs = []; + for (var attachment in this.outputs) { + attachment = parseInt(attachment); + if (attachment >= _gl.COLOR_ATTACHMENT0 && attachment <= _gl.COLOR_ATTACHMENT0 + 8) { + bufs.push(attachment); + } + } + ext.drawBuffersEXT(bufs); + } + + // Always clear + // PENDING + renderer.saveClear(); + renderer.clearBit = __WEBPACK_IMPORTED_MODULE_1__core_glenum__["a" /* default */].DEPTH_BUFFER_BIT | __WEBPACK_IMPORTED_MODULE_1__core_glenum__["a" /* default */].COLOR_BUFFER_BIT; + renderInfo = renderer.render(this.scene, this.camera, !this.autoUpdateScene, this.preZ); + renderer.restoreClear(); + + frameBuffer.unbind(renderer); + } + + this.trigger('afterrender', renderInfo); + + this._rendering = false; + this._rendered = true; + } +}); + +/* harmony default export */ __webpack_exports__["a"] = (SceneNode); + + +/***/ }), +/* 182 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__CompositorNode__ = __webpack_require__(48); + + +/** + * @constructor clay.compositor.TextureNode + * @extends clay.compositor.CompositorNode + */ +var TextureNode = __WEBPACK_IMPORTED_MODULE_0__CompositorNode__["a" /* default */].extend(function() { + return /** @lends clay.compositor.TextureNode# */ { + /** + * @type {clay.Texture2D} + */ + texture: null, + + // Texture node must have output without parameters + outputs: { + color: {} + } + }; +}, function () { +}, { + + getOutput: function (renderer, name) { + return this.texture; + }, + + // Do nothing + beforeFrame: function () {}, + afterFrame: function () {} +}); + +/* harmony default export */ __webpack_exports__["a"] = (TextureNode); + + +/***/ }), +/* 183 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__Pass__ = __webpack_require__(16); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__CompositorNode__ = __webpack_require__(48); +// TODO Shader library + + + +// TODO curlnoise demo wrong + +// PENDING +// Use topological sort ? + +/** + * Filter node + * + * @constructor clay.compositor.FilterNode + * @extends clay.compositor.CompositorNode + * + * @example + var node = new clay.compositor.FilterNode({ + name: 'fxaa', + shader: clay.Shader.source('clay.compositor.fxaa'), + inputs: { + texture: { + node: 'scene', + pin: 'color' + } + }, + // Multiple outputs is preserved for MRT support in WebGL2.0 + outputs: { + color: { + attachment: clay.FrameBuffer.COLOR_ATTACHMENT0 + parameters: { + format: clay.Texture.RGBA, + width: 512, + height: 512 + }, + // Node will keep the RTT rendered in last frame + keepLastFrame: true, + // Force the node output the RTT rendered in last frame + outputLastFrame: true + } + } + }); + * + */ +var FilterNode = __WEBPACK_IMPORTED_MODULE_1__CompositorNode__["a" /* default */].extend(function () { + return /** @lends clay.compositor.FilterNode# */ { + /** + * @type {string} + */ + name: '', + + /** + * @type {Object} + */ + inputs: {}, + + /** + * @type {Object} + */ + outputs: null, + + /** + * @type {string} + */ + shader: '', + + /** + * Input links, will be updated by the graph + * @example: + * inputName: { + * node: someNode, + * pin: 'xxxx' + * } + * @type {Object} + */ + inputLinks: {}, + + /** + * Output links, will be updated by the graph + * @example: + * outputName: { + * node: someNode, + * pin: 'xxxx' + * } + * @type {Object} + */ + outputLinks: {}, + + /** + * @type {clay.compositor.Pass} + */ + pass: null, + + // Save the output texture of previous frame + // Will be used when there exist a circular reference + _prevOutputTextures: {}, + _outputTextures: {}, + + // Example: { name: 2 } + _outputReferences: {}, + + _rendering: false, + // If rendered in this frame + _rendered: false, + + _compositor: null + }; +}, function () { + + var pass = new __WEBPACK_IMPORTED_MODULE_0__Pass__["a" /* default */]({ + fragment: this.shader + }); + this.pass = pass; +}, +/** @lends clay.compositor.FilterNode.prototype */ +{ + /** + * @param {clay.Renderer} renderer + */ + render: function (renderer, frameBuffer) { + this.trigger('beforerender', renderer); + + this._rendering = true; + + var _gl = renderer.gl; + + for (var inputName in this.inputLinks) { + var link = this.inputLinks[inputName]; + var inputTexture = link.node.getOutput(renderer, link.pin); + this.pass.setUniform(inputName, inputTexture); + } + // Output + if (!this.outputs) { + this.pass.outputs = null; + + this._compositor.getFrameBuffer().unbind(renderer); + + this.pass.render(renderer, frameBuffer); + } + else { + this.pass.outputs = {}; + + var attachedTextures = {}; + for (var name in this.outputs) { + var parameters = this.updateParameter(name, renderer); + if (isNaN(parameters.width)) { + this.updateParameter(name, renderer); + } + var outputInfo = this.outputs[name]; + var texture = this._compositor.allocateTexture(parameters); + this._outputTextures[name] = texture; + var attachment = outputInfo.attachment || _gl.COLOR_ATTACHMENT0; + if (typeof(attachment) === 'string') { + attachment = _gl[attachment]; + } + attachedTextures[attachment] = texture; + } + this._compositor.getFrameBuffer().bind(renderer); + + for (var attachment in attachedTextures) { + // FIXME attachment changes in different nodes + this._compositor.getFrameBuffer().attach( + attachedTextures[attachment], attachment + ); + } + + this.pass.render(renderer); + + // Because the data of texture is changed over time, + // Here update the mipmaps of texture each time after rendered; + this._compositor.getFrameBuffer().updateMipmap(renderer); + } + + for (var inputName in this.inputLinks) { + var link = this.inputLinks[inputName]; + link.node.removeReference(link.pin); + } + + this._rendering = false; + this._rendered = true; + + this.trigger('afterrender', renderer); + }, + + // TODO Remove parameter function callback + updateParameter: function (outputName, renderer) { + var outputInfo = this.outputs[outputName]; + var parameters = outputInfo.parameters; + var parametersCopy = outputInfo._parametersCopy; + if (!parametersCopy) { + parametersCopy = outputInfo._parametersCopy = {}; + } + if (parameters) { + for (var key in parameters) { + if (key !== 'width' && key !== 'height') { + parametersCopy[key] = parameters[key]; + } + } + } + var width, height; + if (parameters.width instanceof Function) { + width = parameters.width.call(this, renderer); + } + else { + width = parameters.width; + } + if (parameters.height instanceof Function) { + height = parameters.height.call(this, renderer); + } + else { + height = parameters.height; + } + width = Math.ceil(width); + height = Math.ceil(height); + if ( + parametersCopy.width !== width + || parametersCopy.height !== height + ) { + if (this._outputTextures[outputName]) { + this._outputTextures[outputName].dispose(renderer); + } + } + parametersCopy.width = width; + parametersCopy.height = height; + + return parametersCopy; + }, + + /** + * Set parameter + * @param {string} name + * @param {} value + */ + setParameter: function (name, value) { + this.pass.setUniform(name, value); + }, + /** + * Get parameter value + * @param {string} name + * @return {} + */ + getParameter: function (name) { + return this.pass.getUniform(name); + }, + /** + * Set parameters + * @param {Object} obj + */ + setParameters: function (obj) { + for (var name in obj) { + this.setParameter(name, obj[name]); + } + }, + // /** + // * Set shader code + // * @param {string} shaderStr + // */ + // setShader: function (shaderStr) { + // var material = this.pass.material; + // material.shader.setFragment(shaderStr); + // material.attachShader(material.shader, true); + // }, + /** + * Proxy of pass.material.define('fragment', xxx); + * @param {string} symbol + * @param {number} [val] + */ + define: function (symbol, val) { + this.pass.material.define('fragment', symbol, val); + }, + + /** + * Proxy of pass.material.undefine('fragment', xxx) + * @param {string} symbol + */ + undefine: function (symbol) { + this.pass.material.undefine('fragment', symbol); + }, + + removeReference: function (outputName) { + this._outputReferences[outputName]--; + if (this._outputReferences[outputName] === 0) { + var outputInfo = this.outputs[outputName]; + if (outputInfo.keepLastFrame) { + if (this._prevOutputTextures[outputName]) { + this._compositor.releaseTexture(this._prevOutputTextures[outputName]); + } + this._prevOutputTextures[outputName] = this._outputTextures[outputName]; + } + else { + // Output of this node have alreay been used by all other nodes + // Put the texture back to the pool. + this._compositor.releaseTexture(this._outputTextures[outputName]); + } + } + }, + + clear: function () { + __WEBPACK_IMPORTED_MODULE_1__CompositorNode__["a" /* default */].prototype.clear.call(this); + + // Default disable all texture + this.pass.material.disableTexturesAll(); + } +}); + +/* harmony default export */ __webpack_exports__["a"] = (FilterNode); + + +/***/ }), +/* 184 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony export (immutable) */ __webpack_exports__["a"] = register; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__source_compositor_coloradjust_glsl_js__ = __webpack_require__(185); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__source_compositor_blur_glsl_js__ = __webpack_require__(87); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__source_compositor_lum_glsl_js__ = __webpack_require__(186); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__source_compositor_lut_glsl_js__ = __webpack_require__(88); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4__source_compositor_vignette_glsl_js__ = __webpack_require__(187); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_5__source_compositor_output_glsl_js__ = __webpack_require__(89); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_6__source_compositor_bright_glsl_js__ = __webpack_require__(90); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_7__source_compositor_downsample_glsl_js__ = __webpack_require__(91); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_8__source_compositor_upsample_glsl_js__ = __webpack_require__(92); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_9__source_compositor_hdr_glsl_js__ = __webpack_require__(93); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_10__source_compositor_lensflare_glsl_js__ = __webpack_require__(188); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_11__source_compositor_blend_glsl_js__ = __webpack_require__(94); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_12__source_compositor_fxaa_glsl_js__ = __webpack_require__(95); + + + + + + + + + + + + + +// import fxaa3Essl from './source/compositor/fxaa3.glsl.js'; + +// TODO Must export a module and be used in the other modules. Or it will be tree shaked +function register(Shader) { + // Some build in shaders + Shader['import'](__WEBPACK_IMPORTED_MODULE_0__source_compositor_coloradjust_glsl_js__["a" /* default */]); + Shader['import'](__WEBPACK_IMPORTED_MODULE_1__source_compositor_blur_glsl_js__["a" /* default */]); + Shader['import'](__WEBPACK_IMPORTED_MODULE_2__source_compositor_lum_glsl_js__["a" /* default */]); + Shader['import'](__WEBPACK_IMPORTED_MODULE_3__source_compositor_lut_glsl_js__["a" /* default */]); + Shader['import'](__WEBPACK_IMPORTED_MODULE_4__source_compositor_vignette_glsl_js__["a" /* default */]); + Shader['import'](__WEBPACK_IMPORTED_MODULE_5__source_compositor_output_glsl_js__["a" /* default */]); + Shader['import'](__WEBPACK_IMPORTED_MODULE_6__source_compositor_bright_glsl_js__["a" /* default */]); + Shader['import'](__WEBPACK_IMPORTED_MODULE_7__source_compositor_downsample_glsl_js__["a" /* default */]); + Shader['import'](__WEBPACK_IMPORTED_MODULE_8__source_compositor_upsample_glsl_js__["a" /* default */]); + Shader['import'](__WEBPACK_IMPORTED_MODULE_9__source_compositor_hdr_glsl_js__["a" /* default */]); + Shader['import'](__WEBPACK_IMPORTED_MODULE_10__source_compositor_lensflare_glsl_js__["a" /* default */]); + Shader['import'](__WEBPACK_IMPORTED_MODULE_11__source_compositor_blend_glsl_js__["a" /* default */]); + + Shader['import'](__WEBPACK_IMPORTED_MODULE_12__source_compositor_fxaa_glsl_js__["a" /* default */]); + +} + +/***/ }), +/* 185 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony default export */ __webpack_exports__["a"] = ("@export clay.compositor.coloradjust\nvarying vec2 v_Texcoord;\nuniform sampler2D texture;\nuniform float brightness : 0.0;\nuniform float contrast : 1.0;\nuniform float exposure : 0.0;\nuniform float gamma : 1.0;\nuniform float saturation : 1.0;\nconst vec3 w = vec3(0.2125, 0.7154, 0.0721);\nvoid main()\n{\n vec4 tex = texture2D( texture, v_Texcoord);\n vec3 color = clamp(tex.rgb + vec3(brightness), 0.0, 1.0);\n color = clamp( (color-vec3(0.5))*contrast+vec3(0.5), 0.0, 1.0);\n color = clamp( color * pow(2.0, exposure), 0.0, 1.0);\n color = clamp( pow(color, vec3(gamma)), 0.0, 1.0);\n float luminance = dot( color, w );\n color = mix(vec3(luminance), color, saturation);\n gl_FragColor = vec4(color, tex.a);\n}\n@end\n@export clay.compositor.brightness\nvarying vec2 v_Texcoord;\nuniform sampler2D texture;\nuniform float brightness : 0.0;\nvoid main()\n{\n vec4 tex = texture2D( texture, v_Texcoord);\n vec3 color = tex.rgb + vec3(brightness);\n gl_FragColor = vec4(color, tex.a);\n}\n@end\n@export clay.compositor.contrast\nvarying vec2 v_Texcoord;\nuniform sampler2D texture;\nuniform float contrast : 1.0;\nvoid main()\n{\n vec4 tex = texture2D( texture, v_Texcoord);\n vec3 color = (tex.rgb-vec3(0.5))*contrast+vec3(0.5);\n gl_FragColor = vec4(color, tex.a);\n}\n@end\n@export clay.compositor.exposure\nvarying vec2 v_Texcoord;\nuniform sampler2D texture;\nuniform float exposure : 0.0;\nvoid main()\n{\n vec4 tex = texture2D(texture, v_Texcoord);\n vec3 color = tex.rgb * pow(2.0, exposure);\n gl_FragColor = vec4(color, tex.a);\n}\n@end\n@export clay.compositor.gamma\nvarying vec2 v_Texcoord;\nuniform sampler2D texture;\nuniform float gamma : 1.0;\nvoid main()\n{\n vec4 tex = texture2D(texture, v_Texcoord);\n vec3 color = pow(tex.rgb, vec3(gamma));\n gl_FragColor = vec4(color, tex.a);\n}\n@end\n@export clay.compositor.saturation\nvarying vec2 v_Texcoord;\nuniform sampler2D texture;\nuniform float saturation : 1.0;\nconst vec3 w = vec3(0.2125, 0.7154, 0.0721);\nvoid main()\n{\n vec4 tex = texture2D(texture, v_Texcoord);\n vec3 color = tex.rgb;\n float luminance = dot(color, w);\n color = mix(vec3(luminance), color, saturation);\n gl_FragColor = vec4(color, tex.a);\n}\n@end"); + + +/***/ }), +/* 186 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony default export */ __webpack_exports__["a"] = ("@export clay.compositor.hdr.log_lum\nvarying vec2 v_Texcoord;\nuniform sampler2D texture;\nconst vec3 w = vec3(0.2125, 0.7154, 0.0721);\n@import clay.util.rgbm\nvoid main()\n{\n vec4 tex = decodeHDR(texture2D(texture, v_Texcoord));\n float luminance = dot(tex.rgb, w);\n luminance = log(luminance + 0.001);\n gl_FragColor = encodeHDR(vec4(vec3(luminance), 1.0));\n}\n@end\n@export clay.compositor.hdr.lum_adaption\nvarying vec2 v_Texcoord;\nuniform sampler2D adaptedLum;\nuniform sampler2D currentLum;\nuniform float frameTime : 0.02;\n@import clay.util.rgbm\nvoid main()\n{\n float fAdaptedLum = decodeHDR(texture2D(adaptedLum, vec2(0.5, 0.5))).r;\n float fCurrentLum = exp(encodeHDR(texture2D(currentLum, vec2(0.5, 0.5))).r);\n fAdaptedLum += (fCurrentLum - fAdaptedLum) * (1.0 - pow(0.98, 30.0 * frameTime));\n gl_FragColor = encodeHDR(vec4(vec3(fAdaptedLum), 1.0));\n}\n@end\n@export clay.compositor.lum\nvarying vec2 v_Texcoord;\nuniform sampler2D texture;\nconst vec3 w = vec3(0.2125, 0.7154, 0.0721);\nvoid main()\n{\n vec4 tex = texture2D( texture, v_Texcoord );\n float luminance = dot(tex.rgb, w);\n gl_FragColor = vec4(vec3(luminance), 1.0);\n}\n@end"); + + +/***/ }), +/* 187 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony default export */ __webpack_exports__["a"] = ("@export clay.compositor.vignette\n#define OUTPUT_ALPHA\nvarying vec2 v_Texcoord;\nuniform sampler2D texture;\nuniform float darkness: 1;\nuniform float offset: 1;\n@import clay.util.rgbm\nvoid main()\n{\n vec4 texel = decodeHDR(texture2D(texture, v_Texcoord));\n gl_FragColor.rgb = texel.rgb;\n vec2 uv = (v_Texcoord - vec2(0.5)) * vec2(offset);\n gl_FragColor = encodeHDR(vec4(mix(texel.rgb, vec3(1.0 - darkness), dot(uv, uv)), texel.a));\n}\n@end"); + + +/***/ }), +/* 188 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony default export */ __webpack_exports__["a"] = ("@export clay.compositor.lensflare\n#define SAMPLE_NUMBER 8\nuniform sampler2D texture;\nuniform sampler2D lenscolor;\nuniform vec2 textureSize : [512, 512];\nuniform float dispersal : 0.3;\nuniform float haloWidth : 0.4;\nuniform float distortion : 1.0;\nvarying vec2 v_Texcoord;\n@import clay.util.rgbm\nvec4 textureDistorted(\n in vec2 texcoord,\n in vec2 direction,\n in vec3 distortion\n) {\n return vec4(\n decodeHDR(texture2D(texture, texcoord + direction * distortion.r)).r,\n decodeHDR(texture2D(texture, texcoord + direction * distortion.g)).g,\n decodeHDR(texture2D(texture, texcoord + direction * distortion.b)).b,\n 1.0\n );\n}\nvoid main()\n{\n vec2 texcoord = -v_Texcoord + vec2(1.0); vec2 textureOffset = 1.0 / textureSize;\n vec2 ghostVec = (vec2(0.5) - texcoord) * dispersal;\n vec2 haloVec = normalize(ghostVec) * haloWidth;\n vec3 distortion = vec3(-textureOffset.x * distortion, 0.0, textureOffset.x * distortion);\n vec4 result = vec4(0.0);\n for (int i = 0; i < SAMPLE_NUMBER; i++)\n {\n vec2 offset = fract(texcoord + ghostVec * float(i));\n float weight = length(vec2(0.5) - offset) / length(vec2(0.5));\n weight = pow(1.0 - weight, 10.0);\n result += textureDistorted(offset, normalize(ghostVec), distortion) * weight;\n }\n result *= texture2D(lenscolor, vec2(length(vec2(0.5) - texcoord)) / length(vec2(0.5)));\n float weight = length(vec2(0.5) - fract(texcoord + haloVec)) / length(vec2(0.5));\n weight = pow(1.0 - weight, 10.0);\n vec2 offset = fract(texcoord + haloVec);\n result += textureDistorted(offset, normalize(ghostVec), distortion) * weight;\n gl_FragColor = result;\n}\n@end"); + + +/***/ }), +/* 189 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_claygl_src_math_Matrix4__ = __webpack_require__(9); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_claygl_src_math_Vector3__ = __webpack_require__(3); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2_claygl_src_Texture2D__ = __webpack_require__(5); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3_claygl_src_Texture__ = __webpack_require__(4); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4_claygl_src_compositor_Pass__ = __webpack_require__(16); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_5_claygl_src_Shader__ = __webpack_require__(8); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_6_claygl_src_FrameBuffer__ = __webpack_require__(10); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_7__halton__ = __webpack_require__(49); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_8__SSAO_glsl_js__ = __webpack_require__(190); + + + + + + + + + + +__WEBPACK_IMPORTED_MODULE_5_claygl_src_Shader__["a" /* default */].import(__WEBPACK_IMPORTED_MODULE_8__SSAO_glsl_js__["a" /* default */]); + +function generateNoiseData(size) { + var data = new Uint8Array(size * size * 4); + var n = 0; + var v3 = new __WEBPACK_IMPORTED_MODULE_1_claygl_src_math_Vector3__["a" /* default */](); + + for (var i = 0; i < size; i++) { + for (var j = 0; j < size; j++) { + v3.set(Math.random() * 2 - 1, Math.random() * 2 - 1, 0).normalize(); + data[n++] = (v3.x * 0.5 + 0.5) * 255; + data[n++] = (v3.y * 0.5 + 0.5) * 255; + data[n++] = 0; + data[n++] = 255; + } + } + return data; +} + +function generateNoiseTexture(size) { + return new __WEBPACK_IMPORTED_MODULE_2_claygl_src_Texture2D__["a" /* default */]({ + pixels: generateNoiseData(size), + wrapS: __WEBPACK_IMPORTED_MODULE_3_claygl_src_Texture__["a" /* default */].REPEAT, + wrapT: __WEBPACK_IMPORTED_MODULE_3_claygl_src_Texture__["a" /* default */].REPEAT, + width: size, + height: size + }); +} + +function generateKernel(size, offset, hemisphere) { + var kernel = new Float32Array(size * 3); + offset = offset || 0; + for (var i = 0; i < size; i++) { + var phi = Object(__WEBPACK_IMPORTED_MODULE_7__halton__["a" /* default */])(i + offset, 2) * (hemisphere ? 1 : 2) * Math.PI; + var theta = Object(__WEBPACK_IMPORTED_MODULE_7__halton__["a" /* default */])(i + offset, 3) * Math.PI; + var r = Math.random(); + var x = Math.cos(phi) * Math.sin(theta) * r; + var y = Math.cos(theta) * r; + var z = Math.sin(phi) * Math.sin(theta) * r; + + kernel[i * 3] = x; + kernel[i * 3 + 1] = y; + kernel[i * 3 + 2] = z; + } + return kernel; + + // var kernel = new Float32Array(size * 3); + // var v3 = new Vector3(); + // for (var i = 0; i < size; i++) { + // v3.set(Math.random() * 2 - 1, Math.random() * 2 - 1, Math.random()) + // .normalize().scale(Math.random()); + // kernel[i * 3] = v3.x; + // kernel[i * 3 + 1] = v3.y; + // kernel[i * 3 + 2] = v3.z; + // } + // return kernel; +} + +function SSAOPass(opt) { + opt = opt || {}; + + this._ssaoPass = new __WEBPACK_IMPORTED_MODULE_4_claygl_src_compositor_Pass__["a" /* default */]({ + fragment: __WEBPACK_IMPORTED_MODULE_5_claygl_src_Shader__["a" /* default */].source('ecgl.ssao.estimate') + }); + this._blurPass = new __WEBPACK_IMPORTED_MODULE_4_claygl_src_compositor_Pass__["a" /* default */]({ + fragment: __WEBPACK_IMPORTED_MODULE_5_claygl_src_Shader__["a" /* default */].source('ecgl.ssao.blur') + }); + this._framebuffer = new __WEBPACK_IMPORTED_MODULE_6_claygl_src_FrameBuffer__["a" /* default */]({ + depthBuffer: false + }); + + this._ssaoTexture = new __WEBPACK_IMPORTED_MODULE_2_claygl_src_Texture2D__["a" /* default */](); + this._blurTexture = new __WEBPACK_IMPORTED_MODULE_2_claygl_src_Texture2D__["a" /* default */](); + this._blurTexture2 = new __WEBPACK_IMPORTED_MODULE_2_claygl_src_Texture2D__["a" /* default */](); + + this._depthTex = opt.depthTexture; + this._normalTex = opt.normalTexture; + + this.setNoiseSize(4); + this.setKernelSize(opt.kernelSize || 12); + if (opt.radius != null) { + this.setParameter('radius', opt.radius); + } + if (opt.power != null) { + this.setParameter('power', opt.power); + } + + if (!this._normalTex) { + this._ssaoPass.material.disableTexture('normalTex'); + this._blurPass.material.disableTexture('normalTex'); + } + if (!this._depthTex) { + this._blurPass.material.disableTexture('depthTex'); + } + + this._blurPass.material.setUniform('normalTex', this._normalTex); + this._blurPass.material.setUniform('depthTex', this._depthTex); +} + +SSAOPass.prototype.setDepthTexture = function (depthTex) { + this._depthTex = depthTex; +}; + +SSAOPass.prototype.setNormalTexture = function (normalTex) { + this._normalTex = normalTex; + this._ssaoPass.material[normalTex ? 'enableTexture' : 'disableTexture']('normalTex'); + // Switch between hemisphere and shere kernel. + this.setKernelSize(this._kernelSize); +}; + +SSAOPass.prototype.update = function (renderer, camera, frame) { + var width = renderer.getWidth(); + var height = renderer.getHeight(); + + var ssaoPass = this._ssaoPass; + var blurPass = this._blurPass; + + ssaoPass.setUniform('kernel', this._kernels[frame % this._kernels.length]); + ssaoPass.setUniform('depthTex', this._depthTex); + if (this._normalTex != null) { + ssaoPass.setUniform('normalTex', this._normalTex); + } + ssaoPass.setUniform('depthTexSize', [this._depthTex.width, this._depthTex.height]); + + var viewInverseTranspose = new __WEBPACK_IMPORTED_MODULE_0_claygl_src_math_Matrix4__["a" /* default */](); + __WEBPACK_IMPORTED_MODULE_0_claygl_src_math_Matrix4__["a" /* default */].transpose(viewInverseTranspose, camera.worldTransform); + + ssaoPass.setUniform('projection', camera.projectionMatrix.array); + ssaoPass.setUniform('projectionInv', camera.invProjectionMatrix.array); + ssaoPass.setUniform('viewInverseTranspose', viewInverseTranspose.array); + + var ssaoTexture = this._ssaoTexture; + var blurTexture = this._blurTexture; + var blurTexture2 = this._blurTexture2; + + ssaoTexture.width = width / 2; + ssaoTexture.height = height / 2; + blurTexture.width = width; + blurTexture.height = height; + blurTexture2.width = width; + blurTexture2.height = height; + + this._framebuffer.attach(ssaoTexture); + this._framebuffer.bind(renderer); + renderer.gl.clearColor(1, 1, 1, 1); + renderer.gl.clear(renderer.gl.COLOR_BUFFER_BIT); + ssaoPass.render(renderer); + + blurPass.setUniform('textureSize', [width / 2, height / 2]); + blurPass.setUniform('projection', camera.projectionMatrix.array); + this._framebuffer.attach(blurTexture); + blurPass.setUniform('direction', 0); + blurPass.setUniform('ssaoTexture', ssaoTexture); + blurPass.render(renderer); + + this._framebuffer.attach(blurTexture2); + blurPass.setUniform('textureSize', [width, height]); + blurPass.setUniform('direction', 1); + blurPass.setUniform('ssaoTexture', blurTexture); + blurPass.render(renderer); + + this._framebuffer.unbind(renderer); + + // Restore clear + var clearColor = renderer.clearColor; + renderer.gl.clearColor(clearColor[0], clearColor[1], clearColor[2], clearColor[3]); +}; + +SSAOPass.prototype.getTargetTexture = function () { + return this._blurTexture2; +} + +SSAOPass.prototype.setParameter = function (name, val) { + if (name === 'noiseTexSize') { + this.setNoiseSize(val); + } + else if (name === 'kernelSize') { + this.setKernelSize(val); + } + else if (name === 'intensity') { + this._ssaoPass.material.set('intensity', val); + } + else { + this._ssaoPass.setUniform(name, val); + } +}; + +SSAOPass.prototype.setKernelSize = function (size) { + this._kernelSize = size; + this._ssaoPass.material.define('fragment', 'KERNEL_SIZE', size); + this._kernels = this._kernels || []; + for (var i = 0; i < 30; i++) { + this._kernels[i] = generateKernel(size, i * size, !!this._normalTex); + } +}; + +SSAOPass.prototype.setNoiseSize = function (size) { + var texture = this._ssaoPass.getUniform('noiseTex'); + if (!texture) { + texture = generateNoiseTexture(size); + this._ssaoPass.setUniform('noiseTex', generateNoiseTexture(size)); + } + else { + texture.data = generateNoiseData(size); + texture.width = texture.height = size; + texture.dirty(); + } + + this._ssaoPass.setUniform('noiseTexSize', [size, size]); +}; + +SSAOPass.prototype.dispose = function (renderer) { + this._blurTexture.dispose(renderer); + this._ssaoTexture.dispose(renderer); + this._blurTexture2.dispose(renderer); +}; + +/* harmony default export */ __webpack_exports__["a"] = (SSAOPass); + +/***/ }), +/* 190 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony default export */ __webpack_exports__["a"] = ("@export ecgl.ssao.estimate\n\nuniform sampler2D depthTex;\n\nuniform sampler2D normalTex;\n\nuniform sampler2D noiseTex;\n\nuniform vec2 depthTexSize;\n\nuniform vec2 noiseTexSize;\n\nuniform mat4 projection;\n\nuniform mat4 projectionInv;\n\nuniform mat4 viewInverseTranspose;\n\nuniform vec3 kernel[KERNEL_SIZE];\n\nuniform float radius : 1;\n\nuniform float power : 1;\n\nuniform float bias: 1e-2;\n\nuniform float intensity: 1.0;\n\nvarying vec2 v_Texcoord;\n\nfloat ssaoEstimator(in vec3 originPos, in mat3 kernelBasis) {\n float occlusion = 0.0;\n\n for (int i = 0; i < KERNEL_SIZE; i++) {\n vec3 samplePos = kernel[i];\n#ifdef NORMALTEX_ENABLED\n samplePos = kernelBasis * samplePos;\n#endif\n samplePos = samplePos * radius + originPos;\n\n vec4 texCoord = projection * vec4(samplePos, 1.0);\n texCoord.xy /= texCoord.w;\n\n vec4 depthTexel = texture2D(depthTex, texCoord.xy * 0.5 + 0.5);\n\n float sampleDepth = depthTexel.r * 2.0 - 1.0;\n if (projection[3][3] == 0.0) {\n sampleDepth = projection[3][2] / (sampleDepth * projection[2][3] - projection[2][2]);\n }\n else {\n sampleDepth = (sampleDepth - projection[3][2]) / projection[2][2];\n }\n \n float rangeCheck = smoothstep(0.0, 1.0, radius / abs(originPos.z - sampleDepth));\n occlusion += rangeCheck * step(samplePos.z, sampleDepth - bias);\n }\n#ifdef NORMALTEX_ENABLED\n occlusion = 1.0 - occlusion / float(KERNEL_SIZE);\n#else\n occlusion = 1.0 - clamp((occlusion / float(KERNEL_SIZE) - 0.6) * 2.5, 0.0, 1.0);\n#endif\n return pow(occlusion, power);\n}\n\nvoid main()\n{\n\n vec4 depthTexel = texture2D(depthTex, v_Texcoord);\n\n#ifdef NORMALTEX_ENABLED\n vec4 tex = texture2D(normalTex, v_Texcoord);\n if (dot(tex.rgb, tex.rgb) == 0.0) {\n gl_FragColor = vec4(1.0);\n return;\n }\n vec3 N = tex.rgb * 2.0 - 1.0;\n N = (viewInverseTranspose * vec4(N, 0.0)).xyz;\n\n vec2 noiseTexCoord = depthTexSize / vec2(noiseTexSize) * v_Texcoord;\n vec3 rvec = texture2D(noiseTex, noiseTexCoord).rgb * 2.0 - 1.0;\n vec3 T = normalize(rvec - N * dot(rvec, N));\n vec3 BT = normalize(cross(N, T));\n mat3 kernelBasis = mat3(T, BT, N);\n#else\n if (depthTexel.r > 0.99999) {\n gl_FragColor = vec4(1.0);\n return;\n }\n mat3 kernelBasis;\n#endif\n\n float z = depthTexel.r * 2.0 - 1.0;\n\n vec4 projectedPos = vec4(v_Texcoord * 2.0 - 1.0, z, 1.0);\n vec4 p4 = projectionInv * projectedPos;\n\n vec3 position = p4.xyz / p4.w;\n\n float ao = ssaoEstimator(position, kernelBasis);\n ao = clamp(1.0 - (1.0 - ao) * intensity, 0.0, 1.0);\n gl_FragColor = vec4(vec3(ao), 1.0);\n}\n\n@end\n\n\n@export ecgl.ssao.blur\n#define SHADER_NAME SSAO_BLUR\n\nuniform sampler2D ssaoTexture;\n\n#ifdef NORMALTEX_ENABLED\nuniform sampler2D normalTex;\n#endif\n\nvarying vec2 v_Texcoord;\n\nuniform vec2 textureSize;\nuniform float blurSize : 1.0;\n\nuniform int direction: 0.0;\n\n#ifdef DEPTHTEX_ENABLED\nuniform sampler2D depthTex;\nuniform mat4 projection;\nuniform float depthRange : 0.5;\n\nfloat getLinearDepth(vec2 coord)\n{\n float depth = texture2D(depthTex, coord).r * 2.0 - 1.0;\n return projection[3][2] / (depth * projection[2][3] - projection[2][2]);\n}\n#endif\n\nvoid main()\n{\n float kernel[5];\n kernel[0] = 0.122581;\n kernel[1] = 0.233062;\n kernel[2] = 0.288713;\n kernel[3] = 0.233062;\n kernel[4] = 0.122581;\n\n vec2 off = vec2(0.0);\n if (direction == 0) {\n off[0] = blurSize / textureSize.x;\n }\n else {\n off[1] = blurSize / textureSize.y;\n }\n\n vec2 coord = v_Texcoord;\n\n float sum = 0.0;\n float weightAll = 0.0;\n\n#ifdef NORMALTEX_ENABLED\n vec3 centerNormal = texture2D(normalTex, v_Texcoord).rgb * 2.0 - 1.0;\n#endif\n#if defined(DEPTHTEX_ENABLED)\n float centerDepth = getLinearDepth(v_Texcoord);\n#endif\n\n for (int i = 0; i < 5; i++) {\n vec2 coord = clamp(v_Texcoord + vec2(float(i) - 2.0) * off, vec2(0.0), vec2(1.0));\n\n float w = kernel[i];\n#ifdef NORMALTEX_ENABLED\n vec3 normal = texture2D(normalTex, coord).rgb * 2.0 - 1.0;\n w *= clamp(dot(normal, centerNormal), 0.0, 1.0);\n#endif\n#ifdef DEPTHTEX_ENABLED\n float d = getLinearDepth(coord);\n w *= (1.0 - smoothstep(abs(centerDepth - d) / depthRange, 0.0, 1.0));\n#endif\n\n weightAll += w;\n sum += texture2D(ssaoTexture, coord).r * w;\n }\n\n gl_FragColor = vec4(vec3(sum / weightAll), 1.0);\n}\n\n@end\n"); + + +/***/ }), +/* 191 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_claygl_src_math_Matrix4__ = __webpack_require__(9); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_claygl_src_math_Vector3__ = __webpack_require__(3); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2_claygl_src_Texture2D__ = __webpack_require__(5); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3_claygl_src_Texture__ = __webpack_require__(4); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4_claygl_src_compositor_Pass__ = __webpack_require__(16); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_5_claygl_src_Shader__ = __webpack_require__(8); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_6_claygl_src_FrameBuffer__ = __webpack_require__(10); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_7__halton__ = __webpack_require__(49); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_8_claygl_src_util_cubemap__ = __webpack_require__(77); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_9__SSR_glsl_js__ = __webpack_require__(192); + + + + + + + + + + + + +__WEBPACK_IMPORTED_MODULE_5_claygl_src_Shader__["a" /* default */].import(__WEBPACK_IMPORTED_MODULE_9__SSR_glsl_js__["a" /* default */]); + +function SSRPass(opt) { + opt = opt || {}; + + this._ssrPass = new __WEBPACK_IMPORTED_MODULE_4_claygl_src_compositor_Pass__["a" /* default */]({ + fragment: __WEBPACK_IMPORTED_MODULE_5_claygl_src_Shader__["a" /* default */].source('ecgl.ssr.main'), + clearColor: [0, 0, 0, 0] + }); + this._blurPass1 = new __WEBPACK_IMPORTED_MODULE_4_claygl_src_compositor_Pass__["a" /* default */]({ + fragment: __WEBPACK_IMPORTED_MODULE_5_claygl_src_Shader__["a" /* default */].source('ecgl.ssr.blur'), + clearColor: [0, 0, 0, 0] + }); + this._blurPass2 = new __WEBPACK_IMPORTED_MODULE_4_claygl_src_compositor_Pass__["a" /* default */]({ + fragment: __WEBPACK_IMPORTED_MODULE_5_claygl_src_Shader__["a" /* default */].source('ecgl.ssr.blur'), + clearColor: [0, 0, 0, 0] + }); + this._blendPass = new __WEBPACK_IMPORTED_MODULE_4_claygl_src_compositor_Pass__["a" /* default */]({ + fragment: __WEBPACK_IMPORTED_MODULE_5_claygl_src_Shader__["a" /* default */].source('clay.compositor.blend') + }); + this._blendPass.material.disableTexturesAll(); + this._blendPass.material.enableTexture(['texture1', 'texture2']); + + this._ssrPass.setUniform('gBufferTexture1', opt.normalTexture); + this._ssrPass.setUniform('gBufferTexture2', opt.depthTexture); + // this._ssrPass.setUniform('gBufferTexture3', opt.albedoTexture); + + this._blurPass1.setUniform('gBufferTexture1', opt.normalTexture); + this._blurPass1.setUniform('gBufferTexture2', opt.depthTexture); + + this._blurPass2.setUniform('gBufferTexture1', opt.normalTexture); + this._blurPass2.setUniform('gBufferTexture2', opt.depthTexture); + + this._blurPass2.material.define('fragment', 'VERTICAL'); + this._blurPass2.material.define('fragment', 'BLEND'); + + this._ssrTexture = new __WEBPACK_IMPORTED_MODULE_2_claygl_src_Texture2D__["a" /* default */]({ + type: __WEBPACK_IMPORTED_MODULE_3_claygl_src_Texture__["a" /* default */].HALF_FLOAT + }); + this._texture2 = new __WEBPACK_IMPORTED_MODULE_2_claygl_src_Texture2D__["a" /* default */]({ + type: __WEBPACK_IMPORTED_MODULE_3_claygl_src_Texture__["a" /* default */].HALF_FLOAT + }); + this._texture3 = new __WEBPACK_IMPORTED_MODULE_2_claygl_src_Texture2D__["a" /* default */]({ + type: __WEBPACK_IMPORTED_MODULE_3_claygl_src_Texture__["a" /* default */].HALF_FLOAT + }); + this._prevTexture = new __WEBPACK_IMPORTED_MODULE_2_claygl_src_Texture2D__["a" /* default */]({ + type: __WEBPACK_IMPORTED_MODULE_3_claygl_src_Texture__["a" /* default */].HALF_FLOAT + }); + this._currentTexture = new __WEBPACK_IMPORTED_MODULE_2_claygl_src_Texture2D__["a" /* default */]({ + type: __WEBPACK_IMPORTED_MODULE_3_claygl_src_Texture__["a" /* default */].HALF_FLOAT + }); + + this._frameBuffer = new __WEBPACK_IMPORTED_MODULE_6_claygl_src_FrameBuffer__["a" /* default */]({ + depthBuffer: false + }); + + this._normalDistribution = null; + + this._totalSamples = 256; + this._samplePerFrame = 4; + + this._ssrPass.material.define('fragment', 'SAMPLE_PER_FRAME', this._samplePerFrame); + this._ssrPass.material.define('fragment', 'TOTAL_SAMPLES', this._totalSamples); + + this._downScale = 1; +} + +SSRPass.prototype.setAmbientCubemap = function (specularCubemap, specularIntensity) { + this._ssrPass.material.set('specularCubemap', specularCubemap); + this._ssrPass.material.set('specularIntensity', specularIntensity); + + var enableSpecularMap = specularCubemap && specularIntensity; + this._ssrPass.material[enableSpecularMap ? 'enableTexture' : 'disableTexture']('specularCubemap'); +}; + +SSRPass.prototype.update = function (renderer, camera, sourceTexture, frame) { + var width = renderer.getWidth(); + var height = renderer.getHeight(); + var ssrTexture = this._ssrTexture; + var texture2 = this._texture2; + var texture3 = this._texture3; + ssrTexture.width = this._prevTexture.width = this._currentTexture.width = width / this._downScale; + ssrTexture.height = this._prevTexture.height = this._currentTexture.height = height / this._downScale; + + texture2.width = texture3.width = width; + texture2.height = texture3.height = height; + + var frameBuffer = this._frameBuffer; + + var ssrPass = this._ssrPass; + var blurPass1 = this._blurPass1; + var blurPass2 = this._blurPass2; + var blendPass = this._blendPass; + + var toViewSpace = new __WEBPACK_IMPORTED_MODULE_0_claygl_src_math_Matrix4__["a" /* default */](); + var toWorldSpace = new __WEBPACK_IMPORTED_MODULE_0_claygl_src_math_Matrix4__["a" /* default */](); + __WEBPACK_IMPORTED_MODULE_0_claygl_src_math_Matrix4__["a" /* default */].transpose(toViewSpace, camera.worldTransform); + __WEBPACK_IMPORTED_MODULE_0_claygl_src_math_Matrix4__["a" /* default */].transpose(toWorldSpace, camera.viewMatrix); + + ssrPass.setUniform('sourceTexture', sourceTexture); + ssrPass.setUniform('projection', camera.projectionMatrix.array); + ssrPass.setUniform('projectionInv', camera.invProjectionMatrix.array); + ssrPass.setUniform('toViewSpace', toViewSpace.array); + ssrPass.setUniform('toWorldSpace', toWorldSpace.array); + ssrPass.setUniform('nearZ', camera.near); + + var percent = frame / this._totalSamples * this._samplePerFrame; + ssrPass.setUniform('jitterOffset', percent); + ssrPass.setUniform('sampleOffset', frame * this._samplePerFrame); + + blurPass1.setUniform('textureSize', [ssrTexture.width, ssrTexture.height]); + blurPass2.setUniform('textureSize', [width, height]); + blurPass2.setUniform('sourceTexture', sourceTexture); + + blurPass1.setUniform('projection', camera.projectionMatrix.array); + blurPass2.setUniform('projection', camera.projectionMatrix.array); + + frameBuffer.attach(ssrTexture); + frameBuffer.bind(renderer); + ssrPass.render(renderer); + + if (this._physicallyCorrect) { + frameBuffer.attach(this._currentTexture); + blendPass.setUniform('texture1', this._prevTexture); + blendPass.setUniform('texture2', ssrTexture); + blendPass.material.set({ + 'weight1': frame >= 1 ? 0.95 : 0, + 'weight2': frame >= 1 ? 0.05 : 1 + // weight1: frame >= 1 ? 1 : 0, + // weight2: 1 + }); + blendPass.render(renderer); + } + + frameBuffer.attach(texture2); + blurPass1.setUniform('texture', this._physicallyCorrect ? this._currentTexture : ssrTexture); + blurPass1.render(renderer); + + frameBuffer.attach(texture3); + blurPass2.setUniform('texture', texture2); + blurPass2.render(renderer); + frameBuffer.unbind(renderer); + + if (this._physicallyCorrect) { + var tmp = this._prevTexture; + this._prevTexture = this._currentTexture; + this._currentTexture = tmp; + } +}; + +SSRPass.prototype.getTargetTexture = function () { + return this._texture3; +}; + +SSRPass.prototype.setParameter = function (name, val) { + if (name === 'maxIteration') { + this._ssrPass.material.define('fragment', 'MAX_ITERATION', val); + } + else { + this._ssrPass.setUniform(name, val); + } +}; + +SSRPass.prototype.setPhysicallyCorrect = function (isPhysicallyCorrect) { + if (isPhysicallyCorrect) { + if (!this._normalDistribution) { + this._normalDistribution = __WEBPACK_IMPORTED_MODULE_8_claygl_src_util_cubemap__["a" /* default */].generateNormalDistribution(64, this._totalSamples); + } + this._ssrPass.material.define('fragment', 'PHYSICALLY_CORRECT'); + this._ssrPass.material.set('normalDistribution', this._normalDistribution); + this._ssrPass.material.set('normalDistributionSize', [64, this._totalSamples]); + } + else { + this._ssrPass.material.undefine('fragment', 'PHYSICALLY_CORRECT'); + } + + this._physicallyCorrect = isPhysicallyCorrect; +}; + +SSRPass.prototype.setSSAOTexture = function (texture) { + var blendPass = this._blurPass2; + if (texture) { + blendPass.material.enableTexture('ssaoTex'); + blendPass.material.set('ssaoTex', texture); + } + else { + blendPass.material.disableTexture('ssaoTex'); + } +}; + +SSRPass.prototype.isFinished = function (frame) { + if (this._physicallyCorrect) { + return frame > (this._totalSamples / this._samplePerFrame); + } + else { + return true; + } +}; + +SSRPass.prototype.dispose = function (renderer) { + this._ssrTexture.dispose(renderer); + this._texture2.dispose(renderer); + this._texture3.dispose(renderer); + this._prevTexture.dispose(renderer); + this._currentTexture.dispose(renderer); + this._frameBuffer.dispose(renderer); +}; + +/* harmony default export */ __webpack_exports__["a"] = (SSRPass); + +/***/ }), +/* 192 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony default export */ __webpack_exports__["a"] = ("@export ecgl.ssr.main\n\n#define SHADER_NAME SSR\n#define MAX_ITERATION 20;\n#define SAMPLE_PER_FRAME 5;\n#define TOTAL_SAMPLES 128;\n\nuniform sampler2D sourceTexture;\nuniform sampler2D gBufferTexture1;\nuniform sampler2D gBufferTexture2;\nuniform sampler2D gBufferTexture3;\nuniform samplerCube specularCubemap;\nuniform float specularIntensity: 1;\n\nuniform mat4 projection;\nuniform mat4 projectionInv;\nuniform mat4 toViewSpace;\nuniform mat4 toWorldSpace;\n\nuniform float maxRayDistance: 200;\n\nuniform float pixelStride: 16;\nuniform float pixelStrideZCutoff: 50; \nuniform float screenEdgeFadeStart: 0.9; \nuniform float eyeFadeStart : 0.2; uniform float eyeFadeEnd: 0.8; \nuniform float minGlossiness: 0.2; uniform float zThicknessThreshold: 1;\n\nuniform float nearZ;\nuniform vec2 viewportSize : VIEWPORT_SIZE;\n\nuniform float jitterOffset: 0;\n\nvarying vec2 v_Texcoord;\n\n#ifdef DEPTH_DECODE\n@import clay.util.decode_float\n#endif\n\n#ifdef PHYSICALLY_CORRECT\nuniform sampler2D normalDistribution;\nuniform float sampleOffset: 0;\nuniform vec2 normalDistributionSize;\n\nvec3 transformNormal(vec3 H, vec3 N) {\n vec3 upVector = N.y > 0.999 ? vec3(1.0, 0.0, 0.0) : vec3(0.0, 1.0, 0.0);\n vec3 tangentX = normalize(cross(N, upVector));\n vec3 tangentZ = cross(N, tangentX);\n return normalize(tangentX * H.x + N * H.y + tangentZ * H.z);\n}\nvec3 importanceSampleNormalGGX(float i, float roughness, vec3 N) {\n float p = fract((i + sampleOffset) / float(TOTAL_SAMPLES));\n vec3 H = texture2D(normalDistribution,vec2(roughness, p)).rgb;\n return transformNormal(H, N);\n}\nfloat G_Smith(float g, float ndv, float ndl) {\n float roughness = 1.0 - g;\n float k = roughness * roughness / 2.0;\n float G1V = ndv / (ndv * (1.0 - k) + k);\n float G1L = ndl / (ndl * (1.0 - k) + k);\n return G1L * G1V;\n}\nvec3 F_Schlick(float ndv, vec3 spec) {\n return spec + (1.0 - spec) * pow(1.0 - ndv, 5.0);\n}\n#endif\n\nfloat fetchDepth(sampler2D depthTexture, vec2 uv)\n{\n vec4 depthTexel = texture2D(depthTexture, uv);\n return depthTexel.r * 2.0 - 1.0;\n}\n\nfloat linearDepth(float depth)\n{\n if (projection[3][3] == 0.0) {\n return projection[3][2] / (depth * projection[2][3] - projection[2][2]);\n }\n else {\n return (depth - projection[3][2]) / projection[2][2];\n }\n}\n\nbool rayIntersectDepth(float rayZNear, float rayZFar, vec2 hitPixel)\n{\n if (rayZFar > rayZNear)\n {\n float t = rayZFar; rayZFar = rayZNear; rayZNear = t;\n }\n float cameraZ = linearDepth(fetchDepth(gBufferTexture2, hitPixel));\n return rayZFar <= cameraZ && rayZNear >= cameraZ - zThicknessThreshold;\n}\n\n\nbool traceScreenSpaceRay(\n vec3 rayOrigin, vec3 rayDir, float jitter,\n out vec2 hitPixel, out vec3 hitPoint, out float iterationCount\n)\n{\n float rayLength = ((rayOrigin.z + rayDir.z * maxRayDistance) > -nearZ)\n ? (-nearZ - rayOrigin.z) / rayDir.z : maxRayDistance;\n\n vec3 rayEnd = rayOrigin + rayDir * rayLength;\n\n vec4 H0 = projection * vec4(rayOrigin, 1.0);\n vec4 H1 = projection * vec4(rayEnd, 1.0);\n\n float k0 = 1.0 / H0.w, k1 = 1.0 / H1.w;\n\n vec3 Q0 = rayOrigin * k0, Q1 = rayEnd * k1;\n\n vec2 P0 = (H0.xy * k0 * 0.5 + 0.5) * viewportSize;\n vec2 P1 = (H1.xy * k1 * 0.5 + 0.5) * viewportSize;\n\n P1 += dot(P1 - P0, P1 - P0) < 0.0001 ? 0.01 : 0.0;\n vec2 delta = P1 - P0;\n\n bool permute = false;\n if (abs(delta.x) < abs(delta.y)) {\n permute = true;\n delta = delta.yx;\n P0 = P0.yx;\n P1 = P1.yx;\n }\n float stepDir = sign(delta.x);\n float invdx = stepDir / delta.x;\n\n vec3 dQ = (Q1 - Q0) * invdx;\n float dk = (k1 - k0) * invdx;\n\n vec2 dP = vec2(stepDir, delta.y * invdx);\n\n float strideScaler = 1.0 - min(1.0, -rayOrigin.z / pixelStrideZCutoff);\n float pixStride = 1.0 + strideScaler * pixelStride;\n\n dP *= pixStride; dQ *= pixStride; dk *= pixStride;\n\n vec4 pqk = vec4(P0, Q0.z, k0);\n vec4 dPQK = vec4(dP, dQ.z, dk);\n\n pqk += dPQK * jitter;\n float rayZFar = (dPQK.z * 0.5 + pqk.z) / (dPQK.w * 0.5 + pqk.w);\n float rayZNear;\n\n bool intersect = false;\n\n vec2 texelSize = 1.0 / viewportSize;\n\n iterationCount = 0.0;\n\n for (int i = 0; i < MAX_ITERATION; i++)\n {\n pqk += dPQK;\n\n rayZNear = rayZFar;\n rayZFar = (dPQK.z * 0.5 + pqk.z) / (dPQK.w * 0.5 + pqk.w);\n\n hitPixel = permute ? pqk.yx : pqk.xy;\n hitPixel *= texelSize;\n\n intersect = rayIntersectDepth(rayZNear, rayZFar, hitPixel);\n\n iterationCount += 1.0;\n\n dPQK *= 1.2;\n\n if (intersect) {\n break;\n }\n }\n\n Q0.xy += dQ.xy * iterationCount;\n Q0.z = pqk.z;\n hitPoint = Q0 / pqk.w;\n\n return intersect;\n}\n\nfloat calculateAlpha(\n float iterationCount, float reflectivity,\n vec2 hitPixel, vec3 hitPoint, float dist, vec3 rayDir\n)\n{\n float alpha = clamp(reflectivity, 0.0, 1.0);\n alpha *= 1.0 - (iterationCount / float(MAX_ITERATION));\n vec2 hitPixelNDC = hitPixel * 2.0 - 1.0;\n float maxDimension = min(1.0, max(abs(hitPixelNDC.x), abs(hitPixelNDC.y)));\n alpha *= 1.0 - max(0.0, maxDimension - screenEdgeFadeStart) / (1.0 - screenEdgeFadeStart);\n\n float _eyeFadeStart = eyeFadeStart;\n float _eyeFadeEnd = eyeFadeEnd;\n if (_eyeFadeStart > _eyeFadeEnd) {\n float tmp = _eyeFadeEnd;\n _eyeFadeEnd = _eyeFadeStart;\n _eyeFadeStart = tmp;\n }\n\n float eyeDir = clamp(rayDir.z, _eyeFadeStart, _eyeFadeEnd);\n alpha *= 1.0 - (eyeDir - _eyeFadeStart) / (_eyeFadeEnd - _eyeFadeStart);\n\n alpha *= 1.0 - clamp(dist / maxRayDistance, 0.0, 1.0);\n\n return alpha;\n}\n\n@import clay.util.rand\n\n@import clay.util.rgbm\n\nvoid main()\n{\n vec4 normalAndGloss = texture2D(gBufferTexture1, v_Texcoord);\n\n if (dot(normalAndGloss.rgb, vec3(1.0)) == 0.0) {\n discard;\n }\n\n float g = normalAndGloss.a;\n#if !defined(PHYSICALLY_CORRECT)\n if (g <= minGlossiness) {\n discard;\n }\n#endif\n\n float reflectivity = (g - minGlossiness) / (1.0 - minGlossiness);\n\n vec3 N = normalize(normalAndGloss.rgb * 2.0 - 1.0);\n N = normalize((toViewSpace * vec4(N, 0.0)).xyz);\n\n vec4 projectedPos = vec4(v_Texcoord * 2.0 - 1.0, fetchDepth(gBufferTexture2, v_Texcoord), 1.0);\n vec4 pos = projectionInv * projectedPos;\n vec3 rayOrigin = pos.xyz / pos.w;\n vec3 V = -normalize(rayOrigin);\n\n float ndv = clamp(dot(N, V), 0.0, 1.0);\n float iterationCount;\n float jitter = rand(fract(v_Texcoord + jitterOffset));\n\n#ifdef PHYSICALLY_CORRECT\n vec4 color = vec4(vec3(0.0), 1.0);\n vec4 albedoMetalness = texture2D(gBufferTexture3, v_Texcoord);\n vec3 albedo = albedoMetalness.rgb;\n float m = albedoMetalness.a;\n vec3 diffuseColor = albedo * (1.0 - m);\n vec3 spec = mix(vec3(0.04), albedo, m);\n\n float jitter2 = rand(fract(v_Texcoord)) * float(TOTAL_SAMPLES);\n\n for (int i = 0; i < SAMPLE_PER_FRAME; i++) {\n vec3 H = importanceSampleNormalGGX(float(i) + jitter2, 1.0 - g, N);\n vec3 rayDir = normalize(reflect(-V, H));\n#else\n vec3 rayDir = normalize(reflect(-V, N));\n#endif\n vec2 hitPixel;\n vec3 hitPoint;\n\n bool intersect = traceScreenSpaceRay(rayOrigin, rayDir, jitter, hitPixel, hitPoint, iterationCount);\n\n float dist = distance(rayOrigin, hitPoint);\n\n vec3 hitNormal = texture2D(gBufferTexture1, hitPixel).rgb * 2.0 - 1.0;\n hitNormal = normalize((toViewSpace * vec4(hitNormal, 0.0)).xyz);\n#ifdef PHYSICALLY_CORRECT\n float ndl = clamp(dot(N, rayDir), 0.0, 1.0);\n float vdh = clamp(dot(V, H), 0.0, 1.0);\n float ndh = clamp(dot(N, H), 0.0, 1.0);\n vec3 litTexel = vec3(0.0);\n if (dot(hitNormal, rayDir) < 0.0 && intersect) {\n litTexel = texture2D(sourceTexture, hitPixel).rgb;\n litTexel *= pow(clamp(1.0 - dist / 200.0, 0.0, 1.0), 3.0);\n\n }\n else {\n #ifdef SPECULARCUBEMAP_ENABLED\n vec3 rayDirW = normalize(toWorldSpace * vec4(rayDir, 0.0)).rgb;\n litTexel = RGBMDecode(textureCubeLodEXT(specularCubemap, rayDirW, 0.0), 8.12).rgb * specularIntensity;\n#endif\n }\n color.rgb += ndl * litTexel * (\n F_Schlick(ndl, spec) * G_Smith(g, ndv, ndl) * vdh / (ndh * ndv + 0.001)\n );\n }\n color.rgb /= float(SAMPLE_PER_FRAME);\n#else\n #if !defined(SPECULARCUBEMAP_ENABLED)\n if (dot(hitNormal, rayDir) >= 0.0) {\n discard;\n }\n if (!intersect) {\n discard;\n }\n#endif\n float alpha = clamp(calculateAlpha(iterationCount, reflectivity, hitPixel, hitPoint, dist, rayDir), 0.0, 1.0);\n vec4 color = texture2D(sourceTexture, hitPixel);\n color.rgb *= alpha;\n\n#ifdef SPECULARCUBEMAP_ENABLED\n vec3 rayDirW = normalize(toWorldSpace * vec4(rayDir, 0.0)).rgb;\n alpha = alpha * (intersect ? 1.0 : 0.0);\n float bias = (1.0 -g) * 5.0;\n color.rgb += (1.0 - alpha)\n * RGBMDecode(textureCubeLodEXT(specularCubemap, rayDirW, bias), 8.12).rgb\n * specularIntensity;\n#endif\n\n#endif\n\n gl_FragColor = encodeHDR(color);\n}\n@end\n\n@export ecgl.ssr.blur\n\nuniform sampler2D texture;\nuniform sampler2D gBufferTexture1;\nuniform sampler2D gBufferTexture2;\nuniform mat4 projection;\nuniform float depthRange : 0.05;\n\nvarying vec2 v_Texcoord;\n\nuniform vec2 textureSize;\nuniform float blurSize : 1.0;\n\n#ifdef BLEND\n #ifdef SSAOTEX_ENABLED\nuniform sampler2D ssaoTex;\n #endif\nuniform sampler2D sourceTexture;\n#endif\n\nfloat getLinearDepth(vec2 coord)\n{\n float depth = texture2D(gBufferTexture2, coord).r * 2.0 - 1.0;\n return projection[3][2] / (depth * projection[2][3] - projection[2][2]);\n}\n\n@import clay.util.rgbm\n\n\nvoid main()\n{\n @import clay.compositor.kernel.gaussian_9\n\n vec4 centerNTexel = texture2D(gBufferTexture1, v_Texcoord);\n float g = centerNTexel.a;\n float maxBlurSize = clamp(1.0 - g, 0.0, 1.0) * blurSize;\n#ifdef VERTICAL\n vec2 off = vec2(0.0, maxBlurSize / textureSize.y);\n#else\n vec2 off = vec2(maxBlurSize / textureSize.x, 0.0);\n#endif\n\n vec2 coord = v_Texcoord;\n\n vec4 sum = vec4(0.0);\n float weightAll = 0.0;\n\n vec3 cN = centerNTexel.rgb * 2.0 - 1.0;\n float cD = getLinearDepth(v_Texcoord);\n for (int i = 0; i < 9; i++) {\n vec2 coord = clamp((float(i) - 4.0) * off + v_Texcoord, vec2(0.0), vec2(1.0));\n float w = gaussianKernel[i]\n * clamp(dot(cN, texture2D(gBufferTexture1, coord).rgb * 2.0 - 1.0), 0.0, 1.0);\n float d = getLinearDepth(coord);\n w *= (1.0 - smoothstep(abs(cD - d) / depthRange, 0.0, 1.0));\n\n weightAll += w;\n sum += decodeHDR(texture2D(texture, coord)) * w;\n }\n\n#ifdef BLEND\n float aoFactor = 1.0;\n #ifdef SSAOTEX_ENABLED\n aoFactor = texture2D(ssaoTex, v_Texcoord).r;\n #endif\n gl_FragColor = encodeHDR(\n sum / weightAll * aoFactor + decodeHDR(texture2D(sourceTexture, v_Texcoord))\n );\n#else\n gl_FragColor = encodeHDR(sum / weightAll);\n#endif\n}\n\n@end"); + + +/***/ }), +/* 193 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +// Based on https://bl.ocks.org/mbostock/19168c663618b707158 + +/* harmony default export */ __webpack_exports__["a"] = ([ +0.0, 0.0, +-0.321585265978, -0.154972575841, +0.458126042375, 0.188473391593, +0.842080129861, 0.527766490688, +0.147304551086, -0.659453822776, +-0.331943915203, -0.940619700594, +0.0479226680259, 0.54812163202, +0.701581552186, -0.709825561388, +-0.295436780218, 0.940589268233, +-0.901489676764, 0.237713156085, +0.973570876096, -0.109899459384, +-0.866792314779, -0.451805525005, +0.330975007087, 0.800048655954, +-0.344275183665, 0.381779221166, +-0.386139432542, -0.437418421534, +-0.576478634965, -0.0148463392551, +0.385798197415, -0.262426961053, +-0.666302061145, 0.682427250835, +-0.628010632582, -0.732836215494, +0.10163141741, -0.987658134403, +0.711995289051, -0.320024291314, +0.0296005138058, 0.950296523438, +0.0130612307608, -0.351024443122, +-0.879596633704, -0.10478487883, +0.435712737232, 0.504254490347, +0.779203817497, 0.206477676721, +0.388264289969, -0.896736162545, +-0.153106280781, -0.629203242522, +-0.245517550697, 0.657969239148, +0.126830499058, 0.26862328493, +-0.634888119007, -0.302301223431, +0.617074219636, 0.779817204925 +]); + +/***/ }), +/* 194 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_claygl_src_Texture2D__ = __webpack_require__(5); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_claygl_src_Texture__ = __webpack_require__(4); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2_claygl_src_Shader__ = __webpack_require__(8); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3_claygl_src_FrameBuffer__ = __webpack_require__(10); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4_claygl_src_Material__ = __webpack_require__(19); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_5_claygl_src_compositor_Pass__ = __webpack_require__(16); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_6_claygl_src_util_texture__ = __webpack_require__(61); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_7__util_shader_normal_glsl_js__ = __webpack_require__(195); +// NormalPass will generate normal and depth data. + +// TODO Animation + + + + + + + + + +__WEBPACK_IMPORTED_MODULE_2_claygl_src_Shader__["a" /* default */].import(__WEBPACK_IMPORTED_MODULE_7__util_shader_normal_glsl_js__["a" /* default */]); + +function attachTextureToSlot(renderer, program, symbol, texture, slot) { + var gl = renderer.gl; + program.setUniform(gl, '1i', symbol, slot); + + gl.activeTexture(gl.TEXTURE0 + slot); + // Maybe texture is not loaded yet; + if (texture.isRenderable()) { + texture.bind(renderer); + } + else { + // Bind texture to null + texture.unbind(renderer); + } +} + +// TODO Use globalShader insteadof globalMaterial? +function getBeforeRenderHook (renderer, defaultNormalMap, defaultBumpMap, defaultRoughnessMap, normalMaterial) { + + var previousNormalMap; + var previousBumpMap; + var previousRoughnessMap; + var previousRenderable; + var gl = renderer.gl; + + return function (renderable, normalMaterial, prevNormalMaterial) { + // Material not change + if (previousRenderable && previousRenderable.material === renderable.material) { + return; + } + + var material = renderable.material; + var program = renderable.__program; + + var roughness = material.get('roughness'); + if (roughness == null) { + roughness = 1; + } + + var normalMap = material.get('normalMap') || defaultNormalMap; + var roughnessMap = material.get('roughnessMap'); + var bumpMap = material.get('bumpMap'); + var uvRepeat = material.get('uvRepeat'); + var uvOffset = material.get('uvOffset'); + var detailUvRepeat = material.get('detailUvRepeat'); + var detailUvOffset = material.get('detailUvOffset'); + + var useBumpMap = !!bumpMap && material.isTextureEnabled('bumpMap'); + var useRoughnessMap = !!roughnessMap && material.isTextureEnabled('roughnessMap'); + var doubleSide = material.isDefined('fragment', 'DOUBLE_SIDED'); + + bumpMap = bumpMap || defaultBumpMap; + roughnessMap = roughnessMap || defaultRoughnessMap; + + if (prevNormalMaterial !== normalMaterial) { + normalMaterial.set('normalMap', normalMap); + normalMaterial.set('bumpMap', bumpMap); + normalMaterial.set('roughnessMap', roughnessMap); + normalMaterial.set('useBumpMap', useBumpMap); + normalMaterial.set('useRoughnessMap', useRoughnessMap); + normalMaterial.set('doubleSide', doubleSide); + uvRepeat != null && normalMaterial.set('uvRepeat', uvRepeat); + uvOffset != null && normalMaterial.set('uvOffset', uvOffset); + detailUvRepeat != null && normalMaterial.set('detailUvRepeat', detailUvRepeat); + detailUvOffset != null && normalMaterial.set('detailUvOffset', detailUvOffset); + + normalMaterial.set('roughness', roughness); + } + else { + program.setUniform(gl, '1f', 'roughness', roughness); + + if (previousNormalMap !== normalMap) { + attachTextureToSlot(renderer, program, 'normalMap', normalMap, 0); + } + if (previousBumpMap !== bumpMap && bumpMap) { + attachTextureToSlot(renderer, program, 'bumpMap', bumpMap, 1); + } + if (previousRoughnessMap !== roughnessMap && roughnessMap) { + attachTextureToSlot(renderer, program, 'roughnessMap', roughnessMap, 2); + } + if (uvRepeat != null) { + program.setUniform(gl, '2f', 'uvRepeat', uvRepeat); + } + if (uvOffset != null) { + program.setUniform(gl, '2f', 'uvOffset', uvOffset); + } + if (detailUvRepeat != null) { + program.setUniform(gl, '2f', 'detailUvRepeat', detailUvRepeat); + } + if (detailUvOffset != null) { + program.setUniform(gl, '2f', 'detailUvOffset', detailUvOffset); + } + program.setUniform(gl, '1i', 'useBumpMap', +useBumpMap); + program.setUniform(gl, '1i', 'useRoughnessMap', +useRoughnessMap); + program.setUniform(gl, '1i', 'doubleSide', +doubleSide); + } + + previousNormalMap = normalMap; + previousBumpMap = bumpMap; + previousRoughnessMap = roughnessMap; + + previousRenderable = renderable; + }; +} + +function NormalPass(opt) { + opt = opt || {}; + + this._depthTex = new __WEBPACK_IMPORTED_MODULE_0_claygl_src_Texture2D__["a" /* default */]({ + format: __WEBPACK_IMPORTED_MODULE_1_claygl_src_Texture__["a" /* default */].DEPTH_COMPONENT, + type: __WEBPACK_IMPORTED_MODULE_1_claygl_src_Texture__["a" /* default */].UNSIGNED_INT + }); + this._normalTex = new __WEBPACK_IMPORTED_MODULE_0_claygl_src_Texture2D__["a" /* default */]({ + type: __WEBPACK_IMPORTED_MODULE_1_claygl_src_Texture__["a" /* default */].HALF_FLOAT + }); + + this._framebuffer = new __WEBPACK_IMPORTED_MODULE_3_claygl_src_FrameBuffer__["a" /* default */](); + this._framebuffer.attach(this._normalTex); + this._framebuffer.attach(this._depthTex, __WEBPACK_IMPORTED_MODULE_3_claygl_src_FrameBuffer__["a" /* default */].DEPTH_ATTACHMENT); + + this._normalMaterial = new __WEBPACK_IMPORTED_MODULE_4_claygl_src_Material__["a" /* default */]({ + shader: new __WEBPACK_IMPORTED_MODULE_2_claygl_src_Shader__["a" /* default */]( + __WEBPACK_IMPORTED_MODULE_2_claygl_src_Shader__["a" /* default */].source('ecgl.normal.vertex'), + __WEBPACK_IMPORTED_MODULE_2_claygl_src_Shader__["a" /* default */].source('ecgl.normal.fragment') + ) + }); + this._normalMaterial.enableTexture(['normalMap', 'bumpMap', 'roughnessMap']); + + this._defaultNormalMap = __WEBPACK_IMPORTED_MODULE_6_claygl_src_util_texture__["a" /* default */].createBlank('#000'); + this._defaultBumpMap = __WEBPACK_IMPORTED_MODULE_6_claygl_src_util_texture__["a" /* default */].createBlank('#000'); + this._defaultRoughessMap = __WEBPACK_IMPORTED_MODULE_6_claygl_src_util_texture__["a" /* default */].createBlank('#000'); + + + this._debugPass = new __WEBPACK_IMPORTED_MODULE_5_claygl_src_compositor_Pass__["a" /* default */]({ + fragment: __WEBPACK_IMPORTED_MODULE_2_claygl_src_Shader__["a" /* default */].source('clay.compositor.output') + }); + this._debugPass.setUniform('texture', this._normalTex); + this._debugPass.material.undefine('fragment', 'OUTPUT_ALPHA'); +} + +NormalPass.prototype.getDepthTexture = function () { + return this._depthTex; +}; + +NormalPass.prototype.getNormalTexture = function () { + return this._normalTex; +}; + +NormalPass.prototype.update = function (renderer, scene, camera) { + + var width = renderer.getWidth(); + var height = renderer.getHeight(); + + var depthTexture = this._depthTex; + var normalTexture = this._normalTex; + var normalMaterial = this._normalMaterial; + + depthTexture.width = width; + depthTexture.height = height; + normalTexture.width = width; + normalTexture.height = height; + + var opaqueList = scene.getRenderList(camera).opaque; + + this._framebuffer.bind(renderer); + renderer.gl.clearColor(0, 0, 0, 0); + renderer.gl.clear(renderer.gl.COLOR_BUFFER_BIT | renderer.gl.DEPTH_BUFFER_BIT); + renderer.gl.disable(renderer.gl.BLEND); + + renderer.renderPass(opaqueList, camera, { + getMaterial: function () { + return normalMaterial; + }, + ifRender: function (object) { + return object.renderNormal; + }, + beforeRender: getBeforeRenderHook( + renderer, this._defaultNormalMap, this._defaultBumpMap, this._defaultRoughessMap, this._normalMaterial + ), + sort: renderer.opaqueSortCompare + }); + this._framebuffer.unbind(renderer); +}; + +NormalPass.prototype.renderDebug = function (renderer) { + this._debugPass.render(renderer); +}; + +NormalPass.prototype.dispose = function (renderer) { + this._depthTex.dispose(renderer); + this._normalTex.dispose(renderer); +} + +/* harmony default export */ __webpack_exports__["a"] = (NormalPass); + +/***/ }), +/* 195 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony default export */ __webpack_exports__["a"] = ("@export ecgl.normal.vertex\n\n@import ecgl.common.transformUniforms\n\n@import ecgl.common.uv.header\n\n@import ecgl.common.attributes\n\nvarying vec3 v_Normal;\nvarying vec3 v_WorldPosition;\n\n@import ecgl.common.normalMap.vertexHeader\n\n@import ecgl.common.vertexAnimation.header\n\nvoid main()\n{\n\n @import ecgl.common.vertexAnimation.main\n\n @import ecgl.common.uv.main\n\n v_Normal = normalize((worldInverseTranspose * vec4(normal, 0.0)).xyz);\n v_WorldPosition = (world * vec4(pos, 1.0)).xyz;\n\n @import ecgl.common.normalMap.vertexMain\n\n gl_Position = worldViewProjection * vec4(pos, 1.0);\n\n}\n\n\n@end\n\n\n@export ecgl.normal.fragment\n\n#define ROUGHNESS_CHANEL 0\n\nuniform bool useBumpMap;\nuniform bool useRoughnessMap;\nuniform bool doubleSide;\nuniform float roughness;\n\n@import ecgl.common.uv.fragmentHeader\n\nvarying vec3 v_Normal;\nvarying vec3 v_WorldPosition;\n\nuniform mat4 viewInverse : VIEWINVERSE;\n\n@import ecgl.common.normalMap.fragmentHeader\n@import ecgl.common.bumpMap.header\n\nuniform sampler2D roughnessMap;\n\nvoid main()\n{\n vec3 N = v_Normal;\n \n bool flipNormal = false;\n if (doubleSide) {\n vec3 eyePos = viewInverse[3].xyz;\n vec3 V = normalize(eyePos - v_WorldPosition);\n\n if (dot(N, V) < 0.0) {\n flipNormal = true;\n }\n }\n\n @import ecgl.common.normalMap.fragmentMain\n\n if (useBumpMap) {\n N = bumpNormal(v_WorldPosition, v_Normal, N);\n }\n\n float g = 1.0 - roughness;\n\n if (useRoughnessMap) {\n float g2 = 1.0 - texture2D(roughnessMap, v_DetailTexcoord)[ROUGHNESS_CHANEL];\n g = clamp(g2 + (g - 0.5) * 2.0, 0.0, 1.0);\n }\n\n if (flipNormal) {\n N = -N;\n }\n\n gl_FragColor.rgb = (N.xyz + 1.0) * 0.5;\n gl_FragColor.a = g;\n}\n@end"); + + +/***/ }), +/* 196 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_claygl_src_math_Matrix4__ = __webpack_require__(9); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_claygl_src_math_Vector3__ = __webpack_require__(3); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2_claygl_src_Texture2D__ = __webpack_require__(5); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3_claygl_src_Texture__ = __webpack_require__(4); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4_claygl_src_compositor_Pass__ = __webpack_require__(16); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_5_claygl_src_Shader__ = __webpack_require__(8); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_6_claygl_src_FrameBuffer__ = __webpack_require__(10); + + + + + + + + +function EdgePass(opt) { + opt = opt || {}; + + this._edgePass = new __WEBPACK_IMPORTED_MODULE_4_claygl_src_compositor_Pass__["a" /* default */]({ + fragment: __WEBPACK_IMPORTED_MODULE_5_claygl_src_Shader__["a" /* default */].source('ecgl.edge') + }); + + this._edgePass.setUniform('normalTexture', opt.normalTexture); + this._edgePass.setUniform('depthTexture', opt.depthTexture); + + this._targetTexture = new __WEBPACK_IMPORTED_MODULE_2_claygl_src_Texture2D__["a" /* default */]({ + type: __WEBPACK_IMPORTED_MODULE_3_claygl_src_Texture__["a" /* default */].HALF_FLOAT + }); + + this._frameBuffer = new __WEBPACK_IMPORTED_MODULE_6_claygl_src_FrameBuffer__["a" /* default */](); + this._frameBuffer.attach(this._targetTexture); +} + +EdgePass.prototype.update = function (renderer, camera, sourceTexture, frame) { + var width = renderer.getWidth(); + var height = renderer.getHeight(); + var texture = this._targetTexture; + texture.width = width; + texture.height = height; + var frameBuffer = this._frameBuffer; + + frameBuffer.bind(renderer); + this._edgePass.setUniform('projectionInv', camera.invProjectionMatrix.array); + this._edgePass.setUniform('textureSize', [width, height]); + this._edgePass.setUniform('texture', sourceTexture); + this._edgePass.render(renderer); + + frameBuffer.unbind(renderer); +}; + +EdgePass.prototype.getTargetTexture = function () { + return this._targetTexture; +}; + +EdgePass.prototype.setParameter = function (name, val) { + this._edgePass.setUniform(name, val); +}; + +EdgePass.prototype.dispose = function (renderer) { + this._targetTexture.dispose(renderer); + this._frameBuffer.dispose(renderer); +}; + +/* harmony default export */ __webpack_exports__["a"] = (EdgePass); + +/***/ }), +/* 197 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony default export */ __webpack_exports__["a"] = ({ + 'type' : 'compositor', + 'nodes' : [ + { + 'name': 'source', + 'type': 'texture', + 'outputs': { + 'color': {} + } + }, + { + 'name': 'source_half', + 'shader': '#source(clay.compositor.downsample)', + 'inputs': { + 'texture': 'source' + }, + 'outputs': { + 'color': { + 'parameters': { + 'width': 'expr(width * 1.0 / 2)', + 'height': 'expr(height * 1.0 / 2)', + 'type': 'HALF_FLOAT' + } + } + }, + 'parameters' : { + 'textureSize': 'expr( [width * 1.0, height * 1.0] )' + } + }, + + + { + 'name' : 'bright', + 'shader' : '#source(clay.compositor.bright)', + 'inputs' : { + 'texture' : 'source_half' + }, + 'outputs' : { + 'color' : { + 'parameters' : { + 'width' : 'expr(width * 1.0 / 2)', + 'height' : 'expr(height * 1.0 / 2)', + 'type': 'HALF_FLOAT' + } + } + }, + 'parameters' : { + 'threshold' : 2, + 'scale': 4, + 'textureSize': 'expr([width * 1.0 / 2, height / 2])' + } + }, + + { + 'name': 'bright_downsample_4', + 'shader' : '#source(clay.compositor.downsample)', + 'inputs' : { + 'texture' : 'bright' + }, + 'outputs' : { + 'color' : { + 'parameters' : { + 'width' : 'expr(width * 1.0 / 4)', + 'height' : 'expr(height * 1.0 / 4)', + 'type': 'HALF_FLOAT' + } + } + }, + 'parameters' : { + 'textureSize': 'expr( [width * 1.0 / 2, height / 2] )' + } + }, + { + 'name': 'bright_downsample_8', + 'shader' : '#source(clay.compositor.downsample)', + 'inputs' : { + 'texture' : 'bright_downsample_4' + }, + 'outputs' : { + 'color' : { + 'parameters' : { + 'width' : 'expr(width * 1.0 / 8)', + 'height' : 'expr(height * 1.0 / 8)', + 'type': 'HALF_FLOAT' + } + } + }, + 'parameters' : { + 'textureSize': 'expr( [width * 1.0 / 4, height / 4] )' + } + }, + { + 'name': 'bright_downsample_16', + 'shader' : '#source(clay.compositor.downsample)', + 'inputs' : { + 'texture' : 'bright_downsample_8' + }, + 'outputs' : { + 'color' : { + 'parameters' : { + 'width' : 'expr(width * 1.0 / 16)', + 'height' : 'expr(height * 1.0 / 16)', + 'type': 'HALF_FLOAT' + } + } + }, + 'parameters' : { + 'textureSize': 'expr( [width * 1.0 / 8, height / 8] )' + } + }, + { + 'name': 'bright_downsample_32', + 'shader' : '#source(clay.compositor.downsample)', + 'inputs' : { + 'texture' : 'bright_downsample_16' + }, + 'outputs' : { + 'color' : { + 'parameters' : { + 'width' : 'expr(width * 1.0 / 32)', + 'height' : 'expr(height * 1.0 / 32)', + 'type': 'HALF_FLOAT' + } + } + }, + 'parameters' : { + 'textureSize': 'expr( [width * 1.0 / 16, height / 16] )' + } + }, + + + { + 'name' : 'bright_upsample_16_blur_h', + 'shader' : '#source(clay.compositor.gaussian_blur)', + 'inputs' : { + 'texture' : 'bright_downsample_32' + }, + 'outputs' : { + 'color' : { + 'parameters' : { + 'width' : 'expr(width * 1.0 / 16)', + 'height' : 'expr(height * 1.0 / 16)', + 'type': 'HALF_FLOAT' + } + } + }, + 'parameters' : { + 'blurSize' : 1, + 'blurDir': 0.0, + 'textureSize': 'expr( [width * 1.0 / 32, height / 32] )' + } + }, + { + 'name' : 'bright_upsample_16_blur_v', + 'shader' : '#source(clay.compositor.gaussian_blur)', + 'inputs' : { + 'texture' : 'bright_upsample_16_blur_h' + }, + 'outputs' : { + 'color' : { + 'parameters' : { + 'width' : 'expr(width * 1.0 / 16)', + 'height' : 'expr(height * 1.0 / 16)', + 'type': 'HALF_FLOAT' + } + } + }, + 'parameters' : { + 'blurSize' : 1, + 'blurDir': 1.0, + 'textureSize': 'expr( [width * 1.0 / 16, height * 1.0 / 16] )' + } + }, + + + + { + 'name' : 'bright_upsample_8_blur_h', + 'shader' : '#source(clay.compositor.gaussian_blur)', + 'inputs' : { + 'texture' : 'bright_downsample_16' + }, + 'outputs' : { + 'color' : { + 'parameters' : { + 'width' : 'expr(width * 1.0 / 8)', + 'height' : 'expr(height * 1.0 / 8)', + 'type': 'HALF_FLOAT' + } + } + }, + 'parameters' : { + 'blurSize' : 1, + 'blurDir': 0.0, + 'textureSize': 'expr( [width * 1.0 / 16, height * 1.0 / 16] )' + } + }, + { + 'name' : 'bright_upsample_8_blur_v', + 'shader' : '#source(clay.compositor.gaussian_blur)', + 'inputs' : { + 'texture' : 'bright_upsample_8_blur_h' + }, + 'outputs' : { + 'color' : { + 'parameters' : { + 'width' : 'expr(width * 1.0 / 8)', + 'height' : 'expr(height * 1.0 / 8)', + 'type': 'HALF_FLOAT' + } + } + }, + 'parameters' : { + 'blurSize' : 1, + 'blurDir': 1.0, + 'textureSize': 'expr( [width * 1.0 / 8, height * 1.0 / 8] )' + } + }, + { + 'name' : 'bright_upsample_8_blend', + 'shader' : '#source(clay.compositor.blend)', + 'inputs' : { + 'texture1' : 'bright_upsample_8_blur_v', + 'texture2' : 'bright_upsample_16_blur_v' + }, + 'outputs' : { + 'color' : { + 'parameters' : { + 'width' : 'expr(width * 1.0 / 8)', + 'height' : 'expr(height * 1.0 / 8)', + 'type': 'HALF_FLOAT' + } + } + }, + 'parameters' : { + 'weight1' : 0.3, + 'weight2' : 0.7 + } + }, + + + { + 'name' : 'bright_upsample_4_blur_h', + 'shader' : '#source(clay.compositor.gaussian_blur)', + 'inputs' : { + 'texture' : 'bright_downsample_8' + }, + 'outputs' : { + 'color' : { + 'parameters' : { + 'width' : 'expr(width * 1.0 / 4)', + 'height' : 'expr(height * 1.0 / 4)', + 'type': 'HALF_FLOAT' + } + } + }, + 'parameters' : { + 'blurSize' : 1, + 'blurDir': 0.0, + 'textureSize': 'expr( [width * 1.0 / 8, height * 1.0 / 8] )' + } + }, + { + 'name' : 'bright_upsample_4_blur_v', + 'shader' : '#source(clay.compositor.gaussian_blur)', + 'inputs' : { + 'texture' : 'bright_upsample_4_blur_h' + }, + 'outputs' : { + 'color' : { + 'parameters' : { + 'width' : 'expr(width * 1.0 / 4)', + 'height' : 'expr(height * 1.0 / 4)', + 'type': 'HALF_FLOAT' + } + } + }, + 'parameters' : { + 'blurSize' : 1, + 'blurDir': 1.0, + 'textureSize': 'expr( [width * 1.0 / 4, height * 1.0 / 4] )' + } + }, + { + 'name' : 'bright_upsample_4_blend', + 'shader' : '#source(clay.compositor.blend)', + 'inputs' : { + 'texture1' : 'bright_upsample_4_blur_v', + 'texture2' : 'bright_upsample_8_blend' + }, + 'outputs' : { + 'color' : { + 'parameters' : { + 'width' : 'expr(width * 1.0 / 4)', + 'height' : 'expr(height * 1.0 / 4)', + 'type': 'HALF_FLOAT' + } + } + }, + 'parameters' : { + 'weight1' : 0.3, + 'weight2' : 0.7 + } + }, + + + + + + { + 'name' : 'bright_upsample_2_blur_h', + 'shader' : '#source(clay.compositor.gaussian_blur)', + 'inputs' : { + 'texture' : 'bright_downsample_4' + }, + 'outputs' : { + 'color' : { + 'parameters' : { + 'width' : 'expr(width * 1.0 / 2)', + 'height' : 'expr(height * 1.0 / 2)', + 'type': 'HALF_FLOAT' + } + } + }, + 'parameters' : { + 'blurSize' : 1, + 'blurDir': 0.0, + 'textureSize': 'expr( [width * 1.0 / 4, height * 1.0 / 4] )' + } + }, + { + 'name' : 'bright_upsample_2_blur_v', + 'shader' : '#source(clay.compositor.gaussian_blur)', + 'inputs' : { + 'texture' : 'bright_upsample_2_blur_h' + }, + 'outputs' : { + 'color' : { + 'parameters' : { + 'width' : 'expr(width * 1.0 / 2)', + 'height' : 'expr(height * 1.0 / 2)', + 'type': 'HALF_FLOAT' + } + } + }, + 'parameters' : { + 'blurSize' : 1, + 'blurDir': 1.0, + 'textureSize': 'expr( [width * 1.0 / 2, height * 1.0 / 2] )' + } + }, + { + 'name' : 'bright_upsample_2_blend', + 'shader' : '#source(clay.compositor.blend)', + 'inputs' : { + 'texture1' : 'bright_upsample_2_blur_v', + 'texture2' : 'bright_upsample_4_blend' + }, + 'outputs' : { + 'color' : { + 'parameters' : { + 'width' : 'expr(width * 1.0 / 2)', + 'height' : 'expr(height * 1.0 / 2)', + 'type': 'HALF_FLOAT' + } + } + }, + 'parameters' : { + 'weight1' : 0.3, + 'weight2' : 0.7 + } + }, + + + + { + 'name' : 'bright_upsample_full_blur_h', + 'shader' : '#source(clay.compositor.gaussian_blur)', + 'inputs' : { + 'texture' : 'bright' + }, + 'outputs' : { + 'color' : { + 'parameters' : { + 'width' : 'expr(width * 1.0)', + 'height' : 'expr(height * 1.0)', + 'type': 'HALF_FLOAT' + } + } + }, + 'parameters' : { + 'blurSize' : 1, + 'blurDir': 0.0, + 'textureSize': 'expr( [width * 1.0 / 2, height * 1.0 / 2] )' + } + }, + { + 'name' : 'bright_upsample_full_blur_v', + 'shader' : '#source(clay.compositor.gaussian_blur)', + 'inputs' : { + 'texture' : 'bright_upsample_full_blur_h' + }, + 'outputs' : { + 'color' : { + 'parameters' : { + 'width' : 'expr(width * 1.0)', + 'height' : 'expr(height * 1.0)', + 'type': 'HALF_FLOAT' + } + } + }, + 'parameters' : { + 'blurSize' : 1, + 'blurDir': 1.0, + 'textureSize': 'expr( [width * 1.0, height * 1.0] )' + } + }, + { + 'name' : 'bloom_composite', + 'shader' : '#source(clay.compositor.blend)', + 'inputs' : { + 'texture1' : 'bright_upsample_full_blur_v', + 'texture2' : 'bright_upsample_2_blend' + }, + 'outputs' : { + 'color' : { + 'parameters' : { + 'width' : 'expr(width * 1.0)', + 'height' : 'expr(height * 1.0)', + 'type': 'HALF_FLOAT' + } + } + }, + 'parameters' : { + 'weight1' : 0.3, + 'weight2' : 0.7 + } + }, + + + { + 'name': 'coc', + 'shader': '#source(ecgl.dof.coc)', + 'outputs': { + 'color': { + 'parameters': { + 'minFilter': 'NEAREST', + 'magFilter': 'NEAREST', + 'width': 'expr(width * 1.0)', + 'height': 'expr(height * 1.0)' + } + } + }, + 'parameters': { + 'focalDist': 50, + 'focalRange': 30 + } + }, + + { + 'name': 'dof_far_blur', + 'shader': '#source(ecgl.dof.diskBlur)', + 'inputs': { + 'texture': 'source', + 'coc': 'coc' + }, + 'outputs': { + 'color': { + 'parameters': { + 'width': 'expr(width * 1.0)', + 'height': 'expr(height * 1.0)', + 'type': 'HALF_FLOAT' + } + } + }, + 'parameters': { + 'textureSize': 'expr( [width * 1.0, height * 1.0] )' + } + }, + { + 'name': 'dof_near_blur', + 'shader': '#source(ecgl.dof.diskBlur)', + 'inputs': { + 'texture': 'source', + 'coc': 'coc' + }, + 'outputs': { + 'color': { + 'parameters': { + 'width': 'expr(width * 1.0)', + 'height': 'expr(height * 1.0)', + 'type': 'HALF_FLOAT' + } + } + }, + 'parameters': { + 'textureSize': 'expr( [width * 1.0, height * 1.0] )' + }, + 'defines': { + 'BLUR_NEARFIELD': null + } + }, + + + { + 'name': 'dof_coc_blur', + 'shader': '#source(ecgl.dof.diskBlur)', + 'inputs': { + 'texture': 'coc' + }, + 'outputs': { + 'color': { + 'parameters': { + 'minFilter': 'NEAREST', + 'magFilter': 'NEAREST', + 'width': 'expr(width * 1.0)', + 'height': 'expr(height * 1.0)' + } + } + }, + 'parameters': { + 'textureSize': 'expr( [width * 1.0, height * 1.0] )' + }, + 'defines': { + 'BLUR_COC': null + } + }, + + { + 'name': 'dof_composite', + 'shader': '#source(ecgl.dof.composite)', + 'inputs': { + 'original': 'source', + 'blurred': 'dof_far_blur', + 'nearfield': 'dof_near_blur', + 'coc': 'coc', + 'nearcoc': 'dof_coc_blur' + }, + 'outputs': { + 'color': { + 'parameters': { + 'width': 'expr(width * 1.0)', + 'height': 'expr(height * 1.0)', + 'type': 'HALF_FLOAT' + } + } + } + }, + { + 'name' : 'composite', + 'shader' : '#source(clay.compositor.hdr.composite)', + 'inputs' : { + 'texture': 'source', + 'bloom' : 'bloom_composite' + }, + 'defines': { + // Images are all premultiplied alpha before composite because of blending. + // 'PREMULTIPLY_ALPHA': null, + // 'DEBUG': 2 + } + }, + { + 'name' : 'FXAA', + 'shader' : '#source(clay.compositor.fxaa)', + 'inputs' : { + 'texture' : 'composite' + } + } + ] +}); + +/***/ }), +/* 198 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony default export */ __webpack_exports__["a"] = ("@export ecgl.dof.coc\n\nuniform sampler2D depth;\n\nuniform float zNear: 0.1;\nuniform float zFar: 2000;\n\nuniform float focalDistance: 3;\nuniform float focalRange: 1;\nuniform float focalLength: 30;\nuniform float fstop: 2.8;\n\nvarying vec2 v_Texcoord;\n\n@import clay.util.encode_float\n\nvoid main()\n{\n float z = texture2D(depth, v_Texcoord).r * 2.0 - 1.0;\n\n float dist = 2.0 * zNear * zFar / (zFar + zNear - z * (zFar - zNear));\n\n float aperture = focalLength / fstop;\n\n float coc;\n\n float uppper = focalDistance + focalRange;\n float lower = focalDistance - focalRange;\n if (dist <= uppper && dist >= lower) {\n coc = 0.5;\n }\n else {\n float focalAdjusted = dist > uppper ? uppper : lower;\n\n coc = abs(aperture * (focalLength * (dist - focalAdjusted)) / (dist * (focalAdjusted - focalLength)));\n coc = clamp(coc, 0.0, 2.0) / 2.00001;\n\n if (dist < lower) {\n coc = -coc;\n }\n coc = coc * 0.5 + 0.5;\n }\n\n gl_FragColor = encodeFloat(coc);\n}\n@end\n\n\n@export ecgl.dof.composite\n\n#define DEBUG 0\n\nuniform sampler2D original;\nuniform sampler2D blurred;\nuniform sampler2D nearfield;\nuniform sampler2D coc;\nuniform sampler2D nearcoc;\nvarying vec2 v_Texcoord;\n\n@import clay.util.rgbm\n@import clay.util.float\n\nvoid main()\n{\n vec4 blurredColor = texture2D(blurred, v_Texcoord);\n vec4 originalColor = texture2D(original, v_Texcoord);\n\n float fCoc = decodeFloat(texture2D(coc, v_Texcoord));\n\n fCoc = abs(fCoc * 2.0 - 1.0);\n\n float weight = smoothstep(0.0, 1.0, fCoc);\n \n#ifdef NEARFIELD_ENABLED\n vec4 nearfieldColor = texture2D(nearfield, v_Texcoord);\n float fNearCoc = decodeFloat(texture2D(nearcoc, v_Texcoord));\n fNearCoc = abs(fNearCoc * 2.0 - 1.0);\n\n gl_FragColor = encodeHDR(\n mix(\n nearfieldColor, mix(originalColor, blurredColor, weight),\n pow(1.0 - fNearCoc, 4.0)\n )\n );\n#else\n gl_FragColor = encodeHDR(mix(originalColor, blurredColor, weight));\n#endif\n\n}\n\n@end\n\n\n\n@export ecgl.dof.diskBlur\n\n#define POISSON_KERNEL_SIZE 16;\n\nuniform sampler2D texture;\nuniform sampler2D coc;\nvarying vec2 v_Texcoord;\n\nuniform float blurRadius : 10.0;\nuniform vec2 textureSize : [512.0, 512.0];\n\nuniform vec2 poissonKernel[POISSON_KERNEL_SIZE];\n\nuniform float percent;\n\nfloat nrand(const in vec2 n) {\n return fract(sin(dot(n.xy ,vec2(12.9898,78.233))) * 43758.5453);\n}\n\n@import clay.util.rgbm\n@import clay.util.float\n\n\nvoid main()\n{\n vec2 offset = blurRadius / textureSize;\n\n float rnd = 6.28318 * nrand(v_Texcoord + 0.07 * percent );\n float cosa = cos(rnd);\n float sina = sin(rnd);\n vec4 basis = vec4(cosa, -sina, sina, cosa);\n\n#if !defined(BLUR_NEARFIELD) && !defined(BLUR_COC)\n offset *= abs(decodeFloat(texture2D(coc, v_Texcoord)) * 2.0 - 1.0);\n#endif\n\n#ifdef BLUR_COC\n float cocSum = 0.0;\n#else\n vec4 color = vec4(0.0);\n#endif\n\n\n float weightSum = 0.0;\n\n for (int i = 0; i < POISSON_KERNEL_SIZE; i++) {\n vec2 ofs = poissonKernel[i];\n\n ofs = vec2(dot(ofs, basis.xy), dot(ofs, basis.zw));\n\n vec2 uv = v_Texcoord + ofs * offset;\n vec4 texel = texture2D(texture, uv);\n\n float w = 1.0;\n#ifdef BLUR_COC\n float fCoc = decodeFloat(texel) * 2.0 - 1.0;\n cocSum += clamp(fCoc, -1.0, 0.0) * w;\n#else\n texel = texel;\n #if !defined(BLUR_NEARFIELD)\n float fCoc = decodeFloat(texture2D(coc, uv)) * 2.0 - 1.0;\n w *= abs(fCoc);\n #endif\n texel.rgb *= texel.a;\n color += texel * w;\n#endif\n\n weightSum += w;\n }\n\n#ifdef BLUR_COC\n gl_FragColor = encodeFloat(clamp(cocSum / weightSum, -1.0, 0.0) * 0.5 + 0.5);\n#else\n color /= weightSum;\n color.rgb /= (color.a + 0.0001);\n gl_FragColor = color;\n#endif\n}\n\n@end"); + + +/***/ }), +/* 199 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony default export */ __webpack_exports__["a"] = ("@export ecgl.edge\n\nuniform sampler2D texture;\n\nuniform sampler2D normalTexture;\nuniform sampler2D depthTexture;\n\nuniform mat4 projectionInv;\n\nuniform vec2 textureSize;\n\nuniform vec4 edgeColor: [0,0,0,0.8];\n\nvarying vec2 v_Texcoord;\n\nvec3 packColor(vec2 coord) {\n float z = texture2D(depthTexture, coord).r * 2.0 - 1.0;\n vec4 p = vec4(v_Texcoord * 2.0 - 1.0, z, 1.0);\n vec4 p4 = projectionInv * p;\n\n return vec3(\n texture2D(normalTexture, coord).rg,\n -p4.z / p4.w / 5.0\n );\n}\n\nvoid main() {\n vec2 cc = v_Texcoord;\n vec3 center = packColor(cc);\n\n float size = clamp(1.0 - (center.z - 10.0) / 100.0, 0.0, 1.0) * 0.5;\n float dx = size / textureSize.x;\n float dy = size / textureSize.y;\n\n vec2 coord;\n vec3 topLeft = packColor(cc+vec2(-dx, -dy));\n vec3 top = packColor(cc+vec2(0.0, -dy));\n vec3 topRight = packColor(cc+vec2(dx, -dy));\n vec3 left = packColor(cc+vec2(-dx, 0.0));\n vec3 right = packColor(cc+vec2(dx, 0.0));\n vec3 bottomLeft = packColor(cc+vec2(-dx, dy));\n vec3 bottom = packColor(cc+vec2(0.0, dy));\n vec3 bottomRight = packColor(cc+vec2(dx, dy));\n\n vec3 v = -topLeft-2.0*top-topRight+bottomLeft+2.0*bottom+bottomRight;\n vec3 h = -bottomLeft-2.0*left-topLeft+bottomRight+2.0*right+topRight;\n\n float edge = sqrt(dot(h, h) + dot(v, v));\n\n edge = smoothstep(0.8, 1.0, edge);\n\n gl_FragColor = mix(texture2D(texture, v_Texcoord), vec4(edgeColor.rgb, 1.0), edgeColor.a * edge);\n}\n@end"); + + +/***/ }), +/* 200 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__halton__ = __webpack_require__(49); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_claygl_src_compositor_Pass__ = __webpack_require__(16); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2_claygl_src_FrameBuffer__ = __webpack_require__(10); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3_claygl_src_Texture2D__ = __webpack_require__(5); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4_claygl_src_Shader__ = __webpack_require__(8); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_5_claygl_src_math_Matrix4__ = __webpack_require__(9); +// Temporal Super Sample for static Scene + + + + + + + +function TemporalSuperSampling (frames) { + var haltonSequence = []; + + for (var i = 0; i < 30; i++) { + haltonSequence.push([Object(__WEBPACK_IMPORTED_MODULE_0__halton__["a" /* default */])(i, 2), Object(__WEBPACK_IMPORTED_MODULE_0__halton__["a" /* default */])(i, 3)]); + } + + this._haltonSequence = haltonSequence; + + this._frame = 0; + + this._sourceTex = new __WEBPACK_IMPORTED_MODULE_3_claygl_src_Texture2D__["a" /* default */](); + this._sourceFb = new __WEBPACK_IMPORTED_MODULE_2_claygl_src_FrameBuffer__["a" /* default */](); + this._sourceFb.attach(this._sourceTex); + + // Frame texture before temporal supersampling + this._prevFrameTex = new __WEBPACK_IMPORTED_MODULE_3_claygl_src_Texture2D__["a" /* default */](); + this._outputTex = new __WEBPACK_IMPORTED_MODULE_3_claygl_src_Texture2D__["a" /* default */](); + + var blendPass = this._blendPass = new __WEBPACK_IMPORTED_MODULE_1_claygl_src_compositor_Pass__["a" /* default */]({ + fragment: __WEBPACK_IMPORTED_MODULE_4_claygl_src_Shader__["a" /* default */].source('clay.compositor.blend') + }); + blendPass.material.disableTexturesAll(); + blendPass.material.enableTexture(['texture1', 'texture2']); + + this._blendFb = new __WEBPACK_IMPORTED_MODULE_2_claygl_src_FrameBuffer__["a" /* default */]({ + depthBuffer: false + }); + + this._outputPass = new __WEBPACK_IMPORTED_MODULE_1_claygl_src_compositor_Pass__["a" /* default */]({ + fragment: __WEBPACK_IMPORTED_MODULE_4_claygl_src_Shader__["a" /* default */].source('clay.compositor.output'), + // TODO, alpha is premultiplied? + blendWithPrevious: true + }); + this._outputPass.material.define('fragment', 'OUTPUT_ALPHA'); + this._outputPass.material.blend = function (_gl) { + // FIXME. + // Output is premultiplied alpha when BLEND is enabled ? + // http://stackoverflow.com/questions/2171085/opengl-blending-with-previous-contents-of-framebuffer + _gl.blendEquationSeparate(_gl.FUNC_ADD, _gl.FUNC_ADD); + _gl.blendFuncSeparate(_gl.ONE, _gl.ONE_MINUS_SRC_ALPHA, _gl.ONE, _gl.ONE_MINUS_SRC_ALPHA); + }; +} + +TemporalSuperSampling.prototype = { + + constructor: TemporalSuperSampling, + + /** + * Jitter camera projectionMatrix + * @parma {clay.Renderer} renderer + * @param {clay.Camera} camera + */ + jitterProjection: function (renderer, camera) { + var viewport = renderer.viewport; + var dpr = viewport.devicePixelRatio || renderer.getDevicePixelRatio(); + var width = viewport.width * dpr; + var height = viewport.height * dpr; + + var offset = this._haltonSequence[this._frame % this._haltonSequence.length]; + + var translationMat = new __WEBPACK_IMPORTED_MODULE_5_claygl_src_math_Matrix4__["a" /* default */](); + translationMat.array[12] = (offset[0] * 2.0 - 1.0) / width; + translationMat.array[13] = (offset[1] * 2.0 - 1.0) / height; + + __WEBPACK_IMPORTED_MODULE_5_claygl_src_math_Matrix4__["a" /* default */].mul(camera.projectionMatrix, translationMat, camera.projectionMatrix); + + __WEBPACK_IMPORTED_MODULE_5_claygl_src_math_Matrix4__["a" /* default */].invert(camera.invProjectionMatrix, camera.projectionMatrix); + }, + + /** + * Reset accumulating frame + */ + resetFrame: function () { + this._frame = 0; + }, + + /** + * Return current frame + */ + getFrame: function () { + return this._frame; + }, + + /** + * Get source framebuffer for usage + */ + getSourceFrameBuffer: function () { + return this._sourceFb; + }, + + getOutputTexture: function () { + return this._outputTex; + }, + + resize: function (width, height) { + this._prevFrameTex.width = width; + this._prevFrameTex.height = height; + + this._outputTex.width = width; + this._outputTex.height = height; + + this._sourceTex.width = width; + this._sourceTex.height = height; + + this._prevFrameTex.dirty(); + this._outputTex.dirty(); + this._sourceTex.dirty(); + }, + + isFinished: function () { + return this._frame >= this._haltonSequence.length; + }, + + render: function (renderer, sourceTex, notOutput) { + var blendPass = this._blendPass; + if (this._frame === 0) { + // Direct output + blendPass.setUniform('weight1', 0); + blendPass.setUniform('weight2', 1); + } + else { + blendPass.setUniform('weight1', 0.9); + blendPass.setUniform('weight2', 0.1); + } + blendPass.setUniform('texture1', this._prevFrameTex); + blendPass.setUniform('texture2', sourceTex || this._sourceTex); + + this._blendFb.attach(this._outputTex); + this._blendFb.bind(renderer); + blendPass.render(renderer); + this._blendFb.unbind(renderer); + + if (!notOutput) { + this._outputPass.setUniform('texture', this._outputTex); + this._outputPass.render(renderer); + } + + // Swap texture + var tmp = this._prevFrameTex; + this._prevFrameTex = this._outputTex; + this._outputTex = tmp; + + this._frame++; + }, + + dispose: function (renderer) { + this._sourceFb.dispose(renderer); + this._blendFb.dispose(renderer); + this._prevFrameTex.dispose(renderer); + this._outputTex.dispose(renderer); + this._sourceTex.dispose(renderer); + this._outputPass.dispose(renderer); + this._blendPass.dispose(renderer); + } +}; + +/* harmony default export */ __webpack_exports__["a"] = (TemporalSuperSampling); + +/***/ }), +/* 201 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__geo3D_Geo3DModel__ = __webpack_require__(202); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__geo3D_Geo3DView__ = __webpack_require__(203); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__coord_geo3DCreator__ = __webpack_require__(98); + + + + + + + +__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.registerAction({ + type: 'geo3DChangeCamera', + event: 'geo3dcamerachanged', + update: 'series:updateCamera' +}, function (payload, ecModel) { + ecModel.eachComponent({ + mainType: 'geo3D', query: payload + }, function (componentModel) { + componentModel.setView(payload); + }); +}); + +/***/ }), +/* 202 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__common_componentViewControlMixin__ = __webpack_require__(44); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__common_componentPostEffectMixin__ = __webpack_require__(28); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__common_componentLightMixin__ = __webpack_require__(29); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4__common_componentShadingMixin__ = __webpack_require__(31); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_5__coord_geo3D_geo3DModelMixin__ = __webpack_require__(96); + + + + + + + +var Geo3DModel = __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.extendComponentModel({ + + type: 'geo3D', + + layoutMode: 'box', + + coordinateSystem: null, + + optionUpdated: function () { + var option = this.option; + + option.regions = this.getFilledRegions(option.regions, option.map); + + var dimensions = __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.helper.completeDimensions(['value'], option.data, { + encodeDef: this.get('encode'), + dimsDef: this.get('dimensions') + }); + var list = new __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.List(dimensions, this); + list.initData(option.regions); + + var regionModelMap = {}; + list.each(function (idx) { + var name = list.getName(idx); + var itemModel = list.getItemModel(idx); + regionModelMap[name] = itemModel; + }); + + this._regionModelMap = regionModelMap; + + this._data = list; + }, + + getData: function () { + return this._data; + }, + + getRegionModel: function (idx) { + var name = this.getData().getName(idx); + return this._regionModelMap[name] || new __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.Model(null, this); + }, + + getRegionPolygonCoords: function (idx) { + var name = this.getData().getName(idx); + var region = this.coordinateSystem.getRegion(name); + + return region ? region.geometries : []; + }, + + /** + * Format label + * @param {string} name Region name + * @param {string} [status='normal'] 'normal' or 'emphasis' + * @return {string} + */ + getFormattedLabel: function (dataIndex, status) { + var name = this._data.getName(dataIndex); + var regionModel = this.getRegionModel(name); + var formatter = regionModel.get(status === 'normal' ? ['label', 'formatter'] : ['emphasis', 'label', 'formatter']); + if (formatter == null) { + formatter = regionModel.get(['label', 'formatter']); + } + var params = { + name: name + }; + if (typeof formatter === 'function') { + params.status = status; + return formatter(params); + } + else if (typeof formatter === 'string') { + var serName = params.seriesName; + return formatter.replace('{a}', serName != null ? serName : ''); + } + else { + return name; + } + }, + + defaultOption: { + + // itemStyle: {}, + // height, + // label: {} + // realisticMaterial + regions: [] + } +}); + +__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.util.merge(Geo3DModel.prototype, __WEBPACK_IMPORTED_MODULE_5__coord_geo3D_geo3DModelMixin__["a" /* default */]); + +__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.util.merge(Geo3DModel.prototype, __WEBPACK_IMPORTED_MODULE_1__common_componentViewControlMixin__["a" /* default */]); +__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.util.merge(Geo3DModel.prototype, __WEBPACK_IMPORTED_MODULE_2__common_componentPostEffectMixin__["a" /* default */]); +__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.util.merge(Geo3DModel.prototype, __WEBPACK_IMPORTED_MODULE_3__common_componentLightMixin__["a" /* default */]); +__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.util.merge(Geo3DModel.prototype, __WEBPACK_IMPORTED_MODULE_4__common_componentShadingMixin__["a" /* default */]); + +/* unused harmony default export */ var _unused_webpack_default_export = (Geo3DModel); + +/***/ }), +/* 203 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__common_Geo3DBuilder__ = __webpack_require__(64); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_echarts_lib_echarts__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_echarts_lib_echarts___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_echarts_lib_echarts__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__util_graphicGL__ = __webpack_require__(1); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__util_OrbitControl__ = __webpack_require__(45); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4__common_SceneHelper__ = __webpack_require__(30); + + + + + + + +/* unused harmony default export */ var _unused_webpack_default_export = (__WEBPACK_IMPORTED_MODULE_1_echarts_lib_echarts___default.a.extendComponentView({ + + type: 'geo3D', + + __ecgl__: true, + + init: function (ecModel, api) { + + this._geo3DBuilder = new __WEBPACK_IMPORTED_MODULE_0__common_Geo3DBuilder__["a" /* default */](api); + this.groupGL = new __WEBPACK_IMPORTED_MODULE_2__util_graphicGL__["a" /* default */].Node(); + + this._lightRoot = new __WEBPACK_IMPORTED_MODULE_2__util_graphicGL__["a" /* default */].Node(); + this._sceneHelper = new __WEBPACK_IMPORTED_MODULE_4__common_SceneHelper__["a" /* default */](this._lightRoot); + this._sceneHelper.initLight(this._lightRoot); + + this._control = new __WEBPACK_IMPORTED_MODULE_3__util_OrbitControl__["a" /* default */]({ + zr: api.getZr() + }); + this._control.init(); + }, + + render: function (geo3DModel, ecModel, api) { + this.groupGL.add(this._geo3DBuilder.rootNode); + + var geo3D = geo3DModel.coordinateSystem; + + if (!geo3D || !geo3D.viewGL) { + return; + } + + // Always have light. + geo3D.viewGL.add(this._lightRoot); + + if (geo3DModel.get('show')) { + geo3D.viewGL.add(this.groupGL); + } + else { + geo3D.viewGL.remove(this.groupGL); + } + + var control = this._control; + control.setViewGL(geo3D.viewGL); + + var viewControlModel = geo3DModel.getModel('viewControl'); + control.setFromViewControlModel(viewControlModel, 0); + + this._sceneHelper.setScene(geo3D.viewGL.scene); + this._sceneHelper.updateLight(geo3DModel); + + // Set post effect + geo3D.viewGL.setPostEffect(geo3DModel.getModel('postEffect'), api); + geo3D.viewGL.setTemporalSuperSampling(geo3DModel.getModel('temporalSuperSampling')); + + // Must update after geo3D.viewGL.setPostEffect + this._geo3DBuilder.update(geo3DModel, ecModel, api, 0, geo3DModel.getData().count()); + var srgbDefineMethod = geo3D.viewGL.isLinearSpace() ? 'define' : 'undefine'; + this._geo3DBuilder.rootNode.traverse(function (mesh) { + if (mesh.material) { + mesh.material[srgbDefineMethod]('fragment', 'SRGB_DECODE'); + } + }); + + control.off('update'); + control.on('update', function () { + api.dispatchAction({ + type: 'geo3DChangeCamera', + alpha: control.getAlpha(), + beta: control.getBeta(), + distance: control.getDistance(), + center: control.getCenter(), + from: this.uid, + geo3DId: geo3DModel.id + }); + }); + control.update(); + }, + + afterRender: function (geo3DModel, ecModel, api, layerGL) { + var renderer = layerGL.renderer; + this._sceneHelper.updateAmbientCubemap(renderer, geo3DModel, api); + + this._sceneHelper.updateSkybox(renderer, geo3DModel, api); + }, + + dispose: function () { + this._control.dispose(); + } +})); + +/***/ }), +/* 204 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +// https://github.com/mapbox/earcut/blob/master/src/earcut.js + +/* harmony default export */ __webpack_exports__["a"] = (earcut); + +function earcut(data, holeIndices, dim) { + + dim = dim || 2; + + var hasHoles = holeIndices && holeIndices.length, + outerLen = hasHoles ? holeIndices[0] * dim : data.length, + outerNode = linkedList(data, 0, outerLen, dim, true), + triangles = []; + + if (!outerNode) return triangles; + + var minX, minY, maxX, maxY, x, y, size; + + if (hasHoles) outerNode = eliminateHoles(data, holeIndices, outerNode, dim); + + // if the shape is not too simple, we'll use z-order curve hash later; calculate polygon bbox + if (data.length > 80 * dim) { + minX = maxX = data[0]; + minY = maxY = data[1]; + + for (var i = dim; i < outerLen; i += dim) { + x = data[i]; + y = data[i + 1]; + if (x < minX) minX = x; + if (y < minY) minY = y; + if (x > maxX) maxX = x; + if (y > maxY) maxY = y; + } + + // minX, minY and size are later used to transform coords into integers for z-order calculation + size = Math.max(maxX - minX, maxY - minY); + } + + earcutLinked(outerNode, triangles, dim, minX, minY, size); + + return triangles; +} + +// create a circular doubly linked list from polygon points in the specified winding order +function linkedList(data, start, end, dim, clockwise) { + var i, last; + + if (clockwise === (signedArea(data, start, end, dim) > 0)) { + for (i = start; i < end; i += dim) last = insertNode(i, data[i], data[i + 1], last); + } else { + for (i = end - dim; i >= start; i -= dim) last = insertNode(i, data[i], data[i + 1], last); + } + + if (last && equals(last, last.next)) { + removeNode(last); + last = last.next; + } + + return last; +} + +// eliminate colinear or duplicate points +function filterPoints(start, end) { + if (!start) return start; + if (!end) end = start; + + var p = start, + again; + do { + again = false; + + if (!p.steiner && (equals(p, p.next) || area(p.prev, p, p.next) === 0)) { + removeNode(p); + p = end = p.prev; + if (p === p.next) return null; + again = true; + + } else { + p = p.next; + } + } while (again || p !== end); + + return end; +} + +// main ear slicing loop which triangulates a polygon (given as a linked list) +function earcutLinked(ear, triangles, dim, minX, minY, size, pass) { + if (!ear) return; + + // interlink polygon nodes in z-order + if (!pass && size) indexCurve(ear, minX, minY, size); + + var stop = ear, + prev, next; + + // iterate through ears, slicing them one by one + while (ear.prev !== ear.next) { + prev = ear.prev; + next = ear.next; + + if (size ? isEarHashed(ear, minX, minY, size) : isEar(ear)) { + // cut off the triangle + triangles.push(prev.i / dim); + triangles.push(ear.i / dim); + triangles.push(next.i / dim); + + removeNode(ear); + + // skipping the next vertice leads to less sliver triangles + ear = next.next; + stop = next.next; + + continue; + } + + ear = next; + + // if we looped through the whole remaining polygon and can't find any more ears + if (ear === stop) { + // try filtering points and slicing again + if (!pass) { + earcutLinked(filterPoints(ear), triangles, dim, minX, minY, size, 1); + + // if this didn't work, try curing all small self-intersections locally + } else if (pass === 1) { + ear = cureLocalIntersections(ear, triangles, dim); + earcutLinked(ear, triangles, dim, minX, minY, size, 2); + + // as a last resort, try splitting the remaining polygon into two + } else if (pass === 2) { + splitEarcut(ear, triangles, dim, minX, minY, size); + } + + break; + } + } +} + +// check whether a polygon node forms a valid ear with adjacent nodes +function isEar(ear) { + var a = ear.prev, + b = ear, + c = ear.next; + + if (area(a, b, c) >= 0) return false; // reflex, can't be an ear + + // now make sure we don't have other points inside the potential ear + var p = ear.next.next; + + while (p !== ear.prev) { + if (pointInTriangle(a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y) && + area(p.prev, p, p.next) >= 0) return false; + p = p.next; + } + + return true; +} + +function isEarHashed(ear, minX, minY, size) { + var a = ear.prev, + b = ear, + c = ear.next; + + if (area(a, b, c) >= 0) return false; // reflex, can't be an ear + + // triangle bbox; min & max are calculated like this for speed + var minTX = a.x < b.x ? (a.x < c.x ? a.x : c.x) : (b.x < c.x ? b.x : c.x), + minTY = a.y < b.y ? (a.y < c.y ? a.y : c.y) : (b.y < c.y ? b.y : c.y), + maxTX = a.x > b.x ? (a.x > c.x ? a.x : c.x) : (b.x > c.x ? b.x : c.x), + maxTY = a.y > b.y ? (a.y > c.y ? a.y : c.y) : (b.y > c.y ? b.y : c.y); + + // z-order range for the current triangle bbox; + var minZ = zOrder(minTX, minTY, minX, minY, size), + maxZ = zOrder(maxTX, maxTY, minX, minY, size); + + // first look for points inside the triangle in increasing z-order + var p = ear.nextZ; + + while (p && p.z <= maxZ) { + if (p !== ear.prev && p !== ear.next && + pointInTriangle(a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y) && + area(p.prev, p, p.next) >= 0) return false; + p = p.nextZ; + } + + // then look for points in decreasing z-order + p = ear.prevZ; + + while (p && p.z >= minZ) { + if (p !== ear.prev && p !== ear.next && + pointInTriangle(a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y) && + area(p.prev, p, p.next) >= 0) return false; + p = p.prevZ; + } + + return true; +} + +// go through all polygon nodes and cure small local self-intersections +function cureLocalIntersections(start, triangles, dim) { + var p = start; + do { + var a = p.prev, + b = p.next.next; + + if (!equals(a, b) && intersects(a, p, p.next, b) && locallyInside(a, b) && locallyInside(b, a)) { + + triangles.push(a.i / dim); + triangles.push(p.i / dim); + triangles.push(b.i / dim); + + // remove two nodes involved + removeNode(p); + removeNode(p.next); + + p = start = b; + } + p = p.next; + } while (p !== start); + + return p; +} + +// try splitting polygon into two and triangulate them independently +function splitEarcut(start, triangles, dim, minX, minY, size) { + // look for a valid diagonal that divides the polygon into two + var a = start; + do { + var b = a.next.next; + while (b !== a.prev) { + if (a.i !== b.i && isValidDiagonal(a, b)) { + // split the polygon in two by the diagonal + var c = splitPolygon(a, b); + + // filter colinear points around the cuts + a = filterPoints(a, a.next); + c = filterPoints(c, c.next); + + // run earcut on each half + earcutLinked(a, triangles, dim, minX, minY, size); + earcutLinked(c, triangles, dim, minX, minY, size); + return; + } + b = b.next; + } + a = a.next; + } while (a !== start); +} + +// link every hole into the outer loop, producing a single-ring polygon without holes +function eliminateHoles(data, holeIndices, outerNode, dim) { + var queue = [], + i, len, start, end, list; + + for (i = 0, len = holeIndices.length; i < len; i++) { + start = holeIndices[i] * dim; + end = i < len - 1 ? holeIndices[i + 1] * dim : data.length; + list = linkedList(data, start, end, dim, false); + if (list === list.next) list.steiner = true; + queue.push(getLeftmost(list)); + } + + queue.sort(compareX); + + // process holes from left to right + for (i = 0; i < queue.length; i++) { + eliminateHole(queue[i], outerNode); + outerNode = filterPoints(outerNode, outerNode.next); + } + + return outerNode; +} + +function compareX(a, b) { + return a.x - b.x; +} + +// find a bridge between vertices that connects hole with an outer ring and and link it +function eliminateHole(hole, outerNode) { + outerNode = findHoleBridge(hole, outerNode); + if (outerNode) { + var b = splitPolygon(outerNode, hole); + filterPoints(b, b.next); + } +} + +// David Eberly's algorithm for finding a bridge between hole and outer polygon +function findHoleBridge(hole, outerNode) { + var p = outerNode, + hx = hole.x, + hy = hole.y, + qx = -Infinity, + m; + + // find a segment intersected by a ray from the hole's leftmost point to the left; + // segment's endpoint with lesser x will be potential connection point + do { + if (hy <= p.y && hy >= p.next.y && p.next.y !== p.y) { + var x = p.x + (hy - p.y) * (p.next.x - p.x) / (p.next.y - p.y); + if (x <= hx && x > qx) { + qx = x; + if (x === hx) { + if (hy === p.y) return p; + if (hy === p.next.y) return p.next; + } + m = p.x < p.next.x ? p : p.next; + } + } + p = p.next; + } while (p !== outerNode); + + if (!m) return null; + + if (hx === qx) return m.prev; // hole touches outer segment; pick lower endpoint + + // look for points inside the triangle of hole point, segment intersection and endpoint; + // if there are no points found, we have a valid connection; + // otherwise choose the point of the minimum angle with the ray as connection point + + var stop = m, + mx = m.x, + my = m.y, + tanMin = Infinity, + tan; + + p = m.next; + + while (p !== stop) { + if (hx >= p.x && p.x >= mx && hx !== p.x && + pointInTriangle(hy < my ? hx : qx, hy, mx, my, hy < my ? qx : hx, hy, p.x, p.y)) { + + tan = Math.abs(hy - p.y) / (hx - p.x); // tangential + + if ((tan < tanMin || (tan === tanMin && p.x > m.x)) && locallyInside(p, hole)) { + m = p; + tanMin = tan; + } + } + + p = p.next; + } + + return m; +} + +// interlink polygon nodes in z-order +function indexCurve(start, minX, minY, size) { + var p = start; + do { + if (p.z === null) p.z = zOrder(p.x, p.y, minX, minY, size); + p.prevZ = p.prev; + p.nextZ = p.next; + p = p.next; + } while (p !== start); + + p.prevZ.nextZ = null; + p.prevZ = null; + + sortLinked(p); +} + +// Simon Tatham's linked list merge sort algorithm +// http://www.chiark.greenend.org.uk/~sgtatham/algorithms/listsort.html +function sortLinked(list) { + var i, p, q, e, tail, numMerges, pSize, qSize, + inSize = 1; + + do { + p = list; + list = null; + tail = null; + numMerges = 0; + + while (p) { + numMerges++; + q = p; + pSize = 0; + for (i = 0; i < inSize; i++) { + pSize++; + q = q.nextZ; + if (!q) break; + } + qSize = inSize; + + while (pSize > 0 || (qSize > 0 && q)) { + + if (pSize !== 0 && (qSize === 0 || !q || p.z <= q.z)) { + e = p; + p = p.nextZ; + pSize--; + } else { + e = q; + q = q.nextZ; + qSize--; + } + + if (tail) tail.nextZ = e; + else list = e; + + e.prevZ = tail; + tail = e; + } + + p = q; + } + + tail.nextZ = null; + inSize *= 2; + + } while (numMerges > 1); + + return list; +} + +// z-order of a point given coords and size of the data bounding box +function zOrder(x, y, minX, minY, size) { + // coords are transformed into non-negative 15-bit integer range + x = 32767 * (x - minX) / size; + y = 32767 * (y - minY) / size; + + x = (x | (x << 8)) & 0x00FF00FF; + x = (x | (x << 4)) & 0x0F0F0F0F; + x = (x | (x << 2)) & 0x33333333; + x = (x | (x << 1)) & 0x55555555; + + y = (y | (y << 8)) & 0x00FF00FF; + y = (y | (y << 4)) & 0x0F0F0F0F; + y = (y | (y << 2)) & 0x33333333; + y = (y | (y << 1)) & 0x55555555; + + return x | (y << 1); +} + +// find the leftmost node of a polygon ring +function getLeftmost(start) { + var p = start, + leftmost = start; + do { + if (p.x < leftmost.x) leftmost = p; + p = p.next; + } while (p !== start); + + return leftmost; +} + +// check if a point lies within a convex triangle +function pointInTriangle(ax, ay, bx, by, cx, cy, px, py) { + return (cx - px) * (ay - py) - (ax - px) * (cy - py) >= 0 && + (ax - px) * (by - py) - (bx - px) * (ay - py) >= 0 && + (bx - px) * (cy - py) - (cx - px) * (by - py) >= 0; +} + +// check if a diagonal between two polygon nodes is valid (lies in polygon interior) +function isValidDiagonal(a, b) { + return a.next.i !== b.i && a.prev.i !== b.i && !intersectsPolygon(a, b) && + locallyInside(a, b) && locallyInside(b, a) && middleInside(a, b); +} + +// signed area of a triangle +function area(p, q, r) { + return (q.y - p.y) * (r.x - q.x) - (q.x - p.x) * (r.y - q.y); +} + +// check if two points are equal +function equals(p1, p2) { + return p1.x === p2.x && p1.y === p2.y; +} + +// check if two segments intersect +function intersects(p1, q1, p2, q2) { + if ((equals(p1, q1) && equals(p2, q2)) || + (equals(p1, q2) && equals(p2, q1))) return true; + return area(p1, q1, p2) > 0 !== area(p1, q1, q2) > 0 && + area(p2, q2, p1) > 0 !== area(p2, q2, q1) > 0; +} + +// check if a polygon diagonal intersects any polygon segments +function intersectsPolygon(a, b) { + var p = a; + do { + if (p.i !== a.i && p.next.i !== a.i && p.i !== b.i && p.next.i !== b.i && + intersects(p, p.next, a, b)) return true; + p = p.next; + } while (p !== a); + + return false; +} + +// check if a polygon diagonal is locally inside the polygon +function locallyInside(a, b) { + return area(a.prev, a, a.next) < 0 ? + area(a, b, a.next) >= 0 && area(a, a.prev, b) >= 0 : + area(a, b, a.prev) < 0 || area(a, a.next, b) < 0; +} + +// check if the middle point of a polygon diagonal is inside the polygon +function middleInside(a, b) { + var p = a, + inside = false, + px = (a.x + b.x) / 2, + py = (a.y + b.y) / 2; + do { + if (((p.y > py) !== (p.next.y > py)) && p.next.y !== p.y && + (px < (p.next.x - p.x) * (py - p.y) / (p.next.y - p.y) + p.x)) + inside = !inside; + p = p.next; + } while (p !== a); + + return inside; +} + +// link two polygon vertices with a bridge; if the vertices belong to the same ring, it splits polygon into two; +// if one belongs to the outer ring and another to a hole, it merges it into a single ring +function splitPolygon(a, b) { + var a2 = new Node(a.i, a.x, a.y), + b2 = new Node(b.i, b.x, b.y), + an = a.next, + bp = b.prev; + + a.next = b; + b.prev = a; + + a2.next = an; + an.prev = a2; + + b2.next = a2; + a2.prev = b2; + + bp.next = b2; + b2.prev = bp; + + return b2; +} + +// create a node and optionally link it with previous one (in a circular doubly linked list) +function insertNode(i, x, y, last) { + var p = new Node(i, x, y); + + if (!last) { + p.prev = p; + p.next = p; + + } else { + p.next = last.next; + p.prev = last; + last.next.prev = p; + last.next = p; + } + return p; +} + +function removeNode(p) { + p.next.prev = p.prev; + p.prev.next = p.next; + + if (p.prevZ) p.prevZ.nextZ = p.nextZ; + if (p.nextZ) p.nextZ.prevZ = p.prevZ; +} + +function Node(i, x, y) { + // vertice index in coordinates array + this.i = i; + + // vertex coordinates + this.x = x; + this.y = y; + + // previous and next vertice nodes in a polygon ring + this.prev = null; + this.next = null; + + // z-order curve value + this.z = null; + + // previous and next nodes in z-order + this.prevZ = null; + this.nextZ = null; + + // indicates whether this is a steiner point + this.steiner = false; +} + +// return a percentage difference between the polygon area and its triangulation area; +// used to verify correctness of triangulation +earcut.deviation = function (data, holeIndices, dim, triangles) { + var hasHoles = holeIndices && holeIndices.length; + var outerLen = hasHoles ? holeIndices[0] * dim : data.length; + + var polygonArea = Math.abs(signedArea(data, 0, outerLen, dim)); + if (hasHoles) { + for (var i = 0, len = holeIndices.length; i < len; i++) { + var start = holeIndices[i] * dim; + var end = i < len - 1 ? holeIndices[i + 1] * dim : data.length; + polygonArea -= Math.abs(signedArea(data, start, end, dim)); + } + } + + var trianglesArea = 0; + for (i = 0; i < triangles.length; i += 3) { + var a = triangles[i] * dim; + var b = triangles[i + 1] * dim; + var c = triangles[i + 2] * dim; + trianglesArea += Math.abs( + (data[a] - data[c]) * (data[b + 1] - data[a + 1]) - + (data[a] - data[b]) * (data[c + 1] - data[a + 1])); + } + + return polygonArea === 0 && trianglesArea === 0 ? 0 : + Math.abs((trianglesArea - polygonArea) / polygonArea); +}; + +function signedArea(data, start, end, dim) { + var sum = 0; + for (var i = start, j = end - dim; i < end; i += dim) { + sum += (data[j] - data[i]) * (data[i + 1] + data[j + 1]); + j = i; + } + return sum; +} + +/***/ }), +/* 205 */ +/***/ (function(module, exports, __webpack_require__) { + +var zrUtil = __webpack_require__(13); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ +var coordsOffsetMap = { + '南海诸岛': [32, 80], + // 全国 + '广东': [0, -10], + '香港': [10, 5], + '澳门': [-10, 10], + //'北京': [-10, 0], + '天津': [5, 5] +}; + +function _default(geo) { + zrUtil.each(geo.regions, function (region) { + var coordFix = coordsOffsetMap[region.name]; + + if (coordFix) { + var cp = region.center; + cp[0] += coordFix[0] / 10.5; + cp[1] += -coordFix[1] / (10.5 / 0.75); + } + }); +} + +module.exports = _default; + +/***/ }), +/* 206 */ +/***/ (function(module, exports, __webpack_require__) { + +var zrUtil = __webpack_require__(13); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ +var geoCoordMap = { + 'Russia': [100, 60], + 'United States': [-99, 38], + 'United States of America': [-99, 38] +}; + +function _default(geo) { + zrUtil.each(geo.regions, function (region) { + var geoCoord = geoCoordMap[region.name]; + + if (geoCoord) { + var cp = region.center; + cp[0] = geoCoord[0]; + cp[1] = geoCoord[1]; + } + }); +} + +module.exports = _default; + +/***/ }), +/* 207 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__globe_GlobeModel__ = __webpack_require__(208); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__globe_GlobeView__ = __webpack_require__(209); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__coord_globeCreator__ = __webpack_require__(211); + + + + + + + +__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.registerAction({ + type: 'globeChangeCamera', + event: 'globecamerachanged', + update: 'series:updateCamera' +}, function (payload, ecModel) { + ecModel.eachComponent({ + mainType: 'globe', query: payload + }, function (componentModel) { + componentModel.setView(payload); + }); +}); + +__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.registerAction({ + type: 'globeUpdateDisplacment', + event: 'globedisplacementupdated', + update: 'update' +}, function (payload, ecModel) { + // Noop +}); + +/***/ }), +/* 208 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__common_componentViewControlMixin__ = __webpack_require__(44); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__common_componentPostEffectMixin__ = __webpack_require__(28); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__common_componentLightMixin__ = __webpack_require__(29); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4__common_componentShadingMixin__ = __webpack_require__(31); + + + + + + + +function defaultId(option, idx) { + option.id = option.id || option.name || (idx + ''); +} +var GlobeModel = __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.extendComponentModel({ + + type: 'globe', + + layoutMode: 'box', + + coordinateSystem: null, + + init: function () { + GlobeModel.superApply(this, 'init', arguments); + + __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.util.each(this.option.layers, function (layerOption, idx) { + __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.util.merge(layerOption, this.defaultLayerOption); + defaultId(layerOption, idx); + }, this); + }, + + mergeOption: function (option) { + // TODO test + var oldLayers = this.option.layers; + this.option.layers = null; + GlobeModel.superApply(this, 'mergeOption', arguments); + + function createLayerMap(layers) { + return __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.util.reduce(layers, function (obj, layerOption, idx) { + defaultId(layerOption, idx); + obj[layerOption.id] = layerOption; + return obj; + }, {}); + } + if (oldLayers && oldLayers.length) { + var newLayerMap = createLayerMap(option.layers); + var oldLayerMap = createLayerMap(oldLayers); + for (var id in newLayerMap) { + if (oldLayerMap[id]) { + __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.util.merge(oldLayerMap[id], newLayerMap[id], true); + } + else { + oldLayers.push(option.layers[id]); + } + } + // Copy back + this.option.layers = oldLayers; + } + // else overwrite + + // Set default + __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.util.each(this.option.layers, function (layerOption) { + __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.util.merge(layerOption, this.defaultLayerOption); + }, this); + }, + + optionUpdated: function () { + this.updateDisplacementHash(); + }, + + defaultLayerOption: { + show: true, + type: 'overlay' + }, + + defaultOption: { + + show: true, + + zlevel: -10, + + // Layout used for viewport + left: 0, + top: 0, + width: '100%', + height: '100%', + + environment: 'auto', + + baseColor: '#fff', + + // Base albedo texture + baseTexture: '', + + // Height texture for bump mapping and vertex displacement + heightTexture: '', + + // Texture for vertex displacement, default use heightTexture + displacementTexture: '', + // Scale of vertex displacement, available only if displacementTexture is set. + displacementScale: 0, + + // Detail of displacement. 'low', 'medium', 'high', 'ultra' + displacementQuality: 'medium', + + // Globe radius + globeRadius: 100, + + // Globe outer radius. Which is max of altitude. + globeOuterRadius: 150, + + // Shading of globe + shading: 'lambert', + + // Extend light + light: { + // Main sun light + main: { + // Time, default it will use system time + time: '' + } + }, + + // light + // postEffect + // temporalSuperSampling + + viewControl: { + autoRotate: true, + + panSensitivity: 0, + + targetCoord: null + }, + + + // { + // show: true, + // name: 'cloud', + // type: 'overlay', + // shading: 'lambert', + // distance: 10, + // texture: '' + // } + // { + // type: 'blend', + // blendTo: 'albedo' + // blendType: 'source-over' + // } + + layers: [] + }, + + setDisplacementData: function (data, width, height) { + this.displacementData = data; + this.displacementWidth = width; + this.displacementHeight = height; + }, + + getDisplacementTexture: function () { + return this.get('displacementTexture') || this.get('heightTexture'); + }, + + getDisplacemenScale: function () { + var displacementTexture = this.getDisplacementTexture(); + var displacementScale = this.get('displacementScale'); + if (!displacementTexture || displacementTexture === 'none') { + displacementScale = 0; + } + return displacementScale; + }, + + hasDisplacement: function () { + return this.getDisplacemenScale() > 0; + }, + + _displacementChanged: true, + + _displacementScale: 0, + + updateDisplacementHash: function () { + var displacementTexture = this.getDisplacementTexture(); + var displacementScale = this.getDisplacemenScale(); + + this._displacementChanged = + this._displacementTexture !== displacementTexture + || this._displacementScale !== displacementScale; + + this._displacementTexture = displacementTexture; + this._displacementScale = displacementScale; + }, + + isDisplacementChanged: function () { + return this._displacementChanged; + } +}); + +__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.util.merge(GlobeModel.prototype, __WEBPACK_IMPORTED_MODULE_1__common_componentViewControlMixin__["a" /* default */]); +__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.util.merge(GlobeModel.prototype, __WEBPACK_IMPORTED_MODULE_2__common_componentPostEffectMixin__["a" /* default */]); +__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.util.merge(GlobeModel.prototype, __WEBPACK_IMPORTED_MODULE_3__common_componentLightMixin__["a" /* default */]); +__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.util.merge(GlobeModel.prototype, __WEBPACK_IMPORTED_MODULE_4__common_componentShadingMixin__["a" /* default */]); + +/* unused harmony default export */ var _unused_webpack_default_export = (GlobeModel); + +/***/ }), +/* 209 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__ = __webpack_require__(1); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__util_OrbitControl__ = __webpack_require__(45); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__common_SceneHelper__ = __webpack_require__(30); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4__util_sunCalc__ = __webpack_require__(210); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_5__util_retrieve__ = __webpack_require__(2); + + + + + + + + + +/* unused harmony default export */ var _unused_webpack_default_export = (__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.extendComponentView({ + + type: 'globe', + + __ecgl__: true, + + _displacementScale: 0, + + init: function (ecModel, api) { + this.groupGL = new __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].Node(); + + /** + * @type {clay.geometry.Sphere} + * @private + */ + this._sphereGeometry = new __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].SphereGeometry({ + widthSegments: 200, + heightSegments: 100, + dynamic: true + }); + this._overlayGeometry = new __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].SphereGeometry({ + widthSegments: 80, + heightSegments: 40 + }); + + /** + * @type {clay.geometry.Plane} + */ + this._planeGeometry = new __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].PlaneGeometry(); + + /** + * @type {clay.geometry.Mesh} + */ + this._earthMesh = new __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].Mesh({ + renderNormal: true + }); + + this._lightRoot = new __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].Node(); + this._sceneHelper = new __WEBPACK_IMPORTED_MODULE_3__common_SceneHelper__["a" /* default */](); + this._sceneHelper.initLight(this._lightRoot); + + this.groupGL.add(this._earthMesh); + + this._control = new __WEBPACK_IMPORTED_MODULE_2__util_OrbitControl__["a" /* default */]({ + zr: api.getZr() + }); + + this._control.init(); + + this._layerMeshes = {}; + }, + + render: function (globeModel, ecModel, api) { + var coordSys = globeModel.coordinateSystem; + var shading = globeModel.get('shading'); + + // Always have light. + coordSys.viewGL.add(this._lightRoot); + + if (globeModel.get('show')) { + // Add self to scene; + coordSys.viewGL.add(this.groupGL); + } + else { + coordSys.viewGL.remove(this.groupGL); + } + + this._sceneHelper.setScene(coordSys.viewGL.scene); + + // Set post effect + coordSys.viewGL.setPostEffect(globeModel.getModel('postEffect'), api); + coordSys.viewGL.setTemporalSuperSampling(globeModel.getModel('temporalSuperSampling')); + + var earthMesh = this._earthMesh; + + earthMesh.geometry = this._sphereGeometry; + + var shadingPrefix = 'ecgl.' + shading; + if (!earthMesh.material || earthMesh.material.shader.name !== shadingPrefix) { + earthMesh.material = __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].createMaterial(shadingPrefix); + } + + __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].setMaterialFromModel( + shading, earthMesh.material, globeModel, api + ); + ['roughnessMap', 'metalnessMap', 'detailMap', 'normalMap'].forEach(function (texName) { + var texture = earthMesh.material.get(texName); + if (texture) { + texture.flipY = false; + } + }) + + earthMesh.material.set('color', __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].parseColor( + globeModel.get('baseColor') + )); + + // shrink a little + var scale = coordSys.radius * 0.99; + earthMesh.scale.set(scale, scale, scale); + + var diffuseTexture = earthMesh.material.setTextureImage('diffuseMap', globeModel.get('baseTexture'), api, { + flipY: false, + anisotropic: 8 + }); + if (diffuseTexture && diffuseTexture.surface) { + diffuseTexture.surface.attachToMesh(earthMesh); + } + + // Update bump map + var bumpTexture = earthMesh.material.setTextureImage('bumpMap', globeModel.get('heightTexture'), api, { + flipY: false, + anisotropic: 8 + }); + if (bumpTexture && bumpTexture.surface) { + bumpTexture.surface.attachToMesh(earthMesh); + } + + earthMesh.material[globeModel.get('postEffect.enable') ? 'define' : 'undefine']('fragment', 'SRGB_DECODE'); + + this._updateLight(globeModel, api); + + this._displaceVertices(globeModel, api); + + this._updateViewControl(globeModel, api); + + this._updateLayers(globeModel, api); + }, + + afterRender: function (globeModel, ecModel, api, layerGL) { + // Create ambient cubemap after render because we need to know the renderer. + // TODO + var renderer = layerGL.renderer; + + this._sceneHelper.updateAmbientCubemap(renderer, globeModel, api); + + this._sceneHelper.updateSkybox(renderer, globeModel, api); + }, + + + _updateLayers: function (globeModel, api) { + var coordSys = globeModel.coordinateSystem; + var layers = globeModel.get('layers'); + + var lastDistance = coordSys.radius; + var layerDiffuseTextures = []; + var layerDiffuseIntensity = []; + + var layerEmissiveTextures = []; + var layerEmissionIntensity = []; + __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.util.each(layers, function (layerOption) { + var layerModel = new __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.Model(layerOption); + var layerType = layerModel.get('type'); + + var texture = __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].loadTexture(layerModel.get('texture'), api, { + flipY: false, + anisotropic: 8 + }); + if (texture.surface) { + texture.surface.attachToMesh(this._earthMesh); + } + + if (layerType === 'blend') { + var blendTo = layerModel.get('blendTo'); + var intensity = __WEBPACK_IMPORTED_MODULE_5__util_retrieve__["a" /* default */].firstNotNull(layerModel.get('intensity'), 1.0); + if (blendTo === 'emission') { + layerEmissiveTextures.push(texture); + layerEmissionIntensity.push(intensity); + } + else { // Default is albedo + layerDiffuseTextures.push(texture); + layerDiffuseIntensity.push(intensity); + } + } + else { // Default use overlay + var id = layerModel.get('id'); + var overlayMesh = this._layerMeshes[id]; + if (!overlayMesh) { + overlayMesh = this._layerMeshes[id] = new __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].Mesh({ + geometry: this._overlayGeometry, + castShadow: false, + ignorePicking: true + }); + } + var shading = layerModel.get('shading'); + + if (shading === 'lambert') { + overlayMesh.material = overlayMesh.__lambertMaterial || new __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].Material({ + autoUpdateTextureStatus: false, + shader: __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].createShader('ecgl.lambert'), + transparent: true, + depthMask: false + }); + overlayMesh.__lambertMaterial = overlayMesh.material; + } + else { // color + overlayMesh.material = overlayMesh.__colorMaterial || new __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].Material({ + autoUpdateTextureStatus: false, + shader: __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].createShader('ecgl.color'), + transparent: true, + depthMask: false + }); + overlayMesh.__colorMaterial = overlayMesh.material; + } + // overlay should be transparent if texture is not loaded yet. + overlayMesh.material.enableTexture('diffuseMap'); + + var distance = layerModel.get('distance'); + // Based on distance of last layer + var radius = lastDistance + (distance == null ? coordSys.radius / 100 : distance); + overlayMesh.scale.set(radius, radius, radius); + + lastDistance = radius; + + // FIXME Exists blink. + var blankTexture = this._blankTexture || (this._blankTexture = __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].createBlankTexture('rgba(255, 255, 255, 0)')); + overlayMesh.material.set('diffuseMap', blankTexture); + + __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].loadTexture(layerModel.get('texture'), api, { + flipY: false, + anisotropic: 8 + }, function (texture) { + if (texture.surface) { + texture.surface.attachToMesh(overlayMesh); + } + overlayMesh.material.set('diffuseMap', texture); + api.getZr().refresh(); + }); + + layerModel.get('show') ? this.groupGL.add(overlayMesh) : this.groupGL.remove(overlayMesh); + } + }, this); + + var earthMaterial = this._earthMesh.material; + earthMaterial.define('fragment', 'LAYER_DIFFUSEMAP_COUNT', layerDiffuseTextures.length); + earthMaterial.define('fragment', 'LAYER_EMISSIVEMAP_COUNT', layerEmissiveTextures.length); + + earthMaterial.set('layerDiffuseMap', layerDiffuseTextures); + earthMaterial.set('layerDiffuseIntensity', layerDiffuseIntensity); + earthMaterial.set('layerEmissiveMap', layerEmissiveTextures); + earthMaterial.set('layerEmissionIntensity', layerEmissionIntensity); + + var debugWireframeModel = globeModel.getModel('debug.wireframe'); + if (debugWireframeModel.get('show')) { + earthMaterial.define('both', 'WIREFRAME_TRIANGLE'); + var color = __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].parseColor( + debugWireframeModel.get('lineStyle.color') || 'rgba(0,0,0,0.5)' + ); + var width = __WEBPACK_IMPORTED_MODULE_5__util_retrieve__["a" /* default */].firstNotNull( + debugWireframeModel.get('lineStyle.width'), 1 + ); + earthMaterial.set('wireframeLineWidth', width); + earthMaterial.set('wireframeLineColor', color); + } + else { + earthMaterial.undefine('both', 'WIREFRAME_TRIANGLE'); + } + }, + + _updateViewControl: function (globeModel, api) { + var coordSys = globeModel.coordinateSystem; + // Update camera + var viewControlModel = globeModel.getModel('viewControl'); + + var camera = coordSys.viewGL.camera; + var self = this; + + function makeAction() { + return { + type: 'globeChangeCamera', + alpha: control.getAlpha(), + beta: control.getBeta(), + distance: control.getDistance() - coordSys.radius, + center: control.getCenter(), + from: self.uid, + globeId: globeModel.id + }; + } + + // Update control + var control = this._control; + control.setViewGL(coordSys.viewGL); + + var coord = viewControlModel.get('targetCoord'); + var alpha, beta; + if (coord != null) { + beta = coord[0] + 90; + alpha = coord[1]; + } + + control.setFromViewControlModel(viewControlModel, { + baseDistance: coordSys.radius, + alpha: alpha, + beta: beta + }); + + control.off('update'); + control.on('update', function () { + api.dispatchAction(makeAction()); + }); + }, + + _displaceVertices: function (globeModel, api) { + var displacementQuality = globeModel.get('displacementQuality'); + var showDebugWireframe = globeModel.get('debug.wireframe.show'); + var globe = globeModel.coordinateSystem; + + if (!globeModel.isDisplacementChanged() + && displacementQuality === this._displacementQuality + && showDebugWireframe === this._showDebugWireframe + ) { + return; + } + + this._displacementQuality = displacementQuality; + this._showDebugWireframe = showDebugWireframe; + + var geometry = this._sphereGeometry; + + var widthSegments = ({ + low: 100, + medium: 200, + high: 400, + ultra: 800 + })[displacementQuality] || 200; + var heightSegments = widthSegments / 2; + if (geometry.widthSegments !== widthSegments || showDebugWireframe) { + geometry.widthSegments = widthSegments; + geometry.heightSegments = heightSegments; + geometry.build(); + } + + this._doDisplaceVertices(geometry, globe); + + if (showDebugWireframe) { + geometry.generateBarycentric(); + } + }, + + _doDisplaceVertices: function (geometry, globe) { + var positionArr = geometry.attributes.position.value; + var uvArr = geometry.attributes.texcoord0.value; + + var originalPositionArr = geometry.__originalPosition; + if (!originalPositionArr || originalPositionArr.length !== positionArr.length) { + originalPositionArr = new Float32Array(positionArr.length); + originalPositionArr.set(positionArr); + geometry.__originalPosition = originalPositionArr; + } + + var width = globe.displacementWidth; + var height = globe.displacementHeight; + var data = globe.displacementData; + + for (var i = 0; i < geometry.vertexCount; i++) { + var i3 = i * 3; + var i2 = i * 2; + var x = originalPositionArr[i3 + 1]; + var y = originalPositionArr[i3 + 2]; + var z = originalPositionArr[i3 + 3]; + + var u = uvArr[i2++]; + var v = uvArr[i2++]; + + var j = Math.round(u * (width - 1)); + var k = Math.round(v * (height - 1)); + var idx = k * width + j; + var scale = data ? data[idx] : 0; + + positionArr[i3 + 1] = x + x * scale; + positionArr[i3 + 2] = y + y * scale; + positionArr[i3 + 3] = z + z * scale; + } + + geometry.generateVertexNormals(); + geometry.dirty(); + + geometry.updateBoundingBox(); + }, + + _updateLight: function (globeModel, api) { + var earthMesh = this._earthMesh; + + this._sceneHelper.updateLight(globeModel); + var mainLight = this._sceneHelper.mainLight; + + // Put sun in the right position + var time = globeModel.get('light.main.time') || new Date(); + + // http://en.wikipedia.org/wiki/Azimuth + var pos = __WEBPACK_IMPORTED_MODULE_4__util_sunCalc__["a" /* default */].getPosition(__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.number.parseDate(time), 0, 0); + var r0 = Math.cos(pos.altitude); + // FIXME How to calculate the y ? + mainLight.position.y = -r0 * Math.cos(pos.azimuth); + mainLight.position.x = Math.sin(pos.altitude); + mainLight.position.z = r0 * Math.sin(pos.azimuth); + mainLight.lookAt(earthMesh.getWorldPosition()); + }, + + dispose: function (ecModel, api) { + this.groupGL.removeAll(); + this._control.dispose(); + } +})); + +/***/ }), +/* 210 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* + (c) 2011-2014, Vladimir Agafonkin + SunCalc is a JavaScript library for calculating sun/mooon position and light phases. + https://github.com/mourner/suncalc +*/ + +// shortcuts for easier to read formulas + +var PI = Math.PI, + sin = Math.sin, + cos = Math.cos, + tan = Math.tan, + asin = Math.asin, + atan = Math.atan2, + rad = PI / 180; + +// sun calculations are based on http://aa.quae.nl/en/reken/zonpositie.html formulas + + +// date/time constants and conversions + +var dayMs = 1000 * 60 * 60 * 24, + J1970 = 2440588, + J2000 = 2451545; + +function toJulian (date) { return date.valueOf() / dayMs - 0.5 + J1970; } +function toDays (date) { return toJulian(date) - J2000; } + + +// general calculations for position + +var e = rad * 23.4397; // obliquity of the Earth + +function rightAscension(l, b) { return atan(sin(l) * cos(e) - tan(b) * sin(e), cos(l)); } +function declination(l, b) { return asin(sin(b) * cos(e) + cos(b) * sin(e) * sin(l)); } + +function azimuth(H, phi, dec) { return atan(sin(H), cos(H) * sin(phi) - tan(dec) * cos(phi)); } +function altitude(H, phi, dec) { return asin(sin(phi) * sin(dec) + cos(phi) * cos(dec) * cos(H)); } + +function siderealTime(d, lw) { return rad * (280.16 + 360.9856235 * d) - lw; } + + +// general sun calculations + +function solarMeanAnomaly(d) { return rad * (357.5291 + 0.98560028 * d); } + +function eclipticLongitude(M) { + + var C = rad * (1.9148 * sin(M) + 0.02 * sin(2 * M) + 0.0003 * sin(3 * M)), // equation of center + P = rad * 102.9372; // perihelion of the Earth + + return M + C + P + PI; +} + +function sunCoords(d) { + + var M = solarMeanAnomaly(d), + L = eclipticLongitude(M); + + return { + dec: declination(L, 0), + ra: rightAscension(L, 0) + }; +} + +var SunCalc = {}; + +// calculates sun position for a given date and latitude/longitude + +SunCalc.getPosition = function (date, lat, lng) { + + var lw = rad * -lng, + phi = rad * lat, + d = toDays(date), + + c = sunCoords(d), + H = siderealTime(d, lw) - c.ra; + + return { + azimuth: azimuth(H, phi, c.dec), + altitude: altitude(H, phi, c.dec) + }; +}; + +/* harmony default export */ __webpack_exports__["a"] = (SunCalc); + +/***/ }), +/* 211 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__globe_Globe__ = __webpack_require__(212); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_echarts_lib_echarts__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_echarts_lib_echarts___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_echarts_lib_echarts__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2_echarts_lib_util_layout__ = __webpack_require__(47); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2_echarts_lib_util_layout___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_2_echarts_lib_util_layout__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__core_ViewGL__ = __webpack_require__(22); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4__util_retrieve__ = __webpack_require__(2); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_5__util_graphicGL__ = __webpack_require__(1); + + + + + + + +function getDisplacementData(img, displacementScale) { + var canvas = document.createElement('canvas'); + var ctx = canvas.getContext('2d'); + var width = img.width; + var height = img.height; + canvas.width = width; + canvas.height = height; + ctx.drawImage(img, 0, 0, width, height); + var rgbaArr = ctx.getImageData(0, 0, width, height).data; + + var displacementArr = new Float32Array(rgbaArr.length / 4); + for (var i = 0; i < rgbaArr.length / 4; i++) { + var x = rgbaArr[i * 4]; + displacementArr[i] = x / 255 * displacementScale; + } + return { + data: displacementArr, + width: width, + height: height + }; +} + +function resizeGlobe(globeModel, api) { + // Use left/top/width/height + var boxLayoutOption = globeModel.getBoxLayoutParams(); + + var viewport = __WEBPACK_IMPORTED_MODULE_2_echarts_lib_util_layout___default.a.getLayoutRect(boxLayoutOption, { + width: api.getWidth(), + height: api.getHeight() + }); + + // Flip Y + viewport.y = api.getHeight() - viewport.y - viewport.height; + + this.viewGL.setViewport(viewport.x, viewport.y, viewport.width, viewport.height, api.getDevicePixelRatio()); + + this.radius = globeModel.get('globeRadius'); + + var outerRadius = globeModel.get('globeOuterRadius'); + if (this.altitudeAxis) { + this.altitudeAxis.setExtent(0, outerRadius - this.radius); + } +} + +function updateGlobe(ecModel, api) { + + var altitudeDataExtent = [Infinity, -Infinity] + + ecModel.eachSeries(function (seriesModel) { + if (seriesModel.coordinateSystem !== this) { + return; + } + + // Get altitude data extent. + var data = seriesModel.getData(); + var altDims = seriesModel.coordDimToDataDim('alt'); + var altDim = altDims && altDims[0]; + if (altDim) { + // TODO altitiude is in coords of lines. + var dataExtent = data.getDataExtent(altDim, true); + altitudeDataExtent[0] = Math.min( + altitudeDataExtent[0], dataExtent[0] + ); + altitudeDataExtent[1] = Math.max( + altitudeDataExtent[1], dataExtent[1] + ); + } + }, this); + // Create altitude axis + if (altitudeDataExtent && isFinite(altitudeDataExtent[1] - altitudeDataExtent[0])) { + var scale = __WEBPACK_IMPORTED_MODULE_1_echarts_lib_echarts___default.a.helper.createScale( + altitudeDataExtent, { + type: 'value', + // PENDING + min: 'dataMin', + max: 'dataMax' + } + ); + this.altitudeAxis = new __WEBPACK_IMPORTED_MODULE_1_echarts_lib_echarts___default.a.Axis('altitude', scale); + // Resize again + this.resize(this.model, api); + } +} + +var globeCreator = { + + dimensions: __WEBPACK_IMPORTED_MODULE_0__globe_Globe__["a" /* default */].prototype.dimensions, + + create: function (ecModel, api) { + + var globeList = []; + + ecModel.eachComponent('globe', function (globeModel) { + + // FIXME + globeModel.__viewGL = globeModel.__viewGL || new __WEBPACK_IMPORTED_MODULE_3__core_ViewGL__["a" /* default */](); + + var globe = new __WEBPACK_IMPORTED_MODULE_0__globe_Globe__["a" /* default */](); + globe.viewGL = globeModel.__viewGL; + + globeModel.coordinateSystem = globe; + globe.model = globeModel; + globeList.push(globe); + + // Inject resize + globe.resize = resizeGlobe; + globe.resize(globeModel, api); + + globe.update = updateGlobe; + }); + + ecModel.eachSeries(function (seriesModel) { + if (seriesModel.get('coordinateSystem') === 'globe') { + var globeModel = seriesModel.getReferringComponents('globe')[0]; + if (!globeModel) { + globeModel = ecModel.getComponent('globe'); + } + + if (!globeModel) { + throw new Error('globe "' + __WEBPACK_IMPORTED_MODULE_4__util_retrieve__["a" /* default */].firstNotNull( + seriesModel.get('globe3DIndex'), + seriesModel.get('globe3DId'), + 0 + ) + '" not found'); + } + + var coordSys = globeModel.coordinateSystem; + + seriesModel.coordinateSystem = coordSys; + } + }); + + ecModel.eachComponent('globe', function (globeModel, idx) { + var globe = globeModel.coordinateSystem; + + // Update displacement data + var displacementTextureValue = globeModel.getDisplacementTexture(); + var displacementScale = globeModel.getDisplacemenScale(); + + if (globeModel.isDisplacementChanged()) { + if (globeModel.hasDisplacement()) { + var immediateLoaded = true; + __WEBPACK_IMPORTED_MODULE_5__util_graphicGL__["a" /* default */].loadTexture(displacementTextureValue, api, function (texture) { + var img = texture.image; + var displacementData = getDisplacementData(img, displacementScale); + globeModel.setDisplacementData(displacementData.data, displacementData.width, displacementData.height); + if (!immediateLoaded) { + // Update layouts + api.dispatchAction({ + type: 'globeUpdateDisplacment' + }); + } + }); + immediateLoaded = false; + } + else { + globe.setDisplacementData(null, 0, 0); + } + + globe.setDisplacementData( + globeModel.displacementData, globeModel.displacementWidth, globeModel.displacementHeight + ); + } + }); + + return globeList; + } +}; + +__WEBPACK_IMPORTED_MODULE_1_echarts_lib_echarts___default.a.registerCoordinateSystem('globe', globeCreator); + +/* unused harmony default export */ var _unused_webpack_default_export = (globeCreator); + +/***/ }), +/* 212 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_claygl_src_dep_glmatrix__ = __webpack_require__(6); + +var vec3 = __WEBPACK_IMPORTED_MODULE_0_claygl_src_dep_glmatrix__["a" /* default */].vec3; + + +function Globe(radius) { + + this.radius = radius; + + this.viewGL = null; + + this.altitudeAxis; + + // Displacement data provided by texture. + this.displacementData = null; + this.displacementWidth; + this.displacementHeight; +} + +Globe.prototype = { + + constructor: Globe, + + dimensions: ['lng', 'lat', 'alt'], + + type: 'globe', + + containPoint: function () {}, + + setDisplacementData: function (data, width, height) { + this.displacementData = data; + this.displacementWidth = width; + this.displacementHeight = height; + }, + + _getDisplacementScale: function (lng, lat) { + var i = (lng + 180) / 360 * (this.displacementWidth - 1); + var j = (90 - lat) / 180 * (this.displacementHeight - 1); + // NEAREST SAMPLING + // TODO Better bilinear sampling + var idx = Math.round(i) + Math.round(j) * this.displacementWidth; + return this.displacementData[idx]; + }, + + dataToPoint: function (data, out) { + var lng = data[0]; + var lat = data[1]; + // Default have 0 altitude + var altVal = data[2] || 0; + + var r = this.radius; + if (this.displacementData) { + r *= 1 + this._getDisplacementScale(lng, lat); + } + if (this.altitudeAxis) { + r += this.altitudeAxis.dataToCoord(altVal); + } + + lng = lng * Math.PI / 180; + lat = lat * Math.PI / 180; + + var r0 = Math.cos(lat) * r; + + out = out || []; + // PENDING + out[0] = -r0 * Math.cos(lng + Math.PI); + out[1] = Math.sin(lat) * r; + out[2] = r0 * Math.sin(lng + Math.PI); + + return out; + }, + + pointToData: function (point, out) { + var x = point[0]; + var y = point[1]; + var z = point[2]; + var len = vec3.len(point); + x /= len; + y /= len; + z /= len; + + var theta = Math.asin(y); + var phi = Math.atan2(z, -x); + if (phi < 0) { + phi = Math.PI * 2 + phi; + } + + var lat = theta * 180 / Math.PI; + var lng = phi * 180 / Math.PI - 180; + + out = out || []; + out[0] = lng; + out[1] = lat; + out[2] = len - this.radius; + if (this.altitudeAxis) { + out[2] = this.altitudeAxis.coordToData(out[2]); + } + + return out; + } +}; + +/* harmony default export */ __webpack_exports__["a"] = (Globe); + +/***/ }), +/* 213 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__coord_mapbox3DCreator__ = __webpack_require__(214); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__mapbox3D_Mapbox3DModel__ = __webpack_require__(216); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__mapbox3D_Mapbox3DView__ = __webpack_require__(217); + + + + + + + + +__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.registerAction({ + type: 'mapbox3DChangeCamera', + event: 'mapbox3dcamerachanged', + update: 'mapbox3D:updateCamera' +}, function (payload, ecModel) { + ecModel.eachComponent({ + mainType: 'mapbox3D', query: payload + }, function (componentModel) { + componentModel.setMapboxCameraOption(payload); + }); +}); + +/***/ }), +/* 214 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__mapbox3D_Mapbox3D__ = __webpack_require__(215); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_echarts_lib_echarts__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_echarts_lib_echarts___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_echarts_lib_echarts__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__mapServiceCommon_createMapService3DCreator__ = __webpack_require__(101); + + + + +var mapbox3DCreator = Object(__WEBPACK_IMPORTED_MODULE_2__mapServiceCommon_createMapService3DCreator__["a" /* default */])('mapbox3D', __WEBPACK_IMPORTED_MODULE_0__mapbox3D_Mapbox3D__["a" /* default */], function (mapbox3DList) { + mapbox3DList.forEach(function (mapbox3D) { + mapbox3D.setCameraOption(mapbox3D.model.getMapboxCameraOption()); + }); +}); +__WEBPACK_IMPORTED_MODULE_1_echarts_lib_echarts___default.a.registerCoordinateSystem('mapbox3D', mapbox3DCreator); + +/* unused harmony default export */ var _unused_webpack_default_export = (mapbox3DCreator); + +/***/ }), +/* 215 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__mapServiceCommon_MapService3D__ = __webpack_require__(100); + + +function Mapbox3D() { + __WEBPACK_IMPORTED_MODULE_0__mapServiceCommon_MapService3D__["a" /* default */].apply(this, arguments); +} + +Mapbox3D.prototype = new __WEBPACK_IMPORTED_MODULE_0__mapServiceCommon_MapService3D__["a" /* default */](); +Mapbox3D.prototype.constructor = Mapbox3D; +Mapbox3D.prototype.type = 'mapbox3D'; + +/* harmony default export */ __webpack_exports__["a"] = (Mapbox3D); + +/***/ }), +/* 216 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__common_componentPostEffectMixin__ = __webpack_require__(28); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__common_componentLightMixin__ = __webpack_require__(29); + + + + + +var MAPBOX_CAMERA_OPTION = ['zoom', 'center', 'pitch', 'bearing']; + +var Mapbox3DModel = __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.extendComponentModel({ + + type: 'mapbox3D', + + layoutMode: 'box', + + coordinateSystem: null, + + defaultOption: { + zlevel: -10, + + style: 'mapbox://styles/mapbox/light-v9', + + center: [0, 0], + + zoom: 0, + + pitch: 0, + + bearing: 0, + + light: { + main: { + alpha: 20, + beta: 30 + } + }, + + altitudeScale: 1, + // Default depend on altitudeScale + boxHeight: 'auto' + }, + + getMapboxCameraOption: function () { + var self = this; + return MAPBOX_CAMERA_OPTION.reduce(function (obj, key) { + obj[key] = self.get(key); + return obj; + }, {}); + }, + + setMapboxCameraOption: function (option) { + if (option != null) { + MAPBOX_CAMERA_OPTION.forEach(function (key) { + if (option[key] != null) { + this.option[key] = option[key]; + } + }, this); + } + }, + + /** + * Get mapbox instance + */ + getMapbox: function () { + return this._mapbox; + }, + + setMapbox: function (mapbox) { + this._mapbox = mapbox; + } +}); + +__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.util.merge(Mapbox3DModel.prototype, __WEBPACK_IMPORTED_MODULE_1__common_componentPostEffectMixin__["a" /* default */]); +__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.util.merge(Mapbox3DModel.prototype, __WEBPACK_IMPORTED_MODULE_2__common_componentLightMixin__["a" /* default */]); + +/* unused harmony default export */ var _unused_webpack_default_export = (Mapbox3DModel); + +/***/ }), +/* 217 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__Mapbox3DLayer__ = __webpack_require__(218); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__common_SceneHelper__ = __webpack_require__(30); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__util_graphicGL__ = __webpack_require__(1); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4__util_shader_displayShadow_glsl_js__ = __webpack_require__(102); + + + + + + + +__WEBPACK_IMPORTED_MODULE_3__util_graphicGL__["a" /* default */].Shader.import(__WEBPACK_IMPORTED_MODULE_4__util_shader_displayShadow_glsl_js__["a" /* default */]); + +var TILE_SIZE = 512; + +/* unused harmony default export */ var _unused_webpack_default_export = (__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.extendComponentView({ + + type: 'mapbox3D', + + __ecgl__: true, + + init: function (ecModel, api) { + var zr = api.getZr(); + this._zrLayer = new __WEBPACK_IMPORTED_MODULE_1__Mapbox3DLayer__["a" /* default */]('mapbox3D', zr); + zr.painter.insertLayer(-1000, this._zrLayer); + + this._lightRoot = new __WEBPACK_IMPORTED_MODULE_3__util_graphicGL__["a" /* default */].Node(); + this._sceneHelper = new __WEBPACK_IMPORTED_MODULE_2__common_SceneHelper__["a" /* default */](this._lightRoot); + this._sceneHelper.initLight(this._lightRoot); + + var mapbox = this._zrLayer.getMapbox(); + var dispatchInteractAction = this._dispatchInteractAction.bind(this, api, mapbox); + + // PENDING + ['zoom', 'rotate', 'drag', 'pitch', 'rotate', 'move'].forEach(function (eName) { + mapbox.on(eName, dispatchInteractAction); + }); + + this._groundMesh = new __WEBPACK_IMPORTED_MODULE_3__util_graphicGL__["a" /* default */].Mesh({ + geometry: new __WEBPACK_IMPORTED_MODULE_3__util_graphicGL__["a" /* default */].PlaneGeometry(), + material: new __WEBPACK_IMPORTED_MODULE_3__util_graphicGL__["a" /* default */].Material({ + shader: new __WEBPACK_IMPORTED_MODULE_3__util_graphicGL__["a" /* default */].Shader({ + vertex: __WEBPACK_IMPORTED_MODULE_3__util_graphicGL__["a" /* default */].Shader.source('ecgl.displayShadow.vertex'), + fragment: __WEBPACK_IMPORTED_MODULE_3__util_graphicGL__["a" /* default */].Shader.source('ecgl.displayShadow.fragment') + }), + depthMask: false + }), + // Render first + renderOrder: -100, + culling: false, + castShadow: false, + $ignorePicking: true, + renderNormal: true + }); + }, + + render: function (mapbox3DModel, ecModel, api) { + var mapbox = this._zrLayer.getMapbox(); + var styleDesc = mapbox3DModel.get('style'); + + var styleStr = JSON.stringify(styleDesc); + if (styleStr !== this._oldStyleStr) { + if (styleDesc) { + mapbox.setStyle(styleDesc); + } + } + this._oldStyleStr = styleStr; + + mapbox.setCenter(mapbox3DModel.get('center')); + mapbox.setZoom(mapbox3DModel.get('zoom')); + mapbox.setPitch(mapbox3DModel.get('pitch')); + mapbox.setBearing(mapbox3DModel.get('bearing')); + + mapbox3DModel.setMapbox(mapbox); + + var coordSys = mapbox3DModel.coordinateSystem; + + // Not add to rootNode. Or light direction will be stretched by rootNode scale + coordSys.viewGL.scene.add(this._lightRoot); + coordSys.viewGL.add(this._groundMesh); + + this._updateGroundMesh(); + + // Update lights + this._sceneHelper.setScene(coordSys.viewGL.scene); + this._sceneHelper.updateLight(mapbox3DModel); + + // Update post effects + coordSys.viewGL.setPostEffect(mapbox3DModel.getModel('postEffect'), api); + coordSys.viewGL.setTemporalSuperSampling(mapbox3DModel.getModel('temporalSuperSampling')); + + this._mapbox3DModel = mapbox3DModel; + }, + + afterRender: function (mapbox3DModel, ecModel, api, layerGL) { + var renderer = layerGL.renderer; + this._sceneHelper.updateAmbientCubemap(renderer, mapbox3DModel, api); + this._sceneHelper.updateSkybox(renderer, mapbox3DModel, api); + + // FIXME If other series changes coordinate system. + // FIXME When doing progressive rendering. + mapbox3DModel.coordinateSystem.viewGL.scene.traverse(function (mesh) { + if (mesh.material) { + mesh.material.define('fragment', 'NORMAL_UP_AXIS', 2); + mesh.material.define('fragment', 'NORMAL_FRONT_AXIS', 1); + } + }); + }, + + updateCamera: function (mapbox3DModel, ecModel, api, payload) { + mapbox3DModel.coordinateSystem.setCameraOption(payload); + + this._updateGroundMesh(); + + api.getZr().refresh(); + }, + + _dispatchInteractAction: function (api, mapbox, mapbox3DModel) { + api.dispatchAction({ + type: 'mapbox3DChangeCamera', + pitch: mapbox.getPitch(), + zoom: mapbox.getZoom(), + center: mapbox.getCenter().toArray(), + bearing: mapbox.getBearing(), + mapbox3DId: this._mapbox3DModel && this._mapbox3DModel.id + }); + }, + + _updateGroundMesh: function () { + if (this._mapbox3DModel) { + var coordSys = this._mapbox3DModel.coordinateSystem; + var pt = coordSys.dataToPoint(coordSys.center); + this._groundMesh.position.set(pt[0], pt[1], -0.001); + + var plane = new __WEBPACK_IMPORTED_MODULE_3__util_graphicGL__["a" /* default */].Plane(new __WEBPACK_IMPORTED_MODULE_3__util_graphicGL__["a" /* default */].Vector3(0, 0, 1), 0); + var ray1 = coordSys.viewGL.camera.castRay(new __WEBPACK_IMPORTED_MODULE_3__util_graphicGL__["a" /* default */].Vector2(-1, -1)); + var ray2 = coordSys.viewGL.camera.castRay(new __WEBPACK_IMPORTED_MODULE_3__util_graphicGL__["a" /* default */].Vector2(1, 1)); + var pos0 = ray1.intersectPlane(plane); + var pos1 = ray2.intersectPlane(plane); + var scale = pos0.dist(pos1) / coordSys.viewGL.rootNode.scale.x; + this._groundMesh.scale.set(scale, scale, 1); + } + }, + + dispose: function (ecModel, api) { + if (this._zrLayer) { + this._zrLayer.dispose(); + } + api.getZr().painter.delLayer(-1000); + } +})); + +/***/ }), +/* 218 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/** + * @constructor + * @alias module:echarts-gl/component/mapbox3D/Mapbox3DLayer + * @param {string} id Layer ID + * @param {module:zrender/ZRender} zr + */ +function Mapbox3DLayer (id, zr) { + this.id = id; + this.zr = zr; + + this.dom = document.createElement('div'); + this.dom.style.cssText = 'position:absolute;left:0;right:0;top:0;bottom:0;'; + + // FIXME If in module environment. + if (!mapboxgl) { + throw new Error('Mapbox GL library must be included. See https://www.mapbox.com/mapbox-gl-js/api/'); + } + + this._mapbox = new mapboxgl.Map({ + container: this.dom + }); + + // Proxy events + this._initEvents(); + +} + +Mapbox3DLayer.prototype.resize = function () { + this._mapbox.resize(); +}; + +Mapbox3DLayer.prototype.getMapbox = function () { + return this._mapbox; +}; + +Mapbox3DLayer.prototype.clear = function () {}; +Mapbox3DLayer.prototype.refresh = function () { + this._mapbox.resize(); +}; + +var EVENTS = ['mousedown', 'mouseup', 'click', 'dblclick', 'mousemove', + 'mousewheel', 'wheel', + 'touchstart', 'touchend', 'touchmove', 'touchcancel' +]; +Mapbox3DLayer.prototype._initEvents = function () { + // Event is bound on canvas container. + var mapboxRoot = this._mapbox.getCanvasContainer(); + this._handlers = this._handlers || { + contextmenu: function (e) { + e.preventDefault(); + return false; + } + }; + EVENTS.forEach(function (eName) { + this._handlers[eName] = function (e) { + var obj = {}; + for (var name in e) { + obj[name] = e[name]; + } + obj.bubbles = false; + var newE = new e.constructor(e.type, obj); + mapboxRoot.dispatchEvent(newE); + }; + this.zr.dom.addEventListener(eName, this._handlers[eName]); + }, this); + + // PENDING + this.zr.dom.addEventListener('contextmenu', this._handlers.contextmenu); +}; + +Mapbox3DLayer.prototype.dispose = function () { + EVENTS.forEach(function (eName) { + this.zr.dom.removeEventListener(eName, this._handlers[eName]); + }, this); +}; + +/* harmony default export */ __webpack_exports__["a"] = (Mapbox3DLayer); + +/***/ }), +/* 219 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__coord_maptalks3DCreator__ = __webpack_require__(220); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__maptalks3D_Maptalks3DModel__ = __webpack_require__(222); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__maptalks3D_Maptalks3DView__ = __webpack_require__(223); +// Thanks to https://gitee.com/iverson_hu/maptalks-echarts-gl + + + + + + + + +__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.registerAction({ + type: 'maptalks3DChangeCamera', + event: 'maptalks3dcamerachanged', + update: 'maptalks3D:updateCamera' +}, function (payload, ecModel) { + ecModel.eachComponent({ + mainType: 'maptalks3D', query: payload + }, function (componentModel) { + componentModel.setMaptalksCameraOption(payload); + }); +}); + +/***/ }), +/* 220 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__maptalks3D_Maptalks3D__ = __webpack_require__(221); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_echarts_lib_echarts__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_echarts_lib_echarts___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_echarts_lib_echarts__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__mapServiceCommon_createMapService3DCreator__ = __webpack_require__(101); + + + + +var maptalks3DCreator = Object(__WEBPACK_IMPORTED_MODULE_2__mapServiceCommon_createMapService3DCreator__["a" /* default */])('maptalks3D', __WEBPACK_IMPORTED_MODULE_0__maptalks3D_Maptalks3D__["a" /* default */], function (maptalks3DList) { + maptalks3DList.forEach(function (maptalks3D) { + maptalks3D.setCameraOption(maptalks3D.model.getMaptalksCameraOption()); + }); +}); +__WEBPACK_IMPORTED_MODULE_1_echarts_lib_echarts___default.a.registerCoordinateSystem('maptalks3D', maptalks3DCreator); + +/* unused harmony default export */ var _unused_webpack_default_export = (maptalks3DCreator); + +/***/ }), +/* 221 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__mapServiceCommon_MapService3D__ = __webpack_require__(100); + + +function Maptalks3D() { + __WEBPACK_IMPORTED_MODULE_0__mapServiceCommon_MapService3D__["a" /* default */].apply(this, arguments); + + this.maxPitch = 85; + this.zoomOffset = 1; +} + +Maptalks3D.prototype = new __WEBPACK_IMPORTED_MODULE_0__mapServiceCommon_MapService3D__["a" /* default */](); +Maptalks3D.prototype.constructor = Maptalks3D; +Maptalks3D.prototype.type = 'maptalks3D'; + +/* harmony default export */ __webpack_exports__["a"] = (Maptalks3D); + +/***/ }), +/* 222 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__common_componentPostEffectMixin__ = __webpack_require__(28); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__common_componentLightMixin__ = __webpack_require__(29); + + + + + +var MAPTALKS_CAMERA_OPTION = ['zoom', 'center', 'pitch', 'bearing']; + +var Maptalks3DModel = __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.extendComponentModel({ + + type: 'maptalks3D', + + layoutMode: 'box', + + coordinateSystem: null, + + defaultOption: { + zlevel: -10, + + urlTemplate: 'http://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png', + attribution: '© OpenStreetMap contributors, © CARTO', + + center: [0, 0], + + zoom: 0, + + pitch: 0, + + bearing: 0, + + light: { + main: { + alpha: 20, + beta: 30 + } + }, + + altitudeScale: 1, + // Default depend on altitudeScale + boxHeight: 'auto' + }, + + getMaptalksCameraOption: function () { + var self = this; + return MAPTALKS_CAMERA_OPTION.reduce(function (obj, key) { + obj[key] = self.get(key); + return obj; + }, {}); + }, + + setMaptalksCameraOption: function (option) { + if (option != null) { + MAPTALKS_CAMERA_OPTION.forEach(function (key) { + if (option[key] != null) { + this.option[key] = option[key]; + } + }, this); + } + }, + + /** + * Get maptalks instance + */ + getMaptalks: function () { + return this._maptalks; + }, + + setMaptalks: function (maptalks) { + this._maptalks = maptalks; + } +}); + +__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.util.merge(Maptalks3DModel.prototype, __WEBPACK_IMPORTED_MODULE_1__common_componentPostEffectMixin__["a" /* default */]); +__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.util.merge(Maptalks3DModel.prototype, __WEBPACK_IMPORTED_MODULE_2__common_componentLightMixin__["a" /* default */]); + +/* unused harmony default export */ var _unused_webpack_default_export = (Maptalks3DModel); + +/***/ }), +/* 223 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__Maptalks3DLayer__ = __webpack_require__(224); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__common_SceneHelper__ = __webpack_require__(30); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__util_graphicGL__ = __webpack_require__(1); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4__util_shader_displayShadow_glsl_js__ = __webpack_require__(102); + + + + + + + +__WEBPACK_IMPORTED_MODULE_3__util_graphicGL__["a" /* default */].Shader.import(__WEBPACK_IMPORTED_MODULE_4__util_shader_displayShadow_glsl_js__["a" /* default */]); + +/* unused harmony default export */ var _unused_webpack_default_export = (__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.extendComponentView({ + + type: 'maptalks3D', + + __ecgl__: true, + + init: function (ecModel, api) { + this._groundMesh = new __WEBPACK_IMPORTED_MODULE_3__util_graphicGL__["a" /* default */].Mesh({ + geometry: new __WEBPACK_IMPORTED_MODULE_3__util_graphicGL__["a" /* default */].PlaneGeometry(), + material: new __WEBPACK_IMPORTED_MODULE_3__util_graphicGL__["a" /* default */].Material({ + shader: new __WEBPACK_IMPORTED_MODULE_3__util_graphicGL__["a" /* default */].Shader({ + vertex: __WEBPACK_IMPORTED_MODULE_3__util_graphicGL__["a" /* default */].Shader.source('ecgl.displayShadow.vertex'), + fragment: __WEBPACK_IMPORTED_MODULE_3__util_graphicGL__["a" /* default */].Shader.source('ecgl.displayShadow.fragment') + }), + depthMask: false + }), + // Render first + renderOrder: -100, + culling: false, + castShadow: false, + $ignorePicking: true, + renderNormal: true + }); + }, + + _initMaptalksLayer: function (mapbox3DModel, api) { + var zr = api.getZr(); + this._zrLayer = new __WEBPACK_IMPORTED_MODULE_1__Maptalks3DLayer__["a" /* default */]('maptalks3D', zr, mapbox3DModel.get('center'), mapbox3DModel.get('zoom')); + zr.painter.insertLayer(-1000, this._zrLayer); + + this._lightRoot = new __WEBPACK_IMPORTED_MODULE_3__util_graphicGL__["a" /* default */].Node(); + this._sceneHelper = new __WEBPACK_IMPORTED_MODULE_2__common_SceneHelper__["a" /* default */](this._lightRoot); + this._sceneHelper.initLight(this._lightRoot); + + var maptalks = this._zrLayer.getMaptalks(); + var dispatchInteractAction = this._dispatchInteractAction.bind(this, api, maptalks); + + // PENDING + ['zoomend', 'zooming', 'zoomstart', 'dragrotating', 'pitch', 'pitchend', 'movestart', + 'moving', 'moveend', 'resize', 'touchstart', 'touchmove', 'touchend'].forEach(function (eName) { + maptalks.on(eName, dispatchInteractAction); + }); + + }, + + render: function (maptalks3DModel, ecModel, api) { + if (!this._zrLayer) { + this._initMaptalksLayer(maptalks3DModel, api); + } + + var mtks = this._zrLayer.getMaptalks(); + var urlTemplate = maptalks3DModel.get('urlTemplate'); + + var baseLayer = mtks.getBaseLayer(); + if (urlTemplate !== this._oldUrlTemplate) { + if (!baseLayer) { + baseLayer = new maptalks.TileLayer('maptalks-echarts-gl-baselayer', { + urlTemplate: urlTemplate, + // used sequentially to help with browser parallel requests per domain limitation + subdomains: ['a', 'b', 'c'], + attribution: maptalks3DModel.get('attribution') + }); + mtks.setBaseLayer(baseLayer); + } + else { + // PENDING setOptions may not work? + baseLayer.setOptions({ + urlTemplate: urlTemplate, + attribution: maptalks3DModel.get('attribution') + }); + } + } + this._oldUrlTemplate = urlTemplate; + + mtks.setCenter(maptalks3DModel.get('center')); + mtks.setZoom(maptalks3DModel.get('zoom'),{ animation: false }); + mtks.setPitch(maptalks3DModel.get('pitch')); + mtks.setBearing(maptalks3DModel.get('bearing')); + + maptalks3DModel.setMaptalks(mtks); + + var coordSys = maptalks3DModel.coordinateSystem; + + // Not add to rootNode. Or light direction will be stretched by rootNode scale + coordSys.viewGL.scene.add(this._lightRoot); + coordSys.viewGL.add(this._groundMesh); + + this._updateGroundMesh(); + + // Update lights + this._sceneHelper.setScene(coordSys.viewGL.scene); + this._sceneHelper.updateLight(maptalks3DModel); + + // Update post effects + coordSys.viewGL.setPostEffect(maptalks3DModel.getModel('postEffect'), api); + coordSys.viewGL.setTemporalSuperSampling(maptalks3DModel.getModel('temporalSuperSampling')); + + this._maptalks3DModel = maptalks3DModel; + }, + + afterRender: function (maptalks3DModel, ecModel, api, layerGL) { + var renderer = layerGL.renderer; + this._sceneHelper.updateAmbientCubemap(renderer, maptalks3DModel, api); + this._sceneHelper.updateSkybox(renderer, maptalks3DModel, api); + + // FIXME If other series changes coordinate system. + // FIXME When doing progressive rendering. + maptalks3DModel.coordinateSystem.viewGL.scene.traverse(function (mesh) { + if (mesh.material) { + mesh.material.define('fragment', 'NORMAL_UP_AXIS', 2); + mesh.material.define('fragment', 'NORMAL_FRONT_AXIS', 1); + } + }); + }, + + updateCamera: function (maptalks3DModel, ecModel, api, payload) { + maptalks3DModel.coordinateSystem.setCameraOption(payload); + + this._updateGroundMesh(); + + api.getZr().refresh(); + }, + + _dispatchInteractAction: function (api, maptalks, maptalks3DModel) { + api.dispatchAction({ + type: 'maptalks3DChangeCamera', + pitch: maptalks.getPitch(), + zoom: maptalks.getZoom(), + center: maptalks.getCenter().toArray(), + bearing: maptalks.getBearing(), + maptalks3DId: this._maptalks3DModel && this._maptalks3DModel.id + }); + }, + + _updateGroundMesh: function () { + if (this._maptalks3DModel) { + var coordSys = this._maptalks3DModel.coordinateSystem; + var pt = coordSys.dataToPoint(coordSys.center); + this._groundMesh.position.set(pt[0], pt[1], -0.001); + + var plane = new __WEBPACK_IMPORTED_MODULE_3__util_graphicGL__["a" /* default */].Plane(new __WEBPACK_IMPORTED_MODULE_3__util_graphicGL__["a" /* default */].Vector3(0, 0, 1), 0); + var ray1 = coordSys.viewGL.camera.castRay(new __WEBPACK_IMPORTED_MODULE_3__util_graphicGL__["a" /* default */].Vector2(-1, -1)); + var ray2 = coordSys.viewGL.camera.castRay(new __WEBPACK_IMPORTED_MODULE_3__util_graphicGL__["a" /* default */].Vector2(1, 1)); + var pos0 = ray1.intersectPlane(plane); + var pos1 = ray2.intersectPlane(plane); + var scale = pos0.dist(pos1) / coordSys.viewGL.rootNode.scale.x; + this._groundMesh.scale.set(scale, scale, 1); + } + }, + + dispose: function (ecModel, api) { + if (this._zrLayer) { + this._zrLayer.dispose(); + } + api.getZr().painter.delLayer(-1000); + } +})); + +/***/ }), +/* 224 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/** + * @constructor + * @alias module:echarts-gl/component/maptalks/Maptalks3DLayer + * @param {string} id Layer ID + * @param {module:zrender/ZRender} zr + */ +function Maptalks3DLayer (id, zr, defaultCenter, defaultZoom) { + this.id = id; + this.zr = zr; + + this.dom = document.createElement('div'); + this.dom.style.cssText = 'position:absolute;left:0;right:0;top:0;bottom:0;'; + + // FIXME If in module environment. + if (!maptalks) { + throw new Error('Maptalks library must be included. See https://maptalks.org'); + } + + this._maptalks = new maptalks.Map(this.dom, { + center: defaultCenter, + zoom: defaultZoom, + fog: false + // fogColor: [0, 0, 0] + }); + + // Proxy events + this._initEvents(); + +} + +Maptalks3DLayer.prototype.resize = function () { + this._maptalks.checkSize(); +}; + +Maptalks3DLayer.prototype.getMaptalks = function () { + return this._maptalks; +}; + +Maptalks3DLayer.prototype.clear = function () {}; +Maptalks3DLayer.prototype.refresh = function () { + this._maptalks.checkSize(); +}; + +var EVENTS = ['mousedown', 'mouseup', 'click', 'dblclick', 'mousemove', + 'mousewheel', 'DOMMouseScroll', + 'touchstart', 'touchend', 'touchmove', 'touchcancel' +]; +Maptalks3DLayer.prototype._initEvents = function () { + // Event is bound on canvas container. + var maptalksRoot = this.dom; + this._handlers = this._handlers || { + contextmenu: function (e) { + e.preventDefault(); + return false; + } + }; + EVENTS.forEach(function (eName) { + this._handlers[eName] = function (e) { + var obj = {}; + for (var name in e) { + obj[name] = e[name]; + } + obj.bubbles = false; + var newE = new e.constructor(e.type, obj); + if (eName === 'mousewheel' || eName === 'DOMMouseScroll') { + // maptalks listens events to different elements? + maptalksRoot.dispatchEvent(newE); + } + else { + maptalksRoot.firstElementChild.dispatchEvent(newE); + } + }; + this.zr.dom.addEventListener(eName, this._handlers[eName]); + }, this); + + // PENDING + this.zr.dom.addEventListener('contextmenu', this._handlers.contextmenu); +}; + +Maptalks3DLayer.prototype.dispose = function () { + EVENTS.forEach(function (eName) { + this.zr.dom.removeEventListener(eName, this._handlers[eName]); + }, this); + this._maptalks.remove(); +}; + +/* harmony default export */ __webpack_exports__["a"] = (Maptalks3DLayer); + + +/***/ }), +/* 225 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__bar3D_bar3DLayout__ = __webpack_require__(226); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__bar3D_Bar3DView__ = __webpack_require__(229); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__bar3D_Bar3DSeries__ = __webpack_require__(231); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4__common_opacityVisual__ = __webpack_require__(17); + + + + + + + + + +__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.registerVisual(Object(__WEBPACK_IMPORTED_MODULE_4__common_opacityVisual__["a" /* default */])('bar3D')); + +__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.registerProcessor(function (ecModel, api) { + ecModel.eachSeriesByType('bar3d', function (seriesModel) { + var data = seriesModel.getData(); + data.filterSelf(function (idx) { + return data.hasValue(idx); + }); + }); +}); + +/***/ }), +/* 226 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_claygl_src_math_Vector3__ = __webpack_require__(3); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2_claygl_src_dep_glmatrix__ = __webpack_require__(6); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__cartesian3DLayout__ = __webpack_require__(227); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4__evaluateBarSparseness__ = __webpack_require__(228); + + + + + + +var vec3 = __WEBPACK_IMPORTED_MODULE_2_claygl_src_dep_glmatrix__["a" /* default */].vec3; +var isDimensionStacked = __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.helper.dataStack.isDimensionStacked; + +function globeLayout(seriesModel, coordSys) { + var data = seriesModel.getData(); + var barMinHeight = seriesModel.get('minHeight') || 0; + var barSize = seriesModel.get('barSize'); + var dims = ['lng', 'lat', 'alt'].map(function (coordDimName) { + return seriesModel.coordDimToDataDim(coordDimName)[0]; + }); + if (barSize == null) { + var perimeter = coordSys.radius * Math.PI; + var fillRatio = Object(__WEBPACK_IMPORTED_MODULE_4__evaluateBarSparseness__["a" /* default */])(data, dims[0], dims[1]); + barSize = [ + perimeter / Math.sqrt(data.count() / fillRatio), + perimeter / Math.sqrt(data.count() / fillRatio) + ]; + } + else if (!__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.util.isArray(barSize)) { + barSize = [barSize, barSize]; + } + + var valueDim = getValueDimension(data, dims); + + data.each(dims, function (lng, lat, val, idx) { + var stackedValue = data.get(valueDim.dimension, idx); + var baseValue = valueDim.isStacked ? (stackedValue - val) : coordSys.altitudeAxis.scale.getExtent()[0]; + // TODO Stacked with minHeight. + var height = Math.max(coordSys.altitudeAxis.dataToCoord(val), barMinHeight); + var start = coordSys.dataToPoint([lng, lat, baseValue]); + var end = coordSys.dataToPoint([lng, lat, stackedValue]); + var dir = vec3.sub([], end, start); + vec3.normalize(dir, dir); + var size = [barSize[0], height, barSize[1]]; + data.setItemLayout(idx, [start, dir, size]); + }); + + data.setLayout('orient', __WEBPACK_IMPORTED_MODULE_1_claygl_src_math_Vector3__["a" /* default */].UP.array); +} + +function geo3DLayout(seriesModel, coordSys) { + var data = seriesModel.getData(); + var barSize = seriesModel.get('barSize'); + var barMinHeight = seriesModel.get('minHeight') || 0; + var dims = ['lng', 'lat', 'alt'].map(function (coordDimName) { + return seriesModel.coordDimToDataDim(coordDimName)[0]; + }); + if (barSize == null) { + var size = Math.min(coordSys.size[0], coordSys.size[2]); + + var fillRatio = Object(__WEBPACK_IMPORTED_MODULE_4__evaluateBarSparseness__["a" /* default */])(data, dims[0], dims[1]); + barSize = [ + size / Math.sqrt(data.count() / fillRatio), + size / Math.sqrt(data.count() / fillRatio) + ]; + } + else if (!__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.util.isArray(barSize)) { + barSize = [barSize, barSize]; + } + var dir = [0, 1, 0]; + + var valueDim = getValueDimension(data, dims); + + data.each(dims, function (lng, lat, val, idx) { + var stackedValue = data.get(valueDim.dimension, idx); + var baseValue = valueDim.isStacked ? (stackedValue - val) : coordSys.altitudeAxis.scale.getExtent()[0]; + + var height = Math.max(coordSys.altitudeAxis.dataToCoord(val), barMinHeight); + var start = coordSys.dataToPoint([lng, lat, baseValue]); + var size = [barSize[0], height, barSize[1]]; + data.setItemLayout(idx, [start, dir, size]); + }); + + data.setLayout('orient', [1, 0, 0]); +} + +function mapService3DLayout(seriesModel, coordSys) { + var data = seriesModel.getData(); + var dimLng = seriesModel.coordDimToDataDim('lng')[0]; + var dimLat = seriesModel.coordDimToDataDim('lat')[0]; + var dimAlt = seriesModel.coordDimToDataDim('alt')[0]; + var barSize = seriesModel.get('barSize'); + var barMinHeight = seriesModel.get('minHeight') || 0; + + if (barSize == null) { + var xExtent = data.getDataExtent(dimLng); + var yExtent = data.getDataExtent(dimLat); + var corner0 = coordSys.dataToPoint([xExtent[0], yExtent[0]]); + var corner1 = coordSys.dataToPoint([xExtent[1], yExtent[1]]); + + var size = Math.min( + Math.abs(corner0[0] - corner1[0]), + Math.abs(corner0[1] - corner1[1]) + ) || 1; + + var fillRatio = Object(__WEBPACK_IMPORTED_MODULE_4__evaluateBarSparseness__["a" /* default */])(data, dimLng, dimLat); + // PENDING, data density + barSize = [ + size / Math.sqrt(data.count() / fillRatio), + size / Math.sqrt(data.count() / fillRatio) + ]; + } + else { + if (!__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.util.isArray(barSize)) { + barSize = [barSize, barSize]; + } + barSize[0] /= coordSys.getScale() / 16; + barSize[1] /= coordSys.getScale() / 16; + } + + var dir = [0, 0, 1]; + var dims = [dimLng, dimLat, dimAlt]; + + var valueDim = getValueDimension(data, dims); + + data.each(dims, function (lng, lat, val, idx) { + var stackedValue = data.get(valueDim.dimension, idx); + var baseValue = valueDim.isStacked ? (stackedValue - val) : 0; + + var start = coordSys.dataToPoint([lng, lat, baseValue]); + var end = coordSys.dataToPoint([lng, lat, stackedValue]); + var height = Math.max(end[2] - start[2], barMinHeight); + var size = [barSize[0], height, barSize[1]]; + data.setItemLayout(idx, [start, dir, size]); + }); + + data.setLayout('orient', [1, 0, 0]); +} + +function getValueDimension(data, dataDims) { + var isStacked = isDimensionStacked(data, dataDims[2]); + return { + dimension: isStacked + ? data.getCalculationInfo('stackResultDimension') + : dataDims[2], + isStacked: isStacked + }; +} + +__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.registerLayout(function (ecModel, api) { + ecModel.eachSeriesByType('bar3D', function (seriesModel) { + var coordSys = seriesModel.coordinateSystem; + var coordSysType = coordSys && coordSys.type; + if (coordSysType === 'globe') { + globeLayout(seriesModel, coordSys); + } + else if (coordSysType === 'cartesian3D') { + Object(__WEBPACK_IMPORTED_MODULE_3__cartesian3DLayout__["a" /* default */])(seriesModel, coordSys); + } + else if (coordSysType === 'geo3D') { + geo3DLayout(seriesModel, coordSys); + } + else if (coordSysType === 'mapbox3D' || coordSysType === 'maptalks3D') { + mapService3DLayout(seriesModel, coordSys); + } + else { + if (true) { + if (!coordSys) { + throw new Error('bar3D doesn\'t have coordinate system.'); + } + else { + throw new Error('bar3D doesn\'t support coordinate system ' + coordSys.type); + } + } + } + }); +}); + +/***/ }), +/* 227 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_claygl_src_dep_glmatrix__ = __webpack_require__(6); + + +var vec3 = __WEBPACK_IMPORTED_MODULE_1_claygl_src_dep_glmatrix__["a" /* default */].vec3; +var isDimensionStacked = __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.helper.dataStack.isDimensionStacked; + +function ifCrossZero(extent) { + var min = extent[0]; + var max = extent[1]; + return !((min > 0 && max > 0) || (min < 0 && max < 0)); +}; + +function cartesian3DLayout(seriesModel, coordSys) { + + var data = seriesModel.getData(); + // var barOnPlane = seriesModel.get('onGridPlane'); + + var barSize = seriesModel.get('barSize'); + if (barSize == null) { + var size = coordSys.size; + var barWidth; + var barDepth; + var xAxis = coordSys.getAxis('x'); + var yAxis = coordSys.getAxis('y'); + + if (xAxis.type === 'category') { + barWidth = xAxis.getBandWidth() * 0.7; + } + else { + // PENDING + barWidth = Math.round(size[0] / Math.sqrt(data.count())) * 0.6; + } + if (yAxis.type === 'category') { + barDepth = yAxis.getBandWidth() * 0.7; + } + else { + barDepth = Math.round(size[1] / Math.sqrt(data.count())) * 0.6; + } + barSize = [barWidth, barDepth]; + } + else if (!__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.util.isArray(barSize)) { + barSize = [barSize, barSize]; + } + + var zAxisExtent = coordSys.getAxis('z').scale.getExtent(); + var ifZAxisCrossZero = ifCrossZero(zAxisExtent); + + var dims = ['x', 'y', 'z'].map(function (coordDimName) { + return seriesModel.coordDimToDataDim(coordDimName)[0]; + }); + + var isStacked = isDimensionStacked(data, dims[2]); + var valueDim = isStacked + ? data.getCalculationInfo('stackResultDimension') + : dims[2]; + + data.each(dims, function (x, y, z, idx) { + // TODO zAxis is inversed + // TODO On different plane. + var stackedValue = data.get(valueDim, idx); + + var baseValue = isStacked ? (stackedValue - z) + : (ifZAxisCrossZero ? 0 : zAxisExtent[0]); + + var start = coordSys.dataToPoint([x, y, baseValue]); + var end = coordSys.dataToPoint([x, y, stackedValue]); + var height = vec3.dist(start, end); + // PENDING When zAxis is not cross zero. + var dir = [0, end[1] < start[1] ? -1 : 1, 0]; + if (Math.abs(height) === 0) { + // TODO + height = 0.1; + } + var size = [barSize[0], height, barSize[1]]; + data.setItemLayout(idx, [start, dir, size]); + }); + + data.setLayout('orient', [1, 0, 0]); +} + +/* harmony default export */ __webpack_exports__["a"] = (cartesian3DLayout); + +/***/ }), +/* 228 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony default export */ __webpack_exports__["a"] = (function (data, dimX, dimY) { + var xExtent = data.getDataExtent(dimX); + var yExtent = data.getDataExtent(dimY); + + // TODO Handle one data situation + var xSpan = (xExtent[1] - xExtent[0]) || xExtent[0]; + var ySpan = (yExtent[1] - yExtent[0]) || yExtent[0]; + var dimSize = 50; + var tmp = new Uint8Array(dimSize * dimSize); + for (var i = 0; i < data.count(); i++) { + var x = data.get(dimX, i); + var y = data.get(dimY, i); + var xIdx = Math.floor((x - xExtent[0]) / xSpan * (dimSize - 1)); + var yIdx = Math.floor((y - yExtent[0]) / ySpan * (dimSize - 1)); + var idx = yIdx * dimSize + xIdx; + tmp[idx] = tmp[idx] || 1; + } + var filledCount = 0; + for (var i = 0; i < tmp.length; i++) { + if (tmp[i]) { + filledCount++; + } + } + return filledCount / tmp.length; +});; + +/***/ }), +/* 229 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__ = __webpack_require__(1); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__util_retrieve__ = __webpack_require__(2); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__util_format__ = __webpack_require__(32); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4__util_geometry_Bars3DGeometry__ = __webpack_require__(230); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_5__component_common_LabelsBuilder__ = __webpack_require__(66); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_6_claygl_src_dep_glmatrix__ = __webpack_require__(6); + + + + + + + +var vec3 = __WEBPACK_IMPORTED_MODULE_6_claygl_src_dep_glmatrix__["a" /* default */].vec3; + +/* unused harmony default export */ var _unused_webpack_default_export = (__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.extendChartView({ + + type: 'bar3D', + + __ecgl__: true, + + init: function (ecModel, api) { + + this.groupGL = new __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].Node(); + + this._api = api; + + this._labelsBuilder = new __WEBPACK_IMPORTED_MODULE_5__component_common_LabelsBuilder__["a" /* default */](256, 256, api); + var self = this; + this._labelsBuilder.getLabelPosition = function (dataIndex, position, distance) { + if (self._data) { + var layout = self._data.getItemLayout(dataIndex); + var start = layout[0]; + var dir = layout[1]; + var height = layout[2][1]; + return vec3.scaleAndAdd([], start, dir, distance + height); + } + else { + return [0, 0]; + } + }; + + // Give a large render order. + this._labelsBuilder.getMesh().renderOrder = 100; + }, + + render: function (seriesModel, ecModel, api) { + + // Swap barMesh + var tmp = this._prevBarMesh; + this._prevBarMesh = this._barMesh; + this._barMesh = tmp; + + if (!this._barMesh) { + this._barMesh = new __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].Mesh({ + geometry: new __WEBPACK_IMPORTED_MODULE_4__util_geometry_Bars3DGeometry__["a" /* default */](), + shadowDepthMaterial: new __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].Material({ + shader: new __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].Shader( + __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].Shader.source('ecgl.sm.depth.vertex'), + __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].Shader.source('ecgl.sm.depth.fragment') + ) + }), + // Only cartesian3D enable culling + // FIXME Performance + culling: seriesModel.coordinateSystem.type === 'cartesian3D', + // Render after axes + renderOrder: 10, + // Render normal in normal pass + renderNormal: true + }); + } + + this.groupGL.remove(this._prevBarMesh); + this.groupGL.add(this._barMesh); + this.groupGL.add(this._labelsBuilder.getMesh()); + + var coordSys = seriesModel.coordinateSystem; + this._doRender(seriesModel, api); + if (coordSys && coordSys.viewGL) { + coordSys.viewGL.add(this.groupGL); + + var methodName = coordSys.viewGL.isLinearSpace() ? 'define' : 'undefine'; + this._barMesh.material[methodName]('fragment', 'SRGB_DECODE'); + } + + this._data = seriesModel.getData(); + + this._labelsBuilder.updateData(this._data); + + this._labelsBuilder.updateLabels(); + + this._updateAnimation(seriesModel); + }, + + _updateAnimation: function (seriesModel) { + __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].updateVertexAnimation( + [['prevPosition', 'position'], + ['prevNormal', 'normal']], + this._prevBarMesh, + this._barMesh, + seriesModel + ); + }, + + _doRender: function (seriesModel, api) { + var data = seriesModel.getData(); + var shading = seriesModel.get('shading'); + var enableNormal = shading !== 'color'; + var self = this; + var barMesh = this._barMesh; + + var shadingPrefix = 'ecgl.' + shading; + if (!barMesh.material || barMesh.material.shader.name !== shadingPrefix) { + barMesh.material = __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].createMaterial(shadingPrefix, ['VERTEX_COLOR']); + } + + __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].setMaterialFromModel( + shading, barMesh.material, seriesModel, api + ); + + barMesh.geometry.enableNormal = enableNormal; + + barMesh.geometry.resetOffset(); + + // Bevel settings + var bevelSize = seriesModel.get('bevelSize'); + var bevelSegments = seriesModel.get('bevelSmoothness'); + barMesh.geometry.bevelSegments = bevelSegments; + + barMesh.geometry.bevelSize = bevelSize; + + var colorArr = []; + var vertexColors = new Float32Array(data.count() * 4); + var colorOffset = 0; + var barCount = 0; + var hasTransparent = false; + + data.each(function (idx) { + if (!data.hasValue(idx)) { + return; + } + var color = data.getItemVisual(idx, 'color'); + + var opacity = data.getItemVisual(idx, 'opacity'); + if (opacity == null) { + opacity = 1; + } + + __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].parseColor(color, colorArr); + colorArr[3] *= opacity; + vertexColors[colorOffset++] = colorArr[0]; + vertexColors[colorOffset++] = colorArr[1]; + vertexColors[colorOffset++] = colorArr[2]; + vertexColors[colorOffset++] = colorArr[3]; + + if (colorArr[3] > 0) { + barCount++; + if (colorArr[3] < 0.99) { + hasTransparent = true; + } + } + }); + + barMesh.geometry.setBarCount(barCount); + + var orient = data.getLayout('orient'); + + // Map of dataIndex and barIndex. + var barIndexOfData = this._barIndexOfData = new Int32Array(data.count()); + var barCount = 0; + data.each(function (idx) { + if (!data.hasValue(idx)) { + barIndexOfData[idx] = -1; + return; + } + var layout = data.getItemLayout(idx); + var start = layout[0]; + var dir = layout[1]; + var size = layout[2]; + + var idx4 = idx * 4; + colorArr[0] = vertexColors[idx4++]; + colorArr[1] = vertexColors[idx4++]; + colorArr[2] = vertexColors[idx4++]; + colorArr[3] = vertexColors[idx4++]; + if (colorArr[3] > 0) { + self._barMesh.geometry.addBar(start, dir, orient, size, colorArr, idx); + barIndexOfData[idx] = barCount++; + } + }); + + barMesh.geometry.dirty(); + barMesh.geometry.updateBoundingBox(); + + var material = barMesh.material; + material.transparent = hasTransparent; + material.depthMask = !hasTransparent; + barMesh.geometry.sortTriangles = hasTransparent; + + this._initHandler(seriesModel, api); + }, + + _initHandler: function (seriesModel, api) { + var data = seriesModel.getData(); + var barMesh = this._barMesh; + var isCartesian3D = seriesModel.coordinateSystem.type === 'cartesian3D'; + + barMesh.seriesIndex = seriesModel.seriesIndex; + + var lastDataIndex = -1; + barMesh.off('mousemove'); + barMesh.off('mouseout'); + barMesh.on('mousemove', function (e) { + var dataIndex = barMesh.geometry.getDataIndexOfVertex(e.triangle[0]); + if (dataIndex !== lastDataIndex) { + this._downplay(lastDataIndex); + this._highlight(dataIndex); + this._labelsBuilder.updateLabels([dataIndex]); + + if (isCartesian3D) { + api.dispatchAction({ + type: 'grid3DShowAxisPointer', + value: [data.get('x', dataIndex), data.get('y', dataIndex), data.get('z', dataIndex, true)] + }); + } + } + + lastDataIndex = dataIndex; + barMesh.dataIndex = dataIndex; + }, this); + barMesh.on('mouseout', function (e) { + this._downplay(lastDataIndex); + this._labelsBuilder.updateLabels(); + lastDataIndex = -1; + barMesh.dataIndex = -1; + + if (isCartesian3D) { + api.dispatchAction({ + type: 'grid3DHideAxisPointer' + }); + } + }, this); + }, + + _highlight: function (dataIndex) { + var data = this._data; + if (!data) { + return; + } + var barIndex = this._barIndexOfData[dataIndex]; + if (barIndex < 0) { + return; + } + + var itemModel = data.getItemModel(dataIndex); + var emphasisItemStyleModel = itemModel.getModel('emphasis.itemStyle'); + var emphasisColor = emphasisItemStyleModel.get('color'); + var emphasisOpacity = emphasisItemStyleModel.get('opacity'); + if (emphasisColor == null) { + var color = data.getItemVisual(dataIndex, 'color'); + emphasisColor = __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.color.lift(color, -0.4); + } + if (emphasisOpacity == null) { + emphasisOpacity = data.getItemVisual(dataIndex, 'opacity'); + } + var colorArr = __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].parseColor(emphasisColor); + colorArr[3] *= emphasisOpacity; + + this._barMesh.geometry.setColor(barIndex, colorArr); + + this._api.getZr().refresh(); + }, + + _downplay: function (dataIndex) { + var data = this._data; + if (!data) { + return; + } + var barIndex = this._barIndexOfData[dataIndex]; + if (barIndex < 0) { + return; + } + + var color = data.getItemVisual(dataIndex, 'color'); + var opacity = data.getItemVisual(dataIndex, 'opacity'); + + var colorArr = __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].parseColor(color); + colorArr[3] *= opacity; + + this._barMesh.geometry.setColor(barIndex, colorArr); + + this._api.getZr().refresh(); + }, + + highlight: function (seriesModel, ecModel, api, payload) { + this._toggleStatus('highlight', seriesModel, ecModel, api, payload); + }, + + downplay: function (seriesModel, ecModel, api, payload) { + this._toggleStatus('downplay', seriesModel, ecModel, api, payload); + }, + + _toggleStatus: function (status, seriesModel, ecModel, api, payload) { + var data = seriesModel.getData(); + var dataIndex = __WEBPACK_IMPORTED_MODULE_2__util_retrieve__["a" /* default */].queryDataIndex(data, payload); + + var self = this; + if (dataIndex != null) { + __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.util.each(__WEBPACK_IMPORTED_MODULE_3__util_format__["a" /* default */].normalizeToArray(dataIndex), function (dataIdx) { + status === 'highlight' ? this._highlight(dataIdx) : this._downplay(dataIdx); + }, this); + } + else { + data.each(function (dataIdx) { + status === 'highlight' ? self._highlight(dataIdx) : self._downplay(dataIdx); + }); + } + }, + + remove: function () { + this.groupGL.removeAll(); + }, + + dispose: function () { + this.groupGL.removeAll(); + } +})); + +/***/ }), +/* 230 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__dynamicConvertMixin__ = __webpack_require__(38); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__trianglesSortMixin__ = __webpack_require__(65); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3_claygl_src_Geometry__ = __webpack_require__(15); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4_claygl_src_dep_glmatrix__ = __webpack_require__(6); +/** + * Geometry collecting bars data + * + * @module echarts-gl/chart/bars/BarsGeometry + * @author Yi Shen(http://github.com/pissang) + */ + + + + + + + +var vec3 = __WEBPACK_IMPORTED_MODULE_4_claygl_src_dep_glmatrix__["a" /* default */].vec3; +var mat3 = __WEBPACK_IMPORTED_MODULE_4_claygl_src_dep_glmatrix__["a" /* default */].mat3; + +/** + * @constructor + * @alias module:echarts-gl/chart/bars/BarsGeometry + * @extends clay.Geometry + */ +var BarsGeometry = __WEBPACK_IMPORTED_MODULE_3_claygl_src_Geometry__["a" /* default */].extend(function () { + return { + + attributes: { + position: new __WEBPACK_IMPORTED_MODULE_3_claygl_src_Geometry__["a" /* default */].Attribute('position', 'float', 3, 'POSITION'), + normal: new __WEBPACK_IMPORTED_MODULE_3_claygl_src_Geometry__["a" /* default */].Attribute('normal', 'float', 3, 'NORMAL'), + color: new __WEBPACK_IMPORTED_MODULE_3_claygl_src_Geometry__["a" /* default */].Attribute('color', 'float', 4, 'COLOR'), + + prevPosition: new __WEBPACK_IMPORTED_MODULE_3_claygl_src_Geometry__["a" /* default */].Attribute('prevPosition', 'float', 3), + prevNormal: new __WEBPACK_IMPORTED_MODULE_3_claygl_src_Geometry__["a" /* default */].Attribute('prevNormal', 'float', 3) + }, + + dynamic: true, + + enableNormal: false, + + bevelSize: 1, + bevelSegments: 0, + + // Map from vertexIndex to dataIndex. + _dataIndices: null, + + _vertexOffset: 0, + _triangleOffset: 0 + }; +}, +/** @lends module:echarts-gl/chart/bars/BarsGeometry.prototype */ +{ + + resetOffset: function () { + this._vertexOffset = 0; + this._triangleOffset = 0; + }, + + setBarCount: function (barCount) { + var enableNormal = this.enableNormal; + var vertexCount = this.getBarVertexCount() * barCount; + var triangleCount = this.getBarTriangleCount() * barCount; + + if (this.vertexCount !== vertexCount) { + this.attributes.position.init(vertexCount); + if (enableNormal) { + this.attributes.normal.init(vertexCount); + } + else { + this.attributes.normal.value = null; + } + this.attributes.color.init(vertexCount); + } + + if (this.triangleCount !== triangleCount) { + this.indices = vertexCount > 0xffff ? new Uint32Array(triangleCount * 3) : new Uint16Array(triangleCount * 3); + + this._dataIndices = new Uint32Array(vertexCount); + } + }, + + getBarVertexCount: function () { + var bevelSegments = this.bevelSize > 0 ? this.bevelSegments : 0; + return bevelSegments > 0 ? this._getBevelBarVertexCount(bevelSegments) + : (this.enableNormal ? 24 : 8); + }, + + getBarTriangleCount: function () { + var bevelSegments = this.bevelSize > 0 ? this.bevelSegments : 0; + return bevelSegments > 0 ? this._getBevelBarTriangleCount(bevelSegments) + : 12; + }, + + _getBevelBarVertexCount: function (bevelSegments) { + return (bevelSegments + 1) * 4 * (bevelSegments + 1) * 2; + }, + + _getBevelBarTriangleCount: function (bevelSegments) { + var widthSegments = bevelSegments * 4 + 3; + var heightSegments = bevelSegments * 2 + 1; + return (widthSegments + 1) * heightSegments * 2 + 4; + }, + + setColor: function (idx, color) { + var vertexCount = this.getBarVertexCount(); + var start = vertexCount * idx; + var end = vertexCount * (idx + 1); + for (var i = start; i < end; i++) { + this.attributes.color.set(i, color); + } + this.dirtyAttribute('color'); + }, + + /** + * Get dataIndex of vertex. + * @param {number} vertexIndex + */ + getDataIndexOfVertex: function (vertexIndex) { + return this._dataIndices ? this._dataIndices[vertexIndex] : null; + }, + + /** + * Add a bar + * @param {Array.} start + * @param {Array.} end + * @param {Array.} orient right direction + * @param {Array.} size size on x and z + * @param {Array.} color + */ + addBar: (function () { + var v3Create = vec3.create; + var v3ScaleAndAdd = vec3.scaleAndAdd; + + var end = v3Create(); + var px = v3Create(); + var py = v3Create(); + var pz = v3Create(); + var nx = v3Create(); + var ny = v3Create(); + var nz = v3Create(); + + var pts = []; + var normals = []; + for (var i = 0; i < 8; i++) { + pts[i] = v3Create(); + } + + var cubeFaces4 = [ + // PX + [0, 1, 5, 4], + // NX + [2, 3, 7, 6], + // PY + [4, 5, 6, 7], + // NY + [3, 2, 1, 0], + // PZ + [0, 4, 7, 3], + // NZ + [1, 2, 6, 5] + ]; + var face4To3 = [ + 0, 1, 2, 0, 2, 3 + ]; + var cubeFaces3 = []; + for (var i = 0; i < cubeFaces4.length; i++) { + var face4 = cubeFaces4[i]; + for (var j = 0; j < 2; j++) { + var face = []; + for (var k = 0; k < 3; k++) { + face.push(face4[face4To3[j * 3 + k]]); + } + cubeFaces3.push(face); + } + } + return function (start, dir, leftDir, size, color, dataIndex) { + + // Use vertex, triangle maybe sorted. + var startVertex = this._vertexOffset; + + if (this.bevelSize > 0 && this.bevelSegments > 0) { + this._addBevelBar(start, dir, leftDir, size, this.bevelSize, this.bevelSegments, color); + } + else { + vec3.copy(py, dir); + vec3.normalize(py, py); + // x * y => z + vec3.cross(pz, leftDir, py); + vec3.normalize(pz, pz); + // y * z => x + vec3.cross(px, py, pz); + vec3.normalize(pz, pz); + + vec3.negate(nx, px); + vec3.negate(ny, py); + vec3.negate(nz, pz); + + v3ScaleAndAdd(pts[0], start, px, size[0] / 2); + v3ScaleAndAdd(pts[0], pts[0], pz, size[2] / 2); + v3ScaleAndAdd(pts[1], start, px, size[0] / 2); + v3ScaleAndAdd(pts[1], pts[1], nz, size[2] / 2); + v3ScaleAndAdd(pts[2], start, nx, size[0] / 2); + v3ScaleAndAdd(pts[2], pts[2], nz, size[2] / 2); + v3ScaleAndAdd(pts[3], start, nx, size[0] / 2); + v3ScaleAndAdd(pts[3], pts[3], pz, size[2] / 2); + + v3ScaleAndAdd(end, start, py, size[1]); + + v3ScaleAndAdd(pts[4], end, px, size[0] / 2); + v3ScaleAndAdd(pts[4], pts[4], pz, size[2] / 2); + v3ScaleAndAdd(pts[5], end, px, size[0] / 2); + v3ScaleAndAdd(pts[5], pts[5], nz, size[2] / 2); + v3ScaleAndAdd(pts[6], end, nx, size[0] / 2); + v3ScaleAndAdd(pts[6], pts[6], nz, size[2] / 2); + v3ScaleAndAdd(pts[7], end, nx, size[0] / 2); + v3ScaleAndAdd(pts[7], pts[7], pz, size[2] / 2); + + var attributes = this.attributes; + if (this.enableNormal) { + normals[0] = px; + normals[1] = nx; + normals[2] = py; + normals[3] = ny; + normals[4] = pz; + normals[5] = nz; + + var vertexOffset = this._vertexOffset; + for (var i = 0; i < cubeFaces4.length; i++) { + var idx3 = this._triangleOffset * 3; + for (var k = 0; k < 6; k++) { + this.indices[idx3++] = vertexOffset + face4To3[k]; + } + vertexOffset += 4; + this._triangleOffset += 2; + } + + for (var i = 0; i < cubeFaces4.length; i++) { + var normal = normals[i]; + for (var k = 0; k < 4; k++) { + var idx = cubeFaces4[i][k]; + attributes.position.set(this._vertexOffset, pts[idx]); + attributes.normal.set(this._vertexOffset, normal); + attributes.color.set(this._vertexOffset++, color); + } + } + } + else { + for (var i = 0; i < cubeFaces3.length; i++) { + var idx3 = this._triangleOffset * 3; + for (var k = 0; k < 3; k++) { + this.indices[idx3 + k] = cubeFaces3[i][k] + this._vertexOffset; + } + this._triangleOffset++; + } + + for (var i = 0; i < pts.length; i++) { + attributes.position.set(this._vertexOffset, pts[i]); + attributes.color.set(this._vertexOffset++, color); + } + } + } + + var endVerex = this._vertexOffset; + + for (var i = startVertex; i < endVerex; i++) { + this._dataIndices[i] = dataIndex; + } + }; + })(), + + /** + * Add a bar with bevel + * @param {Array.} start + * @param {Array.} end + * @param {Array.} orient right direction + * @param {Array.} size size on x and z + * @param {number} bevelSize + * @param {number} bevelSegments + * @param {Array.} color + */ + _addBevelBar: (function () { + var px = vec3.create(); + var py = vec3.create(); + var pz = vec3.create(); + + var rotateMat = mat3.create(); + + var bevelStartSize = []; + + var xOffsets = [1, -1, -1, 1]; + var zOffsets = [1, 1, -1, -1]; + var yOffsets = [2, 0]; + + return function (start, dir, leftDir, size, bevelSize, bevelSegments, color) { + vec3.copy(py, dir); + vec3.normalize(py, py); + // x * y => z + vec3.cross(pz, leftDir, py); + vec3.normalize(pz, pz); + // y * z => x + vec3.cross(px, py, pz); + vec3.normalize(pz, pz); + + rotateMat[0] = px[0]; rotateMat[1] = px[1]; rotateMat[2] = px[2]; + rotateMat[3] = py[0]; rotateMat[4] = py[1]; rotateMat[5] = py[2]; + rotateMat[6] = pz[0]; rotateMat[7] = pz[1]; rotateMat[8] = pz[2]; + + bevelSize = Math.min(size[0], size[2]) / 2 * bevelSize; + + for (var i = 0; i < 3; i++) { + bevelStartSize[i] = Math.max(size[i] - bevelSize * 2, 0); + } + var rx = (size[0] - bevelStartSize[0]) / 2; + var ry = (size[1] - bevelStartSize[1]) / 2; + var rz = (size[2] - bevelStartSize[2]) / 2; + + var pos = []; + var normal = []; + var vertexOffset = this._vertexOffset; + + var endIndices = []; + for (var i = 0; i < 2; i++) { + endIndices[i] = endIndices[i] = []; + + for (var m = 0; m <= bevelSegments; m++) { + for (var j = 0; j < 4; j++) { + if ((m === 0 && i === 0) || (i === 1 && m === bevelSegments)) { + endIndices[i].push(vertexOffset); + } + for (var n = 0; n <= bevelSegments; n++) { + + var phi = n / bevelSegments * Math.PI / 2 + Math.PI / 2 * j; + var theta = m / bevelSegments * Math.PI / 2 + Math.PI / 2 * i; + // var r = rx < ry ? (rz < rx ? rz : rx) : (rz < ry ? rz : ry); + normal[0] = rx * Math.cos(phi) * Math.sin(theta); + normal[1] = ry * Math.cos(theta); + normal[2] = rz * Math.sin(phi) * Math.sin(theta); + pos[0] = normal[0] + xOffsets[j] * bevelStartSize[0] / 2; + pos[1] = (normal[1] + ry) + yOffsets[i] * bevelStartSize[1] / 2; + pos[2] = normal[2] + zOffsets[j] * bevelStartSize[2] / 2; + + // Normal is not right if rx, ry, rz not equal. + if (!(Math.abs(rx - ry) < 1e-6 && Math.abs(ry - rz) < 1e-6)) { + normal[0] /= rx * rx; + normal[1] /= ry * ry; + normal[2] /= rz * rz; + } + vec3.normalize(normal, normal); + + vec3.transformMat3(pos, pos, rotateMat); + vec3.transformMat3(normal, normal, rotateMat); + vec3.add(pos, pos, start); + + this.attributes.position.set(vertexOffset, pos); + if (this.enableNormal) { + this.attributes.normal.set(vertexOffset, normal); + } + this.attributes.color.set(vertexOffset, color); + vertexOffset++; + } + } + } + } + + var widthSegments = bevelSegments * 4 + 3; + var heightSegments = bevelSegments * 2 + 1; + + var len = widthSegments + 1; + + for (var j = 0; j < heightSegments; j ++) { + for (var i = 0; i <= widthSegments; i ++) { + var i2 = j * len + i + this._vertexOffset; + var i1 = (j * len + (i + 1) % len) + this._vertexOffset; + var i4 = (j + 1) * len + (i + 1) % len + this._vertexOffset; + var i3 = (j + 1) * len + i + this._vertexOffset; + + this.setTriangleIndices(this._triangleOffset++, [i4, i2, i1]); + this.setTriangleIndices(this._triangleOffset++, [i4, i3, i2]); + } + } + + // Close top and bottom + this.setTriangleIndices(this._triangleOffset++, [endIndices[0][0], endIndices[0][2], endIndices[0][1]]); + this.setTriangleIndices(this._triangleOffset++, [endIndices[0][0], endIndices[0][3], endIndices[0][2]]); + this.setTriangleIndices(this._triangleOffset++, [endIndices[1][0], endIndices[1][1], endIndices[1][2]]); + this.setTriangleIndices(this._triangleOffset++, [endIndices[1][0], endIndices[1][2], endIndices[1][3]]); + + this._vertexOffset = vertexOffset; + }; + })() +}); + +__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.util.defaults(BarsGeometry.prototype, __WEBPACK_IMPORTED_MODULE_1__dynamicConvertMixin__["a" /* default */]); +__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.util.defaults(BarsGeometry.prototype, __WEBPACK_IMPORTED_MODULE_2__trianglesSortMixin__["a" /* default */]); + +/* harmony default export */ __webpack_exports__["a"] = (BarsGeometry); + +/***/ }), +/* 231 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__component_common_componentShadingMixin__ = __webpack_require__(31); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__util_format__ = __webpack_require__(32); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__common_formatTooltip__ = __webpack_require__(39); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4__common_createList__ = __webpack_require__(50); + + + + + + +var Bar3DSeries = __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.extendSeriesModel({ + + type: 'series.bar3D', + + dependencies: ['globe'], + + visualColorAccessPath: 'itemStyle.color', + + getInitialData: function (option, ecModel) { + return Object(__WEBPACK_IMPORTED_MODULE_4__common_createList__["a" /* default */])(this); + }, + + getFormattedLabel: function (dataIndex, status, dataType, dimIndex) { + var text = __WEBPACK_IMPORTED_MODULE_2__util_format__["a" /* default */].getFormattedLabel(this, dataIndex, status, dataType, dimIndex); + if (text == null) { + text = this.getData().get('z', dataIndex); + } + return text; + }, + + formatTooltip: function (dataIndex) { + return Object(__WEBPACK_IMPORTED_MODULE_3__common_formatTooltip__["a" /* default */])(this, dataIndex); + }, + + defaultOption: { + + coordinateSystem: 'cartesian3D', + + globeIndex: 0, + + grid3DIndex: 0, + + zlevel: -10, + + // bevelSize, 0 has no bevel + bevelSize: 0, + // higher is smoother + bevelSmoothness: 2, + + // Bar width and depth + // barSize: [1, 1], + + // On grid plane when coordinateSystem is cartesian3D + onGridPlane: 'xy', + + // Shading of globe + shading: 'color', + + minHeight: 0, + + itemStyle: { + opacity: 1 + }, + + label: { + show: false, + distance: 2, + textStyle: { + fontSize: 14, + color: '#000', + backgroundColor: 'rgba(255,255,255,0.7)', + padding: 3, + borderRadius: 3 + } + }, + + emphasis: { + label: { + show: true + } + }, + + animationDurationUpdate: 500 + } +}); + +__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.util.merge(Bar3DSeries.prototype, __WEBPACK_IMPORTED_MODULE_1__component_common_componentShadingMixin__["a" /* default */]); + +/* unused harmony default export */ var _unused_webpack_default_export = (Bar3DSeries); + +/***/ }), +/* 232 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__line3D_Line3DSeries__ = __webpack_require__(233); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__line3D_Line3DView__ = __webpack_require__(234); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3_echarts_lib_visual_symbol__ = __webpack_require__(51); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3_echarts_lib_visual_symbol___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_3_echarts_lib_visual_symbol__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4__common_opacityVisual__ = __webpack_require__(17); + + + + + + + + +__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.registerVisual(__WEBPACK_IMPORTED_MODULE_3_echarts_lib_visual_symbol___default()('line3D', 'circle', null)); + +__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.registerVisual(Object(__WEBPACK_IMPORTED_MODULE_4__common_opacityVisual__["a" /* default */])('line3D')); + +__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.registerLayout(function (ecModel, api) { + ecModel.eachSeriesByType('line3D', function (seriesModel) { + var data = seriesModel.getData(); + var coordSys = seriesModel.coordinateSystem; + + if (coordSys) { + if (coordSys.type !== 'cartesian3D') { + if (true) { + console.error('line3D needs cartesian3D coordinateSystem'); + } + return; + } + var points = new Float32Array(data.count() * 3); + + var item = []; + var out = []; + + var coordDims = coordSys.dimensions; + var dims = coordDims.map(function (coordDim) { + return seriesModel.coordDimToDataDim(coordDim)[0]; + }); + + if (coordSys) { + data.each(dims, function (x, y, z, idx) { + item[0] = x; + item[1] = y; + item[2] = z; + + coordSys.dataToPoint(item, out); + points[idx * 3] = out[0]; + points[idx * 3 + 1] = out[1]; + points[idx * 3 + 2] = out[2]; + }); + } + data.setLayout('points', points); + } + }); +}); + +/***/ }), +/* 233 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__common_formatTooltip__ = __webpack_require__(39); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__common_createList__ = __webpack_require__(50); + + + + +var Line3DSeries = __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.extendSeriesModel({ + + type: 'series.line3D', + + dependencies: ['grid3D'], + + visualColorAccessPath: 'lineStyle.color', + + getInitialData: function (option, ecModel) { + return Object(__WEBPACK_IMPORTED_MODULE_2__common_createList__["a" /* default */])(this); + }, + + formatTooltip: function (dataIndex) { + return Object(__WEBPACK_IMPORTED_MODULE_1__common_formatTooltip__["a" /* default */])(this, dataIndex); + }, + + defaultOption: { + coordinateSystem: 'cartesian3D', + zlevel: -10, + + // Cartesian coordinate system + grid3DIndex: 0, + + lineStyle: { + width: 2 + }, + + animationDurationUpdate: 500 + } +}); + +/* unused harmony default export */ var _unused_webpack_default_export = (Line3DSeries); + +/***/ }), +/* 234 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__ = __webpack_require__(1); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__util_retrieve__ = __webpack_require__(2); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__util_geometry_Lines3D__ = __webpack_require__(25); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4_claygl_src_math_Matrix4__ = __webpack_require__(9); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_5_claygl_src_math_Vector3__ = __webpack_require__(3); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_6_zrender_lib_contain_line__ = __webpack_require__(235); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_6_zrender_lib_contain_line___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_6_zrender_lib_contain_line__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_7_claygl_src_dep_glmatrix__ = __webpack_require__(6); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_8__util_shader_lines3D_glsl_js__ = __webpack_require__(46); + + + + + + + + + + + +var vec3 = __WEBPACK_IMPORTED_MODULE_7_claygl_src_dep_glmatrix__["a" /* default */].vec3; + +__WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].Shader.import(__WEBPACK_IMPORTED_MODULE_8__util_shader_lines3D_glsl_js__["a" /* default */]); + +/* unused harmony default export */ var _unused_webpack_default_export = (__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.extendChartView({ + + type: 'line3D', + + __ecgl__: true, + + init: function (ecModel, api) { + + this.groupGL = new __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].Node(); + + this._api = api; + }, + + render: function (seriesModel, ecModel, api) { + var tmp = this._prevLine3DMesh; + this._prevLine3DMesh = this._line3DMesh; + this._line3DMesh = tmp; + + if (!this._line3DMesh) { + this._line3DMesh = new __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].Mesh({ + geometry: new __WEBPACK_IMPORTED_MODULE_3__util_geometry_Lines3D__["a" /* default */]({ + useNativeLine: false, + sortTriangles: true + }), + material: new __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].Material({ + shader: __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].createShader('ecgl.meshLines3D') + }), + // Render after axes + renderOrder: 10 + }); + this._line3DMesh.geometry.pick = this._pick.bind(this); + } + + this.groupGL.remove(this._prevLine3DMesh); + this.groupGL.add(this._line3DMesh); + + var coordSys = seriesModel.coordinateSystem; + if (coordSys && coordSys.viewGL) { + coordSys.viewGL.add(this.groupGL); + // TODO + var methodName = coordSys.viewGL.isLinearSpace() ? 'define' : 'undefine'; + this._line3DMesh.material[methodName]('fragment', 'SRGB_DECODE'); + } + this._doRender(seriesModel, api); + + this._data = seriesModel.getData(); + + this._camera = coordSys.viewGL.camera; + + this.updateCamera(); + + this._updateAnimation(seriesModel); + }, + + updateCamera: function () { + this._updateNDCPosition(); + }, + + _doRender: function (seriesModel, api) { + var data = seriesModel.getData(); + var lineMesh = this._line3DMesh; + + lineMesh.geometry.resetOffset(); + + var points = data.getLayout('points'); + + var colorArr = []; + var vertexColors = new Float32Array(points.length / 3 * 4); + var colorOffset = 0; + var hasTransparent = false; + + data.each(function (idx) { + var color = data.getItemVisual(idx, 'color'); + var opacity = data.getItemVisual(idx, 'opacity'); + if (opacity == null) { + opacity = 1; + } + + __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].parseColor(color, colorArr); + colorArr[3] *= opacity; + vertexColors[colorOffset++] = colorArr[0]; + vertexColors[colorOffset++] = colorArr[1]; + vertexColors[colorOffset++] = colorArr[2]; + vertexColors[colorOffset++] = colorArr[3]; + + if (colorArr[3] < 0.99) { + hasTransparent = true; + } + }); + + lineMesh.geometry.setVertexCount( + lineMesh.geometry.getPolylineVertexCount(points) + ); + lineMesh.geometry.setTriangleCount( + lineMesh.geometry.getPolylineTriangleCount(points) + ); + + lineMesh.geometry.addPolyline( + points, vertexColors, + __WEBPACK_IMPORTED_MODULE_2__util_retrieve__["a" /* default */].firstNotNull(seriesModel.get('lineStyle.width'), 1) + ); + + lineMesh.geometry.dirty(); + lineMesh.geometry.updateBoundingBox(); + + var material = lineMesh.material; + material.transparent = hasTransparent; + material.depthMask = !hasTransparent; + + var debugWireframeModel = seriesModel.getModel('debug.wireframe'); + if (debugWireframeModel.get('show')) { + lineMesh.geometry.createAttribute('barycentric', 'float', 3); + lineMesh.geometry.generateBarycentric(); + lineMesh.material.set('both', 'WIREFRAME_TRIANGLE'); + lineMesh.material.set( + 'wireframeLineColor', __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].parseColor( + debugWireframeModel.get('lineStyle.color') || 'rgba(0,0,0,0.5)' + ) + ); + lineMesh.material.set( + 'wireframeLineWidth', __WEBPACK_IMPORTED_MODULE_2__util_retrieve__["a" /* default */].firstNotNull( + debugWireframeModel.get('lineStyle.width'), 1 + ) + ); + } + else { + lineMesh.material.set('both', 'WIREFRAME_TRIANGLE'); + } + + this._points = points; + + this._initHandler(seriesModel, api); + }, + + _updateAnimation: function (seriesModel) { + __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].updateVertexAnimation( + [['prevPosition', 'position'], + ['prevPositionPrev', 'positionPrev'], + ['prevPositionNext', 'positionNext']], + this._prevLine3DMesh, + this._line3DMesh, + seriesModel + ); + }, + + _initHandler: function (seriesModel, api) { + var data = seriesModel.getData(); + var coordSys = seriesModel.coordinateSystem; + var lineMesh = this._line3DMesh; + + var lastDataIndex = -1; + + lineMesh.seriesIndex = seriesModel.seriesIndex; + + lineMesh.off('mousemove'); + lineMesh.off('mouseout'); + lineMesh.on('mousemove', function (e) { + var value = coordSys.pointToData(e.point.array); + var dataIndex = data.indicesOfNearest('x', value[0])[0]; + if (dataIndex !== lastDataIndex) { + // this._downplay(lastDataIndex); + // this._highlight(dataIndex); + + api.dispatchAction({ + type: 'grid3DShowAxisPointer', + value: [data.get('x', dataIndex), data.get('y', dataIndex), data.get('z', dataIndex)] + }); + + lineMesh.dataIndex = dataIndex; + } + + + lastDataIndex = dataIndex; + }, this); + lineMesh.on('mouseout', function (e) { + // this._downplay(lastDataIndex); + lastDataIndex = -1; + lineMesh.dataIndex = -1; + api.dispatchAction({ + type: 'grid3DHideAxisPointer' + }); + }, this); + }, + + // _highlight: function (dataIndex) { + // var data = this._data; + // if (!data) { + // return; + // } + + // }, + + // _downplay: function (dataIndex) { + // var data = this._data; + // if (!data) { + // return; + // } + // }, + + _updateNDCPosition: function () { + + var worldViewProjection = new __WEBPACK_IMPORTED_MODULE_4_claygl_src_math_Matrix4__["a" /* default */](); + var camera = this._camera; + __WEBPACK_IMPORTED_MODULE_4_claygl_src_math_Matrix4__["a" /* default */].multiply(worldViewProjection, camera.projectionMatrix, camera.viewMatrix); + + var positionNDC = this._positionNDC; + var points = this._points; + var nPoints = points.length / 3; + if (!positionNDC || positionNDC.length / 2 !== nPoints) { + positionNDC = this._positionNDC = new Float32Array(nPoints * 2); + } + var pos = []; + for (var i = 0; i < nPoints; i++) { + var i3 = i * 3; + var i2 = i * 2; + pos[0] = points[i3]; + pos[1] = points[i3 + 1]; + pos[2] = points[i3 + 2]; + pos[3] = 1; + + vec3.transformMat4(pos, pos, worldViewProjection.array); + positionNDC[i2] = pos[0] / pos[3]; + positionNDC[i2 + 1] = pos[1] / pos[3]; + } + }, + + _pick: function (x, y, renderer, camera, renderable, out) { + var positionNDC = this._positionNDC; + var seriesModel = this._data.hostModel; + var lineWidth = seriesModel.get('lineStyle.width'); + + var dataIndex = -1; + var width = renderer.viewport.width; + var height = renderer.viewport.height; + + var halfWidth = width * 0.5; + var halfHeight = height * 0.5; + x = (x + 1) * halfWidth; + y = (y + 1) * halfHeight; + + for (var i = 1; i < positionNDC.length / 2; i++) { + var x0 = (positionNDC[(i - 1) * 2] + 1) * halfWidth; + var y0 = (positionNDC[(i - 1) * 2 + 1] + 1) * halfHeight; + var x1 = (positionNDC[i * 2] + 1) * halfWidth; + var y1 = (positionNDC[i * 2 + 1] + 1) * halfHeight; + + if (__WEBPACK_IMPORTED_MODULE_6_zrender_lib_contain_line___default.a.containStroke(x0, y0, x1, y1, lineWidth, x, y)) { + var dist0 = (x0 - x) * (x0 - x) + (y0 - y) * (y0 - y); + var dist1 = (x1 - x) * (x1 - x) + (y1 - y) * (y1 - y); + // Nearest point. + dataIndex = dist0 < dist1 ? (i - 1) : i; + } + } + + if (dataIndex >= 0) { + var i3 = dataIndex * 3; + var point = new __WEBPACK_IMPORTED_MODULE_5_claygl_src_math_Vector3__["a" /* default */]( + this._points[i3], + this._points[i3 + 1], + this._points[i3 + 2] + ); + + out.push({ + dataIndex: dataIndex, + point: point, + pointWorld: point.clone(), + target: this._line3DMesh, + distance: this._camera.getWorldPosition().dist(point) + }); + } + }, + + remove: function () { + this.groupGL.removeAll(); + }, + + dispose: function () { + this.groupGL.removeAll(); + } +})); + +/***/ }), +/* 235 */ +/***/ (function(module, exports) { + +/** + * 线段包含判断 + * @param {number} x0 + * @param {number} y0 + * @param {number} x1 + * @param {number} y1 + * @param {number} lineWidth + * @param {number} x + * @param {number} y + * @return {boolean} + */ +function containStroke(x0, y0, x1, y1, lineWidth, x, y) { + if (lineWidth === 0) { + return false; + } + + var _l = lineWidth; + var _a = 0; + var _b = x0; // Quick reject + + if (y > y0 + _l && y > y1 + _l || y < y0 - _l && y < y1 - _l || x > x0 + _l && x > x1 + _l || x < x0 - _l && x < x1 - _l) { + return false; + } + + if (x0 !== x1) { + _a = (y0 - y1) / (x0 - x1); + _b = (x0 * y1 - x1 * y0) / (x0 - x1); + } else { + return Math.abs(x - x0) <= _l / 2; + } + + var tmp = _a * x - y + _b; + + var _s = tmp * tmp / (_a * _a + 1); + + return _s <= _l / 2 * _l / 2; +} + +exports.containStroke = containStroke; + +/***/ }), +/* 236 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__scatter3D_Scatter3DSeries__ = __webpack_require__(237); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__scatter3D_Scatter3DView__ = __webpack_require__(238); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3_echarts_lib_visual_symbol__ = __webpack_require__(51); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3_echarts_lib_visual_symbol___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_3_echarts_lib_visual_symbol__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4__common_opacityVisual__ = __webpack_require__(17); + + + + + + + +__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.registerVisual(__WEBPACK_IMPORTED_MODULE_3_echarts_lib_visual_symbol___default()('scatter3D', 'circle', null)); + +__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.registerVisual(Object(__WEBPACK_IMPORTED_MODULE_4__common_opacityVisual__["a" /* default */])('scatter3D')); + +__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.registerLayout({ + seriesType: 'scatter3D', + reset: function (seriesModel) { + var coordSys = seriesModel.coordinateSystem; + + if (coordSys) { + var coordDims = coordSys.dimensions; + if (coordDims.length < 3) { + if (true) { + console.error('scatter3D needs 3D coordinateSystem'); + } + return; + } + var dims = coordDims.map(function (coordDim) { + return seriesModel.coordDimToDataDim(coordDim)[0]; + }); + + var item = []; + var out = []; + + return { + progress: function (params, data) { + var points = new Float32Array((params.end - params.start) * 3); + for (var idx = params.start; idx < params.end; idx++) { + var idx3 = (idx - params.start) * 3; + item[0] = data.get(dims[0], idx); + item[1] = data.get(dims[1], idx); + item[2] = data.get(dims[2], idx); + coordSys.dataToPoint(item, out); + points[idx3] = out[0]; + points[idx3 + 1] = out[1]; + points[idx3 + 2] = out[2]; + } + data.setLayout('points', points); + } + }; + } + } +}); + +/***/ }), +/* 237 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__util_format__ = __webpack_require__(32); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__common_formatTooltip__ = __webpack_require__(39); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__common_createList__ = __webpack_require__(50); + + + + + +__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.extendSeriesModel({ + + type: 'series.scatter3D', + + dependencies: ['globe', 'grid3D', 'geo3D'], + + visualColorAccessPath: 'itemStyle.color', + + getInitialData: function (option, ecModel) { + return Object(__WEBPACK_IMPORTED_MODULE_3__common_createList__["a" /* default */])(this); + }, + + getFormattedLabel: function (dataIndex, status, dataType, dimIndex) { + var text = __WEBPACK_IMPORTED_MODULE_1__util_format__["a" /* default */].getFormattedLabel(this, dataIndex, status, dataType, dimIndex); + if (text == null) { + var data = this.getData(); + var lastDim = data.dimensions[data.dimensions.length - 1]; + text = data.get(lastDim, dataIndex); + } + return text; + }, + + formatTooltip: function (dataIndex) { + return Object(__WEBPACK_IMPORTED_MODULE_2__common_formatTooltip__["a" /* default */])(this, dataIndex); + }, + + defaultOption: { + coordinateSystem: 'cartesian3D', + zlevel: -10, + + progressive: 1e5, + progressiveThreshold: 1e5, + + // Cartesian coordinate system + grid3DIndex: 0, + + globeIndex: 0, + + symbol: 'circle', + symbolSize: 10, + + // Support source-over, lighter + blendMode: 'source-over', + + label: { + show: false, + position: 'right', + // Screen space distance + distance: 5, + + textStyle: { + fontSize: 14, + color: '#000', + backgroundColor: 'rgba(255,255,255,0.7)', + padding: 3, + borderRadius: 3 + } + }, + + itemStyle: { + opacity: 0.8 + }, + + emphasis: { + label: { + show: true + } + }, + + animationDurationUpdate: 500 + } +}); + +/***/ }), +/* 238 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__ = __webpack_require__(1); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__util_retrieve__ = __webpack_require__(2); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__util_format__ = __webpack_require__(32); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4__common_PointsBuilder__ = __webpack_require__(67); + + + + + + + +__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.extendChartView({ + + type: 'scatter3D', + + __ecgl__: true, + + init: function (ecModel, api) { + + this.groupGL = new __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].Node(); + + this._pointsBuilderList = []; + this._currentStep = 0; + }, + + render: function (seriesModel, ecModel, api) { + this.groupGL.removeAll(); + if (!seriesModel.getData().count()) { + return; + } + + var coordSys = seriesModel.coordinateSystem; + if (coordSys && coordSys.viewGL) { + coordSys.viewGL.add(this.groupGL); + this._camera = coordSys.viewGL.camera; + + var pointsBuilder = this._pointsBuilderList[0]; + if (!pointsBuilder) { + pointsBuilder = this._pointsBuilderList[0] = new __WEBPACK_IMPORTED_MODULE_4__common_PointsBuilder__["a" /* default */](false, api); + } + this._pointsBuilderList.length = 1; + + this.groupGL.add(pointsBuilder.rootNode); + pointsBuilder.update(seriesModel, ecModel, api); + pointsBuilder.updateView(coordSys.viewGL.camera); + } + else { + if (true) { + throw new Error('Invalid coordinate system'); + } + } + }, + + incrementalPrepareRender: function (seriesModel, ecModel, api) { + var coordSys = seriesModel.coordinateSystem; + if (coordSys && coordSys.viewGL) { + coordSys.viewGL.add(this.groupGL); + this._camera = coordSys.viewGL.camera; + } + else { + if (true) { + throw new Error('Invalid coordinate system'); + } + } + + this.groupGL.removeAll(); + this._currentStep = 0; + }, + + incrementalRender: function (params, seriesModel, ecModel, api) { + // TODO Sort transparency. + if (params.end <= params.start) { + return; + } + var pointsBuilder = this._pointsBuilderList[this._currentStep]; + if (!pointsBuilder) { + pointsBuilder = new __WEBPACK_IMPORTED_MODULE_4__common_PointsBuilder__["a" /* default */](false, api); + this._pointsBuilderList[this._currentStep] = pointsBuilder; + } + this.groupGL.add(pointsBuilder.rootNode); + + pointsBuilder.update(seriesModel, ecModel, api, params.start, params.end); + pointsBuilder.updateView(seriesModel.coordinateSystem.viewGL.camera); + + this._currentStep++; + }, + + updateCamera: function () { + this._pointsBuilderList.forEach(function (pointsBuilder) { + pointsBuilder.updateView(this._camera); + }, this); + }, + + highlight: function (seriesModel, ecModel, api, payload) { + this._toggleStatus('highlight', seriesModel, ecModel, api, payload); + }, + + downplay: function (seriesModel, ecModel, api, payload) { + this._toggleStatus('downplay', seriesModel, ecModel, api, payload); + }, + + _toggleStatus: function (status, seriesModel, ecModel, api, payload) { + var data = seriesModel.getData(); + var dataIndex = __WEBPACK_IMPORTED_MODULE_2__util_retrieve__["a" /* default */].queryDataIndex(data, payload); + + var isHighlight = status === 'highlight'; + if (dataIndex != null) { + __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.util.each(__WEBPACK_IMPORTED_MODULE_3__util_format__["a" /* default */].normalizeToArray(dataIndex), function (dataIdx) { + for (var i = 0; i < this._pointsBuilderList.length; i++) { + var pointsBuilder = this._pointsBuilderList[i]; + isHighlight ? pointsBuilder.highlight(data, dataIdx) : pointsBuilder.downplay(data, dataIdx); + } + }, this); + } + else { + // PENDING, OPTIMIZE + data.each(function (dataIdx) { + for (var i = 0; i < this._pointsBuilderList.length; i++) { + var pointsBuilder = this._pointsBuilderList[i]; + isHighlight ? pointsBuilder.highlight(data, dataIdx) : pointsBuilder.downplay(data, dataIdx); + } + }); + } + }, + + dispose: function () { + this.groupGL.removeAll(); + }, + + remove: function () { + this.groupGL.removeAll(); + } +}); + +/***/ }), +/* 239 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__); + + +function makeSprite(size, canvas, draw) { + // http://simonsarris.com/blog/346-how-you-clear-your-canvas-matters + // http://jsperf.com/canvasclear + // Set width and height is fast + // And use the exist canvas if possible + // http://jsperf.com/create-canvas-vs-set-width-height/2 + var canvas = canvas || document.createElement('canvas'); + canvas.width = size; + canvas.height = size; + var ctx = canvas.getContext('2d'); + + draw && draw(ctx); + + return canvas; +} + +function makePath(symbol, symbolSize, style, marginBias) { + if (!__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.util.isArray(symbolSize)) { + symbolSize = [symbolSize, symbolSize]; + } + var margin = spriteUtil.getMarginByStyle(style, marginBias); + var width = symbolSize[0] + margin.left + margin.right; + var height = symbolSize[1] + margin.top + margin.bottom; + var path = __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.helper.createSymbol(symbol, 0, 0, symbolSize[0], symbolSize[1]); + + var size = Math.max(width, height); + + path.position = [margin.left, margin.top]; + if (width > height) { + path.position[1] += (size - height) / 2; + } + else { + path.position[0] += (size - width) / 2; + } + + var rect = path.getBoundingRect(); + path.position[0] -= rect.x; + path.position[1] -= rect.y; + + path.setStyle(style); + + path.update(); + + path.__size = size; + + return path; +} + + // http://www.valvesoftware.com/publications/2007/SIGGRAPH2007_AlphaTestedMagnification.pdf +function generateSDF(ctx, sourceImageData, range) { + + var sourceWidth = sourceImageData.width; + var sourceHeight = sourceImageData.height; + + var width = ctx.canvas.width; + var height = ctx.canvas.height; + + var scaleX = sourceWidth / width; + var scaleY = sourceHeight / height; + + function sign(r) { + return r < 128 ? 1 : -1; + } + function searchMinDistance(x, y) { + var minDistSqr = Infinity; + x = Math.floor(x * scaleX); + y = Math.floor(y * scaleY); + var i = y * sourceWidth + x; + var r = sourceImageData.data[i * 4]; + var a = sign(r); + // Search for min distance + for (var y2 = Math.max(y - range, 0); y2 < Math.min(y + range, sourceHeight); y2++) { + for (var x2 = Math.max(x - range, 0); x2 < Math.min(x + range, sourceWidth); x2++) { + var i = y2 * sourceWidth + x2; + var r2 = sourceImageData.data[i * 4]; + var b = sign(r2); + var dx = x2 - x; + var dy = y2 - y; + if (a !== b) { + var distSqr = dx * dx + dy * dy; + if (distSqr < minDistSqr) { + minDistSqr = distSqr; + } + } + } + } + return a * Math.sqrt(minDistSqr); + } + + var sdfImageData = ctx.createImageData(width, height); + for (var y = 0; y < height; y++) { + for (var x = 0; x < width; x++) { + var dist = searchMinDistance(x, y); + + var normalized = dist / range * 0.5 + 0.5; + var i = (y * width + x) * 4; + sdfImageData.data[i++] = (1.0 - normalized) * 255; + sdfImageData.data[i++] = (1.0 - normalized) * 255; + sdfImageData.data[i++] = (1.0 - normalized) * 255; + sdfImageData.data[i++] = 255; + } + } + + return sdfImageData; +} + +var spriteUtil = { + + getMarginByStyle: function (style) { + var minMargin = style.minMargin || 0; + + var lineWidth = 0; + if (style.stroke && style.stroke !== 'none') { + lineWidth = style.lineWidth == null ? 1 : style.lineWidth; + } + var shadowBlurSize = style.shadowBlur || 0; + var shadowOffsetX = style.shadowOffsetX || 0; + var shadowOffsetY = style.shadowOffsetY || 0; + + var margin = {}; + margin.left = Math.max(lineWidth / 2, -shadowOffsetX + shadowBlurSize, minMargin); + margin.right = Math.max(lineWidth / 2, shadowOffsetX + shadowBlurSize, minMargin); + margin.top = Math.max(lineWidth / 2, -shadowOffsetY + shadowBlurSize, minMargin); + margin.bottom = Math.max(lineWidth / 2, shadowOffsetY + shadowBlurSize, minMargin); + + return margin; + }, + + // TODO Not consider shadowOffsetX, shadowOffsetY. + /** + * @param {string} symbol + * @param {number | Array.} symbolSize + * @param {Object} style + */ + createSymbolSprite: function (symbol, symbolSize, style, canvas) { + var path = makePath(symbol, symbolSize, style); + + var margin = spriteUtil.getMarginByStyle(style); + + return { + image: makeSprite(path.__size, canvas, function (ctx) { + path.brush(ctx); + }), + margin: margin + }; + }, + + createSDFFromCanvas: function (canvas, size, range, outCanvas) { + // TODO Create a low resolution SDF from high resolution image. + return makeSprite(size, outCanvas, function (outCtx) { + var ctx = canvas.getContext('2d'); + var imgData = ctx.getImageData(0, 0, canvas.width, canvas.height); + + outCtx.putImageData(generateSDF(outCtx, imgData, range), 0, 0); + }); + }, + + createSimpleSprite: function (size, canvas) { + return makeSprite(size, canvas, function (ctx) { + var halfSize = size / 2; + ctx.beginPath(); + ctx.arc(halfSize, halfSize, 60, 0, Math.PI * 2, false) ; + ctx.closePath(); + + var gradient = ctx.createRadialGradient( + halfSize, halfSize, 0, halfSize, halfSize, halfSize + ); + gradient.addColorStop(0, 'rgba(255, 255, 255, 1)'); + gradient.addColorStop(0.5, 'rgba(255, 255, 255, 0.5)'); + gradient.addColorStop(1, 'rgba(255, 255, 255, 0)'); + ctx.fillStyle = gradient; + ctx.fill(); + }); + } +}; + +/* harmony default export */ __webpack_exports__["a"] = (spriteUtil); + +/***/ }), +/* 240 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__util_graphicGL__ = __webpack_require__(1); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__util_geometry_verticesSortMixin__ = __webpack_require__(241); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2_echarts_lib_echarts__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2_echarts_lib_echarts___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_2_echarts_lib_echarts__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3_claygl_src_dep_glmatrix__ = __webpack_require__(6); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4__sdfSprite_glsl_js__ = __webpack_require__(242); + + + + +var vec4 = __WEBPACK_IMPORTED_MODULE_3_claygl_src_dep_glmatrix__["a" /* default */].vec4; + + +__WEBPACK_IMPORTED_MODULE_0__util_graphicGL__["a" /* default */].Shader.import(__WEBPACK_IMPORTED_MODULE_4__sdfSprite_glsl_js__["a" /* default */]); + +var PointsMesh = __WEBPACK_IMPORTED_MODULE_0__util_graphicGL__["a" /* default */].Mesh.extend(function () { + var geometry = new __WEBPACK_IMPORTED_MODULE_0__util_graphicGL__["a" /* default */].Geometry({ + dynamic: true, + attributes: { + color: new __WEBPACK_IMPORTED_MODULE_0__util_graphicGL__["a" /* default */].Geometry.Attribute('color', 'float', 4, 'COLOR'), + position: new __WEBPACK_IMPORTED_MODULE_0__util_graphicGL__["a" /* default */].Geometry.Attribute('position', 'float', 3, 'POSITION'), + size: new __WEBPACK_IMPORTED_MODULE_0__util_graphicGL__["a" /* default */].Geometry.Attribute('size', 'float', 1), + prevPosition: new __WEBPACK_IMPORTED_MODULE_0__util_graphicGL__["a" /* default */].Geometry.Attribute('prevPosition', 'float', 3), + prevSize: new __WEBPACK_IMPORTED_MODULE_0__util_graphicGL__["a" /* default */].Geometry.Attribute('prevSize', 'float', 1) + } + }); + __WEBPACK_IMPORTED_MODULE_2_echarts_lib_echarts___default.a.util.extend(geometry, __WEBPACK_IMPORTED_MODULE_1__util_geometry_verticesSortMixin__["a" /* default */]); + + var material = new __WEBPACK_IMPORTED_MODULE_0__util_graphicGL__["a" /* default */].Material({ + shader: __WEBPACK_IMPORTED_MODULE_0__util_graphicGL__["a" /* default */].createShader('ecgl.sdfSprite'), + transparent: true, + depthMask: false + }); + material.enableTexture('sprite'); + material.define('both', 'VERTEX_COLOR'); + material.define('both', 'VERTEX_SIZE'); + + var sdfTexture = new __WEBPACK_IMPORTED_MODULE_0__util_graphicGL__["a" /* default */].Texture2D({ + image: document.createElement('canvas'), + flipY: false + }); + + material.set('sprite', sdfTexture); + + // Custom pick methods. + geometry.pick = this._pick.bind(this); + + return { + geometry: geometry, + material: material, + mode: __WEBPACK_IMPORTED_MODULE_0__util_graphicGL__["a" /* default */].Mesh.POINTS, + + sizeScale: 1 + }; +}, { + + _pick: function (x, y, renderer, camera, renderable, out) { + var positionNDC = this._positionNDC; + if (!positionNDC) { + return; + } + + var viewport = renderer.viewport; + var ndcScaleX = 2 / viewport.width; + var ndcScaleY = 2 / viewport.height; + // From near to far. indices have been sorted. + for (var i = this.geometry.vertexCount - 1; i >= 0; i--) { + var idx; + if (!this.geometry.indices) { + idx = i; + } + else { + idx = this.geometry.indices[i]; + } + + var cx = positionNDC[idx * 2]; + var cy = positionNDC[idx * 2 + 1]; + + var size = this.geometry.attributes.size.get(idx) / this.sizeScale; + var halfSize = size / 2; + + if ( + x > (cx - halfSize * ndcScaleX) && x < (cx + halfSize * ndcScaleX) + && y > (cy - halfSize * ndcScaleY) && y < (cy + halfSize * ndcScaleY) + ) { + var point = new __WEBPACK_IMPORTED_MODULE_0__util_graphicGL__["a" /* default */].Vector3(); + var pointWorld = new __WEBPACK_IMPORTED_MODULE_0__util_graphicGL__["a" /* default */].Vector3(); + this.geometry.attributes.position.get(idx, point.array); + __WEBPACK_IMPORTED_MODULE_0__util_graphicGL__["a" /* default */].Vector3.transformMat4(pointWorld, point, this.worldTransform); + out.push({ + vertexIndex: idx, + point: point, + pointWorld: pointWorld, + target: this, + distance: pointWorld.distance(camera.getWorldPosition()) + }); + } + } + }, + + updateNDCPosition: function (worldViewProjection, is2D, api) { + var positionNDC = this._positionNDC; + var geometry = this.geometry; + if (!positionNDC || positionNDC.length / 2 !== geometry.vertexCount) { + positionNDC = this._positionNDC = new Float32Array(geometry.vertexCount * 2); + } + + var pos = vec4.create(); + for (var i = 0; i < geometry.vertexCount; i++) { + geometry.attributes.position.get(i, pos); + pos[3] = 1; + vec4.transformMat4(pos, pos, worldViewProjection.array); + vec4.scale(pos, pos, 1 / pos[3]); + + positionNDC[i * 2] = pos[0]; + positionNDC[i * 2 + 1] = pos[1]; + } + } +}); + +/* harmony default export */ __webpack_exports__["a"] = (PointsMesh); + +/***/ }), +/* 241 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__ProgressiveQuickSort__ = __webpack_require__(97); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_claygl_src_dep_glmatrix__ = __webpack_require__(6); + + +var vec3 = __WEBPACK_IMPORTED_MODULE_1_claygl_src_dep_glmatrix__["a" /* default */].vec3; + +/* harmony default export */ __webpack_exports__["a"] = ({ + + needsSortVertices: function () { + return this.sortVertices; + }, + + needsSortVerticesProgressively: function () { + return this.needsSortVertices() && this.vertexCount >= 2e4; + }, + + doSortVertices: function (cameraPos, frame) { + var indices = this.indices; + var p = vec3.create(); + + if (!indices) { + indices = this.indices = this.vertexCount > 0xffff ? new Uint32Array(this.vertexCount) : new Uint16Array(this.vertexCount); + for (var i = 0; i < indices.length; i++) { + indices[i] = i; + } + } + // Do progressive quick sort. + if (frame === 0) { + var posAttr = this.attributes.position; + var cameraPos = cameraPos.array; + var noneCount = 0; + if (!this._zList || this._zList.length !== this.vertexCount) { + this._zList = new Float32Array(this.vertexCount); + } + + var firstZ; + for (var i = 0; i < this.vertexCount; i++) { + posAttr.get(i, p); + // Camera position is in object space + var z = vec3.sqrDist(p, cameraPos); + if (isNaN(z)) { + // Put far away, NaN value may cause sort slow + z = 1e7; + noneCount++; + } + if (i === 0) { + firstZ = z; + z = 0; + } + else { + // Only store the difference to avoid the precision issue. + z = z - firstZ; + } + this._zList[i] = z; + } + + this._noneCount = noneCount; + } + + if (this.vertexCount < 2e4) { + // Use simple native sort for simple geometries. + if (frame === 0) { + this._simpleSort(this._noneCount / this.vertexCount > 0.05); + } + } + else { + for (var i = 0; i < 3; i++) { + this._progressiveQuickSort(frame * 3 + i); + } + } + + this.dirtyIndices(); + }, + + _simpleSort: function (useNativeQuickSort) { + var zList = this._zList; + var indices = this.indices; + function compare(a, b) { + // Sort from far to near. which is descending order + return zList[b] - zList[a]; + } + + // When too much value are equal, using native quick sort with three partition.. + // or the simple quick sort will be nearly O(n*n) + // http://stackoverflow.com/questions/5126586/quicksort-complexity-when-all-the-elements-are-same + + // Otherwise simple quicksort is more effecient than v8 native quick sort when data all different. + if (useNativeQuickSort) { + Array.prototype.sort.call(indices, compare); + } + else { + __WEBPACK_IMPORTED_MODULE_0__ProgressiveQuickSort__["a" /* default */].sort(indices, compare, 0, indices.length - 1); + } + }, + + _progressiveQuickSort: function (frame) { + var zList = this._zList; + var indices = this.indices; + + this._quickSort = this._quickSort || new __WEBPACK_IMPORTED_MODULE_0__ProgressiveQuickSort__["a" /* default */](); + + this._quickSort.step(indices, function (a, b) { + return zList[b] - zList[a]; + }, frame); + } +}); + +/***/ }), +/* 242 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony default export */ __webpack_exports__["a"] = ("@export ecgl.sdfSprite.vertex\n\nuniform mat4 worldViewProjection : WORLDVIEWPROJECTION;\nuniform float elapsedTime : 0;\n\nattribute vec3 position : POSITION;\n\n#ifdef VERTEX_SIZE\nattribute float size;\n#else\nuniform float u_Size;\n#endif\n\n#ifdef VERTEX_COLOR\nattribute vec4 a_FillColor: COLOR;\nvarying vec4 v_Color;\n#endif\n\n#ifdef VERTEX_ANIMATION\nattribute vec3 prevPosition;\nattribute float prevSize;\nuniform float percent : 1.0;\n#endif\n\n\n#ifdef POSITIONTEXTURE_ENABLED\nuniform sampler2D positionTexture;\n#endif\n\nvarying float v_Size;\n\nvoid main()\n{\n\n#ifdef POSITIONTEXTURE_ENABLED\n gl_Position = worldViewProjection * vec4(texture2D(positionTexture, position.xy).xy, -10.0, 1.0);\n#else\n\n #ifdef VERTEX_ANIMATION\n vec3 pos = mix(prevPosition, position, percent);\n #else\n vec3 pos = position;\n #endif\n gl_Position = worldViewProjection * vec4(pos, 1.0);\n#endif\n\n#ifdef VERTEX_SIZE\n#ifdef VERTEX_ANIMATION\n v_Size = mix(prevSize, size, percent);\n#else\n v_Size = size;\n#endif\n#else\n v_Size = u_Size;\n#endif\n\n#ifdef VERTEX_COLOR\n v_Color = a_FillColor;\n #endif\n\n gl_PointSize = v_Size;\n}\n\n@end\n\n@export ecgl.sdfSprite.fragment\n\nuniform vec4 color: [1, 1, 1, 1];\nuniform vec4 strokeColor: [1, 1, 1, 1];\nuniform float smoothing: 0.07;\n\nuniform float lineWidth: 0.0;\n\n#ifdef VERTEX_COLOR\nvarying vec4 v_Color;\n#endif\n\nvarying float v_Size;\n\nuniform sampler2D sprite;\n\n@import clay.util.srgb\n\nvoid main()\n{\n gl_FragColor = color;\n\n vec4 _strokeColor = strokeColor;\n\n#ifdef VERTEX_COLOR\n gl_FragColor *= v_Color;\n #endif\n\n#ifdef SPRITE_ENABLED\n float d = texture2D(sprite, gl_PointCoord).r;\n gl_FragColor.a *= smoothstep(0.5 - smoothing, 0.5 + smoothing, d);\n\n if (lineWidth > 0.0) {\n float sLineWidth = lineWidth / 2.0;\n\n float outlineMaxValue0 = 0.5 + sLineWidth;\n float outlineMaxValue1 = 0.5 + sLineWidth + smoothing;\n float outlineMinValue0 = 0.5 - sLineWidth - smoothing;\n float outlineMinValue1 = 0.5 - sLineWidth;\n\n if (d <= outlineMaxValue1 && d >= outlineMinValue0) {\n float a = _strokeColor.a;\n if (d <= outlineMinValue1) {\n a = a * smoothstep(outlineMinValue0, outlineMinValue1, d);\n }\n else {\n a = a * smoothstep(outlineMaxValue1, outlineMaxValue0, d);\n }\n gl_FragColor.rgb = mix(gl_FragColor.rgb * gl_FragColor.a, _strokeColor.rgb, a);\n gl_FragColor.a = gl_FragColor.a * (1.0 - a) + a;\n }\n }\n#endif\n\n#ifdef SRGB_DECODE\n gl_FragColor = sRGBToLinear(gl_FragColor);\n#endif\n}\n@end"); + + +/***/ }), +/* 243 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__lines3D_lines3DLayout__ = __webpack_require__(244); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__lines3D_Lines3DView__ = __webpack_require__(245); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__lines3D_Lines3DSeries__ = __webpack_require__(248); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4__common_opacityVisual__ = __webpack_require__(17); + + + + + + + + + +__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.registerVisual(Object(__WEBPACK_IMPORTED_MODULE_4__common_opacityVisual__["a" /* default */])('lines3D')); + + +__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.registerAction({ + type: 'lines3DPauseEffect', + event: 'lines3deffectpaused', + update: 'series.lines3D:pauseEffect' +}, function () {}); + +__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.registerAction({ + type: 'lines3DResumeEffect', + event: 'lines3deffectresumed', + update: 'series.lines3D:resumeEffect' +}, function () {}); + +__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.registerAction({ + type: 'lines3DToggleEffect', + event: 'lines3deffectchanged', + update: 'series.lines3D:toggleEffect' +}, function () {}); + +/***/ }), +/* 244 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_claygl_src_dep_glmatrix__ = __webpack_require__(6); + + +var vec3 = __WEBPACK_IMPORTED_MODULE_1_claygl_src_dep_glmatrix__["a" /* default */].vec3; +var vec2 = __WEBPACK_IMPORTED_MODULE_1_claygl_src_dep_glmatrix__["a" /* default */].vec2; +var normalize = vec3.normalize; +var cross = vec3.cross; +var sub = vec3.sub; +var add = vec3.add; +var create = vec3.create; + +var normal = create(); +var tangent = create(); +var bitangent = create(); +var halfVector = create(); + +var coord0 = []; +var coord1 = []; + +function getCubicPointsOnGlobe(coords, coordSys) { + vec2.copy(coord0, coords[0]); + vec2.copy(coord1, coords[1]); + + var pts = []; + var p0 = pts[0] = create(); + var p1 = pts[1] = create(); + var p2 = pts[2] = create(); + var p3 = pts[3] = create(); + coordSys.dataToPoint(coord0, p0); + coordSys.dataToPoint(coord1, p3); + // Get p1 + normalize(normal, p0); + // TODO p0-p3 is parallel with normal + sub(tangent, p3, p0); + normalize(tangent, tangent); + cross(bitangent, tangent, normal); + normalize(bitangent, bitangent); + cross(tangent, normal, bitangent); + // p1 is half vector of p0 and tangent on p0 + add(p1, normal, tangent); + normalize(p1, p1); + + // Get p2 + normalize(normal, p3); + sub(tangent, p0, p3); + normalize(tangent, tangent); + cross(bitangent, tangent, normal); + normalize(bitangent, bitangent); + cross(tangent, normal, bitangent); + // p2 is half vector of p3 and tangent on p3 + add(p2, normal, tangent); + normalize(p2, p2); + + // Project distance of p0 on halfVector + add(halfVector, p0, p3); + normalize(halfVector, halfVector); + var projDist = vec3.dot(p0, halfVector); + // Angle of halfVector and p1 + var cosTheta = vec3.dot(halfVector, p1); + + var len = (Math.max(vec3.len(p0), vec3.len(p3)) - projDist) / cosTheta * 2; + + vec3.scaleAndAdd(p1, p0, p1, len); + vec3.scaleAndAdd(p2, p3, p2, len); + + return pts; +} + +function getCubicPointsOnPlane(coords, coordSys, up) { + var pts = []; + var p0 = pts[0] = vec3.create(); + var p1 = pts[1] = vec3.create(); + var p2 = pts[2] = vec3.create(); + var p3 = pts[3] = vec3.create(); + + coordSys.dataToPoint(coords[0], p0); + coordSys.dataToPoint(coords[1], p3); + + var len = vec3.dist(p0, p3); + vec3.lerp(p1, p0, p3, 0.3); + vec3.lerp(p2, p0, p3, 0.3); + + vec3.scaleAndAdd(p1, p1, up, Math.min(len * 0.1, 10)); + vec3.scaleAndAdd(p2, p2, up, Math.min(len * 0.1, 10)); + + return pts; +} + +function getPolylinePoints(coords, coordSys) { + var pts = new Float32Array(coords.length * 3); + var off = 0; + var pt = []; + for (var i = 0; i < coords.length; i++) { + coordSys.dataToPoint(coords[i], pt); + pts[off++] = pt[0]; + pts[off++] = pt[1]; + pts[off++] = pt[2]; + } + return pts; +} + +function prepareCoords(data) { + var coordsList = []; + + data.each(function (idx) { + var itemModel = data.getItemModel(idx); + var coords = (itemModel.option instanceof Array) ? + itemModel.option : itemModel.getShallow('coords', true); + + if (true) { + if (!(coords instanceof Array && coords.length > 0 && coords[0] instanceof Array)) { + throw new Error('Invalid coords ' + JSON.stringify(coords) + '. Lines must have 2d coords array in data item.'); + } + } + coordsList.push(coords); + }); + + return { + coordsList: coordsList + }; +} + +function layoutGlobe(seriesModel, coordSys) { + var data = seriesModel.getData(); + var isPolyline = seriesModel.get('polyline'); + + data.setLayout('lineType', isPolyline ? 'polyline' : 'cubicBezier'); + + var res = prepareCoords(data); + + data.each(function (idx) { + var coords = res.coordsList[idx]; + var getPointsMethod = isPolyline ? getPolylinePoints : getCubicPointsOnGlobe; + data.setItemLayout(idx, getPointsMethod(coords, coordSys)); + }); +} + +function layoutOnPlane(seriesModel, coordSys, normal) { + var data = seriesModel.getData(); + var isPolyline = seriesModel.get('polyline'); + + var res = prepareCoords(data); + + data.setLayout('lineType', isPolyline ? 'polyline' : 'cubicBezier'); + + data.each(function (idx) { + var coords = res.coordsList[idx]; + var pts = isPolyline ? getPolylinePoints(coords, coordSys) + : getCubicPointsOnPlane(coords, coordSys, normal); + data.setItemLayout(idx, pts); + }); +} + +__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.registerLayout(function (ecModel, api) { + ecModel.eachSeriesByType('lines3D', function (seriesModel) { + var coordSys = seriesModel.coordinateSystem; + if (coordSys.type === 'globe') { + layoutGlobe(seriesModel, coordSys); + } + else if (coordSys.type === 'geo3D') { + layoutOnPlane(seriesModel, coordSys, [0, 1, 0]); + } + else if (coordSys.type === 'mapbox3D' || coordSys.type === 'maptalks3D') { + layoutOnPlane(seriesModel, coordSys, [0, 0, 1]); + } + }); +}); + +/***/ }), +/* 245 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__ = __webpack_require__(1); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__util_geometry_Lines3D__ = __webpack_require__(25); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__TrailMesh2__ = __webpack_require__(246); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4__util_shader_lines3D_glsl_js__ = __webpack_require__(46); + + + +// import TrailMesh from './TrailMesh'; + + + +__WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].Shader.import(__WEBPACK_IMPORTED_MODULE_4__util_shader_lines3D_glsl_js__["a" /* default */]); + +function getCoordSysSize(coordSys) { + if (coordSys.radius != null) { + return coordSys.radius; + } + if (coordSys.size != null) { + return Math.max(coordSys.size[0], coordSys.size[1], coordSys.size[2]); + } + else { + return 100; + } +} + +/* unused harmony default export */ var _unused_webpack_default_export = (__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.extendChartView({ + + type: 'lines3D', + + __ecgl__: true, + + init: function (ecModel, api) { + this.groupGL = new __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].Node(); + + this._meshLinesMaterial = new __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].Material({ + shader: __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].createShader('ecgl.meshLines3D'), + transparent: true, + depthMask: false + }); + this._linesMesh = new __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].Mesh({ + geometry: new __WEBPACK_IMPORTED_MODULE_2__util_geometry_Lines3D__["a" /* default */](), + material: this._meshLinesMaterial, + $ignorePicking: true + }); + + // this._trailMesh = new TrailMesh(); + this._trailMesh = new __WEBPACK_IMPORTED_MODULE_3__TrailMesh2__["a" /* default */](); + }, + + render: function (seriesModel, ecModel, api) { + + this.groupGL.add(this._linesMesh); + + var coordSys = seriesModel.coordinateSystem; + var data = seriesModel.getData(); + + if (coordSys && coordSys.viewGL) { + var viewGL = coordSys.viewGL; + viewGL.add(this.groupGL); + + this._updateLines(seriesModel, ecModel, api); + + var methodName = coordSys.viewGL.isLinearSpace() ? 'define' : 'undefine'; + this._linesMesh.material[methodName]('fragment', 'SRGB_DECODE'); + this._trailMesh.material[methodName]('fragment', 'SRGB_DECODE'); + } + + var trailMesh = this._trailMesh; + trailMesh.stopAnimation(); + + if (seriesModel.get('effect.show')) { + this.groupGL.add(trailMesh); + + trailMesh.updateData(data, api, this._linesMesh.geometry); + + trailMesh.__time = trailMesh.__time || 0; + var time = 3600 * 1000; // 1hour + this._curveEffectsAnimator = trailMesh.animate('', { loop: true }) + .when(time, { + __time: time + }) + .during(function () { + trailMesh.setAnimationTime(trailMesh.__time); + }) + .start(); + } + else { + this.groupGL.remove(trailMesh); + this._curveEffectsAnimator = null; + } + + this._linesMesh.material.blend = this._trailMesh.material.blend + = seriesModel.get('blendMode') === 'lighter' + ? __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].additiveBlend : null; + }, + + pauseEffect: function () { + if (this._curveEffectsAnimator) { + this._curveEffectsAnimator.pause(); + } + }, + + resumeEffect: function () { + if (this._curveEffectsAnimator) { + this._curveEffectsAnimator.resume(); + } + }, + + toggleEffect: function () { + var animator = this._curveEffectsAnimator; + if (animator) { + animator.isPaused() ? animator.resume() : animator.pause(); + } + }, + + _updateLines: function (seriesModel, ecModel, api) { + var data = seriesModel.getData(); + var coordSys = seriesModel.coordinateSystem; + var geometry = this._linesMesh.geometry; + var isPolyline = seriesModel.get('polyline'); + + geometry.expandLine = true; + + var size = getCoordSysSize(coordSys); + geometry.segmentScale = size / 20; + + var lineWidthQueryPath = 'lineStyle.width'.split('.'); + var dpr = api.getDevicePixelRatio(); + var maxLineWidth = 0; + data.each(function (idx) { + var itemModel = data.getItemModel(idx); + var lineWidth = itemModel.get(lineWidthQueryPath); + if (lineWidth == null) { + lineWidth = 1; + } + data.setItemVisual(idx, 'lineWidth', lineWidth); + maxLineWidth = Math.max(lineWidth, maxLineWidth); + }); + + // Must set useNativeLine before calling any other methods + geometry.useNativeLine = false; + + var nVertex = 0; + var nTriangle = 0; + data.each(function (idx) { + var pts = data.getItemLayout(idx); + if (isPolyline) { + nVertex += geometry.getPolylineVertexCount(pts); + nTriangle += geometry.getPolylineTriangleCount(pts); + } + else { + nVertex += geometry.getCubicCurveVertexCount(pts[0], pts[1], pts[2], pts[3]); + nTriangle += geometry.getCubicCurveTriangleCount(pts[0], pts[1], pts[2], pts[3]); + } + }); + + geometry.setVertexCount(nVertex); + geometry.setTriangleCount(nTriangle); + geometry.resetOffset(); + + var colorArr = []; + data.each(function (idx) { + var pts = data.getItemLayout(idx); + var color = data.getItemVisual(idx, 'color'); + var opacity = data.getItemVisual(idx, 'opacity'); + var lineWidth = data.getItemVisual(idx, 'lineWidth') * dpr; + if (opacity == null) { + opacity = 1; + } + + colorArr = __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].parseColor(color, colorArr); + colorArr[3] *= opacity; + if (isPolyline) { + geometry.addPolyline(pts, colorArr, lineWidth); + } + else { + geometry.addCubicCurve(pts[0], pts[1], pts[2], pts[3], colorArr, lineWidth); + } + }); + + geometry.dirty(); + }, + + remove: function () { + this.groupGL.removeAll(); + }, + + dispose: function () { + this.groupGL.removeAll(); + } +})); + +/***/ }), +/* 246 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__ = __webpack_require__(1); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2_claygl_src_dep_glmatrix__ = __webpack_require__(6); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__util_geometry_Lines3D__ = __webpack_require__(25); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4__shader_trail2_glsl_js__ = __webpack_require__(247); + + + + + + + +var vec3 = __WEBPACK_IMPORTED_MODULE_2_claygl_src_dep_glmatrix__["a" /* default */].vec3; + +function sign(a) { + return a > 0 ? 1 : -1; +} + +__WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].Shader.import(__WEBPACK_IMPORTED_MODULE_4__shader_trail2_glsl_js__["a" /* default */]); + +/* harmony default export */ __webpack_exports__["a"] = (__WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].Mesh.extend(function () { + + var material = new __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].Material({ + shader: new __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].Shader( + __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].Shader.source('ecgl.trail2.vertex'), + __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].Shader.source('ecgl.trail2.fragment') + ), + transparent: true, + depthMask: false + }); + + var geometry = new __WEBPACK_IMPORTED_MODULE_3__util_geometry_Lines3D__["a" /* default */]({ + dynamic: true + }); + geometry.createAttribute('dist', 'float', 1); + geometry.createAttribute('distAll', 'float', 1); + geometry.createAttribute('start', 'float', 1); + + return { + geometry: geometry, + material: material, + culling: false, + $ignorePicking: true + }; +}, { + + updateData: function (data, api, lines3DGeometry) { + var seriesModel = data.hostModel; + var geometry = this.geometry; + + var effectModel = seriesModel.getModel('effect'); + var size = effectModel.get('trailWidth') * api.getDevicePixelRatio(); + var trailLength = effectModel.get('trailLength'); + + var speed = seriesModel.get('effect.constantSpeed'); + var period = seriesModel.get('effect.period') * 1000; + var useConstantSpeed = speed != null; + + if (true) { + if (!this.getScene()) { + console.error('TrailMesh must been add to scene before updateData'); + } + } + + useConstantSpeed + ? this.material.set('speed', speed / 1000) + : this.material.set('period', period); + + this.material[useConstantSpeed ? 'define' : 'undefine']('vertex', 'CONSTANT_SPEED'); + + var isPolyline = seriesModel.get('polyline'); + + geometry.trailLength = trailLength; + this.material.set('trailLength', trailLength); + + geometry.resetOffset(); + + ['position', 'positionPrev', 'positionNext'].forEach(function (attrName) { + geometry.attributes[attrName].value = lines3DGeometry.attributes[attrName].value; + }); + + var extraAttrs = ['dist', 'distAll', 'start', 'offset', 'color']; + + extraAttrs.forEach(function (attrName) { + geometry.attributes[attrName].init(geometry.vertexCount); + }); + geometry.indices = lines3DGeometry.indices; + + var colorArr = []; + var effectColor = effectModel.get('trailColor'); + var effectOpacity = effectModel.get('trailOpacity'); + var hasEffectColor = effectColor != null; + var hasEffectOpacity = effectOpacity != null; + + this.updateWorldTransform(); + var xScale = this.worldTransform.x.len(); + var yScale = this.worldTransform.y.len(); + var zScale = this.worldTransform.z.len(); + + var vertexOffset = 0; + + var maxDistance = 0; + + data.each(function (idx) { + var pts = data.getItemLayout(idx); + var opacity = hasEffectOpacity ? effectOpacity : data.getItemVisual(idx, 'opacity'); + var color = data.getItemVisual(idx, 'color'); + + if (opacity == null) { + opacity = 1; + } + colorArr = __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].parseColor(hasEffectColor ? effectColor : color, colorArr); + colorArr[3] *= opacity; + + var vertexCount = isPolyline + ? lines3DGeometry.getPolylineVertexCount(pts) + : lines3DGeometry.getCubicCurveVertexCount(pts[0], pts[1], pts[2], pts[3]) + + var dist = 0; + var pos = []; + var posPrev = []; + for (var i = vertexOffset; i < vertexOffset + vertexCount; i++) { + geometry.attributes.position.get(i, pos); + pos[0] *= xScale; + pos[1] *= yScale; + pos[2] *= zScale; + if (i > vertexOffset) { + dist += vec3.dist(pos, posPrev); + } + geometry.attributes.dist.set(i, dist); + vec3.copy(posPrev, pos); + } + + maxDistance = Math.max(maxDistance, dist); + + var randomStart = Math.random() * (useConstantSpeed ? dist : period); + for (var i = vertexOffset; i < vertexOffset + vertexCount; i++) { + geometry.attributes.distAll.set(i, dist); + geometry.attributes.start.set(i, randomStart); + + geometry.attributes.offset.set( + i, sign(lines3DGeometry.attributes.offset.get(i)) * size / 2 + ); + geometry.attributes.color.set(i, colorArr); + } + + vertexOffset += vertexCount; + }); + + this.material.set('spotSize', maxDistance * 0.1 * trailLength); + this.material.set('spotIntensity', effectModel.get('spotIntensity')); + + geometry.dirty(); + }, + + setAnimationTime: function (time) { + this.material.set('time', time); + } +})); + +/***/ }), +/* 247 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony default export */ __webpack_exports__["a"] = ("@export ecgl.trail2.vertex\nattribute vec3 position: POSITION;\nattribute vec3 positionPrev;\nattribute vec3 positionNext;\nattribute float offset;\nattribute float dist;\nattribute float distAll;\nattribute float start;\n\nattribute vec4 a_Color : COLOR;\n\nuniform mat4 worldViewProjection : WORLDVIEWPROJECTION;\nuniform vec4 viewport : VIEWPORT;\nuniform float near : NEAR;\n\nuniform float speed : 0;\nuniform float trailLength: 0.3;\nuniform float time;\nuniform float period: 1000;\n\nuniform float spotSize: 1;\n\nvarying vec4 v_Color;\nvarying float v_Percent;\nvarying float v_SpotPercent;\n\n@import ecgl.common.wireframe.vertexHeader\n\n@import ecgl.lines3D.clipNear\n\nvoid main()\n{\n @import ecgl.lines3D.expandLine\n\n gl_Position = currProj;\n\n v_Color = a_Color;\n\n @import ecgl.common.wireframe.vertexMain\n\n#ifdef CONSTANT_SPEED\n float t = mod((speed * time + start) / distAll, 1. + trailLength) - trailLength;\n#else\n float t = mod((time + start) / period, 1. + trailLength) - trailLength;\n#endif\n\n float trailLen = distAll * trailLength;\n\n v_Percent = (dist - t * distAll) / trailLen;\n\n v_SpotPercent = spotSize / distAll;\n\n }\n@end\n\n\n@export ecgl.trail2.fragment\n\nuniform vec4 color : [1.0, 1.0, 1.0, 1.0];\nuniform float spotIntensity: 5;\n\nvarying vec4 v_Color;\nvarying float v_Percent;\nvarying float v_SpotPercent;\n\n@import ecgl.common.wireframe.fragmentHeader\n\n@import clay.util.srgb\n\nvoid main()\n{\n if (v_Percent > 1.0 || v_Percent < 0.0) {\n discard;\n }\n\n float fade = v_Percent;\n\n#ifdef SRGB_DECODE\n gl_FragColor = sRGBToLinear(color * v_Color);\n#else\n gl_FragColor = color * v_Color;\n#endif\n\n @import ecgl.common.wireframe.fragmentMain\n\n if (v_Percent > (1.0 - v_SpotPercent)) {\n gl_FragColor.rgb *= spotIntensity;\n }\n\n gl_FragColor.a *= fade;\n}\n\n@end"); + + +/***/ }), +/* 248 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__); + + +__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.extendSeriesModel({ + + type: 'series.lines3D', + + dependencies: ['globe'], + + visualColorAccessPath: 'lineStyle.color', + + getInitialData: function (option, ecModel) { + var lineData = new __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.List(['value'], this); + lineData.hasItemOption = false; + lineData.initData(option.data, [], function (dataItem, dimName, dataIndex, dimIndex) { + // dataItem is simply coords + if (dataItem instanceof Array) { + return NaN; + } + else { + lineData.hasItemOption = true; + var value = dataItem.value; + if (value != null) { + return value instanceof Array ? value[dimIndex] : value; + } + } + }); + + return lineData; + }, + + defaultOption: { + + coordinateSystem: 'globe', + + globeIndex: 0, + + geo3DIndex: 0, + + zlevel: -10, + + polyline: false, + + effect: { + show: false, + period: 4, + // Trail width + trailWidth: 4, + trailLength: 0.2, + + spotIntensity: 6 + }, + + silent: true, + + // Support source-over, lighter + blendMode: 'source-over', + + lineStyle: { + width: 1, + opacity: 0.5 + // color + } + } +}); + +/***/ }), +/* 249 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__polygons3D_Polygons3DSeries__ = __webpack_require__(250); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__polygons3D_Polygons3DView__ = __webpack_require__(251); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__common_opacityVisual__ = __webpack_require__(17); + + + + + + + +__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.registerVisual(Object(__WEBPACK_IMPORTED_MODULE_3__common_opacityVisual__["a" /* default */])('polygons3D')); + +/***/ }), +/* 250 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__component_common_componentShadingMixin__ = __webpack_require__(31); + + + +function transformPolygon(coordSys, poly) { + var ret = []; + for (var i = 0; i < poly.length; i++) { + ret.push(coordSys.dataToPoint(poly[i])); + } + return ret; +} + +var Polygons3DSeries = __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.extendSeriesModel({ + + type: 'series.polygons3D', + + getRegionModel: function (idx) { + return this.getData().getItemModel(idx); + }, + + getRegionPolygonCoords: function (idx) { + var coordSys = this.coordinateSystem; + var itemModel = this.getData().getItemModel(idx); + var coords = itemModel.option instanceof Array + ? itemModel.option : itemModel.getShallow('coords'); + if (!itemModel.get('multiPolygon')) { + coords = [coords]; + } + // TODO Validate + var out = []; + for (var i = 0; i < coords.length; i++) { + // TODO Convert here ? + var interiors = []; + for (var k = 1; k < coords[i].length; k++) { + interiors.push(transformPolygon(coordSys, coords[i][k])); + } + out.push({ + exterior: transformPolygon(coordSys, coords[i][0]), + interiors: interiors + }); + } + return out; + }, + + getInitialData: function (option) { + var polygonsData = new __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.List(['value'], this); + polygonsData.hasItemOption = false; + polygonsData.initData(option.data, [], function (dataItem, dimName, dataIndex, dimIndex) { + // dataItem is simply coords + if (dataItem instanceof Array) { + return NaN; + } + else { + polygonsData.hasItemOption = true; + var value = dataItem.value; + if (value != null) { + return value instanceof Array ? value[dimIndex] : value; + } + } + }); + + return polygonsData; + }, + + defaultOption: { + + show: true, + + data: null, + + multiPolygon: false, + + progressiveThreshold: 1e3, + progressive: 1e3, + + zlevel: -10, + + label: { + show: false, + // Distance in 3d space. + distance: 2, + + textStyle: { + fontSize: 20, + color: '#000', + backgroundColor: 'rgba(255,255,255,0.7)', + padding: 3, + borderRadius: 4 + } + }, + + itemStyle: { + color: '#fff', + borderWidth: 0, + borderColor: '#333' + }, + + emphasis: { + itemStyle: { + color: '#639fc0' + }, + label: { + show: true + } + } + } +}); + +__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.util.merge(Polygons3DSeries.prototype, __WEBPACK_IMPORTED_MODULE_1__component_common_componentShadingMixin__["a" /* default */]); + +/* unused harmony default export */ var _unused_webpack_default_export = (Polygons3DSeries); + +/***/ }), +/* 251 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__component_common_Geo3DBuilder__ = __webpack_require__(64); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__util_graphicGL__ = __webpack_require__(1); + + + + +__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.extendChartView({ + + type: 'polygons3D', + + __ecgl__: true, + + init: function (ecModel, api) { + this.groupGL = new __WEBPACK_IMPORTED_MODULE_2__util_graphicGL__["a" /* default */].Node(); + + this._geo3DBuilderList = []; + + this._currentStep = 0; + }, + + render: function (seriesModel, ecModel, api) { + this.groupGL.removeAll(); + + var coordSys = seriesModel.coordinateSystem; + if (coordSys && coordSys.viewGL) { + coordSys.viewGL.add(this.groupGL); + } + + var geo3DBuilder = this._geo3DBuilderList[0]; + if (!geo3DBuilder) { + geo3DBuilder = new __WEBPACK_IMPORTED_MODULE_1__component_common_Geo3DBuilder__["a" /* default */](api); + geo3DBuilder.extrudeY = coordSys.type !== 'mapbox3D' + && coordSys.type !== 'maptalks3D'; + this._geo3DBuilderList[0] = geo3DBuilder; + } + this._updateShaderDefines(coordSys, geo3DBuilder); + + geo3DBuilder.update(seriesModel, ecModel, api); + this._geo3DBuilderList.length = 1; + + this.groupGL.add(geo3DBuilder.rootNode); + }, + + incrementalPrepareRender: function (seriesModel, ecModel, api) { + this.groupGL.removeAll(); + + var coordSys = seriesModel.coordinateSystem; + if (coordSys && coordSys.viewGL) { + coordSys.viewGL.add(this.groupGL); + } + + this._currentStep = 0; + }, + + incrementalRender: function (params, seriesModel, ecModel, api) { + var geo3DBuilder = this._geo3DBuilderList[this._currentStep]; + var coordSys = seriesModel.coordinateSystem; + if (!geo3DBuilder) { + geo3DBuilder = new __WEBPACK_IMPORTED_MODULE_1__component_common_Geo3DBuilder__["a" /* default */](api); + geo3DBuilder.extrudeY = coordSys.type !== 'mapbox3D' + && coordSys.type !== 'maptalks3D'; + this._geo3DBuilderList[this._currentStep] = geo3DBuilder; + } + geo3DBuilder.update(seriesModel, ecModel, api, params.start, params.end); + this.groupGL.add(geo3DBuilder.rootNode); + + this._updateShaderDefines(coordSys, geo3DBuilder); + + this._currentStep++; + }, + + _updateShaderDefines: function (coordSys, geo3DBuilder) { + var methodName = coordSys.viewGL.isLinearSpace() ? 'define' : 'undefine'; + geo3DBuilder.rootNode.traverse(function (mesh) { + if (mesh.material) { + mesh.material[methodName]('fragment', 'SRGB_DECODE'); + + // FIXME + if (coordSys.type === 'mapbox3D' || coordSys.type === 'maptalks3D') { + mesh.material.define('fragment', 'NORMAL_UP_AXIS', 2); + mesh.material.define('fragment', 'NORMAL_FRONT_AXIS', 1); + } + } + }); + }, + + remove: function () { + this.groupGL.removeAll(); + }, + + dispose: function () { + this.groupGL.removeAll(); + } +}); + +/***/ }), +/* 252 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__surface_SurfaceSeries__ = __webpack_require__(253); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__surface_SurfaceView__ = __webpack_require__(254); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__surface_surfaceLayout__ = __webpack_require__(255); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4__common_opacityVisual__ = __webpack_require__(17); + + + + + + + + +__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.registerVisual(Object(__WEBPACK_IMPORTED_MODULE_4__common_opacityVisual__["a" /* default */])('surface')); + + +/***/ }), +/* 253 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__component_common_componentShadingMixin__ = __webpack_require__(31); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__common_formatTooltip__ = __webpack_require__(39); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__common_createList__ = __webpack_require__(50); + + + + + +var SurfaceSeries = __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.extendSeriesModel({ + + type: 'series.surface', + + dependencies: ['globe', 'grid3D', 'geo3D'], + + visualColorAccessPath: 'itemStyle.color', + + formatTooltip: function (dataIndex) { + return Object(__WEBPACK_IMPORTED_MODULE_2__common_formatTooltip__["a" /* default */])(this, dataIndex); + }, + + getInitialData: function (option, ecModel) { + var data = option.data; + + function validateDimension(dimOpts) { + return !(isNaN(dimOpts.min) || isNaN(dimOpts.max) || isNaN(dimOpts.step)); + } + + function getPrecision(dimOpts) { + var getPrecision = __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.number.getPrecisionSafe; + return Math.max( + getPrecision(dimOpts.min), getPrecision(dimOpts.max), getPrecision(dimOpts.step) + ) + 1; + } + + if (!data) { + if (!option.parametric) { + // From surface equation + var equation = option.equation || {}; + var xOpts = equation.x || {}; + var yOpts = equation.y || {}; + + ['x', 'y'].forEach(function (dim) { + if (!validateDimension(equation[dim])) { + if (true) { + console.error('Invalid equation.%s', dim); + } + return; + } + }); + if (typeof equation.z !== 'function') { + if (true) { + console.error('equation.z needs to be function'); + } + return; + } + var xCount = Math.floor((xOpts.max + xOpts.step - xOpts.min) / xOpts.step); + var yCount = Math.floor((yOpts.max + yOpts.step - yOpts.min) / yOpts.step); + data = new Float32Array(xCount * yCount * 3); + + var xPrecision = getPrecision(xOpts); + var yPrecision = getPrecision(yOpts); + + var off = 0; + for (var j = 0; j < yCount; j++) { + for (var i = 0; i < xCount; i++) { + var x = i * xOpts.step + xOpts.min; + var y = j * yOpts.step + yOpts.min; + var x2 = __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.number.round(Math.min(x, xOpts.max), xPrecision); + var y2 = __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.number.round(Math.min(y, yOpts.max), yPrecision); + var z = equation.z(x2, y2); + data[off++] = x2; + data[off++] = y2; + data[off++] = z; + } + } + } + else { + var parametricEquation = option.parametricEquation || {}; + var uOpts = parametricEquation.u || {}; + var vOpts = parametricEquation.v || {}; + + ['u', 'v'].forEach(function (dim) { + if (!validateDimension(parametricEquation[dim])) { + if (true) { + console.error('Invalid parametricEquation.%s', dim); + } + return; + } + }); + ['x', 'y', 'z'].forEach(function (dim) { + if (typeof parametricEquation[dim] !== 'function') { + if (true) { + console.error('parametricEquation.%s needs to be function', dim); + } + return; + } + }); + + var uCount = Math.floor((uOpts.max + uOpts.step - uOpts.min) / uOpts.step); + var vCount = Math.floor((vOpts.max + vOpts.step - vOpts.min) / vOpts.step); + data = new Float32Array(uCount * vCount * 5); + + + var uPrecision = getPrecision(uOpts); + var vPrecision = getPrecision(vOpts); + var off = 0; + for (var j = 0; j < vCount; j++) { + for (var i = 0; i < uCount; i++) { + var u = i * uOpts.step + uOpts.min; + var v = j * vOpts.step + vOpts.min; + var u2 = __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.number.round(Math.min(u, uOpts.max), uPrecision); + var v2 = __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.number.round(Math.min(v, vOpts.max), vPrecision); + var x = parametricEquation.x(u2, v2); + var y = parametricEquation.y(u2, v2); + var z = parametricEquation.z(u2, v2); + data[off++] = x; + data[off++] = y; + data[off++] = z; + data[off++] = u2; + data[off++] = v2; + } + } + } + } + + var dims = ['x', 'y', 'z']; + if (option.parametric) { + dims.push('u', 'v'); + } + // PENDING getSource? + var list = Object(__WEBPACK_IMPORTED_MODULE_3__common_createList__["a" /* default */])(this, dims, data); + return list; + }, + + defaultOption: { + coordinateSystem: 'cartesian3D', + zlevel: -10, + + // Cartesian coordinate system + grid3DIndex: 0, + + // Surface needs lambert shading to show the difference + shading: 'lambert', + + // If parametric surface + parametric: false, + + wireframe: { + show: true, + + lineStyle: { + color: 'rgba(0,0,0,0.5)', + width: 1 + } + }, + /** + * Generate surface data from z = f(x, y) equation + */ + equation: { + // [min, max, step] + x: { + min: -1, + max: 1, + step: 0.1 + }, + y: { + min: -1, + max: 1, + step: 0.1 + }, + z: null + }, + + parametricEquation: { + // [min, max, step] + u: { + min: -1, + max: 1, + step: 0.1 + }, + v: { + min: -1, + max: 1, + step: 0.1 + }, + // [x, y, z] = f(x, y) + x: null, + y: null, + z: null + }, + + itemStyle: { + // Color + }, + + animationDurationUpdate: 500 + } +}); + +__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.util.merge(SurfaceSeries.prototype, __WEBPACK_IMPORTED_MODULE_1__component_common_componentShadingMixin__["a" /* default */]); + +/* unused harmony default export */ var _unused_webpack_default_export = (SurfaceSeries); + +/***/ }), +/* 254 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__ = __webpack_require__(1); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__util_retrieve__ = __webpack_require__(2); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3_claygl_src_dep_glmatrix__ = __webpack_require__(6); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4__util_geometry_trianglesSortMixin__ = __webpack_require__(65); + + + + + + +var vec3 = __WEBPACK_IMPORTED_MODULE_3_claygl_src_dep_glmatrix__["a" /* default */].vec3; + +function isPointsNaN(pt) { + return isNaN(pt[0]) || isNaN(pt[1]) || isNaN(pt[2]); +} + +__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.extendChartView({ + + type: 'surface', + + __ecgl__: true, + + init: function (ecModel, api) { + + this.groupGL = new __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].Node(); + }, + + render: function (seriesModel, ecModel, api) { + // Swap surfaceMesh + var tmp = this._prevSurfaceMesh; + this._prevSurfaceMesh = this._surfaceMesh; + this._surfaceMesh = tmp; + + if (!this._surfaceMesh) { + this._surfaceMesh = this._createSurfaceMesh(); + } + + this.groupGL.remove(this._prevSurfaceMesh); + this.groupGL.add(this._surfaceMesh); + + var coordSys = seriesModel.coordinateSystem; + var shading = seriesModel.get('shading'); + var data = seriesModel.getData(); + + var shadingPrefix = 'ecgl.' + shading; + if (!this._surfaceMesh.material || this._surfaceMesh.material.shader.name !== shadingPrefix) { + this._surfaceMesh.material = __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].createMaterial(shadingPrefix, ['VERTEX_COLOR', 'DOUBLE_SIDED']); + } + + __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].setMaterialFromModel( + shading, this._surfaceMesh.material, seriesModel, api + ); + + if (coordSys && coordSys.viewGL) { + coordSys.viewGL.add(this.groupGL); + var methodName = coordSys.viewGL.isLinearSpace() ? 'define' : 'undefine'; + this._surfaceMesh.material[methodName]('fragment', 'SRGB_DECODE'); + } + + var isParametric = seriesModel.get('parametric'); + + var dataShape = this._getDataShape(data, isParametric); + + var wireframeModel = seriesModel.getModel('wireframe'); + var wireframeLineWidth = wireframeModel.get('lineStyle.width'); + var showWireframe = wireframeModel.get('show') && wireframeLineWidth > 0; + this._updateSurfaceMesh(this._surfaceMesh, seriesModel, dataShape, showWireframe); + + var material = this._surfaceMesh.material; + if (showWireframe) { + material.define('WIREFRAME_QUAD'); + material.set('wireframeLineWidth', wireframeLineWidth); + material.set('wireframeLineColor', __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].parseColor(wireframeModel.get('lineStyle.color'))); + } + else { + material.undefine('WIREFRAME_QUAD'); + } + + this._initHandler(seriesModel, api); + + this._updateAnimation(seriesModel); + }, + + _updateAnimation: function (seriesModel) { + __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].updateVertexAnimation( + [['prevPosition', 'position'], + ['prevNormal', 'normal']], + this._prevSurfaceMesh, + this._surfaceMesh, + seriesModel + ); + }, + + _createSurfaceMesh: function () { + var mesh = new __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].Mesh({ + geometry: new __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].Geometry({ + dynamic: true, + sortTriangles: true + }), + shadowDepthMaterial: new __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].Material({ + shader: new __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].Shader(__WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].Shader.source('ecgl.sm.depth.vertex'), __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].Shader.source('ecgl.sm.depth.fragment')) + }), + culling: false, + // Render after axes + renderOrder: 10, + // Render normal in normal pass + renderNormal: true + }); + mesh.geometry.createAttribute('barycentric', 'float', 4); + mesh.geometry.createAttribute('prevPosition', 'float', 3); + mesh.geometry.createAttribute('prevNormal', 'float', 3); + + __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.util.extend(mesh.geometry, __WEBPACK_IMPORTED_MODULE_4__util_geometry_trianglesSortMixin__["a" /* default */]); + + return mesh; + }, + + _initHandler: function (seriesModel, api) { + var data = seriesModel.getData(); + var surfaceMesh = this._surfaceMesh; + + var coordSys = seriesModel.coordinateSystem; + + function getNearestPointIdx(triangle, point) { + var nearestDist = Infinity; + var nearestIdx = -1; + var pos = []; + for (var i = 0; i < triangle.length; i++) { + surfaceMesh.geometry.attributes.position.get(triangle[i], pos); + var dist = vec3.dist(point.array, pos); + if (dist < nearestDist) { + nearestDist = dist; + nearestIdx = triangle[i]; + } + } + return nearestIdx; + } + + surfaceMesh.seriesIndex = seriesModel.seriesIndex; + + var lastDataIndex = -1; + + surfaceMesh.off('mousemove'); + surfaceMesh.off('mouseout'); + surfaceMesh.on('mousemove', function (e) { + var idx = getNearestPointIdx(e.triangle, e.point); + if (idx >= 0) { + var point = []; + surfaceMesh.geometry.attributes.position.get(idx, point); + var value = coordSys.pointToData(point); + + var minDist = Infinity; + var dataIndex = -1; + var item = []; + for (var i = 0; i < data.count(); i++) { + item[0] = data.get('x', i); + item[1] = data.get('y', i); + item[2] = data.get('z', i); + var dist = vec3.squaredDistance(item, value); + if (dist < minDist) { + dataIndex = i; + minDist = dist; + } + } + + if (dataIndex !== lastDataIndex) { + api.dispatchAction({ + type: 'grid3DShowAxisPointer', + value: value + }); + } + + lastDataIndex = dataIndex; + surfaceMesh.dataIndex = dataIndex; + } + else { + surfaceMesh.dataIndex = -1; + } + }, this); + surfaceMesh.on('mouseout', function (e) { + lastDataIndex = -1; + surfaceMesh.dataIndex = -1; + + api.dispatchAction({ + type: 'grid3DHideAxisPointer' + }); + }, this); + }, + + _updateSurfaceMesh: function (surfaceMesh, seriesModel, dataShape, showWireframe) { + + var geometry = surfaceMesh.geometry; + var data = seriesModel.getData(); + var pointsArr = data.getLayout('points'); + + var invalidDataCount = 0; + data.each(function (idx) { + if (!data.hasValue(idx)) { + invalidDataCount++; + } + }); + var needsSplitQuad = invalidDataCount || showWireframe; + + var positionAttr = geometry.attributes.position; + var normalAttr = geometry.attributes.normal; + var texcoordAttr = geometry.attributes.texcoord0; + var barycentricAttr = geometry.attributes.barycentric; + var colorAttr = geometry.attributes.color; + var row = dataShape.row; + var column = dataShape.column; + var shading = seriesModel.get('shading'); + var needsNormal = shading !== 'color'; + + if (needsSplitQuad) { + // TODO, If needs remove the invalid points, or set color transparent. + var vertexCount = (row - 1) * (column - 1) * 4; + positionAttr.init(vertexCount); + if (showWireframe) { + barycentricAttr.init(vertexCount); + } + } + else { + positionAttr.value = new Float32Array(pointsArr); + } + colorAttr.init(geometry.vertexCount); + texcoordAttr.init(geometry.vertexCount); + + var quadToTriangle = [0, 3, 1, 1, 3, 2]; + // 3----2 + // 0----1 + // Make sure pixels on 1---3 edge will not have channel 0. + // And pixels on four edges have at least one channel 0. + var quadBarycentric = [ + [1, 1, 0, 0], + [0, 1, 0, 1], + [1, 0, 0, 1], + [1, 0, 1, 0] + ]; + + var indices = geometry.indices = new (geometry.vertexCount > 0xffff ? Uint32Array : Uint16Array)((row - 1) * (column - 1) * 6); + var getQuadIndices = function (i, j, out) { + out[1] = i * column + j; + out[0] = i * column + j + 1; + out[3] = (i + 1) * column + j + 1; + out[2] = (i + 1) * column + j; + }; + + var isTransparent = false; + + if (needsSplitQuad) { + var quadIndices = []; + var pos = []; + var faceOffset = 0; + + if (needsNormal) { + normalAttr.init(geometry.vertexCount); + } + else { + normalAttr.value = null; + } + + var pts = [[], [], []]; + var v21 = [], v32 = []; + var normal = vec3.create(); + + var getFromArray = function (arr, idx, out) { + var idx3 = idx * 3; + out[0] = arr[idx3]; + out[1] = arr[idx3 + 1]; + out[2] = arr[idx3 + 2]; + return out; + }; + var vertexNormals = new Float32Array(pointsArr.length); + var vertexColors = new Float32Array(pointsArr.length / 3 * 4); + + for (var i = 0; i < data.count(); i++) { + if (data.hasValue(i)) { + var rgbaArr = __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].parseColor(data.getItemVisual(i, 'color')); + var opacity = data.getItemVisual(i, 'opacity'); + rgbaArr[3] *= opacity; + if (rgbaArr[3] < 0.99) { + isTransparent = true; + } + for (var k = 0; k < 4; k++) { + vertexColors[i * 4 + k] = rgbaArr[k]; + } + } + } + var farPoints = [1e7, 1e7, 1e7]; + for (var i = 0; i < row - 1; i++) { + for (var j = 0; j < column - 1; j++) { + var dataIndex = i * (column - 1) + j; + var vertexOffset = dataIndex * 4; + + getQuadIndices(i, j, quadIndices); + + var invisibleQuad = false; + for (var k = 0; k < 4; k++) { + getFromArray(pointsArr, quadIndices[k], pos); + if (isPointsNaN(pos)) { + // Quad is invisible if any point is NaN + invisibleQuad = true; + } + } + + for (var k = 0; k < 4; k++) { + if (invisibleQuad) { + // Move point far away + positionAttr.set(vertexOffset + k, farPoints); + } + else { + getFromArray(pointsArr, quadIndices[k], pos); + positionAttr.set(vertexOffset + k, pos); + } + if (showWireframe) { + barycentricAttr.set(vertexOffset + k, quadBarycentric[k]); + } + } + for (var k = 0; k < 6; k++) { + indices[faceOffset++] = quadToTriangle[k] + vertexOffset; + } + // Vertex normals + if (needsNormal && !invisibleQuad) { + for (var k = 0; k < 2; k++) { + var k3 = k * 3; + + for (var m = 0; m < 3; m++) { + var idx = quadIndices[quadToTriangle[k3] + m]; + getFromArray(pointsArr, idx, pts[m]); + } + + vec3.sub(v21, pts[0], pts[1]); + vec3.sub(v32, pts[1], pts[2]); + vec3.cross(normal, v21, v32); + // Weighted by the triangle area + for (var m = 0; m < 3; m++) { + var idx3 = quadIndices[quadToTriangle[k3] + m] * 3; + vertexNormals[idx3] = vertexNormals[idx3] + normal[0]; + vertexNormals[idx3 + 1] = vertexNormals[idx3 + 1] + normal[1]; + vertexNormals[idx3 + 2] = vertexNormals[idx3 + 2] + normal[2]; + } + } + } + + } + } + if (needsNormal) { + for (var i = 0; i < vertexNormals.length / 3; i++) { + getFromArray(vertexNormals, i, normal); + vec3.normalize(normal, normal); + vertexNormals[i * 3] = normal[0]; + vertexNormals[i * 3 + 1] = normal[1]; + vertexNormals[i * 3 + 2] = normal[2]; + } + } + // Split normal and colors, write to the attributes. + var rgbaArr = []; + var uvArr = []; + for (var i = 0; i < row - 1; i++) { + for (var j = 0; j < column - 1; j++) { + var dataIndex = i * (column - 1) + j; + var vertexOffset = dataIndex * 4; + + getQuadIndices(i, j, quadIndices); + for (var k = 0; k < 4; k++) { + for (var m = 0; m < 4; m++) { + rgbaArr[m] = vertexColors[quadIndices[k] * 4 + m]; + } + colorAttr.set(vertexOffset + k, rgbaArr); + + if (needsNormal) { + getFromArray(vertexNormals, quadIndices[k], normal); + normalAttr.set(vertexOffset + k, normal); + } + + var idx = quadIndices[k]; + uvArr[0] = (idx % column) / (column - 1); + uvArr[1] = Math.floor(idx / column) / (row - 1); + texcoordAttr.set(vertexOffset + k, uvArr); + } + dataIndex++; + } + } + } + else { + var uvArr = []; + for (var i = 0; i < data.count(); i++) { + uvArr[0] = (i % column) / (column - 1); + uvArr[1] = Math.floor(i / column) / (row - 1); + var rgbaArr = __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].parseColor(data.getItemVisual(i, 'color')); + var opacity = data.getItemVisual(i, 'opacity'); + rgbaArr[3] *= opacity; + if (rgbaArr[3] < 0.99) { + isTransparent = true; + } + colorAttr.set(i, rgbaArr); + texcoordAttr.set(i, uvArr); + } + var quadIndices = []; + // Triangles + var cursor = 0; + for (var i = 0; i < row - 1; i++) { + for (var j = 0; j < column - 1; j++) { + + getQuadIndices(i, j, quadIndices); + + for (var k = 0; k < 6; k++) { + indices[cursor++] = quadIndices[quadToTriangle[k]]; + } + } + } + if (needsNormal) { + geometry.generateVertexNormals(); + } + else { + normalAttr.value = null; + } + } + if (surfaceMesh.material.get('normalMap')) { + geometry.generateTangents(); + } + + + geometry.updateBoundingBox(); + geometry.dirty(); + + surfaceMesh.material.transparent = isTransparent; + surfaceMesh.material.depthMask = !isTransparent; + }, + + _getDataShape: function (data, isParametric) { + + var prevX = -Infinity; + var rowCount = 0; + var columnCount = 0; + var prevColumnCount = 0; + + var rowDim = isParametric ? 'u' : 'x'; + + // Check data format + for (var i = 0; i < data.count(); i++) { + var x = data.get(rowDim, i); + if (x < prevX) { + if (prevColumnCount && prevColumnCount !== columnCount) { + if (true) { + throw new Error('Invalid data. data should be a row major 2d array.') + } + } + // A new row. + prevColumnCount = columnCount; + columnCount = 0; + rowCount++; + } + prevX = x; + columnCount++; + } + + return { + row: rowCount + 1, + column: columnCount + }; + }, + + dispose: function () { + this.groupGL.removeAll(); + }, + + remove: function () { + this.groupGL.removeAll(); + } +}); + +/***/ }), +/* 255 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__); + + +__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.registerLayout(function (ecModel, api) { + ecModel.eachSeriesByType('surface', function (surfaceModel) { + var cartesian = surfaceModel.coordinateSystem; + if (!cartesian || cartesian.type !== 'cartesian3D') { + if (true) { + console.error('Surface chart only support cartesian3D coordinateSystem'); + } + } + var data = surfaceModel.getData(); + var points = new Float32Array(3 * data.count()); + var nanPoint = [NaN, NaN, NaN]; + + if (cartesian && cartesian.type === 'cartesian3D') { + var coordDims = cartesian.dimensions; + var dims = coordDims.map(function (coordDim) { + return surfaceModel.coordDimToDataDim(coordDim)[0]; + }); + data.each(dims, function (x, y, z, idx) { + var pt; + if (!data.hasValue(idx)) { + pt = nanPoint; + } + else { + pt = cartesian.dataToPoint([x, y, z]); + } + points[idx * 3] = pt[0]; + points[idx * 3 + 1] = pt[1]; + points[idx * 3 + 2] = pt[2]; + }); + } + data.setLayout('points', points); + }); +}); + +/***/ }), +/* 256 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__coord_geo3D_Geo3D__ = __webpack_require__(99); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__map3D_Map3DSeries__ = __webpack_require__(257); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__map3D_Map3DView__ = __webpack_require__(258); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4__common_opacityVisual__ = __webpack_require__(17); + + + + + + + + +__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.registerVisual(Object(__WEBPACK_IMPORTED_MODULE_4__common_opacityVisual__["a" /* default */])('map3D')); + +__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.registerAction({ + type: 'map3DChangeCamera', + event: 'map3dcamerachanged', + update: 'series:updateCamera' +}, function (payload, ecModel) { + ecModel.eachComponent({ + mainType: 'series', subType: 'map3D', query: payload + }, function (componentModel) { + componentModel.setView(payload); + }); +}); + +/***/ }), +/* 257 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__component_common_componentViewControlMixin__ = __webpack_require__(44); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__component_common_componentPostEffectMixin__ = __webpack_require__(28); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__component_common_componentLightMixin__ = __webpack_require__(29); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4__component_common_componentShadingMixin__ = __webpack_require__(31); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_5__coord_geo3D_geo3DModelMixin__ = __webpack_require__(96); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_6__util_format__ = __webpack_require__(32); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_7__common_formatTooltip__ = __webpack_require__(39); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_8__coord_geo3DCreator__ = __webpack_require__(98); + + + + + + + + + + +function transformPolygon(mapbox3DCoordSys, poly) { + var newPoly = []; + for (var k = 0; k < poly.length; k++) { + newPoly.push(mapbox3DCoordSys.dataToPoint(poly[k])); + } + return newPoly; +} + +var Map3DSeries = __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.extendSeriesModel({ + + type: 'series.map3D', + + layoutMode: 'box', + + coordinateSystem: null, + + visualColorAccessPath: 'itemStyle.color', + + optionUpdated: function (newOpt) { + newOpt = newOpt || {}; + var coordSysType = this.get('coordinateSystem'); + if (coordSysType == null || coordSysType === 'geo3D') { + return; + } + + if (true) { + var propsNeedToCheck = [ + 'left', 'top', 'width', 'height', + 'boxWidth', 'boxDepth', 'boxHeight', + 'light', 'viewControl', 'postEffect', 'temporalSuperSampling', + 'environment', 'groundPlane' + ]; + var ignoredProperties = []; + propsNeedToCheck.forEach(function (propName) { + if (newOpt[propName] != null) { + ignoredProperties.push(propName); + } + }); + if (ignoredProperties.length) { + console.warn( + 'Property %s in map3D series will be ignored if coordinate system is %s', + ignoredProperties.join(', '), coordSysType + ); + } + } + + if (this.get('groundPlane.show')) { + // Force disable groundPlane if map3D has other coordinate systems. + this.option.groundPlane.show = false; + } + + // Reset geo. + this._geo = null; + }, + + getInitialData: function (option) { + option.data = this.getFilledRegions(option.data, option.map); + + var dimensions = __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.helper.completeDimensions(['value'], option.data); + var list = new __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.List(dimensions, this); + list.initData(option.data); + + var regionModelMap = {}; + list.each(function (idx) { + var name = list.getName(idx); + var itemModel = list.getItemModel(idx); + regionModelMap[name] = itemModel; + }); + + this._regionModelMap = regionModelMap; + + return list; + }, + + formatTooltip: function (dataIndex) { + return Object(__WEBPACK_IMPORTED_MODULE_7__common_formatTooltip__["a" /* default */])(this, dataIndex); + }, + + getRegionModel: function (idx) { + var name = this.getData().getName(idx); + return this._regionModelMap[name] || new __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.Model(null, this); + }, + + getRegionPolygonCoords: function (idx) { + var coordSys = this.coordinateSystem; + var name = this.getData().getName(idx); + if (coordSys.transform) { + var region = coordSys.getRegion(name); + return region ? region.geometries : []; + } + else { + if (!this._geo) { + this._geo = __WEBPACK_IMPORTED_MODULE_8__coord_geo3DCreator__["a" /* default */].createGeo3D(this); + } + var region = this._geo.getRegion(name); + var ret = []; + for (var k = 0; k < region.geometries.length; k++) { + var geo = region.geometries[k]; + var interiors = []; + var exterior = transformPolygon(coordSys, geo.exterior); + if (interiors && interiors.length) { + for (var m = 0; m < geo.interiors.length; m++) { + interiors.push(transformPolygon(coordSys, interiors[m])); + } + } + ret.push({ + interiors: interiors, + exterior: exterior + }); + } + return ret; + } + }, + + /** + * Format label + * @param {string} name Region name + * @param {string} [status='normal'] 'normal' or 'emphasis' + * @return {string} + */ + getFormattedLabel: function (dataIndex, status) { + var text = __WEBPACK_IMPORTED_MODULE_6__util_format__["a" /* default */].getFormattedLabel(this, dataIndex, status); + if (text == null) { + text = this.getData().getName(dataIndex); + } + return text; + }, + + defaultOption: { + // Support geo3D, mapbox, maptalks3D + coordinateSystem: 'geo3D', + // itemStyle: {}, + // height, + // label: {} + data: null + } +}); + +__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.util.merge(Map3DSeries.prototype, __WEBPACK_IMPORTED_MODULE_5__coord_geo3D_geo3DModelMixin__["a" /* default */]); + +__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.util.merge(Map3DSeries.prototype, __WEBPACK_IMPORTED_MODULE_1__component_common_componentViewControlMixin__["a" /* default */]); +__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.util.merge(Map3DSeries.prototype, __WEBPACK_IMPORTED_MODULE_2__component_common_componentPostEffectMixin__["a" /* default */]); +__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.util.merge(Map3DSeries.prototype, __WEBPACK_IMPORTED_MODULE_3__component_common_componentLightMixin__["a" /* default */]); +__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.util.merge(Map3DSeries.prototype, __WEBPACK_IMPORTED_MODULE_4__component_common_componentShadingMixin__["a" /* default */]); + +/* unused harmony default export */ var _unused_webpack_default_export = (Map3DSeries); + +/***/ }), +/* 258 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__ = __webpack_require__(1); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__util_OrbitControl__ = __webpack_require__(45); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__component_common_SceneHelper__ = __webpack_require__(30); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4__component_common_Geo3DBuilder__ = __webpack_require__(64); + + + + + + + +/* unused harmony default export */ var _unused_webpack_default_export = (__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.extendChartView({ + + type: 'map3D', + + __ecgl__: true, + + init: function (ecModel, api) { + this._geo3DBuilder = new __WEBPACK_IMPORTED_MODULE_4__component_common_Geo3DBuilder__["a" /* default */](api); + this.groupGL = new __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].Node(); + }, + + render: function (map3DModel, ecModel, api) { + + var coordSys = map3DModel.coordinateSystem; + + if (!coordSys || !coordSys.viewGL) { + return; + } + + this.groupGL.add(this._geo3DBuilder.rootNode); + coordSys.viewGL.add(this.groupGL); + + var geo3D; + if (coordSys.type === 'geo3D') { + geo3D = coordSys; + + if (!this._sceneHelper) { + this._sceneHelper = new __WEBPACK_IMPORTED_MODULE_3__component_common_SceneHelper__["a" /* default */](); + this._sceneHelper.initLight(this.groupGL); + } + + this._sceneHelper.setScene(coordSys.viewGL.scene); + this._sceneHelper.updateLight(map3DModel); + + // Set post effect + coordSys.viewGL.setPostEffect(map3DModel.getModel('postEffect'), api); + coordSys.viewGL.setTemporalSuperSampling(map3DModel.getModel('temporalSuperSampling')); + + var control = this._control; + if (!control) { + control = this._control = new __WEBPACK_IMPORTED_MODULE_2__util_OrbitControl__["a" /* default */]({ + zr: api.getZr() + }); + this._control.init(); + } + var viewControlModel = map3DModel.getModel('viewControl'); + control.setViewGL(coordSys.viewGL); + control.setFromViewControlModel(viewControlModel, 0); + + control.off('update'); + control.on('update', function () { + api.dispatchAction({ + type: 'map3DChangeCamera', + alpha: control.getAlpha(), + beta: control.getBeta(), + distance: control.getDistance(), + from: this.uid, + map3DId: map3DModel.id + }); + }); + + this._geo3DBuilder.extrudeY = true; + } + else { + if (this._control) { + this._control.dispose(); + this._control = null; + } + if (this._sceneHelper) { + this._sceneHelper.dispose(); + this._sceneHelper = null; + } + geo3D = map3DModel.getData().getLayout('geo3D'); + + this._geo3DBuilder.extrudeY = false; + } + + this._geo3DBuilder.update(map3DModel, ecModel, api, 0, map3DModel.getData().count()); + + + // Must update after geo3D.viewGL.setPostEffect to determine linear space + var srgbDefineMethod = coordSys.viewGL.isLinearSpace() ? 'define' : 'undefine'; + this._geo3DBuilder.rootNode.traverse(function (mesh) { + if (mesh.material) { + mesh.material[srgbDefineMethod]('fragment', 'SRGB_DECODE'); + } + }); + }, + + afterRender: function (map3DModel, ecModel, api, layerGL) { + var renderer = layerGL.renderer; + var coordSys = map3DModel.coordinateSystem; + if (coordSys && coordSys.type === 'geo3D') { + this._sceneHelper.updateAmbientCubemap(renderer, map3DModel, api); + this._sceneHelper.updateSkybox(renderer, map3DModel, api); + } + }, + + dispose: function () { + this.groupGL.removeAll(); + this._control.dispose(); + } +})); + +/***/ }), +/* 259 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__scatterGL_ScatterGLSeries__ = __webpack_require__(260); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__scatterGL_ScatterGLView__ = __webpack_require__(261); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3_echarts_lib_visual_symbol__ = __webpack_require__(51); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3_echarts_lib_visual_symbol___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_3_echarts_lib_visual_symbol__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4__common_opacityVisual__ = __webpack_require__(17); + + + + + + + + +__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.registerVisual(__WEBPACK_IMPORTED_MODULE_3_echarts_lib_visual_symbol___default()('scatterGL', 'circle', null)); + +__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.registerVisual(Object(__WEBPACK_IMPORTED_MODULE_4__common_opacityVisual__["a" /* default */])('scatterGL')); + +__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.registerLayout({ + seriesType: 'scatterGL', + reset: function (seriesModel) { + var coordSys = seriesModel.coordinateSystem; + + var progress; + if (coordSys) { + var dims = coordSys.dimensions; + var pt = []; + if (dims.length === 1) { + progress = function (params, data) { + var points = new Float32Array((params.end - params.start) * 2); + for (var idx = params.start; idx < params.end; idx++) { + var offset = (idx - params.start) * 2; + var x = data.get(dims[0], idx); + var pt = coordSys.dataToPoint(x); + points[offset] = pt[0]; + points[offset + 1] = pt[1]; + } + data.setLayout('points', points); + }; + } + else if (dims.length === 2) { + progress = function (params, data) { + var points = new Float32Array((params.end - params.start) * 2); + for (var idx = params.start; idx < params.end; idx++) { + var offset = (idx - params.start) * 2; + var x = data.get(dims[0], idx); + var y = data.get(dims[1], idx); + pt[0] = x; + pt[1] = y; + + pt = coordSys.dataToPoint(pt); + points[offset] = pt[0]; + points[offset + 1] = pt[1]; + } + data.setLayout('points', points); + }; + } + } + + return { progress: progress }; + } +}); + +/***/ }), +/* 260 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__); + + +__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.extendSeriesModel({ + + type: 'series.scatterGL', + + dependencies: ['grid', 'polar', 'geo', 'singleAxis'], + + visualColorAccessPath: 'itemStyle.color', + + getInitialData: function () { + return __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.helper.createList(this); + }, + + defaultOption: { + coordinateSystem: 'cartesian2d', + zlevel: 10, + + progressive: 1e5, + progressiveThreshold: 1e5, + + // Cartesian coordinate system + // xAxisIndex: 0, + // yAxisIndex: 0, + + // Polar coordinate system + // polarIndex: 0, + + // Geo coordinate system + // geoIndex: 0, + + large: false, + + symbol: 'circle', + symbolSize: 10, + + // symbolSize scale when zooming. + zoomScale: 0, + + // Support source-over, lighter + blendMode: 'source-over', + + itemStyle: { + opacity: 0.8 + }, + + + postEffect: { + enable: false, + colorCorrection: { + exposure: 0, + brightness: 0, + contrast: 1, + saturation: 1, + enable: true + } + } + + } +}); + +/***/ }), +/* 261 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__ = __webpack_require__(1); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__core_ViewGL__ = __webpack_require__(22); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__common_PointsBuilder__ = __webpack_require__(67); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4__common_GLViewHelper__ = __webpack_require__(103); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_5__util_retrieve__ = __webpack_require__(2); + + + + + + + + +__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.extendChartView({ + + type: 'scatterGL', + + __ecgl__: true, + + init: function (ecModel, api) { + + this.groupGL = new __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].Node(); + this.viewGL = new __WEBPACK_IMPORTED_MODULE_2__core_ViewGL__["a" /* default */]('orthographic'); + + this.viewGL.add(this.groupGL); + + this._pointsBuilderList = []; + this._currentStep = 0; + + this._sizeScale = 1; + + this._glViewHelper = new __WEBPACK_IMPORTED_MODULE_4__common_GLViewHelper__["a" /* default */](this.viewGL); + }, + + render: function (seriesModel, ecModel, api) { + this.groupGL.removeAll(); + this._glViewHelper.reset(seriesModel, api); + + if (!seriesModel.getData().count()) { + return; + } + + var pointsBuilder = this._pointsBuilderList[0]; + if (!pointsBuilder) { + pointsBuilder = this._pointsBuilderList[0] = new __WEBPACK_IMPORTED_MODULE_3__common_PointsBuilder__["a" /* default */](true, api); + } + this._pointsBuilderList.length = 1; + + this.groupGL.add(pointsBuilder.rootNode); + + this._removeTransformInPoints(seriesModel.getData().getLayout('points')); + pointsBuilder.update(seriesModel, ecModel, api); + + this.viewGL.setPostEffect(seriesModel.getModel('postEffect'), api); + }, + + incrementalPrepareRender: function (seriesModel, ecModel, api) { + this.groupGL.removeAll(); + this._glViewHelper.reset(seriesModel, api); + + this._currentStep = 0; + + this.viewGL.setPostEffect(seriesModel.getModel('postEffect'), api); + }, + + incrementalRender: function (params, seriesModel, ecModel, api) { + if (params.end <= params.start) { + return; + } + + var pointsBuilder = this._pointsBuilderList[this._currentStep]; + if (!pointsBuilder) { + pointsBuilder = new __WEBPACK_IMPORTED_MODULE_3__common_PointsBuilder__["a" /* default */](true, api); + this._pointsBuilderList[this._currentStep] = pointsBuilder; + } + this.groupGL.add(pointsBuilder.rootNode); + + this._removeTransformInPoints(seriesModel.getData().getLayout('points')); + + pointsBuilder.setSizeScale(this._sizeScale); + pointsBuilder.update(seriesModel, ecModel, api, params.start, params.end); + + api.getZr().refresh(); + + this._currentStep++; + }, + + updateTransform: function (seriesModel, ecModel, api) { + if (seriesModel.coordinateSystem.getRoamTransform) { + this._glViewHelper.updateTransform(seriesModel, api); + + var zoom = this._glViewHelper.getZoom(); + var sizeScale = Math.max((seriesModel.get('zoomScale') || 0) * (zoom - 1) + 1, 0); + this._sizeScale = sizeScale; + + this._pointsBuilderList.forEach(function (pointsBuilder) { + pointsBuilder.setSizeScale(sizeScale); + }); + } + }, + + _removeTransformInPoints: function (points) { + if (!points) { + return; + } + var pt = []; + for (var i = 0; i < points.length; i += 2) { + pt[0] = points[i]; + pt[1] = points[i + 1]; + this._glViewHelper.removeTransformInPoint(pt); + points[i] = pt[0]; + points[i + 1] = pt[1]; + } + }, + + + dispose: function () { + this.groupGL.removeAll(); + }, + + remove: function () { + this.groupGL.removeAll(); + } +}); + +/***/ }), +/* 262 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__graphGL_GraphGLSeries__ = __webpack_require__(263); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__graphGL_GraphGLView__ = __webpack_require__(268); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3_echarts_lib_visual_symbol__ = __webpack_require__(51); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3_echarts_lib_visual_symbol___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_3_echarts_lib_visual_symbol__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4__common_opacityVisual__ = __webpack_require__(17); + + + + + + + +__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.registerVisual(__WEBPACK_IMPORTED_MODULE_3_echarts_lib_visual_symbol___default()('graphGL', 'circle', null)); + +__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.registerVisual(Object(__WEBPACK_IMPORTED_MODULE_4__common_opacityVisual__["a" /* default */])('graphGL')); + +__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.registerVisual(function (ecModel) { + var paletteScope = {}; + ecModel.eachSeriesByType('graphGL', function (seriesModel) { + var categoriesData = seriesModel.getCategoriesData(); + var data = seriesModel.getData(); + + var categoryNameIdxMap = {}; + + categoriesData.each(function (idx) { + var name = categoriesData.getName(idx); + categoryNameIdxMap[name] = idx; + + var itemModel = categoriesData.getItemModel(idx); + var color = itemModel.get('itemStyle.color') + || seriesModel.getColorFromPalette(name, paletteScope); + categoriesData.setItemVisual(idx, 'color', color); + }); + + // Assign category color to visual + if (categoriesData.count()) { + data.each(function (idx) { + var model = data.getItemModel(idx); + var category = model.getShallow('category'); + if (category != null) { + if (typeof category === 'string') { + category = categoryNameIdxMap[category]; + } + if (!data.getItemVisual(idx, 'color', true)) { + data.setItemVisual( + idx, 'color', + categoriesData.getItemVisual(category, 'color') + ); + } + } + }); + } + }); +}); + +__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.registerVisual(function (ecModel) { + ecModel.eachSeriesByType('graphGL', function (seriesModel) { + var graph = seriesModel.getGraph(); + var edgeData = seriesModel.getEdgeData(); + + var colorQuery = 'lineStyle.color'.split('.'); + var opacityQuery = 'lineStyle.opacity'.split('.'); + + edgeData.setVisual('color', seriesModel.get(colorQuery)); + edgeData.setVisual('opacity', seriesModel.get(opacityQuery)); + + edgeData.each(function (idx) { + var itemModel = edgeData.getItemModel(idx); + var edge = graph.getEdgeByIndex(idx); + // Edge visual must after node visual + var color = itemModel.get(colorQuery); + var opacity = itemModel.get(opacityQuery); + switch (color) { + case 'source': + color = edge.node1.getVisual('color'); + break; + case 'target': + color = edge.node2.getVisual('color'); + break; + } + + edge.setVisual('color', color); + edge.setVisual('opacity', opacity); + }); + }); +}); + +__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.registerAction({ + type: 'graphGLRoam', + event: 'graphglroam', + update: 'series.graphGL:roam' +}, function (payload, ecModel) { + ecModel.eachComponent({ + mainType: 'series', query: payload + }, function (componentModel) { + componentModel.setView(payload); + }); +}); + +function noop() {} + +__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.registerAction({ + type: 'graphGLStartLayout', + event: 'graphgllayoutstarted', + update: 'series.graphGL:startLayout' +}, noop); + +__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.registerAction({ + type: 'graphGLStopLayout', + event: 'graphgllayoutstopped', + update: 'series.graphGL:stopLayout' +}, noop); + +__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.registerAction({ + type: 'graphGLFocusNodeAdjacency', + event: 'graphGLFocusNodeAdjacency', + update: 'series.graphGL:focusNodeAdjacency' +}, noop); + + +__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.registerAction({ + type: 'graphGLUnfocusNodeAdjacency', + event: 'graphGLUnfocusNodeAdjacency', + update: 'series.graphGL:unfocusNodeAdjacency' +}, noop); + +/***/ }), +/* 263 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__createGraphFromNodeEdge__ = __webpack_require__(264); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__util_format__ = __webpack_require__(32); + + + + +var GraphSeries = __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.extendSeriesModel({ + + type: 'series.graphGL', + + visualColorAccessPath: 'itemStyle.color', + + init: function (option) { + GraphSeries.superApply(this, 'init', arguments); + + // Provide data for legend select + this.legendDataProvider = function () { + return this._categoriesData; + }; + + this._updateCategoriesData(); + }, + + mergeOption: function (option) { + GraphSeries.superApply(this, 'mergeOption', arguments); + + this._updateCategoriesData(); + }, + + getFormattedLabel: function (dataIndex, status, dataType, dimIndex) { + var text = __WEBPACK_IMPORTED_MODULE_2__util_format__["a" /* default */].getFormattedLabel(this, dataIndex, status, dataType, dimIndex); + if (text == null) { + var data = this.getData(); + var lastDim = data.dimensions[data.dimensions.length - 1]; + text = data.get(lastDim, dataIndex); + } + return text; + }, + + getInitialData: function (option, ecModel) { + var edges = option.edges || option.links || []; + var nodes = option.data || option.nodes || []; + var self = this; + + if (nodes && edges) { + return Object(__WEBPACK_IMPORTED_MODULE_1__createGraphFromNodeEdge__["a" /* default */])(nodes, edges, this, true, beforeLink).data; + } + + function beforeLink(nodeData, edgeData) { + // Overwrite nodeData.getItemModel to + nodeData.wrapMethod('getItemModel', function (model) { + var categoriesModels = self._categoriesModels; + var categoryIdx = model.getShallow('category'); + var categoryModel = categoriesModels[categoryIdx]; + if (categoryModel) { + categoryModel.parentModel = model.parentModel; + model.parentModel = categoryModel; + } + return model; + }); + + var edgeLabelModel = self.getModel('edgeLabel'); + // For option `edgeLabel` can be found by label.xxx.xxx on item mode. + var fakeSeriesModel = new __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.Model( + { label: edgeLabelModel.option }, + edgeLabelModel.parentModel, + ecModel + ); + + edgeData.wrapMethod('getItemModel', function (model) { + model.customizeGetParent(edgeGetParent); + return model; + }); + + function edgeGetParent(path) { + path = this.parsePath(path); + return (path && path[0] === 'label') + ? fakeSeriesModel + : this.parentModel; + } + } + }, + + /** + * @return {module:echarts/data/Graph} + */ + getGraph: function () { + return this.getData().graph; + }, + + /** + * @return {module:echarts/data/List} + */ + getEdgeData: function () { + return this.getGraph().edgeData; + }, + + /** + * @return {module:echarts/data/List} + */ + getCategoriesData: function () { + return this._categoriesData; + }, + + /** + * @override + */ + formatTooltip: function (dataIndex, multipleSeries, dataType) { + if (dataType === 'edge') { + var nodeData = this.getData(); + var params = this.getDataParams(dataIndex, dataType); + var edge = nodeData.graph.getEdgeByIndex(dataIndex); + var sourceName = nodeData.getName(edge.node1.dataIndex); + var targetName = nodeData.getName(edge.node2.dataIndex); + + var html = []; + sourceName != null && html.push(sourceName); + targetName != null && html.push(targetName); + html = __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.format.encodeHTML(html.join(' > ')); + + if (params.value) { + html += ' : ' + __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.format.encodeHTML(params.value); + } + return html; + } + else { // dataType === 'node' or empty + return GraphSeries.superApply(this, 'formatTooltip', arguments); + } + }, + + _updateCategoriesData: function () { + var categories = (this.option.categories || []).map(function (category) { + // Data must has value + return category.value != null ? category : __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.util.extend({ + value: 0 + }, category); + }); + var categoriesData = new __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.List(['value'], this); + categoriesData.initData(categories); + + this._categoriesData = categoriesData; + + this._categoriesModels = categoriesData.mapArray(function (idx) { + return categoriesData.getItemModel(idx, true); + }); + }, + + setView: function (payload) { + if (payload.zoom != null) { + this.option.zoom = payload.zoom; + } + if (payload.offset != null) { + this.option.offset = payload.offset; + } + }, + + setNodePosition: function (points) { + for (var i = 0; i < points.length / 2; i++) { + var x = points[i * 2]; + var y = points[i * 2 + 1]; + + var opt = this.getData().getRawDataItem(i); + opt.x = x; + opt.y = y; + } + }, + + isAnimationEnabled: function () { + return GraphSeries.superCall(this, 'isAnimationEnabled') + // Not enable animation when do force layout + && !(this.get('layout') === 'force' && this.get('force.layoutAnimation')); + }, + + defaultOption: { + zlevel: 10, + z: 2, + + legendHoverLink: true, + + // Only support forceAtlas2 + layout: 'forceAtlas2', + + // Configuration of force directed layout + forceAtlas2: { + initLayout: null, + + GPU: true, + + steps: 1, + + // barnesHutOptimize + + // Maxp layout steps. + maxSteps: 1000, + + repulsionByDegree: true, + linLogMode: false, + strongGravityMode: false, + gravity: 1.0, + // scaling: 1.0, + + edgeWeightInfluence: 1.0, + + // Edge weight range. + edgeWeight: [1, 4], + // Node weight range. + nodeWeight: [1, 4], + + // jitterTolerence: 0.1, + preventOverlap: false, + gravityCenter: null + }, + + focusNodeAdjacency: true, + + focusNodeAdjacencyOn: 'mouseover', + + left: 'center', + top: 'center', + // right: null, + // bottom: null, + // width: '80%', + // height: '80%', + + symbol: 'circle', + symbolSize: 5, + + roam: false, + + // Default on center of graph + center: null, + + zoom: 1, + + // categories: [], + + // data: [] + // Or + // nodes: [] + // + // links: [] + // Or + // edges: [] + + label: { + show: false, + formatter: '{b}', + position: 'right', + distance: 5, + textStyle: { + fontSize: 14 + } + }, + + itemStyle: {}, + + lineStyle: { + color: '#aaa', + width: 1, + opacity: 0.5 + }, + + emphasis: { + label: { + show: true + } + }, + + animation: false + } +}); + +/* unused harmony default export */ var _unused_webpack_default_export = (GraphSeries); + +/***/ }), +/* 264 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_echarts_lib_data_Graph__ = __webpack_require__(265); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_echarts_lib_data_Graph___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_echarts_lib_data_Graph__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2_echarts_lib_data_helper_linkList__ = __webpack_require__(267); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2_echarts_lib_data_helper_linkList___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_2_echarts_lib_data_helper_linkList__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__util_retrieve__ = __webpack_require__(2); + + + + + +/* harmony default export */ __webpack_exports__["a"] = (function (nodes, edges, hostModel, directed, beforeLink) { + var graph = new __WEBPACK_IMPORTED_MODULE_1_echarts_lib_data_Graph___default.a(directed); + for (var i = 0; i < nodes.length; i++) { + graph.addNode(__WEBPACK_IMPORTED_MODULE_3__util_retrieve__["a" /* default */].firstNotNull( + // Id, name, dataIndex + nodes[i].id, nodes[i].name, i + ), i); + } + + var linkNameList = []; + var validEdges = []; + var linkCount = 0; + for (var i = 0; i < edges.length; i++) { + var link = edges[i]; + var source = link.source; + var target = link.target; + // addEdge may fail when source or target not exists + if (graph.addEdge(source, target, linkCount)) { + validEdges.push(link); + linkNameList.push(__WEBPACK_IMPORTED_MODULE_3__util_retrieve__["a" /* default */].firstNotNull(link.id, source + ' > ' + target)); + linkCount++; + } + } + + var nodeData; + + // FIXME, support more coordinate systems. + var dimensionNames = __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.helper.completeDimensions( + ['value'], nodes + ); + nodeData = new __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.List(dimensionNames, hostModel); + nodeData.initData(nodes); + + var edgeData = new __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.List(['value'], hostModel); + edgeData.initData(validEdges, linkNameList); + + beforeLink && beforeLink(nodeData, edgeData); + + __WEBPACK_IMPORTED_MODULE_2_echarts_lib_data_helper_linkList___default()({ + mainData: nodeData, + struct: graph, + structAttr: 'graph', + datas: {node: nodeData, edge: edgeData}, + datasAttr: {node: 'data', edge: 'edgeData'} + }); + + // Update dataIndex of nodes and edges because invalid edge may be removed + graph.update(); + + return graph; +});; + +/***/ }), +/* 265 */ +/***/ (function(module, exports, __webpack_require__) { + +var _config = __webpack_require__(104); + +var __DEV__ = _config.__DEV__; + +var zrUtil = __webpack_require__(13); + +var _clazz = __webpack_require__(266); + +var enableClassCheck = _clazz.enableClassCheck; + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/** + * Graph data structure + * + * @module echarts/data/Graph + * @author Yi Shen(https://www.github.com/pissang) + */ +// id may be function name of Object, add a prefix to avoid this problem. +function generateNodeKey(id) { + return '_EC_' + id; +} +/** + * @alias module:echarts/data/Graph + * @constructor + * @param {boolean} directed + */ + + +var Graph = function (directed) { + /** + * 是否是有向图 + * @type {boolean} + * @private + */ + this._directed = directed || false; + /** + * @type {Array.} + * @readOnly + */ + + this.nodes = []; + /** + * @type {Array.} + * @readOnly + */ + + this.edges = []; + /** + * @type {Object.} + * @private + */ + + this._nodesMap = {}; + /** + * @type {Object.} + * @private + */ + + this._edgesMap = {}; + /** + * @type {module:echarts/data/List} + * @readOnly + */ + + this.data; + /** + * @type {module:echarts/data/List} + * @readOnly + */ + + this.edgeData; +}; + +var graphProto = Graph.prototype; +/** + * @type {string} + */ + +graphProto.type = 'graph'; +/** + * If is directed graph + * @return {boolean} + */ + +graphProto.isDirected = function () { + return this._directed; +}; +/** + * Add a new node + * @param {string} id + * @param {number} [dataIndex] + */ + + +graphProto.addNode = function (id, dataIndex) { + id = id || '' + dataIndex; + var nodesMap = this._nodesMap; + + if (nodesMap[generateNodeKey(id)]) { + return; + } + + var node = new Node(id, dataIndex); + node.hostGraph = this; + this.nodes.push(node); + nodesMap[generateNodeKey(id)] = node; + return node; +}; +/** + * Get node by data index + * @param {number} dataIndex + * @return {module:echarts/data/Graph~Node} + */ + + +graphProto.getNodeByIndex = function (dataIndex) { + var rawIdx = this.data.getRawIndex(dataIndex); + return this.nodes[rawIdx]; +}; +/** + * Get node by id + * @param {string} id + * @return {module:echarts/data/Graph.Node} + */ + + +graphProto.getNodeById = function (id) { + return this._nodesMap[generateNodeKey(id)]; +}; +/** + * Add a new edge + * @param {number|string|module:echarts/data/Graph.Node} n1 + * @param {number|string|module:echarts/data/Graph.Node} n2 + * @param {number} [dataIndex=-1] + * @return {module:echarts/data/Graph.Edge} + */ + + +graphProto.addEdge = function (n1, n2, dataIndex) { + var nodesMap = this._nodesMap; + var edgesMap = this._edgesMap; // PNEDING + + if (typeof n1 === 'number') { + n1 = this.nodes[n1]; + } + + if (typeof n2 === 'number') { + n2 = this.nodes[n2]; + } + + if (!Node.isInstance(n1)) { + n1 = nodesMap[generateNodeKey(n1)]; + } + + if (!Node.isInstance(n2)) { + n2 = nodesMap[generateNodeKey(n2)]; + } + + if (!n1 || !n2) { + return; + } + + var key = n1.id + '-' + n2.id; // PENDING + + if (edgesMap[key]) { + return; + } + + var edge = new Edge(n1, n2, dataIndex); + edge.hostGraph = this; + + if (this._directed) { + n1.outEdges.push(edge); + n2.inEdges.push(edge); + } + + n1.edges.push(edge); + + if (n1 !== n2) { + n2.edges.push(edge); + } + + this.edges.push(edge); + edgesMap[key] = edge; + return edge; +}; +/** + * Get edge by data index + * @param {number} dataIndex + * @return {module:echarts/data/Graph~Node} + */ + + +graphProto.getEdgeByIndex = function (dataIndex) { + var rawIdx = this.edgeData.getRawIndex(dataIndex); + return this.edges[rawIdx]; +}; +/** + * Get edge by two linked nodes + * @param {module:echarts/data/Graph.Node|string} n1 + * @param {module:echarts/data/Graph.Node|string} n2 + * @return {module:echarts/data/Graph.Edge} + */ + + +graphProto.getEdge = function (n1, n2) { + if (Node.isInstance(n1)) { + n1 = n1.id; + } + + if (Node.isInstance(n2)) { + n2 = n2.id; + } + + var edgesMap = this._edgesMap; + + if (this._directed) { + return edgesMap[n1 + '-' + n2]; + } else { + return edgesMap[n1 + '-' + n2] || edgesMap[n2 + '-' + n1]; + } +}; +/** + * Iterate all nodes + * @param {Function} cb + * @param {*} [context] + */ + + +graphProto.eachNode = function (cb, context) { + var nodes = this.nodes; + var len = nodes.length; + + for (var i = 0; i < len; i++) { + if (nodes[i].dataIndex >= 0) { + cb.call(context, nodes[i], i); + } + } +}; +/** + * Iterate all edges + * @param {Function} cb + * @param {*} [context] + */ + + +graphProto.eachEdge = function (cb, context) { + var edges = this.edges; + var len = edges.length; + + for (var i = 0; i < len; i++) { + if (edges[i].dataIndex >= 0 && edges[i].node1.dataIndex >= 0 && edges[i].node2.dataIndex >= 0) { + cb.call(context, edges[i], i); + } + } +}; +/** + * Breadth first traverse + * @param {Function} cb + * @param {module:echarts/data/Graph.Node} startNode + * @param {string} [direction='none'] 'none'|'in'|'out' + * @param {*} [context] + */ + + +graphProto.breadthFirstTraverse = function (cb, startNode, direction, context) { + if (!Node.isInstance(startNode)) { + startNode = this._nodesMap[generateNodeKey(startNode)]; + } + + if (!startNode) { + return; + } + + var edgeType = direction === 'out' ? 'outEdges' : direction === 'in' ? 'inEdges' : 'edges'; + + for (var i = 0; i < this.nodes.length; i++) { + this.nodes[i].__visited = false; + } + + if (cb.call(context, startNode, null)) { + return; + } + + var queue = [startNode]; + + while (queue.length) { + var currentNode = queue.shift(); + var edges = currentNode[edgeType]; + + for (var i = 0; i < edges.length; i++) { + var e = edges[i]; + var otherNode = e.node1 === currentNode ? e.node2 : e.node1; + + if (!otherNode.__visited) { + if (cb.call(context, otherNode, currentNode)) { + // Stop traversing + return; + } + + queue.push(otherNode); + otherNode.__visited = true; + } + } + } +}; // TODO +// graphProto.depthFirstTraverse = function ( +// cb, startNode, direction, context +// ) { +// }; +// Filter update + + +graphProto.update = function () { + var data = this.data; + var edgeData = this.edgeData; + var nodes = this.nodes; + var edges = this.edges; + + for (var i = 0, len = nodes.length; i < len; i++) { + nodes[i].dataIndex = -1; + } + + for (var i = 0, len = data.count(); i < len; i++) { + nodes[data.getRawIndex(i)].dataIndex = i; + } + + edgeData.filterSelf(function (idx) { + var edge = edges[edgeData.getRawIndex(idx)]; + return edge.node1.dataIndex >= 0 && edge.node2.dataIndex >= 0; + }); // Update edge + + for (var i = 0, len = edges.length; i < len; i++) { + edges[i].dataIndex = -1; + } + + for (var i = 0, len = edgeData.count(); i < len; i++) { + edges[edgeData.getRawIndex(i)].dataIndex = i; + } +}; +/** + * @return {module:echarts/data/Graph} + */ + + +graphProto.clone = function () { + var graph = new Graph(this._directed); + var nodes = this.nodes; + var edges = this.edges; + + for (var i = 0; i < nodes.length; i++) { + graph.addNode(nodes[i].id, nodes[i].dataIndex); + } + + for (var i = 0; i < edges.length; i++) { + var e = edges[i]; + graph.addEdge(e.node1.id, e.node2.id, e.dataIndex); + } + + return graph; +}; +/** + * @alias module:echarts/data/Graph.Node + */ + + +function Node(id, dataIndex) { + /** + * @type {string} + */ + this.id = id == null ? '' : id; + /** + * @type {Array.} + */ + + this.inEdges = []; + /** + * @type {Array.} + */ + + this.outEdges = []; + /** + * @type {Array.} + */ + + this.edges = []; + /** + * @type {module:echarts/data/Graph} + */ + + this.hostGraph; + /** + * @type {number} + */ + + this.dataIndex = dataIndex == null ? -1 : dataIndex; +} + +Node.prototype = { + constructor: Node, + + /** + * @return {number} + */ + degree: function () { + return this.edges.length; + }, + + /** + * @return {number} + */ + inDegree: function () { + return this.inEdges.length; + }, + + /** + * @return {number} + */ + outDegree: function () { + return this.outEdges.length; + }, + + /** + * @param {string} [path] + * @return {module:echarts/model/Model} + */ + getModel: function (path) { + if (this.dataIndex < 0) { + return; + } + + var graph = this.hostGraph; + var itemModel = graph.data.getItemModel(this.dataIndex); + return itemModel.getModel(path); + } +}; +/** + * 图边 + * @alias module:echarts/data/Graph.Edge + * @param {module:echarts/data/Graph.Node} n1 + * @param {module:echarts/data/Graph.Node} n2 + * @param {number} [dataIndex=-1] + */ + +function Edge(n1, n2, dataIndex) { + /** + * 节点1,如果是有向图则为源节点 + * @type {module:echarts/data/Graph.Node} + */ + this.node1 = n1; + /** + * 节点2,如果是有向图则为目标节点 + * @type {module:echarts/data/Graph.Node} + */ + + this.node2 = n2; + this.dataIndex = dataIndex == null ? -1 : dataIndex; +} +/** + * @param {string} [path] + * @return {module:echarts/model/Model} + */ + + +Edge.prototype.getModel = function (path) { + if (this.dataIndex < 0) { + return; + } + + var graph = this.hostGraph; + var itemModel = graph.edgeData.getItemModel(this.dataIndex); + return itemModel.getModel(path); +}; + +var createGraphDataProxyMixin = function (hostName, dataName) { + return { + /** + * @param {string=} [dimension='value'] Default 'value'. can be 'a', 'b', 'c', 'd', 'e'. + * @return {number} + */ + getValue: function (dimension) { + var data = this[hostName][dataName]; + return data.get(data.getDimension(dimension || 'value'), this.dataIndex); + }, + + /** + * @param {Object|string} key + * @param {*} [value] + */ + setVisual: function (key, value) { + this.dataIndex >= 0 && this[hostName][dataName].setItemVisual(this.dataIndex, key, value); + }, + + /** + * @param {string} key + * @return {boolean} + */ + getVisual: function (key, ignoreParent) { + return this[hostName][dataName].getItemVisual(this.dataIndex, key, ignoreParent); + }, + + /** + * @param {Object} layout + * @return {boolean} [merge=false] + */ + setLayout: function (layout, merge) { + this.dataIndex >= 0 && this[hostName][dataName].setItemLayout(this.dataIndex, layout, merge); + }, + + /** + * @return {Object} + */ + getLayout: function () { + return this[hostName][dataName].getItemLayout(this.dataIndex); + }, + + /** + * @return {module:zrender/Element} + */ + getGraphicEl: function () { + return this[hostName][dataName].getItemGraphicEl(this.dataIndex); + }, + + /** + * @return {number} + */ + getRawIndex: function () { + return this[hostName][dataName].getRawIndex(this.dataIndex); + } + }; +}; + +zrUtil.mixin(Node, createGraphDataProxyMixin('hostGraph', 'data')); +zrUtil.mixin(Edge, createGraphDataProxyMixin('hostGraph', 'edgeData')); +Graph.Node = Node; +Graph.Edge = Edge; +enableClassCheck(Node); +enableClassCheck(Edge); +var _default = Graph; +module.exports = _default; + +/***/ }), +/* 266 */ +/***/ (function(module, exports, __webpack_require__) { + +var _config = __webpack_require__(104); + +var __DEV__ = _config.__DEV__; + +var zrUtil = __webpack_require__(13); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ +var TYPE_DELIMITER = '.'; +var IS_CONTAINER = '___EC__COMPONENT__CONTAINER___'; +/** + * Notice, parseClassType('') should returns {main: '', sub: ''} + * @public + */ + +function parseClassType(componentType) { + var ret = { + main: '', + sub: '' + }; + + if (componentType) { + componentType = componentType.split(TYPE_DELIMITER); + ret.main = componentType[0] || ''; + ret.sub = componentType[1] || ''; + } + + return ret; +} +/** + * @public + */ + + +function checkClassType(componentType) { + zrUtil.assert(/^[a-zA-Z0-9_]+([.][a-zA-Z0-9_]+)?$/.test(componentType), 'componentType "' + componentType + '" illegal'); +} +/** + * @public + */ + + +function enableClassExtend(RootClass, mandatoryMethods) { + RootClass.$constructor = RootClass; + + RootClass.extend = function (proto) { + var superClass = this; + + var ExtendedClass = function () { + if (!proto.$constructor) { + superClass.apply(this, arguments); + } else { + proto.$constructor.apply(this, arguments); + } + }; + + zrUtil.extend(ExtendedClass.prototype, proto); + ExtendedClass.extend = this.extend; + ExtendedClass.superCall = superCall; + ExtendedClass.superApply = superApply; + zrUtil.inherits(ExtendedClass, this); + ExtendedClass.superClass = superClass; + return ExtendedClass; + }; +} + +var classBase = 0; +/** + * Can not use instanceof, consider different scope by + * cross domain or es module import in ec extensions. + * Mount a method "isInstance()" to Clz. + */ + +function enableClassCheck(Clz) { + var classAttr = ['__\0is_clz', classBase++, Math.random().toFixed(3)].join('_'); + Clz.prototype[classAttr] = true; + + Clz.isInstance = function (obj) { + return !!(obj && obj[classAttr]); + }; +} // superCall should have class info, which can not be fetch from 'this'. +// Consider this case: +// class A has method f, +// class B inherits class A, overrides method f, f call superApply('f'), +// class C inherits class B, do not overrides method f, +// then when method of class C is called, dead loop occured. + + +function superCall(context, methodName) { + var args = zrUtil.slice(arguments, 2); + return this.superClass.prototype[methodName].apply(context, args); +} + +function superApply(context, methodName, args) { + return this.superClass.prototype[methodName].apply(context, args); +} +/** + * @param {Object} entity + * @param {Object} options + * @param {boolean} [options.registerWhenExtend] + * @public + */ + + +function enableClassManagement(entity, options) { + options = options || {}; + /** + * Component model classes + * key: componentType, + * value: + * componentClass, when componentType is 'xxx' + * or Object., when componentType is 'xxx.yy' + * @type {Object} + */ + + var storage = {}; + + entity.registerClass = function (Clazz, componentType) { + if (componentType) { + checkClassType(componentType); + componentType = parseClassType(componentType); + + if (!componentType.sub) { + storage[componentType.main] = Clazz; + } else if (componentType.sub !== IS_CONTAINER) { + var container = makeContainer(componentType); + container[componentType.sub] = Clazz; + } + } + + return Clazz; + }; + + entity.getClass = function (componentMainType, subType, throwWhenNotFound) { + var Clazz = storage[componentMainType]; + + if (Clazz && Clazz[IS_CONTAINER]) { + Clazz = subType ? Clazz[subType] : null; + } + + if (throwWhenNotFound && !Clazz) { + throw new Error(!subType ? componentMainType + '.' + 'type should be specified.' : 'Component ' + componentMainType + '.' + (subType || '') + ' not exists. Load it first.'); + } + + return Clazz; + }; + + entity.getClassesByMainType = function (componentType) { + componentType = parseClassType(componentType); + var result = []; + var obj = storage[componentType.main]; + + if (obj && obj[IS_CONTAINER]) { + zrUtil.each(obj, function (o, type) { + type !== IS_CONTAINER && result.push(o); + }); + } else { + result.push(obj); + } + + return result; + }; + + entity.hasClass = function (componentType) { + // Just consider componentType.main. + componentType = parseClassType(componentType); + return !!storage[componentType.main]; + }; + /** + * @return {Array.} Like ['aa', 'bb'], but can not be ['aa.xx'] + */ + + + entity.getAllClassMainTypes = function () { + var types = []; + zrUtil.each(storage, function (obj, type) { + types.push(type); + }); + return types; + }; + /** + * If a main type is container and has sub types + * @param {string} mainType + * @return {boolean} + */ + + + entity.hasSubTypes = function (componentType) { + componentType = parseClassType(componentType); + var obj = storage[componentType.main]; + return obj && obj[IS_CONTAINER]; + }; + + entity.parseClassType = parseClassType; + + function makeContainer(componentType) { + var container = storage[componentType.main]; + + if (!container || !container[IS_CONTAINER]) { + container = storage[componentType.main] = {}; + container[IS_CONTAINER] = true; + } + + return container; + } + + if (options.registerWhenExtend) { + var originalExtend = entity.extend; + + if (originalExtend) { + entity.extend = function (proto) { + var ExtendedClass = originalExtend.call(this, proto); + return entity.registerClass(ExtendedClass, proto.type); + }; + } + } + + return entity; +} +/** + * @param {string|Array.} properties + */ + + +function setReadOnly(obj, properties) {// FIXME It seems broken in IE8 simulation of IE11 + // if (!zrUtil.isArray(properties)) { + // properties = properties != null ? [properties] : []; + // } + // zrUtil.each(properties, function (prop) { + // var value = obj[prop]; + // Object.defineProperty + // && Object.defineProperty(obj, prop, { + // value: value, writable: false + // }); + // zrUtil.isArray(obj[prop]) + // && Object.freeze + // && Object.freeze(obj[prop]); + // }); +} + +exports.parseClassType = parseClassType; +exports.enableClassExtend = enableClassExtend; +exports.enableClassCheck = enableClassCheck; +exports.enableClassManagement = enableClassManagement; +exports.setReadOnly = setReadOnly; + +/***/ }), +/* 267 */ +/***/ (function(module, exports, __webpack_require__) { + +var zrUtil = __webpack_require__(13); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/** + * Link lists and struct (graph or tree) + */ +var each = zrUtil.each; +var DATAS = '\0__link_datas'; +var MAIN_DATA = '\0__link_mainData'; // Caution: +// In most case, either list or its shallow clones (see list.cloneShallow) +// is active in echarts process. So considering heap memory consumption, +// we do not clone tree or graph, but share them among list and its shallow clones. +// But in some rare case, we have to keep old list (like do animation in chart). So +// please take care that both the old list and the new list share the same tree/graph. + +/** + * @param {Object} opt + * @param {module:echarts/data/List} opt.mainData + * @param {Object} [opt.struct] For example, instance of Graph or Tree. + * @param {string} [opt.structAttr] designation: list[structAttr] = struct; + * @param {Object} [opt.datas] {dataType: data}, + * like: {node: nodeList, edge: edgeList}. + * Should contain mainData. + * @param {Object} [opt.datasAttr] {dataType: attr}, + * designation: struct[datasAttr[dataType]] = list; + */ + +function linkList(opt) { + var mainData = opt.mainData; + var datas = opt.datas; + + if (!datas) { + datas = { + main: mainData + }; + opt.datasAttr = { + main: 'data' + }; + } + + opt.datas = opt.mainData = null; + linkAll(mainData, datas, opt); // Porxy data original methods. + + each(datas, function (data) { + each(mainData.TRANSFERABLE_METHODS, function (methodName) { + data.wrapMethod(methodName, zrUtil.curry(transferInjection, opt)); + }); + }); // Beyond transfer, additional features should be added to `cloneShallow`. + + mainData.wrapMethod('cloneShallow', zrUtil.curry(cloneShallowInjection, opt)); // Only mainData trigger change, because struct.update may trigger + // another changable methods, which may bring about dead lock. + + each(mainData.CHANGABLE_METHODS, function (methodName) { + mainData.wrapMethod(methodName, zrUtil.curry(changeInjection, opt)); + }); // Make sure datas contains mainData. + + zrUtil.assert(datas[mainData.dataType] === mainData); +} + +function transferInjection(opt, res) { + if (isMainData(this)) { + // Transfer datas to new main data. + var datas = zrUtil.extend({}, this[DATAS]); + datas[this.dataType] = res; + linkAll(res, datas, opt); + } else { + // Modify the reference in main data to point newData. + linkSingle(res, this.dataType, this[MAIN_DATA], opt); + } + + return res; +} + +function changeInjection(opt, res) { + opt.struct && opt.struct.update(this); + return res; +} + +function cloneShallowInjection(opt, res) { + // cloneShallow, which brings about some fragilities, may be inappropriate + // to be exposed as an API. So for implementation simplicity we can make + // the restriction that cloneShallow of not-mainData should not be invoked + // outside, but only be invoked here. + each(res[DATAS], function (data, dataType) { + data !== res && linkSingle(data.cloneShallow(), dataType, res, opt); + }); + return res; +} +/** + * Supplement method to List. + * + * @public + * @param {string} [dataType] If not specified, return mainData. + * @return {module:echarts/data/List} + */ + + +function getLinkedData(dataType) { + var mainData = this[MAIN_DATA]; + return dataType == null || mainData == null ? mainData : mainData[DATAS][dataType]; +} + +function isMainData(data) { + return data[MAIN_DATA] === data; +} + +function linkAll(mainData, datas, opt) { + mainData[DATAS] = {}; + each(datas, function (data, dataType) { + linkSingle(data, dataType, mainData, opt); + }); +} + +function linkSingle(data, dataType, mainData, opt) { + mainData[DATAS][dataType] = data; + data[MAIN_DATA] = mainData; + data.dataType = dataType; + + if (opt.struct) { + data[opt.structAttr] = opt.struct; + opt.struct[opt.datasAttr[dataType]] = data; + } // Supplement method. + + + data.getLinkedData = getLinkedData; +} + +var _default = linkList; +module.exports = _default; + +/***/ }), +/* 268 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_echarts_lib_util_layout__ = __webpack_require__(47); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_echarts_lib_util_layout___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_echarts_lib_util_layout__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__util_graphicGL__ = __webpack_require__(1); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__core_ViewGL__ = __webpack_require__(22); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4__util_geometry_Lines2D__ = __webpack_require__(105); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_5__util_retrieve__ = __webpack_require__(2); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_6__ForceAtlas2GPU__ = __webpack_require__(269); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_7__ForceAtlas2__ = __webpack_require__(271); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_8_zrender_lib_animation_requestAnimationFrame__ = __webpack_require__(80); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_8_zrender_lib_animation_requestAnimationFrame___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_8_zrender_lib_animation_requestAnimationFrame__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_9_claygl_src_dep_glmatrix__ = __webpack_require__(6); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_10__util_Roam2DControl__ = __webpack_require__(273); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_11__common_PointsBuilder__ = __webpack_require__(67); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_12__util_shader_lines2D_glsl_js__ = __webpack_require__(274); + + + + + + + + + + + +var vec2 = __WEBPACK_IMPORTED_MODULE_9_claygl_src_dep_glmatrix__["a" /* default */].vec2; + + + + + + +__WEBPACK_IMPORTED_MODULE_2__util_graphicGL__["a" /* default */].Shader.import(__WEBPACK_IMPORTED_MODULE_12__util_shader_lines2D_glsl_js__["a" /* default */]); + +var globalLayoutId = 1; + +__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.extendChartView({ + + type: 'graphGL', + + __ecgl__: true, + + init: function (ecModel, api) { + + this.groupGL = new __WEBPACK_IMPORTED_MODULE_2__util_graphicGL__["a" /* default */].Node(); + this.viewGL = new __WEBPACK_IMPORTED_MODULE_3__core_ViewGL__["a" /* default */]('orthographic'); + this.viewGL.camera.left = this.viewGL.camera.right = 0; + + this.viewGL.add(this.groupGL); + + this._pointsBuilder = new __WEBPACK_IMPORTED_MODULE_11__common_PointsBuilder__["a" /* default */](true, api); + + // Mesh used during force directed layout. + this._forceEdgesMesh = new __WEBPACK_IMPORTED_MODULE_2__util_graphicGL__["a" /* default */].Mesh({ + material: new __WEBPACK_IMPORTED_MODULE_2__util_graphicGL__["a" /* default */].Material({ + shader: __WEBPACK_IMPORTED_MODULE_2__util_graphicGL__["a" /* default */].createShader('ecgl.forceAtlas2.edges'), + transparent: true, + depthMask: false, + depthTest: false + }), + $ignorePicking: true, + geometry: new __WEBPACK_IMPORTED_MODULE_2__util_graphicGL__["a" /* default */].Geometry({ + attributes: { + node: new __WEBPACK_IMPORTED_MODULE_2__util_graphicGL__["a" /* default */].Geometry.Attribute('node', 'float', 2), + color: new __WEBPACK_IMPORTED_MODULE_2__util_graphicGL__["a" /* default */].Geometry.Attribute('color', 'float', 4, 'COLOR') + }, + dynamic: true, + mainAttribute: 'node' + }), + renderOrder: -1, + mode: __WEBPACK_IMPORTED_MODULE_2__util_graphicGL__["a" /* default */].Mesh.LINES + }); + + // Mesh used after force directed layout. + this._edgesMesh = new __WEBPACK_IMPORTED_MODULE_2__util_graphicGL__["a" /* default */].Mesh({ + material: new __WEBPACK_IMPORTED_MODULE_2__util_graphicGL__["a" /* default */].Material({ + shader: __WEBPACK_IMPORTED_MODULE_2__util_graphicGL__["a" /* default */].createShader('ecgl.meshLines2D'), + transparent: true, + depthMask: false, + depthTest: false + }), + $ignorePicking: true, + geometry: new __WEBPACK_IMPORTED_MODULE_4__util_geometry_Lines2D__["a" /* default */]({ + useNativeLine: false, + dynamic: true + }), + renderOrder: -1, + culling: false + }); + + this._layoutId = 0; + + this._control = new __WEBPACK_IMPORTED_MODULE_10__util_Roam2DControl__["a" /* default */]({ + zr: api.getZr(), + viewGL: this.viewGL + }); + this._control.setTarget(this.groupGL); + this._control.init(); + + + this._clickHandler = this._clickHandler.bind(this); + }, + + render: function (seriesModel, ecModel, api) { + this.groupGL.add(this._pointsBuilder.rootNode); + + this._model = seriesModel; + this._api = api; + + this._initLayout(seriesModel, ecModel, api); + + this._pointsBuilder.update(seriesModel, ecModel, api); + + if (!(this._forceLayoutInstance instanceof __WEBPACK_IMPORTED_MODULE_6__ForceAtlas2GPU__["a" /* default */])) { + this.groupGL.remove(this._forceEdgesMesh); + } + + this._updateCamera(seriesModel, api); + + this._control.off('update'); + this._control.on('update', function () { + api.dispatchAction({ + type: 'graphGLRoam', + seriesId: seriesModel.id, + zoom: this._control.getZoom(), + offset: this._control.getOffset() + }); + + this._pointsBuilder.updateView(this.viewGL.camera); + }, this); + + this._control.setZoom(__WEBPACK_IMPORTED_MODULE_5__util_retrieve__["a" /* default */].firstNotNull(seriesModel.get('zoom'), 1)); + this._control.setOffset(seriesModel.get('offset') || [0, 0]); + + var mesh = this._pointsBuilder.getPointsMesh(); + mesh.off('mousemove', this._mousemoveHandler); + mesh.off('mouseout', this._mouseOutHandler, this); + api.getZr().off('click', this._clickHandler); + + this._pointsBuilder.highlightOnMouseover = true; + if (seriesModel.get('focusNodeAdjacency')) { + var focusNodeAdjacencyOn = seriesModel.get('focusNodeAdjacencyOn'); + if (focusNodeAdjacencyOn === 'click') { + // Remove default emphasis effect + api.getZr().on('click', this._clickHandler); + } + else if (focusNodeAdjacencyOn === 'mouseover') { + mesh.on('mousemove', this._mousemoveHandler, this); + mesh.on('mouseout', this._mouseOutHandler, this); + + this._pointsBuilder.highlightOnMouseover = false; + } + else { + if (true) { + console.warn('Unkown focusNodeAdjacencyOn value \s' + focusNodeAdjacencyOn); + } + } + } + + // Reset + this._lastMouseOverDataIndex = -1; + }, + + _clickHandler: function (e) { + if (this._layouting) { + return; + } + var dataIndex = this._pointsBuilder.getPointsMesh().dataIndex; + if (dataIndex >= 0) { + this._api.dispatchAction({ + type: 'graphGLFocusNodeAdjacency', + seriesId: this._model.id, + dataIndex: dataIndex + }); + } + else { + this._api.dispatchAction({ + type: 'graphGLUnfocusNodeAdjacency', + seriesId: this._model.id + }); + } + }, + + _mousemoveHandler: function (e) { + if (this._layouting) { + return; + } + var dataIndex = this._pointsBuilder.getPointsMesh().dataIndex; + if (dataIndex >= 0) { + if (dataIndex !== this._lastMouseOverDataIndex) { + this._api.dispatchAction({ + type: 'graphGLFocusNodeAdjacency', + seriesId: this._model.id, + dataIndex: dataIndex + }); + } + } + else { + this._mouseOutHandler(e); + } + + this._lastMouseOverDataIndex = dataIndex; + }, + + _mouseOutHandler: function (e) { + if (this._layouting) { + return; + } + + this._api.dispatchAction({ + type: 'graphGLUnfocusNodeAdjacency', + seriesId: this._model.id + }); + + this._lastMouseOverDataIndex = -1; + }, + + _updateForceEdgesGeometry: function (edges, seriesModel) { + var geometry = this._forceEdgesMesh.geometry; + + var edgeData = seriesModel.getEdgeData(); + var offset = 0; + var layoutInstance = this._forceLayoutInstance; + var vertexCount = edgeData.count() * 2; + geometry.attributes.node.init(vertexCount); + geometry.attributes.color.init(vertexCount); + edgeData.each(function (idx) { + var edge = edges[idx]; + geometry.attributes.node.set(offset, layoutInstance.getNodeUV(edge.node1)); + geometry.attributes.node.set(offset + 1, layoutInstance.getNodeUV(edge.node2)); + + var color = edgeData.getItemVisual(edge.dataIndex, 'color'); + var colorArr = __WEBPACK_IMPORTED_MODULE_2__util_graphicGL__["a" /* default */].parseColor(color); + colorArr[3] *= __WEBPACK_IMPORTED_MODULE_5__util_retrieve__["a" /* default */].firstNotNull( + edgeData.getItemVisual(edge.dataIndex, 'opacity'), 1 + ); + geometry.attributes.color.set(offset, colorArr); + geometry.attributes.color.set(offset + 1, colorArr); + + offset += 2; + }); + geometry.dirty(); + }, + + _updateMeshLinesGeometry: function () { + var edgeData = this._model.getEdgeData(); + var geometry = this._edgesMesh.geometry; + var edgeData = this._model.getEdgeData(); + var points = this._model.getData().getLayout('points'); + + geometry.resetOffset(); + geometry.setVertexCount(edgeData.count() * geometry.getLineVertexCount()); + geometry.setTriangleCount(edgeData.count() * geometry.getLineTriangleCount()); + + var p0 = []; + var p1 = []; + + var lineWidthQuery = ['lineStyle', 'width']; + + this._originalEdgeColors = new Float32Array(edgeData.count() * 4); + this._edgeIndicesMap = new Float32Array(edgeData.count()); + edgeData.each(function (idx) { + var edge = edgeData.graph.getEdgeByIndex(idx); + var idx1 = edge.node1.dataIndex * 2; + var idx2 = edge.node2.dataIndex * 2; + p0[0] = points[idx1]; + p0[1] = points[idx1 + 1]; + p1[0] = points[idx2]; + p1[1] = points[idx2 + 1]; + + var color = edgeData.getItemVisual(edge.dataIndex, 'color'); + var colorArr = __WEBPACK_IMPORTED_MODULE_2__util_graphicGL__["a" /* default */].parseColor(color); + colorArr[3] *= __WEBPACK_IMPORTED_MODULE_5__util_retrieve__["a" /* default */].firstNotNull(edgeData.getItemVisual(edge.dataIndex, 'opacity'), 1); + var itemModel = edgeData.getItemModel(edge.dataIndex); + var lineWidth = __WEBPACK_IMPORTED_MODULE_5__util_retrieve__["a" /* default */].firstNotNull(itemModel.get(lineWidthQuery), 1) * this._api.getDevicePixelRatio(); + + geometry.addLine(p0, p1, colorArr, lineWidth); + + for (var k = 0; k < 4; k++) { + this._originalEdgeColors[edge.dataIndex * 4 + k] = colorArr[k]; + } + this._edgeIndicesMap[edge.dataIndex] = idx; + }, this); + + geometry.dirty(); + }, + + _updateForceNodesGeometry: function (nodeData) { + var pointsMesh = this._pointsBuilder.getPointsMesh(); + var pos = []; + for (var i = 0; i < nodeData.count(); i++) { + this._forceLayoutInstance.getNodeUV(i, pos); + pointsMesh.geometry.attributes.position.set(i, pos); + } + pointsMesh.geometry.dirty('position'); + }, + + _initLayout: function (seriesModel, ecModel, api) { + var layout = seriesModel.get('layout'); + var graph = seriesModel.getGraph(); + + var boxLayoutOption = seriesModel.getBoxLayoutParams(); + var viewport = __WEBPACK_IMPORTED_MODULE_1_echarts_lib_util_layout___default.a.getLayoutRect(boxLayoutOption, { + width: api.getWidth(), + height: api.getHeight() + }); + + if (layout === 'force') { + if (true) { + console.warn('Currently only forceAtlas2 layout supported.'); + } + layout = 'forceAtlas2'; + } + // Stop previous layout + this.stopLayout(seriesModel, ecModel, api, { + beforeLayout: true + }); + + var nodeData = seriesModel.getData(); + var edgeData = seriesModel.getData(); + if (layout === 'forceAtlas2') { + var layoutModel = seriesModel.getModel('forceAtlas2'); + var layoutInstance = this._forceLayoutInstance; + var nodes = []; + var edges = []; + + var nodeDataExtent = nodeData.getDataExtent('value'); + var edgeDataExtent = edgeData.getDataExtent('value'); + + var edgeWeightRange = __WEBPACK_IMPORTED_MODULE_5__util_retrieve__["a" /* default */].firstNotNull(layoutModel.get('edgeWeight'), 1.0); + var nodeWeightRange = __WEBPACK_IMPORTED_MODULE_5__util_retrieve__["a" /* default */].firstNotNull(layoutModel.get('nodeWeight'), 1.0); + if (typeof edgeWeightRange === 'number') { + edgeWeightRange = [edgeWeightRange, edgeWeightRange]; + } + if (typeof nodeWeightRange === 'number') { + nodeWeightRange = [nodeWeightRange, nodeWeightRange]; + } + + var offset = 0; + var nodesIndicesMap = {}; + + var layoutPoints = new Float32Array(nodeData.count() * 2); + graph.eachNode(function (node) { + var dataIndex = node.dataIndex; + var value = nodeData.get('value', dataIndex); + var x; + var y; + if (nodeData.hasItemOption) { + var itemModel = nodeData.getItemModel(dataIndex); + x = itemModel.get('x'); + y = itemModel.get('y'); + } + if (x == null) { + // Random in rectangle + x = viewport.x + Math.random() * viewport.width; + y = viewport.y + Math.random() * viewport.height; + } + layoutPoints[offset * 2] = x; + layoutPoints[offset * 2 + 1] = y; + + nodesIndicesMap[node.id] = offset++; + var mass = __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.number.linearMap(value, nodeDataExtent, nodeWeightRange); + if (isNaN(mass)) { + if (!isNaN(nodeWeightRange[0])) { + mass = nodeWeightRange[0]; + } + else { + mass = 1; + } + } + nodes.push({ + x: x, y: y, mass: mass, size: nodeData.getItemVisual(dataIndex, 'symbolSize') + }); + }); + nodeData.setLayout('points', layoutPoints); + + graph.eachEdge(function (edge) { + var dataIndex = edge.dataIndex; + var value = nodeData.get('value', dataIndex); + var weight = __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.number.linearMap(value, edgeDataExtent, edgeWeightRange); + if (isNaN(weight)) { + if (!isNaN(edgeWeightRange[0])) { + weight = edgeWeightRange[0]; + } + else { + weight = 1; + } + } + edges.push({ + node1: nodesIndicesMap[edge.node1.id], + node2: nodesIndicesMap[edge.node2.id], + weight: weight, + dataIndex: dataIndex + }); + }); + if (!layoutInstance) { + var isGPU = layoutModel.get('GPU'); + if (this._forceLayoutInstance) { + if ((isGPU && !(this._forceLayoutInstance instanceof __WEBPACK_IMPORTED_MODULE_6__ForceAtlas2GPU__["a" /* default */])) + || (!isGPU && !(this._forceLayoutInstance instanceof __WEBPACK_IMPORTED_MODULE_7__ForceAtlas2__["a" /* default */])) + ) { + // Mark to dispose + this._forceLayoutInstanceToDispose = this._forceLayoutInstance; + } + } + layoutInstance = this._forceLayoutInstance = isGPU + ? new __WEBPACK_IMPORTED_MODULE_6__ForceAtlas2GPU__["a" /* default */]() + : new __WEBPACK_IMPORTED_MODULE_7__ForceAtlas2__["a" /* default */](); + } + layoutInstance.initData(nodes, edges); + layoutInstance.updateOption(layoutModel.option); + + // Update lines geometry after first layout; + this._updateForceEdgesGeometry(layoutInstance.getEdges(), seriesModel); + this._updatePositionTexture(); + + api.dispatchAction({ + type: 'graphGLStartLayout', + from: this.uid + }); + } + else { + var layoutPoints = new Float32Array(nodeData.count() * 2); + var offset = 0; + graph.eachNode(function (node) { + var dataIndex = node.dataIndex; + var x; + var y; + if (nodeData.hasItemOption) { + var itemModel = nodeData.getItemModel(dataIndex); + x = itemModel.get('x'); + y = itemModel.get('y'); + } + layoutPoints[offset++] = x; + layoutPoints[offset++] = y; + }); + nodeData.setLayout('points', layoutPoints); + + this._updateAfterLayout(seriesModel, ecModel, api); + } + }, + + _updatePositionTexture: function () { + var positionTex = this._forceLayoutInstance.getNodePositionTexture(); + this._pointsBuilder.setPositionTexture(positionTex); + this._forceEdgesMesh.material.set('positionTex', positionTex); + }, + + startLayout: function (seriesModel, ecModel, api, payload) { + if (payload && payload.from != null && payload.from !== this.uid) { + return; + } + + var viewGL = this.viewGL; + var api = this._api; + var layoutInstance = this._forceLayoutInstance; + var data = this._model.getData(); + var layoutModel = this._model.getModel('forceAtlas2'); + + if (!layoutInstance) { + if (true) { + console.error('None layout don\'t have startLayout action'); + } + return; + } + + this.groupGL.remove(this._edgesMesh); + this.groupGL.add(this._forceEdgesMesh); + + if (!this._forceLayoutInstance) { + return; + } + + this._updateForceNodesGeometry(seriesModel.getData()); + this._pointsBuilder.hideLabels(); + + var self = this; + var layoutId = this._layoutId = globalLayoutId++; + var maxSteps = layoutModel.getShallow('maxSteps'); + var steps = layoutModel.getShallow('steps'); + var stepsCount = 0; + var syncStepCount = Math.max(steps * 2, 20); + var doLayout = function (layoutId) { + if (layoutId !== self._layoutId) { + return; + } + if (layoutInstance.isFinished(maxSteps)) { + api.dispatchAction({ + type: 'graphGLStopLayout', + from: self.uid + }); + api.dispatchAction({ + type: 'graphGLFinishLayout', + points: data.getLayout('points'), + from: self.uid + }); + return; + } + + layoutInstance.update(viewGL.layer.renderer, steps, function () { + self._updatePositionTexture(); + // PENDING Performance. + stepsCount += steps; + // Sync posiiton every 20 steps. + if (stepsCount >= syncStepCount) { + self._syncNodePosition(seriesModel); + stepsCount = 0; + } + // Position texture will been swapped. set every time. + api.getZr().refresh(); + + __WEBPACK_IMPORTED_MODULE_8_zrender_lib_animation_requestAnimationFrame___default()(function () { + doLayout(layoutId); + }); + }); + }; + + __WEBPACK_IMPORTED_MODULE_8_zrender_lib_animation_requestAnimationFrame___default()(function () { + if (self._forceLayoutInstanceToDispose) { + self._forceLayoutInstanceToDispose.dispose(viewGL.layer.renderer); + self._forceLayoutInstanceToDispose = null; + } + doLayout(layoutId); + }); + + this._layouting = true; + }, + + stopLayout: function (seriesModel, ecModel, api, payload) { + if (payload && payload.from != null && payload.from !== this.uid) { + return; + } + + this._layoutId = 0; + this.groupGL.remove(this._forceEdgesMesh); + this.groupGL.add(this._edgesMesh); + + if (!this._forceLayoutInstance) { + return; + } + + if (!this.viewGL.layer) { + return; + } + + if (!(payload && payload.beforeLayout)) { + this._syncNodePosition(seriesModel); + this._updateAfterLayout(seriesModel, ecModel, api); + } + + this._api.getZr().refresh(); + + this._layouting = false; + }, + + _syncNodePosition: function (seriesModel) { + var points = this._forceLayoutInstance.getNodePosition(this.viewGL.layer.renderer); + seriesModel.getData().setLayout('points', points); + + seriesModel.setNodePosition(points); + }, + + _updateAfterLayout: function (seriesModel, ecModel, api) { + this._updateMeshLinesGeometry(); + + this._pointsBuilder.removePositionTexture(); + + this._pointsBuilder.updateLayout(seriesModel, ecModel, api); + + this._pointsBuilder.updateView(this.viewGL.camera); + + this._pointsBuilder.updateLabels(); + + this._pointsBuilder.showLabels(); + + }, + + focusNodeAdjacency: function (seriesModel, ecModel, api, payload) { + + var data = this._model.getData(); + + this._downplayAll(); + + var dataIndex = payload.dataIndex; + + var graph = data.graph; + + var focusNodes = []; + var node = graph.getNodeByIndex(dataIndex); + focusNodes.push(node); + node.edges.forEach(function (edge) { + if (edge.dataIndex < 0) { + return; + } + edge.node1 !== node && focusNodes.push(edge.node1); + edge.node2 !== node && focusNodes.push(edge.node2); + }, this); + + this._pointsBuilder.fadeOutAll(0.05); + this._fadeOutEdgesAll(0.05); + + focusNodes.forEach(function (node) { + this._pointsBuilder.highlight(data, node.dataIndex); + }, this); + + this._pointsBuilder.updateLabels(focusNodes.map(function (node) { + return node.dataIndex; + })); + + var focusEdges = []; + node.edges.forEach(function (edge) { + if (edge.dataIndex >= 0) { + this._highlightEdge(edge.dataIndex); + focusEdges.push(edge); + } + }, this); + + this._focusNodes = focusNodes; + this._focusEdges = focusEdges; + }, + + unfocusNodeAdjacency: function (seriesModel, ecModel, api, payload) { + + this._downplayAll(); + + this._pointsBuilder.fadeInAll(); + this._fadeInEdgesAll(); + + this._pointsBuilder.updateLabels(); + }, + + _highlightEdge: function (dataIndex) { + var itemModel = this._model.getEdgeData().getItemModel(dataIndex); + var emphasisColor = __WEBPACK_IMPORTED_MODULE_2__util_graphicGL__["a" /* default */].parseColor(itemModel.get('emphasis.lineStyle.color') || itemModel.get('lineStyle.color')); + var emphasisOpacity = __WEBPACK_IMPORTED_MODULE_5__util_retrieve__["a" /* default */].firstNotNull(itemModel.get('emphasis.lineStyle.opacity'), itemModel.get('lineStyle.opacity'), 1); + emphasisColor[3] *= emphasisOpacity; + + this._edgesMesh.geometry.setItemColor(this._edgeIndicesMap[dataIndex], emphasisColor); + }, + + _downplayAll: function () { + if (this._focusNodes) { + this._focusNodes.forEach(function (node) { + this._pointsBuilder.downplay(this._model.getData(), node.dataIndex); + }, this); + } + if (this._focusEdges) { + this._focusEdges.forEach(function (edge) { + this._downplayEdge(edge.dataIndex); + }, this); + } + }, + + _downplayEdge: function (dataIndex) { + var color = this._getColor(dataIndex, []); + this._edgesMesh.geometry.setItemColor(this._edgeIndicesMap[dataIndex], color); + }, + + _setEdgeFade: (function () { + var color = []; + return function (dataIndex, percent) { + this._getColor(dataIndex, color); + color[3] *= percent; + this._edgesMesh.geometry.setItemColor(this._edgeIndicesMap[dataIndex], color); + }; + })(), + + _getColor: function (dataIndex, out) { + for (var i = 0; i < 4; i++) { + out[i] = this._originalEdgeColors[dataIndex * 4 + i]; + } + return out; + }, + + _fadeOutEdgesAll: function (percent) { + var graph = this._model.getData().graph; + + graph.eachEdge(function (edge) { + this._setEdgeFade(edge.dataIndex, percent); + }, this); + }, + + _fadeInEdgesAll: function () { + this._fadeOutEdgesAll(1); + }, + + _updateCamera: function (seriesModel, api) { + this.viewGL.setViewport(0, 0, api.getWidth(), api.getHeight(), api.getDevicePixelRatio()); + var camera = this.viewGL.camera; + var nodeData = seriesModel.getData(); + var points = nodeData.getLayout('points'); + var min = vec2.create(Infinity, Infinity); + var max = vec2.create(-Infinity, -Infinity); + var pt = []; + for (var i = 0; i < points.length;) { + pt[0] = points[i++]; + pt[1] = points[i++]; + vec2.min(min, min, pt); + vec2.max(max, max, pt); + } + var cy = (max[1] + min[1]) / 2; + var cx = (max[0] + min[0]) / 2; + // Only fit the camera when graph is not in the center. + // PENDING + if (cx > camera.left && cx < camera.right + && cy < camera.bottom && cy > camera.top + ) { + return; + } + + // Scale a bit + var width = Math.max(max[0] - min[0], 10); + // Keep aspect + var height = width / api.getWidth() * api.getHeight(); + width *= 1.4; + height *= 1.4; + min[0] -= width * 0.2; + + camera.left = min[0]; + camera.top = cy - height / 2; + camera.bottom = cy + height / 2; + camera.right = width + min[0]; + camera.near = 0; + camera.far = 100; + }, + + dispose: function () { + var renderer = this.viewGL.layer.renderer; + if (this._forceLayoutInstance) { + this._forceLayoutInstance.dispose(renderer); + } + this.groupGL.removeAll(); + + // Stop layout. + this._layoutId = -1; + }, + + remove: function () { + this.groupGL.removeAll(); + this._control.dispose(); + } +}); + +/***/ }), +/* 269 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__ = __webpack_require__(1); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2_claygl_src_compositor_Pass__ = __webpack_require__(16); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3_claygl_src_FrameBuffer__ = __webpack_require__(10); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4__forceAtlas2_glsl_js__ = __webpack_require__(270); + + + + + + +__WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].Shader.import(__WEBPACK_IMPORTED_MODULE_4__forceAtlas2_glsl_js__["a" /* default */]); + +var defaultConfigs = { + repulsionByDegree: true, + linLogMode: false, + + strongGravityMode: false, + gravity: 1.0, + + scaling: 1.0, + + edgeWeightInfluence: 1.0, + + jitterTolerence: 0.1, + + preventOverlap: false, + + dissuadeHubs: false, + + gravityCenter: null +}; + +function ForceAtlas2GPU(options) { + + var textureOpt = { + type: __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].Texture.FLOAT, + minFilter: __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].Texture.NEAREST, + magFilter: __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].Texture.NEAREST + }; + + this._positionSourceTex = new __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].Texture2D(textureOpt); + this._positionSourceTex.flipY = false; + + this._positionTex = new __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].Texture2D(textureOpt); + this._positionPrevTex = new __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].Texture2D(textureOpt); + this._forceTex = new __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].Texture2D(textureOpt); + this._forcePrevTex = new __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].Texture2D(textureOpt); + + this._weightedSumTex = new __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].Texture2D(textureOpt); + this._weightedSumTex.width = this._weightedSumTex.height = 1; + + this._globalSpeedTex = new __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].Texture2D(textureOpt); + this._globalSpeedPrevTex = new __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].Texture2D(textureOpt); + this._globalSpeedTex.width = this._globalSpeedTex.height = 1; + this._globalSpeedPrevTex.width = this._globalSpeedPrevTex.height = 1; + + this._nodeRepulsionPass = new __WEBPACK_IMPORTED_MODULE_2_claygl_src_compositor_Pass__["a" /* default */]({ + fragment: __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].Shader.source('ecgl.forceAtlas2.updateNodeRepulsion') + }); + this._positionPass = new __WEBPACK_IMPORTED_MODULE_2_claygl_src_compositor_Pass__["a" /* default */]({ + fragment: __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].Shader.source('ecgl.forceAtlas2.updatePosition') + }); + this._globalSpeedPass = new __WEBPACK_IMPORTED_MODULE_2_claygl_src_compositor_Pass__["a" /* default */]({ + fragment: __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].Shader.source('ecgl.forceAtlas2.calcGlobalSpeed') + }); + this._copyPass = new __WEBPACK_IMPORTED_MODULE_2_claygl_src_compositor_Pass__["a" /* default */]({ + fragment: __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].Shader.source('clay.compositor.output') + }); + + var additiveBlend = function (gl) { + gl.blendEquation(gl.FUNC_ADD); + gl.blendFunc(gl.ONE, gl.ONE); + }; + this._edgeForceMesh = new __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].Mesh({ + geometry: new __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].Geometry({ + attributes: { + node1: new __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].Geometry.Attribute('node1', 'float', 2), + node2: new __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].Geometry.Attribute('node2', 'float', 2), + weight: new __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].Geometry.Attribute('weight', 'float', 1) + }, + dynamic: true, + mainAttribute: 'node1' + }), + material: new __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].Material({ + transparent: true, + shader: __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].createShader('ecgl.forceAtlas2.updateEdgeAttraction'), + blend: additiveBlend, + depthMask: false, + depthText: false + }), + mode: __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].Mesh.POINTS + }); + this._weightedSumMesh = new __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].Mesh({ + geometry: new __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].Geometry({ + attributes: { + node: new __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].Geometry.Attribute('node', 'float', 2) + }, + dynamic: true, + mainAttribute: 'node' + }), + material: new __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].Material({ + transparent: true, + shader: __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].createShader('ecgl.forceAtlas2.calcWeightedSum'), + blend: additiveBlend, + depthMask: false, + depthText: false + }), + mode: __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].Mesh.POINTS + }); + + this._framebuffer = new __WEBPACK_IMPORTED_MODULE_3_claygl_src_FrameBuffer__["a" /* default */]({ + depthBuffer: false + }); + + this._dummyCamera = new __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].OrthographicCamera({ + left: -1, right: 1, + top: 1, bottom: -1, + near: 0, far: 100 + }); + + this._globalSpeed = 0; +} + +ForceAtlas2GPU.prototype.updateOption = function (options) { + + // Default config + for (var name in defaultConfigs) { + this[name] = defaultConfigs[name]; + } + + // Config according to data scale + var nNodes = this._nodes.length; + if (nNodes > 50000) { + this.jitterTolerence = 10; + } + else if (nNodes > 5000) { + this.jitterTolerence = 1; + } + else { + this.jitterTolerence = 0.1; + } + + if (nNodes > 100) { + this.scaling = 2.0; + } + else { + this.scaling = 10.0; + } + + // this.edgeWeightInfluence = 1; + // this.gravity = 1; + // this.strongGravityMode = false; + if (options) { + for (var name in defaultConfigs) { + if (options[name] != null) { + this[name] = options[name]; + } + } + } + + if (this.repulsionByDegree) { + var positionBuffer = this._positionSourceTex.pixels; + + for (var i = 0; i < this._nodes.length; i++) { + positionBuffer[i * 4 + 2] = (this._nodes[i].degree || 0) + 1; + } + } +}; + +ForceAtlas2GPU.prototype._updateGravityCenter = function (options) { + var nodes = this._nodes; + var edges = this._edges; + + if (!this.gravityCenter) { + var min = [Infinity, Infinity]; + var max = [-Infinity, -Infinity]; + for (var i = 0; i < nodes.length; i++) { + min[0] = Math.min(nodes[i].x, min[0]); + min[1] = Math.min(nodes[i].y, min[1]); + max[0] = Math.max(nodes[i].x, max[0]); + max[1] = Math.max(nodes[i].y, max[1]); + } + + this._gravityCenter = [(min[0] + max[0]) * 0.5, (min[1] + max[1]) * 0.5]; + } + else { + this._gravityCenter = this.gravityCenter; + } + // Update inDegree, outDegree + for (var i = 0; i < edges.length; i++) { + var node1 = edges[i].node1; + var node2 = edges[i].node2; + + nodes[node1].degree = (nodes[node1].degree || 0) + 1; + nodes[node2].degree = (nodes[node2].degree || 0) + 1; + } +}; +/** + * @param {Array.} [{ x, y, mass }] nodes + * @param {Array.} [{ node1, node2, weight }] edges + */ +ForceAtlas2GPU.prototype.initData = function (nodes, edges) { + + this._nodes = nodes; + this._edges = edges; + + this._updateGravityCenter(); + + var textureWidth = Math.ceil(Math.sqrt(nodes.length)); + var textureHeight = textureWidth; + var positionBuffer = new Float32Array(textureWidth * textureHeight * 4); + + this._resize(textureWidth, textureHeight); + + var offset = 0; + for (var i = 0; i < nodes.length; i++) { + var node = nodes[i]; + positionBuffer[offset++] = node.x || 0; + positionBuffer[offset++] = node.y || 0; + positionBuffer[offset++] = node.mass || 1; + positionBuffer[offset++] = node.size || 1; + } + this._positionSourceTex.pixels = positionBuffer; + + var edgeGeometry = this._edgeForceMesh.geometry; + var edgeLen = edges.length; + edgeGeometry.attributes.node1.init(edgeLen * 2); + edgeGeometry.attributes.node2.init(edgeLen * 2); + edgeGeometry.attributes.weight.init(edgeLen * 2); + + var uv = []; + + for (var i = 0; i < edges.length; i++) { + var attributes = edgeGeometry.attributes; + var weight = edges[i].weight; + if (weight == null) { + weight = 1; + } + // Two way. + attributes.node1.set(i, this.getNodeUV(edges[i].node1, uv)); + attributes.node2.set(i, this.getNodeUV(edges[i].node2, uv)); + attributes.weight.set(i, weight); + + attributes.node1.set(i + edgeLen, this.getNodeUV(edges[i].node2, uv)); + attributes.node2.set(i + edgeLen, this.getNodeUV(edges[i].node1, uv)); + attributes.weight.set(i + edgeLen, weight); + } + + var weigtedSumGeo = this._weightedSumMesh.geometry; + weigtedSumGeo.attributes.node.init(nodes.length); + for (var i = 0; i < nodes.length; i++) { + weigtedSumGeo.attributes.node.set(i, this.getNodeUV(i, uv)); + } + + edgeGeometry.dirty(); + weigtedSumGeo.dirty(); + + this._nodeRepulsionPass.material.define('fragment', 'NODE_COUNT', nodes.length); + this._nodeRepulsionPass.material.setUniform('textureSize', [textureWidth, textureHeight]); + + this._inited = false; + + this._frame = 0; +}; + +ForceAtlas2GPU.prototype.getNodes = function () { + return this._nodes; +}; +ForceAtlas2GPU.prototype.getEdges = function () { + return this._edges; +}; + +ForceAtlas2GPU.prototype.step = function (renderer) { + if (!this._inited) { + this._initFromSource(renderer); + this._inited = true; + } + + this._frame++; + + this._framebuffer.attach(this._forceTex); + this._framebuffer.bind(renderer); + var nodeRepulsionPass = this._nodeRepulsionPass; + // Calc node repulsion, gravity + nodeRepulsionPass.setUniform('strongGravityMode', this.strongGravityMode); + nodeRepulsionPass.setUniform('gravity', this.gravity); + nodeRepulsionPass.setUniform('gravityCenter', this._gravityCenter); + nodeRepulsionPass.setUniform('scaling', this.scaling); + nodeRepulsionPass.setUniform('preventOverlap', this.preventOverlap); + nodeRepulsionPass.setUniform('positionTex', this._positionPrevTex); + nodeRepulsionPass.render(renderer); + + // Calc edge attraction force + var edgeForceMesh = this._edgeForceMesh; + edgeForceMesh.material.set('linLogMode', this.linLogMode); + edgeForceMesh.material.set('edgeWeightInfluence', this.edgeWeightInfluence); + edgeForceMesh.material.set('preventOverlap', this.preventOverlap); + edgeForceMesh.material.set('positionTex', this._positionPrevTex); + renderer.gl.enable(renderer.gl.BLEND); + renderer.renderPass([edgeForceMesh], this._dummyCamera); + + // Calc weighted sum. + this._framebuffer.attach(this._weightedSumTex); + renderer.gl.clearColor(0, 0, 0, 0); + renderer.gl.clear(renderer.gl.COLOR_BUFFER_BIT); + renderer.gl.enable(renderer.gl.BLEND); + var weightedSumMesh = this._weightedSumMesh; + weightedSumMesh.material.set('positionTex', this._positionPrevTex); + weightedSumMesh.material.set('forceTex', this._forceTex); + weightedSumMesh.material.set('forcePrevTex', this._forcePrevTex); + renderer.renderPass([weightedSumMesh], this._dummyCamera); + + // Calc global speed. + this._framebuffer.attach(this._globalSpeedTex); + var globalSpeedPass = this._globalSpeedPass; + globalSpeedPass.setUniform('globalSpeedPrevTex', this._globalSpeedPrevTex); + globalSpeedPass.setUniform('weightedSumTex', this._weightedSumTex); + globalSpeedPass.setUniform('jitterTolerence', this.jitterTolerence); + renderer.gl.disable(renderer.gl.BLEND); + globalSpeedPass.render(renderer); + + // Update position. + var positionPass = this._positionPass; + this._framebuffer.attach(this._positionTex); + positionPass.setUniform('globalSpeedTex', this._globalSpeedTex); + positionPass.setUniform('positionTex', this._positionPrevTex); + positionPass.setUniform('forceTex', this._forceTex); + positionPass.setUniform('forcePrevTex', this._forcePrevTex); + positionPass.render(renderer); + + this._framebuffer.unbind(renderer); + + this._swapTexture(); +}; + +ForceAtlas2GPU.prototype.update = function (renderer, steps, cb) { + if (steps == null) { + steps = 1; + } + steps = Math.max(steps, 1); + + for (var i = 0; i < steps; i++) { + this.step(renderer); + } + + cb && cb(); +}; + +ForceAtlas2GPU.prototype.getNodePositionTexture = function () { + return this._inited + // Texture already been swapped. + ? this._positionPrevTex + : this._positionSourceTex; +}; + +ForceAtlas2GPU.prototype.getNodeUV = function (nodeIndex, uv) { + uv = uv || []; + var textureWidth = this._positionTex.width; + var textureHeight = this._positionTex.height; + uv[0] = (nodeIndex % textureWidth) / (textureWidth - 1); + uv[1] = Math.floor(nodeIndex / textureWidth) / (textureHeight - 1) || 0; + return uv; +}; + +ForceAtlas2GPU.prototype.getNodePosition = function (renderer, out) { + var positionArr = this._positionArr; + var width = this._positionTex.width; + var height = this._positionTex.height; + var size = width * height; + if (!positionArr || positionArr.length !== size * 4) { + positionArr = this._positionArr = new Float32Array(size * 4); + } + this._framebuffer.bind(renderer); + this._framebuffer.attach(this._positionPrevTex); + renderer.gl.readPixels( + 0, 0, width, height, + renderer.gl.RGBA, renderer.gl.FLOAT, + positionArr + ); + this._framebuffer.unbind(renderer); + if (!out) { + out = new Float32Array(this._nodes.length * 2); + } + for (var i = 0; i < this._nodes.length; i++) { + out[i * 2] = positionArr[i * 4]; + out[i * 2 + 1] = positionArr[i * 4 + 1]; + } + return out; +}; + +ForceAtlas2GPU.prototype.getTextureData = function (renderer, textureName) { + var tex = this['_' + textureName + 'Tex']; + var width = tex.width; + var height = tex.height; + this._framebuffer.bind(renderer); + this._framebuffer.attach(tex); + var arr = new Float32Array(width * height * 4); + renderer.gl.readPixels(0, 0, width, height, renderer.gl.RGBA, renderer.gl.FLOAT, arr); + this._framebuffer.unbind(renderer); + return arr; +}; + +ForceAtlas2GPU.prototype.getTextureSize = function () { + return { + width: this._positionTex.width, + height: this._positionTex.height + }; +}; + +ForceAtlas2GPU.prototype.isFinished = function (maxSteps) { + return this._frame > maxSteps; +}; + +ForceAtlas2GPU.prototype._swapTexture = function () { + var tmp = this._positionPrevTex; + this._positionPrevTex = this._positionTex; + this._positionTex = tmp; + + var tmp = this._forcePrevTex; + this._forcePrevTex = this._forceTex; + this._forceTex = tmp; + + var tmp = this._globalSpeedPrevTex; + this._globalSpeedPrevTex = this._globalSpeedTex; + this._globalSpeedTex = tmp; +}; + +ForceAtlas2GPU.prototype._initFromSource = function (renderer) { + this._framebuffer.attach(this._positionPrevTex); + this._framebuffer.bind(renderer); + this._copyPass.setUniform('texture', this._positionSourceTex); + this._copyPass.render(renderer); + + renderer.gl.clearColor(0, 0, 0, 0); + this._framebuffer.attach(this._forcePrevTex); + renderer.gl.clear(renderer.gl.COLOR_BUFFER_BIT); + this._framebuffer.attach(this._globalSpeedPrevTex); + renderer.gl.clear(renderer.gl.COLOR_BUFFER_BIT); + + this._framebuffer.unbind(renderer); +}; + +ForceAtlas2GPU.prototype._resize = function (width, height) { + ['_positionSourceTex', '_positionTex', '_positionPrevTex', '_forceTex', '_forcePrevTex'].forEach(function (texName) { + this[texName].width = width; + this[texName].height = height; + this[texName].dirty(); + }, this); +}; + +ForceAtlas2GPU.prototype.dispose = function (renderer) { + this._framebuffer.dispose(renderer); + + this._copyPass.dispose(renderer); + this._nodeRepulsionPass.dispose(renderer); + this._positionPass.dispose(renderer); + this._globalSpeedPass.dispose(renderer); + + this._edgeForceMesh.geometry.dispose(renderer); + this._weightedSumMesh.geometry.dispose(renderer); + + this._positionSourceTex.dispose(renderer); + this._positionTex.dispose(renderer); + this._positionPrevTex.dispose(renderer); + this._forceTex.dispose(renderer); + this._forcePrevTex.dispose(renderer); + this._weightedSumTex.dispose(renderer); + this._globalSpeedTex.dispose(renderer); + this._globalSpeedPrevTex.dispose(renderer); +}; + +__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.ForceAtlas2GPU = ForceAtlas2GPU; + +/* harmony default export */ __webpack_exports__["a"] = (ForceAtlas2GPU); + +/***/ }), +/* 270 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony default export */ __webpack_exports__["a"] = ("@export ecgl.forceAtlas2.updateNodeRepulsion\n\n#define NODE_COUNT 0\n\nuniform sampler2D positionTex;\n\nuniform vec2 textureSize;\nuniform float gravity;\nuniform float scaling;\nuniform vec2 gravityCenter;\n\nuniform bool strongGravityMode;\nuniform bool preventOverlap;\n\nvarying vec2 v_Texcoord;\n\nvoid main() {\n\n vec4 n0 = texture2D(positionTex, v_Texcoord);\n\n vec2 force = vec2(0.0);\n for (int i = 0; i < NODE_COUNT; i++) {\n vec2 uv = vec2(\n mod(float(i), textureSize.x) / (textureSize.x - 1.0),\n floor(float(i) / textureSize.x) / (textureSize.y - 1.0)\n );\n vec4 n1 = texture2D(positionTex, uv);\n\n vec2 dir = n0.xy - n1.xy;\n float d2 = dot(dir, dir);\n\n if (d2 > 0.0) {\n float factor = 0.0;\n if (preventOverlap) {\n float d = sqrt(d2);\n d = d - n0.w - n1.w;\n if (d > 0.0) {\n factor = scaling * n0.z * n1.z / (d * d);\n }\n else if (d < 0.0) {\n factor = scaling * 100.0 * n0.z * n1.z;\n }\n }\n else {\n factor = scaling * n0.z * n1.z / d2;\n }\n force += dir * factor;\n }\n }\n\n vec2 dir = gravityCenter - n0.xy;\n float d = 1.0;\n if (!strongGravityMode) {\n d = length(dir);\n }\n\n force += dir * n0.z * gravity / (d + 1.0);\n\n gl_FragColor = vec4(force, 0.0, 1.0);\n}\n@end\n\n@export ecgl.forceAtlas2.updateEdgeAttraction.vertex\n\nattribute vec2 node1;\nattribute vec2 node2;\nattribute float weight;\n\nuniform sampler2D positionTex;\nuniform float edgeWeightInfluence;\nuniform bool preventOverlap;\nuniform bool linLogMode;\n\nuniform vec2 windowSize: WINDOW_SIZE;\n\nvarying vec2 v_Force;\n\nvoid main() {\n\n vec4 n0 = texture2D(positionTex, node1);\n vec4 n1 = texture2D(positionTex, node2);\n\n vec2 dir = n1.xy - n0.xy;\n float d = length(dir);\n float w;\n if (edgeWeightInfluence == 0.0) {\n w = 1.0;\n }\n else if (edgeWeightInfluence == 1.0) {\n w = weight;\n }\n else {\n w = pow(weight, edgeWeightInfluence);\n }\n vec2 offset = vec2(1.0 / windowSize.x, 1.0 / windowSize.y);\n vec2 scale = vec2((windowSize.x - 1.0) / windowSize.x, (windowSize.y - 1.0) / windowSize.y);\n vec2 pos = node1 * scale * 2.0 - 1.0;\n gl_Position = vec4(pos + offset, 0.0, 1.0);\n gl_PointSize = 1.0;\n\n float factor;\n if (preventOverlap) {\n d = d - n1.w - n0.w;\n }\n if (d <= 0.0) {\n v_Force = vec2(0.0);\n return;\n }\n\n if (linLogMode) {\n factor = w * log(d) / d;\n }\n else {\n factor = w;\n }\n v_Force = dir * factor;\n}\n@end\n\n@export ecgl.forceAtlas2.updateEdgeAttraction.fragment\n\nvarying vec2 v_Force;\n\nvoid main() {\n gl_FragColor = vec4(v_Force, 0.0, 0.0);\n}\n@end\n\n@export ecgl.forceAtlas2.calcWeightedSum.vertex\n\nattribute vec2 node;\n\nvarying vec2 v_NodeUv;\n\nvoid main() {\n\n v_NodeUv = node;\n gl_Position = vec4(0.0, 0.0, 0.0, 1.0);\n gl_PointSize = 1.0;\n}\n@end\n\n@export ecgl.forceAtlas2.calcWeightedSum.fragment\n\nvarying vec2 v_NodeUv;\n\nuniform sampler2D positionTex;\nuniform sampler2D forceTex;\nuniform sampler2D forcePrevTex;\n\nvoid main() {\n vec2 force = texture2D(forceTex, v_NodeUv).rg;\n vec2 forcePrev = texture2D(forcePrevTex, v_NodeUv).rg;\n\n float mass = texture2D(positionTex, v_NodeUv).z;\n float swing = length(force - forcePrev) * mass;\n float traction = length(force + forcePrev) * 0.5 * mass;\n\n gl_FragColor = vec4(swing, traction, 0.0, 0.0);\n}\n@end\n\n@export ecgl.forceAtlas2.calcGlobalSpeed\n\nuniform sampler2D globalSpeedPrevTex;\nuniform sampler2D weightedSumTex;\nuniform float jitterTolerence;\n\nvoid main() {\n vec2 weightedSum = texture2D(weightedSumTex, vec2(0.5)).xy;\n float prevGlobalSpeed = texture2D(globalSpeedPrevTex, vec2(0.5)).x;\n float globalSpeed = jitterTolerence * jitterTolerence\n * weightedSum.y / weightedSum.x;\n if (prevGlobalSpeed > 0.0) {\n globalSpeed = min(globalSpeed / prevGlobalSpeed, 1.5) * prevGlobalSpeed;\n }\n gl_FragColor = vec4(globalSpeed, 0.0, 0.0, 1.0);\n}\n@end\n\n@export ecgl.forceAtlas2.updatePosition\n\nuniform sampler2D forceTex;\nuniform sampler2D forcePrevTex;\nuniform sampler2D positionTex;\nuniform sampler2D globalSpeedTex;\n\nvarying vec2 v_Texcoord;\n\nvoid main() {\n vec2 force = texture2D(forceTex, v_Texcoord).xy;\n vec2 forcePrev = texture2D(forcePrevTex, v_Texcoord).xy;\n vec4 node = texture2D(positionTex, v_Texcoord);\n\n float globalSpeed = texture2D(globalSpeedTex, vec2(0.5)).r;\n float swing = length(force - forcePrev);\n float speed = 0.1 * globalSpeed / (0.1 + globalSpeed * sqrt(swing));\n\n float df = length(force);\n if (df > 0.0) {\n speed = min(df * speed, 10.0) / df;\n\n gl_FragColor = vec4(node.xy + speed * force, node.zw);\n }\n else {\n gl_FragColor = node;\n }\n}\n@end\n\n@export ecgl.forceAtlas2.edges.vertex\nuniform mat4 worldViewProjection : WORLDVIEWPROJECTION;\n\nattribute vec2 node;\nattribute vec4 a_Color : COLOR;\nvarying vec4 v_Color;\n\nuniform sampler2D positionTex;\n\nvoid main()\n{\n gl_Position = worldViewProjection * vec4(\n texture2D(positionTex, node).xy, -10.0, 1.0\n );\n v_Color = a_Color;\n}\n@end\n\n@export ecgl.forceAtlas2.edges.fragment\nuniform vec4 color : [1.0, 1.0, 1.0, 1.0];\nvarying vec4 v_Color;\nvoid main() {\n gl_FragColor = color * v_Color;\n}\n@end"); + + +/***/ }), +/* 271 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_claygl_src_Texture2D__ = __webpack_require__(5); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_claygl_src_Texture__ = __webpack_require__(4); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__forceAtlas2Worker_js__ = __webpack_require__(272); + + + +var workerUrl = __WEBPACK_IMPORTED_MODULE_2__forceAtlas2Worker_js__["a" /* default */].toString(); +workerUrl = workerUrl.slice(workerUrl.indexOf('{') + 1, workerUrl.lastIndexOf('}')); + +var defaultConfigs = { + + barnesHutOptimize: true, + barnesHutTheta: 1.5, + + repulsionByDegree: true, + linLogMode: false, + + strongGravityMode: false, + gravity: 1.0, + + scaling: 1.0, + + edgeWeightInfluence: 1.0, + + jitterTolerence: 0.1, + + preventOverlap: false, + + dissuadeHubs: false, + + gravityCenter: null +}; + +var ForceAtlas2 = function (options) { + + for (var name in defaultConfigs) { + this[name] = defaultConfigs[name]; + } + + if (options) { + for (var name in options) { + this[name] = options[name]; + } + } + + this._nodes = []; + this._edges = []; + + this._disposed = false; + + this._positionTex = new __WEBPACK_IMPORTED_MODULE_0_claygl_src_Texture2D__["a" /* default */]({ + type: __WEBPACK_IMPORTED_MODULE_1_claygl_src_Texture__["a" /* default */].FLOAT, + flipY: false, + minFilter: __WEBPACK_IMPORTED_MODULE_1_claygl_src_Texture__["a" /* default */].NEAREST, + magFilter: __WEBPACK_IMPORTED_MODULE_1_claygl_src_Texture__["a" /* default */].NEAREST + }); +}; + +ForceAtlas2.prototype.initData = function (nodes, edges) { + + var bb = new Blob([workerUrl]); + var blobURL = window.URL.createObjectURL(bb); + + this._worker = new Worker(blobURL); + + this._worker.onmessage = this._$onupdate.bind(this); + + this._nodes = nodes; + this._edges = edges; + this._frame = 0; + + var nNodes = nodes.length; + var nEdges = edges.length; + + var positionArr = new Float32Array(nNodes * 2); + var massArr = new Float32Array(nNodes); + var sizeArr = new Float32Array(nNodes); + + var edgeArr = new Float32Array(nEdges * 2); + var edgeWeightArr = new Float32Array(nEdges); + + for (var i = 0; i < nodes.length; i++) { + var node = nodes[i]; + + positionArr[i * 2] = node.x; + positionArr[i * 2 + 1] = node.y; + + massArr[i] = node.mass == null ? 1 : node.mass; + sizeArr[i] = node.size == null ? 1 : node.size; + } + + for (var i = 0; i < edges.length; i++) { + var edge = edges[i]; + + var source = edge.node1; + var target = edge.node2; + + edgeArr[i * 2] = source; + edgeArr[i * 2 + 1] = target; + + edgeWeightArr[i] = edge.weight == null ? 1 : edge.weight; + } + + + var textureWidth = Math.ceil(Math.sqrt(nodes.length)); + var textureHeight = textureWidth; + var pixels = new Float32Array(textureWidth * textureHeight * 4); + var positionTex = this._positionTex; + positionTex.width = textureWidth; + positionTex.height = textureHeight; + positionTex.pixels = pixels; + + this._worker.postMessage({ + cmd: 'init', + nodesPosition: positionArr, + nodesMass: massArr, + nodesSize: sizeArr, + edges: edgeArr, + edgesWeight: edgeWeightArr + }); + + this._globalSpeed = Infinity; +}; + +ForceAtlas2.prototype.updateOption = function (options) { + var config = {}; + // Default config + for (var name in defaultConfigs) { + config[name] = defaultConfigs[name]; + } + + var nodes = this._nodes; + var edges = this._edges; + + // Config according to data scale + var nNodes = nodes.length; + if (nNodes > 50000) { + config.jitterTolerence = 10; + } + else if (nNodes > 5000) { + config.jitterTolerence = 1; + } + else { + config.jitterTolerence = 0.1; + } + + if (nNodes > 100) { + config.scaling = 2.0; + } + else { + config.scaling = 10.0; + } + if (nNodes > 1000) { + config.barnesHutOptimize = true; + } + else { + config.barnesHutOptimize = false; + } + + if (options) { + for (var name in defaultConfigs) { + if (options[name] != null) { + config[name] = options[name]; + } + } + } + + if (!config.gravityCenter) { + var min = [Infinity, Infinity]; + var max = [-Infinity, -Infinity]; + for (var i = 0; i < nodes.length; i++) { + min[0] = Math.min(nodes[i].x, min[0]); + min[1] = Math.min(nodes[i].y, min[1]); + max[0] = Math.max(nodes[i].x, max[0]); + max[1] = Math.max(nodes[i].y, max[1]); + } + + config.gravityCenter = [(min[0] + max[0]) * 0.5, (min[1] + max[1]) * 0.5]; + } + + // Update inDegree, outDegree + for (var i = 0; i < edges.length; i++) { + var node1 = edges[i].node1; + var node2 = edges[i].node2; + + nodes[node1].degree = (nodes[node1].degree || 0) + 1; + nodes[node2].degree = (nodes[node2].degree || 0) + 1; + } + + if (this._worker) { + this._worker.postMessage({ + cmd: 'updateConfig', + config: config + }); + } +}; + +// Steps per call, to keep sync with rendering +ForceAtlas2.prototype.update = function (renderer, steps, cb) { + if (steps == null) { + steps = 1; + } + steps = Math.max(steps, 1); + + this._frame += steps; + this._onupdate = cb; + + if (this._worker) { + this._worker.postMessage({ + cmd: 'update', + steps: Math.round(steps) + }); + } +}; + +ForceAtlas2.prototype._$onupdate = function (e) { + // Incase the worker keep postMessage of last frame after it is disposed + if (this._disposed) { + return; + } + + var positionArr = new Float32Array(e.data.buffer); + this._globalSpeed = e.data.globalSpeed; + + this._positionArr = positionArr; + + this._updateTexture(positionArr); + + this._onupdate && this._onupdate(); +}; + +ForceAtlas2.prototype.getNodePositionTexture = function () { + return this._positionTex; +}; + +ForceAtlas2.prototype.getNodeUV = function (nodeIndex, uv) { + uv = uv || []; + var textureWidth = this._positionTex.width; + var textureHeight = this._positionTex.height; + uv[0] = (nodeIndex % textureWidth) / (textureWidth - 1); + uv[1] = Math.floor(nodeIndex / textureWidth) / (textureHeight - 1); + return uv; +}; + +ForceAtlas2.prototype.getNodes = function () { + return this._nodes; +}; +ForceAtlas2.prototype.getEdges = function () { + return this._edges; +}; +ForceAtlas2.prototype.isFinished = function (maxSteps) { + return this._frame > maxSteps; +}; + +ForceAtlas2.prototype.getNodePosition = function (renderer, out) { + if (!out) { + out = new Float32Array(this._nodes.length * 2); + } + if (this._positionArr) { + for (var i = 0; i < this._positionArr.length; i++) { + out[i] = this._positionArr[i]; + } + } + return out; +}; + +ForceAtlas2.prototype._updateTexture = function (positionArr) { + var pixels = this._positionTex.pixels; + var offset = 0; + for (var i = 0; i < positionArr.length;){ + pixels[offset++] = positionArr[i++]; + pixels[offset++] = positionArr[i++]; + pixels[offset++] = 1; + pixels[offset++] = 1; + } + this._positionTex.dirty(); +}; + +ForceAtlas2.prototype.dispose = function (renderer) { + this._disposed = true; + this._worker = null; +}; + +/* harmony default export */ __webpack_exports__["a"] = (ForceAtlas2); + +/***/ }), +/* 272 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/**************************** + * Vector2 math functions + ***************************/ + +function forceAtlas2Worker() { + var vec2 = { + create: function() { + return new Float32Array(2); + }, + dist: function(a, b) { + var x = b[0] - a[0]; + var y = b[1] - a[1]; + return Math.sqrt(x*x + y*y); + }, + len: function(a) { + var x = a[0]; + var y = a[1]; + return Math.sqrt(x*x + y*y); + }, + scaleAndAdd: function(out, a, b, scale) { + out[0] = a[0] + b[0] * scale; + out[1] = a[1] + b[1] * scale; + return out; + }, + scale: function(out, a, b) { + out[0] = a[0] * b; + out[1] = a[1] * b; + return out; + }, + add: function(out, a, b) { + out[0] = a[0] + b[0]; + out[1] = a[1] + b[1]; + return out; + }, + sub: function(out, a, b) { + out[0] = a[0] - b[0]; + out[1] = a[1] - b[1]; + return out; + }, + normalize: function(out, a) { + var x = a[0]; + var y = a[1]; + var len = x*x + y*y; + if (len > 0) { + //TODO: evaluate use of glm_invsqrt here? + len = 1 / Math.sqrt(len); + out[0] = a[0] * len; + out[1] = a[1] * len; + } + return out; + }, + negate: function(out, a) { + out[0] = -a[0]; + out[1] = -a[1]; + return out; + }, + copy: function(out, a) { + out[0] = a[0]; + out[1] = a[1]; + return out; + }, + set: function(out, x, y) { + out[0] = x; + out[1] = y; + return out; + } + } + + /**************************** + * Class: Region + ***************************/ + + function Region() { + + this.subRegions = []; + + this.nSubRegions = 0; + + this.node = null; + + this.mass = 0; + + this.centerOfMass = null; + + this.bbox = new Float32Array(4); + + this.size = 0; + } + + var regionProto = Region.prototype; + + // Reset before update + regionProto.beforeUpdate = function() { + for (var i = 0; i < this.nSubRegions; i++) { + this.subRegions[i].beforeUpdate(); + } + this.mass = 0; + if (this.centerOfMass) { + this.centerOfMass[0] = 0; + this.centerOfMass[1] = 0; + } + this.nSubRegions = 0; + this.node = null; + }; + // Clear after update + regionProto.afterUpdate = function() { + this.subRegions.length = this.nSubRegions; + for (var i = 0; i < this.nSubRegions; i++) { + this.subRegions[i].afterUpdate(); + } + }; + + regionProto.addNode = function(node) { + if (this.nSubRegions === 0) { + if (this.node == null) { + this.node = node; + return; + } + // Already have node, subdivide self. + else { + this._addNodeToSubRegion(this.node); + this.node = null; + } + } + this._addNodeToSubRegion(node); + + this._updateCenterOfMass(node); + }; + + regionProto.findSubRegion = function(x, y) { + for (var i = 0; i < this.nSubRegions; i++) { + var region = this.subRegions[i]; + if (region.contain(x, y)) { + return region; + } + } + }; + + regionProto.contain = function(x, y) { + return this.bbox[0] <= x + && this.bbox[2] >= x + && this.bbox[1] <= y + && this.bbox[3] >= y; + }; + + regionProto.setBBox = function(minX, minY, maxX, maxY) { + // Min + this.bbox[0] = minX; + this.bbox[1] = minY; + // Max + this.bbox[2] = maxX; + this.bbox[3] = maxY; + + this.size = (maxX - minX + maxY - minY) / 2; + }; + + regionProto._newSubRegion = function() { + var subRegion = this.subRegions[this.nSubRegions]; + if (!subRegion) { + subRegion = new Region(); + this.subRegions[this.nSubRegions] = subRegion; + } + this.nSubRegions++; + return subRegion; + }; + + regionProto._addNodeToSubRegion = function(node) { + var subRegion = this.findSubRegion(node.position[0], node.position[1]); + var bbox = this.bbox; + if (!subRegion) { + var cx = (bbox[0] + bbox[2]) / 2; + var cy = (bbox[1] + bbox[3]) / 2; + var w = (bbox[2] - bbox[0]) / 2; + var h = (bbox[3] - bbox[1]) / 2; + + var xi = node.position[0] >= cx ? 1 : 0; + var yi = node.position[1] >= cy ? 1 : 0; + + var subRegion = this._newSubRegion(); + // Min + subRegion.setBBox( + // Min + xi * w + bbox[0], + yi * h + bbox[1], + // Max + (xi + 1) * w + bbox[0], + (yi + 1) * h + bbox[1] + ); + } + + subRegion.addNode(node); + }; + + regionProto._updateCenterOfMass = function(node) { + // Incrementally update + if (this.centerOfMass == null) { + this.centerOfMass = new Float32Array(2); + } + var x = this.centerOfMass[0] * this.mass; + var y = this.centerOfMass[1] * this.mass; + x += node.position[0] * node.mass; + y += node.position[1] * node.mass; + this.mass += node.mass; + this.centerOfMass[0] = x / this.mass; + this.centerOfMass[1] = y / this.mass; + }; + + /**************************** + * Class: Graph Node + ***************************/ + function GraphNode() { + this.position = new Float32Array(2); + + this.force = vec2.create(); + this.forcePrev = vec2.create(); + + // If repulsionByDegree is true + // mass = inDegree + outDegree + 1 + // Else + // mass is manually set + this.mass = 1; + + this.inDegree = 0; + this.outDegree = 0; + + // Optional + // this.size = 1; + } + + /**************************** + * Class: Graph Edge + ***************************/ + function GraphEdge(source, target) { + this.source = source; + this.target = target; + + this.weight = 1; + } + + /**************************** + * Class: ForceStlas2 + ***************************/ + function ForceAtlas2() { + //------------- + // Configs + + // If auto settings is true + // barnesHutOptimize, + // barnesHutTheta, + // scaling, + // jitterTolerence + // Will be set by the system automatically + // preventOverlap will be set false + // if node size is not given + this.autoSettings = true; + + // Barnes Hut + // http://arborjs.org/docs/barnes-hut + this.barnesHutOptimize = true; + this.barnesHutTheta = 1.5; + + // Force Atlas2 Configs + this.repulsionByDegree = true; + + this.linLogMode = false; + + this.strongGravityMode = false; + this.gravity = 1.0; + + this.scaling = 1.0; + + this.edgeWeightInfluence = 1.0; + this.jitterTolerence = 0.1; + + // TODO + this.preventOverlap = false; + this.dissuadeHubs = false; + + // + this.rootRegion = new Region(); + this.rootRegion.centerOfMass = vec2.create(); + + this.nodes = []; + + this.edges = []; + + this.bbox = new Float32Array(4); + + this.gravityCenter = null; + + this._massArr = null; + + this._swingingArr = null; + + this._sizeArr = null; + + this._globalSpeed = 0; + } + + var forceAtlas2Proto = ForceAtlas2.prototype; + + forceAtlas2Proto.initNodes = function(positionArr, massArr, sizeArr) { + var nNodes = massArr.length; + this.nodes.length = 0; + var haveSize = typeof(sizeArr) != 'undefined'; + for (var i = 0; i < nNodes; i++) { + var node = new GraphNode(); + node.position[0] = positionArr[i * 2]; + node.position[1] = positionArr[i * 2 + 1]; + node.mass = massArr[i]; + if (haveSize) { + node.size = sizeArr[i]; + } + this.nodes.push(node); + } + + this._massArr = massArr; + this._swingingArr = new Float32Array(nNodes); + + if (haveSize) { + this._sizeArr = sizeArr; + } + }; + + forceAtlas2Proto.initEdges = function(edgeArr, edgeWeightArr) { + var nEdges = edgeArr.length / 2; + this.edges.length = 0; + for (var i = 0; i < nEdges; i++) { + var sIdx = edgeArr[i * 2]; + var tIdx = edgeArr[i * 2 + 1]; + var sNode = this.nodes[sIdx]; + var tNode = this.nodes[tIdx]; + + if (!sNode || !tNode) { + console.error('Node not exists, try initNodes before initEdges'); + return; + } + sNode.outDegree++; + tNode.inDegree++; + var edge = new GraphEdge(sNode, tNode); + + if (edgeWeightArr) { + edge.weight = edgeWeightArr[i]; + } + + this.edges.push(edge); + } + } + + forceAtlas2Proto.updateSettings = function() { + if (this.repulsionByDegree) { + for (var i = 0; i < this.nodes.length; i++) { + var node = this.nodes[i]; + node.mass = node.inDegree + node.outDegree + 1; + } + } + else { + for (var i = 0; i < this.nodes.length; i++) { + var node = this.nodes[i]; + node.mass = this._massArr[i]; + } + } + }; + + forceAtlas2Proto.update = function() { + var nNodes = this.nodes.length; + + this.updateSettings(); + + this.updateBBox(); + + // Update region + if (this.barnesHutOptimize) { + this.rootRegion.setBBox( + this.bbox[0], this.bbox[1], + this.bbox[2], this.bbox[3] + ); + + this.rootRegion.beforeUpdate(); + for (var i = 0; i < nNodes; i++) { + this.rootRegion.addNode(this.nodes[i]); + } + this.rootRegion.afterUpdate(); + } + + // Reset forces + for (var i = 0; i < nNodes; i++) { + var node = this.nodes[i]; + vec2.copy(node.forcePrev, node.force); + vec2.set(node.force, 0, 0); + } + + // Compute forces + // Repulsion + for (var i = 0; i < nNodes; i++) { + var na = this.nodes[i]; + if (this.barnesHutOptimize) { + this.applyRegionToNodeRepulsion(this.rootRegion, na); + } + else { + for (var j = i + 1; j < nNodes; j++) { + var nb = this.nodes[j]; + this.applyNodeToNodeRepulsion(na, nb, false); + } + } + + // Gravity + if (this.gravity > 0) { + if (this.strongGravityMode) { + this.applyNodeStrongGravity(na); + } + else { + this.applyNodeGravity(na); + } + } + } + + // Attraction + for (var i = 0; i < this.edges.length; i++) { + this.applyEdgeAttraction(this.edges[i]); + } + + // Handle swinging + var swingWeightedSum = 0; + var tractionWeightedSum = 0; + var tmp = vec2.create(); + for (var i = 0; i < nNodes; i++) { + var node = this.nodes[i]; + var swing = vec2.dist(node.force, node.forcePrev); + swingWeightedSum += swing * node.mass; + + vec2.add(tmp, node.force, node.forcePrev); + var traction = vec2.len(tmp) * 0.5; + tractionWeightedSum += traction * node.mass; + + // Save the value for using later + this._swingingArr[i] = swing; + } + var globalSpeed = this.jitterTolerence * this.jitterTolerence + * tractionWeightedSum / swingWeightedSum; + // NB: During our tests we observed that an excessive rise of the global speed could have a negative impact. + // That’s why we limited the increase of global speed s(t)(G) to 50% of the previous step s(t−1)(G). + if (this._globalSpeed > 0) { + globalSpeed = Math.min(globalSpeed / this._globalSpeed, 1.5) * this._globalSpeed; + } + this._globalSpeed = globalSpeed; + + // Apply forces + for (var i = 0; i < nNodes; i++) { + var node = this.nodes[i]; + var swing = this._swingingArr[i]; + + var speed = 0.1 * globalSpeed / (1 + globalSpeed * Math.sqrt(swing)); + + // Additional constraint to prevent local speed gets too high + var df = vec2.len(node.force); + if (df > 0) { + speed = Math.min(df * speed, 10) / df; + vec2.scaleAndAdd(node.position, node.position, node.force, speed); + } + } + }; + + forceAtlas2Proto.applyRegionToNodeRepulsion = (function() { + var v = vec2.create(); + return function applyRegionToNodeRepulsion(region, node) { + if (region.node) { // Region is a leaf + this.applyNodeToNodeRepulsion(region.node, node, true); + } + else { + vec2.sub(v, node.position, region.centerOfMass); + var d2 = v[0] * v[0] + v[1] * v[1]; + if (d2 > this.barnesHutTheta * region.size * region.size) { + var factor = this.scaling * node.mass * region.mass / d2; + vec2.scaleAndAdd(node.force, node.force, v, factor); + } + else { + for (var i = 0; i < region.nSubRegions; i++) { + this.applyRegionToNodeRepulsion(region.subRegions[i], node); + } + } + } + } + })(); + + forceAtlas2Proto.applyNodeToNodeRepulsion = (function() { + var v = vec2.create(); + return function applyNodeToNodeRepulsion(na, nb, oneWay) { + if (na == nb) { + return; + } + vec2.sub(v, na.position, nb.position); + var d2 = v[0] * v[0] + v[1] * v[1]; + + // PENDING + if (d2 === 0) { + return; + } + + var factor; + if (this.preventOverlap) { + var d = Math.sqrt(d2); + d = d - na.size - nb.size; + if (d > 0) { + factor = this.scaling * na.mass * nb.mass / (d * d); + } + else if (d < 0) { + // A stronger repulsion if overlap + factor = this.scaling * 100 * na.mass * nb.mass; + } + else { + // No repulsion + return; + } + } + else { + // Divide factor by an extra `d` to normalize the `v` + factor = this.scaling * na.mass * nb.mass / d2; + } + + vec2.scaleAndAdd(na.force, na.force, v, factor); + vec2.scaleAndAdd(nb.force, nb.force, v, -factor); + } + })(); + + forceAtlas2Proto.applyEdgeAttraction = (function() { + var v = vec2.create(); + return function applyEdgeAttraction(edge) { + var na = edge.source; + var nb = edge.target; + + vec2.sub(v, na.position, nb.position); + var d = vec2.len(v); + + var w; + if (this.edgeWeightInfluence === 0) { + w = 1; + } + else if (this.edgeWeightInfluence === 1) { + w = edge.weight; + } + else { + w = Math.pow(edge.weight, this.edgeWeightInfluence); + } + + var factor; + + if (this.preventOverlap) { + d = d - na.size - nb.size; + if (d <= 0) { + // No attraction + return; + } + } + + if (this.linLogMode) { + // Divide factor by an extra `d` to normalize the `v` + factor = - w * Math.log(d + 1) / (d + 1); + } + else { + factor = - w; + } + vec2.scaleAndAdd(na.force, na.force, v, factor); + vec2.scaleAndAdd(nb.force, nb.force, v, -factor); + } + })(); + + forceAtlas2Proto.applyNodeGravity = (function() { + var v = vec2.create(); + return function(node) { + vec2.sub(v, this.gravityCenter, node.position); + var d = vec2.len(v); + vec2.scaleAndAdd(node.force, node.force, v, this.gravity * node.mass / (d + 1)); + } + })(); + + forceAtlas2Proto.applyNodeStrongGravity = (function() { + var v = vec2.create(); + return function(node) { + vec2.sub(v, this.gravityCenter, node.position); + vec2.scaleAndAdd(node.force, node.force, v, this.gravity * node.mass); + } + })(); + + forceAtlas2Proto.updateBBox = function() { + var minX = Infinity; + var minY = Infinity; + var maxX = -Infinity; + var maxY = -Infinity; + for (var i = 0; i < this.nodes.length; i++) { + var pos = this.nodes[i].position; + minX = Math.min(minX, pos[0]); + minY = Math.min(minY, pos[1]); + maxX = Math.max(maxX, pos[0]); + maxY = Math.max(maxY, pos[1]); + } + this.bbox[0] = minX; + this.bbox[1] = minY; + this.bbox[2] = maxX; + this.bbox[3] = maxY; + }; + + forceAtlas2Proto.getGlobalSpeed = function () { + return this._globalSpeed; + } + + /**************************** + * Main process + ***************************/ + + var forceAtlas2 = null; + + self.onmessage = function(e) { + switch(e.data.cmd) { + case 'init': + forceAtlas2 = new ForceAtlas2(); + forceAtlas2.initNodes(e.data.nodesPosition, e.data.nodesMass, e.data.nodesSize); + forceAtlas2.initEdges(e.data.edges, e.data.edgesWeight); + break; + case 'updateConfig': + if (forceAtlas2) { + for (var name in e.data.config) { + forceAtlas2[name] = e.data.config[name]; + } + } + break; + case 'update': + var steps = e.data.steps; + if (forceAtlas2) { + for (var i = 0; i < steps; i++) { + forceAtlas2.update(); + } + + var nNodes = forceAtlas2.nodes.length; + var positionArr = new Float32Array(nNodes * 2); + // Callback + for (var i = 0; i < nNodes; i++) { + var node = forceAtlas2.nodes[i]; + positionArr[i * 2] = node.position[0]; + positionArr[i * 2 + 1] = node.position[1]; + } + self.postMessage({ + buffer: positionArr.buffer, + globalSpeed: forceAtlas2.getGlobalSpeed() + }, [positionArr.buffer]); + } + else { + // Not initialzied yet + var emptyArr = new Float32Array(); + // Post transfer object + self.postMessage({ + buffer: emptyArr.buffer, + globalSpeed: forceAtlas2.getGlobalSpeed() + }, [emptyArr.buffer]); + } + break; + } + } +} + +/* harmony default export */ __webpack_exports__["a"] = (forceAtlas2Worker); + +/***/ }), +/* 273 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_claygl_src_core_Base__ = __webpack_require__(7); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__retrieve__ = __webpack_require__(2); + + + + +/** + * @alias module:echarts-gl/util/Roam2DControl + */ +var Roam2DControl = __WEBPACK_IMPORTED_MODULE_0_claygl_src_core_Base__["a" /* default */].extend(function () { + + return { + /** + * @type {module:zrender~ZRender} + */ + zr: null, + + /** + * @type {module:echarts-gl/core/ViewGL} + */ + viewGL: null, + + minZoom: 0.2, + + maxZoom: 5, + + _needsUpdate: false, + + _dx: 0, + _dy: 0, + + _zoom: 1 + }; +}, function () { + // Each Roam2DControl has it's own handler + this._mouseDownHandler = this._mouseDownHandler.bind(this); + this._mouseWheelHandler = this._mouseWheelHandler.bind(this); + this._mouseMoveHandler = this._mouseMoveHandler.bind(this); + this._mouseUpHandler = this._mouseUpHandler.bind(this); + this._update = this._update.bind(this); +}, { + + init: function () { + var zr = this.zr; + + zr.on('mousedown', this._mouseDownHandler); + zr.on('mousewheel', this._mouseWheelHandler); + zr.on('globalout', this._mouseUpHandler); + + zr.animation.on('frame', this._update); + }, + + setTarget: function (target) { + this._target = target; + }, + + setZoom: function (zoom) { + this._zoom = Math.max(Math.min( + zoom, this.maxZoom + ), this.minZoom); + this._needsUpdate = true; + }, + + setOffset: function (offset) { + this._dx = offset[0]; + this._dy = offset[1]; + + this._needsUpdate = true; + }, + + getZoom: function () { + return this._zoom; + }, + + getOffset: function () { + return [this._dx, this._dy]; + }, + + _update: function () { + if (!this._target) { + return; + } + if (!this._needsUpdate) { + return; + } + + var target = this._target; + + var scale = this._zoom; + + target.position.x = this._dx; + target.position.y = this._dy; + + target.scale.set(scale, scale, scale); + + this.zr.refresh(); + + this._needsUpdate = false; + + this.trigger('update'); + }, + + _mouseDownHandler: function (e) { + if (e.target) { + return; + } + + var x = e.offsetX; + var y = e.offsetY; + if (this.viewGL && !this.viewGL.containPoint(x, y)) { + return; + } + + this.zr.on('mousemove', this._mouseMoveHandler); + this.zr.on('mouseup', this._mouseUpHandler); + + var pos = this._convertPos(x, y); + + this._x = pos.x; + this._y = pos.y; + }, + + // Convert pos from screen space to viewspace. + _convertPos: function (x, y) { + + var camera = this.viewGL.camera; + var viewport = this.viewGL.viewport; + // PENDING + return { + x: (x - viewport.x) / viewport.width * (camera.right - camera.left) + camera.left, + y: (y - viewport.y) / viewport.height * (camera.bottom - camera.top) + camera.top + }; + }, + + _mouseMoveHandler: function (e) { + + var pos = this._convertPos(e.offsetX, e.offsetY); + + this._dx += pos.x - this._x; + this._dy += pos.y - this._y; + + this._x = pos.x; + this._y = pos.y; + + this._needsUpdate = true; + }, + + _mouseUpHandler: function (e) { + this.zr.off('mousemove', this._mouseMoveHandler); + this.zr.off('mouseup', this._mouseUpHandler); + }, + + _mouseWheelHandler: function (e) { + e = e.event; + var delta = e.wheelDelta // Webkit + || -e.detail; // Firefox + if (delta === 0) { + return; + } + + var x = e.offsetX; + var y = e.offsetY; + if (this.viewGL && !this.viewGL.containPoint(x, y)) { + return; + } + + var zoomScale = delta > 0 ? 1.1 : 0.9; + var newZoom = Math.max(Math.min( + this._zoom * zoomScale, this.maxZoom + ), this.minZoom); + zoomScale = newZoom / this._zoom; + + var pos = this._convertPos(x, y); + + var fixX = (pos.x - this._dx) * (zoomScale - 1); + var fixY = (pos.y - this._dy) * (zoomScale - 1); + + this._dx -= fixX; + this._dy -= fixY; + + this._zoom = newZoom; + + this._needsUpdate = true; + }, + + dispose: function () { + + var zr = this.zr; + zr.off('mousedown', this._mouseDownHandler); + zr.off('mousemove', this._mouseMoveHandler); + zr.off('mouseup', this._mouseUpHandler); + zr.off('mousewheel', this._mouseWheelHandler); + zr.off('globalout', this._mouseUpHandler); + + zr.animation.off('frame', this._update); + } +}); + +/* harmony default export */ __webpack_exports__["a"] = (Roam2DControl); + +/***/ }), +/* 274 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony default export */ __webpack_exports__["a"] = ("@export ecgl.lines2D.vertex\n\nuniform mat4 worldViewProjection : WORLDVIEWPROJECTION;\n\nattribute vec2 position: POSITION;\nattribute vec4 a_Color : COLOR;\nvarying vec4 v_Color;\n\n#ifdef POSITIONTEXTURE_ENABLED\nuniform sampler2D positionTexture;\n#endif\n\nvoid main()\n{\n gl_Position = worldViewProjection * vec4(position, -10.0, 1.0);\n\n v_Color = a_Color;\n}\n\n@end\n\n@export ecgl.lines2D.fragment\n\nuniform vec4 color : [1.0, 1.0, 1.0, 1.0];\n\nvarying vec4 v_Color;\n\nvoid main()\n{\n gl_FragColor = color * v_Color;\n}\n@end\n\n\n@export ecgl.meshLines2D.vertex\n\nattribute vec2 position: POSITION;\nattribute vec2 normal;\nattribute float offset;\nattribute vec4 a_Color : COLOR;\n\nuniform mat4 worldViewProjection : WORLDVIEWPROJECTION;\nuniform vec4 viewport : VIEWPORT;\n\nvarying vec4 v_Color;\nvarying float v_Miter;\n\nvoid main()\n{\n vec4 p2 = worldViewProjection * vec4(position + normal, -10.0, 1.0);\n gl_Position = worldViewProjection * vec4(position, -10.0, 1.0);\n\n p2.xy /= p2.w;\n gl_Position.xy /= gl_Position.w;\n\n vec2 N = normalize(p2.xy - gl_Position.xy);\n gl_Position.xy += N * offset / viewport.zw * 2.0;\n\n gl_Position.xy *= gl_Position.w;\n\n v_Color = a_Color;\n}\n@end\n\n\n@export ecgl.meshLines2D.fragment\n\nuniform vec4 color : [1.0, 1.0, 1.0, 1.0];\n\nvarying vec4 v_Color;\nvarying float v_Miter;\n\nvoid main()\n{\n gl_FragColor = color * v_Color;\n}\n\n@end"); + + +/***/ }), +/* 275 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__flowGL_FlowGLView__ = __webpack_require__(276); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__flowGL_FlowGLSeries__ = __webpack_require__(280); + + + + + + +/***/ }), +/* 276 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__ = __webpack_require__(1); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__util_retrieve__ = __webpack_require__(2); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__core_ViewGL__ = __webpack_require__(22); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4__VectorFieldParticleSurface__ = __webpack_require__(277); + + + + + + + + +// TODO 百度地图不是 linear 的 +__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.extendChartView({ + + type: 'flowGL', + + __ecgl__: true, + + init: function (ecModel, api) { + this.viewGL = new __WEBPACK_IMPORTED_MODULE_3__core_ViewGL__["a" /* default */]('orthographic'); + this.groupGL = new __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].Node(); + this.viewGL.add(this.groupGL); + + this._particleSurface = new __WEBPACK_IMPORTED_MODULE_4__VectorFieldParticleSurface__["a" /* default */](); + + var planeMesh = new __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].Mesh({ + geometry: new __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].PlaneGeometry(), + material: new __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].Material({ + shader: new __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].Shader({ + vertex: __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].Shader.source('ecgl.color.vertex'), + fragment: __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].Shader.source('ecgl.color.fragment') + }), + // Must enable blending and multiply alpha. + // Or premultipliedAlpha will let the alpha useless. + transparent: true + }) + }); + planeMesh.material.enableTexture('diffuseMap'); + + this.groupGL.add(planeMesh); + + this._planeMesh = planeMesh; + + }, + + render: function (seriesModel, ecModel, api) { + var particleSurface = this._particleSurface; + // Set particleType before set others. + particleSurface.setParticleType(seriesModel.get('particleType')); + particleSurface.setSupersampling(seriesModel.get('supersampling')); + + this._updateData(seriesModel, api); + this._updateCamera(api.getWidth(), api.getHeight(), api.getDevicePixelRatio()); + + var particleDensity = __WEBPACK_IMPORTED_MODULE_2__util_retrieve__["a" /* default */].firstNotNull(seriesModel.get('particleDensity'), 128); + particleSurface.setParticleDensity(particleDensity, particleDensity); + + var planeMesh = this._planeMesh; + + var time = +(new Date()); + var self = this; + var firstFrame = true; + planeMesh.__percent = 0; + planeMesh.stopAnimation(); + planeMesh.animate('', { loop: true }) + .when(100000, { + __percent: 1 + }) + .during(function () { + var timeNow = + (new Date()); + var dTime = Math.min(timeNow - time, 20); + time = time + dTime; + if (self._renderer) { + particleSurface.update(self._renderer, api, dTime / 1000, firstFrame); + planeMesh.material.set('diffuseMap', particleSurface.getSurfaceTexture()); + // planeMesh.material.set('diffuseMap', self._particleSurface.vectorFieldTexture); + } + firstFrame = false; + }) + .start(); + + var itemStyleModel = seriesModel.getModel('itemStyle'); + var color = __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].parseColor(itemStyleModel.get('color')); + color[3] *= __WEBPACK_IMPORTED_MODULE_2__util_retrieve__["a" /* default */].firstNotNull(itemStyleModel.get('opacity'), 1); + planeMesh.material.set('color', color); + + particleSurface.setColorTextureImage(seriesModel.get('colorTexture'), api); + particleSurface.setParticleSize(seriesModel.get('particleSize')); + particleSurface.particleSpeedScaling = seriesModel.get('particleSpeed'); + particleSurface.motionBlurFactor = 1.0 - Math.pow(0.1, seriesModel.get('particleTrail')); + }, + + updateTransform: function (seriesModel, ecModel, api) { + this._updateData(seriesModel, api); + }, + + afterRender: function (globeModel, ecModel, api, layerGL) { + var renderer = layerGL.renderer; + this._renderer = renderer; + }, + + _updateData: function (seriesModel, api) { + var coordSys = seriesModel.coordinateSystem; + var dims = coordSys.dimensions.map(function (coordDim) { + return seriesModel.coordDimToDataDim(coordDim)[0]; + }); + + var data = seriesModel.getData(); + var xExtent = data.getDataExtent(dims[0]); + var yExtent = data.getDataExtent(dims[1]); + + var gridWidth = seriesModel.get('gridWidth'); + var gridHeight = seriesModel.get('gridHeight'); + + if (gridWidth == null || gridWidth === 'auto') { + // TODO not accurate. + var aspect = (xExtent[1] - xExtent[0]) / (yExtent[1] - yExtent[0]); + gridWidth = Math.round(Math.sqrt(aspect * data.count())); + } + if (gridHeight == null || gridHeight === 'auto') { + gridHeight = Math.ceil(data.count() / gridWidth); + } + + var vectorFieldTexture = this._particleSurface.vectorFieldTexture; + + // Half Float needs Uint16Array + var pixels = vectorFieldTexture.pixels; + if (!pixels || pixels.length !== gridHeight * gridWidth * 4) { + pixels = vectorFieldTexture.pixels = new Float32Array(gridWidth * gridHeight * 4); + } + else { + for (var i = 0; i < pixels.length; i++) { + pixels[i] = 0; + } + } + + var maxMag = 0; + var minMag = Infinity; + + var points = new Float32Array(data.count() * 2); + var offset = 0; + var bbox = [[Infinity, Infinity], [-Infinity, -Infinity]]; + + data.each([dims[0], dims[1], 'vx', 'vy'], function (x, y, vx, vy) { + var pt = coordSys.dataToPoint([x, y]); + points[offset++] = pt[0]; + points[offset++] = pt[1]; + bbox[0][0] = Math.min(pt[0], bbox[0][0]); + bbox[0][1] = Math.min(pt[1], bbox[0][1]); + bbox[1][0] = Math.max(pt[0], bbox[1][0]); + bbox[1][1] = Math.max(pt[1], bbox[1][1]); + + var mag = Math.sqrt(vx * vx + vy * vy); + maxMag = Math.max(maxMag, mag); + minMag = Math.min(minMag, mag); + }); + + data.each(['vx', 'vy'], function (vx, vy, i) { + var xPix = Math.round((points[i * 2] - bbox[0][0]) / (bbox[1][0] - bbox[0][0]) * (gridWidth - 1)); + var yPix = gridHeight - 1 - Math.round((points[i * 2 + 1] - bbox[0][1]) / (bbox[1][1] - bbox[0][1]) * (gridHeight - 1)); + + var idx = (yPix * gridWidth + xPix) * 4; + + pixels[idx] = (vx / maxMag * 0.5 + 0.5); + pixels[idx + 1] = (vy / maxMag * 0.5 + 0.5); + pixels[idx + 3] = 1; + }); + + vectorFieldTexture.width = gridWidth; + vectorFieldTexture.height = gridHeight; + + if (seriesModel.get('coordinateSystem') === 'bmap') { + this._fillEmptyPixels(vectorFieldTexture); + } + + vectorFieldTexture.dirty(); + + this._updatePlanePosition(bbox[0], bbox[1], seriesModel,api); + this._updateGradientTexture(data.getVisual('visualMeta'), [minMag, maxMag]); + + }, + // PENDING Use grid mesh ? or delaunay triangulation? + _fillEmptyPixels: function (texture) { + var pixels = texture.pixels; + var width = texture.width; + var height = texture.height; + + function fetchPixel(x, y, rg) { + x = Math.max(Math.min(x, width - 1), 0); + y = Math.max(Math.min(y, height - 1), 0); + var idx = (y * (width - 1) + x) * 4; + if (pixels[idx + 3] === 0) { + return false; + } + rg[0] = pixels[idx]; + rg[1] = pixels[idx + 1]; + return true; + } + + function addPixel(a, b, out) { + out[0] = a[0] + b[0]; + out[1] = a[1] + b[1]; + } + + var center = [], left = [], right = [], top = [], bottom = []; + var weight = 0; + for (var y = 0; y < height; y++) { + for (var x = 0; x < width; x++) { + var idx = (y * (width - 1) + x) * 4; + if (pixels[idx + 3] === 0) { + weight = center[0] = center[1] = 0; + if (fetchPixel(x - 1, y, left)) { + weight++; addPixel(left, center, center); + } + if (fetchPixel(x + 1, y, right)) { + weight++; addPixel(right, center, center); + } + if (fetchPixel(x, y - 1, top)) { + weight++; addPixel(top, center, center); + } + if (fetchPixel(x, y + 1, bottom)) { + weight++; addPixel(bottom, center, center); + } + center[0] /= weight; + center[1] /= weight; + // PENDING If overwrite. bilinear interpolation. + pixels[idx] = center[0]; + pixels[idx + 1] = center[1]; + } + pixels[idx + 3] = 1; + } + } + }, + + _updateGradientTexture: function (visualMeta, magExtent) { + if (!visualMeta || !visualMeta.length) { + this._particleSurface.setGradientTexture(null); + return; + } + // TODO Different dimensions + this._gradientTexture = this._gradientTexture || new __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].Texture2D({ + image: document.createElement('canvas') + }); + var gradientTexture = this._gradientTexture; + var canvas = gradientTexture.image; + canvas.width = 200; + canvas.height = 1; + var ctx = canvas.getContext('2d'); + var gradient = ctx.createLinearGradient(0, 0.5, canvas.width, 0.5); + visualMeta[0].stops.forEach(function (stop) { + var offset; + if (magExtent[1] === magExtent[0]) { + offset = 0; + } + else { + offset = stop.value / magExtent[1]; + offset = Math.min(Math.max(offset, 0), 1); + } + + gradient.addColorStop(offset, stop.color); + }); + ctx.fillStyle = gradient; + ctx.fillRect(0, 0, canvas.width, canvas.height); + gradientTexture.dirty(); + + this._particleSurface.setGradientTexture(this._gradientTexture); + }, + + _updatePlanePosition: function (leftTop, rightBottom, seriesModel, api) { + var limitedResult = this._limitInViewportAndFullFill(leftTop, rightBottom, seriesModel, api); + leftTop = limitedResult.leftTop; + rightBottom = limitedResult.rightBottom; + this._particleSurface.setRegion(limitedResult.region); + + this._planeMesh.position.set( + (leftTop[0] + rightBottom[0]) / 2, + api.getHeight() - (leftTop[1] + rightBottom[1]) / 2, + 0 + ); + + var width = rightBottom[0] - leftTop[0]; + var height = rightBottom[1] - leftTop[1]; + this._planeMesh.scale.set(width / 2, height / 2, 1); + + this._particleSurface.resize( + Math.max(Math.min(width, 2048), 1), + Math.max(Math.min(height, 2048), 1) + ); + + if (this._renderer) { + this._particleSurface.clearFrame(this._renderer); + } + }, + + _limitInViewportAndFullFill: function (leftTop, rightBottom, seriesModel, api) { + var newLeftTop = [ + Math.max(leftTop[0], 0), + Math.max(leftTop[1], 0) + ]; + var newRightBottom = [ + Math.min(rightBottom[0], api.getWidth()), + Math.min(rightBottom[1], api.getHeight()) + ]; + // Tiliing in lng orientation. + if (seriesModel.get('coordinateSystem') === 'bmap') { + var lngRange = seriesModel.getData().getDataExtent(seriesModel.coordDimToDataDim('lng')[0]); + // PENDING, consider grid density + var isContinuous = Math.floor(lngRange[1] - lngRange[0]) >= 359; + if (isContinuous) { + if (newLeftTop[0] > 0) { + newLeftTop[0] = 0; + } + if (newRightBottom[0] < api.getWidth()) { + newRightBottom[0] = api.getWidth(); + } + } + } + + var width = rightBottom[0] - leftTop[0]; + var height = rightBottom[1] - leftTop[1]; + var newWidth = newRightBottom[0] - newLeftTop[0]; + var newHeight = newRightBottom[1] - newLeftTop[1]; + + var region = [ + (newLeftTop[0] - leftTop[0]) / width, + 1.0 - newHeight / height - (newLeftTop[1] - leftTop[1]) / height, + newWidth / width, + newHeight / height + ]; + + return { + leftTop: newLeftTop, + rightBottom: newRightBottom, + region: region + }; + }, + + _updateCamera: function (width, height, dpr) { + this.viewGL.setViewport(0, 0, width, height, dpr); + var camera = this.viewGL.camera; + // FIXME bottom can't be larger than top + camera.left = camera.bottom = 0; + camera.top = height; + camera.right = width; + camera.near = 0; + camera.far = 100; + camera.position.z = 10; + }, + + remove: function () { + this._planeMesh.stopAnimation(); + this.groupGL.removeAll(); + }, + + dispose: function () { + if (this._renderer) { + this._particleSurface.dispose(this._renderer); + } + this.groupGL.removeAll(); + } +}); + + +/***/ }), +/* 277 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_claygl_src_compositor_Pass__ = __webpack_require__(16); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_claygl_src_Geometry__ = __webpack_require__(15); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2_claygl_src_Mesh__ = __webpack_require__(40); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3_claygl_src_Material__ = __webpack_require__(19); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4_claygl_src_Shader__ = __webpack_require__(8); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_5_claygl_src_Texture2D__ = __webpack_require__(5); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_6_claygl_src_Texture__ = __webpack_require__(4); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_7_claygl_src_camera_Orthographic__ = __webpack_require__(37); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_8_claygl_src_geometry_Plane__ = __webpack_require__(43); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_9_claygl_src_FrameBuffer__ = __webpack_require__(10); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_10__Line2D__ = __webpack_require__(278); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_11__vectorFieldParticle_glsl_js__ = __webpack_require__(279); + + + + + + + + + + + + +// import TemporalSS from '../../effect/TemporalSuperSampling'; + + + +__WEBPACK_IMPORTED_MODULE_4_claygl_src_Shader__["a" /* default */]['import'](__WEBPACK_IMPORTED_MODULE_11__vectorFieldParticle_glsl_js__["a" /* default */]); + +function createSpriteCanvas(size) { + var canvas = document.createElement('canvas'); + canvas.width = canvas.height = size; + var ctx = canvas.getContext('2d'); + ctx.fillStyle = '#fff'; + ctx.arc(size / 2, size / 2, size / 2, 0, Math.PI * 2); + ctx.fill(); + return canvas; +} + +// import spriteUtil from '../../util/sprite'; + +var VectorFieldParticleSurface = function () { + + /** + * @type {number} + */ + this.motionBlurFactor = 0.99; + /** + * Vector field lookup image + * @type {clay.Texture2D} + */ + this.vectorFieldTexture = new __WEBPACK_IMPORTED_MODULE_5_claygl_src_Texture2D__["a" /* default */]({ + type: __WEBPACK_IMPORTED_MODULE_6_claygl_src_Texture__["a" /* default */].FLOAT, + // minFilter: Texture.NEAREST, + // magFilter: Texture.NEAREST, + flipY: false + }); + + /** + * Particle life range + * @type {Array.} + */ + this.particleLife = [5, 20]; + + this._particleType = 'point'; + + /** + * @type {number} + */ + this._particleSize = 1; + + /** + * @type {Array.} + */ + this.particleColor = [1, 1, 1, 1]; + + /** + * @type {number} + */ + this.particleSpeedScaling = 1.0; + + /** + * @type {clay.Texture2D} + */ + this._thisFrameTexture = null; + + this._particlePass = null; + this._spawnTexture = null; + this._particleTexture0 = null; + this._particleTexture1 = null; + + this._particlePointsMesh = null; + + this._surfaceFrameBuffer = null; + + this._elapsedTime = 0.0; + + this._scene = null; + this._camera = null; + + this._lastFrameTexture = null; + + // this._temporalSS = new TemporalSS(50); + + // this._antialising = false; + + this._supersampling = 1; + + this._downsampleTextures = []; + + this._width = 512; + this._height = 512; + + this.init(); +}; + +VectorFieldParticleSurface.prototype = { + + constructor: VectorFieldParticleSurface, + + init: function () { + var parameters = { + type: __WEBPACK_IMPORTED_MODULE_6_claygl_src_Texture__["a" /* default */].FLOAT, + minFilter: __WEBPACK_IMPORTED_MODULE_6_claygl_src_Texture__["a" /* default */].NEAREST, + magFilter: __WEBPACK_IMPORTED_MODULE_6_claygl_src_Texture__["a" /* default */].NEAREST, + useMipmap: false + }; + this._spawnTexture = new __WEBPACK_IMPORTED_MODULE_5_claygl_src_Texture2D__["a" /* default */](parameters); + + this._particleTexture0 = new __WEBPACK_IMPORTED_MODULE_5_claygl_src_Texture2D__["a" /* default */](parameters); + this._particleTexture1 = new __WEBPACK_IMPORTED_MODULE_5_claygl_src_Texture2D__["a" /* default */](parameters); + + this._frameBuffer = new __WEBPACK_IMPORTED_MODULE_9_claygl_src_FrameBuffer__["a" /* default */]({ + depthBuffer: false + }); + this._particlePass = new __WEBPACK_IMPORTED_MODULE_0_claygl_src_compositor_Pass__["a" /* default */]({ + fragment: __WEBPACK_IMPORTED_MODULE_4_claygl_src_Shader__["a" /* default */].source('ecgl.vfParticle.particle.fragment') + }); + this._particlePass.setUniform('velocityTexture', this.vectorFieldTexture); + this._particlePass.setUniform('spawnTexture', this._spawnTexture); + + this._downsamplePass = new __WEBPACK_IMPORTED_MODULE_0_claygl_src_compositor_Pass__["a" /* default */]({ + fragment: __WEBPACK_IMPORTED_MODULE_4_claygl_src_Shader__["a" /* default */].source('clay.compositor.downsample') + }); + + var particlePointsMesh = new __WEBPACK_IMPORTED_MODULE_2_claygl_src_Mesh__["a" /* default */]({ + // Render after last frame full quad + renderOrder: 10, + material: new __WEBPACK_IMPORTED_MODULE_3_claygl_src_Material__["a" /* default */]({ + shader: new __WEBPACK_IMPORTED_MODULE_4_claygl_src_Shader__["a" /* default */]( + __WEBPACK_IMPORTED_MODULE_4_claygl_src_Shader__["a" /* default */].source('ecgl.vfParticle.renderPoints.vertex'), + __WEBPACK_IMPORTED_MODULE_4_claygl_src_Shader__["a" /* default */].source('ecgl.vfParticle.renderPoints.fragment') + ) + }), + mode: __WEBPACK_IMPORTED_MODULE_2_claygl_src_Mesh__["a" /* default */].POINTS, + geometry: new __WEBPACK_IMPORTED_MODULE_1_claygl_src_Geometry__["a" /* default */]({ + dynamic: true, + mainAttribute: 'texcoord0' + }) + }); + var particleLinesMesh = new __WEBPACK_IMPORTED_MODULE_2_claygl_src_Mesh__["a" /* default */]({ + // Render after last frame full quad + renderOrder: 10, + material: new __WEBPACK_IMPORTED_MODULE_3_claygl_src_Material__["a" /* default */]({ + shader: new __WEBPACK_IMPORTED_MODULE_4_claygl_src_Shader__["a" /* default */]( + __WEBPACK_IMPORTED_MODULE_4_claygl_src_Shader__["a" /* default */].source('ecgl.vfParticle.renderLines.vertex'), + __WEBPACK_IMPORTED_MODULE_4_claygl_src_Shader__["a" /* default */].source('ecgl.vfParticle.renderLines.fragment') + ) + }), + geometry: new __WEBPACK_IMPORTED_MODULE_10__Line2D__["a" /* default */](), + culling: false + }); + var lastFrameFullQuad = new __WEBPACK_IMPORTED_MODULE_2_claygl_src_Mesh__["a" /* default */]({ + material: new __WEBPACK_IMPORTED_MODULE_3_claygl_src_Material__["a" /* default */]({ + shader: new __WEBPACK_IMPORTED_MODULE_4_claygl_src_Shader__["a" /* default */]( + __WEBPACK_IMPORTED_MODULE_4_claygl_src_Shader__["a" /* default */].source('ecgl.color.vertex'), + __WEBPACK_IMPORTED_MODULE_4_claygl_src_Shader__["a" /* default */].source('ecgl.color.fragment') + ) + // DO NOT BLEND Blend will multiply alpha + // transparent: true + }), + geometry: new __WEBPACK_IMPORTED_MODULE_8_claygl_src_geometry_Plane__["a" /* default */]() + }); + lastFrameFullQuad.material.enableTexture('diffuseMap'); + + this._particlePointsMesh = particlePointsMesh; + this._particleLinesMesh = particleLinesMesh; + this._lastFrameFullQuadMesh = lastFrameFullQuad; + + this._camera = new __WEBPACK_IMPORTED_MODULE_7_claygl_src_camera_Orthographic__["a" /* default */](); + this._thisFrameTexture = new __WEBPACK_IMPORTED_MODULE_5_claygl_src_Texture2D__["a" /* default */](); + this._lastFrameTexture = new __WEBPACK_IMPORTED_MODULE_5_claygl_src_Texture2D__["a" /* default */](); + }, + + setParticleDensity: function (width, height) { + var nVertex = width * height; + + var spawnTextureData = new Float32Array(nVertex * 4); + var off = 0; + var lifeRange = this.particleLife; + for (var i = 0; i < width; i++) { + for (var j = 0; j < height; j++, off++) { + // x position, range [0 - 1] + spawnTextureData[off * 4] = Math.random(); + // y position, range [0 - 1] + spawnTextureData[off * 4 + 1] = Math.random(); + // Some property + spawnTextureData[off * 4 + 2] = Math.random(); + var life = (lifeRange[1] - lifeRange[0]) * Math.random() + lifeRange[0]; + // Particle life + spawnTextureData[off * 4 + 3] = life; + } + } + + if (this._particleType === 'line') { + this._setLineGeometry(width, height); + } + else { + this._setPointsGeometry(width, height); + } + + this._spawnTexture.width = width; + this._spawnTexture.height = height; + this._spawnTexture.pixels = spawnTextureData; + + this._particleTexture0.width = this._particleTexture1.width = width; + this._particleTexture0.height = this._particleTexture1.height = height; + + this._particlePass.setUniform('textureSize', [width, height]); + }, + + _setPointsGeometry: function (width, height) { + var nVertex = width * height; + var geometry = this._particlePointsMesh.geometry; + var attributes = geometry.attributes; + attributes.texcoord0.init(nVertex); + + var off = 0; + for (var i = 0; i < width; i++) { + for (var j = 0; j < height; j++, off++) { + attributes.texcoord0.value[off * 2] = i / width; + attributes.texcoord0.value[off * 2 + 1] = j / height; + } + } + geometry.dirty(); + }, + + _setLineGeometry: function (width, height) { + var nLine = width * height; + var geometry = this._getParticleMesh().geometry; + geometry.setLineCount(nLine); + geometry.resetOffset(); + for (var i = 0; i < width; i++) { + for (var j = 0; j < height; j++) { + geometry.addLine([i / width, j / height]); + } + } + geometry.dirty(); + }, + + _getParticleMesh: function () { + return this._particleType === 'line' ? this._particleLinesMesh : this._particlePointsMesh; + }, + + update: function (renderer, api, deltaTime, firstFrame) { + var particleMesh = this._getParticleMesh(); + var frameBuffer = this._frameBuffer; + var particlePass = this._particlePass; + + if (firstFrame) { + this._updateDownsampleTextures(renderer, api); + } + + particleMesh.material.set('size', this._particleSize * this._supersampling); + particleMesh.material.set('color', this.particleColor); + particlePass.setUniform('speedScaling', this.particleSpeedScaling); + + frameBuffer.attach(this._particleTexture1); + particlePass.setUniform('firstFrameTime', firstFrame ? (this.particleLife[1] + this.particleLife[0]) / 2 : 0); + particlePass.setUniform('particleTexture', this._particleTexture0); + particlePass.setUniform('deltaTime', deltaTime); + particlePass.setUniform('elapsedTime', this._elapsedTime); + particlePass.render(renderer, frameBuffer); + + particleMesh.material.set('particleTexture', this._particleTexture1); + particleMesh.material.set('prevParticleTexture', this._particleTexture0); + + frameBuffer.attach(this._thisFrameTexture); + frameBuffer.bind(renderer); + renderer.gl.clear(renderer.gl.DEPTH_BUFFER_BIT | renderer.gl.COLOR_BUFFER_BIT); + var lastFrameFullQuad = this._lastFrameFullQuadMesh; + lastFrameFullQuad.material.set('diffuseMap', this._lastFrameTexture); + lastFrameFullQuad.material.set('color', [1, 1, 1, this.motionBlurFactor]); + + this._camera.update(true); + renderer.renderPass([lastFrameFullQuad, particleMesh], this._camera); + frameBuffer.unbind(renderer); + + this._downsample(renderer); + + this._swapTexture(); + + this._elapsedTime += deltaTime; + }, + + _downsample: function (renderer) { + var downsampleTextures = this._downsampleTextures; + if (downsampleTextures.length === 0) { + return; + } + var current = 0; + var sourceTexture = this._thisFrameTexture; + var targetTexture = downsampleTextures[current]; + + while (targetTexture) { + this._frameBuffer.attach(targetTexture); + this._downsamplePass.setUniform('texture', sourceTexture); + this._downsamplePass.setUniform('textureSize', [sourceTexture.width, sourceTexture.height]); + this._downsamplePass.render(renderer, this._frameBuffer); + + sourceTexture = targetTexture; + targetTexture = downsampleTextures[++current]; + } + }, + + getSurfaceTexture: function () { + var downsampleTextures = this._downsampleTextures; + return downsampleTextures.length > 0 + ? downsampleTextures[downsampleTextures.length - 1] + : this._lastFrameTexture; + }, + + setRegion: function (region) { + this._particlePass.setUniform('region', region); + }, + + resize: function (width, height) { + this._lastFrameTexture.width = width * this._supersampling; + this._lastFrameTexture.height = height * this._supersampling; + this._thisFrameTexture.width = width * this._supersampling; + this._thisFrameTexture.height = height * this._supersampling; + + this._width = width; + this._height = height; + }, + + setParticleSize: function (size) { + var particleMesh = this._getParticleMesh(); + if (size <= 2) { + particleMesh.material.disableTexture('spriteTexture'); + particleMesh.material.transparent = false; + return; + } + if (!this._spriteTexture) { + this._spriteTexture = new __WEBPACK_IMPORTED_MODULE_5_claygl_src_Texture2D__["a" /* default */](); + } + if (!this._spriteTexture.image || this._spriteTexture.image.width !== size) { + this._spriteTexture.image = createSpriteCanvas(size); + this._spriteTexture.dirty(); + } + particleMesh.material.transparent = true; + particleMesh.material.enableTexture('spriteTexture'); + particleMesh.material.set('spriteTexture', this._spriteTexture); + + this._particleSize = size; + }, + + setGradientTexture: function (gradientTexture) { + var material = this._getParticleMesh().material; + material[gradientTexture ? 'enableTexture' : 'disableTexture']('gradientTexture'); + material.setUniform('gradientTexture', gradientTexture); + }, + + setColorTextureImage: function (colorTextureImg, api) { + var material = this._getParticleMesh().material; + material.setTextureImage('colorTexture', colorTextureImg, api, { + flipY: true + }); + }, + + setParticleType: function (type) { + this._particleType = type; + }, + + clearFrame: function (renderer) { + var frameBuffer = this._frameBuffer; + frameBuffer.attach(this._lastFrameTexture); + frameBuffer.bind(renderer); + renderer.gl.clear(renderer.gl.DEPTH_BUFFER_BIT | renderer.gl.COLOR_BUFFER_BIT); + frameBuffer.unbind(renderer); + }, + + setSupersampling: function (supersampling) { + this._supersampling = supersampling; + this.resize(this._width, this._height); + }, + + _updateDownsampleTextures: function (renderer, api) { + var downsampleTextures = this._downsampleTextures; + var upScale = Math.max(Math.floor(Math.log(this._supersampling / api.getDevicePixelRatio()) / Math.log(2)), 0); + var scale = 2; + var width = this._width * this._supersampling; + var height = this._height * this._supersampling; + for (var i = 0; i < upScale; i++) { + downsampleTextures[i] = downsampleTextures[i] || new __WEBPACK_IMPORTED_MODULE_5_claygl_src_Texture2D__["a" /* default */](); + downsampleTextures[i].width = width / scale; + downsampleTextures[i].height = height / scale; + scale *= 2; + } + for (;i < downsampleTextures.length; i++) { + downsampleTextures[i].dispose(renderer); + } + downsampleTextures.length = upScale; + }, + + _swapTexture: function () { + var tmp = this._particleTexture0; + this._particleTexture0 = this._particleTexture1; + this._particleTexture1 = tmp; + + var tmp = this._thisFrameTexture; + this._thisFrameTexture = this._lastFrameTexture; + this._lastFrameTexture = tmp; + }, + + dispose: function (renderer) { + renderer.disposeFrameBuffer(this._frameBuffer); + // Dispose textures + renderer.disposeTexture(this.vectorFieldTexture); + renderer.disposeTexture(this._spawnTexture); + renderer.disposeTexture(this._particleTexture0); + renderer.disposeTexture(this._particleTexture1); + renderer.disposeTexture(this._thisFrameTexture); + renderer.disposeTexture(this._lastFrameTexture); + + renderer.disposeGeometry(this._particleLinesMesh.geometry); + renderer.disposeGeometry(this._particlePointsMesh.geometry); + renderer.disposeGeometry(this._lastFrameFullQuadMesh.geometry); + + if (this._spriteTexture) { + renderer.disposeTexture(this._spriteTexture); + } + + this._particlePass.dispose(renderer); + this._downsamplePass.dispose(renderer); + + this._downsampleTextures.forEach(function (texture) { + texture.dispose(renderer); + }); + } +}; + +/* harmony default export */ __webpack_exports__["a"] = (VectorFieldParticleSurface); + +/***/ }), +/* 278 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_claygl_src_Geometry__ = __webpack_require__(15); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_echarts_lib_echarts__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_echarts_lib_echarts___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_echarts_lib_echarts__); +/** + * Lines geometry + * Use screen space projected lines lineWidth > MAX_LINE_WIDTH + * https://mattdesl.svbtle.com/drawing-lines-is-hard + * @module echarts-gl/util/geometry/LinesGeometry + * @author Yi Shen(http://github.com/pissang) + */ + + + + +/** + * @constructor + * @alias module:echarts-gl/chart/flowGL/Line2D + * @extends clay.Geometry + */ + +var LinesGeometry = __WEBPACK_IMPORTED_MODULE_0_claygl_src_Geometry__["a" /* default */].extend(function () { + return { + + dynamic: true, + + attributes: { + position: new __WEBPACK_IMPORTED_MODULE_0_claygl_src_Geometry__["a" /* default */].Attribute('position', 'float', 3, 'POSITION') + } + }; +}, +/** @lends module: echarts-gl/util/geometry/LinesGeometry.prototype */ +{ + + /** + * Reset offset + */ + resetOffset: function () { + this._vertexOffset = 0; + this._faceOffset = 0; + }, + + /** + * @param {number} nVertex + */ + setLineCount: function (nLine) { + var attributes = this.attributes; + var nVertex = 4 * nLine; + var nTriangle = 2 * nLine; + if (this.vertexCount !== nVertex) { + attributes.position.init(nVertex); + } + if (this.triangleCount !== nTriangle) { + if (nTriangle === 0) { + this.indices = null; + } + else { + this.indices = this.vertexCount > 0xffff ? new Uint32Array(nTriangle * 3) : new Uint16Array(nTriangle * 3); + } + } + }, + + addLine: function (p) { + var vertexOffset = this._vertexOffset; + this.attributes.position.set(vertexOffset, [p[0], p[1], 1]); + this.attributes.position.set(vertexOffset + 1, [p[0], p[1], -1]); + this.attributes.position.set(vertexOffset + 2, [p[0], p[1], 2]); + this.attributes.position.set(vertexOffset + 3, [p[0], p[1], -2]); + + this.setTriangleIndices( + this._faceOffset++, [ + vertexOffset, vertexOffset + 1, vertexOffset + 2 + ] + ); + this.setTriangleIndices( + this._faceOffset++, [ + vertexOffset + 1, vertexOffset + 2, vertexOffset + 3 + ] + ); + + this._vertexOffset += 4; + } +}); + +/* harmony default export */ __webpack_exports__["a"] = (LinesGeometry); + +/***/ }), +/* 279 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony default export */ __webpack_exports__["a"] = ("@export ecgl.vfParticle.particle.fragment\n\nuniform sampler2D particleTexture;\nuniform sampler2D spawnTexture;\nuniform sampler2D velocityTexture;\n\nuniform float deltaTime;\nuniform float elapsedTime;\n\nuniform float speedScaling : 1.0;\n\nuniform vec2 textureSize;\nuniform vec4 region : [0, 0, 1, 1];\nuniform float firstFrameTime;\n\nvarying vec2 v_Texcoord;\n\n\nvoid main()\n{\n vec4 p = texture2D(particleTexture, v_Texcoord);\n bool spawn = false;\n if (p.w <= 0.0) {\n p = texture2D(spawnTexture, fract(v_Texcoord + elapsedTime / 10.0));\n p.w -= firstFrameTime;\n spawn = true;\n }\n vec2 v = texture2D(velocityTexture, fract(p.xy * region.zw + region.xy)).xy;\n v = (v - 0.5) * 2.0;\n p.z = length(v);\n p.xy += v * deltaTime / 10.0 * speedScaling;\n p.w -= deltaTime;\n\n if (spawn || p.xy != fract(p.xy)) {\n p.z = 0.0;\n }\n p.xy = fract(p.xy);\n\n gl_FragColor = p;\n}\n@end\n\n@export ecgl.vfParticle.renderPoints.vertex\n\n#define PI 3.1415926\n\nattribute vec2 texcoord : TEXCOORD_0;\n\nuniform sampler2D particleTexture;\nuniform mat4 worldViewProjection : WORLDVIEWPROJECTION;\n\nuniform float size : 1.0;\n\nvarying float v_Mag;\nvarying vec2 v_Uv;\n\nvoid main()\n{\n vec4 p = texture2D(particleTexture, texcoord);\n\n if (p.w > 0.0 && p.z > 1e-5) {\n gl_Position = worldViewProjection * vec4(p.xy * 2.0 - 1.0, 0.0, 1.0);\n }\n else {\n gl_Position = vec4(100000.0, 100000.0, 100000.0, 1.0);\n }\n\n v_Mag = p.z;\n v_Uv = p.xy;\n\n gl_PointSize = size;\n}\n\n@end\n\n@export ecgl.vfParticle.renderPoints.fragment\n\nuniform vec4 color : [1.0, 1.0, 1.0, 1.0];\nuniform sampler2D gradientTexture;\nuniform sampler2D colorTexture;\nuniform sampler2D spriteTexture;\n\nvarying float v_Mag;\nvarying vec2 v_Uv;\n\nvoid main()\n{\n gl_FragColor = color;\n#ifdef SPRITETEXTURE_ENABLED\n gl_FragColor *= texture2D(spriteTexture, gl_PointCoord);\n if (color.a == 0.0) {\n discard;\n }\n#endif\n#ifdef GRADIENTTEXTURE_ENABLED\n gl_FragColor *= texture2D(gradientTexture, vec2(v_Mag, 0.5));\n#endif\n#ifdef COLORTEXTURE_ENABLED\n gl_FragColor *= texture2D(colorTexture, v_Uv);\n#endif\n}\n\n@end\n\n@export ecgl.vfParticle.renderLines.vertex\n\n#define PI 3.1415926\n\nattribute vec3 position : POSITION;\n\nuniform sampler2D particleTexture;\nuniform sampler2D prevParticleTexture;\n\nuniform float size : 1.0;\nuniform vec4 vp: VIEWPORT;\nuniform mat4 worldViewProjection : WORLDVIEWPROJECTION;\n\nvarying float v_Mag;\nvarying vec2 v_Uv;\n\n@import clay.util.rand\n\nvoid main()\n{\n vec4 p = texture2D(particleTexture, position.xy);\n vec4 p2 = texture2D(prevParticleTexture, position.xy);\n\n p.xy = p.xy * 2.0 - 1.0;\n p2.xy = p2.xy * 2.0 - 1.0;\n\n if (p.w > 0.0 && p.z > 1e-5) {\n vec2 dir = normalize(p.xy - p2.xy);\n vec2 norm = vec2(dir.y / vp.z, -dir.x / vp.w) * sign(position.z) * size;\n if (abs(position.z) == 2.0) {\n gl_Position = vec4(p.xy + norm, 0.0, 1.0);\n v_Uv = p.xy;\n v_Mag = p.z;\n }\n else {\n gl_Position = vec4(p2.xy + norm, 0.0, 1.0);\n v_Mag = p2.z;\n v_Uv = p2.xy;\n }\n gl_Position = worldViewProjection * gl_Position;\n }\n else {\n gl_Position = vec4(100000.0, 100000.0, 100000.0, 1.0);\n }\n}\n\n@end\n\n@export ecgl.vfParticle.renderLines.fragment\n\nuniform vec4 color : [1.0, 1.0, 1.0, 1.0];\nuniform sampler2D gradientTexture;\nuniform sampler2D colorTexture;\n\nvarying float v_Mag;\nvarying vec2 v_Uv;\n\nvoid main()\n{\n gl_FragColor = color;\n #ifdef GRADIENTTEXTURE_ENABLED\n gl_FragColor *= texture2D(gradientTexture, vec2(v_Mag, 0.5));\n#endif\n#ifdef COLORTEXTURE_ENABLED\n gl_FragColor *= texture2D(colorTexture, v_Uv);\n#endif\n}\n\n@end\n"); + + +/***/ }), +/* 280 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__); + + +__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.extendSeriesModel({ + + type: 'series.flowGL', + + dependencies: ['geo', 'grid', 'bmap'], + + visualColorAccessPath: 'itemStyle.color', + + getInitialData: function (option, ecModel) { + var coordSysDimensions = __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.getCoordinateSystemDimensions(this.get('coordinateSystem')) || ['x', 'y']; + if (true) { + if (coordSysDimensions.length > 2) { + throw new Error('flowGL can only be used on 2d coordinate systems.') + } + } + coordSysDimensions.push('vx', 'vy'); + var dimensions = __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.helper.completeDimensions(coordSysDimensions, this.getSource(), { + encodeDef: this.get('encode'), + dimsDef: this.get('dimensions') + }); + var data = new __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.List(dimensions, this); + data.initData(this.getSource()); + return data; + }, + + defaultOption: { + coordinateSystem: 'cartesian2d', + zlevel: 10, + + supersampling: 1, + // 128x128 particles + particleType: 'point', + + particleDensity: 128, + particleSize: 1, + particleSpeed: 1, + + particleTrail: 2, + + colorTexture: null, + + gridWidth: 'auto', + gridHeight: 'auto', + + itemStyle: { + color: '#fff', + opacity: 0.8 + } + } +}); + +/***/ }), +/* 281 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__linesGL_LinesGLSeries__ = __webpack_require__(282); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__linesGL_LinesGLView__ = __webpack_require__(283); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__common_opacityVisual__ = __webpack_require__(17); + + + + + + + +__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.registerVisual(Object(__WEBPACK_IMPORTED_MODULE_3__common_opacityVisual__["a" /* default */])('linesGL')); + +/***/ }), +/* 282 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_zrender_lib_core_util__ = __webpack_require__(13); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_zrender_lib_core_util___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_zrender_lib_core_util__); + + + +var LinesSeries = __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.extendSeriesModel({ + + type: 'series.linesGL', + + dependencies: ['grid', 'geo'], + + visualColorAccessPath: 'lineStyle.color', + + streamEnabled: true, + + init: function (option) { + var result = this._processFlatCoordsArray(option.data); + this._flatCoords = result.flatCoords; + this._flatCoordsOffset = result.flatCoordsOffset; + if (result.flatCoords) { + option.data = new Float32Array(result.count); + } + + LinesSeries.superApply(this, 'init', arguments); + }, + + mergeOption: function (option) { + var result = this._processFlatCoordsArray(option.data); + this._flatCoords = result.flatCoords; + this._flatCoordsOffset = result.flatCoordsOffset; + if (result.flatCoords) { + option.data = new Float32Array(result.count); + } + + LinesSeries.superApply(this, 'mergeOption', arguments); + }, + + appendData: function (params) { + var result = this._processFlatCoordsArray(params.data); + if (result.flatCoords) { + if (!this._flatCoords) { + this._flatCoords = result.flatCoords; + this._flatCoordsOffset = result.flatCoordsOffset; + } + else { + this._flatCoords = Object(__WEBPACK_IMPORTED_MODULE_1_zrender_lib_core_util__["concatArray"])(this._flatCoords, result.flatCoords); + this._flatCoordsOffset = Object(__WEBPACK_IMPORTED_MODULE_1_zrender_lib_core_util__["concatArray"])(this._flatCoordsOffset, result.flatCoordsOffset); + } + params.data = new Float32Array(result.count); + } + + this.getRawData().appendData(params.data); + }, + + _getCoordsFromItemModel: function (idx) { + var itemModel = this.getData().getItemModel(idx); + var coords = (itemModel.option instanceof Array) + ? itemModel.option : itemModel.getShallow('coords'); + + if (true) { + if (!(coords instanceof Array && coords.length > 0 && coords[0] instanceof Array)) { + throw new Error('Invalid coords ' + JSON.stringify(coords) + '. Lines must have 2d coords array in data item.'); + } + } + return coords; + }, + + getLineCoordsCount: function (idx) { + if (this._flatCoordsOffset) { + return this._flatCoordsOffset[idx * 2 + 1]; + } + else { + return this._getCoordsFromItemModel(idx).length; + } + }, + + getLineCoords: function (idx, out) { + if (this._flatCoordsOffset) { + var offset = this._flatCoordsOffset[idx * 2]; + var len = this._flatCoordsOffset[idx * 2 + 1]; + for (var i = 0; i < len; i++) { + out[i] = out[i] || []; + out[i][0] = this._flatCoords[offset + i * 2]; + out[i][1] = this._flatCoords[offset + i * 2 + 1]; + } + return len; + } + else { + var coords = this._getCoordsFromItemModel(idx); + for (var i = 0; i < coords.length; i++) { + out[i] = out[i] || []; + out[i][0] = coords[i][0]; + out[i][1] = coords[i][1]; + } + return coords.length; + } + }, + + _processFlatCoordsArray: function (data) { + var startOffset = 0; + if (this._flatCoords) { + startOffset = this._flatCoords.length; + } + // Stored as a typed array. In format + // Points Count(2) | x | y | x | y | Points Count(3) | x | y | x | y | x | y | + if (typeof data[0] === 'number') { + var len = data.length; + // Store offset and len of each segment + var coordsOffsetAndLenStorage = new Uint32Array(len); + var coordsStorage = new Float64Array(len); + var coordsCursor = 0; + var offsetCursor = 0; + var dataCount = 0; + for (var i = 0; i < len;) { + dataCount++; + var count = data[i++]; + // Offset + coordsOffsetAndLenStorage[offsetCursor++] = coordsCursor + startOffset; + // Len + coordsOffsetAndLenStorage[offsetCursor++] = count; + for (var k = 0; k < count; k++) { + var x = data[i++]; + var y = data[i++]; + coordsStorage[coordsCursor++] = x; + coordsStorage[coordsCursor++] = y; + + if (i > len) { + if (true) { + throw new Error('Invalid data format.'); + } + } + } + } + + return { + flatCoordsOffset: new Uint32Array(coordsOffsetAndLenStorage.buffer, 0, offsetCursor), + flatCoords: coordsStorage, + count: dataCount + }; + } + + return { + flatCoordsOffset: null, + flatCoords: null, + count: data.length + }; + }, + + getInitialData: function (option, ecModel) { + var lineData = new __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.List(['value'], this); + lineData.hasItemOption = false; + + lineData.initData(option.data, [], function (dataItem, dimName, dataIndex, dimIndex) { + // dataItem is simply coords + if (dataItem instanceof Array) { + return NaN; + } + else { + lineData.hasItemOption = true; + var value = dataItem.value; + if (value != null) { + return value instanceof Array ? value[dimIndex] : value; + } + } + }); + + return lineData; + }, + + defaultOption: { + coordinateSystem: 'geo', + zlevel: 10, + + progressive: 1e4, + progressiveThreshold: 5e4, + + // Cartesian coordinate system + // xAxisIndex: 0, + // yAxisIndex: 0, + + // Geo coordinate system + // geoIndex: 0, + + // Support source-over, lighter + blendMode: 'source-over', + + lineStyle: { + opacity: 0.8 + }, + + postEffect: { + enable: false, + colorCorrection: { + exposure: 0, + brightness: 0, + contrast: 1, + saturation: 1, + enable: true + } + } + } +}); + +/***/ }), +/* 283 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__ = __webpack_require__(1); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__core_ViewGL__ = __webpack_require__(22); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__util_geometry_Lines2D__ = __webpack_require__(105); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4__common_GLViewHelper__ = __webpack_require__(103); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_5__util_retrieve__ = __webpack_require__(2); + + + + + + + + +__WEBPACK_IMPORTED_MODULE_0_echarts_lib_echarts___default.a.extendChartView({ + + type: 'linesGL', + + __ecgl__: true, + + init: function (ecModel, api) { + this.groupGL = new __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].Node(); + this.viewGL = new __WEBPACK_IMPORTED_MODULE_2__core_ViewGL__["a" /* default */]('orthographic'); + this.viewGL.add(this.groupGL); + + this._glViewHelper = new __WEBPACK_IMPORTED_MODULE_4__common_GLViewHelper__["a" /* default */](this.viewGL); + + this._nativeLinesShader = __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].createShader('ecgl.lines3D'); + this._meshLinesShader = __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].createShader('ecgl.meshLines3D'); + + this._linesMeshes = []; + this._currentStep = 0; + }, + + render: function (seriesModel, ecModel, api) { + this.groupGL.removeAll(); + this._glViewHelper.reset(seriesModel, api); + + var linesMesh = this._linesMeshes[0]; + if (!linesMesh) { + linesMesh = this._linesMeshes[0] = this._createLinesMesh(seriesModel); + } + this._linesMeshes.length = 1; + + this.groupGL.add(linesMesh); + this._updateLinesMesh(seriesModel, linesMesh, 0, seriesModel.getData().count()); + + this.viewGL.setPostEffect(seriesModel.getModel('postEffect'), api); + }, + + incrementalPrepareRender: function (seriesModel, ecModel, api) { + this.groupGL.removeAll(); + this._glViewHelper.reset(seriesModel, api); + + this._currentStep = 0; + + this.viewGL.setPostEffect(seriesModel.getModel('postEffect'), api); + }, + + incrementalRender: function (params, seriesModel, ecModel, api) { + var linesMesh = this._linesMeshes[this._currentStep]; + if (!linesMesh) { + linesMesh = this._createLinesMesh(seriesModel); + this._linesMeshes[this._currentStep] = linesMesh; + } + this._updateLinesMesh(seriesModel, linesMesh, params.start, params.end); + this.groupGL.add(linesMesh); + api.getZr().refresh(); + + this._currentStep++; + }, + + updateTransform: function (seriesModel, ecModel, api) { + if (seriesModel.coordinateSystem.getRoamTransform) { + this._glViewHelper.updateTransform(seriesModel, api); + } + }, + + _createLinesMesh: function (seriesModel) { + var linesMesh = new __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].Mesh({ + $ignorePicking: true, + material: new __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].Material({ + shader: __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].createShader('ecgl.lines3D'), + transparent: true, + depthMask: false, + depthTest: false + }), + geometry: new __WEBPACK_IMPORTED_MODULE_3__util_geometry_Lines2D__["a" /* default */]({ + segmentScale: 10, + useNativeLine: true, + dynamic: false + }), + mode: __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].Mesh.LINES, + culling: false + }); + + return linesMesh; + }, + + _updateLinesMesh: function (seriesModel, linesMesh, start, end) { + var data = seriesModel.getData(); + linesMesh.material.blend = seriesModel.get('blendMode') === 'lighter' + ? __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].additiveBlend : null; + var curveness = seriesModel.get('lineStyle.curveness') || 0; + var isPolyline = seriesModel.get('polyline'); + var geometry = linesMesh.geometry; + var coordSys = seriesModel.coordinateSystem; + + var lineWidth = __WEBPACK_IMPORTED_MODULE_5__util_retrieve__["a" /* default */].firstNotNull(seriesModel.get('lineStyle.width'), 1); + + if (lineWidth > 1) { + if (linesMesh.material.shader !== this._meshLinesShader) { + linesMesh.material.attachShader(this._meshLinesShader); + } + linesMesh.mode = __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].Mesh.TRIANGLES; + } + else { + if (linesMesh.material.shader !== this._nativeLinesShader) { + linesMesh.material.attachShader(this._nativeLinesShader); + } + linesMesh.mode = __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].Mesh.LINES; + } + + start = start || 0; + end = end || data.count(); + + geometry.resetOffset(); + var vertexCount = 0; + var triangleCount = 0; + var p0 = []; + var p1 = []; + var p2 = []; + var p3 = []; + + var lineCoords = []; + + var t = 0.3; + var t2 = 0.7; + + function updateBezierControlPoints() { + p1[0] = (p0[0] * t2 + p3[0] * t) - (p0[1] - p3[1]) * curveness; + p1[1] = (p0[1] * t2 + p3[1] * t) - (p3[0] - p0[0]) * curveness; + p2[0] = (p0[0] * t + p3[0] * t2) - (p0[1] - p3[1]) * curveness; + p2[1] = (p0[1] * t + p3[1] * t2) - (p3[0] - p0[0]) * curveness; + } + if (isPolyline || curveness !== 0) { + for (var idx = start; idx < end; idx++) { + if (isPolyline) { + var count = seriesModel.getLineCoordsCount(idx); + vertexCount += geometry.getPolylineVertexCount(count); + triangleCount += geometry.getPolylineTriangleCount(count); + } + else { + seriesModel.getLineCoords(idx, lineCoords); + this._glViewHelper.dataToPoint(coordSys, lineCoords[0], p0); + this._glViewHelper.dataToPoint(coordSys, lineCoords[1], p3); + updateBezierControlPoints(); + + vertexCount += geometry.getCubicCurveVertexCount(p0, p1, p2, p3); + triangleCount += geometry.getCubicCurveTriangleCount(p0, p1, p2, p3); + } + } + } + else { + var lineCount = end - start; + vertexCount += lineCount * geometry.getLineVertexCount(); + triangleCount += lineCount * geometry.getLineVertexCount(); + } + geometry.setVertexCount(vertexCount); + geometry.setTriangleCount(triangleCount); + + var dataIndex = start; + var colorArr = []; + for (var idx = start; idx < end; idx++) { + __WEBPACK_IMPORTED_MODULE_1__util_graphicGL__["a" /* default */].parseColor(data.getItemVisual(dataIndex, 'color'), colorArr); + var opacity = __WEBPACK_IMPORTED_MODULE_5__util_retrieve__["a" /* default */].firstNotNull(data.getItemVisual(dataIndex, 'opacity'), 1); + colorArr[3] *= opacity; + + var count = seriesModel.getLineCoords(idx, lineCoords); + for (var k = 0; k < count; k++) { + this._glViewHelper.dataToPoint(coordSys, lineCoords[k], lineCoords[k]); + } + + if (isPolyline) { + geometry.addPolyline(lineCoords, colorArr, lineWidth, 0, count); + } + else if (curveness !== 0) { + p0 = lineCoords[0]; + p3 = lineCoords[1]; + updateBezierControlPoints(); + geometry.addCubicCurve(p0, p1, p2, p3, colorArr, lineWidth); + } + else { + geometry.addPolyline(lineCoords, colorArr, lineWidth, 0, 2); + } + dataIndex++; + } + }, + + dispose: function () { + this.groupGL.removeAll(); + }, + + remove: function () { + this.groupGL.removeAll(); + } +}); + +/***/ }) +/******/ ]); +}); \ No newline at end of file diff --git "a/web/114 HELLO\345\205\261\344\272\253\345\215\225\350\275\246\350\277\220\350\220\245\347\256\241\347\220\206\345\271\263\345\217\260/js/echarts.js" "b/web/114 HELLO\345\205\261\344\272\253\345\215\225\350\275\246\350\277\220\350\220\245\347\256\241\347\220\206\345\271\263\345\217\260/js/echarts.js" new file mode 100644 index 00000000..3d7ffca2 --- /dev/null +++ "b/web/114 HELLO\345\205\261\344\272\253\345\215\225\350\275\246\350\277\220\350\220\245\347\256\241\347\220\206\345\271\263\345\217\260/js/echarts.js" @@ -0,0 +1,93938 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : + typeof define === 'function' && define.amd ? define(['exports'], factory) : + (factory((global.echarts = {}))); +}(this, (function (exports) { 'use strict'; + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +// (1) The code `if (__DEV__) ...` can be removed by build tool. +// (2) If intend to use `__DEV__`, this module should be imported. Use a global +// variable `__DEV__` may cause that miss the declaration (see #6535), or the +// declaration is behind of the using position (for example in `Model.extent`, +// And tools like rollup can not analysis the dependency if not import). + +var dev; + +// In browser +if (typeof window !== 'undefined') { + dev = window.__DEV__; +} +// In node +else if (typeof global !== 'undefined') { + dev = global.__DEV__; +} + +if (typeof dev === 'undefined') { + dev = true; +} + +var __DEV__ = dev; + +/** + * zrender: 生成唯一id + * + * @author errorrik (errorrik@gmail.com) + */ + +var idStart = 0x0907; + +var guid = function () { + return idStart++; +}; + +/** + * echarts设备环境识别 + * + * @desc echarts基于Canvas,纯Javascript图表库,提供直观,生动,可交互,可个性化定制的数据统计图表。 + * @author firede[firede@firede.us] + * @desc thanks zepto. + */ + +var env = {}; + +if (typeof wx === 'object' && typeof wx.getSystemInfoSync === 'function') { + // In Weixin Application + env = { + browser: {}, + os: {}, + node: false, + wxa: true, // Weixin Application + canvasSupported: true, + svgSupported: false, + touchEventsSupported: true, + domSupported: false + }; +} +else if (typeof document === 'undefined' && typeof self !== 'undefined') { + // In worker + env = { + browser: {}, + os: {}, + node: false, + worker: true, + canvasSupported: true, + domSupported: false + }; +} +else if (typeof navigator === 'undefined') { + // In node + env = { + browser: {}, + os: {}, + node: true, + worker: false, + // Assume canvas is supported + canvasSupported: true, + svgSupported: true, + domSupported: false + }; +} +else { + env = detect(navigator.userAgent); +} + +var env$1 = env; + +// Zepto.js +// (c) 2010-2013 Thomas Fuchs +// Zepto.js may be freely distributed under the MIT license. + +function detect(ua) { + var os = {}; + var browser = {}; + // var webkit = ua.match(/Web[kK]it[\/]{0,1}([\d.]+)/); + // var android = ua.match(/(Android);?[\s\/]+([\d.]+)?/); + // var ipad = ua.match(/(iPad).*OS\s([\d_]+)/); + // var ipod = ua.match(/(iPod)(.*OS\s([\d_]+))?/); + // var iphone = !ipad && ua.match(/(iPhone\sOS)\s([\d_]+)/); + // var webos = ua.match(/(webOS|hpwOS)[\s\/]([\d.]+)/); + // var touchpad = webos && ua.match(/TouchPad/); + // var kindle = ua.match(/Kindle\/([\d.]+)/); + // var silk = ua.match(/Silk\/([\d._]+)/); + // var blackberry = ua.match(/(BlackBerry).*Version\/([\d.]+)/); + // var bb10 = ua.match(/(BB10).*Version\/([\d.]+)/); + // var rimtabletos = ua.match(/(RIM\sTablet\sOS)\s([\d.]+)/); + // var playbook = ua.match(/PlayBook/); + // var chrome = ua.match(/Chrome\/([\d.]+)/) || ua.match(/CriOS\/([\d.]+)/); + var firefox = ua.match(/Firefox\/([\d.]+)/); + // var safari = webkit && ua.match(/Mobile\//) && !chrome; + // var webview = ua.match(/(iPhone|iPod|iPad).*AppleWebKit(?!.*Safari)/) && !chrome; + var ie = ua.match(/MSIE\s([\d.]+)/) + // IE 11 Trident/7.0; rv:11.0 + || ua.match(/Trident\/.+?rv:(([\d.]+))/); + var edge = ua.match(/Edge\/([\d.]+)/); // IE 12 and 12+ + + var weChat = (/micromessenger/i).test(ua); + + // Todo: clean this up with a better OS/browser seperation: + // - discern (more) between multiple browsers on android + // - decide if kindle fire in silk mode is android or not + // - Firefox on Android doesn't specify the Android version + // - possibly devide in os, device and browser hashes + + // if (browser.webkit = !!webkit) browser.version = webkit[1]; + + // if (android) os.android = true, os.version = android[2]; + // if (iphone && !ipod) os.ios = os.iphone = true, os.version = iphone[2].replace(/_/g, '.'); + // if (ipad) os.ios = os.ipad = true, os.version = ipad[2].replace(/_/g, '.'); + // if (ipod) os.ios = os.ipod = true, os.version = ipod[3] ? ipod[3].replace(/_/g, '.') : null; + // if (webos) os.webos = true, os.version = webos[2]; + // if (touchpad) os.touchpad = true; + // if (blackberry) os.blackberry = true, os.version = blackberry[2]; + // if (bb10) os.bb10 = true, os.version = bb10[2]; + // if (rimtabletos) os.rimtabletos = true, os.version = rimtabletos[2]; + // if (playbook) browser.playbook = true; + // if (kindle) os.kindle = true, os.version = kindle[1]; + // if (silk) browser.silk = true, browser.version = silk[1]; + // if (!silk && os.android && ua.match(/Kindle Fire/)) browser.silk = true; + // if (chrome) browser.chrome = true, browser.version = chrome[1]; + if (firefox) { + browser.firefox = true; + browser.version = firefox[1]; + } + // if (safari && (ua.match(/Safari/) || !!os.ios)) browser.safari = true; + // if (webview) browser.webview = true; + + if (ie) { + browser.ie = true; + browser.version = ie[1]; + } + + if (edge) { + browser.edge = true; + browser.version = edge[1]; + } + + // It is difficult to detect WeChat in Win Phone precisely, because ua can + // not be set on win phone. So we do not consider Win Phone. + if (weChat) { + browser.weChat = true; + } + + // os.tablet = !!(ipad || playbook || (android && !ua.match(/Mobile/)) || + // (firefox && ua.match(/Tablet/)) || (ie && !ua.match(/Phone/) && ua.match(/Touch/))); + // os.phone = !!(!os.tablet && !os.ipod && (android || iphone || webos || + // (chrome && ua.match(/Android/)) || (chrome && ua.match(/CriOS\/([\d.]+)/)) || + // (firefox && ua.match(/Mobile/)) || (ie && ua.match(/Touch/)))); + + return { + browser: browser, + os: os, + node: false, + // 原生canvas支持,改极端点了 + // canvasSupported : !(browser.ie && parseFloat(browser.version) < 9) + canvasSupported: !!document.createElement('canvas').getContext, + svgSupported: typeof SVGRect !== 'undefined', + // works on most browsers + // IE10/11 does not support touch event, and MS Edge supports them but not by + // default, so we dont check navigator.maxTouchPoints for them here. + touchEventsSupported: 'ontouchstart' in window && !browser.ie && !browser.edge, + // . + pointerEventsSupported: 'onpointerdown' in window + // Firefox supports pointer but not by default, only MS browsers are reliable on pointer + // events currently. So we dont use that on other browsers unless tested sufficiently. + // Although IE 10 supports pointer event, it use old style and is different from the + // standard. So we exclude that. (IE 10 is hardly used on touch device) + && (browser.edge || (browser.ie && browser.version >= 11)), + // passiveSupported: detectPassiveSupport() + domSupported: typeof document !== 'undefined' + }; +} + +// See https://github.com/WICG/EventListenerOptions/blob/gh-pages/explainer.md#feature-detection +// function detectPassiveSupport() { +// // Test via a getter in the options object to see if the passive property is accessed +// var supportsPassive = false; +// try { +// var opts = Object.defineProperty({}, 'passive', { +// get: function() { +// supportsPassive = true; +// } +// }); +// window.addEventListener('testPassive', function() {}, opts); +// } catch (e) { +// } +// return supportsPassive; +// } + +/** + * @module zrender/core/util + */ + +// 用于处理merge时无法遍历Date等对象的问题 +var BUILTIN_OBJECT = { + '[object Function]': 1, + '[object RegExp]': 1, + '[object Date]': 1, + '[object Error]': 1, + '[object CanvasGradient]': 1, + '[object CanvasPattern]': 1, + // For node-canvas + '[object Image]': 1, + '[object Canvas]': 1 +}; + +var TYPED_ARRAY = { + '[object Int8Array]': 1, + '[object Uint8Array]': 1, + '[object Uint8ClampedArray]': 1, + '[object Int16Array]': 1, + '[object Uint16Array]': 1, + '[object Int32Array]': 1, + '[object Uint32Array]': 1, + '[object Float32Array]': 1, + '[object Float64Array]': 1 +}; + +var objToString = Object.prototype.toString; + +var arrayProto = Array.prototype; +var nativeForEach = arrayProto.forEach; +var nativeFilter = arrayProto.filter; +var nativeSlice = arrayProto.slice; +var nativeMap = arrayProto.map; +var nativeReduce = arrayProto.reduce; + +// Avoid assign to an exported variable, for transforming to cjs. +var methods = {}; + +function $override(name, fn) { + // Clear ctx instance for different environment + if (name === 'createCanvas') { + _ctx = null; + } + + methods[name] = fn; +} + +/** + * Those data types can be cloned: + * Plain object, Array, TypedArray, number, string, null, undefined. + * Those data types will be assgined using the orginal data: + * BUILTIN_OBJECT + * Instance of user defined class will be cloned to a plain object, without + * properties in prototype. + * Other data types is not supported (not sure what will happen). + * + * Caution: do not support clone Date, for performance consideration. + * (There might be a large number of date in `series.data`). + * So date should not be modified in and out of echarts. + * + * @param {*} source + * @return {*} new + */ +function clone(source) { + if (source == null || typeof source !== 'object') { + return source; + } + + var result = source; + var typeStr = objToString.call(source); + + if (typeStr === '[object Array]') { + if (!isPrimitive(source)) { + result = []; + for (var i = 0, len = source.length; i < len; i++) { + result[i] = clone(source[i]); + } + } + } + else if (TYPED_ARRAY[typeStr]) { + if (!isPrimitive(source)) { + var Ctor = source.constructor; + if (source.constructor.from) { + result = Ctor.from(source); + } + else { + result = new Ctor(source.length); + for (var i = 0, len = source.length; i < len; i++) { + result[i] = clone(source[i]); + } + } + } + } + else if (!BUILTIN_OBJECT[typeStr] && !isPrimitive(source) && !isDom(source)) { + result = {}; + for (var key in source) { + if (source.hasOwnProperty(key)) { + result[key] = clone(source[key]); + } + } + } + + return result; +} + +/** + * @memberOf module:zrender/core/util + * @param {*} target + * @param {*} source + * @param {boolean} [overwrite=false] + */ +function merge(target, source, overwrite) { + // We should escapse that source is string + // and enter for ... in ... + if (!isObject$1(source) || !isObject$1(target)) { + return overwrite ? clone(source) : target; + } + + for (var key in source) { + if (source.hasOwnProperty(key)) { + var targetProp = target[key]; + var sourceProp = source[key]; + + if (isObject$1(sourceProp) + && isObject$1(targetProp) + && !isArray(sourceProp) + && !isArray(targetProp) + && !isDom(sourceProp) + && !isDom(targetProp) + && !isBuiltInObject(sourceProp) + && !isBuiltInObject(targetProp) + && !isPrimitive(sourceProp) + && !isPrimitive(targetProp) + ) { + // 如果需要递归覆盖,就递归调用merge + merge(targetProp, sourceProp, overwrite); + } + else if (overwrite || !(key in target)) { + // 否则只处理overwrite为true,或者在目标对象中没有此属性的情况 + // NOTE,在 target[key] 不存在的时候也是直接覆盖 + target[key] = clone(source[key], true); + } + } + } + + return target; +} + +/** + * @param {Array} targetAndSources The first item is target, and the rests are source. + * @param {boolean} [overwrite=false] + * @return {*} target + */ +function mergeAll(targetAndSources, overwrite) { + var result = targetAndSources[0]; + for (var i = 1, len = targetAndSources.length; i < len; i++) { + result = merge(result, targetAndSources[i], overwrite); + } + return result; +} + +/** + * @param {*} target + * @param {*} source + * @memberOf module:zrender/core/util + */ +function extend(target, source) { + for (var key in source) { + if (source.hasOwnProperty(key)) { + target[key] = source[key]; + } + } + return target; +} + +/** + * @param {*} target + * @param {*} source + * @param {boolean} [overlay=false] + * @memberOf module:zrender/core/util + */ +function defaults(target, source, overlay) { + for (var key in source) { + if (source.hasOwnProperty(key) + && (overlay ? source[key] != null : target[key] == null) + ) { + target[key] = source[key]; + } + } + return target; +} + +var createCanvas = function () { + return methods.createCanvas(); +}; + +methods.createCanvas = function () { + return document.createElement('canvas'); +}; + +// FIXME +var _ctx; + +function getContext() { + if (!_ctx) { + // Use util.createCanvas instead of createCanvas + // because createCanvas may be overwritten in different environment + _ctx = createCanvas().getContext('2d'); + } + return _ctx; +} + +/** + * 查询数组中元素的index + * @memberOf module:zrender/core/util + */ +function indexOf(array, value) { + if (array) { + if (array.indexOf) { + return array.indexOf(value); + } + for (var i = 0, len = array.length; i < len; i++) { + if (array[i] === value) { + return i; + } + } + } + return -1; +} + +/** + * 构造类继承关系 + * + * @memberOf module:zrender/core/util + * @param {Function} clazz 源类 + * @param {Function} baseClazz 基类 + */ +function inherits(clazz, baseClazz) { + var clazzPrototype = clazz.prototype; + function F() {} + F.prototype = baseClazz.prototype; + clazz.prototype = new F(); + + for (var prop in clazzPrototype) { + clazz.prototype[prop] = clazzPrototype[prop]; + } + clazz.prototype.constructor = clazz; + clazz.superClass = baseClazz; +} + +/** + * @memberOf module:zrender/core/util + * @param {Object|Function} target + * @param {Object|Function} sorce + * @param {boolean} overlay + */ +function mixin(target, source, overlay) { + target = 'prototype' in target ? target.prototype : target; + source = 'prototype' in source ? source.prototype : source; + + defaults(target, source, overlay); +} + +/** + * Consider typed array. + * @param {Array|TypedArray} data + */ +function isArrayLike(data) { + if (!data) { + return; + } + if (typeof data === 'string') { + return false; + } + return typeof data.length === 'number'; +} + +/** + * 数组或对象遍历 + * @memberOf module:zrender/core/util + * @param {Object|Array} obj + * @param {Function} cb + * @param {*} [context] + */ +function each$1(obj, cb, context) { + if (!(obj && cb)) { + return; + } + if (obj.forEach && obj.forEach === nativeForEach) { + obj.forEach(cb, context); + } + else if (obj.length === +obj.length) { + for (var i = 0, len = obj.length; i < len; i++) { + cb.call(context, obj[i], i, obj); + } + } + else { + for (var key in obj) { + if (obj.hasOwnProperty(key)) { + cb.call(context, obj[key], key, obj); + } + } + } +} + +/** + * 数组映射 + * @memberOf module:zrender/core/util + * @param {Array} obj + * @param {Function} cb + * @param {*} [context] + * @return {Array} + */ +function map(obj, cb, context) { + if (!(obj && cb)) { + return; + } + if (obj.map && obj.map === nativeMap) { + return obj.map(cb, context); + } + else { + var result = []; + for (var i = 0, len = obj.length; i < len; i++) { + result.push(cb.call(context, obj[i], i, obj)); + } + return result; + } +} + +/** + * @memberOf module:zrender/core/util + * @param {Array} obj + * @param {Function} cb + * @param {Object} [memo] + * @param {*} [context] + * @return {Array} + */ +function reduce(obj, cb, memo, context) { + if (!(obj && cb)) { + return; + } + if (obj.reduce && obj.reduce === nativeReduce) { + return obj.reduce(cb, memo, context); + } + else { + for (var i = 0, len = obj.length; i < len; i++) { + memo = cb.call(context, memo, obj[i], i, obj); + } + return memo; + } +} + +/** + * 数组过滤 + * @memberOf module:zrender/core/util + * @param {Array} obj + * @param {Function} cb + * @param {*} [context] + * @return {Array} + */ +function filter(obj, cb, context) { + if (!(obj && cb)) { + return; + } + if (obj.filter && obj.filter === nativeFilter) { + return obj.filter(cb, context); + } + else { + var result = []; + for (var i = 0, len = obj.length; i < len; i++) { + if (cb.call(context, obj[i], i, obj)) { + result.push(obj[i]); + } + } + return result; + } +} + +/** + * 数组项查找 + * @memberOf module:zrender/core/util + * @param {Array} obj + * @param {Function} cb + * @param {*} [context] + * @return {*} + */ +function find(obj, cb, context) { + if (!(obj && cb)) { + return; + } + for (var i = 0, len = obj.length; i < len; i++) { + if (cb.call(context, obj[i], i, obj)) { + return obj[i]; + } + } +} + +/** + * @memberOf module:zrender/core/util + * @param {Function} func + * @param {*} context + * @return {Function} + */ +function bind(func, context) { + var args = nativeSlice.call(arguments, 2); + return function () { + return func.apply(context, args.concat(nativeSlice.call(arguments))); + }; +} + +/** + * @memberOf module:zrender/core/util + * @param {Function} func + * @return {Function} + */ +function curry(func) { + var args = nativeSlice.call(arguments, 1); + return function () { + return func.apply(this, args.concat(nativeSlice.call(arguments))); + }; +} + +/** + * @memberOf module:zrender/core/util + * @param {*} value + * @return {boolean} + */ +function isArray(value) { + return objToString.call(value) === '[object Array]'; +} + +/** + * @memberOf module:zrender/core/util + * @param {*} value + * @return {boolean} + */ +function isFunction$1(value) { + return typeof value === 'function'; +} + +/** + * @memberOf module:zrender/core/util + * @param {*} value + * @return {boolean} + */ +function isString(value) { + return objToString.call(value) === '[object String]'; +} + +/** + * @memberOf module:zrender/core/util + * @param {*} value + * @return {boolean} + */ +function isObject$1(value) { + // Avoid a V8 JIT bug in Chrome 19-20. + // See https://code.google.com/p/v8/issues/detail?id=2291 for more details. + var type = typeof value; + return type === 'function' || (!!value && type === 'object'); +} + +/** + * @memberOf module:zrender/core/util + * @param {*} value + * @return {boolean} + */ +function isBuiltInObject(value) { + return !!BUILTIN_OBJECT[objToString.call(value)]; +} + +/** + * @memberOf module:zrender/core/util + * @param {*} value + * @return {boolean} + */ +function isTypedArray(value) { + return !!TYPED_ARRAY[objToString.call(value)]; +} + +/** + * @memberOf module:zrender/core/util + * @param {*} value + * @return {boolean} + */ +function isDom(value) { + return typeof value === 'object' + && typeof value.nodeType === 'number' + && typeof value.ownerDocument === 'object'; +} + +/** + * Whether is exactly NaN. Notice isNaN('a') returns true. + * @param {*} value + * @return {boolean} + */ +function eqNaN(value) { + return value !== value; +} + +/** + * If value1 is not null, then return value1, otherwise judget rest of values. + * Low performance. + * @memberOf module:zrender/core/util + * @return {*} Final value + */ +function retrieve(values) { + for (var i = 0, len = arguments.length; i < len; i++) { + if (arguments[i] != null) { + return arguments[i]; + } + } +} + +function retrieve2(value0, value1) { + return value0 != null + ? value0 + : value1; +} + +function retrieve3(value0, value1, value2) { + return value0 != null + ? value0 + : value1 != null + ? value1 + : value2; +} + +/** + * @memberOf module:zrender/core/util + * @param {Array} arr + * @param {number} startIndex + * @param {number} endIndex + * @return {Array} + */ +function slice() { + return Function.call.apply(nativeSlice, arguments); +} + +/** + * Normalize css liked array configuration + * e.g. + * 3 => [3, 3, 3, 3] + * [4, 2] => [4, 2, 4, 2] + * [4, 3, 2] => [4, 3, 2, 3] + * @param {number|Array.} val + * @return {Array.} + */ +function normalizeCssArray(val) { + if (typeof (val) === 'number') { + return [val, val, val, val]; + } + var len = val.length; + if (len === 2) { + // vertical | horizontal + return [val[0], val[1], val[0], val[1]]; + } + else if (len === 3) { + // top | horizontal | bottom + return [val[0], val[1], val[2], val[1]]; + } + return val; +} + +/** + * @memberOf module:zrender/core/util + * @param {boolean} condition + * @param {string} message + */ +function assert$1(condition, message) { + if (!condition) { + throw new Error(message); + } +} + +/** + * @memberOf module:zrender/core/util + * @param {string} str string to be trimed + * @return {string} trimed string + */ +function trim(str) { + if (str == null) { + return null; + } + else if (typeof str.trim === 'function') { + return str.trim(); + } + else { + return str.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, ''); + } +} + +var primitiveKey = '__ec_primitive__'; +/** + * Set an object as primitive to be ignored traversing children in clone or merge + */ +function setAsPrimitive(obj) { + obj[primitiveKey] = true; +} + +function isPrimitive(obj) { + return obj[primitiveKey]; +} + +/** + * @constructor + * @param {Object} obj Only apply `ownProperty`. + */ +function HashMap(obj) { + var isArr = isArray(obj); + // Key should not be set on this, otherwise + // methods get/set/... may be overrided. + this.data = {}; + var thisMap = this; + + (obj instanceof HashMap) + ? obj.each(visit) + : (obj && each$1(obj, visit)); + + function visit(value, key) { + isArr ? thisMap.set(value, key) : thisMap.set(key, value); + } +} + +HashMap.prototype = { + constructor: HashMap, + // Do not provide `has` method to avoid defining what is `has`. + // (We usually treat `null` and `undefined` as the same, different + // from ES6 Map). + get: function (key) { + return this.data.hasOwnProperty(key) ? this.data[key] : null; + }, + set: function (key, value) { + // Comparing with invocation chaining, `return value` is more commonly + // used in this case: `var someVal = map.set('a', genVal());` + return (this.data[key] = value); + }, + // Although util.each can be performed on this hashMap directly, user + // should not use the exposed keys, who are prefixed. + each: function (cb, context) { + context !== void 0 && (cb = bind(cb, context)); + for (var key in this.data) { + this.data.hasOwnProperty(key) && cb(this.data[key], key); + } + }, + // Do not use this method if performance sensitive. + removeKey: function (key) { + delete this.data[key]; + } +}; + +function createHashMap(obj) { + return new HashMap(obj); +} + +function concatArray(a, b) { + var newArray = new a.constructor(a.length + b.length); + for (var i = 0; i < a.length; i++) { + newArray[i] = a[i]; + } + var offset = a.length; + for (i = 0; i < b.length; i++) { + newArray[i + offset] = b[i]; + } + return newArray; +} + + +function noop() {} + + +var zrUtil = (Object.freeze || Object)({ + $override: $override, + clone: clone, + merge: merge, + mergeAll: mergeAll, + extend: extend, + defaults: defaults, + createCanvas: createCanvas, + getContext: getContext, + indexOf: indexOf, + inherits: inherits, + mixin: mixin, + isArrayLike: isArrayLike, + each: each$1, + map: map, + reduce: reduce, + filter: filter, + find: find, + bind: bind, + curry: curry, + isArray: isArray, + isFunction: isFunction$1, + isString: isString, + isObject: isObject$1, + isBuiltInObject: isBuiltInObject, + isTypedArray: isTypedArray, + isDom: isDom, + eqNaN: eqNaN, + retrieve: retrieve, + retrieve2: retrieve2, + retrieve3: retrieve3, + slice: slice, + normalizeCssArray: normalizeCssArray, + assert: assert$1, + trim: trim, + setAsPrimitive: setAsPrimitive, + isPrimitive: isPrimitive, + createHashMap: createHashMap, + concatArray: concatArray, + noop: noop +}); + +var ArrayCtor = typeof Float32Array === 'undefined' + ? Array + : Float32Array; + +/** + * 创建一个向量 + * @param {number} [x=0] + * @param {number} [y=0] + * @return {Vector2} + */ +function create(x, y) { + var out = new ArrayCtor(2); + if (x == null) { + x = 0; + } + if (y == null) { + y = 0; + } + out[0] = x; + out[1] = y; + return out; +} + +/** + * 复制向量数据 + * @param {Vector2} out + * @param {Vector2} v + * @return {Vector2} + */ +function copy(out, v) { + out[0] = v[0]; + out[1] = v[1]; + return out; +} + +/** + * 克隆一个向量 + * @param {Vector2} v + * @return {Vector2} + */ +function clone$1(v) { + var out = new ArrayCtor(2); + out[0] = v[0]; + out[1] = v[1]; + return out; +} + +/** + * 设置向量的两个项 + * @param {Vector2} out + * @param {number} a + * @param {number} b + * @return {Vector2} 结果 + */ +function set(out, a, b) { + out[0] = a; + out[1] = b; + return out; +} + +/** + * 向量相加 + * @param {Vector2} out + * @param {Vector2} v1 + * @param {Vector2} v2 + */ +function add(out, v1, v2) { + out[0] = v1[0] + v2[0]; + out[1] = v1[1] + v2[1]; + return out; +} + +/** + * 向量缩放后相加 + * @param {Vector2} out + * @param {Vector2} v1 + * @param {Vector2} v2 + * @param {number} a + */ +function scaleAndAdd(out, v1, v2, a) { + out[0] = v1[0] + v2[0] * a; + out[1] = v1[1] + v2[1] * a; + return out; +} + +/** + * 向量相减 + * @param {Vector2} out + * @param {Vector2} v1 + * @param {Vector2} v2 + */ +function sub(out, v1, v2) { + out[0] = v1[0] - v2[0]; + out[1] = v1[1] - v2[1]; + return out; +} + +/** + * 向量长度 + * @param {Vector2} v + * @return {number} + */ +function len(v) { + return Math.sqrt(lenSquare(v)); +} +var length = len; // jshint ignore:line + +/** + * 向量长度平方 + * @param {Vector2} v + * @return {number} + */ +function lenSquare(v) { + return v[0] * v[0] + v[1] * v[1]; +} +var lengthSquare = lenSquare; + +/** + * 向量乘法 + * @param {Vector2} out + * @param {Vector2} v1 + * @param {Vector2} v2 + */ +function mul(out, v1, v2) { + out[0] = v1[0] * v2[0]; + out[1] = v1[1] * v2[1]; + return out; +} + +/** + * 向量除法 + * @param {Vector2} out + * @param {Vector2} v1 + * @param {Vector2} v2 + */ +function div(out, v1, v2) { + out[0] = v1[0] / v2[0]; + out[1] = v1[1] / v2[1]; + return out; +} + +/** + * 向量点乘 + * @param {Vector2} v1 + * @param {Vector2} v2 + * @return {number} + */ +function dot(v1, v2) { + return v1[0] * v2[0] + v1[1] * v2[1]; +} + +/** + * 向量缩放 + * @param {Vector2} out + * @param {Vector2} v + * @param {number} s + */ +function scale(out, v, s) { + out[0] = v[0] * s; + out[1] = v[1] * s; + return out; +} + +/** + * 向量归一化 + * @param {Vector2} out + * @param {Vector2} v + */ +function normalize(out, v) { + var d = len(v); + if (d === 0) { + out[0] = 0; + out[1] = 0; + } + else { + out[0] = v[0] / d; + out[1] = v[1] / d; + } + return out; +} + +/** + * 计算向量间距离 + * @param {Vector2} v1 + * @param {Vector2} v2 + * @return {number} + */ +function distance(v1, v2) { + return Math.sqrt( + (v1[0] - v2[0]) * (v1[0] - v2[0]) + + (v1[1] - v2[1]) * (v1[1] - v2[1]) + ); +} +var dist = distance; + +/** + * 向量距离平方 + * @param {Vector2} v1 + * @param {Vector2} v2 + * @return {number} + */ +function distanceSquare(v1, v2) { + return (v1[0] - v2[0]) * (v1[0] - v2[0]) + + (v1[1] - v2[1]) * (v1[1] - v2[1]); +} +var distSquare = distanceSquare; + +/** + * 求负向量 + * @param {Vector2} out + * @param {Vector2} v + */ +function negate(out, v) { + out[0] = -v[0]; + out[1] = -v[1]; + return out; +} + +/** + * 插值两个点 + * @param {Vector2} out + * @param {Vector2} v1 + * @param {Vector2} v2 + * @param {number} t + */ +function lerp(out, v1, v2, t) { + out[0] = v1[0] + t * (v2[0] - v1[0]); + out[1] = v1[1] + t * (v2[1] - v1[1]); + return out; +} + +/** + * 矩阵左乘向量 + * @param {Vector2} out + * @param {Vector2} v + * @param {Vector2} m + */ +function applyTransform(out, v, m) { + var x = v[0]; + var y = v[1]; + out[0] = m[0] * x + m[2] * y + m[4]; + out[1] = m[1] * x + m[3] * y + m[5]; + return out; +} + +/** + * 求两个向量最小值 + * @param {Vector2} out + * @param {Vector2} v1 + * @param {Vector2} v2 + */ +function min(out, v1, v2) { + out[0] = Math.min(v1[0], v2[0]); + out[1] = Math.min(v1[1], v2[1]); + return out; +} + +/** + * 求两个向量最大值 + * @param {Vector2} out + * @param {Vector2} v1 + * @param {Vector2} v2 + */ +function max(out, v1, v2) { + out[0] = Math.max(v1[0], v2[0]); + out[1] = Math.max(v1[1], v2[1]); + return out; +} + + +var vector = (Object.freeze || Object)({ + create: create, + copy: copy, + clone: clone$1, + set: set, + add: add, + scaleAndAdd: scaleAndAdd, + sub: sub, + len: len, + length: length, + lenSquare: lenSquare, + lengthSquare: lengthSquare, + mul: mul, + div: div, + dot: dot, + scale: scale, + normalize: normalize, + distance: distance, + dist: dist, + distanceSquare: distanceSquare, + distSquare: distSquare, + negate: negate, + lerp: lerp, + applyTransform: applyTransform, + min: min, + max: max +}); + +// TODO Draggable for group +// FIXME Draggable on element which has parent rotation or scale +function Draggable() { + + this.on('mousedown', this._dragStart, this); + this.on('mousemove', this._drag, this); + this.on('mouseup', this._dragEnd, this); + this.on('globalout', this._dragEnd, this); + // this._dropTarget = null; + // this._draggingTarget = null; + + // this._x = 0; + // this._y = 0; +} + +Draggable.prototype = { + + constructor: Draggable, + + _dragStart: function (e) { + var draggingTarget = e.target; + if (draggingTarget && draggingTarget.draggable) { + this._draggingTarget = draggingTarget; + draggingTarget.dragging = true; + this._x = e.offsetX; + this._y = e.offsetY; + + this.dispatchToElement(param(draggingTarget, e), 'dragstart', e.event); + } + }, + + _drag: function (e) { + var draggingTarget = this._draggingTarget; + if (draggingTarget) { + + var x = e.offsetX; + var y = e.offsetY; + + var dx = x - this._x; + var dy = y - this._y; + this._x = x; + this._y = y; + + draggingTarget.drift(dx, dy, e); + this.dispatchToElement(param(draggingTarget, e), 'drag', e.event); + + var dropTarget = this.findHover(x, y, draggingTarget).target; + var lastDropTarget = this._dropTarget; + this._dropTarget = dropTarget; + + if (draggingTarget !== dropTarget) { + if (lastDropTarget && dropTarget !== lastDropTarget) { + this.dispatchToElement(param(lastDropTarget, e), 'dragleave', e.event); + } + if (dropTarget && dropTarget !== lastDropTarget) { + this.dispatchToElement(param(dropTarget, e), 'dragenter', e.event); + } + } + } + }, + + _dragEnd: function (e) { + var draggingTarget = this._draggingTarget; + + if (draggingTarget) { + draggingTarget.dragging = false; + } + + this.dispatchToElement(param(draggingTarget, e), 'dragend', e.event); + + if (this._dropTarget) { + this.dispatchToElement(param(this._dropTarget, e), 'drop', e.event); + } + + this._draggingTarget = null; + this._dropTarget = null; + } + +}; + +function param(target, e) { + return {target: target, topTarget: e && e.topTarget}; +} + +/** + * Event Mixin + * @module zrender/mixin/Eventful + * @author Kener (@Kener-林峰, kener.linfeng@gmail.com) + * pissang (https://www.github.com/pissang) + */ + +var arrySlice = Array.prototype.slice; + +/** + * Event dispatcher. + * + * @alias module:zrender/mixin/Eventful + * @constructor + * @param {Object} [eventProcessor] The object eventProcessor is the scope when + * `eventProcessor.xxx` called. + * @param {Function} [eventProcessor.normalizeQuery] + * param: {string|Object} Raw query. + * return: {string|Object} Normalized query. + * @param {Function} [eventProcessor.filter] Event will be dispatched only + * if it returns `true`. + * param: {string} eventType + * param: {string|Object} query + * return: {boolean} + * @param {Function} [eventProcessor.afterTrigger] Call after all handlers called. + * param: {string} eventType + */ +var Eventful = function (eventProcessor) { + this._$handlers = {}; + this._$eventProcessor = eventProcessor; +}; + +Eventful.prototype = { + + constructor: Eventful, + + /** + * The handler can only be triggered once, then removed. + * + * @param {string} event The event name. + * @param {string|Object} [query] Condition used on event filter. + * @param {Function} handler The event handler. + * @param {Object} context + */ + one: function (event, query, handler, context) { + return on(this, event, query, handler, context, true); + }, + + /** + * Bind a handler. + * + * @param {string} event The event name. + * @param {string|Object} [query] Condition used on event filter. + * @param {Function} handler The event handler. + * @param {Object} [context] + */ + on: function (event, query, handler, context) { + return on(this, event, query, handler, context, false); + }, + + /** + * Whether any handler has bound. + * + * @param {string} event + * @return {boolean} + */ + isSilent: function (event) { + var _h = this._$handlers; + return !_h[event] || !_h[event].length; + }, + + /** + * Unbind a event. + * + * @param {string} event The event name. + * @param {Function} [handler] The event handler. + */ + off: function (event, handler) { + var _h = this._$handlers; + + if (!event) { + this._$handlers = {}; + return this; + } + + if (handler) { + if (_h[event]) { + var newList = []; + for (var i = 0, l = _h[event].length; i < l; i++) { + if (_h[event][i].h !== handler) { + newList.push(_h[event][i]); + } + } + _h[event] = newList; + } + + if (_h[event] && _h[event].length === 0) { + delete _h[event]; + } + } + else { + delete _h[event]; + } + + return this; + }, + + /** + * Dispatch a event. + * + * @param {string} type The event name. + */ + trigger: function (type) { + var _h = this._$handlers[type]; + var eventProcessor = this._$eventProcessor; + + if (_h) { + var args = arguments; + var argLen = args.length; + + if (argLen > 3) { + args = arrySlice.call(args, 1); + } + + var len = _h.length; + for (var i = 0; i < len;) { + var hItem = _h[i]; + if (eventProcessor + && eventProcessor.filter + && hItem.query != null + && !eventProcessor.filter(type, hItem.query) + ) { + i++; + continue; + } + + // Optimize advise from backbone + switch (argLen) { + case 1: + hItem.h.call(hItem.ctx); + break; + case 2: + hItem.h.call(hItem.ctx, args[1]); + break; + case 3: + hItem.h.call(hItem.ctx, args[1], args[2]); + break; + default: + // have more than 2 given arguments + hItem.h.apply(hItem.ctx, args); + break; + } + + if (hItem.one) { + _h.splice(i, 1); + len--; + } + else { + i++; + } + } + } + + eventProcessor && eventProcessor.afterTrigger + && eventProcessor.afterTrigger(type); + + return this; + }, + + /** + * Dispatch a event with context, which is specified at the last parameter. + * + * @param {string} type The event name. + */ + triggerWithContext: function (type) { + var _h = this._$handlers[type]; + var eventProcessor = this._$eventProcessor; + + if (_h) { + var args = arguments; + var argLen = args.length; + + if (argLen > 4) { + args = arrySlice.call(args, 1, args.length - 1); + } + var ctx = args[args.length - 1]; + + var len = _h.length; + for (var i = 0; i < len;) { + var hItem = _h[i]; + if (eventProcessor + && eventProcessor.filter + && hItem.query != null + && !eventProcessor.filter(type, hItem.query) + ) { + i++; + continue; + } + + // Optimize advise from backbone + switch (argLen) { + case 1: + hItem.h.call(ctx); + break; + case 2: + hItem.h.call(ctx, args[1]); + break; + case 3: + hItem.h.call(ctx, args[1], args[2]); + break; + default: + // have more than 2 given arguments + hItem.h.apply(ctx, args); + break; + } + + if (hItem.one) { + _h.splice(i, 1); + len--; + } + else { + i++; + } + } + } + + eventProcessor && eventProcessor.afterTrigger + && eventProcessor.afterTrigger(type); + + return this; + } +}; + +function normalizeQuery(host, query) { + var eventProcessor = host._$eventProcessor; + if (query != null && eventProcessor && eventProcessor.normalizeQuery) { + query = eventProcessor.normalizeQuery(query); + } + return query; +} + +function on(eventful, event, query, handler, context, isOnce) { + var _h = eventful._$handlers; + + if (typeof query === 'function') { + context = handler; + handler = query; + query = null; + } + + if (!handler || !event) { + return eventful; + } + + query = normalizeQuery(eventful, query); + + if (!_h[event]) { + _h[event] = []; + } + + for (var i = 0; i < _h[event].length; i++) { + if (_h[event][i].h === handler) { + return eventful; + } + } + + var wrap = { + h: handler, + one: isOnce, + query: query, + ctx: context || eventful, + // FIXME + // Do not publish this feature util it is proved that it makes sense. + callAtLast: handler.zrEventfulCallAtLast + }; + + var lastIndex = _h[event].length - 1; + var lastWrap = _h[event][lastIndex]; + (lastWrap && lastWrap.callAtLast) + ? _h[event].splice(lastIndex, 0, wrap) + : _h[event].push(wrap); + + return eventful; +} + +/** + * 事件辅助类 + * @module zrender/core/event + * @author Kener (@Kener-林峰, kener.linfeng@gmail.com) + */ + +var isDomLevel2 = (typeof window !== 'undefined') && !!window.addEventListener; + +var MOUSE_EVENT_REG = /^(?:mouse|pointer|contextmenu|drag|drop)|click/; + +function getBoundingClientRect(el) { + // BlackBerry 5, iOS 3 (original iPhone) don't have getBoundingRect + return el.getBoundingClientRect ? el.getBoundingClientRect() : {left: 0, top: 0}; +} + +// `calculate` is optional, default false +function clientToLocal(el, e, out, calculate) { + out = out || {}; + + // According to the W3C Working Draft, offsetX and offsetY should be relative + // to the padding edge of the target element. The only browser using this convention + // is IE. Webkit uses the border edge, Opera uses the content edge, and FireFox does + // not support the properties. + // (see http://www.jacklmoore.com/notes/mouse-position/) + // In zr painter.dom, padding edge equals to border edge. + + // FIXME + // When mousemove event triggered on ec tooltip, target is not zr painter.dom, and + // offsetX/Y is relative to e.target, where the calculation of zrX/Y via offsetX/Y + // is too complex. So css-transfrom dont support in this case temporarily. + if (calculate || !env$1.canvasSupported) { + defaultGetZrXY(el, e, out); + } + // Caution: In FireFox, layerX/layerY Mouse position relative to the closest positioned + // ancestor element, so we should make sure el is positioned (e.g., not position:static). + // BTW1, Webkit don't return the same results as FF in non-simple cases (like add + // zoom-factor, overflow / opacity layers, transforms ...) + // BTW2, (ev.offsetY || ev.pageY - $(ev.target).offset().top) is not correct in preserve-3d. + // + // BTW3, In ff, offsetX/offsetY is always 0. + else if (env$1.browser.firefox && e.layerX != null && e.layerX !== e.offsetX) { + out.zrX = e.layerX; + out.zrY = e.layerY; + } + // For IE6+, chrome, safari, opera. (When will ff support offsetX?) + else if (e.offsetX != null) { + out.zrX = e.offsetX; + out.zrY = e.offsetY; + } + // For some other device, e.g., IOS safari. + else { + defaultGetZrXY(el, e, out); + } + + return out; +} + +function defaultGetZrXY(el, e, out) { + // This well-known method below does not support css transform. + var box = getBoundingClientRect(el); + out.zrX = e.clientX - box.left; + out.zrY = e.clientY - box.top; +} + +/** + * 如果存在第三方嵌入的一些dom触发的事件,或touch事件,需要转换一下事件坐标. + * `calculate` is optional, default false. + */ +function normalizeEvent(el, e, calculate) { + + e = e || window.event; + + if (e.zrX != null) { + return e; + } + + var eventType = e.type; + var isTouch = eventType && eventType.indexOf('touch') >= 0; + + if (!isTouch) { + clientToLocal(el, e, e, calculate); + e.zrDelta = (e.wheelDelta) ? e.wheelDelta / 120 : -(e.detail || 0) / 3; + } + else { + var touch = eventType !== 'touchend' + ? e.targetTouches[0] + : e.changedTouches[0]; + touch && clientToLocal(el, touch, e, calculate); + } + + // Add which for click: 1 === left; 2 === middle; 3 === right; otherwise: 0; + // See jQuery: https://github.com/jquery/jquery/blob/master/src/event.js + // If e.which has been defined, if may be readonly, + // see: https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/which + var button = e.button; + if (e.which == null && button !== undefined && MOUSE_EVENT_REG.test(e.type)) { + e.which = (button & 1 ? 1 : (button & 2 ? 3 : (button & 4 ? 2 : 0))); + } + // [Caution]: `e.which` from browser is not always reliable. For example, + // when press left button and `mousemove (pointermove)` in Edge, the `e.which` + // is 65536 and the `e.button` is -1. But the `mouseup (pointerup)` and + // `mousedown (pointerdown)` is the same as Chrome does. + + return e; +} + +/** + * @param {HTMLElement} el + * @param {string} name + * @param {Function} handler + */ +function addEventListener(el, name, handler) { + if (isDomLevel2) { + // Reproduct the console warning: + // [Violation] Added non-passive event listener to a scroll-blocking event. + // Consider marking event handler as 'passive' to make the page more responsive. + // Just set console log level: verbose in chrome dev tool. + // then the warning log will be printed when addEventListener called. + // See https://github.com/WICG/EventListenerOptions/blob/gh-pages/explainer.md + // We have not yet found a neat way to using passive. Because in zrender the dom event + // listener delegate all of the upper events of element. Some of those events need + // to prevent default. For example, the feature `preventDefaultMouseMove` of echarts. + // Before passive can be adopted, these issues should be considered: + // (1) Whether and how a zrender user specifies an event listener passive. And by default, + // passive or not. + // (2) How to tread that some zrender event listener is passive, and some is not. If + // we use other way but not preventDefault of mousewheel and touchmove, browser + // compatibility should be handled. + + // var opts = (env.passiveSupported && name === 'mousewheel') + // ? {passive: true} + // // By default, the third param of el.addEventListener is `capture: false`. + // : void 0; + // el.addEventListener(name, handler /* , opts */); + el.addEventListener(name, handler); + } + else { + el.attachEvent('on' + name, handler); + } +} + +function removeEventListener(el, name, handler) { + if (isDomLevel2) { + el.removeEventListener(name, handler); + } + else { + el.detachEvent('on' + name, handler); + } +} + +/** + * preventDefault and stopPropagation. + * Notice: do not do that in zrender. Upper application + * do that if necessary. + * + * @memberOf module:zrender/core/event + * @method + * @param {Event} e : event对象 + */ +var stop = isDomLevel2 + ? function (e) { + e.preventDefault(); + e.stopPropagation(); + e.cancelBubble = true; + } + : function (e) { + e.returnValue = false; + e.cancelBubble = true; + }; + +/** + * This method only works for mouseup and mousedown. The functionality is restricted + * for fault tolerance, See the `e.which` compatibility above. + * + * @param {MouseEvent} e + * @return {boolean} + */ +function isMiddleOrRightButtonOnMouseUpDown(e) { + return e.which === 2 || e.which === 3; +} + +/** + * To be removed. + * @deprecated + */ + +/** + * Only implements needed gestures for mobile. + */ + +var GestureMgr = function () { + + /** + * @private + * @type {Array.} + */ + this._track = []; +}; + +GestureMgr.prototype = { + + constructor: GestureMgr, + + recognize: function (event, target, root) { + this._doTrack(event, target, root); + return this._recognize(event); + }, + + clear: function () { + this._track.length = 0; + return this; + }, + + _doTrack: function (event, target, root) { + var touches = event.touches; + + if (!touches) { + return; + } + + var trackItem = { + points: [], + touches: [], + target: target, + event: event + }; + + for (var i = 0, len = touches.length; i < len; i++) { + var touch = touches[i]; + var pos = clientToLocal(root, touch, {}); + trackItem.points.push([pos.zrX, pos.zrY]); + trackItem.touches.push(touch); + } + + this._track.push(trackItem); + }, + + _recognize: function (event) { + for (var eventName in recognizers) { + if (recognizers.hasOwnProperty(eventName)) { + var gestureInfo = recognizers[eventName](this._track, event); + if (gestureInfo) { + return gestureInfo; + } + } + } + } +}; + +function dist$1(pointPair) { + var dx = pointPair[1][0] - pointPair[0][0]; + var dy = pointPair[1][1] - pointPair[0][1]; + + return Math.sqrt(dx * dx + dy * dy); +} + +function center(pointPair) { + return [ + (pointPair[0][0] + pointPair[1][0]) / 2, + (pointPair[0][1] + pointPair[1][1]) / 2 + ]; +} + +var recognizers = { + + pinch: function (track, event) { + var trackLen = track.length; + + if (!trackLen) { + return; + } + + var pinchEnd = (track[trackLen - 1] || {}).points; + var pinchPre = (track[trackLen - 2] || {}).points || pinchEnd; + + if (pinchPre + && pinchPre.length > 1 + && pinchEnd + && pinchEnd.length > 1 + ) { + var pinchScale = dist$1(pinchEnd) / dist$1(pinchPre); + !isFinite(pinchScale) && (pinchScale = 1); + + event.pinchScale = pinchScale; + + var pinchCenter = center(pinchEnd); + event.pinchX = pinchCenter[0]; + event.pinchY = pinchCenter[1]; + + return { + type: 'pinch', + target: track[0].target, + event: event + }; + } + } + + // Only pinch currently. +}; + +var SILENT = 'silent'; + +function makeEventPacket(eveType, targetInfo, event) { + return { + type: eveType, + event: event, + // target can only be an element that is not silent. + target: targetInfo.target, + // topTarget can be a silent element. + topTarget: targetInfo.topTarget, + cancelBubble: false, + offsetX: event.zrX, + offsetY: event.zrY, + gestureEvent: event.gestureEvent, + pinchX: event.pinchX, + pinchY: event.pinchY, + pinchScale: event.pinchScale, + wheelDelta: event.zrDelta, + zrByTouch: event.zrByTouch, + which: event.which, + stop: stopEvent + }; +} + +function stopEvent(event) { + stop(this.event); +} + +function EmptyProxy() {} +EmptyProxy.prototype.dispose = function () {}; + +var handlerNames = [ + 'click', 'dblclick', 'mousewheel', 'mouseout', + 'mouseup', 'mousedown', 'mousemove', 'contextmenu' +]; +/** + * @alias module:zrender/Handler + * @constructor + * @extends module:zrender/mixin/Eventful + * @param {module:zrender/Storage} storage Storage instance. + * @param {module:zrender/Painter} painter Painter instance. + * @param {module:zrender/dom/HandlerProxy} proxy HandlerProxy instance. + * @param {HTMLElement} painterRoot painter.root (not painter.getViewportRoot()). + */ +var Handler = function (storage, painter, proxy, painterRoot) { + Eventful.call(this); + + this.storage = storage; + + this.painter = painter; + + this.painterRoot = painterRoot; + + proxy = proxy || new EmptyProxy(); + + /** + * Proxy of event. can be Dom, WebGLSurface, etc. + */ + this.proxy = null; + + /** + * {target, topTarget, x, y} + * @private + * @type {Object} + */ + this._hovered = {}; + + /** + * @private + * @type {Date} + */ + this._lastTouchMoment; + + /** + * @private + * @type {number} + */ + this._lastX; + + /** + * @private + * @type {number} + */ + this._lastY; + + /** + * @private + * @type {module:zrender/core/GestureMgr} + */ + this._gestureMgr; + + + Draggable.call(this); + + this.setHandlerProxy(proxy); +}; + +Handler.prototype = { + + constructor: Handler, + + setHandlerProxy: function (proxy) { + if (this.proxy) { + this.proxy.dispose(); + } + + if (proxy) { + each$1(handlerNames, function (name) { + proxy.on && proxy.on(name, this[name], this); + }, this); + // Attach handler + proxy.handler = this; + } + this.proxy = proxy; + }, + + mousemove: function (event) { + var x = event.zrX; + var y = event.zrY; + + var lastHovered = this._hovered; + var lastHoveredTarget = lastHovered.target; + + // If lastHoveredTarget is removed from zr (detected by '__zr') by some API call + // (like 'setOption' or 'dispatchAction') in event handlers, we should find + // lastHovered again here. Otherwise 'mouseout' can not be triggered normally. + // See #6198. + if (lastHoveredTarget && !lastHoveredTarget.__zr) { + lastHovered = this.findHover(lastHovered.x, lastHovered.y); + lastHoveredTarget = lastHovered.target; + } + + var hovered = this._hovered = this.findHover(x, y); + var hoveredTarget = hovered.target; + + var proxy = this.proxy; + proxy.setCursor && proxy.setCursor(hoveredTarget ? hoveredTarget.cursor : 'default'); + + // Mouse out on previous hovered element + if (lastHoveredTarget && hoveredTarget !== lastHoveredTarget) { + this.dispatchToElement(lastHovered, 'mouseout', event); + } + + // Mouse moving on one element + this.dispatchToElement(hovered, 'mousemove', event); + + // Mouse over on a new element + if (hoveredTarget && hoveredTarget !== lastHoveredTarget) { + this.dispatchToElement(hovered, 'mouseover', event); + } + }, + + mouseout: function (event) { + this.dispatchToElement(this._hovered, 'mouseout', event); + + // There might be some doms created by upper layer application + // at the same level of painter.getViewportRoot() (e.g., tooltip + // dom created by echarts), where 'globalout' event should not + // be triggered when mouse enters these doms. (But 'mouseout' + // should be triggered at the original hovered element as usual). + var element = event.toElement || event.relatedTarget; + var innerDom; + do { + element = element && element.parentNode; + } + while (element && element.nodeType !== 9 && !( + innerDom = element === this.painterRoot + )); + + !innerDom && this.trigger('globalout', {event: event}); + }, + + /** + * Resize + */ + resize: function (event) { + this._hovered = {}; + }, + + /** + * Dispatch event + * @param {string} eventName + * @param {event=} eventArgs + */ + dispatch: function (eventName, eventArgs) { + var handler = this[eventName]; + handler && handler.call(this, eventArgs); + }, + + /** + * Dispose + */ + dispose: function () { + + this.proxy.dispose(); + + this.storage = + this.proxy = + this.painter = null; + }, + + /** + * 设置默认的cursor style + * @param {string} [cursorStyle='default'] 例如 crosshair + */ + setCursorStyle: function (cursorStyle) { + var proxy = this.proxy; + proxy.setCursor && proxy.setCursor(cursorStyle); + }, + + /** + * 事件分发代理 + * + * @private + * @param {Object} targetInfo {target, topTarget} 目标图形元素 + * @param {string} eventName 事件名称 + * @param {Object} event 事件对象 + */ + dispatchToElement: function (targetInfo, eventName, event) { + targetInfo = targetInfo || {}; + var el = targetInfo.target; + if (el && el.silent) { + return; + } + var eventHandler = 'on' + eventName; + var eventPacket = makeEventPacket(eventName, targetInfo, event); + + while (el) { + el[eventHandler] + && (eventPacket.cancelBubble = el[eventHandler].call(el, eventPacket)); + + el.trigger(eventName, eventPacket); + + el = el.parent; + + if (eventPacket.cancelBubble) { + break; + } + } + + if (!eventPacket.cancelBubble) { + // 冒泡到顶级 zrender 对象 + this.trigger(eventName, eventPacket); + // 分发事件到用户自定义层 + // 用户有可能在全局 click 事件中 dispose,所以需要判断下 painter 是否存在 + this.painter && this.painter.eachOtherLayer(function (layer) { + if (typeof (layer[eventHandler]) === 'function') { + layer[eventHandler].call(layer, eventPacket); + } + if (layer.trigger) { + layer.trigger(eventName, eventPacket); + } + }); + } + }, + + /** + * @private + * @param {number} x + * @param {number} y + * @param {module:zrender/graphic/Displayable} exclude + * @return {model:zrender/Element} + * @method + */ + findHover: function (x, y, exclude) { + var list = this.storage.getDisplayList(); + var out = {x: x, y: y}; + + for (var i = list.length - 1; i >= 0; i--) { + var hoverCheckResult; + if (list[i] !== exclude + // getDisplayList may include ignored item in VML mode + && !list[i].ignore + && (hoverCheckResult = isHover(list[i], x, y)) + ) { + !out.topTarget && (out.topTarget = list[i]); + if (hoverCheckResult !== SILENT) { + out.target = list[i]; + break; + } + } + } + + return out; + }, + + processGesture: function (event, stage) { + if (!this._gestureMgr) { + this._gestureMgr = new GestureMgr(); + } + var gestureMgr = this._gestureMgr; + + stage === 'start' && gestureMgr.clear(); + + var gestureInfo = gestureMgr.recognize( + event, + this.findHover(event.zrX, event.zrY, null).target, + this.proxy.dom + ); + + stage === 'end' && gestureMgr.clear(); + + // Do not do any preventDefault here. Upper application do that if necessary. + if (gestureInfo) { + var type = gestureInfo.type; + event.gestureEvent = type; + + this.dispatchToElement({target: gestureInfo.target}, type, gestureInfo.event); + } + } +}; + +// Common handlers +each$1(['click', 'mousedown', 'mouseup', 'mousewheel', 'dblclick', 'contextmenu'], function (name) { + Handler.prototype[name] = function (event) { + // Find hover again to avoid click event is dispatched manually. Or click is triggered without mouseover + var hovered = this.findHover(event.zrX, event.zrY); + var hoveredTarget = hovered.target; + + if (name === 'mousedown') { + this._downEl = hoveredTarget; + this._downPoint = [event.zrX, event.zrY]; + // In case click triggered before mouseup + this._upEl = hoveredTarget; + } + else if (name === 'mouseup') { + this._upEl = hoveredTarget; + } + else if (name === 'click') { + if (this._downEl !== this._upEl + // Original click event is triggered on the whole canvas element, + // including the case that `mousedown` - `mousemove` - `mouseup`, + // which should be filtered, otherwise it will bring trouble to + // pan and zoom. + || !this._downPoint + // Arbitrary value + || dist(this._downPoint, [event.zrX, event.zrY]) > 4 + ) { + return; + } + this._downPoint = null; + } + + this.dispatchToElement(hovered, name, event); + }; +}); + +function isHover(displayable, x, y) { + if (displayable[displayable.rectHover ? 'rectContain' : 'contain'](x, y)) { + var el = displayable; + var isSilent; + while (el) { + // If clipped by ancestor. + // FIXME: If clipPath has neither stroke nor fill, + // el.clipPath.contain(x, y) will always return false. + if (el.clipPath && !el.clipPath.contain(x, y)) { + return false; + } + if (el.silent) { + isSilent = true; + } + el = el.parent; + } + return isSilent ? SILENT : true; + } + + return false; +} + +mixin(Handler, Eventful); +mixin(Handler, Draggable); + +/** + * 3x2矩阵操作类 + * @exports zrender/tool/matrix + */ + +var ArrayCtor$1 = typeof Float32Array === 'undefined' + ? Array + : Float32Array; + +/** + * Create a identity matrix. + * @return {Float32Array|Array.} + */ +function create$1() { + var out = new ArrayCtor$1(6); + identity(out); + + return out; +} + +/** + * 设置矩阵为单位矩阵 + * @param {Float32Array|Array.} out + */ +function identity(out) { + out[0] = 1; + out[1] = 0; + out[2] = 0; + out[3] = 1; + out[4] = 0; + out[5] = 0; + return out; +} + +/** + * 复制矩阵 + * @param {Float32Array|Array.} out + * @param {Float32Array|Array.} m + */ +function copy$1(out, m) { + out[0] = m[0]; + out[1] = m[1]; + out[2] = m[2]; + out[3] = m[3]; + out[4] = m[4]; + out[5] = m[5]; + return out; +} + +/** + * 矩阵相乘 + * @param {Float32Array|Array.} out + * @param {Float32Array|Array.} m1 + * @param {Float32Array|Array.} m2 + */ +function mul$1(out, m1, m2) { + // Consider matrix.mul(m, m2, m); + // where out is the same as m2. + // So use temp variable to escape error. + var out0 = m1[0] * m2[0] + m1[2] * m2[1]; + var out1 = m1[1] * m2[0] + m1[3] * m2[1]; + var out2 = m1[0] * m2[2] + m1[2] * m2[3]; + var out3 = m1[1] * m2[2] + m1[3] * m2[3]; + var out4 = m1[0] * m2[4] + m1[2] * m2[5] + m1[4]; + var out5 = m1[1] * m2[4] + m1[3] * m2[5] + m1[5]; + out[0] = out0; + out[1] = out1; + out[2] = out2; + out[3] = out3; + out[4] = out4; + out[5] = out5; + return out; +} + +/** + * 平移变换 + * @param {Float32Array|Array.} out + * @param {Float32Array|Array.} a + * @param {Float32Array|Array.} v + */ +function translate(out, a, v) { + out[0] = a[0]; + out[1] = a[1]; + out[2] = a[2]; + out[3] = a[3]; + out[4] = a[4] + v[0]; + out[5] = a[5] + v[1]; + return out; +} + +/** + * 旋转变换 + * @param {Float32Array|Array.} out + * @param {Float32Array|Array.} a + * @param {number} rad + */ +function rotate(out, a, rad) { + var aa = a[0]; + var ac = a[2]; + var atx = a[4]; + var ab = a[1]; + var ad = a[3]; + var aty = a[5]; + var st = Math.sin(rad); + var ct = Math.cos(rad); + + out[0] = aa * ct + ab * st; + out[1] = -aa * st + ab * ct; + out[2] = ac * ct + ad * st; + out[3] = -ac * st + ct * ad; + out[4] = ct * atx + st * aty; + out[5] = ct * aty - st * atx; + return out; +} + +/** + * 缩放变换 + * @param {Float32Array|Array.} out + * @param {Float32Array|Array.} a + * @param {Float32Array|Array.} v + */ +function scale$1(out, a, v) { + var vx = v[0]; + var vy = v[1]; + out[0] = a[0] * vx; + out[1] = a[1] * vy; + out[2] = a[2] * vx; + out[3] = a[3] * vy; + out[4] = a[4] * vx; + out[5] = a[5] * vy; + return out; +} + +/** + * 求逆矩阵 + * @param {Float32Array|Array.} out + * @param {Float32Array|Array.} a + */ +function invert(out, a) { + + var aa = a[0]; + var ac = a[2]; + var atx = a[4]; + var ab = a[1]; + var ad = a[3]; + var aty = a[5]; + + var det = aa * ad - ab * ac; + if (!det) { + return null; + } + det = 1.0 / det; + + out[0] = ad * det; + out[1] = -ab * det; + out[2] = -ac * det; + out[3] = aa * det; + out[4] = (ac * aty - ad * atx) * det; + out[5] = (ab * atx - aa * aty) * det; + return out; +} + +/** + * Clone a new matrix. + * @param {Float32Array|Array.} a + */ +function clone$2(a) { + var b = create$1(); + copy$1(b, a); + return b; +} + +var matrix = (Object.freeze || Object)({ + create: create$1, + identity: identity, + copy: copy$1, + mul: mul$1, + translate: translate, + rotate: rotate, + scale: scale$1, + invert: invert, + clone: clone$2 +}); + +/** + * 提供变换扩展 + * @module zrender/mixin/Transformable + * @author pissang (https://www.github.com/pissang) + */ + +var mIdentity = identity; + +var EPSILON = 5e-5; + +function isNotAroundZero(val) { + return val > EPSILON || val < -EPSILON; +} + +/** + * @alias module:zrender/mixin/Transformable + * @constructor + */ +var Transformable = function (opts) { + opts = opts || {}; + // If there are no given position, rotation, scale + if (!opts.position) { + /** + * 平移 + * @type {Array.} + * @default [0, 0] + */ + this.position = [0, 0]; + } + if (opts.rotation == null) { + /** + * 旋转 + * @type {Array.} + * @default 0 + */ + this.rotation = 0; + } + if (!opts.scale) { + /** + * 缩放 + * @type {Array.} + * @default [1, 1] + */ + this.scale = [1, 1]; + } + /** + * 旋转和缩放的原点 + * @type {Array.} + * @default null + */ + this.origin = this.origin || null; +}; + +var transformableProto = Transformable.prototype; +transformableProto.transform = null; + +/** + * 判断是否需要有坐标变换 + * 如果有坐标变换, 则从position, rotation, scale以及父节点的transform计算出自身的transform矩阵 + */ +transformableProto.needLocalTransform = function () { + return isNotAroundZero(this.rotation) + || isNotAroundZero(this.position[0]) + || isNotAroundZero(this.position[1]) + || isNotAroundZero(this.scale[0] - 1) + || isNotAroundZero(this.scale[1] - 1); +}; + +var scaleTmp = []; +transformableProto.updateTransform = function () { + var parent = this.parent; + var parentHasTransform = parent && parent.transform; + var needLocalTransform = this.needLocalTransform(); + + var m = this.transform; + if (!(needLocalTransform || parentHasTransform)) { + m && mIdentity(m); + return; + } + + m = m || create$1(); + + if (needLocalTransform) { + this.getLocalTransform(m); + } + else { + mIdentity(m); + } + + // 应用父节点变换 + if (parentHasTransform) { + if (needLocalTransform) { + mul$1(m, parent.transform, m); + } + else { + copy$1(m, parent.transform); + } + } + // 保存这个变换矩阵 + this.transform = m; + + var globalScaleRatio = this.globalScaleRatio; + if (globalScaleRatio != null && globalScaleRatio !== 1) { + this.getGlobalScale(scaleTmp); + var relX = scaleTmp[0] < 0 ? -1 : 1; + var relY = scaleTmp[1] < 0 ? -1 : 1; + var sx = ((scaleTmp[0] - relX) * globalScaleRatio + relX) / scaleTmp[0] || 0; + var sy = ((scaleTmp[1] - relY) * globalScaleRatio + relY) / scaleTmp[1] || 0; + + m[0] *= sx; + m[1] *= sx; + m[2] *= sy; + m[3] *= sy; + } + + this.invTransform = this.invTransform || create$1(); + invert(this.invTransform, m); +}; + +transformableProto.getLocalTransform = function (m) { + return Transformable.getLocalTransform(this, m); +}; + +/** + * 将自己的transform应用到context上 + * @param {CanvasRenderingContext2D} ctx + */ +transformableProto.setTransform = function (ctx) { + var m = this.transform; + var dpr = ctx.dpr || 1; + if (m) { + ctx.setTransform(dpr * m[0], dpr * m[1], dpr * m[2], dpr * m[3], dpr * m[4], dpr * m[5]); + } + else { + ctx.setTransform(dpr, 0, 0, dpr, 0, 0); + } +}; + +transformableProto.restoreTransform = function (ctx) { + var dpr = ctx.dpr || 1; + ctx.setTransform(dpr, 0, 0, dpr, 0, 0); +}; + +var tmpTransform = []; +var originTransform = create$1(); + +transformableProto.setLocalTransform = function (m) { + if (!m) { + // TODO return or set identity? + return; + } + var sx = m[0] * m[0] + m[1] * m[1]; + var sy = m[2] * m[2] + m[3] * m[3]; + var position = this.position; + var scale$$1 = this.scale; + if (isNotAroundZero(sx - 1)) { + sx = Math.sqrt(sx); + } + if (isNotAroundZero(sy - 1)) { + sy = Math.sqrt(sy); + } + if (m[0] < 0) { + sx = -sx; + } + if (m[3] < 0) { + sy = -sy; + } + + position[0] = m[4]; + position[1] = m[5]; + scale$$1[0] = sx; + scale$$1[1] = sy; + this.rotation = Math.atan2(-m[1] / sy, m[0] / sx); +}; +/** + * 分解`transform`矩阵到`position`, `rotation`, `scale` + */ +transformableProto.decomposeTransform = function () { + if (!this.transform) { + return; + } + var parent = this.parent; + var m = this.transform; + if (parent && parent.transform) { + // Get local transform and decompose them to position, scale, rotation + mul$1(tmpTransform, parent.invTransform, m); + m = tmpTransform; + } + var origin = this.origin; + if (origin && (origin[0] || origin[1])) { + originTransform[4] = origin[0]; + originTransform[5] = origin[1]; + mul$1(tmpTransform, m, originTransform); + tmpTransform[4] -= origin[0]; + tmpTransform[5] -= origin[1]; + m = tmpTransform; + } + + this.setLocalTransform(m); +}; + +/** + * Get global scale + * @return {Array.} + */ +transformableProto.getGlobalScale = function (out) { + var m = this.transform; + out = out || []; + if (!m) { + out[0] = 1; + out[1] = 1; + return out; + } + out[0] = Math.sqrt(m[0] * m[0] + m[1] * m[1]); + out[1] = Math.sqrt(m[2] * m[2] + m[3] * m[3]); + if (m[0] < 0) { + out[0] = -out[0]; + } + if (m[3] < 0) { + out[1] = -out[1]; + } + return out; +}; +/** + * 变换坐标位置到 shape 的局部坐标空间 + * @method + * @param {number} x + * @param {number} y + * @return {Array.} + */ +transformableProto.transformCoordToLocal = function (x, y) { + var v2 = [x, y]; + var invTransform = this.invTransform; + if (invTransform) { + applyTransform(v2, v2, invTransform); + } + return v2; +}; + +/** + * 变换局部坐标位置到全局坐标空间 + * @method + * @param {number} x + * @param {number} y + * @return {Array.} + */ +transformableProto.transformCoordToGlobal = function (x, y) { + var v2 = [x, y]; + var transform = this.transform; + if (transform) { + applyTransform(v2, v2, transform); + } + return v2; +}; + +/** + * @static + * @param {Object} target + * @param {Array.} target.origin + * @param {number} target.rotation + * @param {Array.} target.position + * @param {Array.} [m] + */ +Transformable.getLocalTransform = function (target, m) { + m = m || []; + mIdentity(m); + + var origin = target.origin; + var scale$$1 = target.scale || [1, 1]; + var rotation = target.rotation || 0; + var position = target.position || [0, 0]; + + if (origin) { + // Translate to origin + m[4] -= origin[0]; + m[5] -= origin[1]; + } + scale$1(m, m, scale$$1); + if (rotation) { + rotate(m, m, rotation); + } + if (origin) { + // Translate back from origin + m[4] += origin[0]; + m[5] += origin[1]; + } + + m[4] += position[0]; + m[5] += position[1]; + + return m; +}; + +/** + * 缓动代码来自 https://github.com/sole/tween.js/blob/master/src/Tween.js + * @see http://sole.github.io/tween.js/examples/03_graphs.html + * @exports zrender/animation/easing + */ +var easing = { + /** + * @param {number} k + * @return {number} + */ + linear: function (k) { + return k; + }, + + /** + * @param {number} k + * @return {number} + */ + quadraticIn: function (k) { + return k * k; + }, + /** + * @param {number} k + * @return {number} + */ + quadraticOut: function (k) { + return k * (2 - k); + }, + /** + * @param {number} k + * @return {number} + */ + quadraticInOut: function (k) { + if ((k *= 2) < 1) { + return 0.5 * k * k; + } + return -0.5 * (--k * (k - 2) - 1); + }, + + // 三次方的缓动(t^3) + /** + * @param {number} k + * @return {number} + */ + cubicIn: function (k) { + return k * k * k; + }, + /** + * @param {number} k + * @return {number} + */ + cubicOut: function (k) { + return --k * k * k + 1; + }, + /** + * @param {number} k + * @return {number} + */ + cubicInOut: function (k) { + if ((k *= 2) < 1) { + return 0.5 * k * k * k; + } + return 0.5 * ((k -= 2) * k * k + 2); + }, + + // 四次方的缓动(t^4) + /** + * @param {number} k + * @return {number} + */ + quarticIn: function (k) { + return k * k * k * k; + }, + /** + * @param {number} k + * @return {number} + */ + quarticOut: function (k) { + return 1 - (--k * k * k * k); + }, + /** + * @param {number} k + * @return {number} + */ + quarticInOut: function (k) { + if ((k *= 2) < 1) { + return 0.5 * k * k * k * k; + } + return -0.5 * ((k -= 2) * k * k * k - 2); + }, + + // 五次方的缓动(t^5) + /** + * @param {number} k + * @return {number} + */ + quinticIn: function (k) { + return k * k * k * k * k; + }, + /** + * @param {number} k + * @return {number} + */ + quinticOut: function (k) { + return --k * k * k * k * k + 1; + }, + /** + * @param {number} k + * @return {number} + */ + quinticInOut: function (k) { + if ((k *= 2) < 1) { + return 0.5 * k * k * k * k * k; + } + return 0.5 * ((k -= 2) * k * k * k * k + 2); + }, + + // 正弦曲线的缓动(sin(t)) + /** + * @param {number} k + * @return {number} + */ + sinusoidalIn: function (k) { + return 1 - Math.cos(k * Math.PI / 2); + }, + /** + * @param {number} k + * @return {number} + */ + sinusoidalOut: function (k) { + return Math.sin(k * Math.PI / 2); + }, + /** + * @param {number} k + * @return {number} + */ + sinusoidalInOut: function (k) { + return 0.5 * (1 - Math.cos(Math.PI * k)); + }, + + // 指数曲线的缓动(2^t) + /** + * @param {number} k + * @return {number} + */ + exponentialIn: function (k) { + return k === 0 ? 0 : Math.pow(1024, k - 1); + }, + /** + * @param {number} k + * @return {number} + */ + exponentialOut: function (k) { + return k === 1 ? 1 : 1 - Math.pow(2, -10 * k); + }, + /** + * @param {number} k + * @return {number} + */ + exponentialInOut: function (k) { + if (k === 0) { + return 0; + } + if (k === 1) { + return 1; + } + if ((k *= 2) < 1) { + return 0.5 * Math.pow(1024, k - 1); + } + return 0.5 * (-Math.pow(2, -10 * (k - 1)) + 2); + }, + + // 圆形曲线的缓动(sqrt(1-t^2)) + /** + * @param {number} k + * @return {number} + */ + circularIn: function (k) { + return 1 - Math.sqrt(1 - k * k); + }, + /** + * @param {number} k + * @return {number} + */ + circularOut: function (k) { + return Math.sqrt(1 - (--k * k)); + }, + /** + * @param {number} k + * @return {number} + */ + circularInOut: function (k) { + if ((k *= 2) < 1) { + return -0.5 * (Math.sqrt(1 - k * k) - 1); + } + return 0.5 * (Math.sqrt(1 - (k -= 2) * k) + 1); + }, + + // 创建类似于弹簧在停止前来回振荡的动画 + /** + * @param {number} k + * @return {number} + */ + elasticIn: function (k) { + var s; + var a = 0.1; + var p = 0.4; + if (k === 0) { + return 0; + } + if (k === 1) { + return 1; + } + if (!a || a < 1) { + a = 1; + s = p / 4; + } + else { + s = p * Math.asin(1 / a) / (2 * Math.PI); + } + return -(a * Math.pow(2, 10 * (k -= 1)) + * Math.sin((k - s) * (2 * Math.PI) / p)); + }, + /** + * @param {number} k + * @return {number} + */ + elasticOut: function (k) { + var s; + var a = 0.1; + var p = 0.4; + if (k === 0) { + return 0; + } + if (k === 1) { + return 1; + } + if (!a || a < 1) { + a = 1; + s = p / 4; + } + else { + s = p * Math.asin(1 / a) / (2 * Math.PI); + } + return (a * Math.pow(2, -10 * k) + * Math.sin((k - s) * (2 * Math.PI) / p) + 1); + }, + /** + * @param {number} k + * @return {number} + */ + elasticInOut: function (k) { + var s; + var a = 0.1; + var p = 0.4; + if (k === 0) { + return 0; + } + if (k === 1) { + return 1; + } + if (!a || a < 1) { + a = 1; + s = p / 4; + } + else { + s = p * Math.asin(1 / a) / (2 * Math.PI); + } + if ((k *= 2) < 1) { + return -0.5 * (a * Math.pow(2, 10 * (k -= 1)) + * Math.sin((k - s) * (2 * Math.PI) / p)); + } + return a * Math.pow(2, -10 * (k -= 1)) + * Math.sin((k - s) * (2 * Math.PI) / p) * 0.5 + 1; + + }, + + // 在某一动画开始沿指示的路径进行动画处理前稍稍收回该动画的移动 + /** + * @param {number} k + * @return {number} + */ + backIn: function (k) { + var s = 1.70158; + return k * k * ((s + 1) * k - s); + }, + /** + * @param {number} k + * @return {number} + */ + backOut: function (k) { + var s = 1.70158; + return --k * k * ((s + 1) * k + s) + 1; + }, + /** + * @param {number} k + * @return {number} + */ + backInOut: function (k) { + var s = 1.70158 * 1.525; + if ((k *= 2) < 1) { + return 0.5 * (k * k * ((s + 1) * k - s)); + } + return 0.5 * ((k -= 2) * k * ((s + 1) * k + s) + 2); + }, + + // 创建弹跳效果 + /** + * @param {number} k + * @return {number} + */ + bounceIn: function (k) { + return 1 - easing.bounceOut(1 - k); + }, + /** + * @param {number} k + * @return {number} + */ + bounceOut: function (k) { + if (k < (1 / 2.75)) { + return 7.5625 * k * k; + } + else if (k < (2 / 2.75)) { + return 7.5625 * (k -= (1.5 / 2.75)) * k + 0.75; + } + else if (k < (2.5 / 2.75)) { + return 7.5625 * (k -= (2.25 / 2.75)) * k + 0.9375; + } + else { + return 7.5625 * (k -= (2.625 / 2.75)) * k + 0.984375; + } + }, + /** + * @param {number} k + * @return {number} + */ + bounceInOut: function (k) { + if (k < 0.5) { + return easing.bounceIn(k * 2) * 0.5; + } + return easing.bounceOut(k * 2 - 1) * 0.5 + 0.5; + } +}; + +/** + * 动画主控制器 + * @config target 动画对象,可以是数组,如果是数组的话会批量分发onframe等事件 + * @config life(1000) 动画时长 + * @config delay(0) 动画延迟时间 + * @config loop(true) + * @config gap(0) 循环的间隔时间 + * @config onframe + * @config easing(optional) + * @config ondestroy(optional) + * @config onrestart(optional) + * + * TODO pause + */ + +function Clip(options) { + + this._target = options.target; + + // 生命周期 + this._life = options.life || 1000; + // 延时 + this._delay = options.delay || 0; + // 开始时间 + // this._startTime = new Date().getTime() + this._delay;// 单位毫秒 + this._initialized = false; + + // 是否循环 + this.loop = options.loop == null ? false : options.loop; + + this.gap = options.gap || 0; + + this.easing = options.easing || 'Linear'; + + this.onframe = options.onframe; + this.ondestroy = options.ondestroy; + this.onrestart = options.onrestart; + + this._pausedTime = 0; + this._paused = false; +} + +Clip.prototype = { + + constructor: Clip, + + step: function (globalTime, deltaTime) { + // Set startTime on first step, or _startTime may has milleseconds different between clips + // PENDING + if (!this._initialized) { + this._startTime = globalTime + this._delay; + this._initialized = true; + } + + if (this._paused) { + this._pausedTime += deltaTime; + return; + } + + var percent = (globalTime - this._startTime - this._pausedTime) / this._life; + + // 还没开始 + if (percent < 0) { + return; + } + + percent = Math.min(percent, 1); + + var easing$$1 = this.easing; + var easingFunc = typeof easing$$1 === 'string' ? easing[easing$$1] : easing$$1; + var schedule = typeof easingFunc === 'function' + ? easingFunc(percent) + : percent; + + this.fire('frame', schedule); + + // 结束 + if (percent === 1) { + if (this.loop) { + this.restart(globalTime); + // 重新开始周期 + // 抛出而不是直接调用事件直到 stage.update 后再统一调用这些事件 + return 'restart'; + } + + // 动画完成将这个控制器标识为待删除 + // 在Animation.update中进行批量删除 + this._needsRemove = true; + return 'destroy'; + } + + return null; + }, + + restart: function (globalTime) { + var remainder = (globalTime - this._startTime - this._pausedTime) % this._life; + this._startTime = globalTime - remainder + this.gap; + this._pausedTime = 0; + + this._needsRemove = false; + }, + + fire: function (eventType, arg) { + eventType = 'on' + eventType; + if (this[eventType]) { + this[eventType](this._target, arg); + } + }, + + pause: function () { + this._paused = true; + }, + + resume: function () { + this._paused = false; + } +}; + +// Simple LRU cache use doubly linked list +// @module zrender/core/LRU + +/** + * Simple double linked list. Compared with array, it has O(1) remove operation. + * @constructor + */ +var LinkedList = function () { + + /** + * @type {module:zrender/core/LRU~Entry} + */ + this.head = null; + + /** + * @type {module:zrender/core/LRU~Entry} + */ + this.tail = null; + + this._len = 0; +}; + +var linkedListProto = LinkedList.prototype; +/** + * Insert a new value at the tail + * @param {} val + * @return {module:zrender/core/LRU~Entry} + */ +linkedListProto.insert = function (val) { + var entry = new Entry(val); + this.insertEntry(entry); + return entry; +}; + +/** + * Insert an entry at the tail + * @param {module:zrender/core/LRU~Entry} entry + */ +linkedListProto.insertEntry = function (entry) { + if (!this.head) { + this.head = this.tail = entry; + } + else { + this.tail.next = entry; + entry.prev = this.tail; + entry.next = null; + this.tail = entry; + } + this._len++; +}; + +/** + * Remove entry. + * @param {module:zrender/core/LRU~Entry} entry + */ +linkedListProto.remove = function (entry) { + var prev = entry.prev; + var next = entry.next; + if (prev) { + prev.next = next; + } + else { + // Is head + this.head = next; + } + if (next) { + next.prev = prev; + } + else { + // Is tail + this.tail = prev; + } + entry.next = entry.prev = null; + this._len--; +}; + +/** + * @return {number} + */ +linkedListProto.len = function () { + return this._len; +}; + +/** + * Clear list + */ +linkedListProto.clear = function () { + this.head = this.tail = null; + this._len = 0; +}; + +/** + * @constructor + * @param {} val + */ +var Entry = function (val) { + /** + * @type {} + */ + this.value = val; + + /** + * @type {module:zrender/core/LRU~Entry} + */ + this.next; + + /** + * @type {module:zrender/core/LRU~Entry} + */ + this.prev; +}; + +/** + * LRU Cache + * @constructor + * @alias module:zrender/core/LRU + */ +var LRU = function (maxSize) { + + this._list = new LinkedList(); + + this._map = {}; + + this._maxSize = maxSize || 10; + + this._lastRemovedEntry = null; +}; + +var LRUProto = LRU.prototype; + +/** + * @param {string} key + * @param {} value + * @return {} Removed value + */ +LRUProto.put = function (key, value) { + var list = this._list; + var map = this._map; + var removed = null; + if (map[key] == null) { + var len = list.len(); + // Reuse last removed entry + var entry = this._lastRemovedEntry; + + if (len >= this._maxSize && len > 0) { + // Remove the least recently used + var leastUsedEntry = list.head; + list.remove(leastUsedEntry); + delete map[leastUsedEntry.key]; + + removed = leastUsedEntry.value; + this._lastRemovedEntry = leastUsedEntry; + } + + if (entry) { + entry.value = value; + } + else { + entry = new Entry(value); + } + entry.key = key; + list.insertEntry(entry); + map[key] = entry; + } + + return removed; +}; + +/** + * @param {string} key + * @return {} + */ +LRUProto.get = function (key) { + var entry = this._map[key]; + var list = this._list; + if (entry != null) { + // Put the latest used entry in the tail + if (entry !== list.tail) { + list.remove(entry); + list.insertEntry(entry); + } + + return entry.value; + } +}; + +/** + * Clear the cache + */ +LRUProto.clear = function () { + this._list.clear(); + this._map = {}; +}; + +var kCSSColorTable = { + 'transparent': [0, 0, 0, 0], 'aliceblue': [240, 248, 255, 1], + 'antiquewhite': [250, 235, 215, 1], 'aqua': [0, 255, 255, 1], + 'aquamarine': [127, 255, 212, 1], 'azure': [240, 255, 255, 1], + 'beige': [245, 245, 220, 1], 'bisque': [255, 228, 196, 1], + 'black': [0, 0, 0, 1], 'blanchedalmond': [255, 235, 205, 1], + 'blue': [0, 0, 255, 1], 'blueviolet': [138, 43, 226, 1], + 'brown': [165, 42, 42, 1], 'burlywood': [222, 184, 135, 1], + 'cadetblue': [95, 158, 160, 1], 'chartreuse': [127, 255, 0, 1], + 'chocolate': [210, 105, 30, 1], 'coral': [255, 127, 80, 1], + 'cornflowerblue': [100, 149, 237, 1], 'cornsilk': [255, 248, 220, 1], + 'crimson': [220, 20, 60, 1], 'cyan': [0, 255, 255, 1], + 'darkblue': [0, 0, 139, 1], 'darkcyan': [0, 139, 139, 1], + 'darkgoldenrod': [184, 134, 11, 1], 'darkgray': [169, 169, 169, 1], + 'darkgreen': [0, 100, 0, 1], 'darkgrey': [169, 169, 169, 1], + 'darkkhaki': [189, 183, 107, 1], 'darkmagenta': [139, 0, 139, 1], + 'darkolivegreen': [85, 107, 47, 1], 'darkorange': [255, 140, 0, 1], + 'darkorchid': [153, 50, 204, 1], 'darkred': [139, 0, 0, 1], + 'darksalmon': [233, 150, 122, 1], 'darkseagreen': [143, 188, 143, 1], + 'darkslateblue': [72, 61, 139, 1], 'darkslategray': [47, 79, 79, 1], + 'darkslategrey': [47, 79, 79, 1], 'darkturquoise': [0, 206, 209, 1], + 'darkviolet': [148, 0, 211, 1], 'deeppink': [255, 20, 147, 1], + 'deepskyblue': [0, 191, 255, 1], 'dimgray': [105, 105, 105, 1], + 'dimgrey': [105, 105, 105, 1], 'dodgerblue': [30, 144, 255, 1], + 'firebrick': [178, 34, 34, 1], 'floralwhite': [255, 250, 240, 1], + 'forestgreen': [34, 139, 34, 1], 'fuchsia': [255, 0, 255, 1], + 'gainsboro': [220, 220, 220, 1], 'ghostwhite': [248, 248, 255, 1], + 'gold': [255, 215, 0, 1], 'goldenrod': [218, 165, 32, 1], + 'gray': [128, 128, 128, 1], 'green': [0, 128, 0, 1], + 'greenyellow': [173, 255, 47, 1], 'grey': [128, 128, 128, 1], + 'honeydew': [240, 255, 240, 1], 'hotpink': [255, 105, 180, 1], + 'indianred': [205, 92, 92, 1], 'indigo': [75, 0, 130, 1], + 'ivory': [255, 255, 240, 1], 'khaki': [240, 230, 140, 1], + 'lavender': [230, 230, 250, 1], 'lavenderblush': [255, 240, 245, 1], + 'lawngreen': [124, 252, 0, 1], 'lemonchiffon': [255, 250, 205, 1], + 'lightblue': [173, 216, 230, 1], 'lightcoral': [240, 128, 128, 1], + 'lightcyan': [224, 255, 255, 1], 'lightgoldenrodyellow': [250, 250, 210, 1], + 'lightgray': [211, 211, 211, 1], 'lightgreen': [144, 238, 144, 1], + 'lightgrey': [211, 211, 211, 1], 'lightpink': [255, 182, 193, 1], + 'lightsalmon': [255, 160, 122, 1], 'lightseagreen': [32, 178, 170, 1], + 'lightskyblue': [135, 206, 250, 1], 'lightslategray': [119, 136, 153, 1], + 'lightslategrey': [119, 136, 153, 1], 'lightsteelblue': [176, 196, 222, 1], + 'lightyellow': [255, 255, 224, 1], 'lime': [0, 255, 0, 1], + 'limegreen': [50, 205, 50, 1], 'linen': [250, 240, 230, 1], + 'magenta': [255, 0, 255, 1], 'maroon': [128, 0, 0, 1], + 'mediumaquamarine': [102, 205, 170, 1], 'mediumblue': [0, 0, 205, 1], + 'mediumorchid': [186, 85, 211, 1], 'mediumpurple': [147, 112, 219, 1], + 'mediumseagreen': [60, 179, 113, 1], 'mediumslateblue': [123, 104, 238, 1], + 'mediumspringgreen': [0, 250, 154, 1], 'mediumturquoise': [72, 209, 204, 1], + 'mediumvioletred': [199, 21, 133, 1], 'midnightblue': [25, 25, 112, 1], + 'mintcream': [245, 255, 250, 1], 'mistyrose': [255, 228, 225, 1], + 'moccasin': [255, 228, 181, 1], 'navajowhite': [255, 222, 173, 1], + 'navy': [0, 0, 128, 1], 'oldlace': [253, 245, 230, 1], + 'olive': [128, 128, 0, 1], 'olivedrab': [107, 142, 35, 1], + 'orange': [255, 165, 0, 1], 'orangered': [255, 69, 0, 1], + 'orchid': [218, 112, 214, 1], 'palegoldenrod': [238, 232, 170, 1], + 'palegreen': [152, 251, 152, 1], 'paleturquoise': [175, 238, 238, 1], + 'palevioletred': [219, 112, 147, 1], 'papayawhip': [255, 239, 213, 1], + 'peachpuff': [255, 218, 185, 1], 'peru': [205, 133, 63, 1], + 'pink': [255, 192, 203, 1], 'plum': [221, 160, 221, 1], + 'powderblue': [176, 224, 230, 1], 'purple': [128, 0, 128, 1], + 'red': [255, 0, 0, 1], 'rosybrown': [188, 143, 143, 1], + 'royalblue': [65, 105, 225, 1], 'saddlebrown': [139, 69, 19, 1], + 'salmon': [250, 128, 114, 1], 'sandybrown': [244, 164, 96, 1], + 'seagreen': [46, 139, 87, 1], 'seashell': [255, 245, 238, 1], + 'sienna': [160, 82, 45, 1], 'silver': [192, 192, 192, 1], + 'skyblue': [135, 206, 235, 1], 'slateblue': [106, 90, 205, 1], + 'slategray': [112, 128, 144, 1], 'slategrey': [112, 128, 144, 1], + 'snow': [255, 250, 250, 1], 'springgreen': [0, 255, 127, 1], + 'steelblue': [70, 130, 180, 1], 'tan': [210, 180, 140, 1], + 'teal': [0, 128, 128, 1], 'thistle': [216, 191, 216, 1], + 'tomato': [255, 99, 71, 1], 'turquoise': [64, 224, 208, 1], + 'violet': [238, 130, 238, 1], 'wheat': [245, 222, 179, 1], + 'white': [255, 255, 255, 1], 'whitesmoke': [245, 245, 245, 1], + 'yellow': [255, 255, 0, 1], 'yellowgreen': [154, 205, 50, 1] +}; + +function clampCssByte(i) { // Clamp to integer 0 .. 255. + i = Math.round(i); // Seems to be what Chrome does (vs truncation). + return i < 0 ? 0 : i > 255 ? 255 : i; +} + +function clampCssAngle(i) { // Clamp to integer 0 .. 360. + i = Math.round(i); // Seems to be what Chrome does (vs truncation). + return i < 0 ? 0 : i > 360 ? 360 : i; +} + +function clampCssFloat(f) { // Clamp to float 0.0 .. 1.0. + return f < 0 ? 0 : f > 1 ? 1 : f; +} + +function parseCssInt(str) { // int or percentage. + if (str.length && str.charAt(str.length - 1) === '%') { + return clampCssByte(parseFloat(str) / 100 * 255); + } + return clampCssByte(parseInt(str, 10)); +} + +function parseCssFloat(str) { // float or percentage. + if (str.length && str.charAt(str.length - 1) === '%') { + return clampCssFloat(parseFloat(str) / 100); + } + return clampCssFloat(parseFloat(str)); +} + +function cssHueToRgb(m1, m2, h) { + if (h < 0) { + h += 1; + } + else if (h > 1) { + h -= 1; + } + + if (h * 6 < 1) { + return m1 + (m2 - m1) * h * 6; + } + if (h * 2 < 1) { + return m2; + } + if (h * 3 < 2) { + return m1 + (m2 - m1) * (2 / 3 - h) * 6; + } + return m1; +} + +function lerpNumber(a, b, p) { + return a + (b - a) * p; +} + +function setRgba(out, r, g, b, a) { + out[0] = r; out[1] = g; out[2] = b; out[3] = a; + return out; +} +function copyRgba(out, a) { + out[0] = a[0]; out[1] = a[1]; out[2] = a[2]; out[3] = a[3]; + return out; +} + +var colorCache = new LRU(20); +var lastRemovedArr = null; + +function putToCache(colorStr, rgbaArr) { + // Reuse removed array + if (lastRemovedArr) { + copyRgba(lastRemovedArr, rgbaArr); + } + lastRemovedArr = colorCache.put(colorStr, lastRemovedArr || (rgbaArr.slice())); +} + +/** + * @param {string} colorStr + * @param {Array.} out + * @return {Array.} + * @memberOf module:zrender/util/color + */ +function parse(colorStr, rgbaArr) { + if (!colorStr) { + return; + } + rgbaArr = rgbaArr || []; + + var cached = colorCache.get(colorStr); + if (cached) { + return copyRgba(rgbaArr, cached); + } + + // colorStr may be not string + colorStr = colorStr + ''; + // Remove all whitespace, not compliant, but should just be more accepting. + var str = colorStr.replace(/ /g, '').toLowerCase(); + + // Color keywords (and transparent) lookup. + if (str in kCSSColorTable) { + copyRgba(rgbaArr, kCSSColorTable[str]); + putToCache(colorStr, rgbaArr); + return rgbaArr; + } + + // #abc and #abc123 syntax. + if (str.charAt(0) === '#') { + if (str.length === 4) { + var iv = parseInt(str.substr(1), 16); // TODO(deanm): Stricter parsing. + if (!(iv >= 0 && iv <= 0xfff)) { + setRgba(rgbaArr, 0, 0, 0, 1); + return; // Covers NaN. + } + setRgba(rgbaArr, + ((iv & 0xf00) >> 4) | ((iv & 0xf00) >> 8), + (iv & 0xf0) | ((iv & 0xf0) >> 4), + (iv & 0xf) | ((iv & 0xf) << 4), + 1 + ); + putToCache(colorStr, rgbaArr); + return rgbaArr; + } + else if (str.length === 7) { + var iv = parseInt(str.substr(1), 16); // TODO(deanm): Stricter parsing. + if (!(iv >= 0 && iv <= 0xffffff)) { + setRgba(rgbaArr, 0, 0, 0, 1); + return; // Covers NaN. + } + setRgba(rgbaArr, + (iv & 0xff0000) >> 16, + (iv & 0xff00) >> 8, + iv & 0xff, + 1 + ); + putToCache(colorStr, rgbaArr); + return rgbaArr; + } + + return; + } + var op = str.indexOf('('); + var ep = str.indexOf(')'); + if (op !== -1 && ep + 1 === str.length) { + var fname = str.substr(0, op); + var params = str.substr(op + 1, ep - (op + 1)).split(','); + var alpha = 1; // To allow case fallthrough. + switch (fname) { + case 'rgba': + if (params.length !== 4) { + setRgba(rgbaArr, 0, 0, 0, 1); + return; + } + alpha = parseCssFloat(params.pop()); // jshint ignore:line + // Fall through. + case 'rgb': + if (params.length !== 3) { + setRgba(rgbaArr, 0, 0, 0, 1); + return; + } + setRgba(rgbaArr, + parseCssInt(params[0]), + parseCssInt(params[1]), + parseCssInt(params[2]), + alpha + ); + putToCache(colorStr, rgbaArr); + return rgbaArr; + case 'hsla': + if (params.length !== 4) { + setRgba(rgbaArr, 0, 0, 0, 1); + return; + } + params[3] = parseCssFloat(params[3]); + hsla2rgba(params, rgbaArr); + putToCache(colorStr, rgbaArr); + return rgbaArr; + case 'hsl': + if (params.length !== 3) { + setRgba(rgbaArr, 0, 0, 0, 1); + return; + } + hsla2rgba(params, rgbaArr); + putToCache(colorStr, rgbaArr); + return rgbaArr; + default: + return; + } + } + + setRgba(rgbaArr, 0, 0, 0, 1); + return; +} + +/** + * @param {Array.} hsla + * @param {Array.} rgba + * @return {Array.} rgba + */ +function hsla2rgba(hsla, rgba) { + var h = (((parseFloat(hsla[0]) % 360) + 360) % 360) / 360; // 0 .. 1 + // NOTE(deanm): According to the CSS spec s/l should only be + // percentages, but we don't bother and let float or percentage. + var s = parseCssFloat(hsla[1]); + var l = parseCssFloat(hsla[2]); + var m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s; + var m1 = l * 2 - m2; + + rgba = rgba || []; + setRgba(rgba, + clampCssByte(cssHueToRgb(m1, m2, h + 1 / 3) * 255), + clampCssByte(cssHueToRgb(m1, m2, h) * 255), + clampCssByte(cssHueToRgb(m1, m2, h - 1 / 3) * 255), + 1 + ); + + if (hsla.length === 4) { + rgba[3] = hsla[3]; + } + + return rgba; +} + +/** + * @param {Array.} rgba + * @return {Array.} hsla + */ +function rgba2hsla(rgba) { + if (!rgba) { + return; + } + + // RGB from 0 to 255 + var R = rgba[0] / 255; + var G = rgba[1] / 255; + var B = rgba[2] / 255; + + var vMin = Math.min(R, G, B); // Min. value of RGB + var vMax = Math.max(R, G, B); // Max. value of RGB + var delta = vMax - vMin; // Delta RGB value + + var L = (vMax + vMin) / 2; + var H; + var S; + // HSL results from 0 to 1 + if (delta === 0) { + H = 0; + S = 0; + } + else { + if (L < 0.5) { + S = delta / (vMax + vMin); + } + else { + S = delta / (2 - vMax - vMin); + } + + var deltaR = (((vMax - R) / 6) + (delta / 2)) / delta; + var deltaG = (((vMax - G) / 6) + (delta / 2)) / delta; + var deltaB = (((vMax - B) / 6) + (delta / 2)) / delta; + + if (R === vMax) { + H = deltaB - deltaG; + } + else if (G === vMax) { + H = (1 / 3) + deltaR - deltaB; + } + else if (B === vMax) { + H = (2 / 3) + deltaG - deltaR; + } + + if (H < 0) { + H += 1; + } + + if (H > 1) { + H -= 1; + } + } + + var hsla = [H * 360, S, L]; + + if (rgba[3] != null) { + hsla.push(rgba[3]); + } + + return hsla; +} + +/** + * @param {string} color + * @param {number} level + * @return {string} + * @memberOf module:zrender/util/color + */ +function lift(color, level) { + var colorArr = parse(color); + if (colorArr) { + for (var i = 0; i < 3; i++) { + if (level < 0) { + colorArr[i] = colorArr[i] * (1 - level) | 0; + } + else { + colorArr[i] = ((255 - colorArr[i]) * level + colorArr[i]) | 0; + } + if (colorArr[i] > 255) { + colorArr[i] = 255; + } + else if (color[i] < 0) { + colorArr[i] = 0; + } + } + return stringify(colorArr, colorArr.length === 4 ? 'rgba' : 'rgb'); + } +} + +/** + * @param {string} color + * @return {string} + * @memberOf module:zrender/util/color + */ +function toHex(color) { + var colorArr = parse(color); + if (colorArr) { + return ((1 << 24) + (colorArr[0] << 16) + (colorArr[1] << 8) + (+colorArr[2])).toString(16).slice(1); + } +} + +/** + * Map value to color. Faster than lerp methods because color is represented by rgba array. + * @param {number} normalizedValue A float between 0 and 1. + * @param {Array.>} colors List of rgba color array + * @param {Array.} [out] Mapped gba color array + * @return {Array.} will be null/undefined if input illegal. + */ +function fastLerp(normalizedValue, colors, out) { + if (!(colors && colors.length) + || !(normalizedValue >= 0 && normalizedValue <= 1) + ) { + return; + } + + out = out || []; + + var value = normalizedValue * (colors.length - 1); + var leftIndex = Math.floor(value); + var rightIndex = Math.ceil(value); + var leftColor = colors[leftIndex]; + var rightColor = colors[rightIndex]; + var dv = value - leftIndex; + out[0] = clampCssByte(lerpNumber(leftColor[0], rightColor[0], dv)); + out[1] = clampCssByte(lerpNumber(leftColor[1], rightColor[1], dv)); + out[2] = clampCssByte(lerpNumber(leftColor[2], rightColor[2], dv)); + out[3] = clampCssFloat(lerpNumber(leftColor[3], rightColor[3], dv)); + + return out; +} + +/** + * @deprecated + */ +var fastMapToColor = fastLerp; + +/** + * @param {number} normalizedValue A float between 0 and 1. + * @param {Array.} colors Color list. + * @param {boolean=} fullOutput Default false. + * @return {(string|Object)} Result color. If fullOutput, + * return {color: ..., leftIndex: ..., rightIndex: ..., value: ...}, + * @memberOf module:zrender/util/color + */ +function lerp$1(normalizedValue, colors, fullOutput) { + if (!(colors && colors.length) + || !(normalizedValue >= 0 && normalizedValue <= 1) + ) { + return; + } + + var value = normalizedValue * (colors.length - 1); + var leftIndex = Math.floor(value); + var rightIndex = Math.ceil(value); + var leftColor = parse(colors[leftIndex]); + var rightColor = parse(colors[rightIndex]); + var dv = value - leftIndex; + + var color = stringify( + [ + clampCssByte(lerpNumber(leftColor[0], rightColor[0], dv)), + clampCssByte(lerpNumber(leftColor[1], rightColor[1], dv)), + clampCssByte(lerpNumber(leftColor[2], rightColor[2], dv)), + clampCssFloat(lerpNumber(leftColor[3], rightColor[3], dv)) + ], + 'rgba' + ); + + return fullOutput + ? { + color: color, + leftIndex: leftIndex, + rightIndex: rightIndex, + value: value + } + : color; +} + +/** + * @deprecated + */ +var mapToColor = lerp$1; + +/** + * @param {string} color + * @param {number=} h 0 ~ 360, ignore when null. + * @param {number=} s 0 ~ 1, ignore when null. + * @param {number=} l 0 ~ 1, ignore when null. + * @return {string} Color string in rgba format. + * @memberOf module:zrender/util/color + */ +function modifyHSL(color, h, s, l) { + color = parse(color); + + if (color) { + color = rgba2hsla(color); + h != null && (color[0] = clampCssAngle(h)); + s != null && (color[1] = parseCssFloat(s)); + l != null && (color[2] = parseCssFloat(l)); + + return stringify(hsla2rgba(color), 'rgba'); + } +} + +/** + * @param {string} color + * @param {number=} alpha 0 ~ 1 + * @return {string} Color string in rgba format. + * @memberOf module:zrender/util/color + */ +function modifyAlpha(color, alpha) { + color = parse(color); + + if (color && alpha != null) { + color[3] = clampCssFloat(alpha); + return stringify(color, 'rgba'); + } +} + +/** + * @param {Array.} arrColor like [12,33,44,0.4] + * @param {string} type 'rgba', 'hsva', ... + * @return {string} Result color. (If input illegal, return undefined). + */ +function stringify(arrColor, type) { + if (!arrColor || !arrColor.length) { + return; + } + var colorStr = arrColor[0] + ',' + arrColor[1] + ',' + arrColor[2]; + if (type === 'rgba' || type === 'hsva' || type === 'hsla') { + colorStr += ',' + arrColor[3]; + } + return type + '(' + colorStr + ')'; +} + + +var color = (Object.freeze || Object)({ + parse: parse, + lift: lift, + toHex: toHex, + fastLerp: fastLerp, + fastMapToColor: fastMapToColor, + lerp: lerp$1, + mapToColor: mapToColor, + modifyHSL: modifyHSL, + modifyAlpha: modifyAlpha, + stringify: stringify +}); + +/** + * @module echarts/animation/Animator + */ + +var arraySlice = Array.prototype.slice; + +function defaultGetter(target, key) { + return target[key]; +} + +function defaultSetter(target, key, value) { + target[key] = value; +} + +/** + * @param {number} p0 + * @param {number} p1 + * @param {number} percent + * @return {number} + */ +function interpolateNumber(p0, p1, percent) { + return (p1 - p0) * percent + p0; +} + +/** + * @param {string} p0 + * @param {string} p1 + * @param {number} percent + * @return {string} + */ +function interpolateString(p0, p1, percent) { + return percent > 0.5 ? p1 : p0; +} + +/** + * @param {Array} p0 + * @param {Array} p1 + * @param {number} percent + * @param {Array} out + * @param {number} arrDim + */ +function interpolateArray(p0, p1, percent, out, arrDim) { + var len = p0.length; + if (arrDim === 1) { + for (var i = 0; i < len; i++) { + out[i] = interpolateNumber(p0[i], p1[i], percent); + } + } + else { + var len2 = len && p0[0].length; + for (var i = 0; i < len; i++) { + for (var j = 0; j < len2; j++) { + out[i][j] = interpolateNumber( + p0[i][j], p1[i][j], percent + ); + } + } + } +} + +// arr0 is source array, arr1 is target array. +// Do some preprocess to avoid error happened when interpolating from arr0 to arr1 +function fillArr(arr0, arr1, arrDim) { + var arr0Len = arr0.length; + var arr1Len = arr1.length; + if (arr0Len !== arr1Len) { + // FIXME Not work for TypedArray + var isPreviousLarger = arr0Len > arr1Len; + if (isPreviousLarger) { + // Cut the previous + arr0.length = arr1Len; + } + else { + // Fill the previous + for (var i = arr0Len; i < arr1Len; i++) { + arr0.push( + arrDim === 1 ? arr1[i] : arraySlice.call(arr1[i]) + ); + } + } + } + // Handling NaN value + var len2 = arr0[0] && arr0[0].length; + for (var i = 0; i < arr0.length; i++) { + if (arrDim === 1) { + if (isNaN(arr0[i])) { + arr0[i] = arr1[i]; + } + } + else { + for (var j = 0; j < len2; j++) { + if (isNaN(arr0[i][j])) { + arr0[i][j] = arr1[i][j]; + } + } + } + } +} + +/** + * @param {Array} arr0 + * @param {Array} arr1 + * @param {number} arrDim + * @return {boolean} + */ +function isArraySame(arr0, arr1, arrDim) { + if (arr0 === arr1) { + return true; + } + var len = arr0.length; + if (len !== arr1.length) { + return false; + } + if (arrDim === 1) { + for (var i = 0; i < len; i++) { + if (arr0[i] !== arr1[i]) { + return false; + } + } + } + else { + var len2 = arr0[0].length; + for (var i = 0; i < len; i++) { + for (var j = 0; j < len2; j++) { + if (arr0[i][j] !== arr1[i][j]) { + return false; + } + } + } + } + return true; +} + +/** + * Catmull Rom interpolate array + * @param {Array} p0 + * @param {Array} p1 + * @param {Array} p2 + * @param {Array} p3 + * @param {number} t + * @param {number} t2 + * @param {number} t3 + * @param {Array} out + * @param {number} arrDim + */ +function catmullRomInterpolateArray( + p0, p1, p2, p3, t, t2, t3, out, arrDim +) { + var len = p0.length; + if (arrDim === 1) { + for (var i = 0; i < len; i++) { + out[i] = catmullRomInterpolate( + p0[i], p1[i], p2[i], p3[i], t, t2, t3 + ); + } + } + else { + var len2 = p0[0].length; + for (var i = 0; i < len; i++) { + for (var j = 0; j < len2; j++) { + out[i][j] = catmullRomInterpolate( + p0[i][j], p1[i][j], p2[i][j], p3[i][j], + t, t2, t3 + ); + } + } + } +} + +/** + * Catmull Rom interpolate number + * @param {number} p0 + * @param {number} p1 + * @param {number} p2 + * @param {number} p3 + * @param {number} t + * @param {number} t2 + * @param {number} t3 + * @return {number} + */ +function catmullRomInterpolate(p0, p1, p2, p3, t, t2, t3) { + var v0 = (p2 - p0) * 0.5; + var v1 = (p3 - p1) * 0.5; + return (2 * (p1 - p2) + v0 + v1) * t3 + + (-3 * (p1 - p2) - 2 * v0 - v1) * t2 + + v0 * t + p1; +} + +function cloneValue(value) { + if (isArrayLike(value)) { + var len = value.length; + if (isArrayLike(value[0])) { + var ret = []; + for (var i = 0; i < len; i++) { + ret.push(arraySlice.call(value[i])); + } + return ret; + } + + return arraySlice.call(value); + } + + return value; +} + +function rgba2String(rgba) { + rgba[0] = Math.floor(rgba[0]); + rgba[1] = Math.floor(rgba[1]); + rgba[2] = Math.floor(rgba[2]); + + return 'rgba(' + rgba.join(',') + ')'; +} + +function getArrayDim(keyframes) { + var lastValue = keyframes[keyframes.length - 1].value; + return isArrayLike(lastValue && lastValue[0]) ? 2 : 1; +} + +function createTrackClip(animator, easing, oneTrackDone, keyframes, propName, forceAnimate) { + var getter = animator._getter; + var setter = animator._setter; + var useSpline = easing === 'spline'; + + var trackLen = keyframes.length; + if (!trackLen) { + return; + } + // Guess data type + var firstVal = keyframes[0].value; + var isValueArray = isArrayLike(firstVal); + var isValueColor = false; + var isValueString = false; + + // For vertices morphing + var arrDim = isValueArray ? getArrayDim(keyframes) : 0; + + var trackMaxTime; + // Sort keyframe as ascending + keyframes.sort(function (a, b) { + return a.time - b.time; + }); + + trackMaxTime = keyframes[trackLen - 1].time; + // Percents of each keyframe + var kfPercents = []; + // Value of each keyframe + var kfValues = []; + var prevValue = keyframes[0].value; + var isAllValueEqual = true; + for (var i = 0; i < trackLen; i++) { + kfPercents.push(keyframes[i].time / trackMaxTime); + // Assume value is a color when it is a string + var value = keyframes[i].value; + + // Check if value is equal, deep check if value is array + if (!((isValueArray && isArraySame(value, prevValue, arrDim)) + || (!isValueArray && value === prevValue))) { + isAllValueEqual = false; + } + prevValue = value; + + // Try converting a string to a color array + if (typeof value === 'string') { + var colorArray = parse(value); + if (colorArray) { + value = colorArray; + isValueColor = true; + } + else { + isValueString = true; + } + } + kfValues.push(value); + } + if (!forceAnimate && isAllValueEqual) { + return; + } + + var lastValue = kfValues[trackLen - 1]; + // Polyfill array and NaN value + for (var i = 0; i < trackLen - 1; i++) { + if (isValueArray) { + fillArr(kfValues[i], lastValue, arrDim); + } + else { + if (isNaN(kfValues[i]) && !isNaN(lastValue) && !isValueString && !isValueColor) { + kfValues[i] = lastValue; + } + } + } + isValueArray && fillArr(getter(animator._target, propName), lastValue, arrDim); + + // Cache the key of last frame to speed up when + // animation playback is sequency + var lastFrame = 0; + var lastFramePercent = 0; + var start; + var w; + var p0; + var p1; + var p2; + var p3; + + if (isValueColor) { + var rgba = [0, 0, 0, 0]; + } + + var onframe = function (target, percent) { + // Find the range keyframes + // kf1-----kf2---------current--------kf3 + // find kf2 and kf3 and do interpolation + var frame; + // In the easing function like elasticOut, percent may less than 0 + if (percent < 0) { + frame = 0; + } + else if (percent < lastFramePercent) { + // Start from next key + // PENDING start from lastFrame ? + start = Math.min(lastFrame + 1, trackLen - 1); + for (frame = start; frame >= 0; frame--) { + if (kfPercents[frame] <= percent) { + break; + } + } + // PENDING really need to do this ? + frame = Math.min(frame, trackLen - 2); + } + else { + for (frame = lastFrame; frame < trackLen; frame++) { + if (kfPercents[frame] > percent) { + break; + } + } + frame = Math.min(frame - 1, trackLen - 2); + } + lastFrame = frame; + lastFramePercent = percent; + + var range = (kfPercents[frame + 1] - kfPercents[frame]); + if (range === 0) { + return; + } + else { + w = (percent - kfPercents[frame]) / range; + } + if (useSpline) { + p1 = kfValues[frame]; + p0 = kfValues[frame === 0 ? frame : frame - 1]; + p2 = kfValues[frame > trackLen - 2 ? trackLen - 1 : frame + 1]; + p3 = kfValues[frame > trackLen - 3 ? trackLen - 1 : frame + 2]; + if (isValueArray) { + catmullRomInterpolateArray( + p0, p1, p2, p3, w, w * w, w * w * w, + getter(target, propName), + arrDim + ); + } + else { + var value; + if (isValueColor) { + value = catmullRomInterpolateArray( + p0, p1, p2, p3, w, w * w, w * w * w, + rgba, 1 + ); + value = rgba2String(rgba); + } + else if (isValueString) { + // String is step(0.5) + return interpolateString(p1, p2, w); + } + else { + value = catmullRomInterpolate( + p0, p1, p2, p3, w, w * w, w * w * w + ); + } + setter( + target, + propName, + value + ); + } + } + else { + if (isValueArray) { + interpolateArray( + kfValues[frame], kfValues[frame + 1], w, + getter(target, propName), + arrDim + ); + } + else { + var value; + if (isValueColor) { + interpolateArray( + kfValues[frame], kfValues[frame + 1], w, + rgba, 1 + ); + value = rgba2String(rgba); + } + else if (isValueString) { + // String is step(0.5) + return interpolateString(kfValues[frame], kfValues[frame + 1], w); + } + else { + value = interpolateNumber(kfValues[frame], kfValues[frame + 1], w); + } + setter( + target, + propName, + value + ); + } + } + }; + + var clip = new Clip({ + target: animator._target, + life: trackMaxTime, + loop: animator._loop, + delay: animator._delay, + onframe: onframe, + ondestroy: oneTrackDone + }); + + if (easing && easing !== 'spline') { + clip.easing = easing; + } + + return clip; +} + +/** + * @alias module:zrender/animation/Animator + * @constructor + * @param {Object} target + * @param {boolean} loop + * @param {Function} getter + * @param {Function} setter + */ +var Animator = function (target, loop, getter, setter) { + this._tracks = {}; + this._target = target; + + this._loop = loop || false; + + this._getter = getter || defaultGetter; + this._setter = setter || defaultSetter; + + this._clipCount = 0; + + this._delay = 0; + + this._doneList = []; + + this._onframeList = []; + + this._clipList = []; +}; + +Animator.prototype = { + /** + * 设置动画关键帧 + * @param {number} time 关键帧时间,单位是ms + * @param {Object} props 关键帧的属性值,key-value表示 + * @return {module:zrender/animation/Animator} + */ + when: function (time /* ms */, props) { + var tracks = this._tracks; + for (var propName in props) { + if (!props.hasOwnProperty(propName)) { + continue; + } + + if (!tracks[propName]) { + tracks[propName] = []; + // Invalid value + var value = this._getter(this._target, propName); + if (value == null) { + // zrLog('Invalid property ' + propName); + continue; + } + // If time is 0 + // Then props is given initialize value + // Else + // Initialize value from current prop value + if (time !== 0) { + tracks[propName].push({ + time: 0, + value: cloneValue(value) + }); + } + } + tracks[propName].push({ + time: time, + value: props[propName] + }); + } + return this; + }, + /** + * 添加动画每一帧的回调函数 + * @param {Function} callback + * @return {module:zrender/animation/Animator} + */ + during: function (callback) { + this._onframeList.push(callback); + return this; + }, + + pause: function () { + for (var i = 0; i < this._clipList.length; i++) { + this._clipList[i].pause(); + } + this._paused = true; + }, + + resume: function () { + for (var i = 0; i < this._clipList.length; i++) { + this._clipList[i].resume(); + } + this._paused = false; + }, + + isPaused: function () { + return !!this._paused; + }, + + _doneCallback: function () { + // Clear all tracks + this._tracks = {}; + // Clear all clips + this._clipList.length = 0; + + var doneList = this._doneList; + var len = doneList.length; + for (var i = 0; i < len; i++) { + doneList[i].call(this); + } + }, + /** + * 开始执行动画 + * @param {string|Function} [easing] + * 动画缓动函数,详见{@link module:zrender/animation/easing} + * @param {boolean} forceAnimate + * @return {module:zrender/animation/Animator} + */ + start: function (easing, forceAnimate) { + + var self = this; + var clipCount = 0; + + var oneTrackDone = function () { + clipCount--; + if (!clipCount) { + self._doneCallback(); + } + }; + + var lastClip; + for (var propName in this._tracks) { + if (!this._tracks.hasOwnProperty(propName)) { + continue; + } + var clip = createTrackClip( + this, easing, oneTrackDone, + this._tracks[propName], propName, forceAnimate + ); + if (clip) { + this._clipList.push(clip); + clipCount++; + + // If start after added to animation + if (this.animation) { + this.animation.addClip(clip); + } + + lastClip = clip; + } + } + + // Add during callback on the last clip + if (lastClip) { + var oldOnFrame = lastClip.onframe; + lastClip.onframe = function (target, percent) { + oldOnFrame(target, percent); + + for (var i = 0; i < self._onframeList.length; i++) { + self._onframeList[i](target, percent); + } + }; + } + + // This optimization will help the case that in the upper application + // the view may be refreshed frequently, where animation will be + // called repeatly but nothing changed. + if (!clipCount) { + this._doneCallback(); + } + return this; + }, + /** + * 停止动画 + * @param {boolean} forwardToLast If move to last frame before stop + */ + stop: function (forwardToLast) { + var clipList = this._clipList; + var animation = this.animation; + for (var i = 0; i < clipList.length; i++) { + var clip = clipList[i]; + if (forwardToLast) { + // Move to last frame before stop + clip.onframe(this._target, 1); + } + animation && animation.removeClip(clip); + } + clipList.length = 0; + }, + /** + * 设置动画延迟开始的时间 + * @param {number} time 单位ms + * @return {module:zrender/animation/Animator} + */ + delay: function (time) { + this._delay = time; + return this; + }, + /** + * 添加动画结束的回调 + * @param {Function} cb + * @return {module:zrender/animation/Animator} + */ + done: function (cb) { + if (cb) { + this._doneList.push(cb); + } + return this; + }, + + /** + * @return {Array.} + */ + getClips: function () { + return this._clipList; + } +}; + +var dpr = 1; + +// If in browser environment +if (typeof window !== 'undefined') { + dpr = Math.max(window.devicePixelRatio || 1, 1); +} + +/** + * config默认配置项 + * @exports zrender/config + * @author Kener (@Kener-林峰, kener.linfeng@gmail.com) + */ + +/** + * debug日志选项:catchBrushException为true下有效 + * 0 : 不生成debug数据,发布用 + * 1 : 异常抛出,调试用 + * 2 : 控制台输出,调试用 + */ +var debugMode = 0; + +// retina 屏幕优化 +var devicePixelRatio = dpr; + +var log = function () { +}; + +if (debugMode === 1) { + log = function () { + for (var k in arguments) { + throw new Error(arguments[k]); + } + }; +} +else if (debugMode > 1) { + log = function () { + for (var k in arguments) { + console.log(arguments[k]); + } + }; +} + +var zrLog = log; + +/** + * @alias modue:zrender/mixin/Animatable + * @constructor + */ +var Animatable = function () { + + /** + * @type {Array.} + * @readOnly + */ + this.animators = []; +}; + +Animatable.prototype = { + + constructor: Animatable, + + /** + * 动画 + * + * @param {string} path The path to fetch value from object, like 'a.b.c'. + * @param {boolean} [loop] Whether to loop animation. + * @return {module:zrender/animation/Animator} + * @example: + * el.animate('style', false) + * .when(1000, {x: 10} ) + * .done(function(){ // Animation done }) + * .start() + */ + animate: function (path, loop) { + var target; + var animatingShape = false; + var el = this; + var zr = this.__zr; + if (path) { + var pathSplitted = path.split('.'); + var prop = el; + // If animating shape + animatingShape = pathSplitted[0] === 'shape'; + for (var i = 0, l = pathSplitted.length; i < l; i++) { + if (!prop) { + continue; + } + prop = prop[pathSplitted[i]]; + } + if (prop) { + target = prop; + } + } + else { + target = el; + } + + if (!target) { + zrLog( + 'Property "' + + path + + '" is not existed in element ' + + el.id + ); + return; + } + + var animators = el.animators; + + var animator = new Animator(target, loop); + + animator.during(function (target) { + el.dirty(animatingShape); + }) + .done(function () { + // FIXME Animator will not be removed if use `Animator#stop` to stop animation + animators.splice(indexOf(animators, animator), 1); + }); + + animators.push(animator); + + // If animate after added to the zrender + if (zr) { + zr.animation.addAnimator(animator); + } + + return animator; + }, + + /** + * 停止动画 + * @param {boolean} forwardToLast If move to last frame before stop + */ + stopAnimation: function (forwardToLast) { + var animators = this.animators; + var len = animators.length; + for (var i = 0; i < len; i++) { + animators[i].stop(forwardToLast); + } + animators.length = 0; + + return this; + }, + + /** + * Caution: this method will stop previous animation. + * So do not use this method to one element twice before + * animation starts, unless you know what you are doing. + * @param {Object} target + * @param {number} [time=500] Time in ms + * @param {string} [easing='linear'] + * @param {number} [delay=0] + * @param {Function} [callback] + * @param {Function} [forceAnimate] Prevent stop animation and callback + * immediently when target values are the same as current values. + * + * @example + * // Animate position + * el.animateTo({ + * position: [10, 10] + * }, function () { // done }) + * + * // Animate shape, style and position in 100ms, delayed 100ms, with cubicOut easing + * el.animateTo({ + * shape: { + * width: 500 + * }, + * style: { + * fill: 'red' + * } + * position: [10, 10] + * }, 100, 100, 'cubicOut', function () { // done }) + */ + // TODO Return animation key + animateTo: function (target, time, delay, easing, callback, forceAnimate) { + animateTo(this, target, time, delay, easing, callback, forceAnimate); + }, + + /** + * Animate from the target state to current state. + * The params and the return value are the same as `this.animateTo`. + */ + animateFrom: function (target, time, delay, easing, callback, forceAnimate) { + animateTo(this, target, time, delay, easing, callback, forceAnimate, true); + } +}; + +function animateTo(animatable, target, time, delay, easing, callback, forceAnimate, reverse) { + // animateTo(target, time, easing, callback); + if (isString(delay)) { + callback = easing; + easing = delay; + delay = 0; + } + // animateTo(target, time, delay, callback); + else if (isFunction$1(easing)) { + callback = easing; + easing = 'linear'; + delay = 0; + } + // animateTo(target, time, callback); + else if (isFunction$1(delay)) { + callback = delay; + delay = 0; + } + // animateTo(target, callback) + else if (isFunction$1(time)) { + callback = time; + time = 500; + } + // animateTo(target) + else if (!time) { + time = 500; + } + // Stop all previous animations + animatable.stopAnimation(); + animateToShallow(animatable, '', animatable, target, time, delay, reverse); + + // Animators may be removed immediately after start + // if there is nothing to animate + var animators = animatable.animators.slice(); + var count = animators.length; + function done() { + count--; + if (!count) { + callback && callback(); + } + } + + // No animators. This should be checked before animators[i].start(), + // because 'done' may be executed immediately if no need to animate. + if (!count) { + callback && callback(); + } + // Start after all animators created + // Incase any animator is done immediately when all animation properties are not changed + for (var i = 0; i < animators.length; i++) { + animators[i] + .done(done) + .start(easing, forceAnimate); + } +} + +/** + * @param {string} path='' + * @param {Object} source=animatable + * @param {Object} target + * @param {number} [time=500] + * @param {number} [delay=0] + * @param {boolean} [reverse] If `true`, animate + * from the `target` to current state. + * + * @example + * // Animate position + * el._animateToShallow({ + * position: [10, 10] + * }) + * + * // Animate shape, style and position in 100ms, delayed 100ms + * el._animateToShallow({ + * shape: { + * width: 500 + * }, + * style: { + * fill: 'red' + * } + * position: [10, 10] + * }, 100, 100) + */ +function animateToShallow(animatable, path, source, target, time, delay, reverse) { + var objShallow = {}; + var propertyCount = 0; + for (var name in target) { + if (!target.hasOwnProperty(name)) { + continue; + } + + if (source[name] != null) { + if (isObject$1(target[name]) && !isArrayLike(target[name])) { + animateToShallow( + animatable, + path ? path + '.' + name : name, + source[name], + target[name], + time, + delay, + reverse + ); + } + else { + if (reverse) { + objShallow[name] = source[name]; + setAttrByPath(animatable, path, name, target[name]); + } + else { + objShallow[name] = target[name]; + } + propertyCount++; + } + } + else if (target[name] != null && !reverse) { + setAttrByPath(animatable, path, name, target[name]); + } + } + + if (propertyCount > 0) { + animatable.animate(path, false) + .when(time == null ? 500 : time, objShallow) + .delay(delay || 0); + } +} + +function setAttrByPath(el, path, name, value) { + // Attr directly if not has property + // FIXME, if some property not needed for element ? + if (!path) { + el.attr(name, value); + } + else { + // Only support set shape or style + var props = {}; + props[path] = {}; + props[path][name] = value; + el.attr(props); + } +} + +/** + * @alias module:zrender/Element + * @constructor + * @extends {module:zrender/mixin/Animatable} + * @extends {module:zrender/mixin/Transformable} + * @extends {module:zrender/mixin/Eventful} + */ +var Element = function (opts) { // jshint ignore:line + + Transformable.call(this, opts); + Eventful.call(this, opts); + Animatable.call(this, opts); + + /** + * 画布元素ID + * @type {string} + */ + this.id = opts.id || guid(); +}; + +Element.prototype = { + + /** + * 元素类型 + * Element type + * @type {string} + */ + type: 'element', + + /** + * 元素名字 + * Element name + * @type {string} + */ + name: '', + + /** + * ZRender 实例对象,会在 element 添加到 zrender 实例中后自动赋值 + * ZRender instance will be assigned when element is associated with zrender + * @name module:/zrender/Element#__zr + * @type {module:zrender/ZRender} + */ + __zr: null, + + /** + * 图形是否忽略,为true时忽略图形的绘制以及事件触发 + * If ignore drawing and events of the element object + * @name module:/zrender/Element#ignore + * @type {boolean} + * @default false + */ + ignore: false, + + /** + * 用于裁剪的路径(shape),所有 Group 内的路径在绘制时都会被这个路径裁剪 + * 该路径会继承被裁减对象的变换 + * @type {module:zrender/graphic/Path} + * @see http://www.w3.org/TR/2dcontext/#clipping-region + * @readOnly + */ + clipPath: null, + + /** + * 是否是 Group + * @type {boolean} + */ + isGroup: false, + + /** + * Drift element + * @param {number} dx dx on the global space + * @param {number} dy dy on the global space + */ + drift: function (dx, dy) { + switch (this.draggable) { + case 'horizontal': + dy = 0; + break; + case 'vertical': + dx = 0; + break; + } + + var m = this.transform; + if (!m) { + m = this.transform = [1, 0, 0, 1, 0, 0]; + } + m[4] += dx; + m[5] += dy; + + this.decomposeTransform(); + this.dirty(false); + }, + + /** + * Hook before update + */ + beforeUpdate: function () {}, + /** + * Hook after update + */ + afterUpdate: function () {}, + /** + * Update each frame + */ + update: function () { + this.updateTransform(); + }, + + /** + * @param {Function} cb + * @param {} context + */ + traverse: function (cb, context) {}, + + /** + * @protected + */ + attrKV: function (key, value) { + if (key === 'position' || key === 'scale' || key === 'origin') { + // Copy the array + if (value) { + var target = this[key]; + if (!target) { + target = this[key] = []; + } + target[0] = value[0]; + target[1] = value[1]; + } + } + else { + this[key] = value; + } + }, + + /** + * Hide the element + */ + hide: function () { + this.ignore = true; + this.__zr && this.__zr.refresh(); + }, + + /** + * Show the element + */ + show: function () { + this.ignore = false; + this.__zr && this.__zr.refresh(); + }, + + /** + * @param {string|Object} key + * @param {*} value + */ + attr: function (key, value) { + if (typeof key === 'string') { + this.attrKV(key, value); + } + else if (isObject$1(key)) { + for (var name in key) { + if (key.hasOwnProperty(name)) { + this.attrKV(name, key[name]); + } + } + } + + this.dirty(false); + + return this; + }, + + /** + * @param {module:zrender/graphic/Path} clipPath + */ + setClipPath: function (clipPath) { + var zr = this.__zr; + if (zr) { + clipPath.addSelfToZr(zr); + } + + // Remove previous clip path + if (this.clipPath && this.clipPath !== clipPath) { + this.removeClipPath(); + } + + this.clipPath = clipPath; + clipPath.__zr = zr; + clipPath.__clipTarget = this; + + this.dirty(false); + }, + + /** + */ + removeClipPath: function () { + var clipPath = this.clipPath; + if (clipPath) { + if (clipPath.__zr) { + clipPath.removeSelfFromZr(clipPath.__zr); + } + + clipPath.__zr = null; + clipPath.__clipTarget = null; + this.clipPath = null; + + this.dirty(false); + } + }, + + /** + * Add self from zrender instance. + * Not recursively because it will be invoked when element added to storage. + * @param {module:zrender/ZRender} zr + */ + addSelfToZr: function (zr) { + this.__zr = zr; + // 添加动画 + var animators = this.animators; + if (animators) { + for (var i = 0; i < animators.length; i++) { + zr.animation.addAnimator(animators[i]); + } + } + + if (this.clipPath) { + this.clipPath.addSelfToZr(zr); + } + }, + + /** + * Remove self from zrender instance. + * Not recursively because it will be invoked when element added to storage. + * @param {module:zrender/ZRender} zr + */ + removeSelfFromZr: function (zr) { + this.__zr = null; + // 移除动画 + var animators = this.animators; + if (animators) { + for (var i = 0; i < animators.length; i++) { + zr.animation.removeAnimator(animators[i]); + } + } + + if (this.clipPath) { + this.clipPath.removeSelfFromZr(zr); + } + } +}; + +mixin(Element, Animatable); +mixin(Element, Transformable); +mixin(Element, Eventful); + +/** + * @module echarts/core/BoundingRect + */ + +var v2ApplyTransform = applyTransform; +var mathMin = Math.min; +var mathMax = Math.max; + +/** + * @alias module:echarts/core/BoundingRect + */ +function BoundingRect(x, y, width, height) { + + if (width < 0) { + x = x + width; + width = -width; + } + if (height < 0) { + y = y + height; + height = -height; + } + + /** + * @type {number} + */ + this.x = x; + /** + * @type {number} + */ + this.y = y; + /** + * @type {number} + */ + this.width = width; + /** + * @type {number} + */ + this.height = height; +} + +BoundingRect.prototype = { + + constructor: BoundingRect, + + /** + * @param {module:echarts/core/BoundingRect} other + */ + union: function (other) { + var x = mathMin(other.x, this.x); + var y = mathMin(other.y, this.y); + + this.width = mathMax( + other.x + other.width, + this.x + this.width + ) - x; + this.height = mathMax( + other.y + other.height, + this.y + this.height + ) - y; + this.x = x; + this.y = y; + }, + + /** + * @param {Array.} m + * @methods + */ + applyTransform: (function () { + var lt = []; + var rb = []; + var lb = []; + var rt = []; + return function (m) { + // In case usage like this + // el.getBoundingRect().applyTransform(el.transform) + // And element has no transform + if (!m) { + return; + } + lt[0] = lb[0] = this.x; + lt[1] = rt[1] = this.y; + rb[0] = rt[0] = this.x + this.width; + rb[1] = lb[1] = this.y + this.height; + + v2ApplyTransform(lt, lt, m); + v2ApplyTransform(rb, rb, m); + v2ApplyTransform(lb, lb, m); + v2ApplyTransform(rt, rt, m); + + this.x = mathMin(lt[0], rb[0], lb[0], rt[0]); + this.y = mathMin(lt[1], rb[1], lb[1], rt[1]); + var maxX = mathMax(lt[0], rb[0], lb[0], rt[0]); + var maxY = mathMax(lt[1], rb[1], lb[1], rt[1]); + this.width = maxX - this.x; + this.height = maxY - this.y; + }; + })(), + + /** + * Calculate matrix of transforming from self to target rect + * @param {module:zrender/core/BoundingRect} b + * @return {Array.} + */ + calculateTransform: function (b) { + var a = this; + var sx = b.width / a.width; + var sy = b.height / a.height; + + var m = create$1(); + + // 矩阵右乘 + translate(m, m, [-a.x, -a.y]); + scale$1(m, m, [sx, sy]); + translate(m, m, [b.x, b.y]); + + return m; + }, + + /** + * @param {(module:echarts/core/BoundingRect|Object)} b + * @return {boolean} + */ + intersect: function (b) { + if (!b) { + return false; + } + + if (!(b instanceof BoundingRect)) { + // Normalize negative width/height. + b = BoundingRect.create(b); + } + + var a = this; + var ax0 = a.x; + var ax1 = a.x + a.width; + var ay0 = a.y; + var ay1 = a.y + a.height; + + var bx0 = b.x; + var bx1 = b.x + b.width; + var by0 = b.y; + var by1 = b.y + b.height; + + return !(ax1 < bx0 || bx1 < ax0 || ay1 < by0 || by1 < ay0); + }, + + contain: function (x, y) { + var rect = this; + return x >= rect.x + && x <= (rect.x + rect.width) + && y >= rect.y + && y <= (rect.y + rect.height); + }, + + /** + * @return {module:echarts/core/BoundingRect} + */ + clone: function () { + return new BoundingRect(this.x, this.y, this.width, this.height); + }, + + /** + * Copy from another rect + */ + copy: function (other) { + this.x = other.x; + this.y = other.y; + this.width = other.width; + this.height = other.height; + }, + + plain: function () { + return { + x: this.x, + y: this.y, + width: this.width, + height: this.height + }; + } +}; + +/** + * @param {Object|module:zrender/core/BoundingRect} rect + * @param {number} rect.x + * @param {number} rect.y + * @param {number} rect.width + * @param {number} rect.height + * @return {module:zrender/core/BoundingRect} + */ +BoundingRect.create = function (rect) { + return new BoundingRect(rect.x, rect.y, rect.width, rect.height); +}; + +/** + * Group是一个容器,可以插入子节点,Group的变换也会被应用到子节点上 + * @module zrender/graphic/Group + * @example + * var Group = require('zrender/container/Group'); + * var Circle = require('zrender/graphic/shape/Circle'); + * var g = new Group(); + * g.position[0] = 100; + * g.position[1] = 100; + * g.add(new Circle({ + * style: { + * x: 100, + * y: 100, + * r: 20, + * } + * })); + * zr.add(g); + */ + +/** + * @alias module:zrender/graphic/Group + * @constructor + * @extends module:zrender/mixin/Transformable + * @extends module:zrender/mixin/Eventful + */ +var Group = function (opts) { + + opts = opts || {}; + + Element.call(this, opts); + + for (var key in opts) { + if (opts.hasOwnProperty(key)) { + this[key] = opts[key]; + } + } + + this._children = []; + + this.__storage = null; + + this.__dirty = true; +}; + +Group.prototype = { + + constructor: Group, + + isGroup: true, + + /** + * @type {string} + */ + type: 'group', + + /** + * 所有子孙元素是否响应鼠标事件 + * @name module:/zrender/container/Group#silent + * @type {boolean} + * @default false + */ + silent: false, + + /** + * @return {Array.} + */ + children: function () { + return this._children.slice(); + }, + + /** + * 获取指定 index 的儿子节点 + * @param {number} idx + * @return {module:zrender/Element} + */ + childAt: function (idx) { + return this._children[idx]; + }, + + /** + * 获取指定名字的儿子节点 + * @param {string} name + * @return {module:zrender/Element} + */ + childOfName: function (name) { + var children = this._children; + for (var i = 0; i < children.length; i++) { + if (children[i].name === name) { + return children[i]; + } + } + }, + + /** + * @return {number} + */ + childCount: function () { + return this._children.length; + }, + + /** + * 添加子节点到最后 + * @param {module:zrender/Element} child + */ + add: function (child) { + if (child && child !== this && child.parent !== this) { + + this._children.push(child); + + this._doAdd(child); + } + + return this; + }, + + /** + * 添加子节点在 nextSibling 之前 + * @param {module:zrender/Element} child + * @param {module:zrender/Element} nextSibling + */ + addBefore: function (child, nextSibling) { + if (child && child !== this && child.parent !== this + && nextSibling && nextSibling.parent === this) { + + var children = this._children; + var idx = children.indexOf(nextSibling); + + if (idx >= 0) { + children.splice(idx, 0, child); + this._doAdd(child); + } + } + + return this; + }, + + _doAdd: function (child) { + if (child.parent) { + child.parent.remove(child); + } + + child.parent = this; + + var storage = this.__storage; + var zr = this.__zr; + if (storage && storage !== child.__storage) { + + storage.addToStorage(child); + + if (child instanceof Group) { + child.addChildrenToStorage(storage); + } + } + + zr && zr.refresh(); + }, + + /** + * 移除子节点 + * @param {module:zrender/Element} child + */ + remove: function (child) { + var zr = this.__zr; + var storage = this.__storage; + var children = this._children; + + var idx = indexOf(children, child); + if (idx < 0) { + return this; + } + children.splice(idx, 1); + + child.parent = null; + + if (storage) { + + storage.delFromStorage(child); + + if (child instanceof Group) { + child.delChildrenFromStorage(storage); + } + } + + zr && zr.refresh(); + + return this; + }, + + /** + * 移除所有子节点 + */ + removeAll: function () { + var children = this._children; + var storage = this.__storage; + var child; + var i; + for (i = 0; i < children.length; i++) { + child = children[i]; + if (storage) { + storage.delFromStorage(child); + if (child instanceof Group) { + child.delChildrenFromStorage(storage); + } + } + child.parent = null; + } + children.length = 0; + + return this; + }, + + /** + * 遍历所有子节点 + * @param {Function} cb + * @param {} context + */ + eachChild: function (cb, context) { + var children = this._children; + for (var i = 0; i < children.length; i++) { + var child = children[i]; + cb.call(context, child, i); + } + return this; + }, + + /** + * 深度优先遍历所有子孙节点 + * @param {Function} cb + * @param {} context + */ + traverse: function (cb, context) { + for (var i = 0; i < this._children.length; i++) { + var child = this._children[i]; + cb.call(context, child); + + if (child.type === 'group') { + child.traverse(cb, context); + } + } + return this; + }, + + addChildrenToStorage: function (storage) { + for (var i = 0; i < this._children.length; i++) { + var child = this._children[i]; + storage.addToStorage(child); + if (child instanceof Group) { + child.addChildrenToStorage(storage); + } + } + }, + + delChildrenFromStorage: function (storage) { + for (var i = 0; i < this._children.length; i++) { + var child = this._children[i]; + storage.delFromStorage(child); + if (child instanceof Group) { + child.delChildrenFromStorage(storage); + } + } + }, + + dirty: function () { + this.__dirty = true; + this.__zr && this.__zr.refresh(); + return this; + }, + + /** + * @return {module:zrender/core/BoundingRect} + */ + getBoundingRect: function (includeChildren) { + // TODO Caching + var rect = null; + var tmpRect = new BoundingRect(0, 0, 0, 0); + var children = includeChildren || this._children; + var tmpMat = []; + + for (var i = 0; i < children.length; i++) { + var child = children[i]; + if (child.ignore || child.invisible) { + continue; + } + + var childRect = child.getBoundingRect(); + var transform = child.getLocalTransform(tmpMat); + // TODO + // The boundingRect cacluated by transforming original + // rect may be bigger than the actual bundingRect when rotation + // is used. (Consider a circle rotated aginst its center, where + // the actual boundingRect should be the same as that not be + // rotated.) But we can not find better approach to calculate + // actual boundingRect yet, considering performance. + if (transform) { + tmpRect.copy(childRect); + tmpRect.applyTransform(transform); + rect = rect || tmpRect.clone(); + rect.union(tmpRect); + } + else { + rect = rect || childRect.clone(); + rect.union(childRect); + } + } + return rect || tmpRect; + } +}; + +inherits(Group, Element); + +// https://github.com/mziccard/node-timsort +var DEFAULT_MIN_MERGE = 32; + +var DEFAULT_MIN_GALLOPING = 7; + +function minRunLength(n) { + var r = 0; + + while (n >= DEFAULT_MIN_MERGE) { + r |= n & 1; + n >>= 1; + } + + return n + r; +} + +function makeAscendingRun(array, lo, hi, compare) { + var runHi = lo + 1; + + if (runHi === hi) { + return 1; + } + + if (compare(array[runHi++], array[lo]) < 0) { + while (runHi < hi && compare(array[runHi], array[runHi - 1]) < 0) { + runHi++; + } + + reverseRun(array, lo, runHi); + } + else { + while (runHi < hi && compare(array[runHi], array[runHi - 1]) >= 0) { + runHi++; + } + } + + return runHi - lo; +} + +function reverseRun(array, lo, hi) { + hi--; + + while (lo < hi) { + var t = array[lo]; + array[lo++] = array[hi]; + array[hi--] = t; + } +} + +function binaryInsertionSort(array, lo, hi, start, compare) { + if (start === lo) { + start++; + } + + for (; start < hi; start++) { + var pivot = array[start]; + + var left = lo; + var right = start; + var mid; + + while (left < right) { + mid = left + right >>> 1; + + if (compare(pivot, array[mid]) < 0) { + right = mid; + } + else { + left = mid + 1; + } + } + + var n = start - left; + + switch (n) { + case 3: + array[left + 3] = array[left + 2]; + + case 2: + array[left + 2] = array[left + 1]; + + case 1: + array[left + 1] = array[left]; + break; + default: + while (n > 0) { + array[left + n] = array[left + n - 1]; + n--; + } + } + + array[left] = pivot; + } +} + +function gallopLeft(value, array, start, length, hint, compare) { + var lastOffset = 0; + var maxOffset = 0; + var offset = 1; + + if (compare(value, array[start + hint]) > 0) { + maxOffset = length - hint; + + while (offset < maxOffset && compare(value, array[start + hint + offset]) > 0) { + lastOffset = offset; + offset = (offset << 1) + 1; + + if (offset <= 0) { + offset = maxOffset; + } + } + + if (offset > maxOffset) { + offset = maxOffset; + } + + lastOffset += hint; + offset += hint; + } + else { + maxOffset = hint + 1; + while (offset < maxOffset && compare(value, array[start + hint - offset]) <= 0) { + lastOffset = offset; + offset = (offset << 1) + 1; + + if (offset <= 0) { + offset = maxOffset; + } + } + if (offset > maxOffset) { + offset = maxOffset; + } + + var tmp = lastOffset; + lastOffset = hint - offset; + offset = hint - tmp; + } + + lastOffset++; + while (lastOffset < offset) { + var m = lastOffset + (offset - lastOffset >>> 1); + + if (compare(value, array[start + m]) > 0) { + lastOffset = m + 1; + } + else { + offset = m; + } + } + return offset; +} + +function gallopRight(value, array, start, length, hint, compare) { + var lastOffset = 0; + var maxOffset = 0; + var offset = 1; + + if (compare(value, array[start + hint]) < 0) { + maxOffset = hint + 1; + + while (offset < maxOffset && compare(value, array[start + hint - offset]) < 0) { + lastOffset = offset; + offset = (offset << 1) + 1; + + if (offset <= 0) { + offset = maxOffset; + } + } + + if (offset > maxOffset) { + offset = maxOffset; + } + + var tmp = lastOffset; + lastOffset = hint - offset; + offset = hint - tmp; + } + else { + maxOffset = length - hint; + + while (offset < maxOffset && compare(value, array[start + hint + offset]) >= 0) { + lastOffset = offset; + offset = (offset << 1) + 1; + + if (offset <= 0) { + offset = maxOffset; + } + } + + if (offset > maxOffset) { + offset = maxOffset; + } + + lastOffset += hint; + offset += hint; + } + + lastOffset++; + + while (lastOffset < offset) { + var m = lastOffset + (offset - lastOffset >>> 1); + + if (compare(value, array[start + m]) < 0) { + offset = m; + } + else { + lastOffset = m + 1; + } + } + + return offset; +} + +function TimSort(array, compare) { + var minGallop = DEFAULT_MIN_GALLOPING; + var runStart; + var runLength; + var stackSize = 0; + + var tmp = []; + + runStart = []; + runLength = []; + + function pushRun(_runStart, _runLength) { + runStart[stackSize] = _runStart; + runLength[stackSize] = _runLength; + stackSize += 1; + } + + function mergeRuns() { + while (stackSize > 1) { + var n = stackSize - 2; + + if (n >= 1 && runLength[n - 1] <= runLength[n] + runLength[n + 1] || n >= 2 && runLength[n - 2] <= runLength[n] + runLength[n - 1]) { + if (runLength[n - 1] < runLength[n + 1]) { + n--; + } + } + else if (runLength[n] > runLength[n + 1]) { + break; + } + mergeAt(n); + } + } + + function forceMergeRuns() { + while (stackSize > 1) { + var n = stackSize - 2; + + if (n > 0 && runLength[n - 1] < runLength[n + 1]) { + n--; + } + + mergeAt(n); + } + } + + function mergeAt(i) { + var start1 = runStart[i]; + var length1 = runLength[i]; + var start2 = runStart[i + 1]; + var length2 = runLength[i + 1]; + + runLength[i] = length1 + length2; + + if (i === stackSize - 3) { + runStart[i + 1] = runStart[i + 2]; + runLength[i + 1] = runLength[i + 2]; + } + + stackSize--; + + var k = gallopRight(array[start2], array, start1, length1, 0, compare); + start1 += k; + length1 -= k; + + if (length1 === 0) { + return; + } + + length2 = gallopLeft(array[start1 + length1 - 1], array, start2, length2, length2 - 1, compare); + + if (length2 === 0) { + return; + } + + if (length1 <= length2) { + mergeLow(start1, length1, start2, length2); + } + else { + mergeHigh(start1, length1, start2, length2); + } + } + + function mergeLow(start1, length1, start2, length2) { + var i = 0; + + for (i = 0; i < length1; i++) { + tmp[i] = array[start1 + i]; + } + + var cursor1 = 0; + var cursor2 = start2; + var dest = start1; + + array[dest++] = array[cursor2++]; + + if (--length2 === 0) { + for (i = 0; i < length1; i++) { + array[dest + i] = tmp[cursor1 + i]; + } + return; + } + + if (length1 === 1) { + for (i = 0; i < length2; i++) { + array[dest + i] = array[cursor2 + i]; + } + array[dest + length2] = tmp[cursor1]; + return; + } + + var _minGallop = minGallop; + var count1, count2, exit; + + while (1) { + count1 = 0; + count2 = 0; + exit = false; + + do { + if (compare(array[cursor2], tmp[cursor1]) < 0) { + array[dest++] = array[cursor2++]; + count2++; + count1 = 0; + + if (--length2 === 0) { + exit = true; + break; + } + } + else { + array[dest++] = tmp[cursor1++]; + count1++; + count2 = 0; + if (--length1 === 1) { + exit = true; + break; + } + } + } while ((count1 | count2) < _minGallop); + + if (exit) { + break; + } + + do { + count1 = gallopRight(array[cursor2], tmp, cursor1, length1, 0, compare); + + if (count1 !== 0) { + for (i = 0; i < count1; i++) { + array[dest + i] = tmp[cursor1 + i]; + } + + dest += count1; + cursor1 += count1; + length1 -= count1; + if (length1 <= 1) { + exit = true; + break; + } + } + + array[dest++] = array[cursor2++]; + + if (--length2 === 0) { + exit = true; + break; + } + + count2 = gallopLeft(tmp[cursor1], array, cursor2, length2, 0, compare); + + if (count2 !== 0) { + for (i = 0; i < count2; i++) { + array[dest + i] = array[cursor2 + i]; + } + + dest += count2; + cursor2 += count2; + length2 -= count2; + + if (length2 === 0) { + exit = true; + break; + } + } + array[dest++] = tmp[cursor1++]; + + if (--length1 === 1) { + exit = true; + break; + } + + _minGallop--; + } while (count1 >= DEFAULT_MIN_GALLOPING || count2 >= DEFAULT_MIN_GALLOPING); + + if (exit) { + break; + } + + if (_minGallop < 0) { + _minGallop = 0; + } + + _minGallop += 2; + } + + minGallop = _minGallop; + + minGallop < 1 && (minGallop = 1); + + if (length1 === 1) { + for (i = 0; i < length2; i++) { + array[dest + i] = array[cursor2 + i]; + } + array[dest + length2] = tmp[cursor1]; + } + else if (length1 === 0) { + throw new Error(); + // throw new Error('mergeLow preconditions were not respected'); + } + else { + for (i = 0; i < length1; i++) { + array[dest + i] = tmp[cursor1 + i]; + } + } + } + + function mergeHigh(start1, length1, start2, length2) { + var i = 0; + + for (i = 0; i < length2; i++) { + tmp[i] = array[start2 + i]; + } + + var cursor1 = start1 + length1 - 1; + var cursor2 = length2 - 1; + var dest = start2 + length2 - 1; + var customCursor = 0; + var customDest = 0; + + array[dest--] = array[cursor1--]; + + if (--length1 === 0) { + customCursor = dest - (length2 - 1); + + for (i = 0; i < length2; i++) { + array[customCursor + i] = tmp[i]; + } + + return; + } + + if (length2 === 1) { + dest -= length1; + cursor1 -= length1; + customDest = dest + 1; + customCursor = cursor1 + 1; + + for (i = length1 - 1; i >= 0; i--) { + array[customDest + i] = array[customCursor + i]; + } + + array[dest] = tmp[cursor2]; + return; + } + + var _minGallop = minGallop; + + while (true) { + var count1 = 0; + var count2 = 0; + var exit = false; + + do { + if (compare(tmp[cursor2], array[cursor1]) < 0) { + array[dest--] = array[cursor1--]; + count1++; + count2 = 0; + if (--length1 === 0) { + exit = true; + break; + } + } + else { + array[dest--] = tmp[cursor2--]; + count2++; + count1 = 0; + if (--length2 === 1) { + exit = true; + break; + } + } + } while ((count1 | count2) < _minGallop); + + if (exit) { + break; + } + + do { + count1 = length1 - gallopRight(tmp[cursor2], array, start1, length1, length1 - 1, compare); + + if (count1 !== 0) { + dest -= count1; + cursor1 -= count1; + length1 -= count1; + customDest = dest + 1; + customCursor = cursor1 + 1; + + for (i = count1 - 1; i >= 0; i--) { + array[customDest + i] = array[customCursor + i]; + } + + if (length1 === 0) { + exit = true; + break; + } + } + + array[dest--] = tmp[cursor2--]; + + if (--length2 === 1) { + exit = true; + break; + } + + count2 = length2 - gallopLeft(array[cursor1], tmp, 0, length2, length2 - 1, compare); + + if (count2 !== 0) { + dest -= count2; + cursor2 -= count2; + length2 -= count2; + customDest = dest + 1; + customCursor = cursor2 + 1; + + for (i = 0; i < count2; i++) { + array[customDest + i] = tmp[customCursor + i]; + } + + if (length2 <= 1) { + exit = true; + break; + } + } + + array[dest--] = array[cursor1--]; + + if (--length1 === 0) { + exit = true; + break; + } + + _minGallop--; + } while (count1 >= DEFAULT_MIN_GALLOPING || count2 >= DEFAULT_MIN_GALLOPING); + + if (exit) { + break; + } + + if (_minGallop < 0) { + _minGallop = 0; + } + + _minGallop += 2; + } + + minGallop = _minGallop; + + if (minGallop < 1) { + minGallop = 1; + } + + if (length2 === 1) { + dest -= length1; + cursor1 -= length1; + customDest = dest + 1; + customCursor = cursor1 + 1; + + for (i = length1 - 1; i >= 0; i--) { + array[customDest + i] = array[customCursor + i]; + } + + array[dest] = tmp[cursor2]; + } + else if (length2 === 0) { + throw new Error(); + // throw new Error('mergeHigh preconditions were not respected'); + } + else { + customCursor = dest - (length2 - 1); + for (i = 0; i < length2; i++) { + array[customCursor + i] = tmp[i]; + } + } + } + + this.mergeRuns = mergeRuns; + this.forceMergeRuns = forceMergeRuns; + this.pushRun = pushRun; +} + +function sort(array, compare, lo, hi) { + if (!lo) { + lo = 0; + } + if (!hi) { + hi = array.length; + } + + var remaining = hi - lo; + + if (remaining < 2) { + return; + } + + var runLength = 0; + + if (remaining < DEFAULT_MIN_MERGE) { + runLength = makeAscendingRun(array, lo, hi, compare); + binaryInsertionSort(array, lo, hi, lo + runLength, compare); + return; + } + + var ts = new TimSort(array, compare); + + var minRun = minRunLength(remaining); + + do { + runLength = makeAscendingRun(array, lo, hi, compare); + if (runLength < minRun) { + var force = remaining; + if (force > minRun) { + force = minRun; + } + + binaryInsertionSort(array, lo, lo + force, lo + runLength, compare); + runLength = force; + } + + ts.pushRun(lo, runLength); + ts.mergeRuns(); + + remaining -= runLength; + lo += runLength; + } while (remaining !== 0); + + ts.forceMergeRuns(); +} + +// Use timsort because in most case elements are partially sorted +// https://jsfiddle.net/pissang/jr4x7mdm/8/ +function shapeCompareFunc(a, b) { + if (a.zlevel === b.zlevel) { + if (a.z === b.z) { + // if (a.z2 === b.z2) { + // // FIXME Slow has renderidx compare + // // http://stackoverflow.com/questions/20883421/sorting-in-javascript-should-every-compare-function-have-a-return-0-statement + // // https://github.com/v8/v8/blob/47cce544a31ed5577ffe2963f67acb4144ee0232/src/js/array.js#L1012 + // return a.__renderidx - b.__renderidx; + // } + return a.z2 - b.z2; + } + return a.z - b.z; + } + return a.zlevel - b.zlevel; +} +/** + * 内容仓库 (M) + * @alias module:zrender/Storage + * @constructor + */ +var Storage = function () { // jshint ignore:line + this._roots = []; + + this._displayList = []; + + this._displayListLen = 0; +}; + +Storage.prototype = { + + constructor: Storage, + + /** + * @param {Function} cb + * + */ + traverse: function (cb, context) { + for (var i = 0; i < this._roots.length; i++) { + this._roots[i].traverse(cb, context); + } + }, + + /** + * 返回所有图形的绘制队列 + * @param {boolean} [update=false] 是否在返回前更新该数组 + * @param {boolean} [includeIgnore=false] 是否包含 ignore 的数组, 在 update 为 true 的时候有效 + * + * 详见{@link module:zrender/graphic/Displayable.prototype.updateDisplayList} + * @return {Array.} + */ + getDisplayList: function (update, includeIgnore) { + includeIgnore = includeIgnore || false; + if (update) { + this.updateDisplayList(includeIgnore); + } + return this._displayList; + }, + + /** + * 更新图形的绘制队列。 + * 每次绘制前都会调用,该方法会先深度优先遍历整个树,更新所有Group和Shape的变换并且把所有可见的Shape保存到数组中, + * 最后根据绘制的优先级(zlevel > z > 插入顺序)排序得到绘制队列 + * @param {boolean} [includeIgnore=false] 是否包含 ignore 的数组 + */ + updateDisplayList: function (includeIgnore) { + this._displayListLen = 0; + + var roots = this._roots; + var displayList = this._displayList; + for (var i = 0, len = roots.length; i < len; i++) { + this._updateAndAddDisplayable(roots[i], null, includeIgnore); + } + + displayList.length = this._displayListLen; + + env$1.canvasSupported && sort(displayList, shapeCompareFunc); + }, + + _updateAndAddDisplayable: function (el, clipPaths, includeIgnore) { + + if (el.ignore && !includeIgnore) { + return; + } + + el.beforeUpdate(); + + if (el.__dirty) { + + el.update(); + + } + + el.afterUpdate(); + + var userSetClipPath = el.clipPath; + if (userSetClipPath) { + + // FIXME 效率影响 + if (clipPaths) { + clipPaths = clipPaths.slice(); + } + else { + clipPaths = []; + } + + var currentClipPath = userSetClipPath; + var parentClipPath = el; + // Recursively add clip path + while (currentClipPath) { + // clipPath 的变换是基于使用这个 clipPath 的元素 + currentClipPath.parent = parentClipPath; + currentClipPath.updateTransform(); + + clipPaths.push(currentClipPath); + + parentClipPath = currentClipPath; + currentClipPath = currentClipPath.clipPath; + } + } + + if (el.isGroup) { + var children = el._children; + + for (var i = 0; i < children.length; i++) { + var child = children[i]; + + // Force to mark as dirty if group is dirty + // FIXME __dirtyPath ? + if (el.__dirty) { + child.__dirty = true; + } + + this._updateAndAddDisplayable(child, clipPaths, includeIgnore); + } + + // Mark group clean here + el.__dirty = false; + + } + else { + el.__clipPaths = clipPaths; + + this._displayList[this._displayListLen++] = el; + } + }, + + /** + * 添加图形(Shape)或者组(Group)到根节点 + * @param {module:zrender/Element} el + */ + addRoot: function (el) { + if (el.__storage === this) { + return; + } + + if (el instanceof Group) { + el.addChildrenToStorage(this); + } + + this.addToStorage(el); + this._roots.push(el); + }, + + /** + * 删除指定的图形(Shape)或者组(Group) + * @param {string|Array.} [el] 如果为空清空整个Storage + */ + delRoot: function (el) { + if (el == null) { + // 不指定el清空 + for (var i = 0; i < this._roots.length; i++) { + var root = this._roots[i]; + if (root instanceof Group) { + root.delChildrenFromStorage(this); + } + } + + this._roots = []; + this._displayList = []; + this._displayListLen = 0; + + return; + } + + if (el instanceof Array) { + for (var i = 0, l = el.length; i < l; i++) { + this.delRoot(el[i]); + } + return; + } + + + var idx = indexOf(this._roots, el); + if (idx >= 0) { + this.delFromStorage(el); + this._roots.splice(idx, 1); + if (el instanceof Group) { + el.delChildrenFromStorage(this); + } + } + }, + + addToStorage: function (el) { + if (el) { + el.__storage = this; + el.dirty(false); + } + return this; + }, + + delFromStorage: function (el) { + if (el) { + el.__storage = null; + } + + return this; + }, + + /** + * 清空并且释放Storage + */ + dispose: function () { + this._renderList = + this._roots = null; + }, + + displayableSortFunc: shapeCompareFunc +}; + +var SHADOW_PROPS = { + 'shadowBlur': 1, + 'shadowOffsetX': 1, + 'shadowOffsetY': 1, + 'textShadowBlur': 1, + 'textShadowOffsetX': 1, + 'textShadowOffsetY': 1, + 'textBoxShadowBlur': 1, + 'textBoxShadowOffsetX': 1, + 'textBoxShadowOffsetY': 1 +}; + +var fixShadow = function (ctx, propName, value) { + if (SHADOW_PROPS.hasOwnProperty(propName)) { + return value *= ctx.dpr; + } + return value; +}; + +var ContextCachedBy = { + NONE: 0, + STYLE_BIND: 1, + PLAIN_TEXT: 2 +}; + +// Avoid confused with 0/false. +var WILL_BE_RESTORED = 9; + +var STYLE_COMMON_PROPS = [ + ['shadowBlur', 0], ['shadowOffsetX', 0], ['shadowOffsetY', 0], ['shadowColor', '#000'], + ['lineCap', 'butt'], ['lineJoin', 'miter'], ['miterLimit', 10] +]; + +// var SHADOW_PROPS = STYLE_COMMON_PROPS.slice(0, 4); +// var LINE_PROPS = STYLE_COMMON_PROPS.slice(4); + +var Style = function (opts) { + this.extendFrom(opts, false); +}; + +function createLinearGradient(ctx, obj, rect) { + var x = obj.x == null ? 0 : obj.x; + var x2 = obj.x2 == null ? 1 : obj.x2; + var y = obj.y == null ? 0 : obj.y; + var y2 = obj.y2 == null ? 0 : obj.y2; + + if (!obj.global) { + x = x * rect.width + rect.x; + x2 = x2 * rect.width + rect.x; + y = y * rect.height + rect.y; + y2 = y2 * rect.height + rect.y; + } + + // Fix NaN when rect is Infinity + x = isNaN(x) ? 0 : x; + x2 = isNaN(x2) ? 1 : x2; + y = isNaN(y) ? 0 : y; + y2 = isNaN(y2) ? 0 : y2; + + var canvasGradient = ctx.createLinearGradient(x, y, x2, y2); + + return canvasGradient; +} + +function createRadialGradient(ctx, obj, rect) { + var width = rect.width; + var height = rect.height; + var min = Math.min(width, height); + + var x = obj.x == null ? 0.5 : obj.x; + var y = obj.y == null ? 0.5 : obj.y; + var r = obj.r == null ? 0.5 : obj.r; + if (!obj.global) { + x = x * width + rect.x; + y = y * height + rect.y; + r = r * min; + } + + var canvasGradient = ctx.createRadialGradient(x, y, 0, x, y, r); + + return canvasGradient; +} + + +Style.prototype = { + + constructor: Style, + + /** + * @type {string} + */ + fill: '#000', + + /** + * @type {string} + */ + stroke: null, + + /** + * @type {number} + */ + opacity: 1, + + /** + * @type {number} + */ + fillOpacity: null, + + /** + * @type {number} + */ + strokeOpacity: null, + + /** + * @type {Array.} + */ + lineDash: null, + + /** + * @type {number} + */ + lineDashOffset: 0, + + /** + * @type {number} + */ + shadowBlur: 0, + + /** + * @type {number} + */ + shadowOffsetX: 0, + + /** + * @type {number} + */ + shadowOffsetY: 0, + + /** + * @type {number} + */ + lineWidth: 1, + + /** + * If stroke ignore scale + * @type {Boolean} + */ + strokeNoScale: false, + + // Bounding rect text configuration + // Not affected by element transform + /** + * @type {string} + */ + text: null, + + /** + * If `fontSize` or `fontFamily` exists, `font` will be reset by + * `fontSize`, `fontStyle`, `fontWeight`, `fontFamily`. + * So do not visit it directly in upper application (like echarts), + * but use `contain/text#makeFont` instead. + * @type {string} + */ + font: null, + + /** + * The same as font. Use font please. + * @deprecated + * @type {string} + */ + textFont: null, + + /** + * It helps merging respectively, rather than parsing an entire font string. + * @type {string} + */ + fontStyle: null, + + /** + * It helps merging respectively, rather than parsing an entire font string. + * @type {string} + */ + fontWeight: null, + + /** + * It helps merging respectively, rather than parsing an entire font string. + * Should be 12 but not '12px'. + * @type {number} + */ + fontSize: null, + + /** + * It helps merging respectively, rather than parsing an entire font string. + * @type {string} + */ + fontFamily: null, + + /** + * Reserved for special functinality, like 'hr'. + * @type {string} + */ + textTag: null, + + /** + * @type {string} + */ + textFill: '#000', + + /** + * @type {string} + */ + textStroke: null, + + /** + * @type {number} + */ + textWidth: null, + + /** + * Only for textBackground. + * @type {number} + */ + textHeight: null, + + /** + * textStroke may be set as some color as a default + * value in upper applicaion, where the default value + * of textStrokeWidth should be 0 to make sure that + * user can choose to do not use text stroke. + * @type {number} + */ + textStrokeWidth: 0, + + /** + * @type {number} + */ + textLineHeight: null, + + /** + * 'inside', 'left', 'right', 'top', 'bottom' + * [x, y] + * Based on x, y of rect. + * @type {string|Array.} + * @default 'inside' + */ + textPosition: 'inside', + + /** + * If not specified, use the boundingRect of a `displayable`. + * @type {Object} + */ + textRect: null, + + /** + * [x, y] + * @type {Array.} + */ + textOffset: null, + + /** + * @type {string} + */ + textAlign: null, + + /** + * @type {string} + */ + textVerticalAlign: null, + + /** + * @type {number} + */ + textDistance: 5, + + /** + * @type {string} + */ + textShadowColor: 'transparent', + + /** + * @type {number} + */ + textShadowBlur: 0, + + /** + * @type {number} + */ + textShadowOffsetX: 0, + + /** + * @type {number} + */ + textShadowOffsetY: 0, + + /** + * @type {string} + */ + textBoxShadowColor: 'transparent', + + /** + * @type {number} + */ + textBoxShadowBlur: 0, + + /** + * @type {number} + */ + textBoxShadowOffsetX: 0, + + /** + * @type {number} + */ + textBoxShadowOffsetY: 0, + + /** + * Whether transform text. + * Only useful in Path and Image element + * @type {boolean} + */ + transformText: false, + + /** + * Text rotate around position of Path or Image + * Only useful in Path and Image element and transformText is false. + */ + textRotation: 0, + + /** + * Text origin of text rotation, like [10, 40]. + * Based on x, y of rect. + * Useful in label rotation of circular symbol. + * By default, this origin is textPosition. + * Can be 'center'. + * @type {string|Array.} + */ + textOrigin: null, + + /** + * @type {string} + */ + textBackgroundColor: null, + + /** + * @type {string} + */ + textBorderColor: null, + + /** + * @type {number} + */ + textBorderWidth: 0, + + /** + * @type {number} + */ + textBorderRadius: 0, + + /** + * Can be `2` or `[2, 4]` or `[2, 3, 4, 5]` + * @type {number|Array.} + */ + textPadding: null, + + /** + * Text styles for rich text. + * @type {Object} + */ + rich: null, + + /** + * {outerWidth, outerHeight, ellipsis, placeholder} + * @type {Object} + */ + truncate: null, + + /** + * https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/globalCompositeOperation + * @type {string} + */ + blend: null, + + /** + * @param {CanvasRenderingContext2D} ctx + */ + bind: function (ctx, el, prevEl) { + var style = this; + var prevStyle = prevEl && prevEl.style; + // If no prevStyle, it means first draw. + // Only apply cache if the last time cachced by this function. + var notCheckCache = !prevStyle || ctx.__attrCachedBy !== ContextCachedBy.STYLE_BIND; + + ctx.__attrCachedBy = ContextCachedBy.STYLE_BIND; + + for (var i = 0; i < STYLE_COMMON_PROPS.length; i++) { + var prop = STYLE_COMMON_PROPS[i]; + var styleName = prop[0]; + + if (notCheckCache || style[styleName] !== prevStyle[styleName]) { + // FIXME Invalid property value will cause style leak from previous element. + ctx[styleName] = + fixShadow(ctx, styleName, style[styleName] || prop[1]); + } + } + + if ((notCheckCache || style.fill !== prevStyle.fill)) { + ctx.fillStyle = style.fill; + } + if ((notCheckCache || style.stroke !== prevStyle.stroke)) { + ctx.strokeStyle = style.stroke; + } + if ((notCheckCache || style.opacity !== prevStyle.opacity)) { + ctx.globalAlpha = style.opacity == null ? 1 : style.opacity; + } + + if ((notCheckCache || style.blend !== prevStyle.blend)) { + ctx.globalCompositeOperation = style.blend || 'source-over'; + } + if (this.hasStroke()) { + var lineWidth = style.lineWidth; + ctx.lineWidth = lineWidth / ( + (this.strokeNoScale && el && el.getLineScale) ? el.getLineScale() : 1 + ); + } + }, + + hasFill: function () { + var fill = this.fill; + return fill != null && fill !== 'none'; + }, + + hasStroke: function () { + var stroke = this.stroke; + return stroke != null && stroke !== 'none' && this.lineWidth > 0; + }, + + /** + * Extend from other style + * @param {zrender/graphic/Style} otherStyle + * @param {boolean} overwrite true: overwrirte any way. + * false: overwrite only when !target.hasOwnProperty + * others: overwrite when property is not null/undefined. + */ + extendFrom: function (otherStyle, overwrite) { + if (otherStyle) { + for (var name in otherStyle) { + if (otherStyle.hasOwnProperty(name) + && (overwrite === true + || ( + overwrite === false + ? !this.hasOwnProperty(name) + : otherStyle[name] != null + ) + ) + ) { + this[name] = otherStyle[name]; + } + } + } + }, + + /** + * Batch setting style with a given object + * @param {Object|string} obj + * @param {*} [obj] + */ + set: function (obj, value) { + if (typeof obj === 'string') { + this[obj] = value; + } + else { + this.extendFrom(obj, true); + } + }, + + /** + * Clone + * @return {zrender/graphic/Style} [description] + */ + clone: function () { + var newStyle = new this.constructor(); + newStyle.extendFrom(this, true); + return newStyle; + }, + + getGradient: function (ctx, obj, rect) { + var method = obj.type === 'radial' ? createRadialGradient : createLinearGradient; + var canvasGradient = method(ctx, obj, rect); + var colorStops = obj.colorStops; + for (var i = 0; i < colorStops.length; i++) { + canvasGradient.addColorStop( + colorStops[i].offset, colorStops[i].color + ); + } + return canvasGradient; + } + +}; + +var styleProto = Style.prototype; +for (var i = 0; i < STYLE_COMMON_PROPS.length; i++) { + var prop = STYLE_COMMON_PROPS[i]; + if (!(prop[0] in styleProto)) { + styleProto[prop[0]] = prop[1]; + } +} + +// Provide for others +Style.getGradient = styleProto.getGradient; + +var Pattern = function (image, repeat) { + // Should do nothing more in this constructor. Because gradient can be + // declard by `color: {image: ...}`, where this constructor will not be called. + + this.image = image; + this.repeat = repeat; + + // Can be cloned + this.type = 'pattern'; +}; + +Pattern.prototype.getCanvasPattern = function (ctx) { + return ctx.createPattern(this.image, this.repeat || 'repeat'); +}; + +/** + * @module zrender/Layer + * @author pissang(https://www.github.com/pissang) + */ + +function returnFalse() { + return false; +} + +/** + * 创建dom + * + * @inner + * @param {string} id dom id 待用 + * @param {Painter} painter painter instance + * @param {number} number + */ +function createDom(id, painter, dpr) { + var newDom = createCanvas(); + var width = painter.getWidth(); + var height = painter.getHeight(); + + var newDomStyle = newDom.style; + if (newDomStyle) { // In node or some other non-browser environment + newDomStyle.position = 'absolute'; + newDomStyle.left = 0; + newDomStyle.top = 0; + newDomStyle.width = width + 'px'; + newDomStyle.height = height + 'px'; + + newDom.setAttribute('data-zr-dom-id', id); + } + + newDom.width = width * dpr; + newDom.height = height * dpr; + + return newDom; +} + +/** + * @alias module:zrender/Layer + * @constructor + * @extends module:zrender/mixin/Transformable + * @param {string} id + * @param {module:zrender/Painter} painter + * @param {number} [dpr] + */ +var Layer = function (id, painter, dpr) { + var dom; + dpr = dpr || devicePixelRatio; + if (typeof id === 'string') { + dom = createDom(id, painter, dpr); + } + // Not using isDom because in node it will return false + else if (isObject$1(id)) { + dom = id; + id = dom.id; + } + this.id = id; + this.dom = dom; + + var domStyle = dom.style; + if (domStyle) { // Not in node + dom.onselectstart = returnFalse; // 避免页面选中的尴尬 + domStyle['-webkit-user-select'] = 'none'; + domStyle['user-select'] = 'none'; + domStyle['-webkit-touch-callout'] = 'none'; + domStyle['-webkit-tap-highlight-color'] = 'rgba(0,0,0,0)'; + domStyle['padding'] = 0; + domStyle['margin'] = 0; + domStyle['border-width'] = 0; + } + + this.domBack = null; + this.ctxBack = null; + + this.painter = painter; + + this.config = null; + + // Configs + /** + * 每次清空画布的颜色 + * @type {string} + * @default 0 + */ + this.clearColor = 0; + /** + * 是否开启动态模糊 + * @type {boolean} + * @default false + */ + this.motionBlur = false; + /** + * 在开启动态模糊的时候使用,与上一帧混合的alpha值,值越大尾迹越明显 + * @type {number} + * @default 0.7 + */ + this.lastFrameAlpha = 0.7; + + /** + * Layer dpr + * @type {number} + */ + this.dpr = dpr; +}; + +Layer.prototype = { + + constructor: Layer, + + __dirty: true, + + __used: false, + + __drawIndex: 0, + __startIndex: 0, + __endIndex: 0, + + incremental: false, + + getElementCount: function () { + return this.__endIndex - this.__startIndex; + }, + + initContext: function () { + this.ctx = this.dom.getContext('2d'); + this.ctx.dpr = this.dpr; + }, + + createBackBuffer: function () { + var dpr = this.dpr; + + this.domBack = createDom('back-' + this.id, this.painter, dpr); + this.ctxBack = this.domBack.getContext('2d'); + + if (dpr !== 1) { + this.ctxBack.scale(dpr, dpr); + } + }, + + /** + * @param {number} width + * @param {number} height + */ + resize: function (width, height) { + var dpr = this.dpr; + + var dom = this.dom; + var domStyle = dom.style; + var domBack = this.domBack; + + if (domStyle) { + domStyle.width = width + 'px'; + domStyle.height = height + 'px'; + } + + dom.width = width * dpr; + dom.height = height * dpr; + + if (domBack) { + domBack.width = width * dpr; + domBack.height = height * dpr; + + if (dpr !== 1) { + this.ctxBack.scale(dpr, dpr); + } + } + }, + + /** + * 清空该层画布 + * @param {boolean} [clearAll]=false Clear all with out motion blur + * @param {Color} [clearColor] + */ + clear: function (clearAll, clearColor) { + var dom = this.dom; + var ctx = this.ctx; + var width = dom.width; + var height = dom.height; + + var clearColor = clearColor || this.clearColor; + var haveMotionBLur = this.motionBlur && !clearAll; + var lastFrameAlpha = this.lastFrameAlpha; + + var dpr = this.dpr; + + if (haveMotionBLur) { + if (!this.domBack) { + this.createBackBuffer(); + } + + this.ctxBack.globalCompositeOperation = 'copy'; + this.ctxBack.drawImage( + dom, 0, 0, + width / dpr, + height / dpr + ); + } + + ctx.clearRect(0, 0, width, height); + if (clearColor && clearColor !== 'transparent') { + var clearColorGradientOrPattern; + // Gradient + if (clearColor.colorStops) { + // Cache canvas gradient + clearColorGradientOrPattern = clearColor.__canvasGradient || Style.getGradient(ctx, clearColor, { + x: 0, + y: 0, + width: width, + height: height + }); + + clearColor.__canvasGradient = clearColorGradientOrPattern; + } + // Pattern + else if (clearColor.image) { + clearColorGradientOrPattern = Pattern.prototype.getCanvasPattern.call(clearColor, ctx); + } + ctx.save(); + ctx.fillStyle = clearColorGradientOrPattern || clearColor; + ctx.fillRect(0, 0, width, height); + ctx.restore(); + } + + if (haveMotionBLur) { + var domBack = this.domBack; + ctx.save(); + ctx.globalAlpha = lastFrameAlpha; + ctx.drawImage(domBack, 0, 0, width, height); + ctx.restore(); + } + } +}; + +var requestAnimationFrame = ( + typeof window !== 'undefined' + && ( + (window.requestAnimationFrame && window.requestAnimationFrame.bind(window)) + // https://github.com/ecomfe/zrender/issues/189#issuecomment-224919809 + || (window.msRequestAnimationFrame && window.msRequestAnimationFrame.bind(window)) + || window.mozRequestAnimationFrame + || window.webkitRequestAnimationFrame + ) +) || function (func) { + setTimeout(func, 16); +}; + +var globalImageCache = new LRU(50); + +/** + * @param {string|HTMLImageElement|HTMLCanvasElement|Canvas} newImageOrSrc + * @return {HTMLImageElement|HTMLCanvasElement|Canvas} image + */ +function findExistImage(newImageOrSrc) { + if (typeof newImageOrSrc === 'string') { + var cachedImgObj = globalImageCache.get(newImageOrSrc); + return cachedImgObj && cachedImgObj.image; + } + else { + return newImageOrSrc; + } +} + +/** + * Caution: User should cache loaded images, but not just count on LRU. + * Consider if required images more than LRU size, will dead loop occur? + * + * @param {string|HTMLImageElement|HTMLCanvasElement|Canvas} newImageOrSrc + * @param {HTMLImageElement|HTMLCanvasElement|Canvas} image Existent image. + * @param {module:zrender/Element} [hostEl] For calling `dirty`. + * @param {Function} [cb] params: (image, cbPayload) + * @param {Object} [cbPayload] Payload on cb calling. + * @return {HTMLImageElement|HTMLCanvasElement|Canvas} image + */ +function createOrUpdateImage(newImageOrSrc, image, hostEl, cb, cbPayload) { + if (!newImageOrSrc) { + return image; + } + else if (typeof newImageOrSrc === 'string') { + + // Image should not be loaded repeatly. + if ((image && image.__zrImageSrc === newImageOrSrc) || !hostEl) { + return image; + } + + // Only when there is no existent image or existent image src + // is different, this method is responsible for load. + var cachedImgObj = globalImageCache.get(newImageOrSrc); + + var pendingWrap = {hostEl: hostEl, cb: cb, cbPayload: cbPayload}; + + if (cachedImgObj) { + image = cachedImgObj.image; + !isImageReady(image) && cachedImgObj.pending.push(pendingWrap); + } + else { + image = new Image(); + image.onload = image.onerror = imageOnLoad; + + globalImageCache.put( + newImageOrSrc, + image.__cachedImgObj = { + image: image, + pending: [pendingWrap] + } + ); + + image.src = image.__zrImageSrc = newImageOrSrc; + } + + return image; + } + // newImageOrSrc is an HTMLImageElement or HTMLCanvasElement or Canvas + else { + return newImageOrSrc; + } +} + +function imageOnLoad() { + var cachedImgObj = this.__cachedImgObj; + this.onload = this.onerror = this.__cachedImgObj = null; + + for (var i = 0; i < cachedImgObj.pending.length; i++) { + var pendingWrap = cachedImgObj.pending[i]; + var cb = pendingWrap.cb; + cb && cb(this, pendingWrap.cbPayload); + pendingWrap.hostEl.dirty(); + } + cachedImgObj.pending.length = 0; +} + +function isImageReady(image) { + return image && image.width && image.height; +} + +var textWidthCache = {}; +var textWidthCacheCounter = 0; + +var TEXT_CACHE_MAX = 5000; +var STYLE_REG = /\{([a-zA-Z0-9_]+)\|([^}]*)\}/g; + +var DEFAULT_FONT$1 = '12px sans-serif'; + +// Avoid assign to an exported variable, for transforming to cjs. +var methods$1 = {}; + +function $override$1(name, fn) { + methods$1[name] = fn; +} + +/** + * @public + * @param {string} text + * @param {string} font + * @return {number} width + */ +function getWidth(text, font) { + font = font || DEFAULT_FONT$1; + var key = text + ':' + font; + if (textWidthCache[key]) { + return textWidthCache[key]; + } + + var textLines = (text + '').split('\n'); + var width = 0; + + for (var i = 0, l = textLines.length; i < l; i++) { + // textContain.measureText may be overrided in SVG or VML + width = Math.max(measureText(textLines[i], font).width, width); + } + + if (textWidthCacheCounter > TEXT_CACHE_MAX) { + textWidthCacheCounter = 0; + textWidthCache = {}; + } + textWidthCacheCounter++; + textWidthCache[key] = width; + + return width; +} + +/** + * @public + * @param {string} text + * @param {string} font + * @param {string} [textAlign='left'] + * @param {string} [textVerticalAlign='top'] + * @param {Array.} [textPadding] + * @param {Object} [rich] + * @param {Object} [truncate] + * @return {Object} {x, y, width, height, lineHeight} + */ +function getBoundingRect(text, font, textAlign, textVerticalAlign, textPadding, textLineHeight, rich, truncate) { + return rich + ? getRichTextRect(text, font, textAlign, textVerticalAlign, textPadding, textLineHeight, rich, truncate) + : getPlainTextRect(text, font, textAlign, textVerticalAlign, textPadding, textLineHeight, truncate); +} + +function getPlainTextRect(text, font, textAlign, textVerticalAlign, textPadding, textLineHeight, truncate) { + var contentBlock = parsePlainText(text, font, textPadding, textLineHeight, truncate); + var outerWidth = getWidth(text, font); + if (textPadding) { + outerWidth += textPadding[1] + textPadding[3]; + } + var outerHeight = contentBlock.outerHeight; + + var x = adjustTextX(0, outerWidth, textAlign); + var y = adjustTextY(0, outerHeight, textVerticalAlign); + + var rect = new BoundingRect(x, y, outerWidth, outerHeight); + rect.lineHeight = contentBlock.lineHeight; + + return rect; +} + +function getRichTextRect(text, font, textAlign, textVerticalAlign, textPadding, textLineHeight, rich, truncate) { + var contentBlock = parseRichText(text, { + rich: rich, + truncate: truncate, + font: font, + textAlign: textAlign, + textPadding: textPadding, + textLineHeight: textLineHeight + }); + var outerWidth = contentBlock.outerWidth; + var outerHeight = contentBlock.outerHeight; + + var x = adjustTextX(0, outerWidth, textAlign); + var y = adjustTextY(0, outerHeight, textVerticalAlign); + + return new BoundingRect(x, y, outerWidth, outerHeight); +} + +/** + * @public + * @param {number} x + * @param {number} width + * @param {string} [textAlign='left'] + * @return {number} Adjusted x. + */ +function adjustTextX(x, width, textAlign) { + // FIXME Right to left language + if (textAlign === 'right') { + x -= width; + } + else if (textAlign === 'center') { + x -= width / 2; + } + return x; +} + +/** + * @public + * @param {number} y + * @param {number} height + * @param {string} [textVerticalAlign='top'] + * @return {number} Adjusted y. + */ +function adjustTextY(y, height, textVerticalAlign) { + if (textVerticalAlign === 'middle') { + y -= height / 2; + } + else if (textVerticalAlign === 'bottom') { + y -= height; + } + return y; +} + +/** + * @public + * @param {stirng} textPosition + * @param {Object} rect {x, y, width, height} + * @param {number} distance + * @return {Object} {x, y, textAlign, textVerticalAlign} + */ +function adjustTextPositionOnRect(textPosition, rect, distance) { + + var x = rect.x; + var y = rect.y; + + var height = rect.height; + var width = rect.width; + var halfHeight = height / 2; + + var textAlign = 'left'; + var textVerticalAlign = 'top'; + + switch (textPosition) { + case 'left': + x -= distance; + y += halfHeight; + textAlign = 'right'; + textVerticalAlign = 'middle'; + break; + case 'right': + x += distance + width; + y += halfHeight; + textVerticalAlign = 'middle'; + break; + case 'top': + x += width / 2; + y -= distance; + textAlign = 'center'; + textVerticalAlign = 'bottom'; + break; + case 'bottom': + x += width / 2; + y += height + distance; + textAlign = 'center'; + break; + case 'inside': + x += width / 2; + y += halfHeight; + textAlign = 'center'; + textVerticalAlign = 'middle'; + break; + case 'insideLeft': + x += distance; + y += halfHeight; + textVerticalAlign = 'middle'; + break; + case 'insideRight': + x += width - distance; + y += halfHeight; + textAlign = 'right'; + textVerticalAlign = 'middle'; + break; + case 'insideTop': + x += width / 2; + y += distance; + textAlign = 'center'; + break; + case 'insideBottom': + x += width / 2; + y += height - distance; + textAlign = 'center'; + textVerticalAlign = 'bottom'; + break; + case 'insideTopLeft': + x += distance; + y += distance; + break; + case 'insideTopRight': + x += width - distance; + y += distance; + textAlign = 'right'; + break; + case 'insideBottomLeft': + x += distance; + y += height - distance; + textVerticalAlign = 'bottom'; + break; + case 'insideBottomRight': + x += width - distance; + y += height - distance; + textAlign = 'right'; + textVerticalAlign = 'bottom'; + break; + } + + return { + x: x, + y: y, + textAlign: textAlign, + textVerticalAlign: textVerticalAlign + }; +} + +/** + * Show ellipsis if overflow. + * + * @public + * @param {string} text + * @param {string} containerWidth + * @param {string} font + * @param {number} [ellipsis='...'] + * @param {Object} [options] + * @param {number} [options.maxIterations=3] + * @param {number} [options.minChar=0] If truncate result are less + * then minChar, ellipsis will not show, which is + * better for user hint in some cases. + * @param {number} [options.placeholder=''] When all truncated, use the placeholder. + * @return {string} + */ +function truncateText(text, containerWidth, font, ellipsis, options) { + if (!containerWidth) { + return ''; + } + + var textLines = (text + '').split('\n'); + options = prepareTruncateOptions(containerWidth, font, ellipsis, options); + + // FIXME + // It is not appropriate that every line has '...' when truncate multiple lines. + for (var i = 0, len = textLines.length; i < len; i++) { + textLines[i] = truncateSingleLine(textLines[i], options); + } + + return textLines.join('\n'); +} + +function prepareTruncateOptions(containerWidth, font, ellipsis, options) { + options = extend({}, options); + + options.font = font; + var ellipsis = retrieve2(ellipsis, '...'); + options.maxIterations = retrieve2(options.maxIterations, 2); + var minChar = options.minChar = retrieve2(options.minChar, 0); + // FIXME + // Other languages? + options.cnCharWidth = getWidth('国', font); + // FIXME + // Consider proportional font? + var ascCharWidth = options.ascCharWidth = getWidth('a', font); + options.placeholder = retrieve2(options.placeholder, ''); + + // Example 1: minChar: 3, text: 'asdfzxcv', truncate result: 'asdf', but not: 'a...'. + // Example 2: minChar: 3, text: '维度', truncate result: '维', but not: '...'. + var contentWidth = containerWidth = Math.max(0, containerWidth - 1); // Reserve some gap. + for (var i = 0; i < minChar && contentWidth >= ascCharWidth; i++) { + contentWidth -= ascCharWidth; + } + + var ellipsisWidth = getWidth(ellipsis, font); + if (ellipsisWidth > contentWidth) { + ellipsis = ''; + ellipsisWidth = 0; + } + + contentWidth = containerWidth - ellipsisWidth; + + options.ellipsis = ellipsis; + options.ellipsisWidth = ellipsisWidth; + options.contentWidth = contentWidth; + options.containerWidth = containerWidth; + + return options; +} + +function truncateSingleLine(textLine, options) { + var containerWidth = options.containerWidth; + var font = options.font; + var contentWidth = options.contentWidth; + + if (!containerWidth) { + return ''; + } + + var lineWidth = getWidth(textLine, font); + + if (lineWidth <= containerWidth) { + return textLine; + } + + for (var j = 0; ; j++) { + if (lineWidth <= contentWidth || j >= options.maxIterations) { + textLine += options.ellipsis; + break; + } + + var subLength = j === 0 + ? estimateLength(textLine, contentWidth, options.ascCharWidth, options.cnCharWidth) + : lineWidth > 0 + ? Math.floor(textLine.length * contentWidth / lineWidth) + : 0; + + textLine = textLine.substr(0, subLength); + lineWidth = getWidth(textLine, font); + } + + if (textLine === '') { + textLine = options.placeholder; + } + + return textLine; +} + +function estimateLength(text, contentWidth, ascCharWidth, cnCharWidth) { + var width = 0; + var i = 0; + for (var len = text.length; i < len && width < contentWidth; i++) { + var charCode = text.charCodeAt(i); + width += (0 <= charCode && charCode <= 127) ? ascCharWidth : cnCharWidth; + } + return i; +} + +/** + * @public + * @param {string} font + * @return {number} line height + */ +function getLineHeight(font) { + // FIXME A rough approach. + return getWidth('国', font); +} + +/** + * @public + * @param {string} text + * @param {string} font + * @return {Object} width + */ +function measureText(text, font) { + return methods$1.measureText(text, font); +} + +// Avoid assign to an exported variable, for transforming to cjs. +methods$1.measureText = function (text, font) { + var ctx = getContext(); + ctx.font = font || DEFAULT_FONT$1; + return ctx.measureText(text); +}; + +/** + * @public + * @param {string} text + * @param {string} font + * @param {Object} [truncate] + * @return {Object} block: {lineHeight, lines, height, outerHeight} + * Notice: for performance, do not calculate outerWidth util needed. + */ +function parsePlainText(text, font, padding, textLineHeight, truncate) { + text != null && (text += ''); + + var lineHeight = retrieve2(textLineHeight, getLineHeight(font)); + var lines = text ? text.split('\n') : []; + var height = lines.length * lineHeight; + var outerHeight = height; + + if (padding) { + outerHeight += padding[0] + padding[2]; + } + + if (text && truncate) { + var truncOuterHeight = truncate.outerHeight; + var truncOuterWidth = truncate.outerWidth; + if (truncOuterHeight != null && outerHeight > truncOuterHeight) { + text = ''; + lines = []; + } + else if (truncOuterWidth != null) { + var options = prepareTruncateOptions( + truncOuterWidth - (padding ? padding[1] + padding[3] : 0), + font, + truncate.ellipsis, + {minChar: truncate.minChar, placeholder: truncate.placeholder} + ); + + // FIXME + // It is not appropriate that every line has '...' when truncate multiple lines. + for (var i = 0, len = lines.length; i < len; i++) { + lines[i] = truncateSingleLine(lines[i], options); + } + } + } + + return { + lines: lines, + height: height, + outerHeight: outerHeight, + lineHeight: lineHeight + }; +} + +/** + * For example: 'some text {a|some text}other text{b|some text}xxx{c|}xxx' + * Also consider 'bbbb{a|xxx\nzzz}xxxx\naaaa'. + * + * @public + * @param {string} text + * @param {Object} style + * @return {Object} block + * { + * width, + * height, + * lines: [{ + * lineHeight, + * width, + * tokens: [[{ + * styleName, + * text, + * width, // include textPadding + * height, // include textPadding + * textWidth, // pure text width + * textHeight, // pure text height + * lineHeihgt, + * font, + * textAlign, + * textVerticalAlign + * }], [...], ...] + * }, ...] + * } + * If styleName is undefined, it is plain text. + */ +function parseRichText(text, style) { + var contentBlock = {lines: [], width: 0, height: 0}; + + text != null && (text += ''); + if (!text) { + return contentBlock; + } + + var lastIndex = STYLE_REG.lastIndex = 0; + var result; + while ((result = STYLE_REG.exec(text)) != null) { + var matchedIndex = result.index; + if (matchedIndex > lastIndex) { + pushTokens(contentBlock, text.substring(lastIndex, matchedIndex)); + } + pushTokens(contentBlock, result[2], result[1]); + lastIndex = STYLE_REG.lastIndex; + } + + if (lastIndex < text.length) { + pushTokens(contentBlock, text.substring(lastIndex, text.length)); + } + + var lines = contentBlock.lines; + var contentHeight = 0; + var contentWidth = 0; + // For `textWidth: 100%` + var pendingList = []; + + var stlPadding = style.textPadding; + + var truncate = style.truncate; + var truncateWidth = truncate && truncate.outerWidth; + var truncateHeight = truncate && truncate.outerHeight; + if (stlPadding) { + truncateWidth != null && (truncateWidth -= stlPadding[1] + stlPadding[3]); + truncateHeight != null && (truncateHeight -= stlPadding[0] + stlPadding[2]); + } + + // Calculate layout info of tokens. + for (var i = 0; i < lines.length; i++) { + var line = lines[i]; + var lineHeight = 0; + var lineWidth = 0; + + for (var j = 0; j < line.tokens.length; j++) { + var token = line.tokens[j]; + var tokenStyle = token.styleName && style.rich[token.styleName] || {}; + // textPadding should not inherit from style. + var textPadding = token.textPadding = tokenStyle.textPadding; + + // textFont has been asigned to font by `normalizeStyle`. + var font = token.font = tokenStyle.font || style.font; + + // textHeight can be used when textVerticalAlign is specified in token. + var tokenHeight = token.textHeight = retrieve2( + // textHeight should not be inherited, consider it can be specified + // as box height of the block. + tokenStyle.textHeight, getLineHeight(font) + ); + textPadding && (tokenHeight += textPadding[0] + textPadding[2]); + token.height = tokenHeight; + token.lineHeight = retrieve3( + tokenStyle.textLineHeight, style.textLineHeight, tokenHeight + ); + + token.textAlign = tokenStyle && tokenStyle.textAlign || style.textAlign; + token.textVerticalAlign = tokenStyle && tokenStyle.textVerticalAlign || 'middle'; + + if (truncateHeight != null && contentHeight + token.lineHeight > truncateHeight) { + return {lines: [], width: 0, height: 0}; + } + + token.textWidth = getWidth(token.text, font); + var tokenWidth = tokenStyle.textWidth; + var tokenWidthNotSpecified = tokenWidth == null || tokenWidth === 'auto'; + + // Percent width, can be `100%`, can be used in drawing separate + // line when box width is needed to be auto. + if (typeof tokenWidth === 'string' && tokenWidth.charAt(tokenWidth.length - 1) === '%') { + token.percentWidth = tokenWidth; + pendingList.push(token); + tokenWidth = 0; + // Do not truncate in this case, because there is no user case + // and it is too complicated. + } + else { + if (tokenWidthNotSpecified) { + tokenWidth = token.textWidth; + + // FIXME: If image is not loaded and textWidth is not specified, calling + // `getBoundingRect()` will not get correct result. + var textBackgroundColor = tokenStyle.textBackgroundColor; + var bgImg = textBackgroundColor && textBackgroundColor.image; + + // Use cases: + // (1) If image is not loaded, it will be loaded at render phase and call + // `dirty()` and `textBackgroundColor.image` will be replaced with the loaded + // image, and then the right size will be calculated here at the next tick. + // See `graphic/helper/text.js`. + // (2) If image loaded, and `textBackgroundColor.image` is image src string, + // use `imageHelper.findExistImage` to find cached image. + // `imageHelper.findExistImage` will always be called here before + // `imageHelper.createOrUpdateImage` in `graphic/helper/text.js#renderRichText` + // which ensures that image will not be rendered before correct size calcualted. + if (bgImg) { + bgImg = findExistImage(bgImg); + if (isImageReady(bgImg)) { + tokenWidth = Math.max(tokenWidth, bgImg.width * tokenHeight / bgImg.height); + } + } + } + + var paddingW = textPadding ? textPadding[1] + textPadding[3] : 0; + tokenWidth += paddingW; + + var remianTruncWidth = truncateWidth != null ? truncateWidth - lineWidth : null; + + if (remianTruncWidth != null && remianTruncWidth < tokenWidth) { + if (!tokenWidthNotSpecified || remianTruncWidth < paddingW) { + token.text = ''; + token.textWidth = tokenWidth = 0; + } + else { + token.text = truncateText( + token.text, remianTruncWidth - paddingW, font, truncate.ellipsis, + {minChar: truncate.minChar} + ); + token.textWidth = getWidth(token.text, font); + tokenWidth = token.textWidth + paddingW; + } + } + } + + lineWidth += (token.width = tokenWidth); + tokenStyle && (lineHeight = Math.max(lineHeight, token.lineHeight)); + } + + line.width = lineWidth; + line.lineHeight = lineHeight; + contentHeight += lineHeight; + contentWidth = Math.max(contentWidth, lineWidth); + } + + contentBlock.outerWidth = contentBlock.width = retrieve2(style.textWidth, contentWidth); + contentBlock.outerHeight = contentBlock.height = retrieve2(style.textHeight, contentHeight); + + if (stlPadding) { + contentBlock.outerWidth += stlPadding[1] + stlPadding[3]; + contentBlock.outerHeight += stlPadding[0] + stlPadding[2]; + } + + for (var i = 0; i < pendingList.length; i++) { + var token = pendingList[i]; + var percentWidth = token.percentWidth; + // Should not base on outerWidth, because token can not be placed out of padding. + token.width = parseInt(percentWidth, 10) / 100 * contentWidth; + } + + return contentBlock; +} + +function pushTokens(block, str, styleName) { + var isEmptyStr = str === ''; + var strs = str.split('\n'); + var lines = block.lines; + + for (var i = 0; i < strs.length; i++) { + var text = strs[i]; + var token = { + styleName: styleName, + text: text, + isLineHolder: !text && !isEmptyStr + }; + + // The first token should be appended to the last line. + if (!i) { + var tokens = (lines[lines.length - 1] || (lines[0] = {tokens: []})).tokens; + + // Consider cases: + // (1) ''.split('\n') => ['', '\n', ''], the '' at the first item + // (which is a placeholder) should be replaced by new token. + // (2) A image backage, where token likes {a|}. + // (3) A redundant '' will affect textAlign in line. + // (4) tokens with the same tplName should not be merged, because + // they should be displayed in different box (with border and padding). + var tokensLen = tokens.length; + (tokensLen === 1 && tokens[0].isLineHolder) + ? (tokens[0] = token) + // Consider text is '', only insert when it is the "lineHolder" or + // "emptyStr". Otherwise a redundant '' will affect textAlign in line. + : ((text || !tokensLen || isEmptyStr) && tokens.push(token)); + } + // Other tokens always start a new line. + else { + // If there is '', insert it as a placeholder. + lines.push({tokens: [token]}); + } + } +} + +function makeFont(style) { + // FIXME in node-canvas fontWeight is before fontStyle + // Use `fontSize` `fontFamily` to check whether font properties are defined. + var font = (style.fontSize || style.fontFamily) && [ + style.fontStyle, + style.fontWeight, + (style.fontSize || 12) + 'px', + // If font properties are defined, `fontFamily` should not be ignored. + style.fontFamily || 'sans-serif' + ].join(' '); + return font && trim(font) || style.textFont || style.font; +} + +/** + * @param {Object} ctx + * @param {Object} shape + * @param {number} shape.x + * @param {number} shape.y + * @param {number} shape.width + * @param {number} shape.height + * @param {number} shape.r + */ +function buildPath(ctx, shape) { + var x = shape.x; + var y = shape.y; + var width = shape.width; + var height = shape.height; + var r = shape.r; + var r1; + var r2; + var r3; + var r4; + + // Convert width and height to positive for better borderRadius + if (width < 0) { + x = x + width; + width = -width; + } + if (height < 0) { + y = y + height; + height = -height; + } + + if (typeof r === 'number') { + r1 = r2 = r3 = r4 = r; + } + else if (r instanceof Array) { + if (r.length === 1) { + r1 = r2 = r3 = r4 = r[0]; + } + else if (r.length === 2) { + r1 = r3 = r[0]; + r2 = r4 = r[1]; + } + else if (r.length === 3) { + r1 = r[0]; + r2 = r4 = r[1]; + r3 = r[2]; + } + else { + r1 = r[0]; + r2 = r[1]; + r3 = r[2]; + r4 = r[3]; + } + } + else { + r1 = r2 = r3 = r4 = 0; + } + + var total; + if (r1 + r2 > width) { + total = r1 + r2; + r1 *= width / total; + r2 *= width / total; + } + if (r3 + r4 > width) { + total = r3 + r4; + r3 *= width / total; + r4 *= width / total; + } + if (r2 + r3 > height) { + total = r2 + r3; + r2 *= height / total; + r3 *= height / total; + } + if (r1 + r4 > height) { + total = r1 + r4; + r1 *= height / total; + r4 *= height / total; + } + ctx.moveTo(x + r1, y); + ctx.lineTo(x + width - r2, y); + r2 !== 0 && ctx.arc(x + width - r2, y + r2, r2, -Math.PI / 2, 0); + ctx.lineTo(x + width, y + height - r3); + r3 !== 0 && ctx.arc(x + width - r3, y + height - r3, r3, 0, Math.PI / 2); + ctx.lineTo(x + r4, y + height); + r4 !== 0 && ctx.arc(x + r4, y + height - r4, r4, Math.PI / 2, Math.PI); + ctx.lineTo(x, y + r1); + r1 !== 0 && ctx.arc(x + r1, y + r1, r1, Math.PI, Math.PI * 1.5); +} + +var DEFAULT_FONT = DEFAULT_FONT$1; + +// TODO: Have not support 'start', 'end' yet. +var VALID_TEXT_ALIGN = {left: 1, right: 1, center: 1}; +var VALID_TEXT_VERTICAL_ALIGN = {top: 1, bottom: 1, middle: 1}; +// Different from `STYLE_COMMON_PROPS` of `graphic/Style`, +// the default value of shadowColor is `'transparent'`. +var SHADOW_STYLE_COMMON_PROPS = [ + ['textShadowBlur', 'shadowBlur', 0], + ['textShadowOffsetX', 'shadowOffsetX', 0], + ['textShadowOffsetY', 'shadowOffsetY', 0], + ['textShadowColor', 'shadowColor', 'transparent'] +]; + +/** + * @param {module:zrender/graphic/Style} style + * @return {module:zrender/graphic/Style} The input style. + */ +function normalizeTextStyle(style) { + normalizeStyle(style); + each$1(style.rich, normalizeStyle); + return style; +} + +function normalizeStyle(style) { + if (style) { + + style.font = makeFont(style); + + var textAlign = style.textAlign; + textAlign === 'middle' && (textAlign = 'center'); + style.textAlign = ( + textAlign == null || VALID_TEXT_ALIGN[textAlign] + ) ? textAlign : 'left'; + + // Compatible with textBaseline. + var textVerticalAlign = style.textVerticalAlign || style.textBaseline; + textVerticalAlign === 'center' && (textVerticalAlign = 'middle'); + style.textVerticalAlign = ( + textVerticalAlign == null || VALID_TEXT_VERTICAL_ALIGN[textVerticalAlign] + ) ? textVerticalAlign : 'top'; + + var textPadding = style.textPadding; + if (textPadding) { + style.textPadding = normalizeCssArray(style.textPadding); + } + } +} + +/** + * @param {CanvasRenderingContext2D} ctx + * @param {string} text + * @param {module:zrender/graphic/Style} style + * @param {Object|boolean} [rect] {x, y, width, height} + * If set false, rect text is not used. + * @param {Element|module:zrender/graphic/helper/constant.WILL_BE_RESTORED} [prevEl] For ctx prop cache. + */ +function renderText(hostEl, ctx, text, style, rect, prevEl) { + style.rich + ? renderRichText(hostEl, ctx, text, style, rect, prevEl) + : renderPlainText(hostEl, ctx, text, style, rect, prevEl); +} + +// Avoid setting to ctx according to prevEl if possible for +// performance in scenarios of large amount text. +function renderPlainText(hostEl, ctx, text, style, rect, prevEl) { + 'use strict'; + + var needDrawBg = needDrawBackground(style); + + var prevStyle; + var checkCache = false; + var cachedByMe = ctx.__attrCachedBy === ContextCachedBy.PLAIN_TEXT; + + // Only take and check cache for `Text` el, but not RectText. + if (prevEl !== WILL_BE_RESTORED) { + if (prevEl) { + prevStyle = prevEl.style; + checkCache = !needDrawBg && cachedByMe && prevStyle; + } + + // Prevent from using cache in `Style::bind`, because of the case: + // ctx property is modified by other properties than `Style::bind` + // used, and Style::bind is called next. + ctx.__attrCachedBy = needDrawBg ? ContextCachedBy.NONE : ContextCachedBy.PLAIN_TEXT; + } + // Since this will be restored, prevent from using these props to check cache in the next + // entering of this method. But do not need to clear other cache like `Style::bind`. + else if (cachedByMe) { + ctx.__attrCachedBy = ContextCachedBy.NONE; + } + + var styleFont = style.font || DEFAULT_FONT; + // PENDING + // Only `Text` el set `font` and keep it (`RectText` will restore). So theoretically + // we can make font cache on ctx, which can cache for text el that are discontinuous. + // But layer save/restore needed to be considered. + // if (styleFont !== ctx.__fontCache) { + // ctx.font = styleFont; + // if (prevEl !== WILL_BE_RESTORED) { + // ctx.__fontCache = styleFont; + // } + // } + if (!checkCache || styleFont !== (prevStyle.font || DEFAULT_FONT)) { + ctx.font = styleFont; + } + + // Use the final font from context-2d, because the final + // font might not be the style.font when it is illegal. + // But get `ctx.font` might be time consuming. + var computedFont = hostEl.__computedFont; + if (hostEl.__styleFont !== styleFont) { + hostEl.__styleFont = styleFont; + computedFont = hostEl.__computedFont = ctx.font; + } + + var textPadding = style.textPadding; + var textLineHeight = style.textLineHeight; + + var contentBlock = hostEl.__textCotentBlock; + if (!contentBlock || hostEl.__dirtyText) { + contentBlock = hostEl.__textCotentBlock = parsePlainText( + text, computedFont, textPadding, textLineHeight, style.truncate + ); + } + + var outerHeight = contentBlock.outerHeight; + + var textLines = contentBlock.lines; + var lineHeight = contentBlock.lineHeight; + + var boxPos = getBoxPosition(outerHeight, style, rect); + var baseX = boxPos.baseX; + var baseY = boxPos.baseY; + var textAlign = boxPos.textAlign || 'left'; + var textVerticalAlign = boxPos.textVerticalAlign; + + // Origin of textRotation should be the base point of text drawing. + applyTextRotation(ctx, style, rect, baseX, baseY); + + var boxY = adjustTextY(baseY, outerHeight, textVerticalAlign); + var textX = baseX; + var textY = boxY; + + if (needDrawBg || textPadding) { + // Consider performance, do not call getTextWidth util necessary. + var textWidth = getWidth(text, computedFont); + var outerWidth = textWidth; + textPadding && (outerWidth += textPadding[1] + textPadding[3]); + var boxX = adjustTextX(baseX, outerWidth, textAlign); + + needDrawBg && drawBackground(hostEl, ctx, style, boxX, boxY, outerWidth, outerHeight); + + if (textPadding) { + textX = getTextXForPadding(baseX, textAlign, textPadding); + textY += textPadding[0]; + } + } + + // Always set textAlign and textBase line, because it is difficute to calculate + // textAlign from prevEl, and we dont sure whether textAlign will be reset if + // font set happened. + ctx.textAlign = textAlign; + // Force baseline to be "middle". Otherwise, if using "top", the + // text will offset downward a little bit in font "Microsoft YaHei". + ctx.textBaseline = 'middle'; + // Set text opacity + ctx.globalAlpha = style.opacity || 1; + + // Always set shadowBlur and shadowOffset to avoid leak from displayable. + for (var i = 0; i < SHADOW_STYLE_COMMON_PROPS.length; i++) { + var propItem = SHADOW_STYLE_COMMON_PROPS[i]; + var styleProp = propItem[0]; + var ctxProp = propItem[1]; + var val = style[styleProp]; + if (!checkCache || val !== prevStyle[styleProp]) { + ctx[ctxProp] = fixShadow(ctx, ctxProp, val || propItem[2]); + } + } + + // `textBaseline` is set as 'middle'. + textY += lineHeight / 2; + + var textStrokeWidth = style.textStrokeWidth; + var textStrokeWidthPrev = checkCache ? prevStyle.textStrokeWidth : null; + var strokeWidthChanged = !checkCache || textStrokeWidth !== textStrokeWidthPrev; + var strokeChanged = !checkCache || strokeWidthChanged || style.textStroke !== prevStyle.textStroke; + var textStroke = getStroke(style.textStroke, textStrokeWidth); + var textFill = getFill(style.textFill); + + if (textStroke) { + if (strokeWidthChanged) { + ctx.lineWidth = textStrokeWidth; + } + if (strokeChanged) { + ctx.strokeStyle = textStroke; + } + } + if (textFill) { + if (!checkCache || style.textFill !== prevStyle.textFill) { + ctx.fillStyle = textFill; + } + } + + // Optimize simply, in most cases only one line exists. + if (textLines.length === 1) { + // Fill after stroke so the outline will not cover the main part. + textStroke && ctx.strokeText(textLines[0], textX, textY); + textFill && ctx.fillText(textLines[0], textX, textY); + } + else { + for (var i = 0; i < textLines.length; i++) { + // Fill after stroke so the outline will not cover the main part. + textStroke && ctx.strokeText(textLines[i], textX, textY); + textFill && ctx.fillText(textLines[i], textX, textY); + textY += lineHeight; + } + } +} + +function renderRichText(hostEl, ctx, text, style, rect, prevEl) { + // Do not do cache for rich text because of the complexity. + // But `RectText` this will be restored, do not need to clear other cache like `Style::bind`. + if (prevEl !== WILL_BE_RESTORED) { + ctx.__attrCachedBy = ContextCachedBy.NONE; + } + + var contentBlock = hostEl.__textCotentBlock; + + if (!contentBlock || hostEl.__dirtyText) { + contentBlock = hostEl.__textCotentBlock = parseRichText(text, style); + } + + drawRichText(hostEl, ctx, contentBlock, style, rect); +} + +function drawRichText(hostEl, ctx, contentBlock, style, rect) { + var contentWidth = contentBlock.width; + var outerWidth = contentBlock.outerWidth; + var outerHeight = contentBlock.outerHeight; + var textPadding = style.textPadding; + + var boxPos = getBoxPosition(outerHeight, style, rect); + var baseX = boxPos.baseX; + var baseY = boxPos.baseY; + var textAlign = boxPos.textAlign; + var textVerticalAlign = boxPos.textVerticalAlign; + + // Origin of textRotation should be the base point of text drawing. + applyTextRotation(ctx, style, rect, baseX, baseY); + + var boxX = adjustTextX(baseX, outerWidth, textAlign); + var boxY = adjustTextY(baseY, outerHeight, textVerticalAlign); + var xLeft = boxX; + var lineTop = boxY; + if (textPadding) { + xLeft += textPadding[3]; + lineTop += textPadding[0]; + } + var xRight = xLeft + contentWidth; + + needDrawBackground(style) && drawBackground( + hostEl, ctx, style, boxX, boxY, outerWidth, outerHeight + ); + + for (var i = 0; i < contentBlock.lines.length; i++) { + var line = contentBlock.lines[i]; + var tokens = line.tokens; + var tokenCount = tokens.length; + var lineHeight = line.lineHeight; + var usedWidth = line.width; + + var leftIndex = 0; + var lineXLeft = xLeft; + var lineXRight = xRight; + var rightIndex = tokenCount - 1; + var token; + + while ( + leftIndex < tokenCount + && (token = tokens[leftIndex], !token.textAlign || token.textAlign === 'left') + ) { + placeToken(hostEl, ctx, token, style, lineHeight, lineTop, lineXLeft, 'left'); + usedWidth -= token.width; + lineXLeft += token.width; + leftIndex++; + } + + while ( + rightIndex >= 0 + && (token = tokens[rightIndex], token.textAlign === 'right') + ) { + placeToken(hostEl, ctx, token, style, lineHeight, lineTop, lineXRight, 'right'); + usedWidth -= token.width; + lineXRight -= token.width; + rightIndex--; + } + + // The other tokens are placed as textAlign 'center' if there is enough space. + lineXLeft += (contentWidth - (lineXLeft - xLeft) - (xRight - lineXRight) - usedWidth) / 2; + while (leftIndex <= rightIndex) { + token = tokens[leftIndex]; + // Consider width specified by user, use 'center' rather than 'left'. + placeToken(hostEl, ctx, token, style, lineHeight, lineTop, lineXLeft + token.width / 2, 'center'); + lineXLeft += token.width; + leftIndex++; + } + + lineTop += lineHeight; + } +} + +function applyTextRotation(ctx, style, rect, x, y) { + // textRotation only apply in RectText. + if (rect && style.textRotation) { + var origin = style.textOrigin; + if (origin === 'center') { + x = rect.width / 2 + rect.x; + y = rect.height / 2 + rect.y; + } + else if (origin) { + x = origin[0] + rect.x; + y = origin[1] + rect.y; + } + + ctx.translate(x, y); + // Positive: anticlockwise + ctx.rotate(-style.textRotation); + ctx.translate(-x, -y); + } +} + +function placeToken(hostEl, ctx, token, style, lineHeight, lineTop, x, textAlign) { + var tokenStyle = style.rich[token.styleName] || {}; + tokenStyle.text = token.text; + + // 'ctx.textBaseline' is always set as 'middle', for sake of + // the bias of "Microsoft YaHei". + var textVerticalAlign = token.textVerticalAlign; + var y = lineTop + lineHeight / 2; + if (textVerticalAlign === 'top') { + y = lineTop + token.height / 2; + } + else if (textVerticalAlign === 'bottom') { + y = lineTop + lineHeight - token.height / 2; + } + + !token.isLineHolder && needDrawBackground(tokenStyle) && drawBackground( + hostEl, + ctx, + tokenStyle, + textAlign === 'right' + ? x - token.width + : textAlign === 'center' + ? x - token.width / 2 + : x, + y - token.height / 2, + token.width, + token.height + ); + + var textPadding = token.textPadding; + if (textPadding) { + x = getTextXForPadding(x, textAlign, textPadding); + y -= token.height / 2 - textPadding[2] - token.textHeight / 2; + } + + setCtx(ctx, 'shadowBlur', retrieve3(tokenStyle.textShadowBlur, style.textShadowBlur, 0)); + setCtx(ctx, 'shadowColor', tokenStyle.textShadowColor || style.textShadowColor || 'transparent'); + setCtx(ctx, 'shadowOffsetX', retrieve3(tokenStyle.textShadowOffsetX, style.textShadowOffsetX, 0)); + setCtx(ctx, 'shadowOffsetY', retrieve3(tokenStyle.textShadowOffsetY, style.textShadowOffsetY, 0)); + + setCtx(ctx, 'textAlign', textAlign); + // Force baseline to be "middle". Otherwise, if using "top", the + // text will offset downward a little bit in font "Microsoft YaHei". + setCtx(ctx, 'textBaseline', 'middle'); + + setCtx(ctx, 'font', token.font || DEFAULT_FONT); + + var textStroke = getStroke(tokenStyle.textStroke || style.textStroke, textStrokeWidth); + var textFill = getFill(tokenStyle.textFill || style.textFill); + var textStrokeWidth = retrieve2(tokenStyle.textStrokeWidth, style.textStrokeWidth); + + // Fill after stroke so the outline will not cover the main part. + if (textStroke) { + setCtx(ctx, 'lineWidth', textStrokeWidth); + setCtx(ctx, 'strokeStyle', textStroke); + ctx.strokeText(token.text, x, y); + } + if (textFill) { + setCtx(ctx, 'fillStyle', textFill); + ctx.fillText(token.text, x, y); + } +} + +function needDrawBackground(style) { + return !!( + style.textBackgroundColor + || (style.textBorderWidth && style.textBorderColor) + ); +} + +// style: {textBackgroundColor, textBorderWidth, textBorderColor, textBorderRadius, text} +// shape: {x, y, width, height} +function drawBackground(hostEl, ctx, style, x, y, width, height) { + var textBackgroundColor = style.textBackgroundColor; + var textBorderWidth = style.textBorderWidth; + var textBorderColor = style.textBorderColor; + var isPlainBg = isString(textBackgroundColor); + + setCtx(ctx, 'shadowBlur', style.textBoxShadowBlur || 0); + setCtx(ctx, 'shadowColor', style.textBoxShadowColor || 'transparent'); + setCtx(ctx, 'shadowOffsetX', style.textBoxShadowOffsetX || 0); + setCtx(ctx, 'shadowOffsetY', style.textBoxShadowOffsetY || 0); + + if (isPlainBg || (textBorderWidth && textBorderColor)) { + ctx.beginPath(); + var textBorderRadius = style.textBorderRadius; + if (!textBorderRadius) { + ctx.rect(x, y, width, height); + } + else { + buildPath(ctx, { + x: x, y: y, width: width, height: height, r: textBorderRadius + }); + } + ctx.closePath(); + } + + if (isPlainBg) { + setCtx(ctx, 'fillStyle', textBackgroundColor); + + if (style.fillOpacity != null) { + var originalGlobalAlpha = ctx.globalAlpha; + ctx.globalAlpha = style.fillOpacity * style.opacity; + ctx.fill(); + ctx.globalAlpha = originalGlobalAlpha; + } + else { + ctx.fill(); + } + } + else if (isObject$1(textBackgroundColor)) { + var image = textBackgroundColor.image; + + image = createOrUpdateImage( + image, null, hostEl, onBgImageLoaded, textBackgroundColor + ); + if (image && isImageReady(image)) { + ctx.drawImage(image, x, y, width, height); + } + } + + if (textBorderWidth && textBorderColor) { + setCtx(ctx, 'lineWidth', textBorderWidth); + setCtx(ctx, 'strokeStyle', textBorderColor); + + if (style.strokeOpacity != null) { + var originalGlobalAlpha = ctx.globalAlpha; + ctx.globalAlpha = style.strokeOpacity * style.opacity; + ctx.stroke(); + ctx.globalAlpha = originalGlobalAlpha; + } + else { + ctx.stroke(); + } + } +} + +function onBgImageLoaded(image, textBackgroundColor) { + // Replace image, so that `contain/text.js#parseRichText` + // will get correct result in next tick. + textBackgroundColor.image = image; +} + +function getBoxPosition(blockHeiht, style, rect) { + var baseX = style.x || 0; + var baseY = style.y || 0; + var textAlign = style.textAlign; + var textVerticalAlign = style.textVerticalAlign; + + // Text position represented by coord + if (rect) { + var textPosition = style.textPosition; + if (textPosition instanceof Array) { + // Percent + baseX = rect.x + parsePercent(textPosition[0], rect.width); + baseY = rect.y + parsePercent(textPosition[1], rect.height); + } + else { + var res = adjustTextPositionOnRect( + textPosition, rect, style.textDistance + ); + baseX = res.x; + baseY = res.y; + // Default align and baseline when has textPosition + textAlign = textAlign || res.textAlign; + textVerticalAlign = textVerticalAlign || res.textVerticalAlign; + } + + // textOffset is only support in RectText, otherwise + // we have to adjust boundingRect for textOffset. + var textOffset = style.textOffset; + if (textOffset) { + baseX += textOffset[0]; + baseY += textOffset[1]; + } + } + + return { + baseX: baseX, + baseY: baseY, + textAlign: textAlign, + textVerticalAlign: textVerticalAlign + }; +} + +function setCtx(ctx, prop, value) { + ctx[prop] = fixShadow(ctx, prop, value); + return ctx[prop]; +} + +/** + * @param {string} [stroke] If specified, do not check style.textStroke. + * @param {string} [lineWidth] If specified, do not check style.textStroke. + * @param {number} style + */ +function getStroke(stroke, lineWidth) { + return (stroke == null || lineWidth <= 0 || stroke === 'transparent' || stroke === 'none') + ? null + // TODO pattern and gradient? + : (stroke.image || stroke.colorStops) + ? '#000' + : stroke; +} + +function getFill(fill) { + return (fill == null || fill === 'none') + ? null + // TODO pattern and gradient? + : (fill.image || fill.colorStops) + ? '#000' + : fill; +} + +function parsePercent(value, maxValue) { + if (typeof value === 'string') { + if (value.lastIndexOf('%') >= 0) { + return parseFloat(value) / 100 * maxValue; + } + return parseFloat(value); + } + return value; +} + +function getTextXForPadding(x, textAlign, textPadding) { + return textAlign === 'right' + ? (x - textPadding[1]) + : textAlign === 'center' + ? (x + textPadding[3] / 2 - textPadding[1] / 2) + : (x + textPadding[3]); +} + +/** + * @param {string} text + * @param {module:zrender/Style} style + * @return {boolean} + */ +function needDrawText(text, style) { + return text != null + && (text + || style.textBackgroundColor + || (style.textBorderWidth && style.textBorderColor) + || style.textPadding + ); +} + +/** + * Mixin for drawing text in a element bounding rect + * @module zrender/mixin/RectText + */ + +var tmpRect$1 = new BoundingRect(); + +var RectText = function () {}; + +RectText.prototype = { + + constructor: RectText, + + /** + * Draw text in a rect with specified position. + * @param {CanvasRenderingContext2D} ctx + * @param {Object} rect Displayable rect + */ + drawRectText: function (ctx, rect) { + var style = this.style; + + rect = style.textRect || rect; + + // Optimize, avoid normalize every time. + this.__dirty && normalizeTextStyle(style, true); + + var text = style.text; + + // Convert to string + text != null && (text += ''); + + if (!needDrawText(text, style)) { + return; + } + + // FIXME + // Do not provide prevEl to `textHelper.renderText` for ctx prop cache, + // but use `ctx.save()` and `ctx.restore()`. Because the cache for rect + // text propably break the cache for its host elements. + ctx.save(); + + // Transform rect to view space + var transform = this.transform; + if (!style.transformText) { + if (transform) { + tmpRect$1.copy(rect); + tmpRect$1.applyTransform(transform); + rect = tmpRect$1; + } + } + else { + this.setTransform(ctx); + } + + // transformText and textRotation can not be used at the same time. + renderText(this, ctx, text, style, rect, WILL_BE_RESTORED); + + ctx.restore(); + } +}; + +/** + * 可绘制的图形基类 + * Base class of all displayable graphic objects + * @module zrender/graphic/Displayable + */ + + +/** + * @alias module:zrender/graphic/Displayable + * @extends module:zrender/Element + * @extends module:zrender/graphic/mixin/RectText + */ +function Displayable(opts) { + + opts = opts || {}; + + Element.call(this, opts); + + // Extend properties + for (var name in opts) { + if ( + opts.hasOwnProperty(name) + && name !== 'style' + ) { + this[name] = opts[name]; + } + } + + /** + * @type {module:zrender/graphic/Style} + */ + this.style = new Style(opts.style, this); + + this._rect = null; + // Shapes for cascade clipping. + this.__clipPaths = []; + + // FIXME Stateful must be mixined after style is setted + // Stateful.call(this, opts); +} + +Displayable.prototype = { + + constructor: Displayable, + + type: 'displayable', + + /** + * Displayable 是否为脏,Painter 中会根据该标记判断是否需要是否需要重新绘制 + * Dirty flag. From which painter will determine if this displayable object needs brush + * @name module:zrender/graphic/Displayable#__dirty + * @type {boolean} + */ + __dirty: true, + + /** + * 图形是否可见,为true时不绘制图形,但是仍能触发鼠标事件 + * If ignore drawing of the displayable object. Mouse event will still be triggered + * @name module:/zrender/graphic/Displayable#invisible + * @type {boolean} + * @default false + */ + invisible: false, + + /** + * @name module:/zrender/graphic/Displayable#z + * @type {number} + * @default 0 + */ + z: 0, + + /** + * @name module:/zrender/graphic/Displayable#z + * @type {number} + * @default 0 + */ + z2: 0, + + /** + * z层level,决定绘画在哪层canvas中 + * @name module:/zrender/graphic/Displayable#zlevel + * @type {number} + * @default 0 + */ + zlevel: 0, + + /** + * 是否可拖拽 + * @name module:/zrender/graphic/Displayable#draggable + * @type {boolean} + * @default false + */ + draggable: false, + + /** + * 是否正在拖拽 + * @name module:/zrender/graphic/Displayable#draggable + * @type {boolean} + * @default false + */ + dragging: false, + + /** + * 是否相应鼠标事件 + * @name module:/zrender/graphic/Displayable#silent + * @type {boolean} + * @default false + */ + silent: false, + + /** + * If enable culling + * @type {boolean} + * @default false + */ + culling: false, + + /** + * Mouse cursor when hovered + * @name module:/zrender/graphic/Displayable#cursor + * @type {string} + */ + cursor: 'pointer', + + /** + * If hover area is bounding rect + * @name module:/zrender/graphic/Displayable#rectHover + * @type {string} + */ + rectHover: false, + + /** + * Render the element progressively when the value >= 0, + * usefull for large data. + * @type {boolean} + */ + progressive: false, + + /** + * @type {boolean} + */ + incremental: false, + /** + * Scale ratio for global scale. + * @type {boolean} + */ + globalScaleRatio: 1, + + beforeBrush: function (ctx) {}, + + afterBrush: function (ctx) {}, + + /** + * 图形绘制方法 + * @param {CanvasRenderingContext2D} ctx + */ + // Interface + brush: function (ctx, prevEl) {}, + + /** + * 获取最小包围盒 + * @return {module:zrender/core/BoundingRect} + */ + // Interface + getBoundingRect: function () {}, + + /** + * 判断坐标 x, y 是否在图形上 + * If displayable element contain coord x, y + * @param {number} x + * @param {number} y + * @return {boolean} + */ + contain: function (x, y) { + return this.rectContain(x, y); + }, + + /** + * @param {Function} cb + * @param {} context + */ + traverse: function (cb, context) { + cb.call(context, this); + }, + + /** + * 判断坐标 x, y 是否在图形的包围盒上 + * If bounding rect of element contain coord x, y + * @param {number} x + * @param {number} y + * @return {boolean} + */ + rectContain: function (x, y) { + var coord = this.transformCoordToLocal(x, y); + var rect = this.getBoundingRect(); + return rect.contain(coord[0], coord[1]); + }, + + /** + * 标记图形元素为脏,并且在下一帧重绘 + * Mark displayable element dirty and refresh next frame + */ + dirty: function () { + this.__dirty = this.__dirtyText = true; + + this._rect = null; + + this.__zr && this.__zr.refresh(); + }, + + /** + * 图形是否会触发事件 + * If displayable object binded any event + * @return {boolean} + */ + // TODO, 通过 bind 绑定的事件 + // isSilent: function () { + // return !( + // this.hoverable || this.draggable + // || this.onmousemove || this.onmouseover || this.onmouseout + // || this.onmousedown || this.onmouseup || this.onclick + // || this.ondragenter || this.ondragover || this.ondragleave + // || this.ondrop + // ); + // }, + /** + * Alias for animate('style') + * @param {boolean} loop + */ + animateStyle: function (loop) { + return this.animate('style', loop); + }, + + attrKV: function (key, value) { + if (key !== 'style') { + Element.prototype.attrKV.call(this, key, value); + } + else { + this.style.set(value); + } + }, + + /** + * @param {Object|string} key + * @param {*} value + */ + setStyle: function (key, value) { + this.style.set(key, value); + this.dirty(false); + return this; + }, + + /** + * Use given style object + * @param {Object} obj + */ + useStyle: function (obj) { + this.style = new Style(obj, this); + this.dirty(false); + return this; + } +}; + +inherits(Displayable, Element); + +mixin(Displayable, RectText); + +/** + * @alias zrender/graphic/Image + * @extends module:zrender/graphic/Displayable + * @constructor + * @param {Object} opts + */ +function ZImage(opts) { + Displayable.call(this, opts); +} + +ZImage.prototype = { + + constructor: ZImage, + + type: 'image', + + brush: function (ctx, prevEl) { + var style = this.style; + var src = style.image; + + // Must bind each time + style.bind(ctx, this, prevEl); + + var image = this._image = createOrUpdateImage( + src, + this._image, + this, + this.onload + ); + + if (!image || !isImageReady(image)) { + return; + } + + // 图片已经加载完成 + // if (image.nodeName.toUpperCase() == 'IMG') { + // if (!image.complete) { + // return; + // } + // } + // Else is canvas + + var x = style.x || 0; + var y = style.y || 0; + var width = style.width; + var height = style.height; + var aspect = image.width / image.height; + if (width == null && height != null) { + // Keep image/height ratio + width = height * aspect; + } + else if (height == null && width != null) { + height = width / aspect; + } + else if (width == null && height == null) { + width = image.width; + height = image.height; + } + + // 设置transform + this.setTransform(ctx); + + if (style.sWidth && style.sHeight) { + var sx = style.sx || 0; + var sy = style.sy || 0; + ctx.drawImage( + image, + sx, sy, style.sWidth, style.sHeight, + x, y, width, height + ); + } + else if (style.sx && style.sy) { + var sx = style.sx; + var sy = style.sy; + var sWidth = width - sx; + var sHeight = height - sy; + ctx.drawImage( + image, + sx, sy, sWidth, sHeight, + x, y, width, height + ); + } + else { + ctx.drawImage(image, x, y, width, height); + } + + // Draw rect text + if (style.text != null) { + // Only restore transform when needs draw text. + this.restoreTransform(ctx); + this.drawRectText(ctx, this.getBoundingRect()); + } + }, + + getBoundingRect: function () { + var style = this.style; + if (!this._rect) { + this._rect = new BoundingRect( + style.x || 0, style.y || 0, style.width || 0, style.height || 0 + ); + } + return this._rect; + } +}; + +inherits(ZImage, Displayable); + +var HOVER_LAYER_ZLEVEL = 1e5; +var CANVAS_ZLEVEL = 314159; + +var EL_AFTER_INCREMENTAL_INC = 0.01; +var INCREMENTAL_INC = 0.001; + +function parseInt10(val) { + return parseInt(val, 10); +} + +function isLayerValid(layer) { + if (!layer) { + return false; + } + + if (layer.__builtin__) { + return true; + } + + if (typeof (layer.resize) !== 'function' + || typeof (layer.refresh) !== 'function' + ) { + return false; + } + + return true; +} + +var tmpRect = new BoundingRect(0, 0, 0, 0); +var viewRect = new BoundingRect(0, 0, 0, 0); +function isDisplayableCulled(el, width, height) { + tmpRect.copy(el.getBoundingRect()); + if (el.transform) { + tmpRect.applyTransform(el.transform); + } + viewRect.width = width; + viewRect.height = height; + return !tmpRect.intersect(viewRect); +} + +function isClipPathChanged(clipPaths, prevClipPaths) { + if (clipPaths === prevClipPaths) { // Can both be null or undefined + return false; + } + + if (!clipPaths || !prevClipPaths || (clipPaths.length !== prevClipPaths.length)) { + return true; + } + for (var i = 0; i < clipPaths.length; i++) { + if (clipPaths[i] !== prevClipPaths[i]) { + return true; + } + } +} + +function doClip(clipPaths, ctx) { + for (var i = 0; i < clipPaths.length; i++) { + var clipPath = clipPaths[i]; + + clipPath.setTransform(ctx); + ctx.beginPath(); + clipPath.buildPath(ctx, clipPath.shape); + ctx.clip(); + // Transform back + clipPath.restoreTransform(ctx); + } +} + +function createRoot(width, height) { + var domRoot = document.createElement('div'); + + // domRoot.onselectstart = returnFalse; // 避免页面选中的尴尬 + domRoot.style.cssText = [ + 'position:relative', + 'overflow:hidden', + 'width:' + width + 'px', + 'height:' + height + 'px', + 'padding:0', + 'margin:0', + 'border-width:0' + ].join(';') + ';'; + + return domRoot; +} + + +/** + * @alias module:zrender/Painter + * @constructor + * @param {HTMLElement} root 绘图容器 + * @param {module:zrender/Storage} storage + * @param {Object} opts + */ +var Painter = function (root, storage, opts) { + + this.type = 'canvas'; + + // In node environment using node-canvas + var singleCanvas = !root.nodeName // In node ? + || root.nodeName.toUpperCase() === 'CANVAS'; + + this._opts = opts = extend({}, opts || {}); + + /** + * @type {number} + */ + this.dpr = opts.devicePixelRatio || devicePixelRatio; + /** + * @type {boolean} + * @private + */ + this._singleCanvas = singleCanvas; + /** + * 绘图容器 + * @type {HTMLElement} + */ + this.root = root; + + var rootStyle = root.style; + + if (rootStyle) { + rootStyle['-webkit-tap-highlight-color'] = 'transparent'; + rootStyle['-webkit-user-select'] = + rootStyle['user-select'] = + rootStyle['-webkit-touch-callout'] = 'none'; + + root.innerHTML = ''; + } + + /** + * @type {module:zrender/Storage} + */ + this.storage = storage; + + /** + * @type {Array.} + * @private + */ + var zlevelList = this._zlevelList = []; + + /** + * @type {Object.} + * @private + */ + var layers = this._layers = {}; + + /** + * @type {Object.} + * @private + */ + this._layerConfig = {}; + + /** + * zrender will do compositing when root is a canvas and have multiple zlevels. + */ + this._needsManuallyCompositing = false; + + if (!singleCanvas) { + this._width = this._getSize(0); + this._height = this._getSize(1); + + var domRoot = this._domRoot = createRoot( + this._width, this._height + ); + root.appendChild(domRoot); + } + else { + var width = root.width; + var height = root.height; + + if (opts.width != null) { + width = opts.width; + } + if (opts.height != null) { + height = opts.height; + } + this.dpr = opts.devicePixelRatio || 1; + + // Use canvas width and height directly + root.width = width * this.dpr; + root.height = height * this.dpr; + + this._width = width; + this._height = height; + + // Create layer if only one given canvas + // Device can be specified to create a high dpi image. + var mainLayer = new Layer(root, this, this.dpr); + mainLayer.__builtin__ = true; + mainLayer.initContext(); + // FIXME Use canvas width and height + // mainLayer.resize(width, height); + layers[CANVAS_ZLEVEL] = mainLayer; + mainLayer.zlevel = CANVAS_ZLEVEL; + // Not use common zlevel. + zlevelList.push(CANVAS_ZLEVEL); + + this._domRoot = root; + } + + /** + * @type {module:zrender/Layer} + * @private + */ + this._hoverlayer = null; + + this._hoverElements = []; +}; + +Painter.prototype = { + + constructor: Painter, + + getType: function () { + return 'canvas'; + }, + + /** + * If painter use a single canvas + * @return {boolean} + */ + isSingleCanvas: function () { + return this._singleCanvas; + }, + /** + * @return {HTMLDivElement} + */ + getViewportRoot: function () { + return this._domRoot; + }, + + getViewportRootOffset: function () { + var viewportRoot = this.getViewportRoot(); + if (viewportRoot) { + return { + offsetLeft: viewportRoot.offsetLeft || 0, + offsetTop: viewportRoot.offsetTop || 0 + }; + } + }, + + /** + * 刷新 + * @param {boolean} [paintAll=false] 强制绘制所有displayable + */ + refresh: function (paintAll) { + + var list = this.storage.getDisplayList(true); + + var zlevelList = this._zlevelList; + + this._redrawId = Math.random(); + + this._paintList(list, paintAll, this._redrawId); + + // Paint custum layers + for (var i = 0; i < zlevelList.length; i++) { + var z = zlevelList[i]; + var layer = this._layers[z]; + if (!layer.__builtin__ && layer.refresh) { + var clearColor = i === 0 ? this._backgroundColor : null; + layer.refresh(clearColor); + } + } + + this.refreshHover(); + + return this; + }, + + addHover: function (el, hoverStyle) { + if (el.__hoverMir) { + return; + } + var elMirror = new el.constructor({ + style: el.style, + shape: el.shape, + z: el.z, + z2: el.z2, + silent: el.silent + }); + elMirror.__from = el; + el.__hoverMir = elMirror; + hoverStyle && elMirror.setStyle(hoverStyle); + this._hoverElements.push(elMirror); + + return elMirror; + }, + + removeHover: function (el) { + var elMirror = el.__hoverMir; + var hoverElements = this._hoverElements; + var idx = indexOf(hoverElements, elMirror); + if (idx >= 0) { + hoverElements.splice(idx, 1); + } + el.__hoverMir = null; + }, + + clearHover: function (el) { + var hoverElements = this._hoverElements; + for (var i = 0; i < hoverElements.length; i++) { + var from = hoverElements[i].__from; + if (from) { + from.__hoverMir = null; + } + } + hoverElements.length = 0; + }, + + refreshHover: function () { + var hoverElements = this._hoverElements; + var len = hoverElements.length; + var hoverLayer = this._hoverlayer; + hoverLayer && hoverLayer.clear(); + + if (!len) { + return; + } + sort(hoverElements, this.storage.displayableSortFunc); + + // Use a extream large zlevel + // FIXME? + if (!hoverLayer) { + hoverLayer = this._hoverlayer = this.getLayer(HOVER_LAYER_ZLEVEL); + } + + var scope = {}; + hoverLayer.ctx.save(); + for (var i = 0; i < len;) { + var el = hoverElements[i]; + var originalEl = el.__from; + // Original el is removed + // PENDING + if (!(originalEl && originalEl.__zr)) { + hoverElements.splice(i, 1); + originalEl.__hoverMir = null; + len--; + continue; + } + i++; + + // Use transform + // FIXME style and shape ? + if (!originalEl.invisible) { + el.transform = originalEl.transform; + el.invTransform = originalEl.invTransform; + el.__clipPaths = originalEl.__clipPaths; + // el. + this._doPaintEl(el, hoverLayer, true, scope); + } + } + + hoverLayer.ctx.restore(); + }, + + getHoverLayer: function () { + return this.getLayer(HOVER_LAYER_ZLEVEL); + }, + + _paintList: function (list, paintAll, redrawId) { + if (this._redrawId !== redrawId) { + return; + } + + paintAll = paintAll || false; + + this._updateLayerStatus(list); + + var finished = this._doPaintList(list, paintAll); + + if (this._needsManuallyCompositing) { + this._compositeManually(); + } + + if (!finished) { + var self = this; + requestAnimationFrame(function () { + self._paintList(list, paintAll, redrawId); + }); + } + }, + + _compositeManually: function () { + var ctx = this.getLayer(CANVAS_ZLEVEL).ctx; + var width = this._domRoot.width; + var height = this._domRoot.height; + ctx.clearRect(0, 0, width, height); + // PENDING, If only builtin layer? + this.eachBuiltinLayer(function (layer) { + if (layer.virtual) { + ctx.drawImage(layer.dom, 0, 0, width, height); + } + }); + }, + + _doPaintList: function (list, paintAll) { + var layerList = []; + for (var zi = 0; zi < this._zlevelList.length; zi++) { + var zlevel = this._zlevelList[zi]; + var layer = this._layers[zlevel]; + if (layer.__builtin__ + && layer !== this._hoverlayer + && (layer.__dirty || paintAll) + ) { + layerList.push(layer); + } + } + + var finished = true; + + for (var k = 0; k < layerList.length; k++) { + var layer = layerList[k]; + var ctx = layer.ctx; + var scope = {}; + ctx.save(); + + var start = paintAll ? layer.__startIndex : layer.__drawIndex; + + var useTimer = !paintAll && layer.incremental && Date.now; + var startTime = useTimer && Date.now(); + + var clearColor = layer.zlevel === this._zlevelList[0] + ? this._backgroundColor : null; + // All elements in this layer are cleared. + if (layer.__startIndex === layer.__endIndex) { + layer.clear(false, clearColor); + } + else if (start === layer.__startIndex) { + var firstEl = list[start]; + if (!firstEl.incremental || !firstEl.notClear || paintAll) { + layer.clear(false, clearColor); + } + } + if (start === -1) { + console.error('For some unknown reason. drawIndex is -1'); + start = layer.__startIndex; + } + for (var i = start; i < layer.__endIndex; i++) { + var el = list[i]; + this._doPaintEl(el, layer, paintAll, scope); + el.__dirty = el.__dirtyText = false; + + if (useTimer) { + // Date.now can be executed in 13,025,305 ops/second. + var dTime = Date.now() - startTime; + // Give 15 millisecond to draw. + // The rest elements will be drawn in the next frame. + if (dTime > 15) { + break; + } + } + } + + layer.__drawIndex = i; + + if (layer.__drawIndex < layer.__endIndex) { + finished = false; + } + + if (scope.prevElClipPaths) { + // Needs restore the state. If last drawn element is in the clipping area. + ctx.restore(); + } + + ctx.restore(); + } + + if (env$1.wxa) { + // Flush for weixin application + each$1(this._layers, function (layer) { + if (layer && layer.ctx && layer.ctx.draw) { + layer.ctx.draw(); + } + }); + } + + return finished; + }, + + _doPaintEl: function (el, currentLayer, forcePaint, scope) { + var ctx = currentLayer.ctx; + var m = el.transform; + if ( + (currentLayer.__dirty || forcePaint) + // Ignore invisible element + && !el.invisible + // Ignore transparent element + && el.style.opacity !== 0 + // Ignore scale 0 element, in some environment like node-canvas + // Draw a scale 0 element can cause all following draw wrong + // And setTransform with scale 0 will cause set back transform failed. + && !(m && !m[0] && !m[3]) + // Ignore culled element + && !(el.culling && isDisplayableCulled(el, this._width, this._height)) + ) { + + var clipPaths = el.__clipPaths; + + // Optimize when clipping on group with several elements + if (!scope.prevElClipPaths + || isClipPathChanged(clipPaths, scope.prevElClipPaths) + ) { + // If has previous clipping state, restore from it + if (scope.prevElClipPaths) { + currentLayer.ctx.restore(); + scope.prevElClipPaths = null; + + // Reset prevEl since context has been restored + scope.prevEl = null; + } + // New clipping state + if (clipPaths) { + ctx.save(); + doClip(clipPaths, ctx); + scope.prevElClipPaths = clipPaths; + } + } + el.beforeBrush && el.beforeBrush(ctx); + + el.brush(ctx, scope.prevEl || null); + scope.prevEl = el; + + el.afterBrush && el.afterBrush(ctx); + } + }, + + /** + * 获取 zlevel 所在层,如果不存在则会创建一个新的层 + * @param {number} zlevel + * @param {boolean} virtual Virtual layer will not be inserted into dom. + * @return {module:zrender/Layer} + */ + getLayer: function (zlevel, virtual) { + if (this._singleCanvas && !this._needsManuallyCompositing) { + zlevel = CANVAS_ZLEVEL; + } + var layer = this._layers[zlevel]; + if (!layer) { + // Create a new layer + layer = new Layer('zr_' + zlevel, this, this.dpr); + layer.zlevel = zlevel; + layer.__builtin__ = true; + + if (this._layerConfig[zlevel]) { + merge(layer, this._layerConfig[zlevel], true); + } + + if (virtual) { + layer.virtual = virtual; + } + + this.insertLayer(zlevel, layer); + + // Context is created after dom inserted to document + // Or excanvas will get 0px clientWidth and clientHeight + layer.initContext(); + } + + return layer; + }, + + insertLayer: function (zlevel, layer) { + + var layersMap = this._layers; + var zlevelList = this._zlevelList; + var len = zlevelList.length; + var prevLayer = null; + var i = -1; + var domRoot = this._domRoot; + + if (layersMap[zlevel]) { + zrLog('ZLevel ' + zlevel + ' has been used already'); + return; + } + // Check if is a valid layer + if (!isLayerValid(layer)) { + zrLog('Layer of zlevel ' + zlevel + ' is not valid'); + return; + } + + if (len > 0 && zlevel > zlevelList[0]) { + for (i = 0; i < len - 1; i++) { + if ( + zlevelList[i] < zlevel + && zlevelList[i + 1] > zlevel + ) { + break; + } + } + prevLayer = layersMap[zlevelList[i]]; + } + zlevelList.splice(i + 1, 0, zlevel); + + layersMap[zlevel] = layer; + + // Vitual layer will not directly show on the screen. + // (It can be a WebGL layer and assigned to a ZImage element) + // But it still under management of zrender. + if (!layer.virtual) { + if (prevLayer) { + var prevDom = prevLayer.dom; + if (prevDom.nextSibling) { + domRoot.insertBefore( + layer.dom, + prevDom.nextSibling + ); + } + else { + domRoot.appendChild(layer.dom); + } + } + else { + if (domRoot.firstChild) { + domRoot.insertBefore(layer.dom, domRoot.firstChild); + } + else { + domRoot.appendChild(layer.dom); + } + } + } + }, + + // Iterate each layer + eachLayer: function (cb, context) { + var zlevelList = this._zlevelList; + var z; + var i; + for (i = 0; i < zlevelList.length; i++) { + z = zlevelList[i]; + cb.call(context, this._layers[z], z); + } + }, + + // Iterate each buildin layer + eachBuiltinLayer: function (cb, context) { + var zlevelList = this._zlevelList; + var layer; + var z; + var i; + for (i = 0; i < zlevelList.length; i++) { + z = zlevelList[i]; + layer = this._layers[z]; + if (layer.__builtin__) { + cb.call(context, layer, z); + } + } + }, + + // Iterate each other layer except buildin layer + eachOtherLayer: function (cb, context) { + var zlevelList = this._zlevelList; + var layer; + var z; + var i; + for (i = 0; i < zlevelList.length; i++) { + z = zlevelList[i]; + layer = this._layers[z]; + if (!layer.__builtin__) { + cb.call(context, layer, z); + } + } + }, + + /** + * 获取所有已创建的层 + * @param {Array.} [prevLayer] + */ + getLayers: function () { + return this._layers; + }, + + _updateLayerStatus: function (list) { + + this.eachBuiltinLayer(function (layer, z) { + layer.__dirty = layer.__used = false; + }); + + function updatePrevLayer(idx) { + if (prevLayer) { + if (prevLayer.__endIndex !== idx) { + prevLayer.__dirty = true; + } + prevLayer.__endIndex = idx; + } + } + + if (this._singleCanvas) { + for (var i = 1; i < list.length; i++) { + var el = list[i]; + if (el.zlevel !== list[i - 1].zlevel || el.incremental) { + this._needsManuallyCompositing = true; + break; + } + } + } + + var prevLayer = null; + var incrementalLayerCount = 0; + for (var i = 0; i < list.length; i++) { + var el = list[i]; + var zlevel = el.zlevel; + var layer; + // PENDING If change one incremental element style ? + // TODO Where there are non-incremental elements between incremental elements. + if (el.incremental) { + layer = this.getLayer(zlevel + INCREMENTAL_INC, this._needsManuallyCompositing); + layer.incremental = true; + incrementalLayerCount = 1; + } + else { + layer = this.getLayer(zlevel + (incrementalLayerCount > 0 ? EL_AFTER_INCREMENTAL_INC : 0), this._needsManuallyCompositing); + } + + if (!layer.__builtin__) { + zrLog('ZLevel ' + zlevel + ' has been used by unkown layer ' + layer.id); + } + + if (layer !== prevLayer) { + layer.__used = true; + if (layer.__startIndex !== i) { + layer.__dirty = true; + } + layer.__startIndex = i; + if (!layer.incremental) { + layer.__drawIndex = i; + } + else { + // Mark layer draw index needs to update. + layer.__drawIndex = -1; + } + updatePrevLayer(i); + prevLayer = layer; + } + if (el.__dirty) { + layer.__dirty = true; + if (layer.incremental && layer.__drawIndex < 0) { + // Start draw from the first dirty element. + layer.__drawIndex = i; + } + } + } + + updatePrevLayer(i); + + this.eachBuiltinLayer(function (layer, z) { + // Used in last frame but not in this frame. Needs clear + if (!layer.__used && layer.getElementCount() > 0) { + layer.__dirty = true; + layer.__startIndex = layer.__endIndex = layer.__drawIndex = 0; + } + // For incremental layer. In case start index changed and no elements are dirty. + if (layer.__dirty && layer.__drawIndex < 0) { + layer.__drawIndex = layer.__startIndex; + } + }); + }, + + /** + * 清除hover层外所有内容 + */ + clear: function () { + this.eachBuiltinLayer(this._clearLayer); + return this; + }, + + _clearLayer: function (layer) { + layer.clear(); + }, + + setBackgroundColor: function (backgroundColor) { + this._backgroundColor = backgroundColor; + }, + + /** + * 修改指定zlevel的绘制参数 + * + * @param {string} zlevel + * @param {Object} config 配置对象 + * @param {string} [config.clearColor=0] 每次清空画布的颜色 + * @param {string} [config.motionBlur=false] 是否开启动态模糊 + * @param {number} [config.lastFrameAlpha=0.7] + * 在开启动态模糊的时候使用,与上一帧混合的alpha值,值越大尾迹越明显 + */ + configLayer: function (zlevel, config) { + if (config) { + var layerConfig = this._layerConfig; + if (!layerConfig[zlevel]) { + layerConfig[zlevel] = config; + } + else { + merge(layerConfig[zlevel], config, true); + } + + for (var i = 0; i < this._zlevelList.length; i++) { + var _zlevel = this._zlevelList[i]; + if (_zlevel === zlevel || _zlevel === zlevel + EL_AFTER_INCREMENTAL_INC) { + var layer = this._layers[_zlevel]; + merge(layer, layerConfig[zlevel], true); + } + } + } + }, + + /** + * 删除指定层 + * @param {number} zlevel 层所在的zlevel + */ + delLayer: function (zlevel) { + var layers = this._layers; + var zlevelList = this._zlevelList; + var layer = layers[zlevel]; + if (!layer) { + return; + } + layer.dom.parentNode.removeChild(layer.dom); + delete layers[zlevel]; + + zlevelList.splice(indexOf(zlevelList, zlevel), 1); + }, + + /** + * 区域大小变化后重绘 + */ + resize: function (width, height) { + if (!this._domRoot.style) { // Maybe in node or worker + if (width == null || height == null) { + return; + } + this._width = width; + this._height = height; + + this.getLayer(CANVAS_ZLEVEL).resize(width, height); + } + else { + var domRoot = this._domRoot; + // FIXME Why ? + domRoot.style.display = 'none'; + + // Save input w/h + var opts = this._opts; + width != null && (opts.width = width); + height != null && (opts.height = height); + + width = this._getSize(0); + height = this._getSize(1); + + domRoot.style.display = ''; + + // 优化没有实际改变的resize + if (this._width !== width || height !== this._height) { + domRoot.style.width = width + 'px'; + domRoot.style.height = height + 'px'; + + for (var id in this._layers) { + if (this._layers.hasOwnProperty(id)) { + this._layers[id].resize(width, height); + } + } + each$1(this._progressiveLayers, function (layer) { + layer.resize(width, height); + }); + + this.refresh(true); + } + + this._width = width; + this._height = height; + + } + return this; + }, + + /** + * 清除单独的一个层 + * @param {number} zlevel + */ + clearLayer: function (zlevel) { + var layer = this._layers[zlevel]; + if (layer) { + layer.clear(); + } + }, + + /** + * 释放 + */ + dispose: function () { + this.root.innerHTML = ''; + + this.root = + this.storage = + + this._domRoot = + this._layers = null; + }, + + /** + * Get canvas which has all thing rendered + * @param {Object} opts + * @param {string} [opts.backgroundColor] + * @param {number} [opts.pixelRatio] + */ + getRenderedCanvas: function (opts) { + opts = opts || {}; + if (this._singleCanvas && !this._compositeManually) { + return this._layers[CANVAS_ZLEVEL].dom; + } + + var imageLayer = new Layer('image', this, opts.pixelRatio || this.dpr); + imageLayer.initContext(); + imageLayer.clear(false, opts.backgroundColor || this._backgroundColor); + + if (opts.pixelRatio <= this.dpr) { + this.refresh(); + + var width = imageLayer.dom.width; + var height = imageLayer.dom.height; + var ctx = imageLayer.ctx; + this.eachLayer(function (layer) { + if (layer.__builtin__) { + ctx.drawImage(layer.dom, 0, 0, width, height); + } + else if (layer.renderToCanvas) { + imageLayer.ctx.save(); + layer.renderToCanvas(imageLayer.ctx); + imageLayer.ctx.restore(); + } + }); + } + else { + // PENDING, echarts-gl and incremental rendering. + var scope = {}; + var displayList = this.storage.getDisplayList(true); + for (var i = 0; i < displayList.length; i++) { + var el = displayList[i]; + this._doPaintEl(el, imageLayer, true, scope); + } + } + + return imageLayer.dom; + }, + /** + * 获取绘图区域宽度 + */ + getWidth: function () { + return this._width; + }, + + /** + * 获取绘图区域高度 + */ + getHeight: function () { + return this._height; + }, + + _getSize: function (whIdx) { + var opts = this._opts; + var wh = ['width', 'height'][whIdx]; + var cwh = ['clientWidth', 'clientHeight'][whIdx]; + var plt = ['paddingLeft', 'paddingTop'][whIdx]; + var prb = ['paddingRight', 'paddingBottom'][whIdx]; + + if (opts[wh] != null && opts[wh] !== 'auto') { + return parseFloat(opts[wh]); + } + + var root = this.root; + // IE8 does not support getComputedStyle, but it use VML. + var stl = document.defaultView.getComputedStyle(root); + + return ( + (root[cwh] || parseInt10(stl[wh]) || parseInt10(root.style[wh])) + - (parseInt10(stl[plt]) || 0) + - (parseInt10(stl[prb]) || 0) + ) | 0; + }, + + pathToImage: function (path, dpr) { + dpr = dpr || this.dpr; + + var canvas = document.createElement('canvas'); + var ctx = canvas.getContext('2d'); + var rect = path.getBoundingRect(); + var style = path.style; + var shadowBlurSize = style.shadowBlur * dpr; + var shadowOffsetX = style.shadowOffsetX * dpr; + var shadowOffsetY = style.shadowOffsetY * dpr; + var lineWidth = style.hasStroke() ? style.lineWidth : 0; + + var leftMargin = Math.max(lineWidth / 2, -shadowOffsetX + shadowBlurSize); + var rightMargin = Math.max(lineWidth / 2, shadowOffsetX + shadowBlurSize); + var topMargin = Math.max(lineWidth / 2, -shadowOffsetY + shadowBlurSize); + var bottomMargin = Math.max(lineWidth / 2, shadowOffsetY + shadowBlurSize); + var width = rect.width + leftMargin + rightMargin; + var height = rect.height + topMargin + bottomMargin; + + canvas.width = width * dpr; + canvas.height = height * dpr; + + ctx.scale(dpr, dpr); + ctx.clearRect(0, 0, width, height); + ctx.dpr = dpr; + + var pathTransform = { + position: path.position, + rotation: path.rotation, + scale: path.scale + }; + path.position = [leftMargin - rect.x, topMargin - rect.y]; + path.rotation = 0; + path.scale = [1, 1]; + path.updateTransform(); + if (path) { + path.brush(ctx); + } + + var ImageShape = ZImage; + var imgShape = new ImageShape({ + style: { + x: 0, + y: 0, + image: canvas + } + }); + + if (pathTransform.position != null) { + imgShape.position = path.position = pathTransform.position; + } + + if (pathTransform.rotation != null) { + imgShape.rotation = path.rotation = pathTransform.rotation; + } + + if (pathTransform.scale != null) { + imgShape.scale = path.scale = pathTransform.scale; + } + + return imgShape; + } +}; + +/** + * 动画主类, 调度和管理所有动画控制器 + * + * @module zrender/animation/Animation + * @author pissang(https://github.com/pissang) + */ +// TODO Additive animation +// http://iosoteric.com/additive-animations-animatewithduration-in-ios-8/ +// https://developer.apple.com/videos/wwdc2014/#236 + +/** + * @typedef {Object} IZRenderStage + * @property {Function} update + */ + +/** + * @alias module:zrender/animation/Animation + * @constructor + * @param {Object} [options] + * @param {Function} [options.onframe] + * @param {IZRenderStage} [options.stage] + * @example + * var animation = new Animation(); + * var obj = { + * x: 100, + * y: 100 + * }; + * animation.animate(node.position) + * .when(1000, { + * x: 500, + * y: 500 + * }) + * .when(2000, { + * x: 100, + * y: 100 + * }) + * .start('spline'); + */ +var Animation = function (options) { + + options = options || {}; + + this.stage = options.stage || {}; + + this.onframe = options.onframe || function () {}; + + // private properties + this._clips = []; + + this._running = false; + + this._time; + + this._pausedTime; + + this._pauseStart; + + this._paused = false; + + Eventful.call(this); +}; + +Animation.prototype = { + + constructor: Animation, + /** + * 添加 clip + * @param {module:zrender/animation/Clip} clip + */ + addClip: function (clip) { + this._clips.push(clip); + }, + /** + * 添加 animator + * @param {module:zrender/animation/Animator} animator + */ + addAnimator: function (animator) { + animator.animation = this; + var clips = animator.getClips(); + for (var i = 0; i < clips.length; i++) { + this.addClip(clips[i]); + } + }, + /** + * 删除动画片段 + * @param {module:zrender/animation/Clip} clip + */ + removeClip: function (clip) { + var idx = indexOf(this._clips, clip); + if (idx >= 0) { + this._clips.splice(idx, 1); + } + }, + + /** + * 删除动画片段 + * @param {module:zrender/animation/Animator} animator + */ + removeAnimator: function (animator) { + var clips = animator.getClips(); + for (var i = 0; i < clips.length; i++) { + this.removeClip(clips[i]); + } + animator.animation = null; + }, + + _update: function () { + var time = new Date().getTime() - this._pausedTime; + var delta = time - this._time; + var clips = this._clips; + var len = clips.length; + + var deferredEvents = []; + var deferredClips = []; + for (var i = 0; i < len; i++) { + var clip = clips[i]; + var e = clip.step(time, delta); + // Throw out the events need to be called after + // stage.update, like destroy + if (e) { + deferredEvents.push(e); + deferredClips.push(clip); + } + } + + // Remove the finished clip + for (var i = 0; i < len;) { + if (clips[i]._needsRemove) { + clips[i] = clips[len - 1]; + clips.pop(); + len--; + } + else { + i++; + } + } + + len = deferredEvents.length; + for (var i = 0; i < len; i++) { + deferredClips[i].fire(deferredEvents[i]); + } + + this._time = time; + + this.onframe(delta); + + // 'frame' should be triggered before stage, because upper application + // depends on the sequence (e.g., echarts-stream and finish + // event judge) + this.trigger('frame', delta); + + if (this.stage.update) { + this.stage.update(); + } + }, + + _startLoop: function () { + var self = this; + + this._running = true; + + function step() { + if (self._running) { + + requestAnimationFrame(step); + + !self._paused && self._update(); + } + } + + requestAnimationFrame(step); + }, + + /** + * Start animation. + */ + start: function () { + + this._time = new Date().getTime(); + this._pausedTime = 0; + + this._startLoop(); + }, + + /** + * Stop animation. + */ + stop: function () { + this._running = false; + }, + + /** + * Pause animation. + */ + pause: function () { + if (!this._paused) { + this._pauseStart = new Date().getTime(); + this._paused = true; + } + }, + + /** + * Resume animation. + */ + resume: function () { + if (this._paused) { + this._pausedTime += (new Date().getTime()) - this._pauseStart; + this._paused = false; + } + }, + + /** + * Clear animation. + */ + clear: function () { + this._clips = []; + }, + + /** + * Whether animation finished. + */ + isFinished: function () { + return !this._clips.length; + }, + + /** + * Creat animator for a target, whose props can be animated. + * + * @param {Object} target + * @param {Object} options + * @param {boolean} [options.loop=false] Whether loop animation. + * @param {Function} [options.getter=null] Get value from target. + * @param {Function} [options.setter=null] Set value to target. + * @return {module:zrender/animation/Animation~Animator} + */ + // TODO Gap + animate: function (target, options) { + options = options || {}; + + var animator = new Animator( + target, + options.loop, + options.getter, + options.setter + ); + + this.addAnimator(animator); + + return animator; + } +}; + +mixin(Animation, Eventful); + +var TOUCH_CLICK_DELAY = 300; + +var mouseHandlerNames = [ + 'click', 'dblclick', 'mousewheel', 'mouseout', + 'mouseup', 'mousedown', 'mousemove', 'contextmenu' +]; + +var touchHandlerNames = [ + 'touchstart', 'touchend', 'touchmove' +]; + +var pointerEventNames = { + pointerdown: 1, pointerup: 1, pointermove: 1, pointerout: 1 +}; + +var pointerHandlerNames = map(mouseHandlerNames, function (name) { + var nm = name.replace('mouse', 'pointer'); + return pointerEventNames[nm] ? nm : name; +}); + +function eventNameFix(name) { + return (name === 'mousewheel' && env$1.browser.firefox) ? 'DOMMouseScroll' : name; +} + +// function onMSGestureChange(proxy, event) { +// if (event.translationX || event.translationY) { +// // mousemove is carried by MSGesture to reduce the sensitivity. +// proxy.handler.dispatchToElement(event.target, 'mousemove', event); +// } +// if (event.scale !== 1) { +// event.pinchX = event.offsetX; +// event.pinchY = event.offsetY; +// event.pinchScale = event.scale; +// proxy.handler.dispatchToElement(event.target, 'pinch', event); +// } +// } + +/** + * Prevent mouse event from being dispatched after Touch Events action + * @see + * 1. Mobile browsers dispatch mouse events 300ms after touchend. + * 2. Chrome for Android dispatch mousedown for long-touch about 650ms + * Result: Blocking Mouse Events for 700ms. + */ +function setTouchTimer(instance) { + instance._touching = true; + clearTimeout(instance._touchTimer); + instance._touchTimer = setTimeout(function () { + instance._touching = false; + }, 700); +} + + +var domHandlers = { + /** + * Mouse move handler + * @inner + * @param {Event} event + */ + mousemove: function (event) { + event = normalizeEvent(this.dom, event); + + this.trigger('mousemove', event); + }, + + /** + * Mouse out handler + * @inner + * @param {Event} event + */ + mouseout: function (event) { + event = normalizeEvent(this.dom, event); + + var element = event.toElement || event.relatedTarget; + if (element !== this.dom) { + while (element && element.nodeType !== 9) { + // 忽略包含在root中的dom引起的mouseOut + if (element === this.dom) { + return; + } + + element = element.parentNode; + } + } + + this.trigger('mouseout', event); + }, + + /** + * Touch开始响应函数 + * @inner + * @param {Event} event + */ + touchstart: function (event) { + // Default mouse behaviour should not be disabled here. + // For example, page may needs to be slided. + event = normalizeEvent(this.dom, event); + + // Mark touch, which is useful in distinguish touch and + // mouse event in upper applicatoin. + event.zrByTouch = true; + + this._lastTouchMoment = new Date(); + + this.handler.processGesture(this, event, 'start'); + + // In touch device, trigger `mousemove`(`mouseover`) should + // be triggered, and must before `mousedown` triggered. + domHandlers.mousemove.call(this, event); + + domHandlers.mousedown.call(this, event); + + setTouchTimer(this); + }, + + /** + * Touch移动响应函数 + * @inner + * @param {Event} event + */ + touchmove: function (event) { + + event = normalizeEvent(this.dom, event); + + // Mark touch, which is useful in distinguish touch and + // mouse event in upper applicatoin. + event.zrByTouch = true; + + this.handler.processGesture(this, event, 'change'); + + // Mouse move should always be triggered no matter whether + // there is gestrue event, because mouse move and pinch may + // be used at the same time. + domHandlers.mousemove.call(this, event); + + setTouchTimer(this); + }, + + /** + * Touch结束响应函数 + * @inner + * @param {Event} event + */ + touchend: function (event) { + + event = normalizeEvent(this.dom, event); + + // Mark touch, which is useful in distinguish touch and + // mouse event in upper applicatoin. + event.zrByTouch = true; + + this.handler.processGesture(this, event, 'end'); + + domHandlers.mouseup.call(this, event); + + // Do not trigger `mouseout` here, in spite of `mousemove`(`mouseover`) is + // triggered in `touchstart`. This seems to be illogical, but by this mechanism, + // we can conveniently implement "hover style" in both PC and touch device just + // by listening to `mouseover` to add "hover style" and listening to `mouseout` + // to remove "hover style" on an element, without any additional code for + // compatibility. (`mouseout` will not be triggered in `touchend`, so "hover + // style" will remain for user view) + + // click event should always be triggered no matter whether + // there is gestrue event. System click can not be prevented. + if (+new Date() - this._lastTouchMoment < TOUCH_CLICK_DELAY) { + domHandlers.click.call(this, event); + } + + setTouchTimer(this); + }, + + pointerdown: function (event) { + domHandlers.mousedown.call(this, event); + + // if (useMSGuesture(this, event)) { + // this._msGesture.addPointer(event.pointerId); + // } + }, + + pointermove: function (event) { + // FIXME + // pointermove is so sensitive that it always triggered when + // tap(click) on touch screen, which affect some judgement in + // upper application. So, we dont support mousemove on MS touch + // device yet. + if (!isPointerFromTouch(event)) { + domHandlers.mousemove.call(this, event); + } + }, + + pointerup: function (event) { + domHandlers.mouseup.call(this, event); + }, + + pointerout: function (event) { + // pointerout will be triggered when tap on touch screen + // (IE11+/Edge on MS Surface) after click event triggered, + // which is inconsistent with the mousout behavior we defined + // in touchend. So we unify them. + // (check domHandlers.touchend for detailed explanation) + if (!isPointerFromTouch(event)) { + domHandlers.mouseout.call(this, event); + } + } +}; + +function isPointerFromTouch(event) { + var pointerType = event.pointerType; + return pointerType === 'pen' || pointerType === 'touch'; +} + +// function useMSGuesture(handlerProxy, event) { +// return isPointerFromTouch(event) && !!handlerProxy._msGesture; +// } + +// Common handlers +each$1(['click', 'mousedown', 'mouseup', 'mousewheel', 'dblclick', 'contextmenu'], function (name) { + domHandlers[name] = function (event) { + event = normalizeEvent(this.dom, event); + this.trigger(name, event); + }; +}); + +/** + * 为控制类实例初始化dom 事件处理函数 + * + * @inner + * @param {module:zrender/Handler} instance 控制类实例 + */ +function initDomHandler(instance) { + each$1(touchHandlerNames, function (name) { + instance._handlers[name] = bind(domHandlers[name], instance); + }); + + each$1(pointerHandlerNames, function (name) { + instance._handlers[name] = bind(domHandlers[name], instance); + }); + + each$1(mouseHandlerNames, function (name) { + instance._handlers[name] = makeMouseHandler(domHandlers[name], instance); + }); + + function makeMouseHandler(fn, instance) { + return function () { + if (instance._touching) { + return; + } + return fn.apply(instance, arguments); + }; + } +} + + +function HandlerDomProxy(dom) { + Eventful.call(this); + + this.dom = dom; + + /** + * @private + * @type {boolean} + */ + this._touching = false; + + /** + * @private + * @type {number} + */ + this._touchTimer; + + this._handlers = {}; + + initDomHandler(this); + + if (env$1.pointerEventsSupported) { // Only IE11+/Edge + // 1. On devices that both enable touch and mouse (e.g., MS Surface and lenovo X240), + // IE11+/Edge do not trigger touch event, but trigger pointer event and mouse event + // at the same time. + // 2. On MS Surface, it probablely only trigger mousedown but no mouseup when tap on + // screen, which do not occurs in pointer event. + // So we use pointer event to both detect touch gesture and mouse behavior. + mountHandlers(pointerHandlerNames, this); + + // FIXME + // Note: MS Gesture require CSS touch-action set. But touch-action is not reliable, + // which does not prevent defuault behavior occasionally (which may cause view port + // zoomed in but use can not zoom it back). And event.preventDefault() does not work. + // So we have to not to use MSGesture and not to support touchmove and pinch on MS + // touch screen. And we only support click behavior on MS touch screen now. + + // MS Gesture Event is only supported on IE11+/Edge and on Windows 8+. + // We dont support touch on IE on win7. + // See + // if (typeof MSGesture === 'function') { + // (this._msGesture = new MSGesture()).target = dom; // jshint ignore:line + // dom.addEventListener('MSGestureChange', onMSGestureChange); + // } + } + else { + if (env$1.touchEventsSupported) { + mountHandlers(touchHandlerNames, this); + // Handler of 'mouseout' event is needed in touch mode, which will be mounted below. + // addEventListener(root, 'mouseout', this._mouseoutHandler); + } + + // 1. Considering some devices that both enable touch and mouse event (like on MS Surface + // and lenovo X240, @see #2350), we make mouse event be always listened, otherwise + // mouse event can not be handle in those devices. + // 2. On MS Surface, Chrome will trigger both touch event and mouse event. How to prevent + // mouseevent after touch event triggered, see `setTouchTimer`. + mountHandlers(mouseHandlerNames, this); + } + + function mountHandlers(handlerNames, instance) { + each$1(handlerNames, function (name) { + addEventListener(dom, eventNameFix(name), instance._handlers[name]); + }, instance); + } +} + +var handlerDomProxyProto = HandlerDomProxy.prototype; +handlerDomProxyProto.dispose = function () { + var handlerNames = mouseHandlerNames.concat(touchHandlerNames); + + for (var i = 0; i < handlerNames.length; i++) { + var name = handlerNames[i]; + removeEventListener(this.dom, eventNameFix(name), this._handlers[name]); + } +}; + +handlerDomProxyProto.setCursor = function (cursorStyle) { + this.dom.style && (this.dom.style.cursor = cursorStyle || 'default'); +}; + +mixin(HandlerDomProxy, Eventful); + +/*! +* ZRender, a high performance 2d drawing library. +* +* Copyright (c) 2013, Baidu Inc. +* All rights reserved. +* +* LICENSE +* https://github.com/ecomfe/zrender/blob/master/LICENSE.txt +*/ + +var useVML = !env$1.canvasSupported; + +var painterCtors = { + canvas: Painter +}; + +var instances$1 = {}; // ZRender实例map索引 + +/** + * @type {string} + */ +var version$1 = '4.0.7'; + +/** + * Initializing a zrender instance + * @param {HTMLElement} dom + * @param {Object} [opts] + * @param {string} [opts.renderer='canvas'] 'canvas' or 'svg' + * @param {number} [opts.devicePixelRatio] + * @param {number|string} [opts.width] Can be 'auto' (the same as null/undefined) + * @param {number|string} [opts.height] Can be 'auto' (the same as null/undefined) + * @return {module:zrender/ZRender} + */ +function init$1(dom, opts) { + var zr = new ZRender(guid(), dom, opts); + instances$1[zr.id] = zr; + return zr; +} + +/** + * Dispose zrender instance + * @param {module:zrender/ZRender} zr + */ +function dispose$1(zr) { + if (zr) { + zr.dispose(); + } + else { + for (var key in instances$1) { + if (instances$1.hasOwnProperty(key)) { + instances$1[key].dispose(); + } + } + instances$1 = {}; + } + + return this; +} + +/** + * Get zrender instance by id + * @param {string} id zrender instance id + * @return {module:zrender/ZRender} + */ +function getInstance(id) { + return instances$1[id]; +} + +function registerPainter(name, Ctor) { + painterCtors[name] = Ctor; +} + +function delInstance(id) { + delete instances$1[id]; +} + +/** + * @module zrender/ZRender + */ +/** + * @constructor + * @alias module:zrender/ZRender + * @param {string} id + * @param {HTMLElement} dom + * @param {Object} opts + * @param {string} [opts.renderer='canvas'] 'canvas' or 'svg' + * @param {number} [opts.devicePixelRatio] + * @param {number} [opts.width] Can be 'auto' (the same as null/undefined) + * @param {number} [opts.height] Can be 'auto' (the same as null/undefined) + */ +var ZRender = function (id, dom, opts) { + + opts = opts || {}; + + /** + * @type {HTMLDomElement} + */ + this.dom = dom; + + /** + * @type {string} + */ + this.id = id; + + var self = this; + var storage = new Storage(); + + var rendererType = opts.renderer; + // TODO WebGL + if (useVML) { + if (!painterCtors.vml) { + throw new Error('You need to require \'zrender/vml/vml\' to support IE8'); + } + rendererType = 'vml'; + } + else if (!rendererType || !painterCtors[rendererType]) { + rendererType = 'canvas'; + } + var painter = new painterCtors[rendererType](dom, storage, opts, id); + + this.storage = storage; + this.painter = painter; + + var handerProxy = (!env$1.node && !env$1.worker) ? new HandlerDomProxy(painter.getViewportRoot()) : null; + this.handler = new Handler(storage, painter, handerProxy, painter.root); + + /** + * @type {module:zrender/animation/Animation} + */ + this.animation = new Animation({ + stage: { + update: bind(this.flush, this) + } + }); + this.animation.start(); + + /** + * @type {boolean} + * @private + */ + this._needsRefresh; + + // 修改 storage.delFromStorage, 每次删除元素之前删除动画 + // FIXME 有点ugly + var oldDelFromStorage = storage.delFromStorage; + var oldAddToStorage = storage.addToStorage; + + storage.delFromStorage = function (el) { + oldDelFromStorage.call(storage, el); + + el && el.removeSelfFromZr(self); + }; + + storage.addToStorage = function (el) { + oldAddToStorage.call(storage, el); + + el.addSelfToZr(self); + }; +}; + +ZRender.prototype = { + + constructor: ZRender, + /** + * 获取实例唯一标识 + * @return {string} + */ + getId: function () { + return this.id; + }, + + /** + * 添加元素 + * @param {module:zrender/Element} el + */ + add: function (el) { + this.storage.addRoot(el); + this._needsRefresh = true; + }, + + /** + * 删除元素 + * @param {module:zrender/Element} el + */ + remove: function (el) { + this.storage.delRoot(el); + this._needsRefresh = true; + }, + + /** + * Change configuration of layer + * @param {string} zLevel + * @param {Object} config + * @param {string} [config.clearColor=0] Clear color + * @param {string} [config.motionBlur=false] If enable motion blur + * @param {number} [config.lastFrameAlpha=0.7] Motion blur factor. Larger value cause longer trailer + */ + configLayer: function (zLevel, config) { + if (this.painter.configLayer) { + this.painter.configLayer(zLevel, config); + } + this._needsRefresh = true; + }, + + /** + * Set background color + * @param {string} backgroundColor + */ + setBackgroundColor: function (backgroundColor) { + if (this.painter.setBackgroundColor) { + this.painter.setBackgroundColor(backgroundColor); + } + this._needsRefresh = true; + }, + + /** + * Repaint the canvas immediately + */ + refreshImmediately: function () { + // var start = new Date(); + // Clear needsRefresh ahead to avoid something wrong happens in refresh + // Or it will cause zrender refreshes again and again. + this._needsRefresh = false; + this.painter.refresh(); + /** + * Avoid trigger zr.refresh in Element#beforeUpdate hook + */ + this._needsRefresh = false; + // var end = new Date(); + // var log = document.getElementById('log'); + // if (log) { + // log.innerHTML = log.innerHTML + '
' + (end - start); + // } + }, + + /** + * Mark and repaint the canvas in the next frame of browser + */ + refresh: function () { + this._needsRefresh = true; + }, + + /** + * Perform all refresh + */ + flush: function () { + var triggerRendered; + + if (this._needsRefresh) { + triggerRendered = true; + this.refreshImmediately(); + } + if (this._needsRefreshHover) { + triggerRendered = true; + this.refreshHoverImmediately(); + } + + triggerRendered && this.trigger('rendered'); + }, + + /** + * Add element to hover layer + * @param {module:zrender/Element} el + * @param {Object} style + */ + addHover: function (el, style) { + if (this.painter.addHover) { + var elMirror = this.painter.addHover(el, style); + this.refreshHover(); + return elMirror; + } + }, + + /** + * Add element from hover layer + * @param {module:zrender/Element} el + */ + removeHover: function (el) { + if (this.painter.removeHover) { + this.painter.removeHover(el); + this.refreshHover(); + } + }, + + /** + * Clear all hover elements in hover layer + * @param {module:zrender/Element} el + */ + clearHover: function () { + if (this.painter.clearHover) { + this.painter.clearHover(); + this.refreshHover(); + } + }, + + /** + * Refresh hover in next frame + */ + refreshHover: function () { + this._needsRefreshHover = true; + }, + + /** + * Refresh hover immediately + */ + refreshHoverImmediately: function () { + this._needsRefreshHover = false; + this.painter.refreshHover && this.painter.refreshHover(); + }, + + /** + * Resize the canvas. + * Should be invoked when container size is changed + * @param {Object} [opts] + * @param {number|string} [opts.width] Can be 'auto' (the same as null/undefined) + * @param {number|string} [opts.height] Can be 'auto' (the same as null/undefined) + */ + resize: function (opts) { + opts = opts || {}; + this.painter.resize(opts.width, opts.height); + this.handler.resize(); + }, + + /** + * Stop and clear all animation immediately + */ + clearAnimation: function () { + this.animation.clear(); + }, + + /** + * Get container width + */ + getWidth: function () { + return this.painter.getWidth(); + }, + + /** + * Get container height + */ + getHeight: function () { + return this.painter.getHeight(); + }, + + /** + * Export the canvas as Base64 URL + * @param {string} type + * @param {string} [backgroundColor='#fff'] + * @return {string} Base64 URL + */ + // toDataURL: function(type, backgroundColor) { + // return this.painter.getRenderedCanvas({ + // backgroundColor: backgroundColor + // }).toDataURL(type); + // }, + + /** + * Converting a path to image. + * It has much better performance of drawing image rather than drawing a vector path. + * @param {module:zrender/graphic/Path} e + * @param {number} width + * @param {number} height + */ + pathToImage: function (e, dpr) { + return this.painter.pathToImage(e, dpr); + }, + + /** + * Set default cursor + * @param {string} [cursorStyle='default'] 例如 crosshair + */ + setCursorStyle: function (cursorStyle) { + this.handler.setCursorStyle(cursorStyle); + }, + + /** + * Find hovered element + * @param {number} x + * @param {number} y + * @return {Object} {target, topTarget} + */ + findHover: function (x, y) { + return this.handler.findHover(x, y); + }, + + /** + * Bind event + * + * @param {string} eventName Event name + * @param {Function} eventHandler Handler function + * @param {Object} [context] Context object + */ + on: function (eventName, eventHandler, context) { + this.handler.on(eventName, eventHandler, context); + }, + + /** + * Unbind event + * @param {string} eventName Event name + * @param {Function} [eventHandler] Handler function + */ + off: function (eventName, eventHandler) { + this.handler.off(eventName, eventHandler); + }, + + /** + * Trigger event manually + * + * @param {string} eventName Event name + * @param {event=} event Event object + */ + trigger: function (eventName, event) { + this.handler.trigger(eventName, event); + }, + + + /** + * Clear all objects and the canvas. + */ + clear: function () { + this.storage.delRoot(); + this.painter.clear(); + }, + + /** + * Dispose self. + */ + dispose: function () { + this.animation.stop(); + + this.clear(); + this.storage.dispose(); + this.painter.dispose(); + this.handler.dispose(); + + this.animation = + this.storage = + this.painter = + this.handler = null; + + delInstance(this.id); + } +}; + + + +var zrender = (Object.freeze || Object)({ + version: version$1, + init: init$1, + dispose: dispose$1, + getInstance: getInstance, + registerPainter: registerPainter +}); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var each$2 = each$1; +var isObject$2 = isObject$1; +var isArray$1 = isArray; + +/** + * Make the name displayable. But we should + * make sure it is not duplicated with user + * specified name, so use '\0'; + */ +var DUMMY_COMPONENT_NAME_PREFIX = 'series\0'; + +/** + * If value is not array, then translate it to array. + * @param {*} value + * @return {Array} [value] or value + */ +function normalizeToArray(value) { + return value instanceof Array + ? value + : value == null + ? [] + : [value]; +} + +/** + * Sync default option between normal and emphasis like `position` and `show` + * In case some one will write code like + * label: { + * show: false, + * position: 'outside', + * fontSize: 18 + * }, + * emphasis: { + * label: { show: true } + * } + * @param {Object} opt + * @param {string} key + * @param {Array.} subOpts + */ +function defaultEmphasis(opt, key, subOpts) { + // Caution: performance sensitive. + if (opt) { + opt[key] = opt[key] || {}; + opt.emphasis = opt.emphasis || {}; + opt.emphasis[key] = opt.emphasis[key] || {}; + + // Default emphasis option from normal + for (var i = 0, len = subOpts.length; i < len; i++) { + var subOptName = subOpts[i]; + if (!opt.emphasis[key].hasOwnProperty(subOptName) + && opt[key].hasOwnProperty(subOptName) + ) { + opt.emphasis[key][subOptName] = opt[key][subOptName]; + } + } + } +} + +var TEXT_STYLE_OPTIONS = [ + 'fontStyle', 'fontWeight', 'fontSize', 'fontFamily', + 'rich', 'tag', 'color', 'textBorderColor', 'textBorderWidth', + 'width', 'height', 'lineHeight', 'align', 'verticalAlign', 'baseline', + 'shadowColor', 'shadowBlur', 'shadowOffsetX', 'shadowOffsetY', + 'textShadowColor', 'textShadowBlur', 'textShadowOffsetX', 'textShadowOffsetY', + 'backgroundColor', 'borderColor', 'borderWidth', 'borderRadius', 'padding' +]; + +// modelUtil.LABEL_OPTIONS = modelUtil.TEXT_STYLE_OPTIONS.concat([ +// 'position', 'offset', 'rotate', 'origin', 'show', 'distance', 'formatter', +// 'fontStyle', 'fontWeight', 'fontSize', 'fontFamily', +// // FIXME: deprecated, check and remove it. +// 'textStyle' +// ]); + +/** + * The method do not ensure performance. + * data could be [12, 2323, {value: 223}, [1221, 23], {value: [2, 23]}] + * This helper method retieves value from data. + * @param {string|number|Date|Array|Object} dataItem + * @return {number|string|Date|Array.} + */ +function getDataItemValue(dataItem) { + return (isObject$2(dataItem) && !isArray$1(dataItem) && !(dataItem instanceof Date)) + ? dataItem.value : dataItem; +} + +/** + * data could be [12, 2323, {value: 223}, [1221, 23], {value: [2, 23]}] + * This helper method determine if dataItem has extra option besides value + * @param {string|number|Date|Array|Object} dataItem + */ +function isDataItemOption(dataItem) { + return isObject$2(dataItem) + && !(dataItem instanceof Array); + // // markLine data can be array + // && !(dataItem[0] && isObject(dataItem[0]) && !(dataItem[0] instanceof Array)); +} + +/** + * Mapping to exists for merge. + * + * @public + * @param {Array.|Array.} exists + * @param {Object|Array.} newCptOptions + * @return {Array.} Result, like [{exist: ..., option: ...}, {}], + * index of which is the same as exists. + */ +function mappingToExists(exists, newCptOptions) { + // Mapping by the order by original option (but not order of + // new option) in merge mode. Because we should ensure + // some specified index (like xAxisIndex) is consistent with + // original option, which is easy to understand, espatially in + // media query. And in most case, merge option is used to + // update partial option but not be expected to change order. + newCptOptions = (newCptOptions || []).slice(); + + var result = map(exists || [], function (obj, index) { + return {exist: obj}; + }); + + // Mapping by id or name if specified. + each$2(newCptOptions, function (cptOption, index) { + if (!isObject$2(cptOption)) { + return; + } + + // id has highest priority. + for (var i = 0; i < result.length; i++) { + if (!result[i].option // Consider name: two map to one. + && cptOption.id != null + && result[i].exist.id === cptOption.id + '' + ) { + result[i].option = cptOption; + newCptOptions[index] = null; + return; + } + } + + for (var i = 0; i < result.length; i++) { + var exist = result[i].exist; + if (!result[i].option // Consider name: two map to one. + // Can not match when both ids exist but different. + && (exist.id == null || cptOption.id == null) + && cptOption.name != null + && !isIdInner(cptOption) + && !isIdInner(exist) + && exist.name === cptOption.name + '' + ) { + result[i].option = cptOption; + newCptOptions[index] = null; + return; + } + } + }); + + // Otherwise mapping by index. + each$2(newCptOptions, function (cptOption, index) { + if (!isObject$2(cptOption)) { + return; + } + + var i = 0; + for (; i < result.length; i++) { + var exist = result[i].exist; + if (!result[i].option + // Existing model that already has id should be able to + // mapped to (because after mapping performed model may + // be assigned with a id, whish should not affect next + // mapping), except those has inner id. + && !isIdInner(exist) + // Caution: + // Do not overwrite id. But name can be overwritten, + // because axis use name as 'show label text'. + // 'exist' always has id and name and we dont + // need to check it. + && cptOption.id == null + ) { + result[i].option = cptOption; + break; + } + } + + if (i >= result.length) { + result.push({option: cptOption}); + } + }); + + return result; +} + +/** + * Make id and name for mapping result (result of mappingToExists) + * into `keyInfo` field. + * + * @public + * @param {Array.} Result, like [{exist: ..., option: ...}, {}], + * which order is the same as exists. + * @return {Array.} The input. + */ +function makeIdAndName(mapResult) { + // We use this id to hash component models and view instances + // in echarts. id can be specified by user, or auto generated. + + // The id generation rule ensures new view instance are able + // to mapped to old instance when setOption are called in + // no-merge mode. So we generate model id by name and plus + // type in view id. + + // name can be duplicated among components, which is convenient + // to specify multi components (like series) by one name. + + // Ensure that each id is distinct. + var idMap = createHashMap(); + + each$2(mapResult, function (item, index) { + var existCpt = item.exist; + existCpt && idMap.set(existCpt.id, item); + }); + + each$2(mapResult, function (item, index) { + var opt = item.option; + + assert$1( + !opt || opt.id == null || !idMap.get(opt.id) || idMap.get(opt.id) === item, + 'id duplicates: ' + (opt && opt.id) + ); + + opt && opt.id != null && idMap.set(opt.id, item); + !item.keyInfo && (item.keyInfo = {}); + }); + + // Make name and id. + each$2(mapResult, function (item, index) { + var existCpt = item.exist; + var opt = item.option; + var keyInfo = item.keyInfo; + + if (!isObject$2(opt)) { + return; + } + + // name can be overwitten. Consider case: axis.name = '20km'. + // But id generated by name will not be changed, which affect + // only in that case: setOption with 'not merge mode' and view + // instance will be recreated, which can be accepted. + keyInfo.name = opt.name != null + ? opt.name + '' + : existCpt + ? existCpt.name + // Avoid diffferent series has the same name, + // because name may be used like in color pallet. + : DUMMY_COMPONENT_NAME_PREFIX + index; + + if (existCpt) { + keyInfo.id = existCpt.id; + } + else if (opt.id != null) { + keyInfo.id = opt.id + ''; + } + else { + // Consider this situatoin: + // optionA: [{name: 'a'}, {name: 'a'}, {..}] + // optionB [{..}, {name: 'a'}, {name: 'a'}] + // Series with the same name between optionA and optionB + // should be mapped. + var idNum = 0; + do { + keyInfo.id = '\0' + keyInfo.name + '\0' + idNum++; + } + while (idMap.get(keyInfo.id)); + } + + idMap.set(keyInfo.id, item); + }); +} + +function isNameSpecified(componentModel) { + var name = componentModel.name; + // Is specified when `indexOf` get -1 or > 0. + return !!(name && name.indexOf(DUMMY_COMPONENT_NAME_PREFIX)); +} + +/** + * @public + * @param {Object} cptOption + * @return {boolean} + */ +function isIdInner(cptOption) { + return isObject$2(cptOption) + && cptOption.id + && (cptOption.id + '').indexOf('\0_ec_\0') === 0; +} + +/** + * A helper for removing duplicate items between batchA and batchB, + * and in themselves, and categorize by series. + * + * @param {Array.} batchA Like: [{seriesId: 2, dataIndex: [32, 4, 5]}, ...] + * @param {Array.} batchB Like: [{seriesId: 2, dataIndex: [32, 4, 5]}, ...] + * @return {Array., Array.>} result: [resultBatchA, resultBatchB] + */ +function compressBatches(batchA, batchB) { + var mapA = {}; + var mapB = {}; + + makeMap(batchA || [], mapA); + makeMap(batchB || [], mapB, mapA); + + return [mapToArray(mapA), mapToArray(mapB)]; + + function makeMap(sourceBatch, map$$1, otherMap) { + for (var i = 0, len = sourceBatch.length; i < len; i++) { + var seriesId = sourceBatch[i].seriesId; + var dataIndices = normalizeToArray(sourceBatch[i].dataIndex); + var otherDataIndices = otherMap && otherMap[seriesId]; + + for (var j = 0, lenj = dataIndices.length; j < lenj; j++) { + var dataIndex = dataIndices[j]; + + if (otherDataIndices && otherDataIndices[dataIndex]) { + otherDataIndices[dataIndex] = null; + } + else { + (map$$1[seriesId] || (map$$1[seriesId] = {}))[dataIndex] = 1; + } + } + } + } + + function mapToArray(map$$1, isData) { + var result = []; + for (var i in map$$1) { + if (map$$1.hasOwnProperty(i) && map$$1[i] != null) { + if (isData) { + result.push(+i); + } + else { + var dataIndices = mapToArray(map$$1[i], true); + dataIndices.length && result.push({seriesId: i, dataIndex: dataIndices}); + } + } + } + return result; + } +} + +/** + * @param {module:echarts/data/List} data + * @param {Object} payload Contains dataIndex (means rawIndex) / dataIndexInside / name + * each of which can be Array or primary type. + * @return {number|Array.} dataIndex If not found, return undefined/null. + */ +function queryDataIndex(data, payload) { + if (payload.dataIndexInside != null) { + return payload.dataIndexInside; + } + else if (payload.dataIndex != null) { + return isArray(payload.dataIndex) + ? map(payload.dataIndex, function (value) { + return data.indexOfRawIndex(value); + }) + : data.indexOfRawIndex(payload.dataIndex); + } + else if (payload.name != null) { + return isArray(payload.name) + ? map(payload.name, function (value) { + return data.indexOfName(value); + }) + : data.indexOfName(payload.name); + } +} + +/** + * Enable property storage to any host object. + * Notice: Serialization is not supported. + * + * For example: + * var inner = zrUitl.makeInner(); + * + * function some1(hostObj) { + * inner(hostObj).someProperty = 1212; + * ... + * } + * function some2() { + * var fields = inner(this); + * fields.someProperty1 = 1212; + * fields.someProperty2 = 'xx'; + * ... + * } + * + * @return {Function} + */ +function makeInner() { + // Consider different scope by es module import. + var key = '__\0ec_inner_' + innerUniqueIndex++ + '_' + Math.random().toFixed(5); + return function (hostObj) { + return hostObj[key] || (hostObj[key] = {}); + }; +} +var innerUniqueIndex = 0; + +/** + * @param {module:echarts/model/Global} ecModel + * @param {string|Object} finder + * If string, e.g., 'geo', means {geoIndex: 0}. + * If Object, could contain some of these properties below: + * { + * seriesIndex, seriesId, seriesName, + * geoIndex, geoId, geoName, + * bmapIndex, bmapId, bmapName, + * xAxisIndex, xAxisId, xAxisName, + * yAxisIndex, yAxisId, yAxisName, + * gridIndex, gridId, gridName, + * ... (can be extended) + * } + * Each properties can be number|string|Array.|Array. + * For example, a finder could be + * { + * seriesIndex: 3, + * geoId: ['aa', 'cc'], + * gridName: ['xx', 'rr'] + * } + * xxxIndex can be set as 'all' (means all xxx) or 'none' (means not specify) + * If nothing or null/undefined specified, return nothing. + * @param {Object} [opt] + * @param {string} [opt.defaultMainType] + * @param {Array.} [opt.includeMainTypes] + * @return {Object} result like: + * { + * seriesModels: [seriesModel1, seriesModel2], + * seriesModel: seriesModel1, // The first model + * geoModels: [geoModel1, geoModel2], + * geoModel: geoModel1, // The first model + * ... + * } + */ +function parseFinder(ecModel, finder, opt) { + if (isString(finder)) { + var obj = {}; + obj[finder + 'Index'] = 0; + finder = obj; + } + + var defaultMainType = opt && opt.defaultMainType; + if (defaultMainType + && !has(finder, defaultMainType + 'Index') + && !has(finder, defaultMainType + 'Id') + && !has(finder, defaultMainType + 'Name') + ) { + finder[defaultMainType + 'Index'] = 0; + } + + var result = {}; + + each$2(finder, function (value, key) { + var value = finder[key]; + + // Exclude 'dataIndex' and other illgal keys. + if (key === 'dataIndex' || key === 'dataIndexInside') { + result[key] = value; + return; + } + + var parsedKey = key.match(/^(\w+)(Index|Id|Name)$/) || []; + var mainType = parsedKey[1]; + var queryType = (parsedKey[2] || '').toLowerCase(); + + if (!mainType + || !queryType + || value == null + || (queryType === 'index' && value === 'none') + || (opt && opt.includeMainTypes && indexOf(opt.includeMainTypes, mainType) < 0) + ) { + return; + } + + var queryParam = {mainType: mainType}; + if (queryType !== 'index' || value !== 'all') { + queryParam[queryType] = value; + } + + var models = ecModel.queryComponents(queryParam); + result[mainType + 'Models'] = models; + result[mainType + 'Model'] = models[0]; + }); + + return result; +} + +function has(obj, prop) { + return obj && obj.hasOwnProperty(prop); +} + +function setAttribute(dom, key, value) { + dom.setAttribute + ? dom.setAttribute(key, value) + : (dom[key] = value); +} + +function getAttribute(dom, key) { + return dom.getAttribute + ? dom.getAttribute(key) + : dom[key]; +} + +function getTooltipRenderMode(renderModeOption) { + if (renderModeOption === 'auto') { + // Using html when `document` exists, use richText otherwise + return env$1.domSupported ? 'html' : 'richText'; + } + else { + return renderModeOption || 'html'; + } +} + +/** + * Group a list by key. + * + * @param {Array} array + * @param {Function} getKey + * param {*} Array item + * return {string} key + * @return {Object} Result + * {Array}: keys, + * {module:zrender/core/util/HashMap} buckets: {key -> Array} + */ +function groupData(array, getKey) { + var buckets = createHashMap(); + var keys = []; + + each$1(array, function (item) { + var key = getKey(item); + (buckets.get(key) + || (keys.push(key), buckets.set(key, [])) + ).push(item); + }); + + return {keys: keys, buckets: buckets}; +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var TYPE_DELIMITER = '.'; +var IS_CONTAINER = '___EC__COMPONENT__CONTAINER___'; + +/** + * Notice, parseClassType('') should returns {main: '', sub: ''} + * @public + */ +function parseClassType$1(componentType) { + var ret = {main: '', sub: ''}; + if (componentType) { + componentType = componentType.split(TYPE_DELIMITER); + ret.main = componentType[0] || ''; + ret.sub = componentType[1] || ''; + } + return ret; +} + +/** + * @public + */ +function checkClassType(componentType) { + assert$1( + /^[a-zA-Z0-9_]+([.][a-zA-Z0-9_]+)?$/.test(componentType), + 'componentType "' + componentType + '" illegal' + ); +} + +/** + * @public + */ +function enableClassExtend(RootClass, mandatoryMethods) { + + RootClass.$constructor = RootClass; + RootClass.extend = function (proto) { + + if (__DEV__) { + each$1(mandatoryMethods, function (method) { + if (!proto[method]) { + console.warn( + 'Method `' + method + '` should be implemented' + + (proto.type ? ' in ' + proto.type : '') + '.' + ); + } + }); + } + + var superClass = this; + var ExtendedClass = function () { + if (!proto.$constructor) { + superClass.apply(this, arguments); + } + else { + proto.$constructor.apply(this, arguments); + } + }; + + extend(ExtendedClass.prototype, proto); + + ExtendedClass.extend = this.extend; + ExtendedClass.superCall = superCall; + ExtendedClass.superApply = superApply; + inherits(ExtendedClass, this); + ExtendedClass.superClass = superClass; + + return ExtendedClass; + }; +} + +var classBase = 0; + +/** + * Can not use instanceof, consider different scope by + * cross domain or es module import in ec extensions. + * Mount a method "isInstance()" to Clz. + */ +function enableClassCheck(Clz) { + var classAttr = ['__\0is_clz', classBase++, Math.random().toFixed(3)].join('_'); + Clz.prototype[classAttr] = true; + + if (__DEV__) { + assert$1(!Clz.isInstance, 'The method "is" can not be defined.'); + } + + Clz.isInstance = function (obj) { + return !!(obj && obj[classAttr]); + }; +} + +// superCall should have class info, which can not be fetch from 'this'. +// Consider this case: +// class A has method f, +// class B inherits class A, overrides method f, f call superApply('f'), +// class C inherits class B, do not overrides method f, +// then when method of class C is called, dead loop occured. +function superCall(context, methodName) { + var args = slice(arguments, 2); + return this.superClass.prototype[methodName].apply(context, args); +} + +function superApply(context, methodName, args) { + return this.superClass.prototype[methodName].apply(context, args); +} + +/** + * @param {Object} entity + * @param {Object} options + * @param {boolean} [options.registerWhenExtend] + * @public + */ +function enableClassManagement(entity, options) { + options = options || {}; + + /** + * Component model classes + * key: componentType, + * value: + * componentClass, when componentType is 'xxx' + * or Object., when componentType is 'xxx.yy' + * @type {Object} + */ + var storage = {}; + + entity.registerClass = function (Clazz, componentType) { + if (componentType) { + checkClassType(componentType); + componentType = parseClassType$1(componentType); + + if (!componentType.sub) { + if (__DEV__) { + if (storage[componentType.main]) { + console.warn(componentType.main + ' exists.'); + } + } + storage[componentType.main] = Clazz; + } + else if (componentType.sub !== IS_CONTAINER) { + var container = makeContainer(componentType); + container[componentType.sub] = Clazz; + } + } + return Clazz; + }; + + entity.getClass = function (componentMainType, subType, throwWhenNotFound) { + var Clazz = storage[componentMainType]; + + if (Clazz && Clazz[IS_CONTAINER]) { + Clazz = subType ? Clazz[subType] : null; + } + + if (throwWhenNotFound && !Clazz) { + throw new Error( + !subType + ? componentMainType + '.' + 'type should be specified.' + : 'Component ' + componentMainType + '.' + (subType || '') + ' not exists. Load it first.' + ); + } + + return Clazz; + }; + + entity.getClassesByMainType = function (componentType) { + componentType = parseClassType$1(componentType); + + var result = []; + var obj = storage[componentType.main]; + + if (obj && obj[IS_CONTAINER]) { + each$1(obj, function (o, type) { + type !== IS_CONTAINER && result.push(o); + }); + } + else { + result.push(obj); + } + + return result; + }; + + entity.hasClass = function (componentType) { + // Just consider componentType.main. + componentType = parseClassType$1(componentType); + return !!storage[componentType.main]; + }; + + /** + * @return {Array.} Like ['aa', 'bb'], but can not be ['aa.xx'] + */ + entity.getAllClassMainTypes = function () { + var types = []; + each$1(storage, function (obj, type) { + types.push(type); + }); + return types; + }; + + /** + * If a main type is container and has sub types + * @param {string} mainType + * @return {boolean} + */ + entity.hasSubTypes = function (componentType) { + componentType = parseClassType$1(componentType); + var obj = storage[componentType.main]; + return obj && obj[IS_CONTAINER]; + }; + + entity.parseClassType = parseClassType$1; + + function makeContainer(componentType) { + var container = storage[componentType.main]; + if (!container || !container[IS_CONTAINER]) { + container = storage[componentType.main] = {}; + container[IS_CONTAINER] = true; + } + return container; + } + + if (options.registerWhenExtend) { + var originalExtend = entity.extend; + if (originalExtend) { + entity.extend = function (proto) { + var ExtendedClass = originalExtend.call(this, proto); + return entity.registerClass(ExtendedClass, proto.type); + }; + } + } + + return entity; +} + +/** + * @param {string|Array.} properties + */ + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +// TODO Parse shadow style +// TODO Only shallow path support +var makeStyleMapper = function (properties) { + // Normalize + for (var i = 0; i < properties.length; i++) { + if (!properties[i][1]) { + properties[i][1] = properties[i][0]; + } + } + return function (model, excludes, includes) { + var style = {}; + for (var i = 0; i < properties.length; i++) { + var propName = properties[i][1]; + if ((excludes && indexOf(excludes, propName) >= 0) + || (includes && indexOf(includes, propName) < 0) + ) { + continue; + } + var val = model.getShallow(propName); + if (val != null) { + style[properties[i][0]] = val; + } + } + return style; + }; +}; + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var getLineStyle = makeStyleMapper( + [ + ['lineWidth', 'width'], + ['stroke', 'color'], + ['opacity'], + ['shadowBlur'], + ['shadowOffsetX'], + ['shadowOffsetY'], + ['shadowColor'] + ] +); + +var lineStyleMixin = { + getLineStyle: function (excludes) { + var style = getLineStyle(this, excludes); + var lineDash = this.getLineDash(style.lineWidth); + lineDash && (style.lineDash = lineDash); + return style; + }, + + getLineDash: function (lineWidth) { + if (lineWidth == null) { + lineWidth = 1; + } + var lineType = this.get('type'); + var dotSize = Math.max(lineWidth, 2); + var dashSize = lineWidth * 4; + return (lineType === 'solid' || lineType == null) ? null + : (lineType === 'dashed' ? [dashSize, dashSize] : [dotSize, dotSize]); + } +}; + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var getAreaStyle = makeStyleMapper( + [ + ['fill', 'color'], + ['shadowBlur'], + ['shadowOffsetX'], + ['shadowOffsetY'], + ['opacity'], + ['shadowColor'] + ] +); + +var areaStyleMixin = { + getAreaStyle: function (excludes, includes) { + return getAreaStyle(this, excludes, includes); + } +}; + +/** + * 曲线辅助模块 + * @module zrender/core/curve + * @author pissang(https://www.github.com/pissang) + */ + +var mathPow = Math.pow; +var mathSqrt$2 = Math.sqrt; + +var EPSILON$1 = 1e-8; +var EPSILON_NUMERIC = 1e-4; + +var THREE_SQRT = mathSqrt$2(3); +var ONE_THIRD = 1 / 3; + +// 临时变量 +var _v0 = create(); +var _v1 = create(); +var _v2 = create(); + +function isAroundZero(val) { + return val > -EPSILON$1 && val < EPSILON$1; +} +function isNotAroundZero$1(val) { + return val > EPSILON$1 || val < -EPSILON$1; +} +/** + * 计算三次贝塞尔值 + * @memberOf module:zrender/core/curve + * @param {number} p0 + * @param {number} p1 + * @param {number} p2 + * @param {number} p3 + * @param {number} t + * @return {number} + */ +function cubicAt(p0, p1, p2, p3, t) { + var onet = 1 - t; + return onet * onet * (onet * p0 + 3 * t * p1) + + t * t * (t * p3 + 3 * onet * p2); +} + +/** + * 计算三次贝塞尔导数值 + * @memberOf module:zrender/core/curve + * @param {number} p0 + * @param {number} p1 + * @param {number} p2 + * @param {number} p3 + * @param {number} t + * @return {number} + */ +function cubicDerivativeAt(p0, p1, p2, p3, t) { + var onet = 1 - t; + return 3 * ( + ((p1 - p0) * onet + 2 * (p2 - p1) * t) * onet + + (p3 - p2) * t * t + ); +} + +/** + * 计算三次贝塞尔方程根,使用盛金公式 + * @memberOf module:zrender/core/curve + * @param {number} p0 + * @param {number} p1 + * @param {number} p2 + * @param {number} p3 + * @param {number} val + * @param {Array.} roots + * @return {number} 有效根数目 + */ +function cubicRootAt(p0, p1, p2, p3, val, roots) { + // Evaluate roots of cubic functions + var a = p3 + 3 * (p1 - p2) - p0; + var b = 3 * (p2 - p1 * 2 + p0); + var c = 3 * (p1 - p0); + var d = p0 - val; + + var A = b * b - 3 * a * c; + var B = b * c - 9 * a * d; + var C = c * c - 3 * b * d; + + var n = 0; + + if (isAroundZero(A) && isAroundZero(B)) { + if (isAroundZero(b)) { + roots[0] = 0; + } + else { + var t1 = -c / b; //t1, t2, t3, b is not zero + if (t1 >= 0 && t1 <= 1) { + roots[n++] = t1; + } + } + } + else { + var disc = B * B - 4 * A * C; + + if (isAroundZero(disc)) { + var K = B / A; + var t1 = -b / a + K; // t1, a is not zero + var t2 = -K / 2; // t2, t3 + if (t1 >= 0 && t1 <= 1) { + roots[n++] = t1; + } + if (t2 >= 0 && t2 <= 1) { + roots[n++] = t2; + } + } + else if (disc > 0) { + var discSqrt = mathSqrt$2(disc); + var Y1 = A * b + 1.5 * a * (-B + discSqrt); + var Y2 = A * b + 1.5 * a * (-B - discSqrt); + if (Y1 < 0) { + Y1 = -mathPow(-Y1, ONE_THIRD); + } + else { + Y1 = mathPow(Y1, ONE_THIRD); + } + if (Y2 < 0) { + Y2 = -mathPow(-Y2, ONE_THIRD); + } + else { + Y2 = mathPow(Y2, ONE_THIRD); + } + var t1 = (-b - (Y1 + Y2)) / (3 * a); + if (t1 >= 0 && t1 <= 1) { + roots[n++] = t1; + } + } + else { + var T = (2 * A * b - 3 * a * B) / (2 * mathSqrt$2(A * A * A)); + var theta = Math.acos(T) / 3; + var ASqrt = mathSqrt$2(A); + var tmp = Math.cos(theta); + + var t1 = (-b - 2 * ASqrt * tmp) / (3 * a); + var t2 = (-b + ASqrt * (tmp + THREE_SQRT * Math.sin(theta))) / (3 * a); + var t3 = (-b + ASqrt * (tmp - THREE_SQRT * Math.sin(theta))) / (3 * a); + if (t1 >= 0 && t1 <= 1) { + roots[n++] = t1; + } + if (t2 >= 0 && t2 <= 1) { + roots[n++] = t2; + } + if (t3 >= 0 && t3 <= 1) { + roots[n++] = t3; + } + } + } + return n; +} + +/** + * 计算三次贝塞尔方程极限值的位置 + * @memberOf module:zrender/core/curve + * @param {number} p0 + * @param {number} p1 + * @param {number} p2 + * @param {number} p3 + * @param {Array.} extrema + * @return {number} 有效数目 + */ +function cubicExtrema(p0, p1, p2, p3, extrema) { + var b = 6 * p2 - 12 * p1 + 6 * p0; + var a = 9 * p1 + 3 * p3 - 3 * p0 - 9 * p2; + var c = 3 * p1 - 3 * p0; + + var n = 0; + if (isAroundZero(a)) { + if (isNotAroundZero$1(b)) { + var t1 = -c / b; + if (t1 >= 0 && t1 <= 1) { + extrema[n++] = t1; + } + } + } + else { + var disc = b * b - 4 * a * c; + if (isAroundZero(disc)) { + extrema[0] = -b / (2 * a); + } + else if (disc > 0) { + var discSqrt = mathSqrt$2(disc); + var t1 = (-b + discSqrt) / (2 * a); + var t2 = (-b - discSqrt) / (2 * a); + if (t1 >= 0 && t1 <= 1) { + extrema[n++] = t1; + } + if (t2 >= 0 && t2 <= 1) { + extrema[n++] = t2; + } + } + } + return n; +} + +/** + * 细分三次贝塞尔曲线 + * @memberOf module:zrender/core/curve + * @param {number} p0 + * @param {number} p1 + * @param {number} p2 + * @param {number} p3 + * @param {number} t + * @param {Array.} out + */ +function cubicSubdivide(p0, p1, p2, p3, t, out) { + var p01 = (p1 - p0) * t + p0; + var p12 = (p2 - p1) * t + p1; + var p23 = (p3 - p2) * t + p2; + + var p012 = (p12 - p01) * t + p01; + var p123 = (p23 - p12) * t + p12; + + var p0123 = (p123 - p012) * t + p012; + // Seg0 + out[0] = p0; + out[1] = p01; + out[2] = p012; + out[3] = p0123; + // Seg1 + out[4] = p0123; + out[5] = p123; + out[6] = p23; + out[7] = p3; +} + +/** + * 投射点到三次贝塞尔曲线上,返回投射距离。 + * 投射点有可能会有一个或者多个,这里只返回其中距离最短的一个。 + * @param {number} x0 + * @param {number} y0 + * @param {number} x1 + * @param {number} y1 + * @param {number} x2 + * @param {number} y2 + * @param {number} x3 + * @param {number} y3 + * @param {number} x + * @param {number} y + * @param {Array.} [out] 投射点 + * @return {number} + */ +function cubicProjectPoint( + x0, y0, x1, y1, x2, y2, x3, y3, + x, y, out +) { + // http://pomax.github.io/bezierinfo/#projections + var t; + var interval = 0.005; + var d = Infinity; + var prev; + var next; + var d1; + var d2; + + _v0[0] = x; + _v0[1] = y; + + // 先粗略估计一下可能的最小距离的 t 值 + // PENDING + for (var _t = 0; _t < 1; _t += 0.05) { + _v1[0] = cubicAt(x0, x1, x2, x3, _t); + _v1[1] = cubicAt(y0, y1, y2, y3, _t); + d1 = distSquare(_v0, _v1); + if (d1 < d) { + t = _t; + d = d1; + } + } + d = Infinity; + + // At most 32 iteration + for (var i = 0; i < 32; i++) { + if (interval < EPSILON_NUMERIC) { + break; + } + prev = t - interval; + next = t + interval; + // t - interval + _v1[0] = cubicAt(x0, x1, x2, x3, prev); + _v1[1] = cubicAt(y0, y1, y2, y3, prev); + + d1 = distSquare(_v1, _v0); + + if (prev >= 0 && d1 < d) { + t = prev; + d = d1; + } + else { + // t + interval + _v2[0] = cubicAt(x0, x1, x2, x3, next); + _v2[1] = cubicAt(y0, y1, y2, y3, next); + d2 = distSquare(_v2, _v0); + + if (next <= 1 && d2 < d) { + t = next; + d = d2; + } + else { + interval *= 0.5; + } + } + } + // t + if (out) { + out[0] = cubicAt(x0, x1, x2, x3, t); + out[1] = cubicAt(y0, y1, y2, y3, t); + } + // console.log(interval, i); + return mathSqrt$2(d); +} + +/** + * 计算二次方贝塞尔值 + * @param {number} p0 + * @param {number} p1 + * @param {number} p2 + * @param {number} t + * @return {number} + */ +function quadraticAt(p0, p1, p2, t) { + var onet = 1 - t; + return onet * (onet * p0 + 2 * t * p1) + t * t * p2; +} + +/** + * 计算二次方贝塞尔导数值 + * @param {number} p0 + * @param {number} p1 + * @param {number} p2 + * @param {number} t + * @return {number} + */ +function quadraticDerivativeAt(p0, p1, p2, t) { + return 2 * ((1 - t) * (p1 - p0) + t * (p2 - p1)); +} + +/** + * 计算二次方贝塞尔方程根 + * @param {number} p0 + * @param {number} p1 + * @param {number} p2 + * @param {number} t + * @param {Array.} roots + * @return {number} 有效根数目 + */ +function quadraticRootAt(p0, p1, p2, val, roots) { + var a = p0 - 2 * p1 + p2; + var b = 2 * (p1 - p0); + var c = p0 - val; + + var n = 0; + if (isAroundZero(a)) { + if (isNotAroundZero$1(b)) { + var t1 = -c / b; + if (t1 >= 0 && t1 <= 1) { + roots[n++] = t1; + } + } + } + else { + var disc = b * b - 4 * a * c; + if (isAroundZero(disc)) { + var t1 = -b / (2 * a); + if (t1 >= 0 && t1 <= 1) { + roots[n++] = t1; + } + } + else if (disc > 0) { + var discSqrt = mathSqrt$2(disc); + var t1 = (-b + discSqrt) / (2 * a); + var t2 = (-b - discSqrt) / (2 * a); + if (t1 >= 0 && t1 <= 1) { + roots[n++] = t1; + } + if (t2 >= 0 && t2 <= 1) { + roots[n++] = t2; + } + } + } + return n; +} + +/** + * 计算二次贝塞尔方程极限值 + * @memberOf module:zrender/core/curve + * @param {number} p0 + * @param {number} p1 + * @param {number} p2 + * @return {number} + */ +function quadraticExtremum(p0, p1, p2) { + var divider = p0 + p2 - 2 * p1; + if (divider === 0) { + // p1 is center of p0 and p2 + return 0.5; + } + else { + return (p0 - p1) / divider; + } +} + +/** + * 细分二次贝塞尔曲线 + * @memberOf module:zrender/core/curve + * @param {number} p0 + * @param {number} p1 + * @param {number} p2 + * @param {number} t + * @param {Array.} out + */ +function quadraticSubdivide(p0, p1, p2, t, out) { + var p01 = (p1 - p0) * t + p0; + var p12 = (p2 - p1) * t + p1; + var p012 = (p12 - p01) * t + p01; + + // Seg0 + out[0] = p0; + out[1] = p01; + out[2] = p012; + + // Seg1 + out[3] = p012; + out[4] = p12; + out[5] = p2; +} + +/** + * 投射点到二次贝塞尔曲线上,返回投射距离。 + * 投射点有可能会有一个或者多个,这里只返回其中距离最短的一个。 + * @param {number} x0 + * @param {number} y0 + * @param {number} x1 + * @param {number} y1 + * @param {number} x2 + * @param {number} y2 + * @param {number} x + * @param {number} y + * @param {Array.} out 投射点 + * @return {number} + */ +function quadraticProjectPoint( + x0, y0, x1, y1, x2, y2, + x, y, out +) { + // http://pomax.github.io/bezierinfo/#projections + var t; + var interval = 0.005; + var d = Infinity; + + _v0[0] = x; + _v0[1] = y; + + // 先粗略估计一下可能的最小距离的 t 值 + // PENDING + for (var _t = 0; _t < 1; _t += 0.05) { + _v1[0] = quadraticAt(x0, x1, x2, _t); + _v1[1] = quadraticAt(y0, y1, y2, _t); + var d1 = distSquare(_v0, _v1); + if (d1 < d) { + t = _t; + d = d1; + } + } + d = Infinity; + + // At most 32 iteration + for (var i = 0; i < 32; i++) { + if (interval < EPSILON_NUMERIC) { + break; + } + var prev = t - interval; + var next = t + interval; + // t - interval + _v1[0] = quadraticAt(x0, x1, x2, prev); + _v1[1] = quadraticAt(y0, y1, y2, prev); + + var d1 = distSquare(_v1, _v0); + + if (prev >= 0 && d1 < d) { + t = prev; + d = d1; + } + else { + // t + interval + _v2[0] = quadraticAt(x0, x1, x2, next); + _v2[1] = quadraticAt(y0, y1, y2, next); + var d2 = distSquare(_v2, _v0); + if (next <= 1 && d2 < d) { + t = next; + d = d2; + } + else { + interval *= 0.5; + } + } + } + // t + if (out) { + out[0] = quadraticAt(x0, x1, x2, t); + out[1] = quadraticAt(y0, y1, y2, t); + } + // console.log(interval, i); + return mathSqrt$2(d); +} + +/** + * @author Yi Shen(https://github.com/pissang) + */ + +var mathMin$3 = Math.min; +var mathMax$3 = Math.max; +var mathSin$2 = Math.sin; +var mathCos$2 = Math.cos; +var PI2 = Math.PI * 2; + +var start = create(); +var end = create(); +var extremity = create(); + +/** + * 从顶点数组中计算出最小包围盒,写入`min`和`max`中 + * @module zrender/core/bbox + * @param {Array} points 顶点数组 + * @param {number} min + * @param {number} max + */ +function fromPoints(points, min$$1, max$$1) { + if (points.length === 0) { + return; + } + var p = points[0]; + var left = p[0]; + var right = p[0]; + var top = p[1]; + var bottom = p[1]; + var i; + + for (i = 1; i < points.length; i++) { + p = points[i]; + left = mathMin$3(left, p[0]); + right = mathMax$3(right, p[0]); + top = mathMin$3(top, p[1]); + bottom = mathMax$3(bottom, p[1]); + } + + min$$1[0] = left; + min$$1[1] = top; + max$$1[0] = right; + max$$1[1] = bottom; +} + +/** + * @memberOf module:zrender/core/bbox + * @param {number} x0 + * @param {number} y0 + * @param {number} x1 + * @param {number} y1 + * @param {Array.} min + * @param {Array.} max + */ +function fromLine(x0, y0, x1, y1, min$$1, max$$1) { + min$$1[0] = mathMin$3(x0, x1); + min$$1[1] = mathMin$3(y0, y1); + max$$1[0] = mathMax$3(x0, x1); + max$$1[1] = mathMax$3(y0, y1); +} + +var xDim = []; +var yDim = []; +/** + * 从三阶贝塞尔曲线(p0, p1, p2, p3)中计算出最小包围盒,写入`min`和`max`中 + * @memberOf module:zrender/core/bbox + * @param {number} x0 + * @param {number} y0 + * @param {number} x1 + * @param {number} y1 + * @param {number} x2 + * @param {number} y2 + * @param {number} x3 + * @param {number} y3 + * @param {Array.} min + * @param {Array.} max + */ +function fromCubic( + x0, y0, x1, y1, x2, y2, x3, y3, min$$1, max$$1 +) { + var cubicExtrema$$1 = cubicExtrema; + var cubicAt$$1 = cubicAt; + var i; + var n = cubicExtrema$$1(x0, x1, x2, x3, xDim); + min$$1[0] = Infinity; + min$$1[1] = Infinity; + max$$1[0] = -Infinity; + max$$1[1] = -Infinity; + + for (i = 0; i < n; i++) { + var x = cubicAt$$1(x0, x1, x2, x3, xDim[i]); + min$$1[0] = mathMin$3(x, min$$1[0]); + max$$1[0] = mathMax$3(x, max$$1[0]); + } + n = cubicExtrema$$1(y0, y1, y2, y3, yDim); + for (i = 0; i < n; i++) { + var y = cubicAt$$1(y0, y1, y2, y3, yDim[i]); + min$$1[1] = mathMin$3(y, min$$1[1]); + max$$1[1] = mathMax$3(y, max$$1[1]); + } + + min$$1[0] = mathMin$3(x0, min$$1[0]); + max$$1[0] = mathMax$3(x0, max$$1[0]); + min$$1[0] = mathMin$3(x3, min$$1[0]); + max$$1[0] = mathMax$3(x3, max$$1[0]); + + min$$1[1] = mathMin$3(y0, min$$1[1]); + max$$1[1] = mathMax$3(y0, max$$1[1]); + min$$1[1] = mathMin$3(y3, min$$1[1]); + max$$1[1] = mathMax$3(y3, max$$1[1]); +} + +/** + * 从二阶贝塞尔曲线(p0, p1, p2)中计算出最小包围盒,写入`min`和`max`中 + * @memberOf module:zrender/core/bbox + * @param {number} x0 + * @param {number} y0 + * @param {number} x1 + * @param {number} y1 + * @param {number} x2 + * @param {number} y2 + * @param {Array.} min + * @param {Array.} max + */ +function fromQuadratic(x0, y0, x1, y1, x2, y2, min$$1, max$$1) { + var quadraticExtremum$$1 = quadraticExtremum; + var quadraticAt$$1 = quadraticAt; + // Find extremities, where derivative in x dim or y dim is zero + var tx = + mathMax$3( + mathMin$3(quadraticExtremum$$1(x0, x1, x2), 1), 0 + ); + var ty = + mathMax$3( + mathMin$3(quadraticExtremum$$1(y0, y1, y2), 1), 0 + ); + + var x = quadraticAt$$1(x0, x1, x2, tx); + var y = quadraticAt$$1(y0, y1, y2, ty); + + min$$1[0] = mathMin$3(x0, x2, x); + min$$1[1] = mathMin$3(y0, y2, y); + max$$1[0] = mathMax$3(x0, x2, x); + max$$1[1] = mathMax$3(y0, y2, y); +} + +/** + * 从圆弧中计算出最小包围盒,写入`min`和`max`中 + * @method + * @memberOf module:zrender/core/bbox + * @param {number} x + * @param {number} y + * @param {number} rx + * @param {number} ry + * @param {number} startAngle + * @param {number} endAngle + * @param {number} anticlockwise + * @param {Array.} min + * @param {Array.} max + */ +function fromArc( + x, y, rx, ry, startAngle, endAngle, anticlockwise, min$$1, max$$1 +) { + var vec2Min = min; + var vec2Max = max; + + var diff = Math.abs(startAngle - endAngle); + + + if (diff % PI2 < 1e-4 && diff > 1e-4) { + // Is a circle + min$$1[0] = x - rx; + min$$1[1] = y - ry; + max$$1[0] = x + rx; + max$$1[1] = y + ry; + return; + } + + start[0] = mathCos$2(startAngle) * rx + x; + start[1] = mathSin$2(startAngle) * ry + y; + + end[0] = mathCos$2(endAngle) * rx + x; + end[1] = mathSin$2(endAngle) * ry + y; + + vec2Min(min$$1, start, end); + vec2Max(max$$1, start, end); + + // Thresh to [0, Math.PI * 2] + startAngle = startAngle % (PI2); + if (startAngle < 0) { + startAngle = startAngle + PI2; + } + endAngle = endAngle % (PI2); + if (endAngle < 0) { + endAngle = endAngle + PI2; + } + + if (startAngle > endAngle && !anticlockwise) { + endAngle += PI2; + } + else if (startAngle < endAngle && anticlockwise) { + startAngle += PI2; + } + if (anticlockwise) { + var tmp = endAngle; + endAngle = startAngle; + startAngle = tmp; + } + + // var number = 0; + // var step = (anticlockwise ? -Math.PI : Math.PI) / 2; + for (var angle = 0; angle < endAngle; angle += Math.PI / 2) { + if (angle > startAngle) { + extremity[0] = mathCos$2(angle) * rx + x; + extremity[1] = mathSin$2(angle) * ry + y; + + vec2Min(min$$1, extremity, min$$1); + vec2Max(max$$1, extremity, max$$1); + } + } +} + +/** + * Path 代理,可以在`buildPath`中用于替代`ctx`, 会保存每个path操作的命令到pathCommands属性中 + * 可以用于 isInsidePath 判断以及获取boundingRect + * + * @module zrender/core/PathProxy + * @author Yi Shen (http://www.github.com/pissang) + */ + +// TODO getTotalLength, getPointAtLength + +var CMD = { + M: 1, + L: 2, + C: 3, + Q: 4, + A: 5, + Z: 6, + // Rect + R: 7 +}; + +// var CMD_MEM_SIZE = { +// M: 3, +// L: 3, +// C: 7, +// Q: 5, +// A: 9, +// R: 5, +// Z: 1 +// }; + +var min$1 = []; +var max$1 = []; +var min2 = []; +var max2 = []; +var mathMin$2 = Math.min; +var mathMax$2 = Math.max; +var mathCos$1 = Math.cos; +var mathSin$1 = Math.sin; +var mathSqrt$1 = Math.sqrt; +var mathAbs = Math.abs; + +var hasTypedArray = typeof Float32Array !== 'undefined'; + +/** + * @alias module:zrender/core/PathProxy + * @constructor + */ +var PathProxy = function (notSaveData) { + + this._saveData = !(notSaveData || false); + + if (this._saveData) { + /** + * Path data. Stored as flat array + * @type {Array.} + */ + this.data = []; + } + + this._ctx = null; +}; + +/** + * 快速计算Path包围盒(并不是最小包围盒) + * @return {Object} + */ +PathProxy.prototype = { + + constructor: PathProxy, + + _xi: 0, + _yi: 0, + + _x0: 0, + _y0: 0, + // Unit x, Unit y. Provide for avoiding drawing that too short line segment + _ux: 0, + _uy: 0, + + _len: 0, + + _lineDash: null, + + _dashOffset: 0, + + _dashIdx: 0, + + _dashSum: 0, + + /** + * @readOnly + */ + setScale: function (sx, sy) { + this._ux = mathAbs(1 / devicePixelRatio / sx) || 0; + this._uy = mathAbs(1 / devicePixelRatio / sy) || 0; + }, + + getContext: function () { + return this._ctx; + }, + + /** + * @param {CanvasRenderingContext2D} ctx + * @return {module:zrender/core/PathProxy} + */ + beginPath: function (ctx) { + + this._ctx = ctx; + + ctx && ctx.beginPath(); + + ctx && (this.dpr = ctx.dpr); + + // Reset + if (this._saveData) { + this._len = 0; + } + + if (this._lineDash) { + this._lineDash = null; + + this._dashOffset = 0; + } + + return this; + }, + + /** + * @param {number} x + * @param {number} y + * @return {module:zrender/core/PathProxy} + */ + moveTo: function (x, y) { + this.addData(CMD.M, x, y); + this._ctx && this._ctx.moveTo(x, y); + + // x0, y0, xi, yi 是记录在 _dashedXXXXTo 方法中使用 + // xi, yi 记录当前点, x0, y0 在 closePath 的时候回到起始点。 + // 有可能在 beginPath 之后直接调用 lineTo,这时候 x0, y0 需要 + // 在 lineTo 方法中记录,这里先不考虑这种情况,dashed line 也只在 IE10- 中不支持 + this._x0 = x; + this._y0 = y; + + this._xi = x; + this._yi = y; + + return this; + }, + + /** + * @param {number} x + * @param {number} y + * @return {module:zrender/core/PathProxy} + */ + lineTo: function (x, y) { + var exceedUnit = mathAbs(x - this._xi) > this._ux + || mathAbs(y - this._yi) > this._uy + // Force draw the first segment + || this._len < 5; + + this.addData(CMD.L, x, y); + + if (this._ctx && exceedUnit) { + this._needsDash() ? this._dashedLineTo(x, y) + : this._ctx.lineTo(x, y); + } + if (exceedUnit) { + this._xi = x; + this._yi = y; + } + + return this; + }, + + /** + * @param {number} x1 + * @param {number} y1 + * @param {number} x2 + * @param {number} y2 + * @param {number} x3 + * @param {number} y3 + * @return {module:zrender/core/PathProxy} + */ + bezierCurveTo: function (x1, y1, x2, y2, x3, y3) { + this.addData(CMD.C, x1, y1, x2, y2, x3, y3); + if (this._ctx) { + this._needsDash() ? this._dashedBezierTo(x1, y1, x2, y2, x3, y3) + : this._ctx.bezierCurveTo(x1, y1, x2, y2, x3, y3); + } + this._xi = x3; + this._yi = y3; + return this; + }, + + /** + * @param {number} x1 + * @param {number} y1 + * @param {number} x2 + * @param {number} y2 + * @return {module:zrender/core/PathProxy} + */ + quadraticCurveTo: function (x1, y1, x2, y2) { + this.addData(CMD.Q, x1, y1, x2, y2); + if (this._ctx) { + this._needsDash() ? this._dashedQuadraticTo(x1, y1, x2, y2) + : this._ctx.quadraticCurveTo(x1, y1, x2, y2); + } + this._xi = x2; + this._yi = y2; + return this; + }, + + /** + * @param {number} cx + * @param {number} cy + * @param {number} r + * @param {number} startAngle + * @param {number} endAngle + * @param {boolean} anticlockwise + * @return {module:zrender/core/PathProxy} + */ + arc: function (cx, cy, r, startAngle, endAngle, anticlockwise) { + this.addData( + CMD.A, cx, cy, r, r, startAngle, endAngle - startAngle, 0, anticlockwise ? 0 : 1 + ); + this._ctx && this._ctx.arc(cx, cy, r, startAngle, endAngle, anticlockwise); + + this._xi = mathCos$1(endAngle) * r + cx; + this._yi = mathSin$1(endAngle) * r + cy; + return this; + }, + + // TODO + arcTo: function (x1, y1, x2, y2, radius) { + if (this._ctx) { + this._ctx.arcTo(x1, y1, x2, y2, radius); + } + return this; + }, + + // TODO + rect: function (x, y, w, h) { + this._ctx && this._ctx.rect(x, y, w, h); + this.addData(CMD.R, x, y, w, h); + return this; + }, + + /** + * @return {module:zrender/core/PathProxy} + */ + closePath: function () { + this.addData(CMD.Z); + + var ctx = this._ctx; + var x0 = this._x0; + var y0 = this._y0; + if (ctx) { + this._needsDash() && this._dashedLineTo(x0, y0); + ctx.closePath(); + } + + this._xi = x0; + this._yi = y0; + return this; + }, + + /** + * Context 从外部传入,因为有可能是 rebuildPath 完之后再 fill。 + * stroke 同样 + * @param {CanvasRenderingContext2D} ctx + * @return {module:zrender/core/PathProxy} + */ + fill: function (ctx) { + ctx && ctx.fill(); + this.toStatic(); + }, + + /** + * @param {CanvasRenderingContext2D} ctx + * @return {module:zrender/core/PathProxy} + */ + stroke: function (ctx) { + ctx && ctx.stroke(); + this.toStatic(); + }, + + /** + * 必须在其它绘制命令前调用 + * Must be invoked before all other path drawing methods + * @return {module:zrender/core/PathProxy} + */ + setLineDash: function (lineDash) { + if (lineDash instanceof Array) { + this._lineDash = lineDash; + + this._dashIdx = 0; + + var lineDashSum = 0; + for (var i = 0; i < lineDash.length; i++) { + lineDashSum += lineDash[i]; + } + this._dashSum = lineDashSum; + } + return this; + }, + + /** + * 必须在其它绘制命令前调用 + * Must be invoked before all other path drawing methods + * @return {module:zrender/core/PathProxy} + */ + setLineDashOffset: function (offset) { + this._dashOffset = offset; + return this; + }, + + /** + * + * @return {boolean} + */ + len: function () { + return this._len; + }, + + /** + * 直接设置 Path 数据 + */ + setData: function (data) { + + var len$$1 = data.length; + + if (!(this.data && this.data.length === len$$1) && hasTypedArray) { + this.data = new Float32Array(len$$1); + } + + for (var i = 0; i < len$$1; i++) { + this.data[i] = data[i]; + } + + this._len = len$$1; + }, + + /** + * 添加子路径 + * @param {module:zrender/core/PathProxy|Array.} path + */ + appendPath: function (path) { + if (!(path instanceof Array)) { + path = [path]; + } + var len$$1 = path.length; + var appendSize = 0; + var offset = this._len; + for (var i = 0; i < len$$1; i++) { + appendSize += path[i].len(); + } + if (hasTypedArray && (this.data instanceof Float32Array)) { + this.data = new Float32Array(offset + appendSize); + } + for (var i = 0; i < len$$1; i++) { + var appendPathData = path[i].data; + for (var k = 0; k < appendPathData.length; k++) { + this.data[offset++] = appendPathData[k]; + } + } + this._len = offset; + }, + + /** + * 填充 Path 数据。 + * 尽量复用而不申明新的数组。大部分图形重绘的指令数据长度都是不变的。 + */ + addData: function (cmd) { + if (!this._saveData) { + return; + } + + var data = this.data; + if (this._len + arguments.length > data.length) { + // 因为之前的数组已经转换成静态的 Float32Array + // 所以不够用时需要扩展一个新的动态数组 + this._expandData(); + data = this.data; + } + for (var i = 0; i < arguments.length; i++) { + data[this._len++] = arguments[i]; + } + + this._prevCmd = cmd; + }, + + _expandData: function () { + // Only if data is Float32Array + if (!(this.data instanceof Array)) { + var newData = []; + for (var i = 0; i < this._len; i++) { + newData[i] = this.data[i]; + } + this.data = newData; + } + }, + + /** + * If needs js implemented dashed line + * @return {boolean} + * @private + */ + _needsDash: function () { + return this._lineDash; + }, + + _dashedLineTo: function (x1, y1) { + var dashSum = this._dashSum; + var offset = this._dashOffset; + var lineDash = this._lineDash; + var ctx = this._ctx; + + var x0 = this._xi; + var y0 = this._yi; + var dx = x1 - x0; + var dy = y1 - y0; + var dist$$1 = mathSqrt$1(dx * dx + dy * dy); + var x = x0; + var y = y0; + var dash; + var nDash = lineDash.length; + var idx; + dx /= dist$$1; + dy /= dist$$1; + + if (offset < 0) { + // Convert to positive offset + offset = dashSum + offset; + } + offset %= dashSum; + x -= offset * dx; + y -= offset * dy; + + while ((dx > 0 && x <= x1) || (dx < 0 && x >= x1) + || (dx === 0 && ((dy > 0 && y <= y1) || (dy < 0 && y >= y1)))) { + idx = this._dashIdx; + dash = lineDash[idx]; + x += dx * dash; + y += dy * dash; + this._dashIdx = (idx + 1) % nDash; + // Skip positive offset + if ((dx > 0 && x < x0) || (dx < 0 && x > x0) || (dy > 0 && y < y0) || (dy < 0 && y > y0)) { + continue; + } + ctx[idx % 2 ? 'moveTo' : 'lineTo']( + dx >= 0 ? mathMin$2(x, x1) : mathMax$2(x, x1), + dy >= 0 ? mathMin$2(y, y1) : mathMax$2(y, y1) + ); + } + // Offset for next lineTo + dx = x - x1; + dy = y - y1; + this._dashOffset = -mathSqrt$1(dx * dx + dy * dy); + }, + + // Not accurate dashed line to + _dashedBezierTo: function (x1, y1, x2, y2, x3, y3) { + var dashSum = this._dashSum; + var offset = this._dashOffset; + var lineDash = this._lineDash; + var ctx = this._ctx; + + var x0 = this._xi; + var y0 = this._yi; + var t; + var dx; + var dy; + var cubicAt$$1 = cubicAt; + var bezierLen = 0; + var idx = this._dashIdx; + var nDash = lineDash.length; + + var x; + var y; + + var tmpLen = 0; + + if (offset < 0) { + // Convert to positive offset + offset = dashSum + offset; + } + offset %= dashSum; + // Bezier approx length + for (t = 0; t < 1; t += 0.1) { + dx = cubicAt$$1(x0, x1, x2, x3, t + 0.1) + - cubicAt$$1(x0, x1, x2, x3, t); + dy = cubicAt$$1(y0, y1, y2, y3, t + 0.1) + - cubicAt$$1(y0, y1, y2, y3, t); + bezierLen += mathSqrt$1(dx * dx + dy * dy); + } + + // Find idx after add offset + for (; idx < nDash; idx++) { + tmpLen += lineDash[idx]; + if (tmpLen > offset) { + break; + } + } + t = (tmpLen - offset) / bezierLen; + + while (t <= 1) { + + x = cubicAt$$1(x0, x1, x2, x3, t); + y = cubicAt$$1(y0, y1, y2, y3, t); + + // Use line to approximate dashed bezier + // Bad result if dash is long + idx % 2 ? ctx.moveTo(x, y) + : ctx.lineTo(x, y); + + t += lineDash[idx] / bezierLen; + + idx = (idx + 1) % nDash; + } + + // Finish the last segment and calculate the new offset + (idx % 2 !== 0) && ctx.lineTo(x3, y3); + dx = x3 - x; + dy = y3 - y; + this._dashOffset = -mathSqrt$1(dx * dx + dy * dy); + }, + + _dashedQuadraticTo: function (x1, y1, x2, y2) { + // Convert quadratic to cubic using degree elevation + var x3 = x2; + var y3 = y2; + x2 = (x2 + 2 * x1) / 3; + y2 = (y2 + 2 * y1) / 3; + x1 = (this._xi + 2 * x1) / 3; + y1 = (this._yi + 2 * y1) / 3; + + this._dashedBezierTo(x1, y1, x2, y2, x3, y3); + }, + + /** + * 转成静态的 Float32Array 减少堆内存占用 + * Convert dynamic array to static Float32Array + */ + toStatic: function () { + var data = this.data; + if (data instanceof Array) { + data.length = this._len; + if (hasTypedArray) { + this.data = new Float32Array(data); + } + } + }, + + /** + * @return {module:zrender/core/BoundingRect} + */ + getBoundingRect: function () { + min$1[0] = min$1[1] = min2[0] = min2[1] = Number.MAX_VALUE; + max$1[0] = max$1[1] = max2[0] = max2[1] = -Number.MAX_VALUE; + + var data = this.data; + var xi = 0; + var yi = 0; + var x0 = 0; + var y0 = 0; + + for (var i = 0; i < data.length;) { + var cmd = data[i++]; + + if (i === 1) { + // 如果第一个命令是 L, C, Q + // 则 previous point 同绘制命令的第一个 point + // + // 第一个命令为 Arc 的情况下会在后面特殊处理 + xi = data[i]; + yi = data[i + 1]; + + x0 = xi; + y0 = yi; + } + + switch (cmd) { + case CMD.M: + // moveTo 命令重新创建一个新的 subpath, 并且更新新的起点 + // 在 closePath 的时候使用 + x0 = data[i++]; + y0 = data[i++]; + xi = x0; + yi = y0; + min2[0] = x0; + min2[1] = y0; + max2[0] = x0; + max2[1] = y0; + break; + case CMD.L: + fromLine(xi, yi, data[i], data[i + 1], min2, max2); + xi = data[i++]; + yi = data[i++]; + break; + case CMD.C: + fromCubic( + xi, yi, data[i++], data[i++], data[i++], data[i++], data[i], data[i + 1], + min2, max2 + ); + xi = data[i++]; + yi = data[i++]; + break; + case CMD.Q: + fromQuadratic( + xi, yi, data[i++], data[i++], data[i], data[i + 1], + min2, max2 + ); + xi = data[i++]; + yi = data[i++]; + break; + case CMD.A: + // TODO Arc 判断的开销比较大 + var cx = data[i++]; + var cy = data[i++]; + var rx = data[i++]; + var ry = data[i++]; + var startAngle = data[i++]; + var endAngle = data[i++] + startAngle; + // TODO Arc 旋转 + i += 1; + var anticlockwise = 1 - data[i++]; + + if (i === 1) { + // 直接使用 arc 命令 + // 第一个命令起点还未定义 + x0 = mathCos$1(startAngle) * rx + cx; + y0 = mathSin$1(startAngle) * ry + cy; + } + + fromArc( + cx, cy, rx, ry, startAngle, endAngle, + anticlockwise, min2, max2 + ); + + xi = mathCos$1(endAngle) * rx + cx; + yi = mathSin$1(endAngle) * ry + cy; + break; + case CMD.R: + x0 = xi = data[i++]; + y0 = yi = data[i++]; + var width = data[i++]; + var height = data[i++]; + // Use fromLine + fromLine(x0, y0, x0 + width, y0 + height, min2, max2); + break; + case CMD.Z: + xi = x0; + yi = y0; + break; + } + + // Union + min(min$1, min$1, min2); + max(max$1, max$1, max2); + } + + // No data + if (i === 0) { + min$1[0] = min$1[1] = max$1[0] = max$1[1] = 0; + } + + return new BoundingRect( + min$1[0], min$1[1], max$1[0] - min$1[0], max$1[1] - min$1[1] + ); + }, + + /** + * Rebuild path from current data + * Rebuild path will not consider javascript implemented line dash. + * @param {CanvasRenderingContext2D} ctx + */ + rebuildPath: function (ctx) { + var d = this.data; + var x0, y0; + var xi, yi; + var x, y; + var ux = this._ux; + var uy = this._uy; + var len$$1 = this._len; + for (var i = 0; i < len$$1;) { + var cmd = d[i++]; + + if (i === 1) { + // 如果第一个命令是 L, C, Q + // 则 previous point 同绘制命令的第一个 point + // + // 第一个命令为 Arc 的情况下会在后面特殊处理 + xi = d[i]; + yi = d[i + 1]; + + x0 = xi; + y0 = yi; + } + switch (cmd) { + case CMD.M: + x0 = xi = d[i++]; + y0 = yi = d[i++]; + ctx.moveTo(xi, yi); + break; + case CMD.L: + x = d[i++]; + y = d[i++]; + // Not draw too small seg between + if (mathAbs(x - xi) > ux || mathAbs(y - yi) > uy || i === len$$1 - 1) { + ctx.lineTo(x, y); + xi = x; + yi = y; + } + break; + case CMD.C: + ctx.bezierCurveTo( + d[i++], d[i++], d[i++], d[i++], d[i++], d[i++] + ); + xi = d[i - 2]; + yi = d[i - 1]; + break; + case CMD.Q: + ctx.quadraticCurveTo(d[i++], d[i++], d[i++], d[i++]); + xi = d[i - 2]; + yi = d[i - 1]; + break; + case CMD.A: + var cx = d[i++]; + var cy = d[i++]; + var rx = d[i++]; + var ry = d[i++]; + var theta = d[i++]; + var dTheta = d[i++]; + var psi = d[i++]; + var fs = d[i++]; + var r = (rx > ry) ? rx : ry; + var scaleX = (rx > ry) ? 1 : rx / ry; + var scaleY = (rx > ry) ? ry / rx : 1; + var isEllipse = Math.abs(rx - ry) > 1e-3; + var endAngle = theta + dTheta; + if (isEllipse) { + ctx.translate(cx, cy); + ctx.rotate(psi); + ctx.scale(scaleX, scaleY); + ctx.arc(0, 0, r, theta, endAngle, 1 - fs); + ctx.scale(1 / scaleX, 1 / scaleY); + ctx.rotate(-psi); + ctx.translate(-cx, -cy); + } + else { + ctx.arc(cx, cy, r, theta, endAngle, 1 - fs); + } + + if (i === 1) { + // 直接使用 arc 命令 + // 第一个命令起点还未定义 + x0 = mathCos$1(theta) * rx + cx; + y0 = mathSin$1(theta) * ry + cy; + } + xi = mathCos$1(endAngle) * rx + cx; + yi = mathSin$1(endAngle) * ry + cy; + break; + case CMD.R: + x0 = xi = d[i]; + y0 = yi = d[i + 1]; + ctx.rect(d[i++], d[i++], d[i++], d[i++]); + break; + case CMD.Z: + ctx.closePath(); + xi = x0; + yi = y0; + } + } + } +}; + +PathProxy.CMD = CMD; + +/** + * 线段包含判断 + * @param {number} x0 + * @param {number} y0 + * @param {number} x1 + * @param {number} y1 + * @param {number} lineWidth + * @param {number} x + * @param {number} y + * @return {boolean} + */ +function containStroke$1(x0, y0, x1, y1, lineWidth, x, y) { + if (lineWidth === 0) { + return false; + } + var _l = lineWidth; + var _a = 0; + var _b = x0; + // Quick reject + if ( + (y > y0 + _l && y > y1 + _l) + || (y < y0 - _l && y < y1 - _l) + || (x > x0 + _l && x > x1 + _l) + || (x < x0 - _l && x < x1 - _l) + ) { + return false; + } + + if (x0 !== x1) { + _a = (y0 - y1) / (x0 - x1); + _b = (x0 * y1 - x1 * y0) / (x0 - x1); + } + else { + return Math.abs(x - x0) <= _l / 2; + } + var tmp = _a * x - y + _b; + var _s = tmp * tmp / (_a * _a + 1); + return _s <= _l / 2 * _l / 2; +} + +/** + * 三次贝塞尔曲线描边包含判断 + * @param {number} x0 + * @param {number} y0 + * @param {number} x1 + * @param {number} y1 + * @param {number} x2 + * @param {number} y2 + * @param {number} x3 + * @param {number} y3 + * @param {number} lineWidth + * @param {number} x + * @param {number} y + * @return {boolean} + */ +function containStroke$2(x0, y0, x1, y1, x2, y2, x3, y3, lineWidth, x, y) { + if (lineWidth === 0) { + return false; + } + var _l = lineWidth; + // Quick reject + if ( + (y > y0 + _l && y > y1 + _l && y > y2 + _l && y > y3 + _l) + || (y < y0 - _l && y < y1 - _l && y < y2 - _l && y < y3 - _l) + || (x > x0 + _l && x > x1 + _l && x > x2 + _l && x > x3 + _l) + || (x < x0 - _l && x < x1 - _l && x < x2 - _l && x < x3 - _l) + ) { + return false; + } + var d = cubicProjectPoint( + x0, y0, x1, y1, x2, y2, x3, y3, + x, y, null + ); + return d <= _l / 2; +} + +/** + * 二次贝塞尔曲线描边包含判断 + * @param {number} x0 + * @param {number} y0 + * @param {number} x1 + * @param {number} y1 + * @param {number} x2 + * @param {number} y2 + * @param {number} lineWidth + * @param {number} x + * @param {number} y + * @return {boolean} + */ +function containStroke$3(x0, y0, x1, y1, x2, y2, lineWidth, x, y) { + if (lineWidth === 0) { + return false; + } + var _l = lineWidth; + // Quick reject + if ( + (y > y0 + _l && y > y1 + _l && y > y2 + _l) + || (y < y0 - _l && y < y1 - _l && y < y2 - _l) + || (x > x0 + _l && x > x1 + _l && x > x2 + _l) + || (x < x0 - _l && x < x1 - _l && x < x2 - _l) + ) { + return false; + } + var d = quadraticProjectPoint( + x0, y0, x1, y1, x2, y2, + x, y, null + ); + return d <= _l / 2; +} + +var PI2$3 = Math.PI * 2; + +function normalizeRadian(angle) { + angle %= PI2$3; + if (angle < 0) { + angle += PI2$3; + } + return angle; +} + +var PI2$2 = Math.PI * 2; + +/** + * 圆弧描边包含判断 + * @param {number} cx + * @param {number} cy + * @param {number} r + * @param {number} startAngle + * @param {number} endAngle + * @param {boolean} anticlockwise + * @param {number} lineWidth + * @param {number} x + * @param {number} y + * @return {Boolean} + */ +function containStroke$4( + cx, cy, r, startAngle, endAngle, anticlockwise, + lineWidth, x, y +) { + + if (lineWidth === 0) { + return false; + } + var _l = lineWidth; + + x -= cx; + y -= cy; + var d = Math.sqrt(x * x + y * y); + + if ((d - _l > r) || (d + _l < r)) { + return false; + } + if (Math.abs(startAngle - endAngle) % PI2$2 < 1e-4) { + // Is a circle + return true; + } + if (anticlockwise) { + var tmp = startAngle; + startAngle = normalizeRadian(endAngle); + endAngle = normalizeRadian(tmp); + } + else { + startAngle = normalizeRadian(startAngle); + endAngle = normalizeRadian(endAngle); + } + if (startAngle > endAngle) { + endAngle += PI2$2; + } + + var angle = Math.atan2(y, x); + if (angle < 0) { + angle += PI2$2; + } + return (angle >= startAngle && angle <= endAngle) + || (angle + PI2$2 >= startAngle && angle + PI2$2 <= endAngle); +} + +function windingLine(x0, y0, x1, y1, x, y) { + if ((y > y0 && y > y1) || (y < y0 && y < y1)) { + return 0; + } + // Ignore horizontal line + if (y1 === y0) { + return 0; + } + var dir = y1 < y0 ? 1 : -1; + var t = (y - y0) / (y1 - y0); + + // Avoid winding error when intersection point is the connect point of two line of polygon + if (t === 1 || t === 0) { + dir = y1 < y0 ? 0.5 : -0.5; + } + + var x_ = t * (x1 - x0) + x0; + + // If (x, y) on the line, considered as "contain". + return x_ === x ? Infinity : x_ > x ? dir : 0; +} + +var CMD$1 = PathProxy.CMD; +var PI2$1 = Math.PI * 2; + +var EPSILON$2 = 1e-4; + +function isAroundEqual(a, b) { + return Math.abs(a - b) < EPSILON$2; +} + +// 临时数组 +var roots = [-1, -1, -1]; +var extrema = [-1, -1]; + +function swapExtrema() { + var tmp = extrema[0]; + extrema[0] = extrema[1]; + extrema[1] = tmp; +} + +function windingCubic(x0, y0, x1, y1, x2, y2, x3, y3, x, y) { + // Quick reject + if ( + (y > y0 && y > y1 && y > y2 && y > y3) + || (y < y0 && y < y1 && y < y2 && y < y3) + ) { + return 0; + } + var nRoots = cubicRootAt(y0, y1, y2, y3, y, roots); + if (nRoots === 0) { + return 0; + } + else { + var w = 0; + var nExtrema = -1; + var y0_; + var y1_; + for (var i = 0; i < nRoots; i++) { + var t = roots[i]; + + // Avoid winding error when intersection point is the connect point of two line of polygon + var unit = (t === 0 || t === 1) ? 0.5 : 1; + + var x_ = cubicAt(x0, x1, x2, x3, t); + if (x_ < x) { // Quick reject + continue; + } + if (nExtrema < 0) { + nExtrema = cubicExtrema(y0, y1, y2, y3, extrema); + if (extrema[1] < extrema[0] && nExtrema > 1) { + swapExtrema(); + } + y0_ = cubicAt(y0, y1, y2, y3, extrema[0]); + if (nExtrema > 1) { + y1_ = cubicAt(y0, y1, y2, y3, extrema[1]); + } + } + if (nExtrema === 2) { + // 分成三段单调函数 + if (t < extrema[0]) { + w += y0_ < y0 ? unit : -unit; + } + else if (t < extrema[1]) { + w += y1_ < y0_ ? unit : -unit; + } + else { + w += y3 < y1_ ? unit : -unit; + } + } + else { + // 分成两段单调函数 + if (t < extrema[0]) { + w += y0_ < y0 ? unit : -unit; + } + else { + w += y3 < y0_ ? unit : -unit; + } + } + } + return w; + } +} + +function windingQuadratic(x0, y0, x1, y1, x2, y2, x, y) { + // Quick reject + if ( + (y > y0 && y > y1 && y > y2) + || (y < y0 && y < y1 && y < y2) + ) { + return 0; + } + var nRoots = quadraticRootAt(y0, y1, y2, y, roots); + if (nRoots === 0) { + return 0; + } + else { + var t = quadraticExtremum(y0, y1, y2); + if (t >= 0 && t <= 1) { + var w = 0; + var y_ = quadraticAt(y0, y1, y2, t); + for (var i = 0; i < nRoots; i++) { + // Remove one endpoint. + var unit = (roots[i] === 0 || roots[i] === 1) ? 0.5 : 1; + + var x_ = quadraticAt(x0, x1, x2, roots[i]); + if (x_ < x) { // Quick reject + continue; + } + if (roots[i] < t) { + w += y_ < y0 ? unit : -unit; + } + else { + w += y2 < y_ ? unit : -unit; + } + } + return w; + } + else { + // Remove one endpoint. + var unit = (roots[0] === 0 || roots[0] === 1) ? 0.5 : 1; + + var x_ = quadraticAt(x0, x1, x2, roots[0]); + if (x_ < x) { // Quick reject + return 0; + } + return y2 < y0 ? unit : -unit; + } + } +} + +// TODO +// Arc 旋转 +function windingArc( + cx, cy, r, startAngle, endAngle, anticlockwise, x, y +) { + y -= cy; + if (y > r || y < -r) { + return 0; + } + var tmp = Math.sqrt(r * r - y * y); + roots[0] = -tmp; + roots[1] = tmp; + + var diff = Math.abs(startAngle - endAngle); + if (diff < 1e-4) { + return 0; + } + if (diff % PI2$1 < 1e-4) { + // Is a circle + startAngle = 0; + endAngle = PI2$1; + var dir = anticlockwise ? 1 : -1; + if (x >= roots[0] + cx && x <= roots[1] + cx) { + return dir; + } + else { + return 0; + } + } + + if (anticlockwise) { + var tmp = startAngle; + startAngle = normalizeRadian(endAngle); + endAngle = normalizeRadian(tmp); + } + else { + startAngle = normalizeRadian(startAngle); + endAngle = normalizeRadian(endAngle); + } + if (startAngle > endAngle) { + endAngle += PI2$1; + } + + var w = 0; + for (var i = 0; i < 2; i++) { + var x_ = roots[i]; + if (x_ + cx > x) { + var angle = Math.atan2(y, x_); + var dir = anticlockwise ? 1 : -1; + if (angle < 0) { + angle = PI2$1 + angle; + } + if ( + (angle >= startAngle && angle <= endAngle) + || (angle + PI2$1 >= startAngle && angle + PI2$1 <= endAngle) + ) { + if (angle > Math.PI / 2 && angle < Math.PI * 1.5) { + dir = -dir; + } + w += dir; + } + } + } + return w; +} + +function containPath(data, lineWidth, isStroke, x, y) { + var w = 0; + var xi = 0; + var yi = 0; + var x0 = 0; + var y0 = 0; + + for (var i = 0; i < data.length;) { + var cmd = data[i++]; + // Begin a new subpath + if (cmd === CMD$1.M && i > 1) { + // Close previous subpath + if (!isStroke) { + w += windingLine(xi, yi, x0, y0, x, y); + } + // 如果被任何一个 subpath 包含 + // if (w !== 0) { + // return true; + // } + } + + if (i === 1) { + // 如果第一个命令是 L, C, Q + // 则 previous point 同绘制命令的第一个 point + // + // 第一个命令为 Arc 的情况下会在后面特殊处理 + xi = data[i]; + yi = data[i + 1]; + + x0 = xi; + y0 = yi; + } + + switch (cmd) { + case CMD$1.M: + // moveTo 命令重新创建一个新的 subpath, 并且更新新的起点 + // 在 closePath 的时候使用 + x0 = data[i++]; + y0 = data[i++]; + xi = x0; + yi = y0; + break; + case CMD$1.L: + if (isStroke) { + if (containStroke$1(xi, yi, data[i], data[i + 1], lineWidth, x, y)) { + return true; + } + } + else { + // NOTE 在第一个命令为 L, C, Q 的时候会计算出 NaN + w += windingLine(xi, yi, data[i], data[i + 1], x, y) || 0; + } + xi = data[i++]; + yi = data[i++]; + break; + case CMD$1.C: + if (isStroke) { + if (containStroke$2(xi, yi, + data[i++], data[i++], data[i++], data[i++], data[i], data[i + 1], + lineWidth, x, y + )) { + return true; + } + } + else { + w += windingCubic( + xi, yi, + data[i++], data[i++], data[i++], data[i++], data[i], data[i + 1], + x, y + ) || 0; + } + xi = data[i++]; + yi = data[i++]; + break; + case CMD$1.Q: + if (isStroke) { + if (containStroke$3(xi, yi, + data[i++], data[i++], data[i], data[i + 1], + lineWidth, x, y + )) { + return true; + } + } + else { + w += windingQuadratic( + xi, yi, + data[i++], data[i++], data[i], data[i + 1], + x, y + ) || 0; + } + xi = data[i++]; + yi = data[i++]; + break; + case CMD$1.A: + // TODO Arc 判断的开销比较大 + var cx = data[i++]; + var cy = data[i++]; + var rx = data[i++]; + var ry = data[i++]; + var theta = data[i++]; + var dTheta = data[i++]; + // TODO Arc 旋转 + i += 1; + var anticlockwise = 1 - data[i++]; + var x1 = Math.cos(theta) * rx + cx; + var y1 = Math.sin(theta) * ry + cy; + // 不是直接使用 arc 命令 + if (i > 1) { + w += windingLine(xi, yi, x1, y1, x, y); + } + else { + // 第一个命令起点还未定义 + x0 = x1; + y0 = y1; + } + // zr 使用scale来模拟椭圆, 这里也对x做一定的缩放 + var _x = (x - cx) * ry / rx + cx; + if (isStroke) { + if (containStroke$4( + cx, cy, ry, theta, theta + dTheta, anticlockwise, + lineWidth, _x, y + )) { + return true; + } + } + else { + w += windingArc( + cx, cy, ry, theta, theta + dTheta, anticlockwise, + _x, y + ); + } + xi = Math.cos(theta + dTheta) * rx + cx; + yi = Math.sin(theta + dTheta) * ry + cy; + break; + case CMD$1.R: + x0 = xi = data[i++]; + y0 = yi = data[i++]; + var width = data[i++]; + var height = data[i++]; + var x1 = x0 + width; + var y1 = y0 + height; + if (isStroke) { + if (containStroke$1(x0, y0, x1, y0, lineWidth, x, y) + || containStroke$1(x1, y0, x1, y1, lineWidth, x, y) + || containStroke$1(x1, y1, x0, y1, lineWidth, x, y) + || containStroke$1(x0, y1, x0, y0, lineWidth, x, y) + ) { + return true; + } + } + else { + // FIXME Clockwise ? + w += windingLine(x1, y0, x1, y1, x, y); + w += windingLine(x0, y1, x0, y0, x, y); + } + break; + case CMD$1.Z: + if (isStroke) { + if (containStroke$1( + xi, yi, x0, y0, lineWidth, x, y + )) { + return true; + } + } + else { + // Close a subpath + w += windingLine(xi, yi, x0, y0, x, y); + // 如果被任何一个 subpath 包含 + // FIXME subpaths may overlap + // if (w !== 0) { + // return true; + // } + } + xi = x0; + yi = y0; + break; + } + } + if (!isStroke && !isAroundEqual(yi, y0)) { + w += windingLine(xi, yi, x0, y0, x, y) || 0; + } + return w !== 0; +} + +function contain(pathData, x, y) { + return containPath(pathData, 0, false, x, y); +} + +function containStroke(pathData, lineWidth, x, y) { + return containPath(pathData, lineWidth, true, x, y); +} + +var getCanvasPattern = Pattern.prototype.getCanvasPattern; + +var abs = Math.abs; + +var pathProxyForDraw = new PathProxy(true); +/** + * @alias module:zrender/graphic/Path + * @extends module:zrender/graphic/Displayable + * @constructor + * @param {Object} opts + */ +function Path(opts) { + Displayable.call(this, opts); + + /** + * @type {module:zrender/core/PathProxy} + * @readOnly + */ + this.path = null; +} + +Path.prototype = { + + constructor: Path, + + type: 'path', + + __dirtyPath: true, + + strokeContainThreshold: 5, + + /** + * See `module:zrender/src/graphic/helper/subPixelOptimize`. + * @type {boolean} + */ + subPixelOptimize: false, + + brush: function (ctx, prevEl) { + var style = this.style; + var path = this.path || pathProxyForDraw; + var hasStroke = style.hasStroke(); + var hasFill = style.hasFill(); + var fill = style.fill; + var stroke = style.stroke; + var hasFillGradient = hasFill && !!(fill.colorStops); + var hasStrokeGradient = hasStroke && !!(stroke.colorStops); + var hasFillPattern = hasFill && !!(fill.image); + var hasStrokePattern = hasStroke && !!(stroke.image); + + style.bind(ctx, this, prevEl); + this.setTransform(ctx); + + if (this.__dirty) { + var rect; + // Update gradient because bounding rect may changed + if (hasFillGradient) { + rect = rect || this.getBoundingRect(); + this._fillGradient = style.getGradient(ctx, fill, rect); + } + if (hasStrokeGradient) { + rect = rect || this.getBoundingRect(); + this._strokeGradient = style.getGradient(ctx, stroke, rect); + } + } + // Use the gradient or pattern + if (hasFillGradient) { + // PENDING If may have affect the state + ctx.fillStyle = this._fillGradient; + } + else if (hasFillPattern) { + ctx.fillStyle = getCanvasPattern.call(fill, ctx); + } + if (hasStrokeGradient) { + ctx.strokeStyle = this._strokeGradient; + } + else if (hasStrokePattern) { + ctx.strokeStyle = getCanvasPattern.call(stroke, ctx); + } + + var lineDash = style.lineDash; + var lineDashOffset = style.lineDashOffset; + + var ctxLineDash = !!ctx.setLineDash; + + // Update path sx, sy + var scale = this.getGlobalScale(); + path.setScale(scale[0], scale[1]); + + // Proxy context + // Rebuild path in following 2 cases + // 1. Path is dirty + // 2. Path needs javascript implemented lineDash stroking. + // In this case, lineDash information will not be saved in PathProxy + if (this.__dirtyPath + || (lineDash && !ctxLineDash && hasStroke) + ) { + path.beginPath(ctx); + + // Setting line dash before build path + if (lineDash && !ctxLineDash) { + path.setLineDash(lineDash); + path.setLineDashOffset(lineDashOffset); + } + + this.buildPath(path, this.shape, false); + + // Clear path dirty flag + if (this.path) { + this.__dirtyPath = false; + } + } + else { + // Replay path building + ctx.beginPath(); + this.path.rebuildPath(ctx); + } + + if (hasFill) { + if (style.fillOpacity != null) { + var originalGlobalAlpha = ctx.globalAlpha; + ctx.globalAlpha = style.fillOpacity * style.opacity; + path.fill(ctx); + ctx.globalAlpha = originalGlobalAlpha; + } + else { + path.fill(ctx); + } + } + + if (lineDash && ctxLineDash) { + ctx.setLineDash(lineDash); + ctx.lineDashOffset = lineDashOffset; + } + + if (hasStroke) { + if (style.strokeOpacity != null) { + var originalGlobalAlpha = ctx.globalAlpha; + ctx.globalAlpha = style.strokeOpacity * style.opacity; + path.stroke(ctx); + ctx.globalAlpha = originalGlobalAlpha; + } + else { + path.stroke(ctx); + } + } + + if (lineDash && ctxLineDash) { + // PENDING + // Remove lineDash + ctx.setLineDash([]); + } + + // Draw rect text + if (style.text != null) { + // Only restore transform when needs draw text. + this.restoreTransform(ctx); + this.drawRectText(ctx, this.getBoundingRect()); + } + }, + + // When bundling path, some shape may decide if use moveTo to begin a new subpath or closePath + // Like in circle + buildPath: function (ctx, shapeCfg, inBundle) {}, + + createPathProxy: function () { + this.path = new PathProxy(); + }, + + getBoundingRect: function () { + var rect = this._rect; + var style = this.style; + var needsUpdateRect = !rect; + if (needsUpdateRect) { + var path = this.path; + if (!path) { + // Create path on demand. + path = this.path = new PathProxy(); + } + if (this.__dirtyPath) { + path.beginPath(); + this.buildPath(path, this.shape, false); + } + rect = path.getBoundingRect(); + } + this._rect = rect; + + if (style.hasStroke()) { + // Needs update rect with stroke lineWidth when + // 1. Element changes scale or lineWidth + // 2. Shape is changed + var rectWithStroke = this._rectWithStroke || (this._rectWithStroke = rect.clone()); + if (this.__dirty || needsUpdateRect) { + rectWithStroke.copy(rect); + // FIXME Must after updateTransform + var w = style.lineWidth; + // PENDING, Min line width is needed when line is horizontal or vertical + var lineScale = style.strokeNoScale ? this.getLineScale() : 1; + + // Only add extra hover lineWidth when there are no fill + if (!style.hasFill()) { + w = Math.max(w, this.strokeContainThreshold || 4); + } + // Consider line width + // Line scale can't be 0; + if (lineScale > 1e-10) { + rectWithStroke.width += w / lineScale; + rectWithStroke.height += w / lineScale; + rectWithStroke.x -= w / lineScale / 2; + rectWithStroke.y -= w / lineScale / 2; + } + } + + // Return rect with stroke + return rectWithStroke; + } + + return rect; + }, + + contain: function (x, y) { + var localPos = this.transformCoordToLocal(x, y); + var rect = this.getBoundingRect(); + var style = this.style; + x = localPos[0]; + y = localPos[1]; + + if (rect.contain(x, y)) { + var pathData = this.path.data; + if (style.hasStroke()) { + var lineWidth = style.lineWidth; + var lineScale = style.strokeNoScale ? this.getLineScale() : 1; + // Line scale can't be 0; + if (lineScale > 1e-10) { + // Only add extra hover lineWidth when there are no fill + if (!style.hasFill()) { + lineWidth = Math.max(lineWidth, this.strokeContainThreshold); + } + if (containStroke( + pathData, lineWidth / lineScale, x, y + )) { + return true; + } + } + } + if (style.hasFill()) { + return contain(pathData, x, y); + } + } + return false; + }, + + /** + * @param {boolean} dirtyPath + */ + dirty: function (dirtyPath) { + if (dirtyPath == null) { + dirtyPath = true; + } + // Only mark dirty, not mark clean + if (dirtyPath) { + this.__dirtyPath = dirtyPath; + this._rect = null; + } + + this.__dirty = this.__dirtyText = true; + + this.__zr && this.__zr.refresh(); + + // Used as a clipping path + if (this.__clipTarget) { + this.__clipTarget.dirty(); + } + }, + + /** + * Alias for animate('shape') + * @param {boolean} loop + */ + animateShape: function (loop) { + return this.animate('shape', loop); + }, + + // Overwrite attrKV + attrKV: function (key, value) { + // FIXME + if (key === 'shape') { + this.setShape(value); + this.__dirtyPath = true; + this._rect = null; + } + else { + Displayable.prototype.attrKV.call(this, key, value); + } + }, + + /** + * @param {Object|string} key + * @param {*} value + */ + setShape: function (key, value) { + var shape = this.shape; + // Path from string may not have shape + if (shape) { + if (isObject$1(key)) { + for (var name in key) { + if (key.hasOwnProperty(name)) { + shape[name] = key[name]; + } + } + } + else { + shape[key] = value; + } + this.dirty(true); + } + return this; + }, + + getLineScale: function () { + var m = this.transform; + // Get the line scale. + // Determinant of `m` means how much the area is enlarged by the + // transformation. So its square root can be used as a scale factor + // for width. + return m && abs(m[0] - 1) > 1e-10 && abs(m[3] - 1) > 1e-10 + ? Math.sqrt(abs(m[0] * m[3] - m[2] * m[1])) + : 1; + } +}; + +/** + * 扩展一个 Path element, 比如星形,圆等。 + * Extend a path element + * @param {Object} props + * @param {string} props.type Path type + * @param {Function} props.init Initialize + * @param {Function} props.buildPath Overwrite buildPath method + * @param {Object} [props.style] Extended default style config + * @param {Object} [props.shape] Extended default shape config + */ +Path.extend = function (defaults$$1) { + var Sub = function (opts) { + Path.call(this, opts); + + if (defaults$$1.style) { + // Extend default style + this.style.extendFrom(defaults$$1.style, false); + } + + // Extend default shape + var defaultShape = defaults$$1.shape; + if (defaultShape) { + this.shape = this.shape || {}; + var thisShape = this.shape; + for (var name in defaultShape) { + if ( + !thisShape.hasOwnProperty(name) + && defaultShape.hasOwnProperty(name) + ) { + thisShape[name] = defaultShape[name]; + } + } + } + + defaults$$1.init && defaults$$1.init.call(this, opts); + }; + + inherits(Sub, Path); + + // FIXME 不能 extend position, rotation 等引用对象 + for (var name in defaults$$1) { + // Extending prototype values and methods + if (name !== 'style' && name !== 'shape') { + Sub.prototype[name] = defaults$$1[name]; + } + } + + return Sub; +}; + +inherits(Path, Displayable); + +var CMD$2 = PathProxy.CMD; + +var points = [[], [], []]; +var mathSqrt$3 = Math.sqrt; +var mathAtan2 = Math.atan2; + +var transformPath = function (path, m) { + var data = path.data; + var cmd; + var nPoint; + var i; + var j; + var k; + var p; + + var M = CMD$2.M; + var C = CMD$2.C; + var L = CMD$2.L; + var R = CMD$2.R; + var A = CMD$2.A; + var Q = CMD$2.Q; + + for (i = 0, j = 0; i < data.length;) { + cmd = data[i++]; + j = i; + nPoint = 0; + + switch (cmd) { + case M: + nPoint = 1; + break; + case L: + nPoint = 1; + break; + case C: + nPoint = 3; + break; + case Q: + nPoint = 2; + break; + case A: + var x = m[4]; + var y = m[5]; + var sx = mathSqrt$3(m[0] * m[0] + m[1] * m[1]); + var sy = mathSqrt$3(m[2] * m[2] + m[3] * m[3]); + var angle = mathAtan2(-m[1] / sy, m[0] / sx); + // cx + data[i] *= sx; + data[i++] += x; + // cy + data[i] *= sy; + data[i++] += y; + // Scale rx and ry + // FIXME Assume psi is 0 here + data[i++] *= sx; + data[i++] *= sy; + + // Start angle + data[i++] += angle; + // end angle + data[i++] += angle; + // FIXME psi + i += 2; + j = i; + break; + case R: + // x0, y0 + p[0] = data[i++]; + p[1] = data[i++]; + applyTransform(p, p, m); + data[j++] = p[0]; + data[j++] = p[1]; + // x1, y1 + p[0] += data[i++]; + p[1] += data[i++]; + applyTransform(p, p, m); + data[j++] = p[0]; + data[j++] = p[1]; + } + + for (k = 0; k < nPoint; k++) { + var p = points[k]; + p[0] = data[i++]; + p[1] = data[i++]; + + applyTransform(p, p, m); + // Write back + data[j++] = p[0]; + data[j++] = p[1]; + } + } +}; + +// command chars +// var cc = [ +// 'm', 'M', 'l', 'L', 'v', 'V', 'h', 'H', 'z', 'Z', +// 'c', 'C', 'q', 'Q', 't', 'T', 's', 'S', 'a', 'A' +// ]; + +var mathSqrt = Math.sqrt; +var mathSin = Math.sin; +var mathCos = Math.cos; +var PI = Math.PI; + +var vMag = function (v) { + return Math.sqrt(v[0] * v[0] + v[1] * v[1]); +}; +var vRatio = function (u, v) { + return (u[0] * v[0] + u[1] * v[1]) / (vMag(u) * vMag(v)); +}; +var vAngle = function (u, v) { + return (u[0] * v[1] < u[1] * v[0] ? -1 : 1) + * Math.acos(vRatio(u, v)); +}; + +function processArc(x1, y1, x2, y2, fa, fs, rx, ry, psiDeg, cmd, path) { + var psi = psiDeg * (PI / 180.0); + var xp = mathCos(psi) * (x1 - x2) / 2.0 + + mathSin(psi) * (y1 - y2) / 2.0; + var yp = -1 * mathSin(psi) * (x1 - x2) / 2.0 + + mathCos(psi) * (y1 - y2) / 2.0; + + var lambda = (xp * xp) / (rx * rx) + (yp * yp) / (ry * ry); + + if (lambda > 1) { + rx *= mathSqrt(lambda); + ry *= mathSqrt(lambda); + } + + var f = (fa === fs ? -1 : 1) + * mathSqrt((((rx * rx) * (ry * ry)) + - ((rx * rx) * (yp * yp)) + - ((ry * ry) * (xp * xp))) / ((rx * rx) * (yp * yp) + + (ry * ry) * (xp * xp)) + ) || 0; + + var cxp = f * rx * yp / ry; + var cyp = f * -ry * xp / rx; + + var cx = (x1 + x2) / 2.0 + + mathCos(psi) * cxp + - mathSin(psi) * cyp; + var cy = (y1 + y2) / 2.0 + + mathSin(psi) * cxp + + mathCos(psi) * cyp; + + var theta = vAngle([ 1, 0 ], [ (xp - cxp) / rx, (yp - cyp) / ry ]); + var u = [ (xp - cxp) / rx, (yp - cyp) / ry ]; + var v = [ (-1 * xp - cxp) / rx, (-1 * yp - cyp) / ry ]; + var dTheta = vAngle(u, v); + + if (vRatio(u, v) <= -1) { + dTheta = PI; + } + if (vRatio(u, v) >= 1) { + dTheta = 0; + } + if (fs === 0 && dTheta > 0) { + dTheta = dTheta - 2 * PI; + } + if (fs === 1 && dTheta < 0) { + dTheta = dTheta + 2 * PI; + } + + path.addData(cmd, cx, cy, rx, ry, theta, dTheta, psi, fs); +} + + +var commandReg = /([mlvhzcqtsa])([^mlvhzcqtsa]*)/ig; +// Consider case: +// (1) delimiter can be comma or space, where continuous commas +// or spaces should be seen as one comma. +// (2) value can be like: +// '2e-4', 'l.5.9' (ignore 0), 'M-10-10', 'l-2.43e-1,34.9983', +// 'l-.5E1,54', '121-23-44-11' (no delimiter) +var numberReg = /-?([0-9]*\.)?[0-9]+([eE]-?[0-9]+)?/g; +// var valueSplitReg = /[\s,]+/; + +function createPathProxyFromString(data) { + if (!data) { + return new PathProxy(); + } + + // var data = data.replace(/-/g, ' -') + // .replace(/ /g, ' ') + // .replace(/ /g, ',') + // .replace(/,,/g, ','); + + // var n; + // create pipes so that we can split the data + // for (n = 0; n < cc.length; n++) { + // cs = cs.replace(new RegExp(cc[n], 'g'), '|' + cc[n]); + // } + + // data = data.replace(/-/g, ',-'); + + // create array + // var arr = cs.split('|'); + // init context point + var cpx = 0; + var cpy = 0; + var subpathX = cpx; + var subpathY = cpy; + var prevCmd; + + var path = new PathProxy(); + var CMD = PathProxy.CMD; + + // commandReg.lastIndex = 0; + // var cmdResult; + // while ((cmdResult = commandReg.exec(data)) != null) { + // var cmdStr = cmdResult[1]; + // var cmdContent = cmdResult[2]; + + var cmdList = data.match(commandReg); + for (var l = 0; l < cmdList.length; l++) { + var cmdText = cmdList[l]; + var cmdStr = cmdText.charAt(0); + + var cmd; + + // String#split is faster a little bit than String#replace or RegExp#exec. + // var p = cmdContent.split(valueSplitReg); + // var pLen = 0; + // for (var i = 0; i < p.length; i++) { + // // '' and other invalid str => NaN + // var val = parseFloat(p[i]); + // !isNaN(val) && (p[pLen++] = val); + // } + + var p = cmdText.match(numberReg) || []; + var pLen = p.length; + for (var i = 0; i < pLen; i++) { + p[i] = parseFloat(p[i]); + } + + var off = 0; + while (off < pLen) { + var ctlPtx; + var ctlPty; + + var rx; + var ry; + var psi; + var fa; + var fs; + + var x1 = cpx; + var y1 = cpy; + + // convert l, H, h, V, and v to L + switch (cmdStr) { + case 'l': + cpx += p[off++]; + cpy += p[off++]; + cmd = CMD.L; + path.addData(cmd, cpx, cpy); + break; + case 'L': + cpx = p[off++]; + cpy = p[off++]; + cmd = CMD.L; + path.addData(cmd, cpx, cpy); + break; + case 'm': + cpx += p[off++]; + cpy += p[off++]; + cmd = CMD.M; + path.addData(cmd, cpx, cpy); + subpathX = cpx; + subpathY = cpy; + cmdStr = 'l'; + break; + case 'M': + cpx = p[off++]; + cpy = p[off++]; + cmd = CMD.M; + path.addData(cmd, cpx, cpy); + subpathX = cpx; + subpathY = cpy; + cmdStr = 'L'; + break; + case 'h': + cpx += p[off++]; + cmd = CMD.L; + path.addData(cmd, cpx, cpy); + break; + case 'H': + cpx = p[off++]; + cmd = CMD.L; + path.addData(cmd, cpx, cpy); + break; + case 'v': + cpy += p[off++]; + cmd = CMD.L; + path.addData(cmd, cpx, cpy); + break; + case 'V': + cpy = p[off++]; + cmd = CMD.L; + path.addData(cmd, cpx, cpy); + break; + case 'C': + cmd = CMD.C; + path.addData( + cmd, p[off++], p[off++], p[off++], p[off++], p[off++], p[off++] + ); + cpx = p[off - 2]; + cpy = p[off - 1]; + break; + case 'c': + cmd = CMD.C; + path.addData( + cmd, + p[off++] + cpx, p[off++] + cpy, + p[off++] + cpx, p[off++] + cpy, + p[off++] + cpx, p[off++] + cpy + ); + cpx += p[off - 2]; + cpy += p[off - 1]; + break; + case 'S': + ctlPtx = cpx; + ctlPty = cpy; + var len = path.len(); + var pathData = path.data; + if (prevCmd === CMD.C) { + ctlPtx += cpx - pathData[len - 4]; + ctlPty += cpy - pathData[len - 3]; + } + cmd = CMD.C; + x1 = p[off++]; + y1 = p[off++]; + cpx = p[off++]; + cpy = p[off++]; + path.addData(cmd, ctlPtx, ctlPty, x1, y1, cpx, cpy); + break; + case 's': + ctlPtx = cpx; + ctlPty = cpy; + var len = path.len(); + var pathData = path.data; + if (prevCmd === CMD.C) { + ctlPtx += cpx - pathData[len - 4]; + ctlPty += cpy - pathData[len - 3]; + } + cmd = CMD.C; + x1 = cpx + p[off++]; + y1 = cpy + p[off++]; + cpx += p[off++]; + cpy += p[off++]; + path.addData(cmd, ctlPtx, ctlPty, x1, y1, cpx, cpy); + break; + case 'Q': + x1 = p[off++]; + y1 = p[off++]; + cpx = p[off++]; + cpy = p[off++]; + cmd = CMD.Q; + path.addData(cmd, x1, y1, cpx, cpy); + break; + case 'q': + x1 = p[off++] + cpx; + y1 = p[off++] + cpy; + cpx += p[off++]; + cpy += p[off++]; + cmd = CMD.Q; + path.addData(cmd, x1, y1, cpx, cpy); + break; + case 'T': + ctlPtx = cpx; + ctlPty = cpy; + var len = path.len(); + var pathData = path.data; + if (prevCmd === CMD.Q) { + ctlPtx += cpx - pathData[len - 4]; + ctlPty += cpy - pathData[len - 3]; + } + cpx = p[off++]; + cpy = p[off++]; + cmd = CMD.Q; + path.addData(cmd, ctlPtx, ctlPty, cpx, cpy); + break; + case 't': + ctlPtx = cpx; + ctlPty = cpy; + var len = path.len(); + var pathData = path.data; + if (prevCmd === CMD.Q) { + ctlPtx += cpx - pathData[len - 4]; + ctlPty += cpy - pathData[len - 3]; + } + cpx += p[off++]; + cpy += p[off++]; + cmd = CMD.Q; + path.addData(cmd, ctlPtx, ctlPty, cpx, cpy); + break; + case 'A': + rx = p[off++]; + ry = p[off++]; + psi = p[off++]; + fa = p[off++]; + fs = p[off++]; + + x1 = cpx, y1 = cpy; + cpx = p[off++]; + cpy = p[off++]; + cmd = CMD.A; + processArc( + x1, y1, cpx, cpy, fa, fs, rx, ry, psi, cmd, path + ); + break; + case 'a': + rx = p[off++]; + ry = p[off++]; + psi = p[off++]; + fa = p[off++]; + fs = p[off++]; + + x1 = cpx, y1 = cpy; + cpx += p[off++]; + cpy += p[off++]; + cmd = CMD.A; + processArc( + x1, y1, cpx, cpy, fa, fs, rx, ry, psi, cmd, path + ); + break; + } + } + + if (cmdStr === 'z' || cmdStr === 'Z') { + cmd = CMD.Z; + path.addData(cmd); + // z may be in the middle of the path. + cpx = subpathX; + cpy = subpathY; + } + + prevCmd = cmd; + } + + path.toStatic(); + + return path; +} + +// TODO Optimize double memory cost problem +function createPathOptions(str, opts) { + var pathProxy = createPathProxyFromString(str); + opts = opts || {}; + opts.buildPath = function (path) { + if (path.setData) { + path.setData(pathProxy.data); + // Svg and vml renderer don't have context + var ctx = path.getContext(); + if (ctx) { + path.rebuildPath(ctx); + } + } + else { + var ctx = path; + pathProxy.rebuildPath(ctx); + } + }; + + opts.applyTransform = function (m) { + transformPath(pathProxy, m); + this.dirty(true); + }; + + return opts; +} + +/** + * Create a Path object from path string data + * http://www.w3.org/TR/SVG/paths.html#PathData + * @param {Object} opts Other options + */ +function createFromString(str, opts) { + return new Path(createPathOptions(str, opts)); +} + +/** + * Create a Path class from path string data + * @param {string} str + * @param {Object} opts Other options + */ +function extendFromString(str, opts) { + return Path.extend(createPathOptions(str, opts)); +} + +/** + * Merge multiple paths + */ +// TODO Apply transform +// TODO stroke dash +// TODO Optimize double memory cost problem +function mergePath$1(pathEls, opts) { + var pathList = []; + var len = pathEls.length; + for (var i = 0; i < len; i++) { + var pathEl = pathEls[i]; + if (!pathEl.path) { + pathEl.createPathProxy(); + } + if (pathEl.__dirtyPath) { + pathEl.buildPath(pathEl.path, pathEl.shape, true); + } + pathList.push(pathEl.path); + } + + var pathBundle = new Path(opts); + // Need path proxy. + pathBundle.createPathProxy(); + pathBundle.buildPath = function (path) { + path.appendPath(pathList); + // Svg and vml renderer don't have context + var ctx = path.getContext(); + if (ctx) { + path.rebuildPath(ctx); + } + }; + + return pathBundle; +} + +/** + * @alias zrender/graphic/Text + * @extends module:zrender/graphic/Displayable + * @constructor + * @param {Object} opts + */ +var Text = function (opts) { // jshint ignore:line + Displayable.call(this, opts); +}; + +Text.prototype = { + + constructor: Text, + + type: 'text', + + brush: function (ctx, prevEl) { + var style = this.style; + + // Optimize, avoid normalize every time. + this.__dirty && normalizeTextStyle(style, true); + + // Use props with prefix 'text'. + style.fill = style.stroke = style.shadowBlur = style.shadowColor = + style.shadowOffsetX = style.shadowOffsetY = null; + + var text = style.text; + // Convert to string + text != null && (text += ''); + + // Do not apply style.bind in Text node. Because the real bind job + // is in textHelper.renderText, and performance of text render should + // be considered. + // style.bind(ctx, this, prevEl); + + if (!needDrawText(text, style)) { + // The current el.style is not applied + // and should not be used as cache. + ctx.__attrCachedBy = ContextCachedBy.NONE; + return; + } + + this.setTransform(ctx); + + renderText(this, ctx, text, style, null, prevEl); + + this.restoreTransform(ctx); + }, + + getBoundingRect: function () { + var style = this.style; + + // Optimize, avoid normalize every time. + this.__dirty && normalizeTextStyle(style, true); + + if (!this._rect) { + var text = style.text; + text != null ? (text += '') : (text = ''); + + var rect = getBoundingRect( + style.text + '', + style.font, + style.textAlign, + style.textVerticalAlign, + style.textPadding, + style.textLineHeight, + style.rich + ); + + rect.x += style.x || 0; + rect.y += style.y || 0; + + if (getStroke(style.textStroke, style.textStrokeWidth)) { + var w = style.textStrokeWidth; + rect.x -= w / 2; + rect.y -= w / 2; + rect.width += w; + rect.height += w; + } + + this._rect = rect; + } + + return this._rect; + } +}; + +inherits(Text, Displayable); + +/** + * 圆形 + * @module zrender/shape/Circle + */ + +var Circle = Path.extend({ + + type: 'circle', + + shape: { + cx: 0, + cy: 0, + r: 0 + }, + + + buildPath: function (ctx, shape, inBundle) { + // Better stroking in ShapeBundle + // Always do it may have performence issue ( fill may be 2x more cost) + if (inBundle) { + ctx.moveTo(shape.cx + shape.r, shape.cy); + } + // else { + // if (ctx.allocate && !ctx.data.length) { + // ctx.allocate(ctx.CMD_MEM_SIZE.A); + // } + // } + // Better stroking in ShapeBundle + // ctx.moveTo(shape.cx + shape.r, shape.cy); + ctx.arc(shape.cx, shape.cy, shape.r, 0, Math.PI * 2, true); + } +}); + +// Fix weird bug in some version of IE11 (like 11.0.9600.178**), +// where exception "unexpected call to method or property access" +// might be thrown when calling ctx.fill or ctx.stroke after a path +// whose area size is zero is drawn and ctx.clip() is called and +// shadowBlur is set. See #4572, #3112, #5777. +// (e.g., +// ctx.moveTo(10, 10); +// ctx.lineTo(20, 10); +// ctx.closePath(); +// ctx.clip(); +// ctx.shadowBlur = 10; +// ... +// ctx.fill(); +// ) + +var shadowTemp = [ + ['shadowBlur', 0], + ['shadowColor', '#000'], + ['shadowOffsetX', 0], + ['shadowOffsetY', 0] +]; + +var fixClipWithShadow = function (orignalBrush) { + + // version string can be: '11.0' + return (env$1.browser.ie && env$1.browser.version >= 11) + + ? function () { + var clipPaths = this.__clipPaths; + var style = this.style; + var modified; + + if (clipPaths) { + for (var i = 0; i < clipPaths.length; i++) { + var clipPath = clipPaths[i]; + var shape = clipPath && clipPath.shape; + var type = clipPath && clipPath.type; + + if (shape && ( + (type === 'sector' && shape.startAngle === shape.endAngle) + || (type === 'rect' && (!shape.width || !shape.height)) + )) { + for (var j = 0; j < shadowTemp.length; j++) { + // It is save to put shadowTemp static, because shadowTemp + // will be all modified each item brush called. + shadowTemp[j][2] = style[shadowTemp[j][0]]; + style[shadowTemp[j][0]] = shadowTemp[j][1]; + } + modified = true; + break; + } + } + } + + orignalBrush.apply(this, arguments); + + if (modified) { + for (var j = 0; j < shadowTemp.length; j++) { + style[shadowTemp[j][0]] = shadowTemp[j][2]; + } + } + } + + : orignalBrush; +}; + +/** + * 扇形 + * @module zrender/graphic/shape/Sector + */ + +var Sector = Path.extend({ + + type: 'sector', + + shape: { + + cx: 0, + + cy: 0, + + r0: 0, + + r: 0, + + startAngle: 0, + + endAngle: Math.PI * 2, + + clockwise: true + }, + + brush: fixClipWithShadow(Path.prototype.brush), + + buildPath: function (ctx, shape) { + + var x = shape.cx; + var y = shape.cy; + var r0 = Math.max(shape.r0 || 0, 0); + var r = Math.max(shape.r, 0); + var startAngle = shape.startAngle; + var endAngle = shape.endAngle; + var clockwise = shape.clockwise; + + var unitX = Math.cos(startAngle); + var unitY = Math.sin(startAngle); + + ctx.moveTo(unitX * r0 + x, unitY * r0 + y); + + ctx.lineTo(unitX * r + x, unitY * r + y); + + ctx.arc(x, y, r, startAngle, endAngle, !clockwise); + + ctx.lineTo( + Math.cos(endAngle) * r0 + x, + Math.sin(endAngle) * r0 + y + ); + + if (r0 !== 0) { + ctx.arc(x, y, r0, endAngle, startAngle, clockwise); + } + + ctx.closePath(); + } +}); + +/** + * 圆环 + * @module zrender/graphic/shape/Ring + */ + +var Ring = Path.extend({ + + type: 'ring', + + shape: { + cx: 0, + cy: 0, + r: 0, + r0: 0 + }, + + buildPath: function (ctx, shape) { + var x = shape.cx; + var y = shape.cy; + var PI2 = Math.PI * 2; + ctx.moveTo(x + shape.r, y); + ctx.arc(x, y, shape.r, 0, PI2, false); + ctx.moveTo(x + shape.r0, y); + ctx.arc(x, y, shape.r0, 0, PI2, true); + } +}); + +/** + * Catmull-Rom spline 插值折线 + * @module zrender/shape/util/smoothSpline + * @author pissang (https://www.github.com/pissang) + * Kener (@Kener-林峰, kener.linfeng@gmail.com) + * errorrik (errorrik@gmail.com) + */ + +/** + * @inner + */ +function interpolate(p0, p1, p2, p3, t, t2, t3) { + var v0 = (p2 - p0) * 0.5; + var v1 = (p3 - p1) * 0.5; + return (2 * (p1 - p2) + v0 + v1) * t3 + + (-3 * (p1 - p2) - 2 * v0 - v1) * t2 + + v0 * t + p1; +} + +/** + * @alias module:zrender/shape/util/smoothSpline + * @param {Array} points 线段顶点数组 + * @param {boolean} isLoop + * @return {Array} + */ +var smoothSpline = function (points, isLoop) { + var len$$1 = points.length; + var ret = []; + + var distance$$1 = 0; + for (var i = 1; i < len$$1; i++) { + distance$$1 += distance(points[i - 1], points[i]); + } + + var segs = distance$$1 / 2; + segs = segs < len$$1 ? len$$1 : segs; + for (var i = 0; i < segs; i++) { + var pos = i / (segs - 1) * (isLoop ? len$$1 : len$$1 - 1); + var idx = Math.floor(pos); + + var w = pos - idx; + + var p0; + var p1 = points[idx % len$$1]; + var p2; + var p3; + if (!isLoop) { + p0 = points[idx === 0 ? idx : idx - 1]; + p2 = points[idx > len$$1 - 2 ? len$$1 - 1 : idx + 1]; + p3 = points[idx > len$$1 - 3 ? len$$1 - 1 : idx + 2]; + } + else { + p0 = points[(idx - 1 + len$$1) % len$$1]; + p2 = points[(idx + 1) % len$$1]; + p3 = points[(idx + 2) % len$$1]; + } + + var w2 = w * w; + var w3 = w * w2; + + ret.push([ + interpolate(p0[0], p1[0], p2[0], p3[0], w, w2, w3), + interpolate(p0[1], p1[1], p2[1], p3[1], w, w2, w3) + ]); + } + return ret; +}; + +/** + * 贝塞尔平滑曲线 + * @module zrender/shape/util/smoothBezier + * @author pissang (https://www.github.com/pissang) + * Kener (@Kener-林峰, kener.linfeng@gmail.com) + * errorrik (errorrik@gmail.com) + */ + +/** + * 贝塞尔平滑曲线 + * @alias module:zrender/shape/util/smoothBezier + * @param {Array} points 线段顶点数组 + * @param {number} smooth 平滑等级, 0-1 + * @param {boolean} isLoop + * @param {Array} constraint 将计算出来的控制点约束在一个包围盒内 + * 比如 [[0, 0], [100, 100]], 这个包围盒会与 + * 整个折线的包围盒做一个并集用来约束控制点。 + * @param {Array} 计算出来的控制点数组 + */ +var smoothBezier = function (points, smooth, isLoop, constraint) { + var cps = []; + + var v = []; + var v1 = []; + var v2 = []; + var prevPoint; + var nextPoint; + + var min$$1; + var max$$1; + if (constraint) { + min$$1 = [Infinity, Infinity]; + max$$1 = [-Infinity, -Infinity]; + for (var i = 0, len$$1 = points.length; i < len$$1; i++) { + min(min$$1, min$$1, points[i]); + max(max$$1, max$$1, points[i]); + } + // 与指定的包围盒做并集 + min(min$$1, min$$1, constraint[0]); + max(max$$1, max$$1, constraint[1]); + } + + for (var i = 0, len$$1 = points.length; i < len$$1; i++) { + var point = points[i]; + + if (isLoop) { + prevPoint = points[i ? i - 1 : len$$1 - 1]; + nextPoint = points[(i + 1) % len$$1]; + } + else { + if (i === 0 || i === len$$1 - 1) { + cps.push(clone$1(points[i])); + continue; + } + else { + prevPoint = points[i - 1]; + nextPoint = points[i + 1]; + } + } + + sub(v, nextPoint, prevPoint); + + // use degree to scale the handle length + scale(v, v, smooth); + + var d0 = distance(point, prevPoint); + var d1 = distance(point, nextPoint); + var sum = d0 + d1; + if (sum !== 0) { + d0 /= sum; + d1 /= sum; + } + + scale(v1, v, -d0); + scale(v2, v, d1); + var cp0 = add([], point, v1); + var cp1 = add([], point, v2); + if (constraint) { + max(cp0, cp0, min$$1); + min(cp0, cp0, max$$1); + max(cp1, cp1, min$$1); + min(cp1, cp1, max$$1); + } + cps.push(cp0); + cps.push(cp1); + } + + if (isLoop) { + cps.push(cps.shift()); + } + + return cps; +}; + +function buildPath$1(ctx, shape, closePath) { + var points = shape.points; + var smooth = shape.smooth; + if (points && points.length >= 2) { + if (smooth && smooth !== 'spline') { + var controlPoints = smoothBezier( + points, smooth, closePath, shape.smoothConstraint + ); + + ctx.moveTo(points[0][0], points[0][1]); + var len = points.length; + for (var i = 0; i < (closePath ? len : len - 1); i++) { + var cp1 = controlPoints[i * 2]; + var cp2 = controlPoints[i * 2 + 1]; + var p = points[(i + 1) % len]; + ctx.bezierCurveTo( + cp1[0], cp1[1], cp2[0], cp2[1], p[0], p[1] + ); + } + } + else { + if (smooth === 'spline') { + points = smoothSpline(points, closePath); + } + + ctx.moveTo(points[0][0], points[0][1]); + for (var i = 1, l = points.length; i < l; i++) { + ctx.lineTo(points[i][0], points[i][1]); + } + } + + closePath && ctx.closePath(); + } +} + +/** + * 多边形 + * @module zrender/shape/Polygon + */ + +var Polygon = Path.extend({ + + type: 'polygon', + + shape: { + points: null, + + smooth: false, + + smoothConstraint: null + }, + + buildPath: function (ctx, shape) { + buildPath$1(ctx, shape, true); + } +}); + +/** + * @module zrender/graphic/shape/Polyline + */ + +var Polyline = Path.extend({ + + type: 'polyline', + + shape: { + points: null, + + smooth: false, + + smoothConstraint: null + }, + + style: { + stroke: '#000', + + fill: null + }, + + buildPath: function (ctx, shape) { + buildPath$1(ctx, shape, false); + } +}); + +/** + * Sub-pixel optimize for canvas rendering, prevent from blur + * when rendering a thin vertical/horizontal line. + */ + +var round$1 = Math.round; + +/** + * Sub pixel optimize line for canvas + * + * @param {Object} outputShape The modification will be performed on `outputShape`. + * `outputShape` and `inputShape` can be the same object. + * `outputShape` object can be used repeatly, because all of + * the `x1`, `x2`, `y1`, `y2` will be assigned in this method. + * @param {Object} [inputShape] + * @param {number} [inputShape.x1] + * @param {number} [inputShape.y1] + * @param {number} [inputShape.x2] + * @param {number} [inputShape.y2] + * @param {Object} [style] + * @param {number} [style.lineWidth] + */ +function subPixelOptimizeLine$1(outputShape, inputShape, style) { + var lineWidth = style && style.lineWidth; + + if (!inputShape || !lineWidth) { + return; + } + + var x1 = inputShape.x1; + var x2 = inputShape.x2; + var y1 = inputShape.y1; + var y2 = inputShape.y2; + + if (round$1(x1 * 2) === round$1(x2 * 2)) { + outputShape.x1 = outputShape.x2 = subPixelOptimize$1(x1, lineWidth, true); + } + else { + outputShape.x1 = x1; + outputShape.x2 = x2; + } + if (round$1(y1 * 2) === round$1(y2 * 2)) { + outputShape.y1 = outputShape.y2 = subPixelOptimize$1(y1, lineWidth, true); + } + else { + outputShape.y1 = y1; + outputShape.y2 = y2; + } +} + +/** + * Sub pixel optimize rect for canvas + * + * @param {Object} outputShape The modification will be performed on `outputShape`. + * `outputShape` and `inputShape` can be the same object. + * `outputShape` object can be used repeatly, because all of + * the `x`, `y`, `width`, `height` will be assigned in this method. + * @param {Object} [inputShape] + * @param {number} [inputShape.x] + * @param {number} [inputShape.y] + * @param {number} [inputShape.width] + * @param {number} [inputShape.height] + * @param {Object} [style] + * @param {number} [style.lineWidth] + */ +function subPixelOptimizeRect$1(outputShape, inputShape, style) { + var lineWidth = style && style.lineWidth; + + if (!inputShape || !lineWidth) { + return; + } + + var originX = inputShape.x; + var originY = inputShape.y; + var originWidth = inputShape.width; + var originHeight = inputShape.height; + + outputShape.x = subPixelOptimize$1(originX, lineWidth, true); + outputShape.y = subPixelOptimize$1(originY, lineWidth, true); + outputShape.width = Math.max( + subPixelOptimize$1(originX + originWidth, lineWidth, false) - outputShape.x, + originWidth === 0 ? 0 : 1 + ); + outputShape.height = Math.max( + subPixelOptimize$1(originY + originHeight, lineWidth, false) - outputShape.y, + originHeight === 0 ? 0 : 1 + ); +} + +/** + * Sub pixel optimize for canvas + * + * @param {number} position Coordinate, such as x, y + * @param {number} lineWidth Should be nonnegative integer. + * @param {boolean=} positiveOrNegative Default false (negative). + * @return {number} Optimized position. + */ +function subPixelOptimize$1(position, lineWidth, positiveOrNegative) { + // Assure that (position + lineWidth / 2) is near integer edge, + // otherwise line will be fuzzy in canvas. + var doubledPosition = round$1(position * 2); + return (doubledPosition + round$1(lineWidth)) % 2 === 0 + ? doubledPosition / 2 + : (doubledPosition + (positiveOrNegative ? 1 : -1)) / 2; +} + +/** + * 矩形 + * @module zrender/graphic/shape/Rect + */ + +// Avoid create repeatly. +var subPixelOptimizeOutputShape = {}; + +var Rect = Path.extend({ + + type: 'rect', + + shape: { + // 左上、右上、右下、左下角的半径依次为r1、r2、r3、r4 + // r缩写为1 相当于 [1, 1, 1, 1] + // r缩写为[1] 相当于 [1, 1, 1, 1] + // r缩写为[1, 2] 相当于 [1, 2, 1, 2] + // r缩写为[1, 2, 3] 相当于 [1, 2, 3, 2] + r: 0, + + x: 0, + y: 0, + width: 0, + height: 0 + }, + + buildPath: function (ctx, shape) { + var x; + var y; + var width; + var height; + + if (this.subPixelOptimize) { + subPixelOptimizeRect$1(subPixelOptimizeOutputShape, shape, this.style); + x = subPixelOptimizeOutputShape.x; + y = subPixelOptimizeOutputShape.y; + width = subPixelOptimizeOutputShape.width; + height = subPixelOptimizeOutputShape.height; + subPixelOptimizeOutputShape.r = shape.r; + shape = subPixelOptimizeOutputShape; + } + else { + x = shape.x; + y = shape.y; + width = shape.width; + height = shape.height; + } + + if (!shape.r) { + ctx.rect(x, y, width, height); + } + else { + buildPath(ctx, shape); + } + ctx.closePath(); + return; + } +}); + +/** + * 直线 + * @module zrender/graphic/shape/Line + */ + +// Avoid create repeatly. +var subPixelOptimizeOutputShape$1 = {}; + +var Line = Path.extend({ + + type: 'line', + + shape: { + // Start point + x1: 0, + y1: 0, + // End point + x2: 0, + y2: 0, + + percent: 1 + }, + + style: { + stroke: '#000', + fill: null + }, + + buildPath: function (ctx, shape) { + var x1; + var y1; + var x2; + var y2; + + if (this.subPixelOptimize) { + subPixelOptimizeLine$1(subPixelOptimizeOutputShape$1, shape, this.style); + x1 = subPixelOptimizeOutputShape$1.x1; + y1 = subPixelOptimizeOutputShape$1.y1; + x2 = subPixelOptimizeOutputShape$1.x2; + y2 = subPixelOptimizeOutputShape$1.y2; + } + else { + x1 = shape.x1; + y1 = shape.y1; + x2 = shape.x2; + y2 = shape.y2; + } + + var percent = shape.percent; + + if (percent === 0) { + return; + } + + ctx.moveTo(x1, y1); + + if (percent < 1) { + x2 = x1 * (1 - percent) + x2 * percent; + y2 = y1 * (1 - percent) + y2 * percent; + } + ctx.lineTo(x2, y2); + }, + + /** + * Get point at percent + * @param {number} percent + * @return {Array.} + */ + pointAt: function (p) { + var shape = this.shape; + return [ + shape.x1 * (1 - p) + shape.x2 * p, + shape.y1 * (1 - p) + shape.y2 * p + ]; + } +}); + +/** + * 贝塞尔曲线 + * @module zrender/shape/BezierCurve + */ + +var out = []; + +function someVectorAt(shape, t, isTangent) { + var cpx2 = shape.cpx2; + var cpy2 = shape.cpy2; + if (cpx2 === null || cpy2 === null) { + return [ + (isTangent ? cubicDerivativeAt : cubicAt)(shape.x1, shape.cpx1, shape.cpx2, shape.x2, t), + (isTangent ? cubicDerivativeAt : cubicAt)(shape.y1, shape.cpy1, shape.cpy2, shape.y2, t) + ]; + } + else { + return [ + (isTangent ? quadraticDerivativeAt : quadraticAt)(shape.x1, shape.cpx1, shape.x2, t), + (isTangent ? quadraticDerivativeAt : quadraticAt)(shape.y1, shape.cpy1, shape.y2, t) + ]; + } +} + +var BezierCurve = Path.extend({ + + type: 'bezier-curve', + + shape: { + x1: 0, + y1: 0, + x2: 0, + y2: 0, + cpx1: 0, + cpy1: 0, + // cpx2: 0, + // cpy2: 0 + + // Curve show percent, for animating + percent: 1 + }, + + style: { + stroke: '#000', + fill: null + }, + + buildPath: function (ctx, shape) { + var x1 = shape.x1; + var y1 = shape.y1; + var x2 = shape.x2; + var y2 = shape.y2; + var cpx1 = shape.cpx1; + var cpy1 = shape.cpy1; + var cpx2 = shape.cpx2; + var cpy2 = shape.cpy2; + var percent = shape.percent; + if (percent === 0) { + return; + } + + ctx.moveTo(x1, y1); + + if (cpx2 == null || cpy2 == null) { + if (percent < 1) { + quadraticSubdivide( + x1, cpx1, x2, percent, out + ); + cpx1 = out[1]; + x2 = out[2]; + quadraticSubdivide( + y1, cpy1, y2, percent, out + ); + cpy1 = out[1]; + y2 = out[2]; + } + + ctx.quadraticCurveTo( + cpx1, cpy1, + x2, y2 + ); + } + else { + if (percent < 1) { + cubicSubdivide( + x1, cpx1, cpx2, x2, percent, out + ); + cpx1 = out[1]; + cpx2 = out[2]; + x2 = out[3]; + cubicSubdivide( + y1, cpy1, cpy2, y2, percent, out + ); + cpy1 = out[1]; + cpy2 = out[2]; + y2 = out[3]; + } + ctx.bezierCurveTo( + cpx1, cpy1, + cpx2, cpy2, + x2, y2 + ); + } + }, + + /** + * Get point at percent + * @param {number} t + * @return {Array.} + */ + pointAt: function (t) { + return someVectorAt(this.shape, t, false); + }, + + /** + * Get tangent at percent + * @param {number} t + * @return {Array.} + */ + tangentAt: function (t) { + var p = someVectorAt(this.shape, t, true); + return normalize(p, p); + } +}); + +/** + * 圆弧 + * @module zrender/graphic/shape/Arc + */ + +var Arc = Path.extend({ + + type: 'arc', + + shape: { + + cx: 0, + + cy: 0, + + r: 0, + + startAngle: 0, + + endAngle: Math.PI * 2, + + clockwise: true + }, + + style: { + + stroke: '#000', + + fill: null + }, + + buildPath: function (ctx, shape) { + + var x = shape.cx; + var y = shape.cy; + var r = Math.max(shape.r, 0); + var startAngle = shape.startAngle; + var endAngle = shape.endAngle; + var clockwise = shape.clockwise; + + var unitX = Math.cos(startAngle); + var unitY = Math.sin(startAngle); + + ctx.moveTo(unitX * r + x, unitY * r + y); + ctx.arc(x, y, r, startAngle, endAngle, !clockwise); + } +}); + +// CompoundPath to improve performance + +var CompoundPath = Path.extend({ + + type: 'compound', + + shape: { + + paths: null + }, + + _updatePathDirty: function () { + var dirtyPath = this.__dirtyPath; + var paths = this.shape.paths; + for (var i = 0; i < paths.length; i++) { + // Mark as dirty if any subpath is dirty + dirtyPath = dirtyPath || paths[i].__dirtyPath; + } + this.__dirtyPath = dirtyPath; + this.__dirty = this.__dirty || dirtyPath; + }, + + beforeBrush: function () { + this._updatePathDirty(); + var paths = this.shape.paths || []; + var scale = this.getGlobalScale(); + // Update path scale + for (var i = 0; i < paths.length; i++) { + if (!paths[i].path) { + paths[i].createPathProxy(); + } + paths[i].path.setScale(scale[0], scale[1]); + } + }, + + buildPath: function (ctx, shape) { + var paths = shape.paths || []; + for (var i = 0; i < paths.length; i++) { + paths[i].buildPath(ctx, paths[i].shape, true); + } + }, + + afterBrush: function () { + var paths = this.shape.paths || []; + for (var i = 0; i < paths.length; i++) { + paths[i].__dirtyPath = false; + } + }, + + getBoundingRect: function () { + this._updatePathDirty(); + return Path.prototype.getBoundingRect.call(this); + } +}); + +/** + * @param {Array.} colorStops + */ +var Gradient = function (colorStops) { + + this.colorStops = colorStops || []; + +}; + +Gradient.prototype = { + + constructor: Gradient, + + addColorStop: function (offset, color) { + this.colorStops.push({ + + offset: offset, + + color: color + }); + } + +}; + +/** + * x, y, x2, y2 are all percent from 0 to 1 + * @param {number} [x=0] + * @param {number} [y=0] + * @param {number} [x2=1] + * @param {number} [y2=0] + * @param {Array.} colorStops + * @param {boolean} [globalCoord=false] + */ +var LinearGradient = function (x, y, x2, y2, colorStops, globalCoord) { + // Should do nothing more in this constructor. Because gradient can be + // declard by `color: {type: 'linear', colorStops: ...}`, where + // this constructor will not be called. + + this.x = x == null ? 0 : x; + + this.y = y == null ? 0 : y; + + this.x2 = x2 == null ? 1 : x2; + + this.y2 = y2 == null ? 0 : y2; + + // Can be cloned + this.type = 'linear'; + + // If use global coord + this.global = globalCoord || false; + + Gradient.call(this, colorStops); +}; + +LinearGradient.prototype = { + + constructor: LinearGradient +}; + +inherits(LinearGradient, Gradient); + +/** + * x, y, r are all percent from 0 to 1 + * @param {number} [x=0.5] + * @param {number} [y=0.5] + * @param {number} [r=0.5] + * @param {Array.} [colorStops] + * @param {boolean} [globalCoord=false] + */ +var RadialGradient = function (x, y, r, colorStops, globalCoord) { + // Should do nothing more in this constructor. Because gradient can be + // declard by `color: {type: 'radial', colorStops: ...}`, where + // this constructor will not be called. + + this.x = x == null ? 0.5 : x; + + this.y = y == null ? 0.5 : y; + + this.r = r == null ? 0.5 : r; + + // Can be cloned + this.type = 'radial'; + + // If use global coord + this.global = globalCoord || false; + + Gradient.call(this, colorStops); +}; + +RadialGradient.prototype = { + + constructor: RadialGradient +}; + +inherits(RadialGradient, Gradient); + +/** + * Displayable for incremental rendering. It will be rendered in a separate layer + * IncrementalDisplay have two main methods. `clearDisplayables` and `addDisplayables` + * addDisplayables will render the added displayables incremetally. + * + * It use a not clearFlag to tell the painter don't clear the layer if it's the first element. + */ +// TODO Style override ? +function IncrementalDisplayble(opts) { + + Displayable.call(this, opts); + + this._displayables = []; + + this._temporaryDisplayables = []; + + this._cursor = 0; + + this.notClear = true; +} + +IncrementalDisplayble.prototype.incremental = true; + +IncrementalDisplayble.prototype.clearDisplaybles = function () { + this._displayables = []; + this._temporaryDisplayables = []; + this._cursor = 0; + this.dirty(); + + this.notClear = false; +}; + +IncrementalDisplayble.prototype.addDisplayable = function (displayable, notPersistent) { + if (notPersistent) { + this._temporaryDisplayables.push(displayable); + } + else { + this._displayables.push(displayable); + } + this.dirty(); +}; + +IncrementalDisplayble.prototype.addDisplayables = function (displayables, notPersistent) { + notPersistent = notPersistent || false; + for (var i = 0; i < displayables.length; i++) { + this.addDisplayable(displayables[i], notPersistent); + } +}; + +IncrementalDisplayble.prototype.eachPendingDisplayable = function (cb) { + for (var i = this._cursor; i < this._displayables.length; i++) { + cb && cb(this._displayables[i]); + } + for (var i = 0; i < this._temporaryDisplayables.length; i++) { + cb && cb(this._temporaryDisplayables[i]); + } +}; + +IncrementalDisplayble.prototype.update = function () { + this.updateTransform(); + for (var i = this._cursor; i < this._displayables.length; i++) { + var displayable = this._displayables[i]; + // PENDING + displayable.parent = this; + displayable.update(); + displayable.parent = null; + } + for (var i = 0; i < this._temporaryDisplayables.length; i++) { + var displayable = this._temporaryDisplayables[i]; + // PENDING + displayable.parent = this; + displayable.update(); + displayable.parent = null; + } +}; + +IncrementalDisplayble.prototype.brush = function (ctx, prevEl) { + // Render persistant displayables. + for (var i = this._cursor; i < this._displayables.length; i++) { + var displayable = this._displayables[i]; + displayable.beforeBrush && displayable.beforeBrush(ctx); + displayable.brush(ctx, i === this._cursor ? null : this._displayables[i - 1]); + displayable.afterBrush && displayable.afterBrush(ctx); + } + this._cursor = i; + // Render temporary displayables. + for (var i = 0; i < this._temporaryDisplayables.length; i++) { + var displayable = this._temporaryDisplayables[i]; + displayable.beforeBrush && displayable.beforeBrush(ctx); + displayable.brush(ctx, i === 0 ? null : this._temporaryDisplayables[i - 1]); + displayable.afterBrush && displayable.afterBrush(ctx); + } + + this._temporaryDisplayables = []; + + this.notClear = true; +}; + +var m = []; +IncrementalDisplayble.prototype.getBoundingRect = function () { + if (!this._rect) { + var rect = new BoundingRect(Infinity, Infinity, -Infinity, -Infinity); + for (var i = 0; i < this._displayables.length; i++) { + var displayable = this._displayables[i]; + var childRect = displayable.getBoundingRect().clone(); + if (displayable.needLocalTransform()) { + childRect.applyTransform(displayable.getLocalTransform(m)); + } + rect.union(childRect); + } + this._rect = rect; + } + return this._rect; +}; + +IncrementalDisplayble.prototype.contain = function (x, y) { + var localPos = this.transformCoordToLocal(x, y); + var rect = this.getBoundingRect(); + + if (rect.contain(localPos[0], localPos[1])) { + for (var i = 0; i < this._displayables.length; i++) { + var displayable = this._displayables[i]; + if (displayable.contain(x, y)) { + return true; + } + } + } + return false; +}; + +inherits(IncrementalDisplayble, Displayable); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var round = Math.round; +var mathMax$1 = Math.max; +var mathMin$1 = Math.min; + +var EMPTY_OBJ = {}; + +var Z2_EMPHASIS_LIFT = 1; + +/** + * Extend shape with parameters + */ +function extendShape(opts) { + return Path.extend(opts); +} + +/** + * Extend path + */ +function extendPath(pathData, opts) { + return extendFromString(pathData, opts); +} + +/** + * Create a path element from path data string + * @param {string} pathData + * @param {Object} opts + * @param {module:zrender/core/BoundingRect} rect + * @param {string} [layout=cover] 'center' or 'cover' + */ +function makePath(pathData, opts, rect, layout) { + var path = createFromString(pathData, opts); + if (rect) { + if (layout === 'center') { + rect = centerGraphic(rect, path.getBoundingRect()); + } + resizePath(path, rect); + } + return path; +} + +/** + * Create a image element from image url + * @param {string} imageUrl image url + * @param {Object} opts options + * @param {module:zrender/core/BoundingRect} rect constrain rect + * @param {string} [layout=cover] 'center' or 'cover' + */ +function makeImage(imageUrl, rect, layout) { + var path = new ZImage({ + style: { + image: imageUrl, + x: rect.x, + y: rect.y, + width: rect.width, + height: rect.height + }, + onload: function (img) { + if (layout === 'center') { + var boundingRect = { + width: img.width, + height: img.height + }; + path.setStyle(centerGraphic(rect, boundingRect)); + } + } + }); + return path; +} + +/** + * Get position of centered element in bounding box. + * + * @param {Object} rect element local bounding box + * @param {Object} boundingRect constraint bounding box + * @return {Object} element position containing x, y, width, and height + */ +function centerGraphic(rect, boundingRect) { + // Set rect to center, keep width / height ratio. + var aspect = boundingRect.width / boundingRect.height; + var width = rect.height * aspect; + var height; + if (width <= rect.width) { + height = rect.height; + } + else { + width = rect.width; + height = width / aspect; + } + var cx = rect.x + rect.width / 2; + var cy = rect.y + rect.height / 2; + + return { + x: cx - width / 2, + y: cy - height / 2, + width: width, + height: height + }; +} + +var mergePath = mergePath$1; + +/** + * Resize a path to fit the rect + * @param {module:zrender/graphic/Path} path + * @param {Object} rect + */ +function resizePath(path, rect) { + if (!path.applyTransform) { + return; + } + + var pathRect = path.getBoundingRect(); + + var m = pathRect.calculateTransform(rect); + + path.applyTransform(m); +} + +/** + * Sub pixel optimize line for canvas + * + * @param {Object} param + * @param {Object} [param.shape] + * @param {number} [param.shape.x1] + * @param {number} [param.shape.y1] + * @param {number} [param.shape.x2] + * @param {number} [param.shape.y2] + * @param {Object} [param.style] + * @param {number} [param.style.lineWidth] + * @return {Object} Modified param + */ +function subPixelOptimizeLine(param) { + var shape = param.shape; + var lineWidth = param.style.lineWidth; + + if (round(shape.x1 * 2) === round(shape.x2 * 2)) { + shape.x1 = shape.x2 = subPixelOptimize(shape.x1, lineWidth, true); + } + if (round(shape.y1 * 2) === round(shape.y2 * 2)) { + shape.y1 = shape.y2 = subPixelOptimize(shape.y1, lineWidth, true); + } + return param; +} + +/** + * Sub pixel optimize rect for canvas + * + * @param {Object} param + * @param {Object} [param.shape] + * @param {number} [param.shape.x] + * @param {number} [param.shape.y] + * @param {number} [param.shape.width] + * @param {number} [param.shape.height] + * @param {Object} [param.style] + * @param {number} [param.style.lineWidth] + * @return {Object} Modified param + */ +function subPixelOptimizeRect(param) { + var shape = param.shape; + var lineWidth = param.style.lineWidth; + var originX = shape.x; + var originY = shape.y; + var originWidth = shape.width; + var originHeight = shape.height; + shape.x = subPixelOptimize(shape.x, lineWidth, true); + shape.y = subPixelOptimize(shape.y, lineWidth, true); + shape.width = Math.max( + subPixelOptimize(originX + originWidth, lineWidth, false) - shape.x, + originWidth === 0 ? 0 : 1 + ); + shape.height = Math.max( + subPixelOptimize(originY + originHeight, lineWidth, false) - shape.y, + originHeight === 0 ? 0 : 1 + ); + return param; +} + +/** + * Sub pixel optimize for canvas + * + * @param {number} position Coordinate, such as x, y + * @param {number} lineWidth Should be nonnegative integer. + * @param {boolean=} positiveOrNegative Default false (negative). + * @return {number} Optimized position. + */ +function subPixelOptimize(position, lineWidth, positiveOrNegative) { + // Assure that (position + lineWidth / 2) is near integer edge, + // otherwise line will be fuzzy in canvas. + var doubledPosition = round(position * 2); + return (doubledPosition + round(lineWidth)) % 2 === 0 + ? doubledPosition / 2 + : (doubledPosition + (positiveOrNegative ? 1 : -1)) / 2; +} + +function hasFillOrStroke(fillOrStroke) { + return fillOrStroke != null && fillOrStroke !== 'none'; +} + +// Most lifted color are duplicated. +var liftedColorMap = createHashMap(); +var liftedColorCount = 0; + +function liftColor(color) { + if (typeof color !== 'string') { + return color; + } + var liftedColor = liftedColorMap.get(color); + if (!liftedColor) { + liftedColor = lift(color, -0.1); + if (liftedColorCount < 10000) { + liftedColorMap.set(color, liftedColor); + liftedColorCount++; + } + } + return liftedColor; +} + +function cacheElementStl(el) { + if (!el.__hoverStlDirty) { + return; + } + el.__hoverStlDirty = false; + + var hoverStyle = el.__hoverStl; + if (!hoverStyle) { + el.__cachedNormalStl = el.__cachedNormalZ2 = null; + return; + } + + var normalStyle = el.__cachedNormalStl = {}; + el.__cachedNormalZ2 = el.z2; + var elStyle = el.style; + + for (var name in hoverStyle) { + // See comment in `doSingleEnterHover`. + if (hoverStyle[name] != null) { + normalStyle[name] = elStyle[name]; + } + } + + // Always cache fill and stroke to normalStyle for lifting color. + normalStyle.fill = elStyle.fill; + normalStyle.stroke = elStyle.stroke; +} + +function doSingleEnterHover(el) { + var hoverStl = el.__hoverStl; + + if (!hoverStl || el.__highlighted) { + return; + } + + var useHoverLayer = el.useHoverLayer; + el.__highlighted = useHoverLayer ? 'layer' : 'plain'; + + var zr = el.__zr; + if (!zr && useHoverLayer) { + return; + } + + var elTarget = el; + var targetStyle = el.style; + + if (useHoverLayer) { + elTarget = zr.addHover(el); + targetStyle = elTarget.style; + } + + rollbackDefaultTextStyle(targetStyle); + + if (!useHoverLayer) { + cacheElementStl(elTarget); + } + + // styles can be: + // { + // label: { + // show: false, + // position: 'outside', + // fontSize: 18 + // }, + // emphasis: { + // label: { + // show: true + // } + // } + // }, + // where properties of `emphasis` may not appear in `normal`. We previously use + // module:echarts/util/model#defaultEmphasis to merge `normal` to `emphasis`. + // But consider rich text and setOption in merge mode, it is impossible to cover + // all properties in merge. So we use merge mode when setting style here, where + // only properties that is not `null/undefined` can be set. The disadventage: + // null/undefined can not be used to remove style any more in `emphasis`. + targetStyle.extendFrom(hoverStl); + + setDefaultHoverFillStroke(targetStyle, hoverStl, 'fill'); + setDefaultHoverFillStroke(targetStyle, hoverStl, 'stroke'); + + applyDefaultTextStyle(targetStyle); + + if (!useHoverLayer) { + el.dirty(false); + el.z2 += Z2_EMPHASIS_LIFT; + } +} + +function setDefaultHoverFillStroke(targetStyle, hoverStyle, prop) { + if (!hasFillOrStroke(hoverStyle[prop]) && hasFillOrStroke(targetStyle[prop])) { + targetStyle[prop] = liftColor(targetStyle[prop]); + } +} + +function doSingleLeaveHover(el) { + var highlighted = el.__highlighted; + + if (!highlighted) { + return; + } + + el.__highlighted = false; + + if (highlighted === 'layer') { + el.__zr && el.__zr.removeHover(el); + } + else if (highlighted) { + var style = el.style; + + var normalStl = el.__cachedNormalStl; + if (normalStl) { + rollbackDefaultTextStyle(style); + // Consider null/undefined value, should use + // `setStyle` but not `extendFrom(stl, true)`. + el.setStyle(normalStl); + applyDefaultTextStyle(style); + } + // `__cachedNormalZ2` will not be reset if calling `setElementHoverStyle` + // when `el` is on emphasis state. So here by comparing with 1, we try + // hard to make the bug case rare. + var normalZ2 = el.__cachedNormalZ2; + if (normalZ2 != null && el.z2 - normalZ2 === Z2_EMPHASIS_LIFT) { + el.z2 = normalZ2; + } + } +} + +function traverseCall(el, method) { + el.isGroup + ? el.traverse(function (child) { + !child.isGroup && method(child); + }) + : method(el); +} + +/** + * Set hover style (namely "emphasis style") of element, based on the current + * style of the given `el`. + * This method should be called after all of the normal styles have been adopted + * to the `el`. See the reason on `setHoverStyle`. + * + * @param {module:zrender/Element} el Should not be `zrender/container/Group`. + * @param {Object|boolean} [hoverStl] The specified hover style. + * If set as `false`, disable the hover style. + * Similarly, The `el.hoverStyle` can alse be set + * as `false` to disable the hover style. + * Otherwise, use the default hover style if not provided. + * @param {Object} [opt] + * @param {boolean} [opt.hoverSilentOnTouch=false] See `graphic.setAsHoverStyleTrigger` + */ +function setElementHoverStyle(el, hoverStl) { + // For performance consideration, it might be better to make the "hover style" only the + // difference properties from the "normal style", but not a entire copy of all styles. + hoverStl = el.__hoverStl = hoverStl !== false && (hoverStl || {}); + el.__hoverStlDirty = true; + + // FIXME + // It is not completely right to save "normal"/"emphasis" flag on elements. + // It probably should be saved on `data` of series. Consider the cases: + // (1) A highlighted elements are moved out of the view port and re-enter + // again by dataZoom. + // (2) call `setOption` and replace elements totally when they are highlighted. + if (el.__highlighted) { + // Consider the case: + // The styles of a highlighted `el` is being updated. The new "emphasis style" + // should be adapted to the `el`. Notice here new "normal styles" should have + // been set outside and the cached "normal style" is out of date. + el.__cachedNormalStl = null; + // Do not clear `__cachedNormalZ2` here, because setting `z2` is not a constraint + // of this method. In most cases, `z2` is not set and hover style should be able + // to rollback. Of course, that would bring bug, but only in a rare case, see + // `doSingleLeaveHover` for details. + doSingleLeaveHover(el); + + doSingleEnterHover(el); + } +} + +/** + * Emphasis (called by API) has higher priority than `mouseover`. + * When element has been called to be entered emphasis, mouse over + * should not trigger the highlight effect (for example, animation + * scale) again, and `mouseout` should not downplay the highlight + * effect. So the listener of `mouseover` and `mouseout` should + * check `isInEmphasis`. + * + * @param {module:zrender/Element} el + * @return {boolean} + */ +function isInEmphasis(el) { + return el && el.__isEmphasisEntered; +} + +function onElementMouseOver(e) { + if (this.__hoverSilentOnTouch && e.zrByTouch) { + return; + } + + // Only if element is not in emphasis status + !this.__isEmphasisEntered && traverseCall(this, doSingleEnterHover); +} + +function onElementMouseOut(e) { + if (this.__hoverSilentOnTouch && e.zrByTouch) { + return; + } + + // Only if element is not in emphasis status + !this.__isEmphasisEntered && traverseCall(this, doSingleLeaveHover); +} + +function enterEmphasis() { + this.__isEmphasisEntered = true; + traverseCall(this, doSingleEnterHover); +} + +function leaveEmphasis() { + this.__isEmphasisEntered = false; + traverseCall(this, doSingleLeaveHover); +} + +/** + * Set hover style (namely "emphasis style") of element, + * based on the current style of the given `el`. + * + * (1) + * **CONSTRAINTS** for this method: + * This method MUST be called after all of the normal styles having been adopted + * to the `el`. + * The input `hoverStyle` (that is, "emphasis style") MUST be the subset of the + * "normal style" having been set to the el. + * `color` MUST be one of the "normal styles" (because color might be lifted as + * a default hover style). + * + * The reason: this method treat the current style of the `el` as the "normal style" + * and cache them when enter/update the "emphasis style". Consider the case: the `el` + * is in "emphasis" state and `setOption`/`dispatchAction` trigger the style updating + * logic, where the el should shift from the original emphasis style to the new + * "emphasis style" and should be able to "downplay" back to the new "normal style". + * + * Indeed, it is error-prone to make a interface has so many constraints, but I have + * not found a better solution yet to fit the backward compatibility, performance and + * the current programming style. + * + * (2) + * Call the method for a "root" element once. Do not call it for each descendants. + * If the descendants elemenets of a group has itself hover style different from the + * root group, we can simply mount the style on `el.hoverStyle` for them, but should + * not call this method for them. + * + * @param {module:zrender/Element} el + * @param {Object|boolean} [hoverStyle] See `graphic.setElementHoverStyle`. + * @param {Object} [opt] + * @param {boolean} [opt.hoverSilentOnTouch=false] See `graphic.setAsHoverStyleTrigger`. + */ +function setHoverStyle(el, hoverStyle, opt) { + el.isGroup + ? el.traverse(function (child) { + // If element has sepcified hoverStyle, then use it instead of given hoverStyle + // Often used when item group has a label element and it's hoverStyle is different + !child.isGroup && setElementHoverStyle(child, child.hoverStyle || hoverStyle); + }) + : setElementHoverStyle(el, el.hoverStyle || hoverStyle); + + setAsHoverStyleTrigger(el, opt); +} + +/** + * @param {Object|boolean} [opt] If `false`, means disable trigger. + * @param {boolean} [opt.hoverSilentOnTouch=false] + * In touch device, mouseover event will be trigger on touchstart event + * (see module:zrender/dom/HandlerProxy). By this mechanism, we can + * conveniently use hoverStyle when tap on touch screen without additional + * code for compatibility. + * But if the chart/component has select feature, which usually also use + * hoverStyle, there might be conflict between 'select-highlight' and + * 'hover-highlight' especially when roam is enabled (see geo for example). + * In this case, hoverSilentOnTouch should be used to disable hover-highlight + * on touch device. + */ +function setAsHoverStyleTrigger(el, opt) { + var disable = opt === false; + el.__hoverSilentOnTouch = opt != null && opt.hoverSilentOnTouch; + + // Simple optimize, since this method might be + // called for each elements of a group in some cases. + if (!disable || el.__hoverStyleTrigger) { + var method = disable ? 'off' : 'on'; + + // Duplicated function will be auto-ignored, see Eventful.js. + el[method]('mouseover', onElementMouseOver)[method]('mouseout', onElementMouseOut); + // Emphasis, normal can be triggered manually + el[method]('emphasis', enterEmphasis)[method]('normal', leaveEmphasis); + + el.__hoverStyleTrigger = !disable; + } +} + +/** + * See more info in `setTextStyleCommon`. + * @param {Object|module:zrender/graphic/Style} normalStyle + * @param {Object} emphasisStyle + * @param {module:echarts/model/Model} normalModel + * @param {module:echarts/model/Model} emphasisModel + * @param {Object} opt Check `opt` of `setTextStyleCommon` to find other props. + * @param {string|Function} [opt.defaultText] + * @param {module:echarts/model/Model} [opt.labelFetcher] Fetch text by + * `opt.labelFetcher.getFormattedLabel(opt.labelDataIndex, 'normal'/'emphasis', null, opt.labelDimIndex)` + * @param {module:echarts/model/Model} [opt.labelDataIndex] Fetch text by + * `opt.textFetcher.getFormattedLabel(opt.labelDataIndex, 'normal'/'emphasis', null, opt.labelDimIndex)` + * @param {module:echarts/model/Model} [opt.labelDimIndex] Fetch text by + * `opt.textFetcher.getFormattedLabel(opt.labelDataIndex, 'normal'/'emphasis', null, opt.labelDimIndex)` + * @param {Object} [normalSpecified] + * @param {Object} [emphasisSpecified] + */ +function setLabelStyle( + normalStyle, emphasisStyle, + normalModel, emphasisModel, + opt, + normalSpecified, emphasisSpecified +) { + opt = opt || EMPTY_OBJ; + var labelFetcher = opt.labelFetcher; + var labelDataIndex = opt.labelDataIndex; + var labelDimIndex = opt.labelDimIndex; + + // This scenario, `label.normal.show = true; label.emphasis.show = false`, + // is not supported util someone requests. + + var showNormal = normalModel.getShallow('show'); + var showEmphasis = emphasisModel.getShallow('show'); + + // Consider performance, only fetch label when necessary. + // If `normal.show` is `false` and `emphasis.show` is `true` and `emphasis.formatter` is not set, + // label should be displayed, where text is fetched by `normal.formatter` or `opt.defaultText`. + var baseText; + if (showNormal || showEmphasis) { + if (labelFetcher) { + baseText = labelFetcher.getFormattedLabel(labelDataIndex, 'normal', null, labelDimIndex); + } + if (baseText == null) { + baseText = isFunction$1(opt.defaultText) ? opt.defaultText(labelDataIndex, opt) : opt.defaultText; + } + } + var normalStyleText = showNormal ? baseText : null; + var emphasisStyleText = showEmphasis + ? retrieve2( + labelFetcher + ? labelFetcher.getFormattedLabel(labelDataIndex, 'emphasis', null, labelDimIndex) + : null, + baseText + ) + : null; + + // Optimize: If style.text is null, text will not be drawn. + if (normalStyleText != null || emphasisStyleText != null) { + // Always set `textStyle` even if `normalStyle.text` is null, because default + // values have to be set on `normalStyle`. + // If we set default values on `emphasisStyle`, consider case: + // Firstly, `setOption(... label: {normal: {text: null}, emphasis: {show: true}} ...);` + // Secondly, `setOption(... label: {noraml: {show: true, text: 'abc', color: 'red'} ...);` + // Then the 'red' will not work on emphasis. + setTextStyle(normalStyle, normalModel, normalSpecified, opt); + setTextStyle(emphasisStyle, emphasisModel, emphasisSpecified, opt, true); + } + + normalStyle.text = normalStyleText; + emphasisStyle.text = emphasisStyleText; +} + +/** + * Set basic textStyle properties. + * See more info in `setTextStyleCommon`. + * @param {Object|module:zrender/graphic/Style} textStyle + * @param {module:echarts/model/Model} model + * @param {Object} [specifiedTextStyle] Can be overrided by settings in model. + * @param {Object} [opt] See `opt` of `setTextStyleCommon`. + * @param {boolean} [isEmphasis] + */ +function setTextStyle( + textStyle, textStyleModel, specifiedTextStyle, opt, isEmphasis +) { + setTextStyleCommon(textStyle, textStyleModel, opt, isEmphasis); + specifiedTextStyle && extend(textStyle, specifiedTextStyle); + // textStyle.host && textStyle.host.dirty && textStyle.host.dirty(false); + + return textStyle; +} + +/** + * Set text option in the style. + * See more info in `setTextStyleCommon`. + * @deprecated + * @param {Object} textStyle + * @param {module:echarts/model/Model} labelModel + * @param {string|boolean} defaultColor Default text color. + * If set as false, it will be processed as a emphasis style. + */ +function setText(textStyle, labelModel, defaultColor) { + var opt = {isRectText: true}; + var isEmphasis; + + if (defaultColor === false) { + isEmphasis = true; + } + else { + // Support setting color as 'auto' to get visual color. + opt.autoColor = defaultColor; + } + setTextStyleCommon(textStyle, labelModel, opt, isEmphasis); + // textStyle.host && textStyle.host.dirty && textStyle.host.dirty(false); +} + +/** + * The uniform entry of set text style, that is, retrieve style definitions + * from `model` and set to `textStyle` object. + * + * Never in merge mode, but in overwrite mode, that is, all of the text style + * properties will be set. (Consider the states of normal and emphasis and + * default value can be adopted, merge would make the logic too complicated + * to manage.) + * + * The `textStyle` object can either be a plain object or an instance of + * `zrender/src/graphic/Style`, and either be the style of normal or emphasis. + * After this mothod called, the `textStyle` object can then be used in + * `el.setStyle(textStyle)` or `el.hoverStyle = textStyle`. + * + * Default value will be adopted and `insideRollbackOpt` will be created. + * See `applyDefaultTextStyle` `rollbackDefaultTextStyle` for more details. + * + * opt: { + * disableBox: boolean, Whether diable drawing box of block (outer most). + * isRectText: boolean, + * autoColor: string, specify a color when color is 'auto', + * for textFill, textStroke, textBackgroundColor, and textBorderColor. + * If autoColor specified, it is used as default textFill. + * useInsideStyle: + * `true`: Use inside style (textFill, textStroke, textStrokeWidth) + * if `textFill` is not specified. + * `false`: Do not use inside style. + * `null/undefined`: use inside style if `isRectText` is true and + * `textFill` is not specified and textPosition contains `'inside'`. + * forceRich: boolean + * } + */ +function setTextStyleCommon(textStyle, textStyleModel, opt, isEmphasis) { + // Consider there will be abnormal when merge hover style to normal style if given default value. + opt = opt || EMPTY_OBJ; + + if (opt.isRectText) { + var textPosition = textStyleModel.getShallow('position') + || (isEmphasis ? null : 'inside'); + // 'outside' is not a valid zr textPostion value, but used + // in bar series, and magric type should be considered. + textPosition === 'outside' && (textPosition = 'top'); + textStyle.textPosition = textPosition; + textStyle.textOffset = textStyleModel.getShallow('offset'); + var labelRotate = textStyleModel.getShallow('rotate'); + labelRotate != null && (labelRotate *= Math.PI / 180); + textStyle.textRotation = labelRotate; + textStyle.textDistance = retrieve2( + textStyleModel.getShallow('distance'), isEmphasis ? null : 5 + ); + } + + var ecModel = textStyleModel.ecModel; + var globalTextStyle = ecModel && ecModel.option.textStyle; + + // Consider case: + // { + // data: [{ + // value: 12, + // label: { + // rich: { + // // no 'a' here but using parent 'a'. + // } + // } + // }], + // rich: { + // a: { ... } + // } + // } + var richItemNames = getRichItemNames(textStyleModel); + var richResult; + if (richItemNames) { + richResult = {}; + for (var name in richItemNames) { + if (richItemNames.hasOwnProperty(name)) { + // Cascade is supported in rich. + var richTextStyle = textStyleModel.getModel(['rich', name]); + // In rich, never `disableBox`. + setTokenTextStyle(richResult[name] = {}, richTextStyle, globalTextStyle, opt, isEmphasis); + } + } + } + textStyle.rich = richResult; + + setTokenTextStyle(textStyle, textStyleModel, globalTextStyle, opt, isEmphasis, true); + + if (opt.forceRich && !opt.textStyle) { + opt.textStyle = {}; + } + + return textStyle; +} + +// Consider case: +// { +// data: [{ +// value: 12, +// label: { +// rich: { +// // no 'a' here but using parent 'a'. +// } +// } +// }], +// rich: { +// a: { ... } +// } +// } +function getRichItemNames(textStyleModel) { + // Use object to remove duplicated names. + var richItemNameMap; + while (textStyleModel && textStyleModel !== textStyleModel.ecModel) { + var rich = (textStyleModel.option || EMPTY_OBJ).rich; + if (rich) { + richItemNameMap = richItemNameMap || {}; + for (var name in rich) { + if (rich.hasOwnProperty(name)) { + richItemNameMap[name] = 1; + } + } + } + textStyleModel = textStyleModel.parentModel; + } + return richItemNameMap; +} + +function setTokenTextStyle(textStyle, textStyleModel, globalTextStyle, opt, isEmphasis, isBlock) { + // In merge mode, default value should not be given. + globalTextStyle = !isEmphasis && globalTextStyle || EMPTY_OBJ; + + textStyle.textFill = getAutoColor(textStyleModel.getShallow('color'), opt) + || globalTextStyle.color; + textStyle.textStroke = getAutoColor(textStyleModel.getShallow('textBorderColor'), opt) + || globalTextStyle.textBorderColor; + textStyle.textStrokeWidth = retrieve2( + textStyleModel.getShallow('textBorderWidth'), + globalTextStyle.textBorderWidth + ); + + // Save original textPosition, because style.textPosition will be repalced by + // real location (like [10, 30]) in zrender. + textStyle.insideRawTextPosition = textStyle.textPosition; + + if (!isEmphasis) { + if (isBlock) { + textStyle.insideRollbackOpt = opt; + applyDefaultTextStyle(textStyle); + } + + // Set default finally. + if (textStyle.textFill == null) { + textStyle.textFill = opt.autoColor; + } + } + + // Do not use `getFont` here, because merge should be supported, where + // part of these properties may be changed in emphasis style, and the + // others should remain their original value got from normal style. + textStyle.fontStyle = textStyleModel.getShallow('fontStyle') || globalTextStyle.fontStyle; + textStyle.fontWeight = textStyleModel.getShallow('fontWeight') || globalTextStyle.fontWeight; + textStyle.fontSize = textStyleModel.getShallow('fontSize') || globalTextStyle.fontSize; + textStyle.fontFamily = textStyleModel.getShallow('fontFamily') || globalTextStyle.fontFamily; + + textStyle.textAlign = textStyleModel.getShallow('align'); + textStyle.textVerticalAlign = textStyleModel.getShallow('verticalAlign') + || textStyleModel.getShallow('baseline'); + + textStyle.textLineHeight = textStyleModel.getShallow('lineHeight'); + textStyle.textWidth = textStyleModel.getShallow('width'); + textStyle.textHeight = textStyleModel.getShallow('height'); + textStyle.textTag = textStyleModel.getShallow('tag'); + + if (!isBlock || !opt.disableBox) { + textStyle.textBackgroundColor = getAutoColor(textStyleModel.getShallow('backgroundColor'), opt); + textStyle.textPadding = textStyleModel.getShallow('padding'); + textStyle.textBorderColor = getAutoColor(textStyleModel.getShallow('borderColor'), opt); + textStyle.textBorderWidth = textStyleModel.getShallow('borderWidth'); + textStyle.textBorderRadius = textStyleModel.getShallow('borderRadius'); + + textStyle.textBoxShadowColor = textStyleModel.getShallow('shadowColor'); + textStyle.textBoxShadowBlur = textStyleModel.getShallow('shadowBlur'); + textStyle.textBoxShadowOffsetX = textStyleModel.getShallow('shadowOffsetX'); + textStyle.textBoxShadowOffsetY = textStyleModel.getShallow('shadowOffsetY'); + } + + textStyle.textShadowColor = textStyleModel.getShallow('textShadowColor') + || globalTextStyle.textShadowColor; + textStyle.textShadowBlur = textStyleModel.getShallow('textShadowBlur') + || globalTextStyle.textShadowBlur; + textStyle.textShadowOffsetX = textStyleModel.getShallow('textShadowOffsetX') + || globalTextStyle.textShadowOffsetX; + textStyle.textShadowOffsetY = textStyleModel.getShallow('textShadowOffsetY') + || globalTextStyle.textShadowOffsetY; +} + +function getAutoColor(color, opt) { + return color !== 'auto' ? color : (opt && opt.autoColor) ? opt.autoColor : null; +} + +/** + * Give some default value to the input `textStyle` object, based on the current settings + * in this `textStyle` object. + * + * The Scenario: + * when text position is `inside` and `textFill` is not specified, we show + * text border by default for better view. But it should be considered that text position + * might be changed when hovering or being emphasis, where the `insideRollback` is used to + * restore the style. + * + * Usage (& NOTICE): + * When a style object (eithor plain object or instance of `zrender/src/graphic/Style`) is + * about to be modified on its text related properties, `rollbackDefaultTextStyle` should + * be called before the modification and `applyDefaultTextStyle` should be called after that. + * (For the case that all of the text related properties is reset, like `setTextStyleCommon` + * does, `rollbackDefaultTextStyle` is not needed to be called). + */ +function applyDefaultTextStyle(textStyle) { + var opt = textStyle.insideRollbackOpt; + + // Only `insideRollbackOpt` created (in `setTextStyleCommon`), + // applyDefaultTextStyle works. + if (!opt || textStyle.textFill != null) { + return; + } + + var useInsideStyle = opt.useInsideStyle; + var textPosition = textStyle.insideRawTextPosition; + var insideRollback; + var autoColor = opt.autoColor; + + if (useInsideStyle !== false + && (useInsideStyle === true + || (opt.isRectText + && textPosition + // textPosition can be [10, 30] + && typeof textPosition === 'string' + && textPosition.indexOf('inside') >= 0 + ) + ) + ) { + insideRollback = { + textFill: null, + textStroke: textStyle.textStroke, + textStrokeWidth: textStyle.textStrokeWidth + }; + textStyle.textFill = '#fff'; + // Consider text with #fff overflow its container. + if (textStyle.textStroke == null) { + textStyle.textStroke = autoColor; + textStyle.textStrokeWidth == null && (textStyle.textStrokeWidth = 2); + } + } + else if (autoColor != null) { + insideRollback = {textFill: null}; + textStyle.textFill = autoColor; + } + + // Always set `insideRollback`, for clearing previous. + if (insideRollback) { + textStyle.insideRollback = insideRollback; + } +} + +/** + * Consider the case: in a scatter, + * label: { + * normal: {position: 'inside'}, + * emphasis: {position: 'top'} + * } + * In the normal state, the `textFill` will be set as '#fff' for pretty view (see + * `applyDefaultTextStyle`), but when switching to emphasis state, the `textFill` + * should be retured to 'autoColor', but not keep '#fff'. + */ +function rollbackDefaultTextStyle(style) { + var insideRollback = style.insideRollback; + if (insideRollback) { + style.textFill = insideRollback.textFill; + style.textStroke = insideRollback.textStroke; + style.textStrokeWidth = insideRollback.textStrokeWidth; + style.insideRollback = null; + } +} + +function getFont(opt, ecModel) { + // ecModel or default text style model. + var gTextStyleModel = ecModel || ecModel.getModel('textStyle'); + return trim([ + // FIXME in node-canvas fontWeight is before fontStyle + opt.fontStyle || gTextStyleModel && gTextStyleModel.getShallow('fontStyle') || '', + opt.fontWeight || gTextStyleModel && gTextStyleModel.getShallow('fontWeight') || '', + (opt.fontSize || gTextStyleModel && gTextStyleModel.getShallow('fontSize') || 12) + 'px', + opt.fontFamily || gTextStyleModel && gTextStyleModel.getShallow('fontFamily') || 'sans-serif' + ].join(' ')); +} + +function animateOrSetProps(isUpdate, el, props, animatableModel, dataIndex, cb) { + if (typeof dataIndex === 'function') { + cb = dataIndex; + dataIndex = null; + } + // Do not check 'animation' property directly here. Consider this case: + // animation model is an `itemModel`, whose does not have `isAnimationEnabled` + // but its parent model (`seriesModel`) does. + var animationEnabled = animatableModel && animatableModel.isAnimationEnabled(); + + if (animationEnabled) { + var postfix = isUpdate ? 'Update' : ''; + var duration = animatableModel.getShallow('animationDuration' + postfix); + var animationEasing = animatableModel.getShallow('animationEasing' + postfix); + var animationDelay = animatableModel.getShallow('animationDelay' + postfix); + if (typeof animationDelay === 'function') { + animationDelay = animationDelay( + dataIndex, + animatableModel.getAnimationDelayParams + ? animatableModel.getAnimationDelayParams(el, dataIndex) + : null + ); + } + if (typeof duration === 'function') { + duration = duration(dataIndex); + } + + duration > 0 + ? el.animateTo(props, duration, animationDelay || 0, animationEasing, cb, !!cb) + : (el.stopAnimation(), el.attr(props), cb && cb()); + } + else { + el.stopAnimation(); + el.attr(props); + cb && cb(); + } +} + +/** + * Update graphic element properties with or without animation according to the + * configuration in series. + * + * Caution: this method will stop previous animation. + * So if do not use this method to one element twice before + * animation starts, unless you know what you are doing. + * + * @param {module:zrender/Element} el + * @param {Object} props + * @param {module:echarts/model/Model} [animatableModel] + * @param {number} [dataIndex] + * @param {Function} [cb] + * @example + * graphic.updateProps(el, { + * position: [100, 100] + * }, seriesModel, dataIndex, function () { console.log('Animation done!'); }); + * // Or + * graphic.updateProps(el, { + * position: [100, 100] + * }, seriesModel, function () { console.log('Animation done!'); }); + */ +function updateProps(el, props, animatableModel, dataIndex, cb) { + animateOrSetProps(true, el, props, animatableModel, dataIndex, cb); +} + +/** + * Init graphic element properties with or without animation according to the + * configuration in series. + * + * Caution: this method will stop previous animation. + * So if do not use this method to one element twice before + * animation starts, unless you know what you are doing. + * + * @param {module:zrender/Element} el + * @param {Object} props + * @param {module:echarts/model/Model} [animatableModel] + * @param {number} [dataIndex] + * @param {Function} cb + */ +function initProps(el, props, animatableModel, dataIndex, cb) { + animateOrSetProps(false, el, props, animatableModel, dataIndex, cb); +} + +/** + * Get transform matrix of target (param target), + * in coordinate of its ancestor (param ancestor) + * + * @param {module:zrender/mixin/Transformable} target + * @param {module:zrender/mixin/Transformable} [ancestor] + */ +function getTransform(target, ancestor) { + var mat = identity([]); + + while (target && target !== ancestor) { + mul$1(mat, target.getLocalTransform(), mat); + target = target.parent; + } + + return mat; +} + +/** + * Apply transform to an vertex. + * @param {Array.} target [x, y] + * @param {Array.|TypedArray.|Object} transform Can be: + * + Transform matrix: like [1, 0, 0, 1, 0, 0] + * + {position, rotation, scale}, the same as `zrender/Transformable`. + * @param {boolean=} invert Whether use invert matrix. + * @return {Array.} [x, y] + */ +function applyTransform$1(target, transform, invert$$1) { + if (transform && !isArrayLike(transform)) { + transform = Transformable.getLocalTransform(transform); + } + + if (invert$$1) { + transform = invert([], transform); + } + return applyTransform([], target, transform); +} + +/** + * @param {string} direction 'left' 'right' 'top' 'bottom' + * @param {Array.} transform Transform matrix: like [1, 0, 0, 1, 0, 0] + * @param {boolean=} invert Whether use invert matrix. + * @return {string} Transformed direction. 'left' 'right' 'top' 'bottom' + */ +function transformDirection(direction, transform, invert$$1) { + + // Pick a base, ensure that transform result will not be (0, 0). + var hBase = (transform[4] === 0 || transform[5] === 0 || transform[0] === 0) + ? 1 : Math.abs(2 * transform[4] / transform[0]); + var vBase = (transform[4] === 0 || transform[5] === 0 || transform[2] === 0) + ? 1 : Math.abs(2 * transform[4] / transform[2]); + + var vertex = [ + direction === 'left' ? -hBase : direction === 'right' ? hBase : 0, + direction === 'top' ? -vBase : direction === 'bottom' ? vBase : 0 + ]; + + vertex = applyTransform$1(vertex, transform, invert$$1); + + return Math.abs(vertex[0]) > Math.abs(vertex[1]) + ? (vertex[0] > 0 ? 'right' : 'left') + : (vertex[1] > 0 ? 'bottom' : 'top'); +} + +/** + * Apply group transition animation from g1 to g2. + * If no animatableModel, no animation. + */ +function groupTransition(g1, g2, animatableModel, cb) { + if (!g1 || !g2) { + return; + } + + function getElMap(g) { + var elMap = {}; + g.traverse(function (el) { + if (!el.isGroup && el.anid) { + elMap[el.anid] = el; + } + }); + return elMap; + } + function getAnimatableProps(el) { + var obj = { + position: clone$1(el.position), + rotation: el.rotation + }; + if (el.shape) { + obj.shape = extend({}, el.shape); + } + return obj; + } + var elMap1 = getElMap(g1); + + g2.traverse(function (el) { + if (!el.isGroup && el.anid) { + var oldEl = elMap1[el.anid]; + if (oldEl) { + var newProp = getAnimatableProps(el); + el.attr(getAnimatableProps(oldEl)); + updateProps(el, newProp, animatableModel, el.dataIndex); + } + // else { + // if (el.previousProps) { + // graphic.updateProps + // } + // } + } + }); +} + +/** + * @param {Array.>} points Like: [[23, 44], [53, 66], ...] + * @param {Object} rect {x, y, width, height} + * @return {Array.>} A new clipped points. + */ +function clipPointsByRect(points, rect) { + // FIXME: this way migth be incorrect when grpahic clipped by a corner. + // and when element have border. + return map(points, function (point) { + var x = point[0]; + x = mathMax$1(x, rect.x); + x = mathMin$1(x, rect.x + rect.width); + var y = point[1]; + y = mathMax$1(y, rect.y); + y = mathMin$1(y, rect.y + rect.height); + return [x, y]; + }); +} + +/** + * @param {Object} targetRect {x, y, width, height} + * @param {Object} rect {x, y, width, height} + * @return {Object} A new clipped rect. If rect size are negative, return undefined. + */ +function clipRectByRect(targetRect, rect) { + var x = mathMax$1(targetRect.x, rect.x); + var x2 = mathMin$1(targetRect.x + targetRect.width, rect.x + rect.width); + var y = mathMax$1(targetRect.y, rect.y); + var y2 = mathMin$1(targetRect.y + targetRect.height, rect.y + rect.height); + + // If the total rect is cliped, nothing, including the border, + // should be painted. So return undefined. + if (x2 >= x && y2 >= y) { + return { + x: x, + y: y, + width: x2 - x, + height: y2 - y + }; + } +} + +/** + * @param {string} iconStr Support 'image://' or 'path://' or direct svg path. + * @param {Object} [opt] Properties of `module:zrender/Element`, except `style`. + * @param {Object} [rect] {x, y, width, height} + * @return {module:zrender/Element} Icon path or image element. + */ +function createIcon(iconStr, opt, rect) { + opt = extend({rectHover: true}, opt); + var style = opt.style = {strokeNoScale: true}; + rect = rect || {x: -1, y: -1, width: 2, height: 2}; + + if (iconStr) { + return iconStr.indexOf('image://') === 0 + ? ( + style.image = iconStr.slice(8), + defaults(style, rect), + new ZImage(opt) + ) + : ( + makePath( + iconStr.replace('path://', ''), + opt, + rect, + 'center' + ) + ); + } +} + + + + +var graphic = (Object.freeze || Object)({ + Z2_EMPHASIS_LIFT: Z2_EMPHASIS_LIFT, + extendShape: extendShape, + extendPath: extendPath, + makePath: makePath, + makeImage: makeImage, + mergePath: mergePath, + resizePath: resizePath, + subPixelOptimizeLine: subPixelOptimizeLine, + subPixelOptimizeRect: subPixelOptimizeRect, + subPixelOptimize: subPixelOptimize, + setElementHoverStyle: setElementHoverStyle, + isInEmphasis: isInEmphasis, + setHoverStyle: setHoverStyle, + setAsHoverStyleTrigger: setAsHoverStyleTrigger, + setLabelStyle: setLabelStyle, + setTextStyle: setTextStyle, + setText: setText, + getFont: getFont, + updateProps: updateProps, + initProps: initProps, + getTransform: getTransform, + applyTransform: applyTransform$1, + transformDirection: transformDirection, + groupTransition: groupTransition, + clipPointsByRect: clipPointsByRect, + clipRectByRect: clipRectByRect, + createIcon: createIcon, + Group: Group, + Image: ZImage, + Text: Text, + Circle: Circle, + Sector: Sector, + Ring: Ring, + Polygon: Polygon, + Polyline: Polyline, + Rect: Rect, + Line: Line, + BezierCurve: BezierCurve, + Arc: Arc, + IncrementalDisplayable: IncrementalDisplayble, + CompoundPath: CompoundPath, + LinearGradient: LinearGradient, + RadialGradient: RadialGradient, + BoundingRect: BoundingRect +}); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var PATH_COLOR = ['textStyle', 'color']; + +var textStyleMixin = { + /** + * Get color property or get color from option.textStyle.color + * @param {boolean} [isEmphasis] + * @return {string} + */ + getTextColor: function (isEmphasis) { + var ecModel = this.ecModel; + return this.getShallow('color') + || ( + (!isEmphasis && ecModel) ? ecModel.get(PATH_COLOR) : null + ); + }, + + /** + * Create font string from fontStyle, fontWeight, fontSize, fontFamily + * @return {string} + */ + getFont: function () { + return getFont({ + fontStyle: this.getShallow('fontStyle'), + fontWeight: this.getShallow('fontWeight'), + fontSize: this.getShallow('fontSize'), + fontFamily: this.getShallow('fontFamily') + }, this.ecModel); + }, + + getTextRect: function (text) { + return getBoundingRect( + text, + this.getFont(), + this.getShallow('align'), + this.getShallow('verticalAlign') || this.getShallow('baseline'), + this.getShallow('padding'), + this.getShallow('lineHeight'), + this.getShallow('rich'), + this.getShallow('truncateText') + ); + } +}; + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var getItemStyle = makeStyleMapper( + [ + ['fill', 'color'], + ['stroke', 'borderColor'], + ['lineWidth', 'borderWidth'], + ['opacity'], + ['shadowBlur'], + ['shadowOffsetX'], + ['shadowOffsetY'], + ['shadowColor'], + ['textPosition'], + ['textAlign'] + ] +); + +var itemStyleMixin = { + getItemStyle: function (excludes, includes) { + var style = getItemStyle(this, excludes, includes); + var lineDash = this.getBorderLineDash(); + lineDash && (style.lineDash = lineDash); + return style; + }, + + getBorderLineDash: function () { + var lineType = this.get('borderType'); + return (lineType === 'solid' || lineType == null) ? null + : (lineType === 'dashed' ? [5, 5] : [1, 1]); + } +}; + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/** + * @module echarts/model/Model + */ + +var mixin$1 = mixin; +var inner = makeInner(); + +/** + * @alias module:echarts/model/Model + * @constructor + * @param {Object} [option] + * @param {module:echarts/model/Model} [parentModel] + * @param {module:echarts/model/Global} [ecModel] + */ +function Model(option, parentModel, ecModel) { + /** + * @type {module:echarts/model/Model} + * @readOnly + */ + this.parentModel = parentModel; + + /** + * @type {module:echarts/model/Global} + * @readOnly + */ + this.ecModel = ecModel; + + /** + * @type {Object} + * @protected + */ + this.option = option; + + // Simple optimization + // if (this.init) { + // if (arguments.length <= 4) { + // this.init(option, parentModel, ecModel, extraOpt); + // } + // else { + // this.init.apply(this, arguments); + // } + // } +} + +Model.prototype = { + + constructor: Model, + + /** + * Model 的初始化函数 + * @param {Object} option + */ + init: null, + + /** + * 从新的 Option merge + */ + mergeOption: function (option) { + merge(this.option, option, true); + }, + + /** + * @param {string|Array.} path + * @param {boolean} [ignoreParent=false] + * @return {*} + */ + get: function (path, ignoreParent) { + if (path == null) { + return this.option; + } + + return doGet( + this.option, + this.parsePath(path), + !ignoreParent && getParent(this, path) + ); + }, + + /** + * @param {string} key + * @param {boolean} [ignoreParent=false] + * @return {*} + */ + getShallow: function (key, ignoreParent) { + var option = this.option; + + var val = option == null ? option : option[key]; + var parentModel = !ignoreParent && getParent(this, key); + if (val == null && parentModel) { + val = parentModel.getShallow(key); + } + return val; + }, + + /** + * @param {string|Array.} [path] + * @param {module:echarts/model/Model} [parentModel] + * @return {module:echarts/model/Model} + */ + getModel: function (path, parentModel) { + var obj = path == null + ? this.option + : doGet(this.option, path = this.parsePath(path)); + + var thisParentModel; + parentModel = parentModel || ( + (thisParentModel = getParent(this, path)) + && thisParentModel.getModel(path) + ); + + return new Model(obj, parentModel, this.ecModel); + }, + + /** + * If model has option + */ + isEmpty: function () { + return this.option == null; + }, + + restoreData: function () {}, + + // Pending + clone: function () { + var Ctor = this.constructor; + return new Ctor(clone(this.option)); + }, + + setReadOnly: function (properties) { + // clazzUtil.setReadOnly(this, properties); + }, + + // If path is null/undefined, return null/undefined. + parsePath: function (path) { + if (typeof path === 'string') { + path = path.split('.'); + } + return path; + }, + + /** + * @param {Function} getParentMethod + * param {Array.|string} path + * return {module:echarts/model/Model} + */ + customizeGetParent: function (getParentMethod) { + inner(this).getParent = getParentMethod; + }, + + isAnimationEnabled: function () { + if (!env$1.node) { + if (this.option.animation != null) { + return !!this.option.animation; + } + else if (this.parentModel) { + return this.parentModel.isAnimationEnabled(); + } + } + } + +}; + +function doGet(obj, pathArr, parentModel) { + for (var i = 0; i < pathArr.length; i++) { + // Ignore empty + if (!pathArr[i]) { + continue; + } + // obj could be number/string/... (like 0) + obj = (obj && typeof obj === 'object') ? obj[pathArr[i]] : null; + if (obj == null) { + break; + } + } + if (obj == null && parentModel) { + obj = parentModel.get(pathArr); + } + return obj; +} + +// `path` can be null/undefined +function getParent(model, path) { + var getParentMethod = inner(model).getParent; + return getParentMethod ? getParentMethod.call(model, path) : model.parentModel; +} + +// Enable Model.extend. +enableClassExtend(Model); +enableClassCheck(Model); + +mixin$1(Model, lineStyleMixin); +mixin$1(Model, areaStyleMixin); +mixin$1(Model, textStyleMixin); +mixin$1(Model, itemStyleMixin); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var base = 0; + +/** + * @public + * @param {string} type + * @return {string} + */ +function getUID(type) { + // Considering the case of crossing js context, + // use Math.random to make id as unique as possible. + return [(type || ''), base++, Math.random().toFixed(5)].join('_'); +} + +/** + * @inner + */ +function enableSubTypeDefaulter(entity) { + + var subTypeDefaulters = {}; + + entity.registerSubTypeDefaulter = function (componentType, defaulter) { + componentType = parseClassType$1(componentType); + subTypeDefaulters[componentType.main] = defaulter; + }; + + entity.determineSubType = function (componentType, option) { + var type = option.type; + if (!type) { + var componentTypeMain = parseClassType$1(componentType).main; + if (entity.hasSubTypes(componentType) && subTypeDefaulters[componentTypeMain]) { + type = subTypeDefaulters[componentTypeMain](option); + } + } + return type; + }; + + return entity; +} + +/** + * Topological travel on Activity Network (Activity On Vertices). + * Dependencies is defined in Model.prototype.dependencies, like ['xAxis', 'yAxis']. + * + * If 'xAxis' or 'yAxis' is absent in componentTypeList, just ignore it in topology. + * + * If there is circle dependencey, Error will be thrown. + * + */ +function enableTopologicalTravel(entity, dependencyGetter) { + + /** + * @public + * @param {Array.} targetNameList Target Component type list. + * Can be ['aa', 'bb', 'aa.xx'] + * @param {Array.} fullNameList By which we can build dependency graph. + * @param {Function} callback Params: componentType, dependencies. + * @param {Object} context Scope of callback. + */ + entity.topologicalTravel = function (targetNameList, fullNameList, callback, context) { + if (!targetNameList.length) { + return; + } + + var result = makeDepndencyGraph(fullNameList); + var graph = result.graph; + var stack = result.noEntryList; + + var targetNameSet = {}; + each$1(targetNameList, function (name) { + targetNameSet[name] = true; + }); + + while (stack.length) { + var currComponentType = stack.pop(); + var currVertex = graph[currComponentType]; + var isInTargetNameSet = !!targetNameSet[currComponentType]; + if (isInTargetNameSet) { + callback.call(context, currComponentType, currVertex.originalDeps.slice()); + delete targetNameSet[currComponentType]; + } + each$1( + currVertex.successor, + isInTargetNameSet ? removeEdgeAndAdd : removeEdge + ); + } + + each$1(targetNameSet, function () { + throw new Error('Circle dependency may exists'); + }); + + function removeEdge(succComponentType) { + graph[succComponentType].entryCount--; + if (graph[succComponentType].entryCount === 0) { + stack.push(succComponentType); + } + } + + // Consider this case: legend depends on series, and we call + // chart.setOption({series: [...]}), where only series is in option. + // If we do not have 'removeEdgeAndAdd', legendModel.mergeOption will + // not be called, but only sereis.mergeOption is called. Thus legend + // have no chance to update its local record about series (like which + // name of series is available in legend). + function removeEdgeAndAdd(succComponentType) { + targetNameSet[succComponentType] = true; + removeEdge(succComponentType); + } + }; + + /** + * DepndencyGraph: {Object} + * key: conponentType, + * value: { + * successor: [conponentTypes...], + * originalDeps: [conponentTypes...], + * entryCount: {number} + * } + */ + function makeDepndencyGraph(fullNameList) { + var graph = {}; + var noEntryList = []; + + each$1(fullNameList, function (name) { + + var thisItem = createDependencyGraphItem(graph, name); + var originalDeps = thisItem.originalDeps = dependencyGetter(name); + + var availableDeps = getAvailableDependencies(originalDeps, fullNameList); + thisItem.entryCount = availableDeps.length; + if (thisItem.entryCount === 0) { + noEntryList.push(name); + } + + each$1(availableDeps, function (dependentName) { + if (indexOf(thisItem.predecessor, dependentName) < 0) { + thisItem.predecessor.push(dependentName); + } + var thatItem = createDependencyGraphItem(graph, dependentName); + if (indexOf(thatItem.successor, dependentName) < 0) { + thatItem.successor.push(name); + } + }); + }); + + return {graph: graph, noEntryList: noEntryList}; + } + + function createDependencyGraphItem(graph, name) { + if (!graph[name]) { + graph[name] = {predecessor: [], successor: []}; + } + return graph[name]; + } + + function getAvailableDependencies(originalDeps, fullNameList) { + var availableDeps = []; + each$1(originalDeps, function (dep) { + indexOf(fullNameList, dep) >= 0 && availableDeps.push(dep); + }); + return availableDeps; + } +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/* +* A third-party license is embeded for some of the code in this file: +* The method "quantile" was copied from "d3.js". +* (See more details in the comment of the method below.) +* The use of the source code of this file is also subject to the terms +* and consitions of the license of "d3.js" (BSD-3Clause, see +* ). +*/ + +var RADIAN_EPSILON = 1e-4; + +function _trim(str) { + return str.replace(/^\s+/, '').replace(/\s+$/, ''); +} + +/** + * Linear mapping a value from domain to range + * @memberOf module:echarts/util/number + * @param {(number|Array.)} val + * @param {Array.} domain Domain extent domain[0] can be bigger than domain[1] + * @param {Array.} range Range extent range[0] can be bigger than range[1] + * @param {boolean} clamp + * @return {(number|Array.} + */ +function linearMap(val, domain, range, clamp) { + var subDomain = domain[1] - domain[0]; + var subRange = range[1] - range[0]; + + if (subDomain === 0) { + return subRange === 0 + ? range[0] + : (range[0] + range[1]) / 2; + } + + // Avoid accuracy problem in edge, such as + // 146.39 - 62.83 === 83.55999999999999. + // See echarts/test/ut/spec/util/number.js#linearMap#accuracyError + // It is a little verbose for efficiency considering this method + // is a hotspot. + if (clamp) { + if (subDomain > 0) { + if (val <= domain[0]) { + return range[0]; + } + else if (val >= domain[1]) { + return range[1]; + } + } + else { + if (val >= domain[0]) { + return range[0]; + } + else if (val <= domain[1]) { + return range[1]; + } + } + } + else { + if (val === domain[0]) { + return range[0]; + } + if (val === domain[1]) { + return range[1]; + } + } + + return (val - domain[0]) / subDomain * subRange + range[0]; +} + +/** + * Convert a percent string to absolute number. + * Returns NaN if percent is not a valid string or number + * @memberOf module:echarts/util/number + * @param {string|number} percent + * @param {number} all + * @return {number} + */ +function parsePercent$1(percent, all) { + switch (percent) { + case 'center': + case 'middle': + percent = '50%'; + break; + case 'left': + case 'top': + percent = '0%'; + break; + case 'right': + case 'bottom': + percent = '100%'; + break; + } + if (typeof percent === 'string') { + if (_trim(percent).match(/%$/)) { + return parseFloat(percent) / 100 * all; + } + + return parseFloat(percent); + } + + return percent == null ? NaN : +percent; +} + +/** + * (1) Fix rounding error of float numbers. + * (2) Support return string to avoid scientific notation like '3.5e-7'. + * + * @param {number} x + * @param {number} [precision] + * @param {boolean} [returnStr] + * @return {number|string} + */ +function round$2(x, precision, returnStr) { + if (precision == null) { + precision = 10; + } + // Avoid range error + precision = Math.min(Math.max(0, precision), 20); + x = (+x).toFixed(precision); + return returnStr ? x : +x; +} + +function asc(arr) { + arr.sort(function (a, b) { + return a - b; + }); + return arr; +} + +/** + * Get precision + * @param {number} val + */ +function getPrecision(val) { + val = +val; + if (isNaN(val)) { + return 0; + } + // It is much faster than methods converting number to string as follows + // var tmp = val.toString(); + // return tmp.length - 1 - tmp.indexOf('.'); + // especially when precision is low + var e = 1; + var count = 0; + while (Math.round(val * e) / e !== val) { + e *= 10; + count++; + } + return count; +} + +/** + * @param {string|number} val + * @return {number} + */ +function getPrecisionSafe(val) { + var str = val.toString(); + + // Consider scientific notation: '3.4e-12' '3.4e+12' + var eIndex = str.indexOf('e'); + if (eIndex > 0) { + var precision = +str.slice(eIndex + 1); + return precision < 0 ? -precision : 0; + } + else { + var dotIndex = str.indexOf('.'); + return dotIndex < 0 ? 0 : str.length - 1 - dotIndex; + } +} + +/** + * Minimal dicernible data precisioin according to a single pixel. + * + * @param {Array.} dataExtent + * @param {Array.} pixelExtent + * @return {number} precision + */ +function getPixelPrecision(dataExtent, pixelExtent) { + var log = Math.log; + var LN10 = Math.LN10; + var dataQuantity = Math.floor(log(dataExtent[1] - dataExtent[0]) / LN10); + var sizeQuantity = Math.round(log(Math.abs(pixelExtent[1] - pixelExtent[0])) / LN10); + // toFixed() digits argument must be between 0 and 20. + var precision = Math.min(Math.max(-dataQuantity + sizeQuantity, 0), 20); + return !isFinite(precision) ? 20 : precision; +} + +/** + * Get a data of given precision, assuring the sum of percentages + * in valueList is 1. + * The largest remainer method is used. + * https://en.wikipedia.org/wiki/Largest_remainder_method + * + * @param {Array.} valueList a list of all data + * @param {number} idx index of the data to be processed in valueList + * @param {number} precision integer number showing digits of precision + * @return {number} percent ranging from 0 to 100 + */ +function getPercentWithPrecision(valueList, idx, precision) { + if (!valueList[idx]) { + return 0; + } + + var sum = reduce(valueList, function (acc, val) { + return acc + (isNaN(val) ? 0 : val); + }, 0); + if (sum === 0) { + return 0; + } + + var digits = Math.pow(10, precision); + var votesPerQuota = map(valueList, function (val) { + return (isNaN(val) ? 0 : val) / sum * digits * 100; + }); + var targetSeats = digits * 100; + + var seats = map(votesPerQuota, function (votes) { + // Assign automatic seats. + return Math.floor(votes); + }); + var currentSum = reduce(seats, function (acc, val) { + return acc + val; + }, 0); + + var remainder = map(votesPerQuota, function (votes, idx) { + return votes - seats[idx]; + }); + + // Has remainding votes. + while (currentSum < targetSeats) { + // Find next largest remainder. + var max = Number.NEGATIVE_INFINITY; + var maxId = null; + for (var i = 0, len = remainder.length; i < len; ++i) { + if (remainder[i] > max) { + max = remainder[i]; + maxId = i; + } + } + + // Add a vote to max remainder. + ++seats[maxId]; + remainder[maxId] = 0; + ++currentSum; + } + + return seats[idx] / digits; +} + +// Number.MAX_SAFE_INTEGER, ie do not support. +var MAX_SAFE_INTEGER = 9007199254740991; + +/** + * To 0 - 2 * PI, considering negative radian. + * @param {number} radian + * @return {number} + */ +function remRadian(radian) { + var pi2 = Math.PI * 2; + return (radian % pi2 + pi2) % pi2; +} + +/** + * @param {type} radian + * @return {boolean} + */ +function isRadianAroundZero(val) { + return val > -RADIAN_EPSILON && val < RADIAN_EPSILON; +} + +/* eslint-disable */ +var TIME_REG = /^(?:(\d{4})(?:[-\/](\d{1,2})(?:[-\/](\d{1,2})(?:[T ](\d{1,2})(?::(\d\d)(?::(\d\d)(?:[.,](\d+))?)?)?(Z|[\+\-]\d\d:?\d\d)?)?)?)?)?$/; // jshint ignore:line +/* eslint-enable */ + +/** + * @param {string|Date|number} value These values can be accepted: + * + An instance of Date, represent a time in its own time zone. + * + Or string in a subset of ISO 8601, only including: + * + only year, month, date: '2012-03', '2012-03-01', '2012-03-01 05', '2012-03-01 05:06', + * + separated with T or space: '2012-03-01T12:22:33.123', '2012-03-01 12:22:33.123', + * + time zone: '2012-03-01T12:22:33Z', '2012-03-01T12:22:33+8000', '2012-03-01T12:22:33-05:00', + * all of which will be treated as local time if time zone is not specified + * (see ). + * + Or other string format, including (all of which will be treated as loacal time): + * '2012', '2012-3-1', '2012/3/1', '2012/03/01', + * '2009/6/12 2:00', '2009/6/12 2:05:08', '2009/6/12 2:05:08.123' + * + a timestamp, which represent a time in UTC. + * @return {Date} date + */ +function parseDate(value) { + if (value instanceof Date) { + return value; + } + else if (typeof value === 'string') { + // Different browsers parse date in different way, so we parse it manually. + // Some other issues: + // new Date('1970-01-01') is UTC, + // new Date('1970/01/01') and new Date('1970-1-01') is local. + // See issue #3623 + var match = TIME_REG.exec(value); + + if (!match) { + // return Invalid Date. + return new Date(NaN); + } + + // Use local time when no timezone offset specifed. + if (!match[8]) { + // match[n] can only be string or undefined. + // But take care of '12' + 1 => '121'. + return new Date( + +match[1], + +(match[2] || 1) - 1, + +match[3] || 1, + +match[4] || 0, + +(match[5] || 0), + +match[6] || 0, + +match[7] || 0 + ); + } + // Timezoneoffset of Javascript Date has considered DST (Daylight Saving Time, + // https://tc39.github.io/ecma262/#sec-daylight-saving-time-adjustment). + // For example, system timezone is set as "Time Zone: America/Toronto", + // then these code will get different result: + // `new Date(1478411999999).getTimezoneOffset(); // get 240` + // `new Date(1478412000000).getTimezoneOffset(); // get 300` + // So we should not use `new Date`, but use `Date.UTC`. + else { + var hour = +match[4] || 0; + if (match[8].toUpperCase() !== 'Z') { + hour -= match[8].slice(0, 3); + } + return new Date(Date.UTC( + +match[1], + +(match[2] || 1) - 1, + +match[3] || 1, + hour, + +(match[5] || 0), + +match[6] || 0, + +match[7] || 0 + )); + } + } + else if (value == null) { + return new Date(NaN); + } + + return new Date(Math.round(value)); +} + +/** + * Quantity of a number. e.g. 0.1, 1, 10, 100 + * + * @param {number} val + * @return {number} + */ +function quantity(val) { + return Math.pow(10, quantityExponent(val)); +} + +function quantityExponent(val) { + return Math.floor(Math.log(val) / Math.LN10); +} + +/** + * find a “nice” number approximately equal to x. Round the number if round = true, + * take ceiling if round = false. The primary observation is that the “nicest” + * numbers in decimal are 1, 2, and 5, and all power-of-ten multiples of these numbers. + * + * See "Nice Numbers for Graph Labels" of Graphic Gems. + * + * @param {number} val Non-negative value. + * @param {boolean} round + * @return {number} + */ +function nice(val, round) { + var exponent = quantityExponent(val); + var exp10 = Math.pow(10, exponent); + var f = val / exp10; // 1 <= f < 10 + var nf; + if (round) { + if (f < 1.5) { + nf = 1; + } + else if (f < 2.5) { + nf = 2; + } + else if (f < 4) { + nf = 3; + } + else if (f < 7) { + nf = 5; + } + else { + nf = 10; + } + } + else { + if (f < 1) { + nf = 1; + } + else if (f < 2) { + nf = 2; + } + else if (f < 3) { + nf = 3; + } + else if (f < 5) { + nf = 5; + } + else { + nf = 10; + } + } + val = nf * exp10; + + // Fix 3 * 0.1 === 0.30000000000000004 issue (see IEEE 754). + // 20 is the uppper bound of toFixed. + return exponent >= -20 ? +val.toFixed(exponent < 0 ? -exponent : 0) : val; +} + +/** + * This code was copied from "d3.js" + * . + * See the license statement at the head of this file. + * @param {Array.} ascArr + */ +function quantile(ascArr, p) { + var H = (ascArr.length - 1) * p + 1; + var h = Math.floor(H); + var v = +ascArr[h - 1]; + var e = H - h; + return e ? v + e * (ascArr[h] - v) : v; +} + +/** + * Order intervals asc, and split them when overlap. + * expect(numberUtil.reformIntervals([ + * {interval: [18, 62], close: [1, 1]}, + * {interval: [-Infinity, -70], close: [0, 0]}, + * {interval: [-70, -26], close: [1, 1]}, + * {interval: [-26, 18], close: [1, 1]}, + * {interval: [62, 150], close: [1, 1]}, + * {interval: [106, 150], close: [1, 1]}, + * {interval: [150, Infinity], close: [0, 0]} + * ])).toEqual([ + * {interval: [-Infinity, -70], close: [0, 0]}, + * {interval: [-70, -26], close: [1, 1]}, + * {interval: [-26, 18], close: [0, 1]}, + * {interval: [18, 62], close: [0, 1]}, + * {interval: [62, 150], close: [0, 1]}, + * {interval: [150, Infinity], close: [0, 0]} + * ]); + * @param {Array.} list, where `close` mean open or close + * of the interval, and Infinity can be used. + * @return {Array.} The origin list, which has been reformed. + */ +function reformIntervals(list) { + list.sort(function (a, b) { + return littleThan(a, b, 0) ? -1 : 1; + }); + + var curr = -Infinity; + var currClose = 1; + for (var i = 0; i < list.length;) { + var interval = list[i].interval; + var close = list[i].close; + + for (var lg = 0; lg < 2; lg++) { + if (interval[lg] <= curr) { + interval[lg] = curr; + close[lg] = !lg ? 1 - currClose : 1; + } + curr = interval[lg]; + currClose = close[lg]; + } + + if (interval[0] === interval[1] && close[0] * close[1] !== 1) { + list.splice(i, 1); + } + else { + i++; + } + } + + return list; + + function littleThan(a, b, lg) { + return a.interval[lg] < b.interval[lg] + || ( + a.interval[lg] === b.interval[lg] + && ( + (a.close[lg] - b.close[lg] === (!lg ? 1 : -1)) + || (!lg && littleThan(a, b, 1)) + ) + ); + } +} + +/** + * parseFloat NaNs numeric-cast false positives (null|true|false|"") + * ...but misinterprets leading-number strings, particularly hex literals ("0x...") + * subtraction forces infinities to NaN + * + * @param {*} v + * @return {boolean} + */ +function isNumeric(v) { + return v - parseFloat(v) >= 0; +} + + +var number = (Object.freeze || Object)({ + linearMap: linearMap, + parsePercent: parsePercent$1, + round: round$2, + asc: asc, + getPrecision: getPrecision, + getPrecisionSafe: getPrecisionSafe, + getPixelPrecision: getPixelPrecision, + getPercentWithPrecision: getPercentWithPrecision, + MAX_SAFE_INTEGER: MAX_SAFE_INTEGER, + remRadian: remRadian, + isRadianAroundZero: isRadianAroundZero, + parseDate: parseDate, + quantity: quantity, + nice: nice, + quantile: quantile, + reformIntervals: reformIntervals, + isNumeric: isNumeric +}); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +// import Text from 'zrender/src/graphic/Text'; + +/** + * 每三位默认加,格式化 + * @param {string|number} x + * @return {string} + */ +function addCommas(x) { + if (isNaN(x)) { + return '-'; + } + x = (x + '').split('.'); + return x[0].replace(/(\d{1,3})(?=(?:\d{3})+(?!\d))/g, '$1,') + + (x.length > 1 ? ('.' + x[1]) : ''); +} + +/** + * @param {string} str + * @param {boolean} [upperCaseFirst=false] + * @return {string} str + */ +function toCamelCase(str, upperCaseFirst) { + str = (str || '').toLowerCase().replace(/-(.)/g, function (match, group1) { + return group1.toUpperCase(); + }); + + if (upperCaseFirst && str) { + str = str.charAt(0).toUpperCase() + str.slice(1); + } + + return str; +} + +var normalizeCssArray$1 = normalizeCssArray; + + +var replaceReg = /([&<>"'])/g; +var replaceMap = { + '&': '&', + '<': '<', + '>': '>', + '"': '"', + '\'': ''' +}; + +function encodeHTML(source) { + return source == null + ? '' + : (source + '').replace(replaceReg, function (str, c) { + return replaceMap[c]; + }); +} + +var TPL_VAR_ALIAS = ['a', 'b', 'c', 'd', 'e', 'f', 'g']; + +var wrapVar = function (varName, seriesIdx) { + return '{' + varName + (seriesIdx == null ? '' : seriesIdx) + '}'; +}; + +/** + * Template formatter + * @param {string} tpl + * @param {Array.|Object} paramsList + * @param {boolean} [encode=false] + * @return {string} + */ +function formatTpl(tpl, paramsList, encode) { + if (!isArray(paramsList)) { + paramsList = [paramsList]; + } + var seriesLen = paramsList.length; + if (!seriesLen) { + return ''; + } + + var $vars = paramsList[0].$vars || []; + for (var i = 0; i < $vars.length; i++) { + var alias = TPL_VAR_ALIAS[i]; + tpl = tpl.replace(wrapVar(alias), wrapVar(alias, 0)); + } + for (var seriesIdx = 0; seriesIdx < seriesLen; seriesIdx++) { + for (var k = 0; k < $vars.length; k++) { + var val = paramsList[seriesIdx][$vars[k]]; + tpl = tpl.replace( + wrapVar(TPL_VAR_ALIAS[k], seriesIdx), + encode ? encodeHTML(val) : val + ); + } + } + + return tpl; +} + +/** + * simple Template formatter + * + * @param {string} tpl + * @param {Object} param + * @param {boolean} [encode=false] + * @return {string} + */ +function formatTplSimple(tpl, param, encode) { + each$1(param, function (value, key) { + tpl = tpl.replace( + '{' + key + '}', + encode ? encodeHTML(value) : value + ); + }); + return tpl; +} + +/** + * @param {Object|string} [opt] If string, means color. + * @param {string} [opt.color] + * @param {string} [opt.extraCssText] + * @param {string} [opt.type='item'] 'item' or 'subItem' + * @param {string} [opt.renderMode='html'] render mode of tooltip, 'html' or 'richText' + * @param {string} [opt.markerId='X'] id name for marker. If only one marker is in a rich text, this can be omitted. + * @return {string} + */ +function getTooltipMarker(opt, extraCssText) { + opt = isString(opt) ? {color: opt, extraCssText: extraCssText} : (opt || {}); + var color = opt.color; + var type = opt.type; + var extraCssText = opt.extraCssText; + var renderMode = opt.renderMode || 'html'; + var markerId = opt.markerId || 'X'; + + if (!color) { + return ''; + } + + if (renderMode === 'html') { + return type === 'subItem' + ? '' + : ''; + } + else { + // Space for rich element marker + return { + renderMode: renderMode, + content: '{marker' + markerId + '|} ', + style: { + color: color + } + }; + } +} + +function pad(str, len) { + str += ''; + return '0000'.substr(0, len - str.length) + str; +} + + +/** + * ISO Date format + * @param {string} tpl + * @param {number} value + * @param {boolean} [isUTC=false] Default in local time. + * see `module:echarts/scale/Time` + * and `module:echarts/util/number#parseDate`. + * @inner + */ +function formatTime(tpl, value, isUTC) { + if (tpl === 'week' + || tpl === 'month' + || tpl === 'quarter' + || tpl === 'half-year' + || tpl === 'year' + ) { + tpl = 'MM-dd\nyyyy'; + } + + var date = parseDate(value); + var utc = isUTC ? 'UTC' : ''; + var y = date['get' + utc + 'FullYear'](); + var M = date['get' + utc + 'Month']() + 1; + var d = date['get' + utc + 'Date'](); + var h = date['get' + utc + 'Hours'](); + var m = date['get' + utc + 'Minutes'](); + var s = date['get' + utc + 'Seconds'](); + var S = date['get' + utc + 'Milliseconds'](); + + tpl = tpl.replace('MM', pad(M, 2)) + .replace('M', M) + .replace('yyyy', y) + .replace('yy', y % 100) + .replace('dd', pad(d, 2)) + .replace('d', d) + .replace('hh', pad(h, 2)) + .replace('h', h) + .replace('mm', pad(m, 2)) + .replace('m', m) + .replace('ss', pad(s, 2)) + .replace('s', s) + .replace('SSS', pad(S, 3)); + + return tpl; +} + +/** + * Capital first + * @param {string} str + * @return {string} + */ +function capitalFirst(str) { + return str ? str.charAt(0).toUpperCase() + str.substr(1) : str; +} + +var truncateText$1 = truncateText; + +/** + * @public + * @param {Object} opt + * @param {string} opt.text + * @param {string} opt.font + * @param {string} [opt.textAlign='left'] + * @param {string} [opt.textVerticalAlign='top'] + * @param {Array.} [opt.textPadding] + * @param {number} [opt.textLineHeight] + * @param {Object} [opt.rich] + * @param {Object} [opt.truncate] + * @return {Object} {x, y, width, height, lineHeight} + */ +function getTextBoundingRect(opt) { + return getBoundingRect( + opt.text, + opt.font, + opt.textAlign, + opt.textVerticalAlign, + opt.textPadding, + opt.textLineHeight, + opt.rich, + opt.truncate + ); +} + +/** + * @deprecated + * the `textLineHeight` was added later. + * For backward compatiblility, put it as the last parameter. + * But deprecated this interface. Please use `getTextBoundingRect` instead. + */ +function getTextRect( + text, font, textAlign, textVerticalAlign, textPadding, rich, truncate, textLineHeight +) { + return getBoundingRect( + text, font, textAlign, textVerticalAlign, textPadding, textLineHeight, rich, truncate + ); +} + + +var format = (Object.freeze || Object)({ + addCommas: addCommas, + toCamelCase: toCamelCase, + normalizeCssArray: normalizeCssArray$1, + encodeHTML: encodeHTML, + formatTpl: formatTpl, + formatTplSimple: formatTplSimple, + getTooltipMarker: getTooltipMarker, + formatTime: formatTime, + capitalFirst: capitalFirst, + truncateText: truncateText$1, + getTextBoundingRect: getTextBoundingRect, + getTextRect: getTextRect +}); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +// Layout helpers for each component positioning + +var each$3 = each$1; + +/** + * @public + */ +var LOCATION_PARAMS = [ + 'left', 'right', 'top', 'bottom', 'width', 'height' +]; + +/** + * @public + */ +var HV_NAMES = [ + ['width', 'left', 'right'], + ['height', 'top', 'bottom'] +]; + +function boxLayout(orient, group, gap, maxWidth, maxHeight) { + var x = 0; + var y = 0; + + if (maxWidth == null) { + maxWidth = Infinity; + } + if (maxHeight == null) { + maxHeight = Infinity; + } + var currentLineMaxSize = 0; + + group.eachChild(function (child, idx) { + var position = child.position; + var rect = child.getBoundingRect(); + var nextChild = group.childAt(idx + 1); + var nextChildRect = nextChild && nextChild.getBoundingRect(); + var nextX; + var nextY; + + if (orient === 'horizontal') { + var moveX = rect.width + (nextChildRect ? (-nextChildRect.x + rect.x) : 0); + nextX = x + moveX; + // Wrap when width exceeds maxWidth or meet a `newline` group + // FIXME compare before adding gap? + if (nextX > maxWidth || child.newline) { + x = 0; + nextX = moveX; + y += currentLineMaxSize + gap; + currentLineMaxSize = rect.height; + } + else { + // FIXME: consider rect.y is not `0`? + currentLineMaxSize = Math.max(currentLineMaxSize, rect.height); + } + } + else { + var moveY = rect.height + (nextChildRect ? (-nextChildRect.y + rect.y) : 0); + nextY = y + moveY; + // Wrap when width exceeds maxHeight or meet a `newline` group + if (nextY > maxHeight || child.newline) { + x += currentLineMaxSize + gap; + y = 0; + nextY = moveY; + currentLineMaxSize = rect.width; + } + else { + currentLineMaxSize = Math.max(currentLineMaxSize, rect.width); + } + } + + if (child.newline) { + return; + } + + position[0] = x; + position[1] = y; + + orient === 'horizontal' + ? (x = nextX + gap) + : (y = nextY + gap); + }); +} + +/** + * VBox or HBox layouting + * @param {string} orient + * @param {module:zrender/container/Group} group + * @param {number} gap + * @param {number} [width=Infinity] + * @param {number} [height=Infinity] + */ +var box = boxLayout; + +/** + * VBox layouting + * @param {module:zrender/container/Group} group + * @param {number} gap + * @param {number} [width=Infinity] + * @param {number} [height=Infinity] + */ +var vbox = curry(boxLayout, 'vertical'); + +/** + * HBox layouting + * @param {module:zrender/container/Group} group + * @param {number} gap + * @param {number} [width=Infinity] + * @param {number} [height=Infinity] + */ +var hbox = curry(boxLayout, 'horizontal'); + +/** + * If x or x2 is not specified or 'center' 'left' 'right', + * the width would be as long as possible. + * If y or y2 is not specified or 'middle' 'top' 'bottom', + * the height would be as long as possible. + * + * @param {Object} positionInfo + * @param {number|string} [positionInfo.x] + * @param {number|string} [positionInfo.y] + * @param {number|string} [positionInfo.x2] + * @param {number|string} [positionInfo.y2] + * @param {Object} containerRect {width, height} + * @param {string|number} margin + * @return {Object} {width, height} + */ +function getAvailableSize(positionInfo, containerRect, margin) { + var containerWidth = containerRect.width; + var containerHeight = containerRect.height; + + var x = parsePercent$1(positionInfo.x, containerWidth); + var y = parsePercent$1(positionInfo.y, containerHeight); + var x2 = parsePercent$1(positionInfo.x2, containerWidth); + var y2 = parsePercent$1(positionInfo.y2, containerHeight); + + (isNaN(x) || isNaN(parseFloat(positionInfo.x))) && (x = 0); + (isNaN(x2) || isNaN(parseFloat(positionInfo.x2))) && (x2 = containerWidth); + (isNaN(y) || isNaN(parseFloat(positionInfo.y))) && (y = 0); + (isNaN(y2) || isNaN(parseFloat(positionInfo.y2))) && (y2 = containerHeight); + + margin = normalizeCssArray$1(margin || 0); + + return { + width: Math.max(x2 - x - margin[1] - margin[3], 0), + height: Math.max(y2 - y - margin[0] - margin[2], 0) + }; +} + +/** + * Parse position info. + * + * @param {Object} positionInfo + * @param {number|string} [positionInfo.left] + * @param {number|string} [positionInfo.top] + * @param {number|string} [positionInfo.right] + * @param {number|string} [positionInfo.bottom] + * @param {number|string} [positionInfo.width] + * @param {number|string} [positionInfo.height] + * @param {number|string} [positionInfo.aspect] Aspect is width / height + * @param {Object} containerRect + * @param {string|number} [margin] + * + * @return {module:zrender/core/BoundingRect} + */ +function getLayoutRect( + positionInfo, containerRect, margin +) { + margin = normalizeCssArray$1(margin || 0); + + var containerWidth = containerRect.width; + var containerHeight = containerRect.height; + + var left = parsePercent$1(positionInfo.left, containerWidth); + var top = parsePercent$1(positionInfo.top, containerHeight); + var right = parsePercent$1(positionInfo.right, containerWidth); + var bottom = parsePercent$1(positionInfo.bottom, containerHeight); + var width = parsePercent$1(positionInfo.width, containerWidth); + var height = parsePercent$1(positionInfo.height, containerHeight); + + var verticalMargin = margin[2] + margin[0]; + var horizontalMargin = margin[1] + margin[3]; + var aspect = positionInfo.aspect; + + // If width is not specified, calculate width from left and right + if (isNaN(width)) { + width = containerWidth - right - horizontalMargin - left; + } + if (isNaN(height)) { + height = containerHeight - bottom - verticalMargin - top; + } + + if (aspect != null) { + // If width and height are not given + // 1. Graph should not exceeds the container + // 2. Aspect must be keeped + // 3. Graph should take the space as more as possible + // FIXME + // Margin is not considered, because there is no case that both + // using margin and aspect so far. + if (isNaN(width) && isNaN(height)) { + if (aspect > containerWidth / containerHeight) { + width = containerWidth * 0.8; + } + else { + height = containerHeight * 0.8; + } + } + + // Calculate width or height with given aspect + if (isNaN(width)) { + width = aspect * height; + } + if (isNaN(height)) { + height = width / aspect; + } + } + + // If left is not specified, calculate left from right and width + if (isNaN(left)) { + left = containerWidth - right - width - horizontalMargin; + } + if (isNaN(top)) { + top = containerHeight - bottom - height - verticalMargin; + } + + // Align left and top + switch (positionInfo.left || positionInfo.right) { + case 'center': + left = containerWidth / 2 - width / 2 - margin[3]; + break; + case 'right': + left = containerWidth - width - horizontalMargin; + break; + } + switch (positionInfo.top || positionInfo.bottom) { + case 'middle': + case 'center': + top = containerHeight / 2 - height / 2 - margin[0]; + break; + case 'bottom': + top = containerHeight - height - verticalMargin; + break; + } + // If something is wrong and left, top, width, height are calculated as NaN + left = left || 0; + top = top || 0; + if (isNaN(width)) { + // Width may be NaN if only one value is given except width + width = containerWidth - horizontalMargin - left - (right || 0); + } + if (isNaN(height)) { + // Height may be NaN if only one value is given except height + height = containerHeight - verticalMargin - top - (bottom || 0); + } + + var rect = new BoundingRect(left + margin[3], top + margin[0], width, height); + rect.margin = margin; + return rect; +} + + +/** + * Position a zr element in viewport + * Group position is specified by either + * {left, top}, {right, bottom} + * If all properties exists, right and bottom will be igonred. + * + * Logic: + * 1. Scale (against origin point in parent coord) + * 2. Rotate (against origin point in parent coord) + * 3. Traslate (with el.position by this method) + * So this method only fixes the last step 'Traslate', which does not affect + * scaling and rotating. + * + * If be called repeatly with the same input el, the same result will be gotten. + * + * @param {module:zrender/Element} el Should have `getBoundingRect` method. + * @param {Object} positionInfo + * @param {number|string} [positionInfo.left] + * @param {number|string} [positionInfo.top] + * @param {number|string} [positionInfo.right] + * @param {number|string} [positionInfo.bottom] + * @param {number|string} [positionInfo.width] Only for opt.boundingModel: 'raw' + * @param {number|string} [positionInfo.height] Only for opt.boundingModel: 'raw' + * @param {Object} containerRect + * @param {string|number} margin + * @param {Object} [opt] + * @param {Array.} [opt.hv=[1,1]] Only horizontal or only vertical. + * @param {Array.} [opt.boundingMode='all'] + * Specify how to calculate boundingRect when locating. + * 'all': Position the boundingRect that is transformed and uioned + * both itself and its descendants. + * This mode simplies confine the elements in the bounding + * of their container (e.g., using 'right: 0'). + * 'raw': Position the boundingRect that is not transformed and only itself. + * This mode is useful when you want a element can overflow its + * container. (Consider a rotated circle needs to be located in a corner.) + * In this mode positionInfo.width/height can only be number. + */ +function positionElement(el, positionInfo, containerRect, margin, opt) { + var h = !opt || !opt.hv || opt.hv[0]; + var v = !opt || !opt.hv || opt.hv[1]; + var boundingMode = opt && opt.boundingMode || 'all'; + + if (!h && !v) { + return; + } + + var rect; + if (boundingMode === 'raw') { + rect = el.type === 'group' + ? new BoundingRect(0, 0, +positionInfo.width || 0, +positionInfo.height || 0) + : el.getBoundingRect(); + } + else { + rect = el.getBoundingRect(); + if (el.needLocalTransform()) { + var transform = el.getLocalTransform(); + // Notice: raw rect may be inner object of el, + // which should not be modified. + rect = rect.clone(); + rect.applyTransform(transform); + } + } + + // The real width and height can not be specified but calculated by the given el. + positionInfo = getLayoutRect( + defaults( + {width: rect.width, height: rect.height}, + positionInfo + ), + containerRect, + margin + ); + + // Because 'tranlate' is the last step in transform + // (see zrender/core/Transformable#getLocalTransform), + // we can just only modify el.position to get final result. + var elPos = el.position; + var dx = h ? positionInfo.x - rect.x : 0; + var dy = v ? positionInfo.y - rect.y : 0; + + el.attr('position', boundingMode === 'raw' ? [dx, dy] : [elPos[0] + dx, elPos[1] + dy]); +} + +/** + * @param {Object} option Contains some of the properties in HV_NAMES. + * @param {number} hvIdx 0: horizontal; 1: vertical. + */ +function sizeCalculable(option, hvIdx) { + return option[HV_NAMES[hvIdx][0]] != null + || (option[HV_NAMES[hvIdx][1]] != null && option[HV_NAMES[hvIdx][2]] != null); +} + +/** + * Consider Case: + * When defulat option has {left: 0, width: 100}, and we set {right: 0} + * through setOption or media query, using normal zrUtil.merge will cause + * {right: 0} does not take effect. + * + * @example + * ComponentModel.extend({ + * init: function () { + * ... + * var inputPositionParams = layout.getLayoutParams(option); + * this.mergeOption(inputPositionParams); + * }, + * mergeOption: function (newOption) { + * newOption && zrUtil.merge(thisOption, newOption, true); + * layout.mergeLayoutParam(thisOption, newOption); + * } + * }); + * + * @param {Object} targetOption + * @param {Object} newOption + * @param {Object|string} [opt] + * @param {boolean|Array.} [opt.ignoreSize=false] Used for the components + * that width (or height) should not be calculated by left and right (or top and bottom). + */ +function mergeLayoutParam(targetOption, newOption, opt) { + !isObject$1(opt) && (opt = {}); + + var ignoreSize = opt.ignoreSize; + !isArray(ignoreSize) && (ignoreSize = [ignoreSize, ignoreSize]); + + var hResult = merge$$1(HV_NAMES[0], 0); + var vResult = merge$$1(HV_NAMES[1], 1); + + copy(HV_NAMES[0], targetOption, hResult); + copy(HV_NAMES[1], targetOption, vResult); + + function merge$$1(names, hvIdx) { + var newParams = {}; + var newValueCount = 0; + var merged = {}; + var mergedValueCount = 0; + var enoughParamNumber = 2; + + each$3(names, function (name) { + merged[name] = targetOption[name]; + }); + each$3(names, function (name) { + // Consider case: newOption.width is null, which is + // set by user for removing width setting. + hasProp(newOption, name) && (newParams[name] = merged[name] = newOption[name]); + hasValue(newParams, name) && newValueCount++; + hasValue(merged, name) && mergedValueCount++; + }); + + if (ignoreSize[hvIdx]) { + // Only one of left/right is premitted to exist. + if (hasValue(newOption, names[1])) { + merged[names[2]] = null; + } + else if (hasValue(newOption, names[2])) { + merged[names[1]] = null; + } + return merged; + } + + // Case: newOption: {width: ..., right: ...}, + // or targetOption: {right: ...} and newOption: {width: ...}, + // There is no conflict when merged only has params count + // little than enoughParamNumber. + if (mergedValueCount === enoughParamNumber || !newValueCount) { + return merged; + } + // Case: newOption: {width: ..., right: ...}, + // Than we can make sure user only want those two, and ignore + // all origin params in targetOption. + else if (newValueCount >= enoughParamNumber) { + return newParams; + } + else { + // Chose another param from targetOption by priority. + for (var i = 0; i < names.length; i++) { + var name = names[i]; + if (!hasProp(newParams, name) && hasProp(targetOption, name)) { + newParams[name] = targetOption[name]; + break; + } + } + return newParams; + } + } + + function hasProp(obj, name) { + return obj.hasOwnProperty(name); + } + + function hasValue(obj, name) { + return obj[name] != null && obj[name] !== 'auto'; + } + + function copy(names, target, source) { + each$3(names, function (name) { + target[name] = source[name]; + }); + } +} + +/** + * Retrieve 'left', 'right', 'top', 'bottom', 'width', 'height' from object. + * @param {Object} source + * @return {Object} Result contains those props. + */ +function getLayoutParams(source) { + return copyLayoutParams({}, source); +} + +/** + * Retrieve 'left', 'right', 'top', 'bottom', 'width', 'height' from object. + * @param {Object} source + * @return {Object} Result contains those props. + */ +function copyLayoutParams(target, source) { + source && target && each$3(LOCATION_PARAMS, function (name) { + source.hasOwnProperty(name) && (target[name] = source[name]); + }); + return target; +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + + +var boxLayoutMixin = { + getBoxLayoutParams: function () { + return { + left: this.get('left'), + top: this.get('top'), + right: this.get('right'), + bottom: this.get('bottom'), + width: this.get('width'), + height: this.get('height') + }; + } +}; + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/** + * Component model + * + * @module echarts/model/Component + */ + +var inner$1 = makeInner(); + +/** + * @alias module:echarts/model/Component + * @constructor + * @param {Object} option + * @param {module:echarts/model/Model} parentModel + * @param {module:echarts/model/Model} ecModel + */ +var ComponentModel = Model.extend({ + + type: 'component', + + /** + * @readOnly + * @type {string} + */ + id: '', + + /** + * Because simplified concept is probably better, series.name (or component.name) + * has been having too many resposibilities: + * (1) Generating id (which requires name in option should not be modified). + * (2) As an index to mapping series when merging option or calling API (a name + * can refer to more then one components, which is convinient is some case). + * (3) Display. + * @readOnly + */ + name: '', + + /** + * @readOnly + * @type {string} + */ + mainType: '', + + /** + * @readOnly + * @type {string} + */ + subType: '', + + /** + * @readOnly + * @type {number} + */ + componentIndex: 0, + + /** + * @type {Object} + * @protected + */ + defaultOption: null, + + /** + * @type {module:echarts/model/Global} + * @readOnly + */ + ecModel: null, + + /** + * key: componentType + * value: Component model list, can not be null. + * @type {Object.>} + * @readOnly + */ + dependentModels: [], + + /** + * @type {string} + * @readOnly + */ + uid: null, + + /** + * Support merge layout params. + * Only support 'box' now (left/right/top/bottom/width/height). + * @type {string|Object} Object can be {ignoreSize: true} + * @readOnly + */ + layoutMode: null, + + $constructor: function (option, parentModel, ecModel, extraOpt) { + Model.call(this, option, parentModel, ecModel, extraOpt); + + this.uid = getUID('ec_cpt_model'); + }, + + init: function (option, parentModel, ecModel, extraOpt) { + this.mergeDefaultAndTheme(option, ecModel); + }, + + mergeDefaultAndTheme: function (option, ecModel) { + var layoutMode = this.layoutMode; + var inputPositionParams = layoutMode + ? getLayoutParams(option) : {}; + + var themeModel = ecModel.getTheme(); + merge(option, themeModel.get(this.mainType)); + merge(option, this.getDefaultOption()); + + if (layoutMode) { + mergeLayoutParam(option, inputPositionParams, layoutMode); + } + }, + + mergeOption: function (option, extraOpt) { + merge(this.option, option, true); + + var layoutMode = this.layoutMode; + if (layoutMode) { + mergeLayoutParam(this.option, option, layoutMode); + } + }, + + // Hooker after init or mergeOption + optionUpdated: function (newCptOption, isInit) {}, + + getDefaultOption: function () { + var fields = inner$1(this); + if (!fields.defaultOption) { + var optList = []; + var Class = this.constructor; + while (Class) { + var opt = Class.prototype.defaultOption; + opt && optList.push(opt); + Class = Class.superClass; + } + + var defaultOption = {}; + for (var i = optList.length - 1; i >= 0; i--) { + defaultOption = merge(defaultOption, optList[i], true); + } + fields.defaultOption = defaultOption; + } + return fields.defaultOption; + }, + + getReferringComponents: function (mainType) { + return this.ecModel.queryComponents({ + mainType: mainType, + index: this.get(mainType + 'Index', true), + id: this.get(mainType + 'Id', true) + }); + } + +}); + +// Reset ComponentModel.extend, add preConstruct. +// clazzUtil.enableClassExtend( +// ComponentModel, +// function (option, parentModel, ecModel, extraOpt) { +// // Set dependentModels, componentIndex, name, id, mainType, subType. +// zrUtil.extend(this, extraOpt); + +// this.uid = componentUtil.getUID('componentModel'); + +// // this.setReadOnly([ +// // 'type', 'id', 'uid', 'name', 'mainType', 'subType', +// // 'dependentModels', 'componentIndex' +// // ]); +// } +// ); + +// Add capability of registerClass, getClass, hasClass, registerSubTypeDefaulter and so on. +enableClassManagement( + ComponentModel, {registerWhenExtend: true} +); +enableSubTypeDefaulter(ComponentModel); + +// Add capability of ComponentModel.topologicalTravel. +enableTopologicalTravel(ComponentModel, getDependencies); + +function getDependencies(componentType) { + var deps = []; + each$1(ComponentModel.getClassesByMainType(componentType), function (Clazz) { + deps = deps.concat(Clazz.prototype.dependencies || []); + }); + + // Ensure main type. + deps = map(deps, function (type) { + return parseClassType$1(type).main; + }); + + // Hack dataset for convenience. + if (componentType !== 'dataset' && indexOf(deps, 'dataset') <= 0) { + deps.unshift('dataset'); + } + + return deps; +} + +mixin(ComponentModel, boxLayoutMixin); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + + +var platform = ''; +// Navigator not exists in node +if (typeof navigator !== 'undefined') { + platform = navigator.platform || ''; +} + +var globalDefault = { + // backgroundColor: 'rgba(0,0,0,0)', + + // https://dribbble.com/shots/1065960-Infographic-Pie-chart-visualization + // color: ['#5793f3', '#d14a61', '#fd9c35', '#675bba', '#fec42c', '#dd4444', '#d4df5a', '#cd4870'], + // Light colors: + // color: ['#bcd3bb', '#e88f70', '#edc1a5', '#9dc5c8', '#e1e8c8', '#7b7c68', '#e5b5b5', '#f0b489', '#928ea8', '#bda29a'], + // color: ['#cc5664', '#9bd6ec', '#ea946e', '#8acaaa', '#f1ec64', '#ee8686', '#a48dc1', '#5da6bc', '#b9dcae'], + // Dark colors: + color: [ + '#c23531', '#2f4554', '#61a0a8', '#d48265', '#91c7ae', '#749f83', + '#ca8622', '#bda29a', '#6e7074', '#546570', '#c4ccd3' + ], + + gradientColor: ['#f6efa6', '#d88273', '#bf444c'], + + // If xAxis and yAxis declared, grid is created by default. + // grid: {}, + + textStyle: { + // color: '#000', + // decoration: 'none', + // PENDING + fontFamily: platform.match(/^Win/) ? 'Microsoft YaHei' : 'sans-serif', + // fontFamily: 'Arial, Verdana, sans-serif', + fontSize: 12, + fontStyle: 'normal', + fontWeight: 'normal' + }, + + // http://blogs.adobe.com/webplatform/2014/02/24/using-blend-modes-in-html-canvas/ + // https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/globalCompositeOperation + // Default is source-over + blendMode: null, + + animation: 'auto', + animationDuration: 1000, + animationDurationUpdate: 300, + animationEasing: 'exponentialOut', + animationEasingUpdate: 'cubicOut', + + animationThreshold: 2000, + // Configuration for progressive/incremental rendering + progressiveThreshold: 3000, + progressive: 400, + + // Threshold of if use single hover layer to optimize. + // It is recommended that `hoverLayerThreshold` is equivalent to or less than + // `progressiveThreshold`, otherwise hover will cause restart of progressive, + // which is unexpected. + // see example . + hoverLayerThreshold: 3000, + + // See: module:echarts/scale/Time + useUTC: false +}; + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var inner$2 = makeInner(); + +function getNearestColorPalette(colors, requestColorNum) { + var paletteNum = colors.length; + // TODO colors must be in order + for (var i = 0; i < paletteNum; i++) { + if (colors[i].length > requestColorNum) { + return colors[i]; + } + } + return colors[paletteNum - 1]; +} + +var colorPaletteMixin = { + clearColorPalette: function () { + inner$2(this).colorIdx = 0; + inner$2(this).colorNameMap = {}; + }, + + /** + * @param {string} name MUST NOT be null/undefined. Otherwise call this function + * twise with the same parameters will get different result. + * @param {Object} [scope=this] + * @param {Object} [requestColorNum] + * @return {string} color string. + */ + getColorFromPalette: function (name, scope, requestColorNum) { + scope = scope || this; + var scopeFields = inner$2(scope); + var colorIdx = scopeFields.colorIdx || 0; + var colorNameMap = scopeFields.colorNameMap = scopeFields.colorNameMap || {}; + // Use `hasOwnProperty` to avoid conflict with Object.prototype. + if (colorNameMap.hasOwnProperty(name)) { + return colorNameMap[name]; + } + var defaultColorPalette = normalizeToArray(this.get('color', true)); + var layeredColorPalette = this.get('colorLayer', true); + var colorPalette = ((requestColorNum == null || !layeredColorPalette) + ? defaultColorPalette : getNearestColorPalette(layeredColorPalette, requestColorNum)); + + // In case can't find in layered color palette. + colorPalette = colorPalette || defaultColorPalette; + + if (!colorPalette || !colorPalette.length) { + return; + } + + var color = colorPalette[colorIdx]; + if (name) { + colorNameMap[name] = color; + } + scopeFields.colorIdx = (colorIdx + 1) % colorPalette.length; + + return color; + } +}; + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/** + * Helper for model references. + * There are many manners to refer axis/coordSys. + */ + +// TODO +// merge relevant logic to this file? +// check: "modelHelper" of tooltip and "BrushTargetManager". + +/** + * @return {Object} For example: + * { + * coordSysName: 'cartesian2d', + * coordSysDims: ['x', 'y', ...], + * axisMap: HashMap({ + * x: xAxisModel, + * y: yAxisModel + * }), + * categoryAxisMap: HashMap({ + * x: xAxisModel, + * y: undefined + * }), + * // It also indicate that whether there is category axis. + * firstCategoryDimIndex: 1, + * // To replace user specified encode. + * } + */ +function getCoordSysDefineBySeries(seriesModel) { + var coordSysName = seriesModel.get('coordinateSystem'); + var result = { + coordSysName: coordSysName, + coordSysDims: [], + axisMap: createHashMap(), + categoryAxisMap: createHashMap() + }; + var fetch = fetchers[coordSysName]; + if (fetch) { + fetch(seriesModel, result, result.axisMap, result.categoryAxisMap); + return result; + } +} + +var fetchers = { + + cartesian2d: function (seriesModel, result, axisMap, categoryAxisMap) { + var xAxisModel = seriesModel.getReferringComponents('xAxis')[0]; + var yAxisModel = seriesModel.getReferringComponents('yAxis')[0]; + + if (__DEV__) { + if (!xAxisModel) { + throw new Error('xAxis "' + retrieve( + seriesModel.get('xAxisIndex'), + seriesModel.get('xAxisId'), + 0 + ) + '" not found'); + } + if (!yAxisModel) { + throw new Error('yAxis "' + retrieve( + seriesModel.get('xAxisIndex'), + seriesModel.get('yAxisId'), + 0 + ) + '" not found'); + } + } + + result.coordSysDims = ['x', 'y']; + axisMap.set('x', xAxisModel); + axisMap.set('y', yAxisModel); + + if (isCategory(xAxisModel)) { + categoryAxisMap.set('x', xAxisModel); + result.firstCategoryDimIndex = 0; + } + if (isCategory(yAxisModel)) { + categoryAxisMap.set('y', yAxisModel); + result.firstCategoryDimIndex = 1; + } + }, + + singleAxis: function (seriesModel, result, axisMap, categoryAxisMap) { + var singleAxisModel = seriesModel.getReferringComponents('singleAxis')[0]; + + if (__DEV__) { + if (!singleAxisModel) { + throw new Error('singleAxis should be specified.'); + } + } + + result.coordSysDims = ['single']; + axisMap.set('single', singleAxisModel); + + if (isCategory(singleAxisModel)) { + categoryAxisMap.set('single', singleAxisModel); + result.firstCategoryDimIndex = 0; + } + }, + + polar: function (seriesModel, result, axisMap, categoryAxisMap) { + var polarModel = seriesModel.getReferringComponents('polar')[0]; + var radiusAxisModel = polarModel.findAxisModel('radiusAxis'); + var angleAxisModel = polarModel.findAxisModel('angleAxis'); + + if (__DEV__) { + if (!angleAxisModel) { + throw new Error('angleAxis option not found'); + } + if (!radiusAxisModel) { + throw new Error('radiusAxis option not found'); + } + } + + result.coordSysDims = ['radius', 'angle']; + axisMap.set('radius', radiusAxisModel); + axisMap.set('angle', angleAxisModel); + + if (isCategory(radiusAxisModel)) { + categoryAxisMap.set('radius', radiusAxisModel); + result.firstCategoryDimIndex = 0; + } + if (isCategory(angleAxisModel)) { + categoryAxisMap.set('angle', angleAxisModel); + result.firstCategoryDimIndex = 1; + } + }, + + geo: function (seriesModel, result, axisMap, categoryAxisMap) { + result.coordSysDims = ['lng', 'lat']; + }, + + parallel: function (seriesModel, result, axisMap, categoryAxisMap) { + var ecModel = seriesModel.ecModel; + var parallelModel = ecModel.getComponent( + 'parallel', seriesModel.get('parallelIndex') + ); + var coordSysDims = result.coordSysDims = parallelModel.dimensions.slice(); + + each$1(parallelModel.parallelAxisIndex, function (axisIndex, index) { + var axisModel = ecModel.getComponent('parallelAxis', axisIndex); + var axisDim = coordSysDims[index]; + axisMap.set(axisDim, axisModel); + + if (isCategory(axisModel) && result.firstCategoryDimIndex == null) { + categoryAxisMap.set(axisDim, axisModel); + result.firstCategoryDimIndex = index; + } + }); + } +}; + +function isCategory(axisModel) { + return axisModel.get('type') === 'category'; +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +// Avoid typo. +var SOURCE_FORMAT_ORIGINAL = 'original'; +var SOURCE_FORMAT_ARRAY_ROWS = 'arrayRows'; +var SOURCE_FORMAT_OBJECT_ROWS = 'objectRows'; +var SOURCE_FORMAT_KEYED_COLUMNS = 'keyedColumns'; +var SOURCE_FORMAT_UNKNOWN = 'unknown'; +// ??? CHANGE A NAME +var SOURCE_FORMAT_TYPED_ARRAY = 'typedArray'; + +var SERIES_LAYOUT_BY_COLUMN = 'column'; +var SERIES_LAYOUT_BY_ROW = 'row'; + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/** + * [sourceFormat] + * + * + "original": + * This format is only used in series.data, where + * itemStyle can be specified in data item. + * + * + "arrayRows": + * [ + * ['product', 'score', 'amount'], + * ['Matcha Latte', 89.3, 95.8], + * ['Milk Tea', 92.1, 89.4], + * ['Cheese Cocoa', 94.4, 91.2], + * ['Walnut Brownie', 85.4, 76.9] + * ] + * + * + "objectRows": + * [ + * {product: 'Matcha Latte', score: 89.3, amount: 95.8}, + * {product: 'Milk Tea', score: 92.1, amount: 89.4}, + * {product: 'Cheese Cocoa', score: 94.4, amount: 91.2}, + * {product: 'Walnut Brownie', score: 85.4, amount: 76.9} + * ] + * + * + "keyedColumns": + * { + * 'product': ['Matcha Latte', 'Milk Tea', 'Cheese Cocoa', 'Walnut Brownie'], + * 'count': [823, 235, 1042, 988], + * 'score': [95.8, 81.4, 91.2, 76.9] + * } + * + * + "typedArray" + * + * + "unknown" + */ + +/** + * @constructor + * @param {Object} fields + * @param {string} fields.sourceFormat + * @param {Array|Object} fields.fromDataset + * @param {Array|Object} [fields.data] + * @param {string} [seriesLayoutBy='column'] + * @param {Array.} [dimensionsDefine] + * @param {Objet|HashMap} [encodeDefine] + * @param {number} [startIndex=0] + * @param {number} [dimensionsDetectCount] + */ +function Source(fields) { + + /** + * @type {boolean} + */ + this.fromDataset = fields.fromDataset; + + /** + * Not null/undefined. + * @type {Array|Object} + */ + this.data = fields.data || ( + fields.sourceFormat === SOURCE_FORMAT_KEYED_COLUMNS ? {} : [] + ); + + /** + * See also "detectSourceFormat". + * Not null/undefined. + * @type {string} + */ + this.sourceFormat = fields.sourceFormat || SOURCE_FORMAT_UNKNOWN; + + /** + * 'row' or 'column' + * Not null/undefined. + * @type {string} seriesLayoutBy + */ + this.seriesLayoutBy = fields.seriesLayoutBy || SERIES_LAYOUT_BY_COLUMN; + + /** + * dimensions definition in option. + * can be null/undefined. + * @type {Array.} + */ + this.dimensionsDefine = fields.dimensionsDefine; + + /** + * encode definition in option. + * can be null/undefined. + * @type {Objet|HashMap} + */ + this.encodeDefine = fields.encodeDefine && createHashMap(fields.encodeDefine); + + /** + * Not null/undefined, uint. + * @type {number} + */ + this.startIndex = fields.startIndex || 0; + + /** + * Can be null/undefined (when unknown), uint. + * @type {number} + */ + this.dimensionsDetectCount = fields.dimensionsDetectCount; +} + +/** + * Wrap original series data for some compatibility cases. + */ +Source.seriesDataToSource = function (data) { + return new Source({ + data: data, + sourceFormat: isTypedArray(data) + ? SOURCE_FORMAT_TYPED_ARRAY + : SOURCE_FORMAT_ORIGINAL, + fromDataset: false + }); +}; + +enableClassCheck(Source); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var inner$3 = makeInner(); + +/** + * @see {module:echarts/data/Source} + * @param {module:echarts/component/dataset/DatasetModel} datasetModel + * @return {string} sourceFormat + */ +function detectSourceFormat(datasetModel) { + var data = datasetModel.option.source; + var sourceFormat = SOURCE_FORMAT_UNKNOWN; + + if (isTypedArray(data)) { + sourceFormat = SOURCE_FORMAT_TYPED_ARRAY; + } + else if (isArray(data)) { + // FIXME Whether tolerate null in top level array? + if (data.length === 0) { + sourceFormat = SOURCE_FORMAT_ARRAY_ROWS; + } + + for (var i = 0, len = data.length; i < len; i++) { + var item = data[i]; + + if (item == null) { + continue; + } + else if (isArray(item)) { + sourceFormat = SOURCE_FORMAT_ARRAY_ROWS; + break; + } + else if (isObject$1(item)) { + sourceFormat = SOURCE_FORMAT_OBJECT_ROWS; + break; + } + } + } + else if (isObject$1(data)) { + for (var key in data) { + if (data.hasOwnProperty(key) && isArrayLike(data[key])) { + sourceFormat = SOURCE_FORMAT_KEYED_COLUMNS; + break; + } + } + } + else if (data != null) { + throw new Error('Invalid data'); + } + + inner$3(datasetModel).sourceFormat = sourceFormat; +} + +/** + * [Scenarios]: + * (1) Provide source data directly: + * series: { + * encode: {...}, + * dimensions: [...] + * seriesLayoutBy: 'row', + * data: [[...]] + * } + * (2) Refer to datasetModel. + * series: [{ + * encode: {...} + * // Ignore datasetIndex means `datasetIndex: 0` + * // and the dimensions defination in dataset is used + * }, { + * encode: {...}, + * seriesLayoutBy: 'column', + * datasetIndex: 1 + * }] + * + * Get data from series itself or datset. + * @return {module:echarts/data/Source} source + */ +function getSource(seriesModel) { + return inner$3(seriesModel).source; +} + +/** + * MUST be called before mergeOption of all series. + * @param {module:echarts/model/Global} ecModel + */ +function resetSourceDefaulter(ecModel) { + // `datasetMap` is used to make default encode. + inner$3(ecModel).datasetMap = createHashMap(); +} + +/** + * [Caution]: + * MUST be called after series option merged and + * before "series.getInitailData()" called. + * + * [The rule of making default encode]: + * Category axis (if exists) alway map to the first dimension. + * Each other axis occupies a subsequent dimension. + * + * [Why make default encode]: + * Simplify the typing of encode in option, avoiding the case like that: + * series: [{encode: {x: 0, y: 1}}, {encode: {x: 0, y: 2}}, {encode: {x: 0, y: 3}}], + * where the "y" have to be manually typed as "1, 2, 3, ...". + * + * @param {module:echarts/model/Series} seriesModel + */ +function prepareSource(seriesModel) { + var seriesOption = seriesModel.option; + + var data = seriesOption.data; + var sourceFormat = isTypedArray(data) + ? SOURCE_FORMAT_TYPED_ARRAY : SOURCE_FORMAT_ORIGINAL; + var fromDataset = false; + + var seriesLayoutBy = seriesOption.seriesLayoutBy; + var sourceHeader = seriesOption.sourceHeader; + var dimensionsDefine = seriesOption.dimensions; + + var datasetModel = getDatasetModel(seriesModel); + if (datasetModel) { + var datasetOption = datasetModel.option; + + data = datasetOption.source; + sourceFormat = inner$3(datasetModel).sourceFormat; + fromDataset = true; + + // These settings from series has higher priority. + seriesLayoutBy = seriesLayoutBy || datasetOption.seriesLayoutBy; + sourceHeader == null && (sourceHeader = datasetOption.sourceHeader); + dimensionsDefine = dimensionsDefine || datasetOption.dimensions; + } + + var completeResult = completeBySourceData( + data, sourceFormat, seriesLayoutBy, sourceHeader, dimensionsDefine + ); + + // Note: dataset option does not have `encode`. + var encodeDefine = seriesOption.encode; + if (!encodeDefine && datasetModel) { + encodeDefine = makeDefaultEncode( + seriesModel, datasetModel, data, sourceFormat, seriesLayoutBy, completeResult + ); + } + + inner$3(seriesModel).source = new Source({ + data: data, + fromDataset: fromDataset, + seriesLayoutBy: seriesLayoutBy, + sourceFormat: sourceFormat, + dimensionsDefine: completeResult.dimensionsDefine, + startIndex: completeResult.startIndex, + dimensionsDetectCount: completeResult.dimensionsDetectCount, + encodeDefine: encodeDefine + }); +} + +// return {startIndex, dimensionsDefine, dimensionsCount} +function completeBySourceData(data, sourceFormat, seriesLayoutBy, sourceHeader, dimensionsDefine) { + if (!data) { + return {dimensionsDefine: normalizeDimensionsDefine(dimensionsDefine)}; + } + + var dimensionsDetectCount; + var startIndex; + var findPotentialName; + + if (sourceFormat === SOURCE_FORMAT_ARRAY_ROWS) { + // Rule: Most of the first line are string: it is header. + // Caution: consider a line with 5 string and 1 number, + // it still can not be sure it is a head, because the + // 5 string may be 5 values of category columns. + if (sourceHeader === 'auto' || sourceHeader == null) { + arrayRowsTravelFirst(function (val) { + // '-' is regarded as null/undefined. + if (val != null && val !== '-') { + if (isString(val)) { + startIndex == null && (startIndex = 1); + } + else { + startIndex = 0; + } + } + // 10 is an experience number, avoid long loop. + }, seriesLayoutBy, data, 10); + } + else { + startIndex = sourceHeader ? 1 : 0; + } + + if (!dimensionsDefine && startIndex === 1) { + dimensionsDefine = []; + arrayRowsTravelFirst(function (val, index) { + dimensionsDefine[index] = val != null ? val : ''; + }, seriesLayoutBy, data); + } + + dimensionsDetectCount = dimensionsDefine + ? dimensionsDefine.length + : seriesLayoutBy === SERIES_LAYOUT_BY_ROW + ? data.length + : data[0] + ? data[0].length + : null; + } + else if (sourceFormat === SOURCE_FORMAT_OBJECT_ROWS) { + if (!dimensionsDefine) { + dimensionsDefine = objectRowsCollectDimensions(data); + findPotentialName = true; + } + } + else if (sourceFormat === SOURCE_FORMAT_KEYED_COLUMNS) { + if (!dimensionsDefine) { + dimensionsDefine = []; + findPotentialName = true; + each$1(data, function (colArr, key) { + dimensionsDefine.push(key); + }); + } + } + else if (sourceFormat === SOURCE_FORMAT_ORIGINAL) { + var value0 = getDataItemValue(data[0]); + dimensionsDetectCount = isArray(value0) && value0.length || 1; + } + else if (sourceFormat === SOURCE_FORMAT_TYPED_ARRAY) { + if (__DEV__) { + assert$1(!!dimensionsDefine, 'dimensions must be given if data is TypedArray.'); + } + } + + var potentialNameDimIndex; + if (findPotentialName) { + each$1(dimensionsDefine, function (dim, idx) { + if ((isObject$1(dim) ? dim.name : dim) === 'name') { + potentialNameDimIndex = idx; + } + }); + } + + return { + startIndex: startIndex, + dimensionsDefine: normalizeDimensionsDefine(dimensionsDefine), + dimensionsDetectCount: dimensionsDetectCount, + potentialNameDimIndex: potentialNameDimIndex + // TODO: potentialIdDimIdx + }; +} + +// Consider dimensions defined like ['A', 'price', 'B', 'price', 'C', 'price'], +// which is reasonable. But dimension name is duplicated. +// Returns undefined or an array contains only object without null/undefiend or string. +function normalizeDimensionsDefine(dimensionsDefine) { + if (!dimensionsDefine) { + // The meaning of null/undefined is different from empty array. + return; + } + var nameMap = createHashMap(); + return map(dimensionsDefine, function (item, index) { + item = extend({}, isObject$1(item) ? item : {name: item}); + + // User can set null in dimensions. + // We dont auto specify name, othewise a given name may + // cause it be refered unexpectedly. + if (item.name == null) { + return item; + } + + // Also consider number form like 2012. + item.name += ''; + // User may also specify displayName. + // displayName will always exists except user not + // specified or dim name is not specified or detected. + // (A auto generated dim name will not be used as + // displayName). + if (item.displayName == null) { + item.displayName = item.name; + } + + var exist = nameMap.get(item.name); + if (!exist) { + nameMap.set(item.name, {count: 1}); + } + else { + item.name += '-' + exist.count++; + } + + return item; + }); +} + +function arrayRowsTravelFirst(cb, seriesLayoutBy, data, maxLoop) { + maxLoop == null && (maxLoop = Infinity); + if (seriesLayoutBy === SERIES_LAYOUT_BY_ROW) { + for (var i = 0; i < data.length && i < maxLoop; i++) { + cb(data[i] ? data[i][0] : null, i); + } + } + else { + var value0 = data[0] || []; + for (var i = 0; i < value0.length && i < maxLoop; i++) { + cb(value0[i], i); + } + } +} + +function objectRowsCollectDimensions(data) { + var firstIndex = 0; + var obj; + while (firstIndex < data.length && !(obj = data[firstIndex++])) {} // jshint ignore: line + if (obj) { + var dimensions = []; + each$1(obj, function (value, key) { + dimensions.push(key); + }); + return dimensions; + } +} + +// ??? TODO merge to completedimensions, where also has +// default encode making logic. And the default rule +// should depends on series? consider 'map'. +function makeDefaultEncode( + seriesModel, datasetModel, data, sourceFormat, seriesLayoutBy, completeResult +) { + var coordSysDefine = getCoordSysDefineBySeries(seriesModel); + var encode = {}; + // var encodeTooltip = []; + // var encodeLabel = []; + var encodeItemName = []; + var encodeSeriesName = []; + var seriesType = seriesModel.subType; + + // ??? TODO refactor: provide by series itself. + // Consider the case: 'map' series is based on geo coordSys, + // 'graph', 'heatmap' can be based on cartesian. But can not + // give default rule simply here. + var nSeriesMap = createHashMap(['pie', 'map', 'funnel']); + var cSeriesMap = createHashMap([ + 'line', 'bar', 'pictorialBar', 'scatter', 'effectScatter', 'candlestick', 'boxplot' + ]); + + // Usually in this case series will use the first data + // dimension as the "value" dimension, or other default + // processes respectively. + if (coordSysDefine && cSeriesMap.get(seriesType) != null) { + var ecModel = seriesModel.ecModel; + var datasetMap = inner$3(ecModel).datasetMap; + var key = datasetModel.uid + '_' + seriesLayoutBy; + var datasetRecord = datasetMap.get(key) + || datasetMap.set(key, {categoryWayDim: 1, valueWayDim: 0}); + + // TODO + // Auto detect first time axis and do arrangement. + each$1(coordSysDefine.coordSysDims, function (coordDim) { + // In value way. + if (coordSysDefine.firstCategoryDimIndex == null) { + var dataDim = datasetRecord.valueWayDim++; + encode[coordDim] = dataDim; + + // ??? TODO give a better default series name rule? + // especially when encode x y specified. + // consider: when mutiple series share one dimension + // category axis, series name should better use + // the other dimsion name. On the other hand, use + // both dimensions name. + + encodeSeriesName.push(dataDim); + // encodeTooltip.push(dataDim); + // encodeLabel.push(dataDim); + } + // In category way, category axis. + else if (coordSysDefine.categoryAxisMap.get(coordDim)) { + encode[coordDim] = 0; + encodeItemName.push(0); + } + // In category way, non-category axis. + else { + var dataDim = datasetRecord.categoryWayDim++; + encode[coordDim] = dataDim; + // encodeTooltip.push(dataDim); + // encodeLabel.push(dataDim); + encodeSeriesName.push(dataDim); + } + }); + } + // Do not make a complex rule! Hard to code maintain and not necessary. + // ??? TODO refactor: provide by series itself. + // [{name: ..., value: ...}, ...] like: + else if (nSeriesMap.get(seriesType) != null) { + // Find the first not ordinal. (5 is an experience value) + var firstNotOrdinal; + for (var i = 0; i < 5 && firstNotOrdinal == null; i++) { + if (!doGuessOrdinal( + data, sourceFormat, seriesLayoutBy, + completeResult.dimensionsDefine, completeResult.startIndex, i + )) { + firstNotOrdinal = i; + } + } + if (firstNotOrdinal != null) { + encode.value = firstNotOrdinal; + var nameDimIndex = completeResult.potentialNameDimIndex + || Math.max(firstNotOrdinal - 1, 0); + // By default, label use itemName in charts. + // So we dont set encodeLabel here. + encodeSeriesName.push(nameDimIndex); + encodeItemName.push(nameDimIndex); + // encodeTooltip.push(firstNotOrdinal); + } + } + + // encodeTooltip.length && (encode.tooltip = encodeTooltip); + // encodeLabel.length && (encode.label = encodeLabel); + encodeItemName.length && (encode.itemName = encodeItemName); + encodeSeriesName.length && (encode.seriesName = encodeSeriesName); + + return encode; +} + +/** + * If return null/undefined, indicate that should not use datasetModel. + */ +function getDatasetModel(seriesModel) { + var option = seriesModel.option; + // Caution: consider the scenario: + // A dataset is declared and a series is not expected to use the dataset, + // and at the beginning `setOption({series: { noData })` (just prepare other + // option but no data), then `setOption({series: {data: [...]}); In this case, + // the user should set an empty array to avoid that dataset is used by default. + var thisData = option.data; + if (!thisData) { + return seriesModel.ecModel.getComponent('dataset', option.datasetIndex || 0); + } +} + +/** + * The rule should not be complex, otherwise user might not + * be able to known where the data is wrong. + * The code is ugly, but how to make it neat? + * + * @param {module:echars/data/Source} source + * @param {number} dimIndex + * @return {boolean} Whether ordinal. + */ +function guessOrdinal(source, dimIndex) { + return doGuessOrdinal( + source.data, + source.sourceFormat, + source.seriesLayoutBy, + source.dimensionsDefine, + source.startIndex, + dimIndex + ); +} + +// dimIndex may be overflow source data. +function doGuessOrdinal( + data, sourceFormat, seriesLayoutBy, dimensionsDefine, startIndex, dimIndex +) { + var result; + // Experience value. + var maxLoop = 5; + + if (isTypedArray(data)) { + return false; + } + + // When sourceType is 'objectRows' or 'keyedColumns', dimensionsDefine + // always exists in source. + var dimName; + if (dimensionsDefine) { + dimName = dimensionsDefine[dimIndex]; + dimName = isObject$1(dimName) ? dimName.name : dimName; + } + + if (sourceFormat === SOURCE_FORMAT_ARRAY_ROWS) { + if (seriesLayoutBy === SERIES_LAYOUT_BY_ROW) { + var sample = data[dimIndex]; + for (var i = 0; i < (sample || []).length && i < maxLoop; i++) { + if ((result = detectValue(sample[startIndex + i])) != null) { + return result; + } + } + } + else { + for (var i = 0; i < data.length && i < maxLoop; i++) { + var row = data[startIndex + i]; + if (row && (result = detectValue(row[dimIndex])) != null) { + return result; + } + } + } + } + else if (sourceFormat === SOURCE_FORMAT_OBJECT_ROWS) { + if (!dimName) { + return; + } + for (var i = 0; i < data.length && i < maxLoop; i++) { + var item = data[i]; + if (item && (result = detectValue(item[dimName])) != null) { + return result; + } + } + } + else if (sourceFormat === SOURCE_FORMAT_KEYED_COLUMNS) { + if (!dimName) { + return; + } + var sample = data[dimName]; + if (!sample || isTypedArray(sample)) { + return false; + } + for (var i = 0; i < sample.length && i < maxLoop; i++) { + if ((result = detectValue(sample[i])) != null) { + return result; + } + } + } + else if (sourceFormat === SOURCE_FORMAT_ORIGINAL) { + for (var i = 0; i < data.length && i < maxLoop; i++) { + var item = data[i]; + var val = getDataItemValue(item); + if (!isArray(val)) { + return false; + } + if ((result = detectValue(val[dimIndex])) != null) { + return result; + } + } + } + + function detectValue(val) { + // Consider usage convenience, '1', '2' will be treated as "number". + // `isFinit('')` get `true`. + if (val != null && isFinite(val) && val !== '') { + return false; + } + else if (isString(val) && val !== '-') { + return true; + } + } + + return false; +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/** + * ECharts global model + * + * @module {echarts/model/Global} + */ + + +/** + * Caution: If the mechanism should be changed some day, these cases + * should be considered: + * + * (1) In `merge option` mode, if using the same option to call `setOption` + * many times, the result should be the same (try our best to ensure that). + * (2) In `merge option` mode, if a component has no id/name specified, it + * will be merged by index, and the result sequence of the components is + * consistent to the original sequence. + * (3) `reset` feature (in toolbox). Find detailed info in comments about + * `mergeOption` in module:echarts/model/OptionManager. + */ + +var OPTION_INNER_KEY = '\0_ec_inner'; + +/** + * @alias module:echarts/model/Global + * + * @param {Object} option + * @param {module:echarts/model/Model} parentModel + * @param {Object} theme + */ +var GlobalModel = Model.extend({ + + init: function (option, parentModel, theme, optionManager) { + theme = theme || {}; + + this.option = null; // Mark as not initialized. + + /** + * @type {module:echarts/model/Model} + * @private + */ + this._theme = new Model(theme); + + /** + * @type {module:echarts/model/OptionManager} + */ + this._optionManager = optionManager; + }, + + setOption: function (option, optionPreprocessorFuncs) { + assert$1( + !(OPTION_INNER_KEY in option), + 'please use chart.getOption()' + ); + + this._optionManager.setOption(option, optionPreprocessorFuncs); + + this.resetOption(null); + }, + + /** + * @param {string} type null/undefined: reset all. + * 'recreate': force recreate all. + * 'timeline': only reset timeline option + * 'media': only reset media query option + * @return {boolean} Whether option changed. + */ + resetOption: function (type) { + var optionChanged = false; + var optionManager = this._optionManager; + + if (!type || type === 'recreate') { + var baseOption = optionManager.mountOption(type === 'recreate'); + + if (!this.option || type === 'recreate') { + initBase.call(this, baseOption); + } + else { + this.restoreData(); + this.mergeOption(baseOption); + } + optionChanged = true; + } + + if (type === 'timeline' || type === 'media') { + this.restoreData(); + } + + if (!type || type === 'recreate' || type === 'timeline') { + var timelineOption = optionManager.getTimelineOption(this); + timelineOption && (this.mergeOption(timelineOption), optionChanged = true); + } + + if (!type || type === 'recreate' || type === 'media') { + var mediaOptions = optionManager.getMediaOption(this, this._api); + if (mediaOptions.length) { + each$1(mediaOptions, function (mediaOption) { + this.mergeOption(mediaOption, optionChanged = true); + }, this); + } + } + + return optionChanged; + }, + + /** + * @protected + */ + mergeOption: function (newOption) { + var option = this.option; + var componentsMap = this._componentsMap; + var newCptTypes = []; + + resetSourceDefaulter(this); + + // If no component class, merge directly. + // For example: color, animaiton options, etc. + each$1(newOption, function (componentOption, mainType) { + if (componentOption == null) { + return; + } + + if (!ComponentModel.hasClass(mainType)) { + // globalSettingTask.dirty(); + option[mainType] = option[mainType] == null + ? clone(componentOption) + : merge(option[mainType], componentOption, true); + } + else if (mainType) { + newCptTypes.push(mainType); + } + }); + + ComponentModel.topologicalTravel( + newCptTypes, ComponentModel.getAllClassMainTypes(), visitComponent, this + ); + + function visitComponent(mainType, dependencies) { + + var newCptOptionList = normalizeToArray(newOption[mainType]); + + var mapResult = mappingToExists( + componentsMap.get(mainType), newCptOptionList + ); + + makeIdAndName(mapResult); + + // Set mainType and complete subType. + each$1(mapResult, function (item, index) { + var opt = item.option; + if (isObject$1(opt)) { + item.keyInfo.mainType = mainType; + item.keyInfo.subType = determineSubType(mainType, opt, item.exist); + } + }); + + var dependentModels = getComponentsByTypes( + componentsMap, dependencies + ); + + option[mainType] = []; + componentsMap.set(mainType, []); + + each$1(mapResult, function (resultItem, index) { + var componentModel = resultItem.exist; + var newCptOption = resultItem.option; + + assert$1( + isObject$1(newCptOption) || componentModel, + 'Empty component definition' + ); + + // Consider where is no new option and should be merged using {}, + // see removeEdgeAndAdd in topologicalTravel and + // ComponentModel.getAllClassMainTypes. + if (!newCptOption) { + componentModel.mergeOption({}, this); + componentModel.optionUpdated({}, false); + } + else { + var ComponentModelClass = ComponentModel.getClass( + mainType, resultItem.keyInfo.subType, true + ); + + if (componentModel && componentModel instanceof ComponentModelClass) { + componentModel.name = resultItem.keyInfo.name; + // componentModel.settingTask && componentModel.settingTask.dirty(); + componentModel.mergeOption(newCptOption, this); + componentModel.optionUpdated(newCptOption, false); + } + else { + // PENDING Global as parent ? + var extraOpt = extend( + { + dependentModels: dependentModels, + componentIndex: index + }, + resultItem.keyInfo + ); + componentModel = new ComponentModelClass( + newCptOption, this, this, extraOpt + ); + extend(componentModel, extraOpt); + componentModel.init(newCptOption, this, this, extraOpt); + + // Call optionUpdated after init. + // newCptOption has been used as componentModel.option + // and may be merged with theme and default, so pass null + // to avoid confusion. + componentModel.optionUpdated(null, true); + } + } + + componentsMap.get(mainType)[index] = componentModel; + option[mainType][index] = componentModel.option; + }, this); + + // Backup series for filtering. + if (mainType === 'series') { + createSeriesIndices(this, componentsMap.get('series')); + } + } + + this._seriesIndicesMap = createHashMap( + this._seriesIndices = this._seriesIndices || [] + ); + }, + + /** + * Get option for output (cloned option and inner info removed) + * @public + * @return {Object} + */ + getOption: function () { + var option = clone(this.option); + + each$1(option, function (opts, mainType) { + if (ComponentModel.hasClass(mainType)) { + var opts = normalizeToArray(opts); + for (var i = opts.length - 1; i >= 0; i--) { + // Remove options with inner id. + if (isIdInner(opts[i])) { + opts.splice(i, 1); + } + } + option[mainType] = opts; + } + }); + + delete option[OPTION_INNER_KEY]; + + return option; + }, + + /** + * @return {module:echarts/model/Model} + */ + getTheme: function () { + return this._theme; + }, + + /** + * @param {string} mainType + * @param {number} [idx=0] + * @return {module:echarts/model/Component} + */ + getComponent: function (mainType, idx) { + var list = this._componentsMap.get(mainType); + if (list) { + return list[idx || 0]; + } + }, + + /** + * If none of index and id and name used, return all components with mainType. + * @param {Object} condition + * @param {string} condition.mainType + * @param {string} [condition.subType] If ignore, only query by mainType + * @param {number|Array.} [condition.index] Either input index or id or name. + * @param {string|Array.} [condition.id] Either input index or id or name. + * @param {string|Array.} [condition.name] Either input index or id or name. + * @return {Array.} + */ + queryComponents: function (condition) { + var mainType = condition.mainType; + if (!mainType) { + return []; + } + + var index = condition.index; + var id = condition.id; + var name = condition.name; + + var cpts = this._componentsMap.get(mainType); + + if (!cpts || !cpts.length) { + return []; + } + + var result; + + if (index != null) { + if (!isArray(index)) { + index = [index]; + } + result = filter(map(index, function (idx) { + return cpts[idx]; + }), function (val) { + return !!val; + }); + } + else if (id != null) { + var isIdArray = isArray(id); + result = filter(cpts, function (cpt) { + return (isIdArray && indexOf(id, cpt.id) >= 0) + || (!isIdArray && cpt.id === id); + }); + } + else if (name != null) { + var isNameArray = isArray(name); + result = filter(cpts, function (cpt) { + return (isNameArray && indexOf(name, cpt.name) >= 0) + || (!isNameArray && cpt.name === name); + }); + } + else { + // Return all components with mainType + result = cpts.slice(); + } + + return filterBySubType(result, condition); + }, + + /** + * The interface is different from queryComponents, + * which is convenient for inner usage. + * + * @usage + * var result = findComponents( + * {mainType: 'dataZoom', query: {dataZoomId: 'abc'}} + * ); + * var result = findComponents( + * {mainType: 'series', subType: 'pie', query: {seriesName: 'uio'}} + * ); + * var result = findComponents( + * {mainType: 'series'}, + * function (model, index) {...} + * ); + * // result like [component0, componnet1, ...] + * + * @param {Object} condition + * @param {string} condition.mainType Mandatory. + * @param {string} [condition.subType] Optional. + * @param {Object} [condition.query] like {xxxIndex, xxxId, xxxName}, + * where xxx is mainType. + * If query attribute is null/undefined or has no index/id/name, + * do not filtering by query conditions, which is convenient for + * no-payload situations or when target of action is global. + * @param {Function} [condition.filter] parameter: component, return boolean. + * @return {Array.} + */ + findComponents: function (condition) { + var query = condition.query; + var mainType = condition.mainType; + + var queryCond = getQueryCond(query); + var result = queryCond + ? this.queryComponents(queryCond) + : this._componentsMap.get(mainType); + + return doFilter(filterBySubType(result, condition)); + + function getQueryCond(q) { + var indexAttr = mainType + 'Index'; + var idAttr = mainType + 'Id'; + var nameAttr = mainType + 'Name'; + return q && ( + q[indexAttr] != null + || q[idAttr] != null + || q[nameAttr] != null + ) + ? { + mainType: mainType, + // subType will be filtered finally. + index: q[indexAttr], + id: q[idAttr], + name: q[nameAttr] + } + : null; + } + + function doFilter(res) { + return condition.filter + ? filter(res, condition.filter) + : res; + } + }, + + /** + * @usage + * eachComponent('legend', function (legendModel, index) { + * ... + * }); + * eachComponent(function (componentType, model, index) { + * // componentType does not include subType + * // (componentType is 'xxx' but not 'xxx.aa') + * }); + * eachComponent( + * {mainType: 'dataZoom', query: {dataZoomId: 'abc'}}, + * function (model, index) {...} + * ); + * eachComponent( + * {mainType: 'series', subType: 'pie', query: {seriesName: 'uio'}}, + * function (model, index) {...} + * ); + * + * @param {string|Object=} mainType When mainType is object, the definition + * is the same as the method 'findComponents'. + * @param {Function} cb + * @param {*} context + */ + eachComponent: function (mainType, cb, context) { + var componentsMap = this._componentsMap; + + if (typeof mainType === 'function') { + context = cb; + cb = mainType; + componentsMap.each(function (components, componentType) { + each$1(components, function (component, index) { + cb.call(context, componentType, component, index); + }); + }); + } + else if (isString(mainType)) { + each$1(componentsMap.get(mainType), cb, context); + } + else if (isObject$1(mainType)) { + var queryResult = this.findComponents(mainType); + each$1(queryResult, cb, context); + } + }, + + /** + * @param {string} name + * @return {Array.} + */ + getSeriesByName: function (name) { + var series = this._componentsMap.get('series'); + return filter(series, function (oneSeries) { + return oneSeries.name === name; + }); + }, + + /** + * @param {number} seriesIndex + * @return {module:echarts/model/Series} + */ + getSeriesByIndex: function (seriesIndex) { + return this._componentsMap.get('series')[seriesIndex]; + }, + + /** + * Get series list before filtered by type. + * FIXME: rename to getRawSeriesByType? + * + * @param {string} subType + * @return {Array.} + */ + getSeriesByType: function (subType) { + var series = this._componentsMap.get('series'); + return filter(series, function (oneSeries) { + return oneSeries.subType === subType; + }); + }, + + /** + * @return {Array.} + */ + getSeries: function () { + return this._componentsMap.get('series').slice(); + }, + + /** + * @return {number} + */ + getSeriesCount: function () { + return this._componentsMap.get('series').length; + }, + + /** + * After filtering, series may be different + * frome raw series. + * + * @param {Function} cb + * @param {*} context + */ + eachSeries: function (cb, context) { + assertSeriesInitialized(this); + each$1(this._seriesIndices, function (rawSeriesIndex) { + var series = this._componentsMap.get('series')[rawSeriesIndex]; + cb.call(context, series, rawSeriesIndex); + }, this); + }, + + /** + * Iterate raw series before filtered. + * + * @param {Function} cb + * @param {*} context + */ + eachRawSeries: function (cb, context) { + each$1(this._componentsMap.get('series'), cb, context); + }, + + /** + * After filtering, series may be different. + * frome raw series. + * + * @parma {string} subType + * @param {Function} cb + * @param {*} context + */ + eachSeriesByType: function (subType, cb, context) { + assertSeriesInitialized(this); + each$1(this._seriesIndices, function (rawSeriesIndex) { + var series = this._componentsMap.get('series')[rawSeriesIndex]; + if (series.subType === subType) { + cb.call(context, series, rawSeriesIndex); + } + }, this); + }, + + /** + * Iterate raw series before filtered of given type. + * + * @parma {string} subType + * @param {Function} cb + * @param {*} context + */ + eachRawSeriesByType: function (subType, cb, context) { + return each$1(this.getSeriesByType(subType), cb, context); + }, + + /** + * @param {module:echarts/model/Series} seriesModel + */ + isSeriesFiltered: function (seriesModel) { + assertSeriesInitialized(this); + return this._seriesIndicesMap.get(seriesModel.componentIndex) == null; + }, + + /** + * @return {Array.} + */ + getCurrentSeriesIndices: function () { + return (this._seriesIndices || []).slice(); + }, + + /** + * @param {Function} cb + * @param {*} context + */ + filterSeries: function (cb, context) { + assertSeriesInitialized(this); + var filteredSeries = filter( + this._componentsMap.get('series'), cb, context + ); + createSeriesIndices(this, filteredSeries); + }, + + restoreData: function (payload) { + var componentsMap = this._componentsMap; + + createSeriesIndices(this, componentsMap.get('series')); + + var componentTypes = []; + componentsMap.each(function (components, componentType) { + componentTypes.push(componentType); + }); + + ComponentModel.topologicalTravel( + componentTypes, + ComponentModel.getAllClassMainTypes(), + function (componentType, dependencies) { + each$1(componentsMap.get(componentType), function (component) { + (componentType !== 'series' || !isNotTargetSeries(component, payload)) + && component.restoreData(); + }); + } + ); + } + +}); + +function isNotTargetSeries(seriesModel, payload) { + if (payload) { + var index = payload.seiresIndex; + var id = payload.seriesId; + var name = payload.seriesName; + return (index != null && seriesModel.componentIndex !== index) + || (id != null && seriesModel.id !== id) + || (name != null && seriesModel.name !== name); + } +} + +/** + * @inner + */ +function mergeTheme(option, theme) { + // PENDING + // NOT use `colorLayer` in theme if option has `color` + var notMergeColorLayer = option.color && !option.colorLayer; + + each$1(theme, function (themeItem, name) { + if (name === 'colorLayer' && notMergeColorLayer) { + return; + } + // 如果有 component model 则把具体的 merge 逻辑交给该 model 处理 + if (!ComponentModel.hasClass(name)) { + if (typeof themeItem === 'object') { + option[name] = !option[name] + ? clone(themeItem) + : merge(option[name], themeItem, false); + } + else { + if (option[name] == null) { + option[name] = themeItem; + } + } + } + }); +} + +function initBase(baseOption) { + baseOption = baseOption; + + // Using OPTION_INNER_KEY to mark that this option can not be used outside, + // i.e. `chart.setOption(chart.getModel().option);` is forbiden. + this.option = {}; + this.option[OPTION_INNER_KEY] = 1; + + /** + * Init with series: [], in case of calling findSeries method + * before series initialized. + * @type {Object.>} + * @private + */ + this._componentsMap = createHashMap({series: []}); + + /** + * Mapping between filtered series list and raw series list. + * key: filtered series indices, value: raw series indices. + * @type {Array.} + * @private + */ + this._seriesIndices; + + this._seriesIndicesMap; + + mergeTheme(baseOption, this._theme.option); + + // TODO Needs clone when merging to the unexisted property + merge(baseOption, globalDefault, false); + + this.mergeOption(baseOption); +} + +/** + * @inner + * @param {Array.|string} types model types + * @return {Object} key: {string} type, value: {Array.} models + */ +function getComponentsByTypes(componentsMap, types) { + if (!isArray(types)) { + types = types ? [types] : []; + } + + var ret = {}; + each$1(types, function (type) { + ret[type] = (componentsMap.get(type) || []).slice(); + }); + + return ret; +} + +/** + * @inner + */ +function determineSubType(mainType, newCptOption, existComponent) { + var subType = newCptOption.type + ? newCptOption.type + : existComponent + ? existComponent.subType + // Use determineSubType only when there is no existComponent. + : ComponentModel.determineSubType(mainType, newCptOption); + + // tooltip, markline, markpoint may always has no subType + return subType; +} + +/** + * @inner + */ +function createSeriesIndices(ecModel, seriesModels) { + ecModel._seriesIndicesMap = createHashMap( + ecModel._seriesIndices = map(seriesModels, function (series) { + return series.componentIndex; + }) || [] + ); +} + +/** + * @inner + */ +function filterBySubType(components, condition) { + // Using hasOwnProperty for restrict. Consider + // subType is undefined in user payload. + return condition.hasOwnProperty('subType') + ? filter(components, function (cpt) { + return cpt.subType === condition.subType; + }) + : components; +} + +/** + * @inner + */ +function assertSeriesInitialized(ecModel) { + // Components that use _seriesIndices should depends on series component, + // which make sure that their initialization is after series. + if (__DEV__) { + if (!ecModel._seriesIndices) { + throw new Error('Option should contains series.'); + } + } +} + +mixin(GlobalModel, colorPaletteMixin); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var echartsAPIList = [ + 'getDom', 'getZr', 'getWidth', 'getHeight', 'getDevicePixelRatio', 'dispatchAction', 'isDisposed', + 'on', 'off', 'getDataURL', 'getConnectedDataURL', 'getModel', 'getOption', + 'getViewOfComponentModel', 'getViewOfSeriesModel' +]; +// And `getCoordinateSystems` and `getComponentByElement` will be injected in echarts.js + +function ExtensionAPI(chartInstance) { + each$1(echartsAPIList, function (name) { + this[name] = bind(chartInstance[name], chartInstance); + }, this); +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var coordinateSystemCreators = {}; + +function CoordinateSystemManager() { + + this._coordinateSystems = []; +} + +CoordinateSystemManager.prototype = { + + constructor: CoordinateSystemManager, + + create: function (ecModel, api) { + var coordinateSystems = []; + each$1(coordinateSystemCreators, function (creater, type) { + var list = creater.create(ecModel, api); + coordinateSystems = coordinateSystems.concat(list || []); + }); + + this._coordinateSystems = coordinateSystems; + }, + + update: function (ecModel, api) { + each$1(this._coordinateSystems, function (coordSys) { + coordSys.update && coordSys.update(ecModel, api); + }); + }, + + getCoordinateSystems: function () { + return this._coordinateSystems.slice(); + } +}; + +CoordinateSystemManager.register = function (type, coordinateSystemCreator) { + coordinateSystemCreators[type] = coordinateSystemCreator; +}; + +CoordinateSystemManager.get = function (type) { + return coordinateSystemCreators[type]; +}; + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/** + * ECharts option manager + * + * @module {echarts/model/OptionManager} + */ + + +var each$4 = each$1; +var clone$3 = clone; +var map$1 = map; +var merge$1 = merge; + +var QUERY_REG = /^(min|max)?(.+)$/; + +/** + * TERM EXPLANATIONS: + * + * [option]: + * + * An object that contains definitions of components. For example: + * var option = { + * title: {...}, + * legend: {...}, + * visualMap: {...}, + * series: [ + * {data: [...]}, + * {data: [...]}, + * ... + * ] + * }; + * + * [rawOption]: + * + * An object input to echarts.setOption. 'rawOption' may be an + * 'option', or may be an object contains multi-options. For example: + * var option = { + * baseOption: { + * title: {...}, + * legend: {...}, + * series: [ + * {data: [...]}, + * {data: [...]}, + * ... + * ] + * }, + * timeline: {...}, + * options: [ + * {title: {...}, series: {data: [...]}}, + * {title: {...}, series: {data: [...]}}, + * ... + * ], + * media: [ + * { + * query: {maxWidth: 320}, + * option: {series: {x: 20}, visualMap: {show: false}} + * }, + * { + * query: {minWidth: 320, maxWidth: 720}, + * option: {series: {x: 500}, visualMap: {show: true}} + * }, + * { + * option: {series: {x: 1200}, visualMap: {show: true}} + * } + * ] + * }; + * + * @alias module:echarts/model/OptionManager + * @param {module:echarts/ExtensionAPI} api + */ +function OptionManager(api) { + + /** + * @private + * @type {module:echarts/ExtensionAPI} + */ + this._api = api; + + /** + * @private + * @type {Array.} + */ + this._timelineOptions = []; + + /** + * @private + * @type {Array.} + */ + this._mediaList = []; + + /** + * @private + * @type {Object} + */ + this._mediaDefault; + + /** + * -1, means default. + * empty means no media. + * @private + * @type {Array.} + */ + this._currentMediaIndices = []; + + /** + * @private + * @type {Object} + */ + this._optionBackup; + + /** + * @private + * @type {Object} + */ + this._newBaseOption; +} + +// timeline.notMerge is not supported in ec3. Firstly there is rearly +// case that notMerge is needed. Secondly supporting 'notMerge' requires +// rawOption cloned and backuped when timeline changed, which does no +// good to performance. What's more, that both timeline and setOption +// method supply 'notMerge' brings complex and some problems. +// Consider this case: +// (step1) chart.setOption({timeline: {notMerge: false}, ...}, false); +// (step2) chart.setOption({timeline: {notMerge: true}, ...}, false); + +OptionManager.prototype = { + + constructor: OptionManager, + + /** + * @public + * @param {Object} rawOption Raw option. + * @param {module:echarts/model/Global} ecModel + * @param {Array.} optionPreprocessorFuncs + * @return {Object} Init option + */ + setOption: function (rawOption, optionPreprocessorFuncs) { + if (rawOption) { + // That set dat primitive is dangerous if user reuse the data when setOption again. + each$1(normalizeToArray(rawOption.series), function (series) { + series && series.data && isTypedArray(series.data) && setAsPrimitive(series.data); + }); + } + + // Caution: some series modify option data, if do not clone, + // it should ensure that the repeat modify correctly + // (create a new object when modify itself). + rawOption = clone$3(rawOption, true); + + // FIXME + // 如果 timeline options 或者 media 中设置了某个属性,而baseOption中没有设置,则进行警告。 + + var oldOptionBackup = this._optionBackup; + var newParsedOption = parseRawOption.call( + this, rawOption, optionPreprocessorFuncs, !oldOptionBackup + ); + this._newBaseOption = newParsedOption.baseOption; + + // For setOption at second time (using merge mode); + if (oldOptionBackup) { + // Only baseOption can be merged. + mergeOption(oldOptionBackup.baseOption, newParsedOption.baseOption); + + // For simplicity, timeline options and media options do not support merge, + // that is, if you `setOption` twice and both has timeline options, the latter + // timeline opitons will not be merged to the formers, but just substitude them. + if (newParsedOption.timelineOptions.length) { + oldOptionBackup.timelineOptions = newParsedOption.timelineOptions; + } + if (newParsedOption.mediaList.length) { + oldOptionBackup.mediaList = newParsedOption.mediaList; + } + if (newParsedOption.mediaDefault) { + oldOptionBackup.mediaDefault = newParsedOption.mediaDefault; + } + } + else { + this._optionBackup = newParsedOption; + } + }, + + /** + * @param {boolean} isRecreate + * @return {Object} + */ + mountOption: function (isRecreate) { + var optionBackup = this._optionBackup; + + // TODO + // 如果没有reset功能则不clone。 + + this._timelineOptions = map$1(optionBackup.timelineOptions, clone$3); + this._mediaList = map$1(optionBackup.mediaList, clone$3); + this._mediaDefault = clone$3(optionBackup.mediaDefault); + this._currentMediaIndices = []; + + return clone$3(isRecreate + // this._optionBackup.baseOption, which is created at the first `setOption` + // called, and is merged into every new option by inner method `mergeOption` + // each time `setOption` called, can be only used in `isRecreate`, because + // its reliability is under suspicion. In other cases option merge is + // performed by `model.mergeOption`. + ? optionBackup.baseOption : this._newBaseOption + ); + }, + + /** + * @param {module:echarts/model/Global} ecModel + * @return {Object} + */ + getTimelineOption: function (ecModel) { + var option; + var timelineOptions = this._timelineOptions; + + if (timelineOptions.length) { + // getTimelineOption can only be called after ecModel inited, + // so we can get currentIndex from timelineModel. + var timelineModel = ecModel.getComponent('timeline'); + if (timelineModel) { + option = clone$3( + timelineOptions[timelineModel.getCurrentIndex()], + true + ); + } + } + + return option; + }, + + /** + * @param {module:echarts/model/Global} ecModel + * @return {Array.} + */ + getMediaOption: function (ecModel) { + var ecWidth = this._api.getWidth(); + var ecHeight = this._api.getHeight(); + var mediaList = this._mediaList; + var mediaDefault = this._mediaDefault; + var indices = []; + var result = []; + + // No media defined. + if (!mediaList.length && !mediaDefault) { + return result; + } + + // Multi media may be applied, the latter defined media has higher priority. + for (var i = 0, len = mediaList.length; i < len; i++) { + if (applyMediaQuery(mediaList[i].query, ecWidth, ecHeight)) { + indices.push(i); + } + } + + // FIXME + // 是否mediaDefault应该强制用户设置,否则可能修改不能回归。 + if (!indices.length && mediaDefault) { + indices = [-1]; + } + + if (indices.length && !indicesEquals(indices, this._currentMediaIndices)) { + result = map$1(indices, function (index) { + return clone$3( + index === -1 ? mediaDefault.option : mediaList[index].option + ); + }); + } + // Otherwise return nothing. + + this._currentMediaIndices = indices; + + return result; + } +}; + +function parseRawOption(rawOption, optionPreprocessorFuncs, isNew) { + var timelineOptions = []; + var mediaList = []; + var mediaDefault; + var baseOption; + + // Compatible with ec2. + var timelineOpt = rawOption.timeline; + + if (rawOption.baseOption) { + baseOption = rawOption.baseOption; + } + + // For timeline + if (timelineOpt || rawOption.options) { + baseOption = baseOption || {}; + timelineOptions = (rawOption.options || []).slice(); + } + + // For media query + if (rawOption.media) { + baseOption = baseOption || {}; + var media = rawOption.media; + each$4(media, function (singleMedia) { + if (singleMedia && singleMedia.option) { + if (singleMedia.query) { + mediaList.push(singleMedia); + } + else if (!mediaDefault) { + // Use the first media default. + mediaDefault = singleMedia; + } + } + }); + } + + // For normal option + if (!baseOption) { + baseOption = rawOption; + } + + // Set timelineOpt to baseOption in ec3, + // which is convenient for merge option. + if (!baseOption.timeline) { + baseOption.timeline = timelineOpt; + } + + // Preprocess. + each$4([baseOption].concat(timelineOptions) + .concat(map(mediaList, function (media) { + return media.option; + })), + function (option) { + each$4(optionPreprocessorFuncs, function (preProcess) { + preProcess(option, isNew); + }); + } + ); + + return { + baseOption: baseOption, + timelineOptions: timelineOptions, + mediaDefault: mediaDefault, + mediaList: mediaList + }; +} + +/** + * @see + * Support: width, height, aspectRatio + * Can use max or min as prefix. + */ +function applyMediaQuery(query, ecWidth, ecHeight) { + var realMap = { + width: ecWidth, + height: ecHeight, + aspectratio: ecWidth / ecHeight // lowser case for convenientce. + }; + + var applicatable = true; + + each$1(query, function (value, attr) { + var matched = attr.match(QUERY_REG); + + if (!matched || !matched[1] || !matched[2]) { + return; + } + + var operator = matched[1]; + var realAttr = matched[2].toLowerCase(); + + if (!compare(realMap[realAttr], value, operator)) { + applicatable = false; + } + }); + + return applicatable; +} + +function compare(real, expect, operator) { + if (operator === 'min') { + return real >= expect; + } + else if (operator === 'max') { + return real <= expect; + } + else { // Equals + return real === expect; + } +} + +function indicesEquals(indices1, indices2) { + // indices is always order by asc and has only finite number. + return indices1.join(',') === indices2.join(','); +} + +/** + * Consider case: + * `chart.setOption(opt1);` + * Then user do some interaction like dataZoom, dataView changing. + * `chart.setOption(opt2);` + * Then user press 'reset button' in toolbox. + * + * After doing that all of the interaction effects should be reset, the + * chart should be the same as the result of invoke + * `chart.setOption(opt1); chart.setOption(opt2);`. + * + * Although it is not able ensure that + * `chart.setOption(opt1); chart.setOption(opt2);` is equivalents to + * `chart.setOption(merge(opt1, opt2));` exactly, + * this might be the only simple way to implement that feature. + * + * MEMO: We've considered some other approaches: + * 1. Each model handle its self restoration but not uniform treatment. + * (Too complex in logic and error-prone) + * 2. Use a shadow ecModel. (Performace expensive) + */ +function mergeOption(oldOption, newOption) { + newOption = newOption || {}; + + each$4(newOption, function (newCptOpt, mainType) { + if (newCptOpt == null) { + return; + } + + var oldCptOpt = oldOption[mainType]; + + if (!ComponentModel.hasClass(mainType)) { + oldOption[mainType] = merge$1(oldCptOpt, newCptOpt, true); + } + else { + newCptOpt = normalizeToArray(newCptOpt); + oldCptOpt = normalizeToArray(oldCptOpt); + + var mapResult = mappingToExists(oldCptOpt, newCptOpt); + + oldOption[mainType] = map$1(mapResult, function (item) { + return (item.option && item.exist) + ? merge$1(item.exist, item.option, true) + : (item.exist || item.option); + }); + } + }); +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var each$5 = each$1; +var isObject$3 = isObject$1; + +var POSSIBLE_STYLES = [ + 'areaStyle', 'lineStyle', 'nodeStyle', 'linkStyle', + 'chordStyle', 'label', 'labelLine' +]; + +function compatEC2ItemStyle(opt) { + var itemStyleOpt = opt && opt.itemStyle; + if (!itemStyleOpt) { + return; + } + for (var i = 0, len = POSSIBLE_STYLES.length; i < len; i++) { + var styleName = POSSIBLE_STYLES[i]; + var normalItemStyleOpt = itemStyleOpt.normal; + var emphasisItemStyleOpt = itemStyleOpt.emphasis; + if (normalItemStyleOpt && normalItemStyleOpt[styleName]) { + opt[styleName] = opt[styleName] || {}; + if (!opt[styleName].normal) { + opt[styleName].normal = normalItemStyleOpt[styleName]; + } + else { + merge(opt[styleName].normal, normalItemStyleOpt[styleName]); + } + normalItemStyleOpt[styleName] = null; + } + if (emphasisItemStyleOpt && emphasisItemStyleOpt[styleName]) { + opt[styleName] = opt[styleName] || {}; + if (!opt[styleName].emphasis) { + opt[styleName].emphasis = emphasisItemStyleOpt[styleName]; + } + else { + merge(opt[styleName].emphasis, emphasisItemStyleOpt[styleName]); + } + emphasisItemStyleOpt[styleName] = null; + } + } +} + +function convertNormalEmphasis(opt, optType, useExtend) { + if (opt && opt[optType] && (opt[optType].normal || opt[optType].emphasis)) { + var normalOpt = opt[optType].normal; + var emphasisOpt = opt[optType].emphasis; + + if (normalOpt) { + // Timeline controlStyle has other properties besides normal and emphasis + if (useExtend) { + opt[optType].normal = opt[optType].emphasis = null; + defaults(opt[optType], normalOpt); + } + else { + opt[optType] = normalOpt; + } + } + if (emphasisOpt) { + opt.emphasis = opt.emphasis || {}; + opt.emphasis[optType] = emphasisOpt; + } + } +} +function removeEC3NormalStatus(opt) { + convertNormalEmphasis(opt, 'itemStyle'); + convertNormalEmphasis(opt, 'lineStyle'); + convertNormalEmphasis(opt, 'areaStyle'); + convertNormalEmphasis(opt, 'label'); + convertNormalEmphasis(opt, 'labelLine'); + // treemap + convertNormalEmphasis(opt, 'upperLabel'); + // graph + convertNormalEmphasis(opt, 'edgeLabel'); +} + +function compatTextStyle(opt, propName) { + // Check whether is not object (string\null\undefined ...) + var labelOptSingle = isObject$3(opt) && opt[propName]; + var textStyle = isObject$3(labelOptSingle) && labelOptSingle.textStyle; + if (textStyle) { + for (var i = 0, len = TEXT_STYLE_OPTIONS.length; i < len; i++) { + var propName = TEXT_STYLE_OPTIONS[i]; + if (textStyle.hasOwnProperty(propName)) { + labelOptSingle[propName] = textStyle[propName]; + } + } + } +} + +function compatEC3CommonStyles(opt) { + if (opt) { + removeEC3NormalStatus(opt); + compatTextStyle(opt, 'label'); + opt.emphasis && compatTextStyle(opt.emphasis, 'label'); + } +} + +function processSeries(seriesOpt) { + if (!isObject$3(seriesOpt)) { + return; + } + + compatEC2ItemStyle(seriesOpt); + removeEC3NormalStatus(seriesOpt); + + compatTextStyle(seriesOpt, 'label'); + // treemap + compatTextStyle(seriesOpt, 'upperLabel'); + // graph + compatTextStyle(seriesOpt, 'edgeLabel'); + if (seriesOpt.emphasis) { + compatTextStyle(seriesOpt.emphasis, 'label'); + // treemap + compatTextStyle(seriesOpt.emphasis, 'upperLabel'); + // graph + compatTextStyle(seriesOpt.emphasis, 'edgeLabel'); + } + + var markPoint = seriesOpt.markPoint; + if (markPoint) { + compatEC2ItemStyle(markPoint); + compatEC3CommonStyles(markPoint); + } + + var markLine = seriesOpt.markLine; + if (markLine) { + compatEC2ItemStyle(markLine); + compatEC3CommonStyles(markLine); + } + + var markArea = seriesOpt.markArea; + if (markArea) { + compatEC3CommonStyles(markArea); + } + + var data = seriesOpt.data; + + // Break with ec3: if `setOption` again, there may be no `type` in option, + // then the backward compat based on option type will not be performed. + + if (seriesOpt.type === 'graph') { + data = data || seriesOpt.nodes; + var edgeData = seriesOpt.links || seriesOpt.edges; + if (edgeData && !isTypedArray(edgeData)) { + for (var i = 0; i < edgeData.length; i++) { + compatEC3CommonStyles(edgeData[i]); + } + } + each$1(seriesOpt.categories, function (opt) { + removeEC3NormalStatus(opt); + }); + } + + if (data && !isTypedArray(data)) { + for (var i = 0; i < data.length; i++) { + compatEC3CommonStyles(data[i]); + } + } + + // mark point data + var markPoint = seriesOpt.markPoint; + if (markPoint && markPoint.data) { + var mpData = markPoint.data; + for (var i = 0; i < mpData.length; i++) { + compatEC3CommonStyles(mpData[i]); + } + } + // mark line data + var markLine = seriesOpt.markLine; + if (markLine && markLine.data) { + var mlData = markLine.data; + for (var i = 0; i < mlData.length; i++) { + if (isArray(mlData[i])) { + compatEC3CommonStyles(mlData[i][0]); + compatEC3CommonStyles(mlData[i][1]); + } + else { + compatEC3CommonStyles(mlData[i]); + } + } + } + + // Series + if (seriesOpt.type === 'gauge') { + compatTextStyle(seriesOpt, 'axisLabel'); + compatTextStyle(seriesOpt, 'title'); + compatTextStyle(seriesOpt, 'detail'); + } + else if (seriesOpt.type === 'treemap') { + convertNormalEmphasis(seriesOpt.breadcrumb, 'itemStyle'); + each$1(seriesOpt.levels, function (opt) { + removeEC3NormalStatus(opt); + }); + } + else if (seriesOpt.type === 'tree') { + removeEC3NormalStatus(seriesOpt.leaves); + } + // sunburst starts from ec4, so it does not need to compat levels. +} + +function toArr(o) { + return isArray(o) ? o : o ? [o] : []; +} + +function toObj(o) { + return (isArray(o) ? o[0] : o) || {}; +} + +var compatStyle = function (option, isTheme) { + each$5(toArr(option.series), function (seriesOpt) { + isObject$3(seriesOpt) && processSeries(seriesOpt); + }); + + var axes = ['xAxis', 'yAxis', 'radiusAxis', 'angleAxis', 'singleAxis', 'parallelAxis', 'radar']; + isTheme && axes.push('valueAxis', 'categoryAxis', 'logAxis', 'timeAxis'); + + each$5( + axes, + function (axisName) { + each$5(toArr(option[axisName]), function (axisOpt) { + if (axisOpt) { + compatTextStyle(axisOpt, 'axisLabel'); + compatTextStyle(axisOpt.axisPointer, 'label'); + } + }); + } + ); + + each$5(toArr(option.parallel), function (parallelOpt) { + var parallelAxisDefault = parallelOpt && parallelOpt.parallelAxisDefault; + compatTextStyle(parallelAxisDefault, 'axisLabel'); + compatTextStyle(parallelAxisDefault && parallelAxisDefault.axisPointer, 'label'); + }); + + each$5(toArr(option.calendar), function (calendarOpt) { + convertNormalEmphasis(calendarOpt, 'itemStyle'); + compatTextStyle(calendarOpt, 'dayLabel'); + compatTextStyle(calendarOpt, 'monthLabel'); + compatTextStyle(calendarOpt, 'yearLabel'); + }); + + // radar.name.textStyle + each$5(toArr(option.radar), function (radarOpt) { + compatTextStyle(radarOpt, 'name'); + }); + + each$5(toArr(option.geo), function (geoOpt) { + if (isObject$3(geoOpt)) { + compatEC3CommonStyles(geoOpt); + each$5(toArr(geoOpt.regions), function (regionObj) { + compatEC3CommonStyles(regionObj); + }); + } + }); + + each$5(toArr(option.timeline), function (timelineOpt) { + compatEC3CommonStyles(timelineOpt); + convertNormalEmphasis(timelineOpt, 'label'); + convertNormalEmphasis(timelineOpt, 'itemStyle'); + convertNormalEmphasis(timelineOpt, 'controlStyle', true); + + var data = timelineOpt.data; + isArray(data) && each$1(data, function (item) { + if (isObject$1(item)) { + convertNormalEmphasis(item, 'label'); + convertNormalEmphasis(item, 'itemStyle'); + } + }); + }); + + each$5(toArr(option.toolbox), function (toolboxOpt) { + convertNormalEmphasis(toolboxOpt, 'iconStyle'); + each$5(toolboxOpt.feature, function (featureOpt) { + convertNormalEmphasis(featureOpt, 'iconStyle'); + }); + }); + + compatTextStyle(toObj(option.axisPointer), 'label'); + compatTextStyle(toObj(option.tooltip).axisPointer, 'label'); +}; + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +// Compatitable with 2.0 + +function get(opt, path) { + path = path.split(','); + var obj = opt; + for (var i = 0; i < path.length; i++) { + obj = obj && obj[path[i]]; + if (obj == null) { + break; + } + } + return obj; +} + +function set$1(opt, path, val, overwrite) { + path = path.split(','); + var obj = opt; + var key; + for (var i = 0; i < path.length - 1; i++) { + key = path[i]; + if (obj[key] == null) { + obj[key] = {}; + } + obj = obj[key]; + } + if (overwrite || obj[path[i]] == null) { + obj[path[i]] = val; + } +} + +function compatLayoutProperties(option) { + each$1(LAYOUT_PROPERTIES, function (prop) { + if (prop[0] in option && !(prop[1] in option)) { + option[prop[1]] = option[prop[0]]; + } + }); +} + +var LAYOUT_PROPERTIES = [ + ['x', 'left'], ['y', 'top'], ['x2', 'right'], ['y2', 'bottom'] +]; + +var COMPATITABLE_COMPONENTS = [ + 'grid', 'geo', 'parallel', 'legend', 'toolbox', 'title', 'visualMap', 'dataZoom', 'timeline' +]; + +var backwardCompat = function (option, isTheme) { + compatStyle(option, isTheme); + + // Make sure series array for model initialization. + option.series = normalizeToArray(option.series); + + each$1(option.series, function (seriesOpt) { + if (!isObject$1(seriesOpt)) { + return; + } + + var seriesType = seriesOpt.type; + + if (seriesType === 'pie' || seriesType === 'gauge') { + if (seriesOpt.clockWise != null) { + seriesOpt.clockwise = seriesOpt.clockWise; + } + } + if (seriesType === 'gauge') { + var pointerColor = get(seriesOpt, 'pointer.color'); + pointerColor != null + && set$1(seriesOpt, 'itemStyle.normal.color', pointerColor); + } + + compatLayoutProperties(seriesOpt); + }); + + // dataRange has changed to visualMap + if (option.dataRange) { + option.visualMap = option.dataRange; + } + + each$1(COMPATITABLE_COMPONENTS, function (componentName) { + var options = option[componentName]; + if (options) { + if (!isArray(options)) { + options = [options]; + } + each$1(options, function (option) { + compatLayoutProperties(option); + }); + } + }); +}; + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +// (1) [Caution]: the logic is correct based on the premises: +// data processing stage is blocked in stream. +// See +// (2) Only register once when import repeatly. +// Should be executed before after series filtered and before stack calculation. +var dataStack = function (ecModel) { + var stackInfoMap = createHashMap(); + ecModel.eachSeries(function (seriesModel) { + var stack = seriesModel.get('stack'); + // Compatibal: when `stack` is set as '', do not stack. + if (stack) { + var stackInfoList = stackInfoMap.get(stack) || stackInfoMap.set(stack, []); + var data = seriesModel.getData(); + + var stackInfo = { + // Used for calculate axis extent automatically. + stackResultDimension: data.getCalculationInfo('stackResultDimension'), + stackedOverDimension: data.getCalculationInfo('stackedOverDimension'), + stackedDimension: data.getCalculationInfo('stackedDimension'), + stackedByDimension: data.getCalculationInfo('stackedByDimension'), + isStackedByIndex: data.getCalculationInfo('isStackedByIndex'), + data: data, + seriesModel: seriesModel + }; + + // If stacked on axis that do not support data stack. + if (!stackInfo.stackedDimension + || !(stackInfo.isStackedByIndex || stackInfo.stackedByDimension) + ) { + return; + } + + stackInfoList.length && data.setCalculationInfo( + 'stackedOnSeries', stackInfoList[stackInfoList.length - 1].seriesModel + ); + + stackInfoList.push(stackInfo); + } + }); + + stackInfoMap.each(calculateStack); +}; + +function calculateStack(stackInfoList) { + each$1(stackInfoList, function (targetStackInfo, idxInStack) { + var resultVal = []; + var resultNaN = [NaN, NaN]; + var dims = [targetStackInfo.stackResultDimension, targetStackInfo.stackedOverDimension]; + var targetData = targetStackInfo.data; + var isStackedByIndex = targetStackInfo.isStackedByIndex; + + // Should not write on raw data, because stack series model list changes + // depending on legend selection. + var newData = targetData.map(dims, function (v0, v1, dataIndex) { + var sum = targetData.get(targetStackInfo.stackedDimension, dataIndex); + + // Consider `connectNulls` of line area, if value is NaN, stackedOver + // should also be NaN, to draw a appropriate belt area. + if (isNaN(sum)) { + return resultNaN; + } + + var byValue; + var stackedDataRawIndex; + + if (isStackedByIndex) { + stackedDataRawIndex = targetData.getRawIndex(dataIndex); + } + else { + byValue = targetData.get(targetStackInfo.stackedByDimension, dataIndex); + } + + // If stackOver is NaN, chart view will render point on value start. + var stackedOver = NaN; + + for (var j = idxInStack - 1; j >= 0; j--) { + var stackInfo = stackInfoList[j]; + + // Has been optimized by inverted indices on `stackedByDimension`. + if (!isStackedByIndex) { + stackedDataRawIndex = stackInfo.data.rawIndexOf(stackInfo.stackedByDimension, byValue); + } + + if (stackedDataRawIndex >= 0) { + var val = stackInfo.data.getByRawIndex(stackInfo.stackResultDimension, stackedDataRawIndex); + + // Considering positive stack, negative stack and empty data + if ((sum >= 0 && val > 0) // Positive stack + || (sum <= 0 && val < 0) // Negative stack + ) { + sum += val; + stackedOver = val; + break; + } + } + } + + resultVal[0] = sum; + resultVal[1] = stackedOver; + + return resultVal; + }); + + targetData.hostModel.setData(newData); + // Update for consequent calculation + targetStackInfo.data = newData; + }); +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +// TODO +// ??? refactor? check the outer usage of data provider. +// merge with defaultDimValueGetter? + +/** + * If normal array used, mutable chunk size is supported. + * If typed array used, chunk size must be fixed. + */ +function DefaultDataProvider(source, dimSize) { + if (!Source.isInstance(source)) { + source = Source.seriesDataToSource(source); + } + this._source = source; + + var data = this._data = source.data; + var sourceFormat = source.sourceFormat; + + // Typed array. TODO IE10+? + if (sourceFormat === SOURCE_FORMAT_TYPED_ARRAY) { + if (__DEV__) { + if (dimSize == null) { + throw new Error('Typed array data must specify dimension size'); + } + } + this._offset = 0; + this._dimSize = dimSize; + this._data = data; + } + + var methods = providerMethods[ + sourceFormat === SOURCE_FORMAT_ARRAY_ROWS + ? sourceFormat + '_' + source.seriesLayoutBy + : sourceFormat + ]; + + if (__DEV__) { + assert$1(methods, 'Invalide sourceFormat: ' + sourceFormat); + } + + extend(this, methods); +} + +var providerProto = DefaultDataProvider.prototype; +// If data is pure without style configuration +providerProto.pure = false; +// If data is persistent and will not be released after use. +providerProto.persistent = true; + +// ???! FIXME legacy data provider do not has method getSource +providerProto.getSource = function () { + return this._source; +}; + +var providerMethods = { + + 'arrayRows_column': { + pure: true, + count: function () { + return Math.max(0, this._data.length - this._source.startIndex); + }, + getItem: function (idx) { + return this._data[idx + this._source.startIndex]; + }, + appendData: appendDataSimply + }, + + 'arrayRows_row': { + pure: true, + count: function () { + var row = this._data[0]; + return row ? Math.max(0, row.length - this._source.startIndex) : 0; + }, + getItem: function (idx) { + idx += this._source.startIndex; + var item = []; + var data = this._data; + for (var i = 0; i < data.length; i++) { + var row = data[i]; + item.push(row ? row[idx] : null); + } + return item; + }, + appendData: function () { + throw new Error('Do not support appendData when set seriesLayoutBy: "row".'); + } + }, + + 'objectRows': { + pure: true, + count: countSimply, + getItem: getItemSimply, + appendData: appendDataSimply + }, + + 'keyedColumns': { + pure: true, + count: function () { + var dimName = this._source.dimensionsDefine[0].name; + var col = this._data[dimName]; + return col ? col.length : 0; + }, + getItem: function (idx) { + var item = []; + var dims = this._source.dimensionsDefine; + for (var i = 0; i < dims.length; i++) { + var col = this._data[dims[i].name]; + item.push(col ? col[idx] : null); + } + return item; + }, + appendData: function (newData) { + var data = this._data; + each$1(newData, function (newCol, key) { + var oldCol = data[key] || (data[key] = []); + for (var i = 0; i < (newCol || []).length; i++) { + oldCol.push(newCol[i]); + } + }); + } + }, + + 'original': { + count: countSimply, + getItem: getItemSimply, + appendData: appendDataSimply + }, + + 'typedArray': { + persistent: false, + pure: true, + count: function () { + return this._data ? (this._data.length / this._dimSize) : 0; + }, + getItem: function (idx, out) { + idx = idx - this._offset; + out = out || []; + var offset = this._dimSize * idx; + for (var i = 0; i < this._dimSize; i++) { + out[i] = this._data[offset + i]; + } + return out; + }, + appendData: function (newData) { + if (__DEV__) { + assert$1( + isTypedArray(newData), + 'Added data must be TypedArray if data in initialization is TypedArray' + ); + } + + this._data = newData; + }, + + // Clean self if data is already used. + clean: function () { + // PENDING + this._offset += this.count(); + this._data = null; + } + } +}; + +function countSimply() { + return this._data.length; +} +function getItemSimply(idx) { + return this._data[idx]; +} +function appendDataSimply(newData) { + for (var i = 0; i < newData.length; i++) { + this._data.push(newData[i]); + } +} + + + +var rawValueGetters = { + + arrayRows: getRawValueSimply, + + objectRows: function (dataItem, dataIndex, dimIndex, dimName) { + return dimIndex != null ? dataItem[dimName] : dataItem; + }, + + keyedColumns: getRawValueSimply, + + original: function (dataItem, dataIndex, dimIndex, dimName) { + // FIXME + // In some case (markpoint in geo (geo-map.html)), dataItem + // is {coord: [...]} + var value = getDataItemValue(dataItem); + return (dimIndex == null || !(value instanceof Array)) + ? value + : value[dimIndex]; + }, + + typedArray: getRawValueSimply +}; + +function getRawValueSimply(dataItem, dataIndex, dimIndex, dimName) { + return dimIndex != null ? dataItem[dimIndex] : dataItem; +} + + +var defaultDimValueGetters = { + + arrayRows: getDimValueSimply, + + objectRows: function (dataItem, dimName, dataIndex, dimIndex) { + return converDataValue(dataItem[dimName], this._dimensionInfos[dimName]); + }, + + keyedColumns: getDimValueSimply, + + original: function (dataItem, dimName, dataIndex, dimIndex) { + // Performance sensitive, do not use modelUtil.getDataItemValue. + // If dataItem is an plain object with no value field, the var `value` + // will be assigned with the object, but it will be tread correctly + // in the `convertDataValue`. + var value = dataItem && (dataItem.value == null ? dataItem : dataItem.value); + + // If any dataItem is like { value: 10 } + if (!this._rawData.pure && isDataItemOption(dataItem)) { + this.hasItemOption = true; + } + return converDataValue( + (value instanceof Array) + ? value[dimIndex] + // If value is a single number or something else not array. + : value, + this._dimensionInfos[dimName] + ); + }, + + typedArray: function (dataItem, dimName, dataIndex, dimIndex) { + return dataItem[dimIndex]; + } + +}; + +function getDimValueSimply(dataItem, dimName, dataIndex, dimIndex) { + return converDataValue(dataItem[dimIndex], this._dimensionInfos[dimName]); +} + +/** + * This helper method convert value in data. + * @param {string|number|Date} value + * @param {Object|string} [dimInfo] If string (like 'x'), dimType defaults 'number'. + * If "dimInfo.ordinalParseAndSave", ordinal value can be parsed. + */ +function converDataValue(value, dimInfo) { + // Performance sensitive. + var dimType = dimInfo && dimInfo.type; + if (dimType === 'ordinal') { + // If given value is a category string + var ordinalMeta = dimInfo && dimInfo.ordinalMeta; + return ordinalMeta + ? ordinalMeta.parseAndCollect(value) + : value; + } + + if (dimType === 'time' + // spead up when using timestamp + && typeof value !== 'number' + && value != null + && value !== '-' + ) { + value = +parseDate(value); + } + + // dimType defaults 'number'. + // If dimType is not ordinal and value is null or undefined or NaN or '-', + // parse to NaN. + return (value == null || value === '') + ? NaN + // If string (like '-'), using '+' parse to NaN + // If object, also parse to NaN + : +value; +} + +// ??? FIXME can these logic be more neat: getRawValue, getRawDataItem, +// Consider persistent. +// Caution: why use raw value to display on label or tooltip? +// A reason is to avoid format. For example time value we do not know +// how to format is expected. More over, if stack is used, calculated +// value may be 0.91000000001, which have brings trouble to display. +// TODO: consider how to treat null/undefined/NaN when display? +/** + * @param {module:echarts/data/List} data + * @param {number} dataIndex + * @param {string|number} [dim] dimName or dimIndex + * @return {Array.|string|number} can be null/undefined. + */ +function retrieveRawValue(data, dataIndex, dim) { + if (!data) { + return; + } + + // Consider data may be not persistent. + var dataItem = data.getRawDataItem(dataIndex); + + if (dataItem == null) { + return; + } + + var sourceFormat = data.getProvider().getSource().sourceFormat; + var dimName; + var dimIndex; + + var dimInfo = data.getDimensionInfo(dim); + if (dimInfo) { + dimName = dimInfo.name; + dimIndex = dimInfo.index; + } + + return rawValueGetters[sourceFormat](dataItem, dataIndex, dimIndex, dimName); +} + +/** + * Compatible with some cases (in pie, map) like: + * data: [{name: 'xx', value: 5, selected: true}, ...] + * where only sourceFormat is 'original' and 'objectRows' supported. + * + * ??? TODO + * Supported detail options in data item when using 'arrayRows'. + * + * @param {module:echarts/data/List} data + * @param {number} dataIndex + * @param {string} attr like 'selected' + */ +function retrieveRawAttr(data, dataIndex, attr) { + if (!data) { + return; + } + + var sourceFormat = data.getProvider().getSource().sourceFormat; + + if (sourceFormat !== SOURCE_FORMAT_ORIGINAL + && sourceFormat !== SOURCE_FORMAT_OBJECT_ROWS + ) { + return; + } + + var dataItem = data.getRawDataItem(dataIndex); + if (sourceFormat === SOURCE_FORMAT_ORIGINAL && !isObject$1(dataItem)) { + dataItem = null; + } + if (dataItem) { + return dataItem[attr]; + } +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var DIMENSION_LABEL_REG = /\{@(.+?)\}/g; + +// PENDING A little ugly +var dataFormatMixin = { + /** + * Get params for formatter + * @param {number} dataIndex + * @param {string} [dataType] + * @return {Object} + */ + getDataParams: function (dataIndex, dataType) { + var data = this.getData(dataType); + var rawValue = this.getRawValue(dataIndex, dataType); + var rawDataIndex = data.getRawIndex(dataIndex); + var name = data.getName(dataIndex); + var itemOpt = data.getRawDataItem(dataIndex); + var color = data.getItemVisual(dataIndex, 'color'); + var tooltipModel = this.ecModel.getComponent('tooltip'); + var renderModeOption = tooltipModel && tooltipModel.get('renderMode'); + var renderMode = getTooltipRenderMode(renderModeOption); + var mainType = this.mainType; + var isSeries = mainType === 'series'; + + return { + componentType: mainType, + componentSubType: this.subType, + componentIndex: this.componentIndex, + seriesType: isSeries ? this.subType : null, + seriesIndex: this.seriesIndex, + seriesId: isSeries ? this.id : null, + seriesName: isSeries ? this.name : null, + name: name, + dataIndex: rawDataIndex, + data: itemOpt, + dataType: dataType, + value: rawValue, + color: color, + marker: getTooltipMarker({ + color: color, + renderMode: renderMode + }), + + // Param name list for mapping `a`, `b`, `c`, `d`, `e` + $vars: ['seriesName', 'name', 'value'] + }; + }, + + /** + * Format label + * @param {number} dataIndex + * @param {string} [status='normal'] 'normal' or 'emphasis' + * @param {string} [dataType] + * @param {number} [dimIndex] + * @param {string} [labelProp='label'] + * @return {string} If not formatter, return null/undefined + */ + getFormattedLabel: function (dataIndex, status, dataType, dimIndex, labelProp) { + status = status || 'normal'; + var data = this.getData(dataType); + var itemModel = data.getItemModel(dataIndex); + + var params = this.getDataParams(dataIndex, dataType); + if (dimIndex != null && (params.value instanceof Array)) { + params.value = params.value[dimIndex]; + } + + var formatter = itemModel.get( + status === 'normal' + ? [labelProp || 'label', 'formatter'] + : [status, labelProp || 'label', 'formatter'] + ); + + if (typeof formatter === 'function') { + params.status = status; + return formatter(params); + } + else if (typeof formatter === 'string') { + var str = formatTpl(formatter, params); + + // Support 'aaa{@[3]}bbb{@product}ccc'. + // Do not support '}' in dim name util have to. + return str.replace(DIMENSION_LABEL_REG, function (origin, dim) { + var len = dim.length; + if (dim.charAt(0) === '[' && dim.charAt(len - 1) === ']') { + dim = +dim.slice(1, len - 1); // Also: '[]' => 0 + } + return retrieveRawValue(data, dataIndex, dim); + }); + } + }, + + /** + * Get raw value in option + * @param {number} idx + * @param {string} [dataType] + * @return {Array|number|string} + */ + getRawValue: function (idx, dataType) { + return retrieveRawValue(this.getData(dataType), idx); + }, + + /** + * Should be implemented. + * @param {number} dataIndex + * @param {boolean} [multipleSeries=false] + * @param {number} [dataType] + * @return {string} tooltip string + */ + formatTooltip: function () { + // Empty function + } +}; + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/** + * @param {Object} define + * @return See the return of `createTask`. + */ +function createTask(define) { + return new Task(define); +} + +/** + * @constructor + * @param {Object} define + * @param {Function} define.reset Custom reset + * @param {Function} [define.plan] Returns 'reset' indicate reset immediately. + * @param {Function} [define.count] count is used to determin data task. + * @param {Function} [define.onDirty] count is used to determin data task. + */ +function Task(define) { + define = define || {}; + + this._reset = define.reset; + this._plan = define.plan; + this._count = define.count; + this._onDirty = define.onDirty; + + this._dirty = true; + + // Context must be specified implicitly, to + // avoid miss update context when model changed. + this.context; +} + +var taskProto = Task.prototype; + +/** + * @param {Object} performArgs + * @param {number} [performArgs.step] Specified step. + * @param {number} [performArgs.skip] Skip customer perform call. + * @param {number} [performArgs.modBy] Sampling window size. + * @param {number} [performArgs.modDataCount] Sampling count. + */ +taskProto.perform = function (performArgs) { + var upTask = this._upstream; + var skip = performArgs && performArgs.skip; + + // TODO some refactor. + // Pull data. Must pull data each time, because context.data + // may be updated by Series.setData. + if (this._dirty && upTask) { + var context = this.context; + context.data = context.outputData = upTask.context.outputData; + } + + if (this.__pipeline) { + this.__pipeline.currentTask = this; + } + + var planResult; + if (this._plan && !skip) { + planResult = this._plan(this.context); + } + + // Support sharding by mod, which changes the render sequence and makes the rendered graphic + // elements uniformed distributed when progress, especially when moving or zooming. + var lastModBy = normalizeModBy(this._modBy); + var lastModDataCount = this._modDataCount || 0; + var modBy = normalizeModBy(performArgs && performArgs.modBy); + var modDataCount = performArgs && performArgs.modDataCount || 0; + if (lastModBy !== modBy || lastModDataCount !== modDataCount) { + planResult = 'reset'; + } + + function normalizeModBy(val) { + !(val >= 1) && (val = 1); // jshint ignore:line + return val; + } + + var forceFirstProgress; + if (this._dirty || planResult === 'reset') { + this._dirty = false; + forceFirstProgress = reset(this, skip); + } + + this._modBy = modBy; + this._modDataCount = modDataCount; + + var step = performArgs && performArgs.step; + + if (upTask) { + + if (__DEV__) { + assert$1(upTask._outputDueEnd != null); + } + this._dueEnd = upTask._outputDueEnd; + } + // DataTask or overallTask + else { + if (__DEV__) { + assert$1(!this._progress || this._count); + } + this._dueEnd = this._count ? this._count(this.context) : Infinity; + } + + // Note: Stubs, that its host overall task let it has progress, has progress. + // If no progress, pass index from upstream to downstream each time plan called. + if (this._progress) { + var start = this._dueIndex; + var end = Math.min( + step != null ? this._dueIndex + step : Infinity, + this._dueEnd + ); + + if (!skip && (forceFirstProgress || start < end)) { + var progress = this._progress; + if (isArray(progress)) { + for (var i = 0; i < progress.length; i++) { + doProgress(this, progress[i], start, end, modBy, modDataCount); + } + } + else { + doProgress(this, progress, start, end, modBy, modDataCount); + } + } + + this._dueIndex = end; + // If no `outputDueEnd`, assume that output data and + // input data is the same, so use `dueIndex` as `outputDueEnd`. + var outputDueEnd = this._settedOutputEnd != null + ? this._settedOutputEnd : end; + + if (__DEV__) { + // ??? Can not rollback. + assert$1(outputDueEnd >= this._outputDueEnd); + } + + this._outputDueEnd = outputDueEnd; + } + else { + // (1) Some overall task has no progress. + // (2) Stubs, that its host overall task do not let it has progress, has no progress. + // This should always be performed so it can be passed to downstream. + this._dueIndex = this._outputDueEnd = this._settedOutputEnd != null + ? this._settedOutputEnd : this._dueEnd; + } + + return this.unfinished(); +}; + +var iterator = (function () { + + var end; + var current; + var modBy; + var modDataCount; + var winCount; + + var it = { + reset: function (s, e, sStep, sCount) { + current = s; + end = e; + + modBy = sStep; + modDataCount = sCount; + winCount = Math.ceil(modDataCount / modBy); + + it.next = (modBy > 1 && modDataCount > 0) ? modNext : sequentialNext; + } + }; + + return it; + + function sequentialNext() { + return current < end ? current++ : null; + } + + function modNext() { + var dataIndex = (current % winCount) * modBy + Math.ceil(current / winCount); + var result = current >= end + ? null + : dataIndex < modDataCount + ? dataIndex + // If modDataCount is smaller than data.count() (consider `appendData` case), + // Use normal linear rendering mode. + : current; + current++; + return result; + } +})(); + +taskProto.dirty = function () { + this._dirty = true; + this._onDirty && this._onDirty(this.context); +}; + +function doProgress(taskIns, progress, start, end, modBy, modDataCount) { + iterator.reset(start, end, modBy, modDataCount); + taskIns._callingProgress = progress; + taskIns._callingProgress({ + start: start, end: end, count: end - start, next: iterator.next + }, taskIns.context); +} + +function reset(taskIns, skip) { + taskIns._dueIndex = taskIns._outputDueEnd = taskIns._dueEnd = 0; + taskIns._settedOutputEnd = null; + + var progress; + var forceFirstProgress; + + if (!skip && taskIns._reset) { + progress = taskIns._reset(taskIns.context); + if (progress && progress.progress) { + forceFirstProgress = progress.forceFirstProgress; + progress = progress.progress; + } + // To simplify no progress checking, array must has item. + if (isArray(progress) && !progress.length) { + progress = null; + } + } + + taskIns._progress = progress; + taskIns._modBy = taskIns._modDataCount = null; + + var downstream = taskIns._downstream; + downstream && downstream.dirty(); + + return forceFirstProgress; +} + +/** + * @return {boolean} + */ +taskProto.unfinished = function () { + return this._progress && this._dueIndex < this._dueEnd; +}; + +/** + * @param {Object} downTask The downstream task. + * @return {Object} The downstream task. + */ +taskProto.pipe = function (downTask) { + if (__DEV__) { + assert$1(downTask && !downTask._disposed && downTask !== this); + } + + // If already downstream, do not dirty downTask. + if (this._downstream !== downTask || this._dirty) { + this._downstream = downTask; + downTask._upstream = this; + downTask.dirty(); + } +}; + +taskProto.dispose = function () { + if (this._disposed) { + return; + } + + this._upstream && (this._upstream._downstream = null); + this._downstream && (this._downstream._upstream = null); + + this._dirty = false; + this._disposed = true; +}; + +taskProto.getUpstream = function () { + return this._upstream; +}; + +taskProto.getDownstream = function () { + return this._downstream; +}; + +taskProto.setOutputEnd = function (end) { + // This only happend in dataTask, dataZoom, map, currently. + // where dataZoom do not set end each time, but only set + // when reset. So we should record the setted end, in case + // that the stub of dataZoom perform again and earse the + // setted end by upstream. + this._outputDueEnd = this._settedOutputEnd = end; +}; + + +/////////////////////////////////////////////////////////// +// For stream debug (Should be commented out after used!) +// Usage: printTask(this, 'begin'); +// Usage: printTask(this, null, {someExtraProp}); +// function printTask(task, prefix, extra) { +// window.ecTaskUID == null && (window.ecTaskUID = 0); +// task.uidDebug == null && (task.uidDebug = `task_${window.ecTaskUID++}`); +// task.agent && task.agent.uidDebug == null && (task.agent.uidDebug = `task_${window.ecTaskUID++}`); +// var props = []; +// if (task.__pipeline) { +// var val = `${task.__idxInPipeline}/${task.__pipeline.tail.__idxInPipeline} ${task.agent ? '(stub)' : ''}`; +// props.push({text: 'idx', value: val}); +// } else { +// var stubCount = 0; +// task.agentStubMap.each(() => stubCount++); +// props.push({text: 'idx', value: `overall (stubs: ${stubCount})`}); +// } +// props.push({text: 'uid', value: task.uidDebug}); +// if (task.__pipeline) { +// props.push({text: 'pid', value: task.__pipeline.id}); +// task.agent && props.push( +// {text: 'stubFor', value: task.agent.uidDebug} +// ); +// } +// props.push( +// {text: 'dirty', value: task._dirty}, +// {text: 'dueIndex', value: task._dueIndex}, +// {text: 'dueEnd', value: task._dueEnd}, +// {text: 'outputDueEnd', value: task._outputDueEnd} +// ); +// if (extra) { +// Object.keys(extra).forEach(key => { +// props.push({text: key, value: extra[key]}); +// }); +// } +// var args = ['color: blue']; +// var msg = `%c[${prefix || 'T'}] %c` + props.map(item => ( +// args.push('color: black', 'color: red'), +// `${item.text}: %c${item.value}` +// )).join('%c, '); +// console.log.apply(console, [msg].concat(args)); +// // console.log(this); +// } + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var inner$4 = makeInner(); + +var SeriesModel = ComponentModel.extend({ + + type: 'series.__base__', + + /** + * @readOnly + */ + seriesIndex: 0, + + // coodinateSystem will be injected in the echarts/CoordinateSystem + coordinateSystem: null, + + /** + * @type {Object} + * @protected + */ + defaultOption: null, + + /** + * Data provided for legend + * @type {Function} + */ + // PENDING + legendDataProvider: null, + + /** + * Access path of color for visual + */ + visualColorAccessPath: 'itemStyle.color', + + /** + * Support merge layout params. + * Only support 'box' now (left/right/top/bottom/width/height). + * @type {string|Object} Object can be {ignoreSize: true} + * @readOnly + */ + layoutMode: null, + + init: function (option, parentModel, ecModel, extraOpt) { + + /** + * @type {number} + * @readOnly + */ + this.seriesIndex = this.componentIndex; + + this.dataTask = createTask({ + count: dataTaskCount, + reset: dataTaskReset + }); + this.dataTask.context = {model: this}; + + this.mergeDefaultAndTheme(option, ecModel); + + prepareSource(this); + + + var data = this.getInitialData(option, ecModel); + wrapData(data, this); + this.dataTask.context.data = data; + + if (__DEV__) { + assert$1(data, 'getInitialData returned invalid data.'); + } + + /** + * @type {module:echarts/data/List|module:echarts/data/Tree|module:echarts/data/Graph} + * @private + */ + inner$4(this).dataBeforeProcessed = data; + + // If we reverse the order (make data firstly, and then make + // dataBeforeProcessed by cloneShallow), cloneShallow will + // cause data.graph.data !== data when using + // module:echarts/data/Graph or module:echarts/data/Tree. + // See module:echarts/data/helper/linkList + + // Theoretically, it is unreasonable to call `seriesModel.getData()` in the model + // init or merge stage, because the data can be restored. So we do not `restoreData` + // and `setData` here, which forbids calling `seriesModel.getData()` in this stage. + // Call `seriesModel.getRawData()` instead. + // this.restoreData(); + + autoSeriesName(this); + }, + + /** + * Util for merge default and theme to option + * @param {Object} option + * @param {module:echarts/model/Global} ecModel + */ + mergeDefaultAndTheme: function (option, ecModel) { + var layoutMode = this.layoutMode; + var inputPositionParams = layoutMode + ? getLayoutParams(option) : {}; + + // Backward compat: using subType on theme. + // But if name duplicate between series subType + // (for example: parallel) add component mainType, + // add suffix 'Series'. + var themeSubType = this.subType; + if (ComponentModel.hasClass(themeSubType)) { + themeSubType += 'Series'; + } + merge( + option, + ecModel.getTheme().get(this.subType) + ); + merge(option, this.getDefaultOption()); + + // Default label emphasis `show` + defaultEmphasis(option, 'label', ['show']); + + this.fillDataTextStyle(option.data); + + if (layoutMode) { + mergeLayoutParam(option, inputPositionParams, layoutMode); + } + }, + + mergeOption: function (newSeriesOption, ecModel) { + // this.settingTask.dirty(); + + newSeriesOption = merge(this.option, newSeriesOption, true); + this.fillDataTextStyle(newSeriesOption.data); + + var layoutMode = this.layoutMode; + if (layoutMode) { + mergeLayoutParam(this.option, newSeriesOption, layoutMode); + } + + prepareSource(this); + + var data = this.getInitialData(newSeriesOption, ecModel); + wrapData(data, this); + this.dataTask.dirty(); + this.dataTask.context.data = data; + + inner$4(this).dataBeforeProcessed = data; + + autoSeriesName(this); + }, + + fillDataTextStyle: function (data) { + // Default data label emphasis `show` + // FIXME Tree structure data ? + // FIXME Performance ? + if (data && !isTypedArray(data)) { + var props = ['show']; + for (var i = 0; i < data.length; i++) { + if (data[i] && data[i].label) { + defaultEmphasis(data[i], 'label', props); + } + } + } + }, + + /** + * Init a data structure from data related option in series + * Must be overwritten + */ + getInitialData: function () {}, + + /** + * Append data to list + * @param {Object} params + * @param {Array|TypedArray} params.data + */ + appendData: function (params) { + // FIXME ??? + // (1) If data from dataset, forbidden append. + // (2) support append data of dataset. + var data = this.getRawData(); + data.appendData(params.data); + }, + + /** + * Consider some method like `filter`, `map` need make new data, + * We should make sure that `seriesModel.getData()` get correct + * data in the stream procedure. So we fetch data from upstream + * each time `task.perform` called. + * @param {string} [dataType] + * @return {module:echarts/data/List} + */ + getData: function (dataType) { + var task = getCurrentTask(this); + if (task) { + var data = task.context.data; + return dataType == null ? data : data.getLinkedData(dataType); + } + else { + // When series is not alive (that may happen when click toolbox + // restore or setOption with not merge mode), series data may + // be still need to judge animation or something when graphic + // elements want to know whether fade out. + return inner$4(this).data; + } + }, + + /** + * @param {module:echarts/data/List} data + */ + setData: function (data) { + var task = getCurrentTask(this); + if (task) { + var context = task.context; + // Consider case: filter, data sample. + if (context.data !== data && task.modifyOutputEnd) { + task.setOutputEnd(data.count()); + } + context.outputData = data; + // Caution: setData should update context.data, + // Because getData may be called multiply in a + // single stage and expect to get the data just + // set. (For example, AxisProxy, x y both call + // getData and setDate sequentially). + // So the context.data should be fetched from + // upstream each time when a stage starts to be + // performed. + if (task !== this.dataTask) { + context.data = data; + } + } + inner$4(this).data = data; + }, + + /** + * @see {module:echarts/data/helper/sourceHelper#getSource} + * @return {module:echarts/data/Source} source + */ + getSource: function () { + return getSource(this); + }, + + /** + * Get data before processed + * @return {module:echarts/data/List} + */ + getRawData: function () { + return inner$4(this).dataBeforeProcessed; + }, + + /** + * Get base axis if has coordinate system and has axis. + * By default use coordSys.getBaseAxis(); + * Can be overrided for some chart. + * @return {type} description + */ + getBaseAxis: function () { + var coordSys = this.coordinateSystem; + return coordSys && coordSys.getBaseAxis && coordSys.getBaseAxis(); + }, + + // FIXME + /** + * Default tooltip formatter + * + * @param {number} dataIndex + * @param {boolean} [multipleSeries=false] + * @param {number} [dataType] + * @param {string} [renderMode='html'] valid values: 'html' and 'richText'. + * 'html' is used for rendering tooltip in extra DOM form, and the result + * string is used as DOM HTML content. + * 'richText' is used for rendering tooltip in rich text form, for those where + * DOM operation is not supported. + * @return {Object} formatted tooltip with `html` and `markers` + */ + formatTooltip: function (dataIndex, multipleSeries, dataType, renderMode) { + + var series = this; + renderMode = renderMode || 'html'; + var newLine = renderMode === 'html' ? '
' : '\n'; + var isRichText = renderMode === 'richText'; + var markers = {}; + var markerId = 0; + + function formatArrayValue(value) { + // ??? TODO refactor these logic. + // check: category-no-encode-has-axis-data in dataset.html + var vertially = reduce(value, function (vertially, val, idx) { + var dimItem = data.getDimensionInfo(idx); + return vertially |= dimItem && dimItem.tooltip !== false && dimItem.displayName != null; + }, 0); + + var result = []; + + tooltipDims.length + ? each$1(tooltipDims, function (dim) { + setEachItem(retrieveRawValue(data, dataIndex, dim), dim); + }) + // By default, all dims is used on tooltip. + : each$1(value, setEachItem); + + function setEachItem(val, dim) { + var dimInfo = data.getDimensionInfo(dim); + // If `dimInfo.tooltip` is not set, show tooltip. + if (!dimInfo || dimInfo.otherDims.tooltip === false) { + return; + } + var dimType = dimInfo.type; + var markName = 'sub' + series.seriesIndex + 'at' + markerId; + var dimHead = getTooltipMarker({ + color: color, + type: 'subItem', + renderMode: renderMode, + markerId: markName + }); + + var dimHeadStr = typeof dimHead === 'string' ? dimHead : dimHead.content; + var valStr = (vertially + ? dimHeadStr + encodeHTML(dimInfo.displayName || '-') + ': ' + : '' + ) + // FIXME should not format time for raw data? + + encodeHTML(dimType === 'ordinal' + ? val + '' + : dimType === 'time' + ? (multipleSeries ? '' : formatTime('yyyy/MM/dd hh:mm:ss', val)) + : addCommas(val) + ); + valStr && result.push(valStr); + + if (isRichText) { + markers[markName] = color; + ++markerId; + } + } + + var newLine = vertially ? (isRichText ? '\n' : '
') : ''; + var content = newLine + result.join(newLine || ', '); + return { + renderMode: renderMode, + content: content, + style: markers + }; + } + + function formatSingleValue(val) { + // return encodeHTML(addCommas(val)); + return { + renderMode: renderMode, + content: encodeHTML(addCommas(val)), + style: markers + }; + } + + var data = this.getData(); + var tooltipDims = data.mapDimension('defaultedTooltip', true); + var tooltipDimLen = tooltipDims.length; + var value = this.getRawValue(dataIndex); + var isValueArr = isArray(value); + + var color = data.getItemVisual(dataIndex, 'color'); + if (isObject$1(color) && color.colorStops) { + color = (color.colorStops[0] || {}).color; + } + color = color || 'transparent'; + + // Complicated rule for pretty tooltip. + var formattedValue = (tooltipDimLen > 1 || (isValueArr && !tooltipDimLen)) + ? formatArrayValue(value) + : tooltipDimLen + ? formatSingleValue(retrieveRawValue(data, dataIndex, tooltipDims[0])) + : formatSingleValue(isValueArr ? value[0] : value); + var content = formattedValue.content; + + var markName = series.seriesIndex + 'at' + markerId; + var colorEl = getTooltipMarker({ + color: color, + type: 'item', + renderMode: renderMode, + markerId: markName + }); + markers[markName] = color; + ++markerId; + + var name = data.getName(dataIndex); + + var seriesName = this.name; + if (!isNameSpecified(this)) { + seriesName = ''; + } + seriesName = seriesName + ? encodeHTML(seriesName) + (!multipleSeries ? newLine : ': ') + : ''; + + var colorStr = typeof colorEl === 'string' ? colorEl : colorEl.content; + var html = !multipleSeries + ? seriesName + colorStr + + (name + ? encodeHTML(name) + ': ' + content + : content + ) + : colorStr + seriesName + content; + + return { + html: html, + markers: markers + }; + }, + + /** + * @return {boolean} + */ + isAnimationEnabled: function () { + if (env$1.node) { + return false; + } + + var animationEnabled = this.getShallow('animation'); + if (animationEnabled) { + if (this.getData().count() > this.getShallow('animationThreshold')) { + animationEnabled = false; + } + } + return animationEnabled; + }, + + restoreData: function () { + this.dataTask.dirty(); + }, + + getColorFromPalette: function (name, scope, requestColorNum) { + var ecModel = this.ecModel; + // PENDING + var color = colorPaletteMixin.getColorFromPalette.call(this, name, scope, requestColorNum); + if (!color) { + color = ecModel.getColorFromPalette(name, scope, requestColorNum); + } + return color; + }, + + /** + * Use `data.mapDimension(coordDim, true)` instead. + * @deprecated + */ + coordDimToDataDim: function (coordDim) { + return this.getRawData().mapDimension(coordDim, true); + }, + + /** + * Get progressive rendering count each step + * @return {number} + */ + getProgressive: function () { + return this.get('progressive'); + }, + + /** + * Get progressive rendering count each step + * @return {number} + */ + getProgressiveThreshold: function () { + return this.get('progressiveThreshold'); + }, + + /** + * Get data indices for show tooltip content. See tooltip. + * @abstract + * @param {Array.|string} dim + * @param {Array.} value + * @param {module:echarts/coord/single/SingleAxis} baseAxis + * @return {Object} {dataIndices, nestestValue}. + */ + getAxisTooltipData: null, + + /** + * See tooltip. + * @abstract + * @param {number} dataIndex + * @return {Array.} Point of tooltip. null/undefined can be returned. + */ + getTooltipPosition: null, + + /** + * @see {module:echarts/stream/Scheduler} + */ + pipeTask: null, + + /** + * Convinient for override in extended class. + * @protected + * @type {Function} + */ + preventIncremental: null, + + /** + * @public + * @readOnly + * @type {Object} + */ + pipelineContext: null + +}); + + +mixin(SeriesModel, dataFormatMixin); +mixin(SeriesModel, colorPaletteMixin); + +/** + * MUST be called after `prepareSource` called + * Here we need to make auto series, especially for auto legend. But we + * do not modify series.name in option to avoid side effects. + */ +function autoSeriesName(seriesModel) { + // User specified name has higher priority, otherwise it may cause + // series can not be queried unexpectedly. + var name = seriesModel.name; + if (!isNameSpecified(seriesModel)) { + seriesModel.name = getSeriesAutoName(seriesModel) || name; + } +} + +function getSeriesAutoName(seriesModel) { + var data = seriesModel.getRawData(); + var dataDims = data.mapDimension('seriesName', true); + var nameArr = []; + each$1(dataDims, function (dataDim) { + var dimInfo = data.getDimensionInfo(dataDim); + dimInfo.displayName && nameArr.push(dimInfo.displayName); + }); + return nameArr.join(' '); +} + +function dataTaskCount(context) { + return context.model.getRawData().count(); +} + +function dataTaskReset(context) { + var seriesModel = context.model; + seriesModel.setData(seriesModel.getRawData().cloneShallow()); + return dataTaskProgress; +} + +function dataTaskProgress(param, context) { + // Avoid repead cloneShallow when data just created in reset. + if (param.end > context.outputData.count()) { + context.model.getRawData().cloneShallow(context.outputData); + } +} + +// TODO refactor +function wrapData(data, seriesModel) { + each$1(data.CHANGABLE_METHODS, function (methodName) { + data.wrapMethod(methodName, curry(onDataSelfChange, seriesModel)); + }); +} + +function onDataSelfChange(seriesModel) { + var task = getCurrentTask(seriesModel); + if (task) { + // Consider case: filter, selectRange + task.setOutputEnd(this.count()); + } +} + +function getCurrentTask(seriesModel) { + var scheduler = (seriesModel.ecModel || {}).scheduler; + var pipeline = scheduler && scheduler.getPipeline(seriesModel.uid); + + if (pipeline) { + // When pipline finished, the currrentTask keep the last + // task (renderTask). + var task = pipeline.currentTask; + if (task) { + var agentStubMap = task.agentStubMap; + if (agentStubMap) { + task = agentStubMap.get(seriesModel.uid); + } + } + return task; + } +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var Component = function () { + /** + * @type {module:zrender/container/Group} + * @readOnly + */ + this.group = new Group(); + + /** + * @type {string} + * @readOnly + */ + this.uid = getUID('viewComponent'); +}; + +Component.prototype = { + + constructor: Component, + + init: function (ecModel, api) {}, + + render: function (componentModel, ecModel, api, payload) {}, + + dispose: function () {}, + + /** + * @param {string} eventType + * @param {Object} query + * @param {module:zrender/Element} targetEl + * @param {Object} packedEvent + * @return {boolen} Pass only when return `true`. + */ + filterForExposedEvent: null + +}; + +var componentProto = Component.prototype; +componentProto.updateView + = componentProto.updateLayout + = componentProto.updateVisual + = function (seriesModel, ecModel, api, payload) { + // Do nothing; + }; +// Enable Component.extend. +enableClassExtend(Component); + +// Enable capability of registerClass, getClass, hasClass, registerSubTypeDefaulter and so on. +enableClassManagement(Component, {registerWhenExtend: true}); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/** + * @return {string} If large mode changed, return string 'reset'; + */ +var createRenderPlanner = function () { + var inner = makeInner(); + + return function (seriesModel) { + var fields = inner(seriesModel); + var pipelineContext = seriesModel.pipelineContext; + + var originalLarge = fields.large; + var originalProgressive = fields.progressiveRender; + + var large = fields.large = pipelineContext.large; + var progressive = fields.progressiveRender = pipelineContext.progressiveRender; + + return !!((originalLarge ^ large) || (originalProgressive ^ progressive)) && 'reset'; + }; +}; + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var inner$5 = makeInner(); +var renderPlanner = createRenderPlanner(); + +function Chart() { + + /** + * @type {module:zrender/container/Group} + * @readOnly + */ + this.group = new Group(); + + /** + * @type {string} + * @readOnly + */ + this.uid = getUID('viewChart'); + + this.renderTask = createTask({ + plan: renderTaskPlan, + reset: renderTaskReset + }); + this.renderTask.context = {view: this}; +} + +Chart.prototype = { + + type: 'chart', + + /** + * Init the chart. + * @param {module:echarts/model/Global} ecModel + * @param {module:echarts/ExtensionAPI} api + */ + init: function (ecModel, api) {}, + + /** + * Render the chart. + * @param {module:echarts/model/Series} seriesModel + * @param {module:echarts/model/Global} ecModel + * @param {module:echarts/ExtensionAPI} api + * @param {Object} payload + */ + render: function (seriesModel, ecModel, api, payload) {}, + + /** + * Highlight series or specified data item. + * @param {module:echarts/model/Series} seriesModel + * @param {module:echarts/model/Global} ecModel + * @param {module:echarts/ExtensionAPI} api + * @param {Object} payload + */ + highlight: function (seriesModel, ecModel, api, payload) { + toggleHighlight(seriesModel.getData(), payload, 'emphasis'); + }, + + /** + * Downplay series or specified data item. + * @param {module:echarts/model/Series} seriesModel + * @param {module:echarts/model/Global} ecModel + * @param {module:echarts/ExtensionAPI} api + * @param {Object} payload + */ + downplay: function (seriesModel, ecModel, api, payload) { + toggleHighlight(seriesModel.getData(), payload, 'normal'); + }, + + /** + * Remove self. + * @param {module:echarts/model/Global} ecModel + * @param {module:echarts/ExtensionAPI} api + */ + remove: function (ecModel, api) { + this.group.removeAll(); + }, + + /** + * Dispose self. + * @param {module:echarts/model/Global} ecModel + * @param {module:echarts/ExtensionAPI} api + */ + dispose: function () {}, + + /** + * Rendering preparation in progressive mode. + * @param {module:echarts/model/Series} seriesModel + * @param {module:echarts/model/Global} ecModel + * @param {module:echarts/ExtensionAPI} api + * @param {Object} payload + */ + incrementalPrepareRender: null, + + /** + * Render in progressive mode. + * @param {Object} params See taskParams in `stream/task.js` + * @param {module:echarts/model/Series} seriesModel + * @param {module:echarts/model/Global} ecModel + * @param {module:echarts/ExtensionAPI} api + * @param {Object} payload + */ + incrementalRender: null, + + /** + * Update transform directly. + * @param {module:echarts/model/Series} seriesModel + * @param {module:echarts/model/Global} ecModel + * @param {module:echarts/ExtensionAPI} api + * @param {Object} payload + * @return {Object} {update: true} + */ + updateTransform: null, + + /** + * The view contains the given point. + * @interface + * @param {Array.} point + * @return {boolean} + */ + // containPoint: function () {} + + /** + * @param {string} eventType + * @param {Object} query + * @param {module:zrender/Element} targetEl + * @param {Object} packedEvent + * @return {boolen} Pass only when return `true`. + */ + filterForExposedEvent: null + +}; + +var chartProto = Chart.prototype; +chartProto.updateView + = chartProto.updateLayout + = chartProto.updateVisual + = function (seriesModel, ecModel, api, payload) { + this.render(seriesModel, ecModel, api, payload); + }; + +/** + * Set state of single element + * @param {module:zrender/Element} el + * @param {string} state + */ +function elSetState(el, state) { + if (el) { + el.trigger(state); + if (el.type === 'group') { + for (var i = 0; i < el.childCount(); i++) { + elSetState(el.childAt(i), state); + } + } + } +} +/** + * @param {module:echarts/data/List} data + * @param {Object} payload + * @param {string} state 'normal'|'emphasis' + */ +function toggleHighlight(data, payload, state) { + var dataIndex = queryDataIndex(data, payload); + + if (dataIndex != null) { + each$1(normalizeToArray(dataIndex), function (dataIdx) { + elSetState(data.getItemGraphicEl(dataIdx), state); + }); + } + else { + data.eachItemGraphicEl(function (el) { + elSetState(el, state); + }); + } +} + +// Enable Chart.extend. +enableClassExtend(Chart, ['dispose']); + +// Add capability of registerClass, getClass, hasClass, registerSubTypeDefaulter and so on. +enableClassManagement(Chart, {registerWhenExtend: true}); + +Chart.markUpdateMethod = function (payload, methodName) { + inner$5(payload).updateMethod = methodName; +}; + +function renderTaskPlan(context) { + return renderPlanner(context.model); +} + +function renderTaskReset(context) { + var seriesModel = context.model; + var ecModel = context.ecModel; + var api = context.api; + var payload = context.payload; + // ???! remove updateView updateVisual + var progressiveRender = seriesModel.pipelineContext.progressiveRender; + var view = context.view; + + var updateMethod = payload && inner$5(payload).updateMethod; + var methodName = progressiveRender + ? 'incrementalPrepareRender' + : (updateMethod && view[updateMethod]) + ? updateMethod + // `appendData` is also supported when data amount + // is less than progressive threshold. + : 'render'; + + if (methodName !== 'render') { + view[methodName](seriesModel, ecModel, api, payload); + } + + return progressMethodMap[methodName]; +} + +var progressMethodMap = { + incrementalPrepareRender: { + progress: function (params, context) { + context.view.incrementalRender( + params, context.model, context.ecModel, context.api, context.payload + ); + } + }, + render: { + // Put view.render in `progress` to support appendData. But in this case + // view.render should not be called in reset, otherwise it will be called + // twise. Use `forceFirstProgress` to make sure that view.render is called + // in any cases. + forceFirstProgress: true, + progress: function (params, context) { + context.view.render( + context.model, context.ecModel, context.api, context.payload + ); + } + } +}; + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + + +var ORIGIN_METHOD = '\0__throttleOriginMethod'; +var RATE = '\0__throttleRate'; +var THROTTLE_TYPE = '\0__throttleType'; + +/** + * @public + * @param {(Function)} fn + * @param {number} [delay=0] Unit: ms. + * @param {boolean} [debounce=false] + * true: If call interval less than `delay`, only the last call works. + * false: If call interval less than `delay, call works on fixed rate. + * @return {(Function)} throttled fn. + */ +function throttle(fn, delay, debounce) { + + var currCall; + var lastCall = 0; + var lastExec = 0; + var timer = null; + var diff; + var scope; + var args; + var debounceNextCall; + + delay = delay || 0; + + function exec() { + lastExec = (new Date()).getTime(); + timer = null; + fn.apply(scope, args || []); + } + + var cb = function () { + currCall = (new Date()).getTime(); + scope = this; + args = arguments; + var thisDelay = debounceNextCall || delay; + var thisDebounce = debounceNextCall || debounce; + debounceNextCall = null; + diff = currCall - (thisDebounce ? lastCall : lastExec) - thisDelay; + + clearTimeout(timer); + + // Here we should make sure that: the `exec` SHOULD NOT be called later + // than a new call of `cb`, that is, preserving the command order. Consider + // calculating "scale rate" when roaming as an example. When a call of `cb` + // happens, either the `exec` is called dierectly, or the call is delayed. + // But the delayed call should never be later than next call of `cb`. Under + // this assurance, we can simply update view state each time `dispatchAction` + // triggered by user roaming, but not need to add extra code to avoid the + // state being "rolled-back". + if (thisDebounce) { + timer = setTimeout(exec, thisDelay); + } + else { + if (diff >= 0) { + exec(); + } + else { + timer = setTimeout(exec, -diff); + } + } + + lastCall = currCall; + }; + + /** + * Clear throttle. + * @public + */ + cb.clear = function () { + if (timer) { + clearTimeout(timer); + timer = null; + } + }; + + /** + * Enable debounce once. + */ + cb.debounceNextCall = function (debounceDelay) { + debounceNextCall = debounceDelay; + }; + + return cb; +} + +/** + * Create throttle method or update throttle rate. + * + * @example + * ComponentView.prototype.render = function () { + * ... + * throttle.createOrUpdate( + * this, + * '_dispatchAction', + * this.model.get('throttle'), + * 'fixRate' + * ); + * }; + * ComponentView.prototype.remove = function () { + * throttle.clear(this, '_dispatchAction'); + * }; + * ComponentView.prototype.dispose = function () { + * throttle.clear(this, '_dispatchAction'); + * }; + * + * @public + * @param {Object} obj + * @param {string} fnAttr + * @param {number} [rate] + * @param {string} [throttleType='fixRate'] 'fixRate' or 'debounce' + * @return {Function} throttled function. + */ +function createOrUpdate(obj, fnAttr, rate, throttleType) { + var fn = obj[fnAttr]; + + if (!fn) { + return; + } + + var originFn = fn[ORIGIN_METHOD] || fn; + var lastThrottleType = fn[THROTTLE_TYPE]; + var lastRate = fn[RATE]; + + if (lastRate !== rate || lastThrottleType !== throttleType) { + if (rate == null || !throttleType) { + return (obj[fnAttr] = originFn); + } + + fn = obj[fnAttr] = throttle( + originFn, rate, throttleType === 'debounce' + ); + fn[ORIGIN_METHOD] = originFn; + fn[THROTTLE_TYPE] = throttleType; + fn[RATE] = rate; + } + + return fn; +} + +/** + * Clear throttle. Example see throttle.createOrUpdate. + * + * @public + * @param {Object} obj + * @param {string} fnAttr + */ +function clear(obj, fnAttr) { + var fn = obj[fnAttr]; + if (fn && fn[ORIGIN_METHOD]) { + obj[fnAttr] = fn[ORIGIN_METHOD]; + } +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var seriesColor = { + createOnAllSeries: true, + performRawSeries: true, + reset: function (seriesModel, ecModel) { + var data = seriesModel.getData(); + var colorAccessPath = (seriesModel.visualColorAccessPath || 'itemStyle.color').split('.'); + var color = seriesModel.get(colorAccessPath) // Set in itemStyle + || seriesModel.getColorFromPalette( + // TODO series count changed. + seriesModel.name, null, ecModel.getSeriesCount() + ); // Default color + + // FIXME Set color function or use the platte color + data.setVisual('color', color); + + // Only visible series has each data be visual encoded + if (!ecModel.isSeriesFiltered(seriesModel)) { + if (typeof color === 'function' && !(color instanceof Gradient)) { + data.each(function (idx) { + data.setItemVisual( + idx, 'color', color(seriesModel.getDataParams(idx)) + ); + }); + } + + // itemStyle in each data item + var dataEach = function (data, idx) { + var itemModel = data.getItemModel(idx); + var color = itemModel.get(colorAccessPath, true); + if (color != null) { + data.setItemVisual(idx, 'color', color); + } + }; + + return { dataEach: data.hasItemOption ? dataEach : null }; + } + } +}; + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + + +var lang = { + toolbox: { + brush: { + title: { + rect: '矩形选择', + polygon: '圈选', + lineX: '横向选择', + lineY: '纵向选择', + keep: '保持选择', + clear: '清除选择' + } + }, + dataView: { + title: '数据视图', + lang: ['数据视图', '关闭', '刷新'] + }, + dataZoom: { + title: { + zoom: '区域缩放', + back: '区域缩放还原' + } + }, + magicType: { + title: { + line: '切换为折线图', + bar: '切换为柱状图', + stack: '切换为堆叠', + tiled: '切换为平铺' + } + }, + restore: { + title: '还原' + }, + saveAsImage: { + title: '保存为图片', + lang: ['右键另存为图片'] + } + }, + series: { + typeNames: { + pie: '饼图', + bar: '柱状图', + line: '折线图', + scatter: '散点图', + effectScatter: '涟漪散点图', + radar: '雷达图', + tree: '树图', + treemap: '矩形树图', + boxplot: '箱型图', + candlestick: 'K线图', + k: 'K线图', + heatmap: '热力图', + map: '地图', + parallel: '平行坐标图', + lines: '线图', + graph: '关系图', + sankey: '桑基图', + funnel: '漏斗图', + gauge: '仪表盘图', + pictorialBar: '象形柱图', + themeRiver: '主题河流图', + sunburst: '旭日图' + } + }, + aria: { + general: { + withTitle: '这是一个关于“{title}”的图表。', + withoutTitle: '这是一个图表,' + }, + series: { + single: { + prefix: '', + withName: '图表类型是{seriesType},表示{seriesName}。', + withoutName: '图表类型是{seriesType}。' + }, + multiple: { + prefix: '它由{seriesCount}个图表系列组成。', + withName: '第{seriesId}个系列是一个表示{seriesName}的{seriesType},', + withoutName: '第{seriesId}个系列是一个{seriesType},', + separator: { + middle: ';', + end: '。' + } + } + }, + data: { + allData: '其数据是——', + partialData: '其中,前{displayCnt}项是——', + withName: '{name}的数据是{value}', + withoutName: '{value}', + separator: { + middle: ',', + end: '' + } + } + } +}; + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var aria = function (dom, ecModel) { + var ariaModel = ecModel.getModel('aria'); + if (!ariaModel.get('show')) { + return; + } + else if (ariaModel.get('description')) { + dom.setAttribute('aria-label', ariaModel.get('description')); + return; + } + + var seriesCnt = 0; + ecModel.eachSeries(function (seriesModel, idx) { + ++seriesCnt; + }, this); + + var maxDataCnt = ariaModel.get('data.maxCount') || 10; + var maxSeriesCnt = ariaModel.get('series.maxCount') || 10; + var displaySeriesCnt = Math.min(seriesCnt, maxSeriesCnt); + + var ariaLabel; + if (seriesCnt < 1) { + // No series, no aria label + return; + } + else { + var title = getTitle(); + if (title) { + ariaLabel = replace(getConfig('general.withTitle'), { + title: title + }); + } + else { + ariaLabel = getConfig('general.withoutTitle'); + } + + var seriesLabels = []; + var prefix = seriesCnt > 1 + ? 'series.multiple.prefix' + : 'series.single.prefix'; + ariaLabel += replace(getConfig(prefix), { seriesCount: seriesCnt }); + + ecModel.eachSeries(function (seriesModel, idx) { + if (idx < displaySeriesCnt) { + var seriesLabel; + + var seriesName = seriesModel.get('name'); + var seriesTpl = 'series.' + + (seriesCnt > 1 ? 'multiple' : 'single') + '.'; + seriesLabel = getConfig(seriesName + ? seriesTpl + 'withName' + : seriesTpl + 'withoutName'); + + seriesLabel = replace(seriesLabel, { + seriesId: seriesModel.seriesIndex, + seriesName: seriesModel.get('name'), + seriesType: getSeriesTypeName(seriesModel.subType) + }); + + var data = seriesModel.getData(); + window.data = data; + if (data.count() > maxDataCnt) { + // Show part of data + seriesLabel += replace(getConfig('data.partialData'), { + displayCnt: maxDataCnt + }); + } + else { + seriesLabel += getConfig('data.allData'); + } + + var dataLabels = []; + for (var i = 0; i < data.count(); i++) { + if (i < maxDataCnt) { + var name = data.getName(i); + var value = retrieveRawValue(data, i); + dataLabels.push( + replace( + name + ? getConfig('data.withName') + : getConfig('data.withoutName'), + { + name: name, + value: value + } + ) + ); + } + } + seriesLabel += dataLabels + .join(getConfig('data.separator.middle')) + + getConfig('data.separator.end'); + + seriesLabels.push(seriesLabel); + } + }); + + ariaLabel += seriesLabels + .join(getConfig('series.multiple.separator.middle')) + + getConfig('series.multiple.separator.end'); + + dom.setAttribute('aria-label', ariaLabel); + } + + function replace(str, keyValues) { + if (typeof str !== 'string') { + return str; + } + + var result = str; + each$1(keyValues, function (value, key) { + result = result.replace( + new RegExp('\\{\\s*' + key + '\\s*\\}', 'g'), + value + ); + }); + return result; + } + + function getConfig(path) { + var userConfig = ariaModel.get(path); + if (userConfig == null) { + var pathArr = path.split('.'); + var result = lang.aria; + for (var i = 0; i < pathArr.length; ++i) { + result = result[pathArr[i]]; + } + return result; + } + else { + return userConfig; + } + } + + function getTitle() { + var title = ecModel.getModel('title').option; + if (title && title.length) { + title = title[0]; + } + return title && title.text; + } + + function getSeriesTypeName(type) { + return lang.series.typeNames[type] || '自定义图'; + } +}; + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var PI$1 = Math.PI; + +/** + * @param {module:echarts/ExtensionAPI} api + * @param {Object} [opts] + * @param {string} [opts.text] + * @param {string} [opts.color] + * @param {string} [opts.textColor] + * @return {module:zrender/Element} + */ +var loadingDefault = function (api, opts) { + opts = opts || {}; + defaults(opts, { + text: 'loading', + color: '#c23531', + textColor: '#000', + maskColor: 'rgba(255, 255, 255, 0.8)', + zlevel: 0 + }); + var mask = new Rect({ + style: { + fill: opts.maskColor + }, + zlevel: opts.zlevel, + z: 10000 + }); + var arc = new Arc({ + shape: { + startAngle: -PI$1 / 2, + endAngle: -PI$1 / 2 + 0.1, + r: 10 + }, + style: { + stroke: opts.color, + lineCap: 'round', + lineWidth: 5 + }, + zlevel: opts.zlevel, + z: 10001 + }); + var labelRect = new Rect({ + style: { + fill: 'none', + text: opts.text, + textPosition: 'right', + textDistance: 10, + textFill: opts.textColor + }, + zlevel: opts.zlevel, + z: 10001 + }); + + arc.animateShape(true) + .when(1000, { + endAngle: PI$1 * 3 / 2 + }) + .start('circularInOut'); + arc.animateShape(true) + .when(1000, { + startAngle: PI$1 * 3 / 2 + }) + .delay(300) + .start('circularInOut'); + + var group = new Group(); + group.add(arc); + group.add(labelRect); + group.add(mask); + // Inject resize + group.resize = function () { + var cx = api.getWidth() / 2; + var cy = api.getHeight() / 2; + arc.setShape({ + cx: cx, + cy: cy + }); + var r = arc.shape.r; + labelRect.setShape({ + x: cx - r, + y: cy - r, + width: r * 2, + height: r * 2 + }); + + mask.setShape({ + x: 0, + y: 0, + width: api.getWidth(), + height: api.getHeight() + }); + }; + group.resize(); + return group; +}; + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/** + * @module echarts/stream/Scheduler + */ + +/** + * @constructor + */ +function Scheduler(ecInstance, api, dataProcessorHandlers, visualHandlers) { + this.ecInstance = ecInstance; + this.api = api; + this.unfinished; + + // Fix current processors in case that in some rear cases that + // processors might be registered after echarts instance created. + // Register processors incrementally for a echarts instance is + // not supported by this stream architecture. + var dataProcessorHandlers = this._dataProcessorHandlers = dataProcessorHandlers.slice(); + var visualHandlers = this._visualHandlers = visualHandlers.slice(); + this._allHandlers = dataProcessorHandlers.concat(visualHandlers); + + /** + * @private + * @type { + * [handlerUID: string]: { + * seriesTaskMap?: { + * [seriesUID: string]: Task + * }, + * overallTask?: Task + * } + * } + */ + this._stageTaskMap = createHashMap(); +} + +var proto = Scheduler.prototype; + +/** + * @param {module:echarts/model/Global} ecModel + * @param {Object} payload + */ +proto.restoreData = function (ecModel, payload) { + // TODO: Only restroe needed series and components, but not all components. + // Currently `restoreData` of all of the series and component will be called. + // But some independent components like `title`, `legend`, `graphic`, `toolbox`, + // `tooltip`, `axisPointer`, etc, do not need series refresh when `setOption`, + // and some components like coordinate system, axes, dataZoom, visualMap only + // need their target series refresh. + // (1) If we are implementing this feature some day, we should consider these cases: + // if a data processor depends on a component (e.g., dataZoomProcessor depends + // on the settings of `dataZoom`), it should be re-performed if the component + // is modified by `setOption`. + // (2) If a processor depends on sevral series, speicified by its `getTargetSeries`, + // it should be re-performed when the result array of `getTargetSeries` changed. + // We use `dependencies` to cover these issues. + // (3) How to update target series when coordinate system related components modified. + + // TODO: simply the dirty mechanism? Check whether only the case here can set tasks dirty, + // and this case all of the tasks will be set as dirty. + + ecModel.restoreData(payload); + + // Theoretically an overall task not only depends on each of its target series, but also + // depends on all of the series. + // The overall task is not in pipeline, and `ecModel.restoreData` only set pipeline tasks + // dirty. If `getTargetSeries` of an overall task returns nothing, we should also ensure + // that the overall task is set as dirty and to be performed, otherwise it probably cause + // state chaos. So we have to set dirty of all of the overall tasks manually, otherwise it + // probably cause state chaos (consider `dataZoomProcessor`). + this._stageTaskMap.each(function (taskRecord) { + var overallTask = taskRecord.overallTask; + overallTask && overallTask.dirty(); + }); +}; + +// If seriesModel provided, incremental threshold is check by series data. +proto.getPerformArgs = function (task, isBlock) { + // For overall task + if (!task.__pipeline) { + return; + } + + var pipeline = this._pipelineMap.get(task.__pipeline.id); + var pCtx = pipeline.context; + var incremental = !isBlock + && pipeline.progressiveEnabled + && (!pCtx || pCtx.progressiveRender) + && task.__idxInPipeline > pipeline.blockIndex; + + var step = incremental ? pipeline.step : null; + var modDataCount = pCtx && pCtx.modDataCount; + var modBy = modDataCount != null ? Math.ceil(modDataCount / step) : null; + + return {step: step, modBy: modBy, modDataCount: modDataCount}; +}; + +proto.getPipeline = function (pipelineId) { + return this._pipelineMap.get(pipelineId); +}; + +/** + * Current, progressive rendering starts from visual and layout. + * Always detect render mode in the same stage, avoiding that incorrect + * detection caused by data filtering. + * Caution: + * `updateStreamModes` use `seriesModel.getData()`. + */ +proto.updateStreamModes = function (seriesModel, view) { + var pipeline = this._pipelineMap.get(seriesModel.uid); + var data = seriesModel.getData(); + var dataLen = data.count(); + + // `progressiveRender` means that can render progressively in each + // animation frame. Note that some types of series do not provide + // `view.incrementalPrepareRender` but support `chart.appendData`. We + // use the term `incremental` but not `progressive` to describe the + // case that `chart.appendData`. + var progressiveRender = pipeline.progressiveEnabled + && view.incrementalPrepareRender + && dataLen >= pipeline.threshold; + + var large = seriesModel.get('large') && dataLen >= seriesModel.get('largeThreshold'); + + // TODO: modDataCount should not updated if `appendData`, otherwise cause whole repaint. + // see `test/candlestick-large3.html` + var modDataCount = seriesModel.get('progressiveChunkMode') === 'mod' ? dataLen : null; + + seriesModel.pipelineContext = pipeline.context = { + progressiveRender: progressiveRender, + modDataCount: modDataCount, + large: large + }; +}; + +proto.restorePipelines = function (ecModel) { + var scheduler = this; + var pipelineMap = scheduler._pipelineMap = createHashMap(); + + ecModel.eachSeries(function (seriesModel) { + var progressive = seriesModel.getProgressive(); + var pipelineId = seriesModel.uid; + + pipelineMap.set(pipelineId, { + id: pipelineId, + head: null, + tail: null, + threshold: seriesModel.getProgressiveThreshold(), + progressiveEnabled: progressive + && !(seriesModel.preventIncremental && seriesModel.preventIncremental()), + blockIndex: -1, + step: Math.round(progressive || 700), + count: 0 + }); + + pipe(scheduler, seriesModel, seriesModel.dataTask); + }); +}; + +proto.prepareStageTasks = function () { + var stageTaskMap = this._stageTaskMap; + var ecModel = this.ecInstance.getModel(); + var api = this.api; + + each$1(this._allHandlers, function (handler) { + var record = stageTaskMap.get(handler.uid) || stageTaskMap.set(handler.uid, []); + + handler.reset && createSeriesStageTask(this, handler, record, ecModel, api); + handler.overallReset && createOverallStageTask(this, handler, record, ecModel, api); + }, this); +}; + +proto.prepareView = function (view, model, ecModel, api) { + var renderTask = view.renderTask; + var context = renderTask.context; + + context.model = model; + context.ecModel = ecModel; + context.api = api; + + renderTask.__block = !view.incrementalPrepareRender; + + pipe(this, model, renderTask); +}; + + +proto.performDataProcessorTasks = function (ecModel, payload) { + // If we do not use `block` here, it should be considered when to update modes. + performStageTasks(this, this._dataProcessorHandlers, ecModel, payload, {block: true}); +}; + +// opt +// opt.visualType: 'visual' or 'layout' +// opt.setDirty +proto.performVisualTasks = function (ecModel, payload, opt) { + performStageTasks(this, this._visualHandlers, ecModel, payload, opt); +}; + +function performStageTasks(scheduler, stageHandlers, ecModel, payload, opt) { + opt = opt || {}; + var unfinished; + + each$1(stageHandlers, function (stageHandler, idx) { + if (opt.visualType && opt.visualType !== stageHandler.visualType) { + return; + } + + var stageHandlerRecord = scheduler._stageTaskMap.get(stageHandler.uid); + var seriesTaskMap = stageHandlerRecord.seriesTaskMap; + var overallTask = stageHandlerRecord.overallTask; + + if (overallTask) { + var overallNeedDirty; + var agentStubMap = overallTask.agentStubMap; + agentStubMap.each(function (stub) { + if (needSetDirty(opt, stub)) { + stub.dirty(); + overallNeedDirty = true; + } + }); + overallNeedDirty && overallTask.dirty(); + updatePayload(overallTask, payload); + var performArgs = scheduler.getPerformArgs(overallTask, opt.block); + // Execute stubs firstly, which may set the overall task dirty, + // then execute the overall task. And stub will call seriesModel.setData, + // which ensures that in the overallTask seriesModel.getData() will not + // return incorrect data. + agentStubMap.each(function (stub) { + stub.perform(performArgs); + }); + unfinished |= overallTask.perform(performArgs); + } + else if (seriesTaskMap) { + seriesTaskMap.each(function (task, pipelineId) { + if (needSetDirty(opt, task)) { + task.dirty(); + } + var performArgs = scheduler.getPerformArgs(task, opt.block); + performArgs.skip = !stageHandler.performRawSeries + && ecModel.isSeriesFiltered(task.context.model); + updatePayload(task, payload); + unfinished |= task.perform(performArgs); + }); + } + }); + + function needSetDirty(opt, task) { + return opt.setDirty && (!opt.dirtyMap || opt.dirtyMap.get(task.__pipeline.id)); + } + + scheduler.unfinished |= unfinished; +} + +proto.performSeriesTasks = function (ecModel) { + var unfinished; + + ecModel.eachSeries(function (seriesModel) { + // Progress to the end for dataInit and dataRestore. + unfinished |= seriesModel.dataTask.perform(); + }); + + this.unfinished |= unfinished; +}; + +proto.plan = function () { + // Travel pipelines, check block. + this._pipelineMap.each(function (pipeline) { + var task = pipeline.tail; + do { + if (task.__block) { + pipeline.blockIndex = task.__idxInPipeline; + break; + } + task = task.getUpstream(); + } + while (task); + }); +}; + +var updatePayload = proto.updatePayload = function (task, payload) { + payload !== 'remain' && (task.context.payload = payload); +}; + +function createSeriesStageTask(scheduler, stageHandler, stageHandlerRecord, ecModel, api) { + var seriesTaskMap = stageHandlerRecord.seriesTaskMap + || (stageHandlerRecord.seriesTaskMap = createHashMap()); + var seriesType = stageHandler.seriesType; + var getTargetSeries = stageHandler.getTargetSeries; + + // If a stageHandler should cover all series, `createOnAllSeries` should be declared mandatorily, + // to avoid some typo or abuse. Otherwise if an extension do not specify a `seriesType`, + // it works but it may cause other irrelevant charts blocked. + if (stageHandler.createOnAllSeries) { + ecModel.eachRawSeries(create); + } + else if (seriesType) { + ecModel.eachRawSeriesByType(seriesType, create); + } + else if (getTargetSeries) { + getTargetSeries(ecModel, api).each(create); + } + + function create(seriesModel) { + var pipelineId = seriesModel.uid; + + // Init tasks for each seriesModel only once. + // Reuse original task instance. + var task = seriesTaskMap.get(pipelineId) + || seriesTaskMap.set(pipelineId, createTask({ + plan: seriesTaskPlan, + reset: seriesTaskReset, + count: seriesTaskCount + })); + task.context = { + model: seriesModel, + ecModel: ecModel, + api: api, + useClearVisual: stageHandler.isVisual && !stageHandler.isLayout, + plan: stageHandler.plan, + reset: stageHandler.reset, + scheduler: scheduler + }; + pipe(scheduler, seriesModel, task); + } + + // Clear unused series tasks. + var pipelineMap = scheduler._pipelineMap; + seriesTaskMap.each(function (task, pipelineId) { + if (!pipelineMap.get(pipelineId)) { + task.dispose(); + seriesTaskMap.removeKey(pipelineId); + } + }); +} + +function createOverallStageTask(scheduler, stageHandler, stageHandlerRecord, ecModel, api) { + var overallTask = stageHandlerRecord.overallTask = stageHandlerRecord.overallTask + // For overall task, the function only be called on reset stage. + || createTask({reset: overallTaskReset}); + + overallTask.context = { + ecModel: ecModel, + api: api, + overallReset: stageHandler.overallReset, + scheduler: scheduler + }; + + // Reuse orignal stubs. + var agentStubMap = overallTask.agentStubMap = overallTask.agentStubMap || createHashMap(); + + var seriesType = stageHandler.seriesType; + var getTargetSeries = stageHandler.getTargetSeries; + var overallProgress = true; + var modifyOutputEnd = stageHandler.modifyOutputEnd; + + // An overall task with seriesType detected or has `getTargetSeries`, we add + // stub in each pipelines, it will set the overall task dirty when the pipeline + // progress. Moreover, to avoid call the overall task each frame (too frequent), + // we set the pipeline block. + if (seriesType) { + ecModel.eachRawSeriesByType(seriesType, createStub); + } + else if (getTargetSeries) { + getTargetSeries(ecModel, api).each(createStub); + } + // Otherwise, (usually it is legancy case), the overall task will only be + // executed when upstream dirty. Otherwise the progressive rendering of all + // pipelines will be disabled unexpectedly. But it still needs stubs to receive + // dirty info from upsteam. + else { + overallProgress = false; + each$1(ecModel.getSeries(), createStub); + } + + function createStub(seriesModel) { + var pipelineId = seriesModel.uid; + var stub = agentStubMap.get(pipelineId); + if (!stub) { + stub = agentStubMap.set(pipelineId, createTask( + {reset: stubReset, onDirty: stubOnDirty} + )); + // When the result of `getTargetSeries` changed, the overallTask + // should be set as dirty and re-performed. + overallTask.dirty(); + } + stub.context = { + model: seriesModel, + overallProgress: overallProgress, + modifyOutputEnd: modifyOutputEnd + }; + stub.agent = overallTask; + stub.__block = overallProgress; + + pipe(scheduler, seriesModel, stub); + } + + // Clear unused stubs. + var pipelineMap = scheduler._pipelineMap; + agentStubMap.each(function (stub, pipelineId) { + if (!pipelineMap.get(pipelineId)) { + stub.dispose(); + // When the result of `getTargetSeries` changed, the overallTask + // should be set as dirty and re-performed. + overallTask.dirty(); + agentStubMap.removeKey(pipelineId); + } + }); +} + +function overallTaskReset(context) { + context.overallReset( + context.ecModel, context.api, context.payload + ); +} + +function stubReset(context, upstreamContext) { + return context.overallProgress && stubProgress; +} + +function stubProgress() { + this.agent.dirty(); + this.getDownstream().dirty(); +} + +function stubOnDirty() { + this.agent && this.agent.dirty(); +} + +function seriesTaskPlan(context) { + return context.plan && context.plan( + context.model, context.ecModel, context.api, context.payload + ); +} + +function seriesTaskReset(context) { + if (context.useClearVisual) { + context.data.clearAllVisual(); + } + var resetDefines = context.resetDefines = normalizeToArray(context.reset( + context.model, context.ecModel, context.api, context.payload + )); + return resetDefines.length > 1 + ? map(resetDefines, function (v, idx) { + return makeSeriesTaskProgress(idx); + }) + : singleSeriesTaskProgress; +} + +var singleSeriesTaskProgress = makeSeriesTaskProgress(0); + +function makeSeriesTaskProgress(resetDefineIdx) { + return function (params, context) { + var data = context.data; + var resetDefine = context.resetDefines[resetDefineIdx]; + + if (resetDefine && resetDefine.dataEach) { + for (var i = params.start; i < params.end; i++) { + resetDefine.dataEach(data, i); + } + } + else if (resetDefine && resetDefine.progress) { + resetDefine.progress(params, data); + } + }; +} + +function seriesTaskCount(context) { + return context.data.count(); +} + +function pipe(scheduler, seriesModel, task) { + var pipelineId = seriesModel.uid; + var pipeline = scheduler._pipelineMap.get(pipelineId); + !pipeline.head && (pipeline.head = task); + pipeline.tail && pipeline.tail.pipe(task); + pipeline.tail = task; + task.__idxInPipeline = pipeline.count++; + task.__pipeline = pipeline; +} + +Scheduler.wrapStageHandler = function (stageHandler, visualType) { + if (isFunction$1(stageHandler)) { + stageHandler = { + overallReset: stageHandler, + seriesType: detectSeriseType(stageHandler) + }; + } + + stageHandler.uid = getUID('stageHandler'); + visualType && (stageHandler.visualType = visualType); + + return stageHandler; +}; + + + +/** + * Only some legacy stage handlers (usually in echarts extensions) are pure function. + * To ensure that they can work normally, they should work in block mode, that is, + * they should not be started util the previous tasks finished. So they cause the + * progressive rendering disabled. We try to detect the series type, to narrow down + * the block range to only the series type they concern, but not all series. + */ +function detectSeriseType(legacyFunc) { + seriesType = null; + try { + // Assume there is no async when calling `eachSeriesByType`. + legacyFunc(ecModelMock, apiMock); + } + catch (e) { + } + return seriesType; +} + +var ecModelMock = {}; +var apiMock = {}; +var seriesType; + +mockMethods(ecModelMock, GlobalModel); +mockMethods(apiMock, ExtensionAPI); +ecModelMock.eachSeriesByType = ecModelMock.eachRawSeriesByType = function (type) { + seriesType = type; +}; +ecModelMock.eachComponent = function (cond) { + if (cond.mainType === 'series' && cond.subType) { + seriesType = cond.subType; + } +}; + +function mockMethods(target, Clz) { + /* eslint-disable */ + for (var name in Clz.prototype) { + // Do not use hasOwnProperty + target[name] = noop; + } + /* eslint-enable */ +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var colorAll = [ + '#37A2DA', '#32C5E9', '#67E0E3', '#9FE6B8', '#FFDB5C', '#ff9f7f', + '#fb7293', '#E062AE', '#E690D1', '#e7bcf3', '#9d96f5', '#8378EA', '#96BFFF' +]; + +var lightTheme = { + + color: colorAll, + + colorLayer: [ + ['#37A2DA', '#ffd85c', '#fd7b5f'], + ['#37A2DA', '#67E0E3', '#FFDB5C', '#ff9f7f', '#E062AE', '#9d96f5'], + ['#37A2DA', '#32C5E9', '#9FE6B8', '#FFDB5C', '#ff9f7f', '#fb7293', '#e7bcf3', '#8378EA', '#96BFFF'], + colorAll + ] +}; + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var contrastColor = '#eee'; +var axisCommon = function () { + return { + axisLine: { + lineStyle: { + color: contrastColor + } + }, + axisTick: { + lineStyle: { + color: contrastColor + } + }, + axisLabel: { + textStyle: { + color: contrastColor + } + }, + splitLine: { + lineStyle: { + type: 'dashed', + color: '#aaa' + } + }, + splitArea: { + areaStyle: { + color: contrastColor + } + } + }; +}; + +var colorPalette = [ + '#dd6b66', '#759aa0', '#e69d87', '#8dc1a9', '#ea7e53', + '#eedd78', '#73a373', '#73b9bc', '#7289ab', '#91ca8c', '#f49f42' +]; +var theme = { + color: colorPalette, + backgroundColor: '#333', + tooltip: { + axisPointer: { + lineStyle: { + color: contrastColor + }, + crossStyle: { + color: contrastColor + } + } + }, + legend: { + textStyle: { + color: contrastColor + } + }, + textStyle: { + color: contrastColor + }, + title: { + textStyle: { + color: contrastColor + } + }, + toolbox: { + iconStyle: { + normal: { + borderColor: contrastColor + } + } + }, + dataZoom: { + textStyle: { + color: contrastColor + } + }, + visualMap: { + textStyle: { + color: contrastColor + } + }, + timeline: { + lineStyle: { + color: contrastColor + }, + itemStyle: { + normal: { + color: colorPalette[1] + } + }, + label: { + normal: { + textStyle: { + color: contrastColor + } + } + }, + controlStyle: { + normal: { + color: contrastColor, + borderColor: contrastColor + } + } + }, + timeAxis: axisCommon(), + logAxis: axisCommon(), + valueAxis: axisCommon(), + categoryAxis: axisCommon(), + + line: { + symbol: 'circle' + }, + graph: { + color: colorPalette + }, + gauge: { + title: { + textStyle: { + color: contrastColor + } + } + }, + candlestick: { + itemStyle: { + normal: { + color: '#FD1050', + color0: '#0CF49B', + borderColor: '#FD1050', + borderColor0: '#0CF49B' + } + } + } +}; +theme.categoryAxis.splitLine.show = false; + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/** + * This module is imported by echarts directly. + * + * Notice: + * Always keep this file exists for backward compatibility. + * Because before 4.1.0, dataset is an optional component, + * some users may import this module manually. + */ + +ComponentModel.extend({ + + type: 'dataset', + + /** + * @protected + */ + defaultOption: { + + // 'row', 'column' + seriesLayoutBy: SERIES_LAYOUT_BY_COLUMN, + + // null/'auto': auto detect header, see "module:echarts/data/helper/sourceHelper" + sourceHeader: null, + + dimensions: null, + + source: null + }, + + optionUpdated: function () { + detectSourceFormat(this); + } + +}); + +Component.extend({ + + type: 'dataset' + +}); + +/** + * 椭圆形状 + * @module zrender/graphic/shape/Ellipse + */ + +var Ellipse = Path.extend({ + + type: 'ellipse', + + shape: { + cx: 0, cy: 0, + rx: 0, ry: 0 + }, + + buildPath: function (ctx, shape) { + var k = 0.5522848; + var x = shape.cx; + var y = shape.cy; + var a = shape.rx; + var b = shape.ry; + var ox = a * k; // 水平控制点偏移量 + var oy = b * k; // 垂直控制点偏移量 + // 从椭圆的左端点开始顺时针绘制四条三次贝塞尔曲线 + ctx.moveTo(x - a, y); + ctx.bezierCurveTo(x - a, y - oy, x - ox, y - b, x, y - b); + ctx.bezierCurveTo(x + ox, y - b, x + a, y - oy, x + a, y); + ctx.bezierCurveTo(x + a, y + oy, x + ox, y + b, x, y + b); + ctx.bezierCurveTo(x - ox, y + b, x - a, y + oy, x - a, y); + ctx.closePath(); + } +}); + +// import RadialGradient from '../graphic/RadialGradient'; +// import Pattern from '../graphic/Pattern'; +// import * as vector from '../core/vector'; +// Most of the values can be separated by comma and/or white space. +var DILIMITER_REG = /[\s,]+/; + +/** + * For big svg string, this method might be time consuming. + * + * @param {string} svg xml string + * @return {Object} xml root. + */ +function parseXML(svg) { + if (isString(svg)) { + var parser = new DOMParser(); + svg = parser.parseFromString(svg, 'text/xml'); + } + + // Document node. If using $.get, doc node may be input. + if (svg.nodeType === 9) { + svg = svg.firstChild; + } + // nodeName of is also 'svg'. + while (svg.nodeName.toLowerCase() !== 'svg' || svg.nodeType !== 1) { + svg = svg.nextSibling; + } + + return svg; +} + +function SVGParser() { + this._defs = {}; + this._root = null; + + this._isDefine = false; + this._isText = false; +} + +SVGParser.prototype.parse = function (xml, opt) { + opt = opt || {}; + + var svg = parseXML(xml); + + if (!svg) { + throw new Error('Illegal svg'); + } + + var root = new Group(); + this._root = root; + // parse view port + var viewBox = svg.getAttribute('viewBox') || ''; + + // If width/height not specified, means "100%" of `opt.width/height`. + // TODO: Other percent value not supported yet. + var width = parseFloat(svg.getAttribute('width') || opt.width); + var height = parseFloat(svg.getAttribute('height') || opt.height); + // If width/height not specified, set as null for output. + isNaN(width) && (width = null); + isNaN(height) && (height = null); + + // Apply inline style on svg element. + parseAttributes(svg, root, null, true); + + var child = svg.firstChild; + while (child) { + this._parseNode(child, root); + child = child.nextSibling; + } + + var viewBoxRect; + var viewBoxTransform; + + if (viewBox) { + var viewBoxArr = trim(viewBox).split(DILIMITER_REG); + // Some invalid case like viewBox: 'none'. + if (viewBoxArr.length >= 4) { + viewBoxRect = { + x: parseFloat(viewBoxArr[0] || 0), + y: parseFloat(viewBoxArr[1] || 0), + width: parseFloat(viewBoxArr[2]), + height: parseFloat(viewBoxArr[3]) + }; + } + } + + if (viewBoxRect && width != null && height != null) { + viewBoxTransform = makeViewBoxTransform(viewBoxRect, width, height); + + if (!opt.ignoreViewBox) { + // If set transform on the output group, it probably bring trouble when + // some users only intend to show the clipped content inside the viewBox, + // but not intend to transform the output group. So we keep the output + // group no transform. If the user intend to use the viewBox as a + // camera, just set `opt.ignoreViewBox` as `true` and set transfrom + // manually according to the viewBox info in the output of this method. + var elRoot = root; + root = new Group(); + root.add(elRoot); + elRoot.scale = viewBoxTransform.scale.slice(); + elRoot.position = viewBoxTransform.position.slice(); + } + } + + // Some shapes might be overflow the viewport, which should be + // clipped despite whether the viewBox is used, as the SVG does. + if (!opt.ignoreRootClip && width != null && height != null) { + root.setClipPath(new Rect({ + shape: {x: 0, y: 0, width: width, height: height} + })); + } + + // Set width/height on group just for output the viewport size. + return { + root: root, + width: width, + height: height, + viewBoxRect: viewBoxRect, + viewBoxTransform: viewBoxTransform + }; +}; + +SVGParser.prototype._parseNode = function (xmlNode, parentGroup) { + + var nodeName = xmlNode.nodeName.toLowerCase(); + + // TODO + // support in svg, where nodeName is 'style', + // CSS classes is defined globally wherever the style tags are declared. + + if (nodeName === 'defs') { + // define flag + this._isDefine = true; + } + else if (nodeName === 'text') { + this._isText = true; + } + + var el; + if (this._isDefine) { + var parser = defineParsers[nodeName]; + if (parser) { + var def = parser.call(this, xmlNode); + var id = xmlNode.getAttribute('id'); + if (id) { + this._defs[id] = def; + } + } + } + else { + var parser = nodeParsers[nodeName]; + if (parser) { + el = parser.call(this, xmlNode, parentGroup); + parentGroup.add(el); + } + } + + var child = xmlNode.firstChild; + while (child) { + if (child.nodeType === 1) { + this._parseNode(child, el); + } + // Is text + if (child.nodeType === 3 && this._isText) { + this._parseText(child, el); + } + child = child.nextSibling; + } + + // Quit define + if (nodeName === 'defs') { + this._isDefine = false; + } + else if (nodeName === 'text') { + this._isText = false; + } +}; + +SVGParser.prototype._parseText = function (xmlNode, parentGroup) { + if (xmlNode.nodeType === 1) { + var dx = xmlNode.getAttribute('dx') || 0; + var dy = xmlNode.getAttribute('dy') || 0; + this._textX += parseFloat(dx); + this._textY += parseFloat(dy); + } + + var text = new Text({ + style: { + text: xmlNode.textContent, + transformText: true + }, + position: [this._textX || 0, this._textY || 0] + }); + + inheritStyle(parentGroup, text); + parseAttributes(xmlNode, text, this._defs); + + var fontSize = text.style.fontSize; + if (fontSize && fontSize < 9) { + // PENDING + text.style.fontSize = 9; + text.scale = text.scale || [1, 1]; + text.scale[0] *= fontSize / 9; + text.scale[1] *= fontSize / 9; + } + + var rect = text.getBoundingRect(); + this._textX += rect.width; + + parentGroup.add(text); + + return text; +}; + +var nodeParsers = { + 'g': function (xmlNode, parentGroup) { + var g = new Group(); + inheritStyle(parentGroup, g); + parseAttributes(xmlNode, g, this._defs); + + return g; + }, + 'rect': function (xmlNode, parentGroup) { + var rect = new Rect(); + inheritStyle(parentGroup, rect); + parseAttributes(xmlNode, rect, this._defs); + + rect.setShape({ + x: parseFloat(xmlNode.getAttribute('x') || 0), + y: parseFloat(xmlNode.getAttribute('y') || 0), + width: parseFloat(xmlNode.getAttribute('width') || 0), + height: parseFloat(xmlNode.getAttribute('height') || 0) + }); + + // console.log(xmlNode.getAttribute('transform')); + // console.log(rect.transform); + + return rect; + }, + 'circle': function (xmlNode, parentGroup) { + var circle = new Circle(); + inheritStyle(parentGroup, circle); + parseAttributes(xmlNode, circle, this._defs); + + circle.setShape({ + cx: parseFloat(xmlNode.getAttribute('cx') || 0), + cy: parseFloat(xmlNode.getAttribute('cy') || 0), + r: parseFloat(xmlNode.getAttribute('r') || 0) + }); + + return circle; + }, + 'line': function (xmlNode, parentGroup) { + var line = new Line(); + inheritStyle(parentGroup, line); + parseAttributes(xmlNode, line, this._defs); + + line.setShape({ + x1: parseFloat(xmlNode.getAttribute('x1') || 0), + y1: parseFloat(xmlNode.getAttribute('y1') || 0), + x2: parseFloat(xmlNode.getAttribute('x2') || 0), + y2: parseFloat(xmlNode.getAttribute('y2') || 0) + }); + + return line; + }, + 'ellipse': function (xmlNode, parentGroup) { + var ellipse = new Ellipse(); + inheritStyle(parentGroup, ellipse); + parseAttributes(xmlNode, ellipse, this._defs); + + ellipse.setShape({ + cx: parseFloat(xmlNode.getAttribute('cx') || 0), + cy: parseFloat(xmlNode.getAttribute('cy') || 0), + rx: parseFloat(xmlNode.getAttribute('rx') || 0), + ry: parseFloat(xmlNode.getAttribute('ry') || 0) + }); + return ellipse; + }, + 'polygon': function (xmlNode, parentGroup) { + var points = xmlNode.getAttribute('points'); + if (points) { + points = parsePoints(points); + } + var polygon = new Polygon({ + shape: { + points: points || [] + } + }); + + inheritStyle(parentGroup, polygon); + parseAttributes(xmlNode, polygon, this._defs); + + return polygon; + }, + 'polyline': function (xmlNode, parentGroup) { + var path = new Path(); + inheritStyle(parentGroup, path); + parseAttributes(xmlNode, path, this._defs); + + var points = xmlNode.getAttribute('points'); + if (points) { + points = parsePoints(points); + } + var polyline = new Polyline({ + shape: { + points: points || [] + } + }); + + return polyline; + }, + 'image': function (xmlNode, parentGroup) { + var img = new ZImage(); + inheritStyle(parentGroup, img); + parseAttributes(xmlNode, img, this._defs); + + img.setStyle({ + image: xmlNode.getAttribute('xlink:href'), + x: xmlNode.getAttribute('x'), + y: xmlNode.getAttribute('y'), + width: xmlNode.getAttribute('width'), + height: xmlNode.getAttribute('height') + }); + + return img; + }, + 'text': function (xmlNode, parentGroup) { + var x = xmlNode.getAttribute('x') || 0; + var y = xmlNode.getAttribute('y') || 0; + var dx = xmlNode.getAttribute('dx') || 0; + var dy = xmlNode.getAttribute('dy') || 0; + + this._textX = parseFloat(x) + parseFloat(dx); + this._textY = parseFloat(y) + parseFloat(dy); + + var g = new Group(); + inheritStyle(parentGroup, g); + parseAttributes(xmlNode, g, this._defs); + + return g; + }, + 'tspan': function (xmlNode, parentGroup) { + var x = xmlNode.getAttribute('x'); + var y = xmlNode.getAttribute('y'); + if (x != null) { + // new offset x + this._textX = parseFloat(x); + } + if (y != null) { + // new offset y + this._textY = parseFloat(y); + } + var dx = xmlNode.getAttribute('dx') || 0; + var dy = xmlNode.getAttribute('dy') || 0; + + var g = new Group(); + + inheritStyle(parentGroup, g); + parseAttributes(xmlNode, g, this._defs); + + + this._textX += dx; + this._textY += dy; + + return g; + }, + 'path': function (xmlNode, parentGroup) { + // TODO svg fill rule + // https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-rule + // path.style.globalCompositeOperation = 'xor'; + var d = xmlNode.getAttribute('d') || ''; + + // Performance sensitive. + + var path = createFromString(d); + + inheritStyle(parentGroup, path); + parseAttributes(xmlNode, path, this._defs); + + return path; + } +}; + +var defineParsers = { + + 'lineargradient': function (xmlNode) { + var x1 = parseInt(xmlNode.getAttribute('x1') || 0, 10); + var y1 = parseInt(xmlNode.getAttribute('y1') || 0, 10); + var x2 = parseInt(xmlNode.getAttribute('x2') || 10, 10); + var y2 = parseInt(xmlNode.getAttribute('y2') || 0, 10); + + var gradient = new LinearGradient(x1, y1, x2, y2); + + _parseGradientColorStops(xmlNode, gradient); + + return gradient; + }, + + 'radialgradient': function (xmlNode) { + + } +}; + +function _parseGradientColorStops(xmlNode, gradient) { + + var stop = xmlNode.firstChild; + + while (stop) { + if (stop.nodeType === 1) { + var offset = stop.getAttribute('offset'); + if (offset.indexOf('%') > 0) { // percentage + offset = parseInt(offset, 10) / 100; + } + else if (offset) { // number from 0 to 1 + offset = parseFloat(offset); + } + else { + offset = 0; + } + + var stopColor = stop.getAttribute('stop-color') || '#000000'; + + gradient.addColorStop(offset, stopColor); + } + stop = stop.nextSibling; + } +} + +function inheritStyle(parent, child) { + if (parent && parent.__inheritedStyle) { + if (!child.__inheritedStyle) { + child.__inheritedStyle = {}; + } + defaults(child.__inheritedStyle, parent.__inheritedStyle); + } +} + +function parsePoints(pointsString) { + var list = trim(pointsString).split(DILIMITER_REG); + var points = []; + + for (var i = 0; i < list.length; i += 2) { + var x = parseFloat(list[i]); + var y = parseFloat(list[i + 1]); + points.push([x, y]); + } + return points; +} + +var attributesMap = { + 'fill': 'fill', + 'stroke': 'stroke', + 'stroke-width': 'lineWidth', + 'opacity': 'opacity', + 'fill-opacity': 'fillOpacity', + 'stroke-opacity': 'strokeOpacity', + 'stroke-dasharray': 'lineDash', + 'stroke-dashoffset': 'lineDashOffset', + 'stroke-linecap': 'lineCap', + 'stroke-linejoin': 'lineJoin', + 'stroke-miterlimit': 'miterLimit', + 'font-family': 'fontFamily', + 'font-size': 'fontSize', + 'font-style': 'fontStyle', + 'font-weight': 'fontWeight', + + 'text-align': 'textAlign', + 'alignment-baseline': 'textBaseline' +}; + +function parseAttributes(xmlNode, el, defs, onlyInlineStyle) { + var zrStyle = el.__inheritedStyle || {}; + var isTextEl = el.type === 'text'; + + // TODO Shadow + if (xmlNode.nodeType === 1) { + parseTransformAttribute(xmlNode, el); + + extend(zrStyle, parseStyleAttribute(xmlNode)); + + if (!onlyInlineStyle) { + for (var svgAttrName in attributesMap) { + if (attributesMap.hasOwnProperty(svgAttrName)) { + var attrValue = xmlNode.getAttribute(svgAttrName); + if (attrValue != null) { + zrStyle[attributesMap[svgAttrName]] = attrValue; + } + } + } + } + } + + var elFillProp = isTextEl ? 'textFill' : 'fill'; + var elStrokeProp = isTextEl ? 'textStroke' : 'stroke'; + + el.style = el.style || new Style(); + var elStyle = el.style; + + zrStyle.fill != null && elStyle.set(elFillProp, getPaint(zrStyle.fill, defs)); + zrStyle.stroke != null && elStyle.set(elStrokeProp, getPaint(zrStyle.stroke, defs)); + + each$1([ + 'lineWidth', 'opacity', 'fillOpacity', 'strokeOpacity', 'miterLimit', 'fontSize' + ], function (propName) { + var elPropName = (propName === 'lineWidth' && isTextEl) ? 'textStrokeWidth' : propName; + zrStyle[propName] != null && elStyle.set(elPropName, parseFloat(zrStyle[propName])); + }); + + if (!zrStyle.textBaseline || zrStyle.textBaseline === 'auto') { + zrStyle.textBaseline = 'alphabetic'; + } + if (zrStyle.textBaseline === 'alphabetic') { + zrStyle.textBaseline = 'bottom'; + } + if (zrStyle.textAlign === 'start') { + zrStyle.textAlign = 'left'; + } + if (zrStyle.textAlign === 'end') { + zrStyle.textAlign = 'right'; + } + + each$1(['lineDashOffset', 'lineCap', 'lineJoin', + 'fontWeight', 'fontFamily', 'fontStyle', 'textAlign', 'textBaseline' + ], function (propName) { + zrStyle[propName] != null && elStyle.set(propName, zrStyle[propName]); + }); + + if (zrStyle.lineDash) { + el.style.lineDash = trim(zrStyle.lineDash).split(DILIMITER_REG); + } + + if (elStyle[elStrokeProp] && elStyle[elStrokeProp] !== 'none') { + // enable stroke + el[elStrokeProp] = true; + } + + el.__inheritedStyle = zrStyle; +} + + +var urlRegex = /url\(\s*#(.*?)\)/; +function getPaint(str, defs) { + // if (str === 'none') { + // return; + // } + var urlMatch = defs && str && str.match(urlRegex); + if (urlMatch) { + var url = trim(urlMatch[1]); + var def = defs[url]; + return def; + } + return str; +} + +var transformRegex = /(translate|scale|rotate|skewX|skewY|matrix)\(([\-\s0-9\.e,]*)\)/g; + +function parseTransformAttribute(xmlNode, node) { + var transform = xmlNode.getAttribute('transform'); + if (transform) { + transform = transform.replace(/,/g, ' '); + var m = null; + var transformOps = []; + transform.replace(transformRegex, function (str, type, value) { + transformOps.push(type, value); + }); + for (var i = transformOps.length - 1; i > 0; i -= 2) { + var value = transformOps[i]; + var type = transformOps[i - 1]; + m = m || create$1(); + switch (type) { + case 'translate': + value = trim(value).split(DILIMITER_REG); + translate(m, m, [parseFloat(value[0]), parseFloat(value[1] || 0)]); + break; + case 'scale': + value = trim(value).split(DILIMITER_REG); + scale$1(m, m, [parseFloat(value[0]), parseFloat(value[1] || value[0])]); + break; + case 'rotate': + value = trim(value).split(DILIMITER_REG); + rotate(m, m, parseFloat(value[0])); + break; + case 'skew': + value = trim(value).split(DILIMITER_REG); + console.warn('Skew transform is not supported yet'); + break; + case 'matrix': + var value = trim(value).split(DILIMITER_REG); + m[0] = parseFloat(value[0]); + m[1] = parseFloat(value[1]); + m[2] = parseFloat(value[2]); + m[3] = parseFloat(value[3]); + m[4] = parseFloat(value[4]); + m[5] = parseFloat(value[5]); + break; + } + } + node.setLocalTransform(m); + } +} + +// Value may contain space. +var styleRegex = /([^\s:;]+)\s*:\s*([^:;]+)/g; +function parseStyleAttribute(xmlNode) { + var style = xmlNode.getAttribute('style'); + var result = {}; + + if (!style) { + return result; + } + + var styleList = {}; + styleRegex.lastIndex = 0; + var styleRegResult; + while ((styleRegResult = styleRegex.exec(style)) != null) { + styleList[styleRegResult[1]] = styleRegResult[2]; + } + + for (var svgAttrName in attributesMap) { + if (attributesMap.hasOwnProperty(svgAttrName) && styleList[svgAttrName] != null) { + result[attributesMap[svgAttrName]] = styleList[svgAttrName]; + } + } + + return result; +} + +/** + * @param {Array.} viewBoxRect + * @param {number} width + * @param {number} height + * @return {Object} {scale, position} + */ +function makeViewBoxTransform(viewBoxRect, width, height) { + var scaleX = width / viewBoxRect.width; + var scaleY = height / viewBoxRect.height; + var scale = Math.min(scaleX, scaleY); + // preserveAspectRatio 'xMidYMid' + var viewBoxScale = [scale, scale]; + var viewBoxPosition = [ + -(viewBoxRect.x + viewBoxRect.width / 2) * scale + width / 2, + -(viewBoxRect.y + viewBoxRect.height / 2) * scale + height / 2 + ]; + + return { + scale: viewBoxScale, + position: viewBoxPosition + }; +} + +/** + * @param {string|XMLElement} xml + * @param {Object} [opt] + * @param {number} [opt.width] Default width if svg width not specified or is a percent value. + * @param {number} [opt.height] Default height if svg height not specified or is a percent value. + * @param {boolean} [opt.ignoreViewBox] + * @param {boolean} [opt.ignoreRootClip] + * @return {Object} result: + * { + * root: Group, The root of the the result tree of zrender shapes, + * width: number, the viewport width of the SVG, + * height: number, the viewport height of the SVG, + * viewBoxRect: {x, y, width, height}, the declared viewBox rect of the SVG, if exists, + * viewBoxTransform: the {scale, position} calculated by viewBox and viewport, is exists. + * } + */ +function parseSVG(xml, opt) { + var parser = new SVGParser(); + return parser.parse(xml, opt); +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var storage = createHashMap(); + +// For minimize the code size of common echarts package, +// do not put too much logic in this module. + +var mapDataStorage = { + + // The format of record: see `echarts.registerMap`. + // Compatible with previous `echarts.registerMap`. + registerMap: function (mapName, rawGeoJson, rawSpecialAreas) { + + var records; + + if (isArray(rawGeoJson)) { + records = rawGeoJson; + } + else if (rawGeoJson.svg) { + records = [{ + type: 'svg', + source: rawGeoJson.svg, + specialAreas: rawGeoJson.specialAreas + }]; + } + else { + // Backward compatibility. + if (rawGeoJson.geoJson && !rawGeoJson.features) { + rawSpecialAreas = rawGeoJson.specialAreas; + rawGeoJson = rawGeoJson.geoJson; + } + records = [{ + type: 'geoJSON', + source: rawGeoJson, + specialAreas: rawSpecialAreas + }]; + } + + each$1(records, function (record) { + var type = record.type; + type === 'geoJson' && (type = record.type = 'geoJSON'); + + var parse = parsers[type]; + + if (__DEV__) { + assert$1(parse, 'Illegal map type: ' + type); + } + + parse(record); + }); + + return storage.set(mapName, records); + }, + + retrieveMap: function (mapName) { + return storage.get(mapName); + } + +}; + +var parsers = { + + geoJSON: function (record) { + var source = record.source; + record.geoJSON = !isString(source) + ? source + : (typeof JSON !== 'undefined' && JSON.parse) + ? JSON.parse(source) + : (new Function('return (' + source + ');'))(); + }, + + // Only perform parse to XML object here, which might be time + // consiming for large SVG. + // Although convert XML to zrender element is also time consiming, + // if we do it here, the clone of zrender elements has to be + // required. So we do it once for each geo instance, util real + // performance issues call for optimizing it. + svg: function (record) { + record.svgXML = parseXML(record.source); + } + +}; + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ +var assert = assert$1; +var each = each$1; +var isFunction = isFunction$1; +var isObject = isObject$1; +var parseClassType = ComponentModel.parseClassType; + +var version = '4.2.1'; + +var dependencies = { + zrender: '4.0.6' +}; + +var TEST_FRAME_REMAIN_TIME = 1; + +var PRIORITY_PROCESSOR_FILTER = 1000; +var PRIORITY_PROCESSOR_STATISTIC = 5000; + +var PRIORITY_VISUAL_LAYOUT = 1000; +var PRIORITY_VISUAL_GLOBAL = 2000; +var PRIORITY_VISUAL_CHART = 3000; +var PRIORITY_VISUAL_COMPONENT = 4000; +// FIXME +// necessary? +var PRIORITY_VISUAL_BRUSH = 5000; + +var PRIORITY = { + PROCESSOR: { + FILTER: PRIORITY_PROCESSOR_FILTER, + STATISTIC: PRIORITY_PROCESSOR_STATISTIC + }, + VISUAL: { + LAYOUT: PRIORITY_VISUAL_LAYOUT, + GLOBAL: PRIORITY_VISUAL_GLOBAL, + CHART: PRIORITY_VISUAL_CHART, + COMPONENT: PRIORITY_VISUAL_COMPONENT, + BRUSH: PRIORITY_VISUAL_BRUSH + } +}; + +// Main process have three entries: `setOption`, `dispatchAction` and `resize`, +// where they must not be invoked nestedly, except the only case: invoke +// dispatchAction with updateMethod "none" in main process. +// This flag is used to carry out this rule. +// All events will be triggered out side main process (i.e. when !this[IN_MAIN_PROCESS]). +var IN_MAIN_PROCESS = '__flagInMainProcess'; +var OPTION_UPDATED = '__optionUpdated'; +var ACTION_REG = /^[a-zA-Z0-9_]+$/; + + +function createRegisterEventWithLowercaseName(method) { + return function (eventName, handler, context) { + // Event name is all lowercase + eventName = eventName && eventName.toLowerCase(); + Eventful.prototype[method].call(this, eventName, handler, context); + }; +} + +/** + * @module echarts~MessageCenter + */ +function MessageCenter() { + Eventful.call(this); +} +MessageCenter.prototype.on = createRegisterEventWithLowercaseName('on'); +MessageCenter.prototype.off = createRegisterEventWithLowercaseName('off'); +MessageCenter.prototype.one = createRegisterEventWithLowercaseName('one'); +mixin(MessageCenter, Eventful); + +/** + * @module echarts~ECharts + */ +function ECharts(dom, theme$$1, opts) { + opts = opts || {}; + + // Get theme by name + if (typeof theme$$1 === 'string') { + theme$$1 = themeStorage[theme$$1]; + } + + /** + * @type {string} + */ + this.id; + + /** + * Group id + * @type {string} + */ + this.group; + + /** + * @type {HTMLElement} + * @private + */ + this._dom = dom; + + var defaultRenderer = 'canvas'; + if (__DEV__) { + defaultRenderer = ( + typeof window === 'undefined' ? global : window + ).__ECHARTS__DEFAULT__RENDERER__ || defaultRenderer; + } + + /** + * @type {module:zrender/ZRender} + * @private + */ + var zr = this._zr = init$1(dom, { + renderer: opts.renderer || defaultRenderer, + devicePixelRatio: opts.devicePixelRatio, + width: opts.width, + height: opts.height + }); + + /** + * Expect 60 pfs. + * @type {Function} + * @private + */ + this._throttledZrFlush = throttle(bind(zr.flush, zr), 17); + + var theme$$1 = clone(theme$$1); + theme$$1 && backwardCompat(theme$$1, true); + /** + * @type {Object} + * @private + */ + this._theme = theme$$1; + + /** + * @type {Array.} + * @private + */ + this._chartsViews = []; + + /** + * @type {Object.} + * @private + */ + this._chartsMap = {}; + + /** + * @type {Array.} + * @private + */ + this._componentsViews = []; + + /** + * @type {Object.} + * @private + */ + this._componentsMap = {}; + + /** + * @type {module:echarts/CoordinateSystem} + * @private + */ + this._coordSysMgr = new CoordinateSystemManager(); + + /** + * @type {module:echarts/ExtensionAPI} + * @private + */ + var api = this._api = createExtensionAPI(this); + + // Sort on demand + function prioritySortFunc(a, b) { + return a.__prio - b.__prio; + } + sort(visualFuncs, prioritySortFunc); + sort(dataProcessorFuncs, prioritySortFunc); + + /** + * @type {module:echarts/stream/Scheduler} + */ + this._scheduler = new Scheduler(this, api, dataProcessorFuncs, visualFuncs); + + Eventful.call(this, this._ecEventProcessor = new EventProcessor()); + + /** + * @type {module:echarts~MessageCenter} + * @private + */ + this._messageCenter = new MessageCenter(); + + // Init mouse events + this._initEvents(); + + // In case some people write `window.onresize = chart.resize` + this.resize = bind(this.resize, this); + + // Can't dispatch action during rendering procedure + this._pendingActions = []; + + zr.animation.on('frame', this._onframe, this); + + bindRenderedEvent(zr, this); + + // ECharts instance can be used as value. + setAsPrimitive(this); +} + +var echartsProto = ECharts.prototype; + +echartsProto._onframe = function () { + if (this._disposed) { + return; + } + + var scheduler = this._scheduler; + + // Lazy update + if (this[OPTION_UPDATED]) { + var silent = this[OPTION_UPDATED].silent; + + this[IN_MAIN_PROCESS] = true; + + prepare(this); + updateMethods.update.call(this); + + this[IN_MAIN_PROCESS] = false; + + this[OPTION_UPDATED] = false; + + flushPendingActions.call(this, silent); + + triggerUpdatedEvent.call(this, silent); + } + // Avoid do both lazy update and progress in one frame. + else if (scheduler.unfinished) { + // Stream progress. + var remainTime = TEST_FRAME_REMAIN_TIME; + var ecModel = this._model; + var api = this._api; + scheduler.unfinished = false; + do { + var startTime = +new Date(); + + scheduler.performSeriesTasks(ecModel); + + // Currently dataProcessorFuncs do not check threshold. + scheduler.performDataProcessorTasks(ecModel); + + updateStreamModes(this, ecModel); + + // Do not update coordinate system here. Because that coord system update in + // each frame is not a good user experience. So we follow the rule that + // the extent of the coordinate system is determin in the first frame (the + // frame is executed immedietely after task reset. + // this._coordSysMgr.update(ecModel, api); + + // console.log('--- ec frame visual ---', remainTime); + scheduler.performVisualTasks(ecModel); + + renderSeries(this, this._model, api, 'remain'); + + remainTime -= (+new Date() - startTime); + } + while (remainTime > 0 && scheduler.unfinished); + + // Call flush explicitly for trigger finished event. + if (!scheduler.unfinished) { + this._zr.flush(); + } + // Else, zr flushing be ensue within the same frame, + // because zr flushing is after onframe event. + } +}; + +/** + * @return {HTMLElement} + */ +echartsProto.getDom = function () { + return this._dom; +}; + +/** + * @return {module:zrender~ZRender} + */ +echartsProto.getZr = function () { + return this._zr; +}; + +/** + * Usage: + * chart.setOption(option, notMerge, lazyUpdate); + * chart.setOption(option, { + * notMerge: ..., + * lazyUpdate: ..., + * silent: ... + * }); + * + * @param {Object} option + * @param {Object|boolean} [opts] opts or notMerge. + * @param {boolean} [opts.notMerge=false] + * @param {boolean} [opts.lazyUpdate=false] Useful when setOption frequently. + */ +echartsProto.setOption = function (option, notMerge, lazyUpdate) { + if (__DEV__) { + assert(!this[IN_MAIN_PROCESS], '`setOption` should not be called during main process.'); + } + + var silent; + if (isObject(notMerge)) { + lazyUpdate = notMerge.lazyUpdate; + silent = notMerge.silent; + notMerge = notMerge.notMerge; + } + + this[IN_MAIN_PROCESS] = true; + + if (!this._model || notMerge) { + var optionManager = new OptionManager(this._api); + var theme$$1 = this._theme; + var ecModel = this._model = new GlobalModel(null, null, theme$$1, optionManager); + ecModel.scheduler = this._scheduler; + ecModel.init(null, null, theme$$1, optionManager); + } + + this._model.setOption(option, optionPreprocessorFuncs); + + if (lazyUpdate) { + this[OPTION_UPDATED] = {silent: silent}; + this[IN_MAIN_PROCESS] = false; + } + else { + prepare(this); + + updateMethods.update.call(this); + + // Ensure zr refresh sychronously, and then pixel in canvas can be + // fetched after `setOption`. + this._zr.flush(); + + this[OPTION_UPDATED] = false; + this[IN_MAIN_PROCESS] = false; + + flushPendingActions.call(this, silent); + triggerUpdatedEvent.call(this, silent); + } +}; + +/** + * @DEPRECATED + */ +echartsProto.setTheme = function () { + console.error('ECharts#setTheme() is DEPRECATED in ECharts 3.0'); +}; + +/** + * @return {module:echarts/model/Global} + */ +echartsProto.getModel = function () { + return this._model; +}; + +/** + * @return {Object} + */ +echartsProto.getOption = function () { + return this._model && this._model.getOption(); +}; + +/** + * @return {number} + */ +echartsProto.getWidth = function () { + return this._zr.getWidth(); +}; + +/** + * @return {number} + */ +echartsProto.getHeight = function () { + return this._zr.getHeight(); +}; + +/** + * @return {number} + */ +echartsProto.getDevicePixelRatio = function () { + return this._zr.painter.dpr || window.devicePixelRatio || 1; +}; + +/** + * Get canvas which has all thing rendered + * @param {Object} opts + * @param {string} [opts.backgroundColor] + * @return {string} + */ +echartsProto.getRenderedCanvas = function (opts) { + if (!env$1.canvasSupported) { + return; + } + opts = opts || {}; + opts.pixelRatio = opts.pixelRatio || 1; + opts.backgroundColor = opts.backgroundColor + || this._model.get('backgroundColor'); + var zr = this._zr; + // var list = zr.storage.getDisplayList(); + // Stop animations + // Never works before in init animation, so remove it. + // zrUtil.each(list, function (el) { + // el.stopAnimation(true); + // }); + return zr.painter.getRenderedCanvas(opts); +}; + +/** + * Get svg data url + * @return {string} + */ +echartsProto.getSvgDataUrl = function () { + if (!env$1.svgSupported) { + return; + } + + var zr = this._zr; + var list = zr.storage.getDisplayList(); + // Stop animations + each$1(list, function (el) { + el.stopAnimation(true); + }); + + return zr.painter.pathToDataUrl(); +}; + +/** + * @return {string} + * @param {Object} opts + * @param {string} [opts.type='png'] + * @param {string} [opts.pixelRatio=1] + * @param {string} [opts.backgroundColor] + * @param {string} [opts.excludeComponents] + */ +echartsProto.getDataURL = function (opts) { + opts = opts || {}; + var excludeComponents = opts.excludeComponents; + var ecModel = this._model; + var excludesComponentViews = []; + var self = this; + + each(excludeComponents, function (componentType) { + ecModel.eachComponent({ + mainType: componentType + }, function (component) { + var view = self._componentsMap[component.__viewId]; + if (!view.group.ignore) { + excludesComponentViews.push(view); + view.group.ignore = true; + } + }); + }); + + var url = this._zr.painter.getType() === 'svg' + ? this.getSvgDataUrl() + : this.getRenderedCanvas(opts).toDataURL( + 'image/' + (opts && opts.type || 'png') + ); + + each(excludesComponentViews, function (view) { + view.group.ignore = false; + }); + + return url; +}; + + +/** + * @return {string} + * @param {Object} opts + * @param {string} [opts.type='png'] + * @param {string} [opts.pixelRatio=1] + * @param {string} [opts.backgroundColor] + */ +echartsProto.getConnectedDataURL = function (opts) { + if (!env$1.canvasSupported) { + return; + } + var groupId = this.group; + var mathMin = Math.min; + var mathMax = Math.max; + var MAX_NUMBER = Infinity; + if (connectedGroups[groupId]) { + var left = MAX_NUMBER; + var top = MAX_NUMBER; + var right = -MAX_NUMBER; + var bottom = -MAX_NUMBER; + var canvasList = []; + var dpr = (opts && opts.pixelRatio) || 1; + + each$1(instances, function (chart, id) { + if (chart.group === groupId) { + var canvas = chart.getRenderedCanvas( + clone(opts) + ); + var boundingRect = chart.getDom().getBoundingClientRect(); + left = mathMin(boundingRect.left, left); + top = mathMin(boundingRect.top, top); + right = mathMax(boundingRect.right, right); + bottom = mathMax(boundingRect.bottom, bottom); + canvasList.push({ + dom: canvas, + left: boundingRect.left, + top: boundingRect.top + }); + } + }); + + left *= dpr; + top *= dpr; + right *= dpr; + bottom *= dpr; + var width = right - left; + var height = bottom - top; + var targetCanvas = createCanvas(); + targetCanvas.width = width; + targetCanvas.height = height; + var zr = init$1(targetCanvas); + + each(canvasList, function (item) { + var img = new ZImage({ + style: { + x: item.left * dpr - left, + y: item.top * dpr - top, + image: item.dom + } + }); + zr.add(img); + }); + zr.refreshImmediately(); + + return targetCanvas.toDataURL('image/' + (opts && opts.type || 'png')); + } + else { + return this.getDataURL(opts); + } +}; + +/** + * Convert from logical coordinate system to pixel coordinate system. + * See CoordinateSystem#convertToPixel. + * @param {string|Object} finder + * If string, e.g., 'geo', means {geoIndex: 0}. + * If Object, could contain some of these properties below: + * { + * seriesIndex / seriesId / seriesName, + * geoIndex / geoId, geoName, + * bmapIndex / bmapId / bmapName, + * xAxisIndex / xAxisId / xAxisName, + * yAxisIndex / yAxisId / yAxisName, + * gridIndex / gridId / gridName, + * ... (can be extended) + * } + * @param {Array|number} value + * @return {Array|number} result + */ +echartsProto.convertToPixel = curry(doConvertPixel, 'convertToPixel'); + +/** + * Convert from pixel coordinate system to logical coordinate system. + * See CoordinateSystem#convertFromPixel. + * @param {string|Object} finder + * If string, e.g., 'geo', means {geoIndex: 0}. + * If Object, could contain some of these properties below: + * { + * seriesIndex / seriesId / seriesName, + * geoIndex / geoId / geoName, + * bmapIndex / bmapId / bmapName, + * xAxisIndex / xAxisId / xAxisName, + * yAxisIndex / yAxisId / yAxisName + * gridIndex / gridId / gridName, + * ... (can be extended) + * } + * @param {Array|number} value + * @return {Array|number} result + */ +echartsProto.convertFromPixel = curry(doConvertPixel, 'convertFromPixel'); + +function doConvertPixel(methodName, finder, value) { + var ecModel = this._model; + var coordSysList = this._coordSysMgr.getCoordinateSystems(); + var result; + + finder = parseFinder(ecModel, finder); + + for (var i = 0; i < coordSysList.length; i++) { + var coordSys = coordSysList[i]; + if (coordSys[methodName] + && (result = coordSys[methodName](ecModel, finder, value)) != null + ) { + return result; + } + } + + if (__DEV__) { + console.warn( + 'No coordinate system that supports ' + methodName + ' found by the given finder.' + ); + } +} + +/** + * Is the specified coordinate systems or components contain the given pixel point. + * @param {string|Object} finder + * If string, e.g., 'geo', means {geoIndex: 0}. + * If Object, could contain some of these properties below: + * { + * seriesIndex / seriesId / seriesName, + * geoIndex / geoId / geoName, + * bmapIndex / bmapId / bmapName, + * xAxisIndex / xAxisId / xAxisName, + * yAxisIndex / yAxisId / yAxisName, + * gridIndex / gridId / gridName, + * ... (can be extended) + * } + * @param {Array|number} value + * @return {boolean} result + */ +echartsProto.containPixel = function (finder, value) { + var ecModel = this._model; + var result; + + finder = parseFinder(ecModel, finder); + + each$1(finder, function (models, key) { + key.indexOf('Models') >= 0 && each$1(models, function (model) { + var coordSys = model.coordinateSystem; + if (coordSys && coordSys.containPoint) { + result |= !!coordSys.containPoint(value); + } + else if (key === 'seriesModels') { + var view = this._chartsMap[model.__viewId]; + if (view && view.containPoint) { + result |= view.containPoint(value, model); + } + else { + if (__DEV__) { + console.warn(key + ': ' + (view + ? 'The found component do not support containPoint.' + : 'No view mapping to the found component.' + )); + } + } + } + else { + if (__DEV__) { + console.warn(key + ': containPoint is not supported'); + } + } + }, this); + }, this); + + return !!result; +}; + +/** + * Get visual from series or data. + * @param {string|Object} finder + * If string, e.g., 'series', means {seriesIndex: 0}. + * If Object, could contain some of these properties below: + * { + * seriesIndex / seriesId / seriesName, + * dataIndex / dataIndexInside + * } + * If dataIndex is not specified, series visual will be fetched, + * but not data item visual. + * If all of seriesIndex, seriesId, seriesName are not specified, + * visual will be fetched from first series. + * @param {string} visualType 'color', 'symbol', 'symbolSize' + */ +echartsProto.getVisual = function (finder, visualType) { + var ecModel = this._model; + + finder = parseFinder(ecModel, finder, {defaultMainType: 'series'}); + + var seriesModel = finder.seriesModel; + + if (__DEV__) { + if (!seriesModel) { + console.warn('There is no specified seires model'); + } + } + + var data = seriesModel.getData(); + + var dataIndexInside = finder.hasOwnProperty('dataIndexInside') + ? finder.dataIndexInside + : finder.hasOwnProperty('dataIndex') + ? data.indexOfRawIndex(finder.dataIndex) + : null; + + return dataIndexInside != null + ? data.getItemVisual(dataIndexInside, visualType) + : data.getVisual(visualType); +}; + +/** + * Get view of corresponding component model + * @param {module:echarts/model/Component} componentModel + * @return {module:echarts/view/Component} + */ +echartsProto.getViewOfComponentModel = function (componentModel) { + return this._componentsMap[componentModel.__viewId]; +}; + +/** + * Get view of corresponding series model + * @param {module:echarts/model/Series} seriesModel + * @return {module:echarts/view/Chart} + */ +echartsProto.getViewOfSeriesModel = function (seriesModel) { + return this._chartsMap[seriesModel.__viewId]; +}; + +var updateMethods = { + + prepareAndUpdate: function (payload) { + prepare(this); + updateMethods.update.call(this, payload); + }, + + /** + * @param {Object} payload + * @private + */ + update: function (payload) { + // console.profile && console.profile('update'); + + var ecModel = this._model; + var api = this._api; + var zr = this._zr; + var coordSysMgr = this._coordSysMgr; + var scheduler = this._scheduler; + + // update before setOption + if (!ecModel) { + return; + } + + scheduler.restoreData(ecModel, payload); + + scheduler.performSeriesTasks(ecModel); + + // TODO + // Save total ecModel here for undo/redo (after restoring data and before processing data). + // Undo (restoration of total ecModel) can be carried out in 'action' or outside API call. + + // Create new coordinate system each update + // In LineView may save the old coordinate system and use it to get the orignal point + coordSysMgr.create(ecModel, api); + + scheduler.performDataProcessorTasks(ecModel, payload); + + // Current stream render is not supported in data process. So we can update + // stream modes after data processing, where the filtered data is used to + // deteming whether use progressive rendering. + updateStreamModes(this, ecModel); + + // We update stream modes before coordinate system updated, then the modes info + // can be fetched when coord sys updating (consider the barGrid extent fix). But + // the drawback is the full coord info can not be fetched. Fortunately this full + // coord is not requied in stream mode updater currently. + coordSysMgr.update(ecModel, api); + + clearColorPalette(ecModel); + scheduler.performVisualTasks(ecModel, payload); + + render(this, ecModel, api, payload); + + // Set background + var backgroundColor = ecModel.get('backgroundColor') || 'transparent'; + + // In IE8 + if (!env$1.canvasSupported) { + var colorArr = parse(backgroundColor); + backgroundColor = stringify(colorArr, 'rgb'); + if (colorArr[3] === 0) { + backgroundColor = 'transparent'; + } + } + else { + zr.setBackgroundColor(backgroundColor); + } + + performPostUpdateFuncs(ecModel, api); + + // console.profile && console.profileEnd('update'); + }, + + /** + * @param {Object} payload + * @private + */ + updateTransform: function (payload) { + var ecModel = this._model; + var ecIns = this; + var api = this._api; + + // update before setOption + if (!ecModel) { + return; + } + + // ChartView.markUpdateMethod(payload, 'updateTransform'); + + var componentDirtyList = []; + ecModel.eachComponent(function (componentType, componentModel) { + var componentView = ecIns.getViewOfComponentModel(componentModel); + if (componentView && componentView.__alive) { + if (componentView.updateTransform) { + var result = componentView.updateTransform(componentModel, ecModel, api, payload); + result && result.update && componentDirtyList.push(componentView); + } + else { + componentDirtyList.push(componentView); + } + } + }); + + var seriesDirtyMap = createHashMap(); + ecModel.eachSeries(function (seriesModel) { + var chartView = ecIns._chartsMap[seriesModel.__viewId]; + if (chartView.updateTransform) { + var result = chartView.updateTransform(seriesModel, ecModel, api, payload); + result && result.update && seriesDirtyMap.set(seriesModel.uid, 1); + } + else { + seriesDirtyMap.set(seriesModel.uid, 1); + } + }); + + clearColorPalette(ecModel); + // Keep pipe to the exist pipeline because it depends on the render task of the full pipeline. + // this._scheduler.performVisualTasks(ecModel, payload, 'layout', true); + this._scheduler.performVisualTasks( + ecModel, payload, {setDirty: true, dirtyMap: seriesDirtyMap} + ); + + // Currently, not call render of components. Geo render cost a lot. + // renderComponents(ecIns, ecModel, api, payload, componentDirtyList); + renderSeries(ecIns, ecModel, api, payload, seriesDirtyMap); + + performPostUpdateFuncs(ecModel, this._api); + }, + + /** + * @param {Object} payload + * @private + */ + updateView: function (payload) { + var ecModel = this._model; + + // update before setOption + if (!ecModel) { + return; + } + + Chart.markUpdateMethod(payload, 'updateView'); + + clearColorPalette(ecModel); + + // Keep pipe to the exist pipeline because it depends on the render task of the full pipeline. + this._scheduler.performVisualTasks(ecModel, payload, {setDirty: true}); + + render(this, this._model, this._api, payload); + + performPostUpdateFuncs(ecModel, this._api); + }, + + /** + * @param {Object} payload + * @private + */ + updateVisual: function (payload) { + updateMethods.update.call(this, payload); + + // var ecModel = this._model; + + // // update before setOption + // if (!ecModel) { + // return; + // } + + // ChartView.markUpdateMethod(payload, 'updateVisual'); + + // clearColorPalette(ecModel); + + // // Keep pipe to the exist pipeline because it depends on the render task of the full pipeline. + // this._scheduler.performVisualTasks(ecModel, payload, {visualType: 'visual', setDirty: true}); + + // render(this, this._model, this._api, payload); + + // performPostUpdateFuncs(ecModel, this._api); + }, + + /** + * @param {Object} payload + * @private + */ + updateLayout: function (payload) { + updateMethods.update.call(this, payload); + + // var ecModel = this._model; + + // // update before setOption + // if (!ecModel) { + // return; + // } + + // ChartView.markUpdateMethod(payload, 'updateLayout'); + + // // Keep pipe to the exist pipeline because it depends on the render task of the full pipeline. + // // this._scheduler.performVisualTasks(ecModel, payload, 'layout', true); + // this._scheduler.performVisualTasks(ecModel, payload, {setDirty: true}); + + // render(this, this._model, this._api, payload); + + // performPostUpdateFuncs(ecModel, this._api); + } +}; + +function prepare(ecIns) { + var ecModel = ecIns._model; + var scheduler = ecIns._scheduler; + + scheduler.restorePipelines(ecModel); + + scheduler.prepareStageTasks(); + + prepareView(ecIns, 'component', ecModel, scheduler); + + prepareView(ecIns, 'chart', ecModel, scheduler); + + scheduler.plan(); +} + +/** + * @private + */ +function updateDirectly(ecIns, method, payload, mainType, subType) { + var ecModel = ecIns._model; + + // broadcast + if (!mainType) { + // FIXME + // Chart will not be update directly here, except set dirty. + // But there is no such scenario now. + each(ecIns._componentsViews.concat(ecIns._chartsViews), callView); + return; + } + + var query = {}; + query[mainType + 'Id'] = payload[mainType + 'Id']; + query[mainType + 'Index'] = payload[mainType + 'Index']; + query[mainType + 'Name'] = payload[mainType + 'Name']; + + var condition = {mainType: mainType, query: query}; + subType && (condition.subType = subType); // subType may be '' by parseClassType; + + var excludeSeriesId = payload.excludeSeriesId; + if (excludeSeriesId != null) { + excludeSeriesId = createHashMap(normalizeToArray(excludeSeriesId)); + } + + // If dispatchAction before setOption, do nothing. + ecModel && ecModel.eachComponent(condition, function (model) { + if (!excludeSeriesId || excludeSeriesId.get(model.id) == null) { + callView(ecIns[ + mainType === 'series' ? '_chartsMap' : '_componentsMap' + ][model.__viewId]); + } + }, ecIns); + + function callView(view) { + view && view.__alive && view[method] && view[method]( + view.__model, ecModel, ecIns._api, payload + ); + } +} + +/** + * Resize the chart + * @param {Object} opts + * @param {number} [opts.width] Can be 'auto' (the same as null/undefined) + * @param {number} [opts.height] Can be 'auto' (the same as null/undefined) + * @param {boolean} [opts.silent=false] + */ +echartsProto.resize = function (opts) { + if (__DEV__) { + assert(!this[IN_MAIN_PROCESS], '`resize` should not be called during main process.'); + } + + this._zr.resize(opts); + + var ecModel = this._model; + + // Resize loading effect + this._loadingFX && this._loadingFX.resize(); + + if (!ecModel) { + return; + } + + var optionChanged = ecModel.resetOption('media'); + + var silent = opts && opts.silent; + + this[IN_MAIN_PROCESS] = true; + + optionChanged && prepare(this); + updateMethods.update.call(this); + + this[IN_MAIN_PROCESS] = false; + + flushPendingActions.call(this, silent); + + triggerUpdatedEvent.call(this, silent); +}; + +function updateStreamModes(ecIns, ecModel) { + var chartsMap = ecIns._chartsMap; + var scheduler = ecIns._scheduler; + ecModel.eachSeries(function (seriesModel) { + scheduler.updateStreamModes(seriesModel, chartsMap[seriesModel.__viewId]); + }); +} + +/** + * Show loading effect + * @param {string} [name='default'] + * @param {Object} [cfg] + */ +echartsProto.showLoading = function (name, cfg) { + if (isObject(name)) { + cfg = name; + name = ''; + } + name = name || 'default'; + + this.hideLoading(); + if (!loadingEffects[name]) { + if (__DEV__) { + console.warn('Loading effects ' + name + ' not exists.'); + } + return; + } + var el = loadingEffects[name](this._api, cfg); + var zr = this._zr; + this._loadingFX = el; + + zr.add(el); +}; + +/** + * Hide loading effect + */ +echartsProto.hideLoading = function () { + this._loadingFX && this._zr.remove(this._loadingFX); + this._loadingFX = null; +}; + +/** + * @param {Object} eventObj + * @return {Object} + */ +echartsProto.makeActionFromEvent = function (eventObj) { + var payload = extend({}, eventObj); + payload.type = eventActionMap[eventObj.type]; + return payload; +}; + +/** + * @pubilc + * @param {Object} payload + * @param {string} [payload.type] Action type + * @param {Object|boolean} [opt] If pass boolean, means opt.silent + * @param {boolean} [opt.silent=false] Whether trigger events. + * @param {boolean} [opt.flush=undefined] + * true: Flush immediately, and then pixel in canvas can be fetched + * immediately. Caution: it might affect performance. + * false: Not not flush. + * undefined: Auto decide whether perform flush. + */ +echartsProto.dispatchAction = function (payload, opt) { + if (!isObject(opt)) { + opt = {silent: !!opt}; + } + + if (!actions[payload.type]) { + return; + } + + // Avoid dispatch action before setOption. Especially in `connect`. + if (!this._model) { + return; + } + + // May dispatchAction in rendering procedure + if (this[IN_MAIN_PROCESS]) { + this._pendingActions.push(payload); + return; + } + + doDispatchAction.call(this, payload, opt.silent); + + if (opt.flush) { + this._zr.flush(true); + } + else if (opt.flush !== false && env$1.browser.weChat) { + // In WeChat embeded browser, `requestAnimationFrame` and `setInterval` + // hang when sliding page (on touch event), which cause that zr does not + // refresh util user interaction finished, which is not expected. + // But `dispatchAction` may be called too frequently when pan on touch + // screen, which impacts performance if do not throttle them. + this._throttledZrFlush(); + } + + flushPendingActions.call(this, opt.silent); + + triggerUpdatedEvent.call(this, opt.silent); +}; + +function doDispatchAction(payload, silent) { + var payloadType = payload.type; + var escapeConnect = payload.escapeConnect; + var actionWrap = actions[payloadType]; + var actionInfo = actionWrap.actionInfo; + + var cptType = (actionInfo.update || 'update').split(':'); + var updateMethod = cptType.pop(); + cptType = cptType[0] != null && parseClassType(cptType[0]); + + this[IN_MAIN_PROCESS] = true; + + var payloads = [payload]; + var batched = false; + // Batch action + if (payload.batch) { + batched = true; + payloads = map(payload.batch, function (item) { + item = defaults(extend({}, item), payload); + item.batch = null; + return item; + }); + } + + var eventObjBatch = []; + var eventObj; + var isHighDown = payloadType === 'highlight' || payloadType === 'downplay'; + + each(payloads, function (batchItem) { + // Action can specify the event by return it. + eventObj = actionWrap.action(batchItem, this._model, this._api); + // Emit event outside + eventObj = eventObj || extend({}, batchItem); + // Convert type to eventType + eventObj.type = actionInfo.event || eventObj.type; + eventObjBatch.push(eventObj); + + // light update does not perform data process, layout and visual. + if (isHighDown) { + // method, payload, mainType, subType + updateDirectly(this, updateMethod, batchItem, 'series'); + } + else if (cptType) { + updateDirectly(this, updateMethod, batchItem, cptType.main, cptType.sub); + } + }, this); + + if (updateMethod !== 'none' && !isHighDown && !cptType) { + // Still dirty + if (this[OPTION_UPDATED]) { + // FIXME Pass payload ? + prepare(this); + updateMethods.update.call(this, payload); + this[OPTION_UPDATED] = false; + } + else { + updateMethods[updateMethod].call(this, payload); + } + } + + // Follow the rule of action batch + if (batched) { + eventObj = { + type: actionInfo.event || payloadType, + escapeConnect: escapeConnect, + batch: eventObjBatch + }; + } + else { + eventObj = eventObjBatch[0]; + } + + this[IN_MAIN_PROCESS] = false; + + !silent && this._messageCenter.trigger(eventObj.type, eventObj); +} + +function flushPendingActions(silent) { + var pendingActions = this._pendingActions; + while (pendingActions.length) { + var payload = pendingActions.shift(); + doDispatchAction.call(this, payload, silent); + } +} + +function triggerUpdatedEvent(silent) { + !silent && this.trigger('updated'); +} + +/** + * Event `rendered` is triggered when zr + * rendered. It is useful for realtime + * snapshot (reflect animation). + * + * Event `finished` is triggered when: + * (1) zrender rendering finished. + * (2) initial animation finished. + * (3) progressive rendering finished. + * (4) no pending action. + * (5) no delayed setOption needs to be processed. + */ +function bindRenderedEvent(zr, ecIns) { + zr.on('rendered', function () { + + ecIns.trigger('rendered'); + + // The `finished` event should not be triggered repeatly, + // so it should only be triggered when rendering indeed happend + // in zrender. (Consider the case that dipatchAction is keep + // triggering when mouse move). + if ( + // Although zr is dirty if initial animation is not finished + // and this checking is called on frame, we also check + // animation finished for robustness. + zr.animation.isFinished() + && !ecIns[OPTION_UPDATED] + && !ecIns._scheduler.unfinished + && !ecIns._pendingActions.length + ) { + ecIns.trigger('finished'); + } + }); +} + +/** + * @param {Object} params + * @param {number} params.seriesIndex + * @param {Array|TypedArray} params.data + */ +echartsProto.appendData = function (params) { + var seriesIndex = params.seriesIndex; + var ecModel = this.getModel(); + var seriesModel = ecModel.getSeriesByIndex(seriesIndex); + + if (__DEV__) { + assert(params.data && seriesModel); + } + + seriesModel.appendData(params); + + // Note: `appendData` does not support that update extent of coordinate + // system, util some scenario require that. In the expected usage of + // `appendData`, the initial extent of coordinate system should better + // be fixed by axis `min`/`max` setting or initial data, otherwise if + // the extent changed while `appendData`, the location of the painted + // graphic elements have to be changed, which make the usage of + // `appendData` meaningless. + + this._scheduler.unfinished = true; +}; + +/** + * Register event + * @method + */ +echartsProto.on = createRegisterEventWithLowercaseName('on'); +echartsProto.off = createRegisterEventWithLowercaseName('off'); +echartsProto.one = createRegisterEventWithLowercaseName('one'); + +/** + * Prepare view instances of charts and components + * @param {module:echarts/model/Global} ecModel + * @private + */ +function prepareView(ecIns, type, ecModel, scheduler) { + var isComponent = type === 'component'; + var viewList = isComponent ? ecIns._componentsViews : ecIns._chartsViews; + var viewMap = isComponent ? ecIns._componentsMap : ecIns._chartsMap; + var zr = ecIns._zr; + var api = ecIns._api; + + for (var i = 0; i < viewList.length; i++) { + viewList[i].__alive = false; + } + + isComponent + ? ecModel.eachComponent(function (componentType, model) { + componentType !== 'series' && doPrepare(model); + }) + : ecModel.eachSeries(doPrepare); + + function doPrepare(model) { + // Consider: id same and type changed. + var viewId = '_ec_' + model.id + '_' + model.type; + var view = viewMap[viewId]; + if (!view) { + var classType = parseClassType(model.type); + var Clazz = isComponent + ? Component.getClass(classType.main, classType.sub) + : Chart.getClass(classType.sub); + + if (__DEV__) { + assert(Clazz, classType.sub + ' does not exist.'); + } + + view = new Clazz(); + view.init(ecModel, api); + viewMap[viewId] = view; + viewList.push(view); + zr.add(view.group); + } + + model.__viewId = view.__id = viewId; + view.__alive = true; + view.__model = model; + view.group.__ecComponentInfo = { + mainType: model.mainType, + index: model.componentIndex + }; + !isComponent && scheduler.prepareView(view, model, ecModel, api); + } + + for (var i = 0; i < viewList.length;) { + var view = viewList[i]; + if (!view.__alive) { + !isComponent && view.renderTask.dispose(); + zr.remove(view.group); + view.dispose(ecModel, api); + viewList.splice(i, 1); + delete viewMap[view.__id]; + view.__id = view.group.__ecComponentInfo = null; + } + else { + i++; + } + } +} + +// /** +// * Encode visual infomation from data after data processing +// * +// * @param {module:echarts/model/Global} ecModel +// * @param {object} layout +// * @param {boolean} [layoutFilter] `true`: only layout, +// * `false`: only not layout, +// * `null`/`undefined`: all. +// * @param {string} taskBaseTag +// * @private +// */ +// function startVisualEncoding(ecIns, ecModel, api, payload, layoutFilter) { +// each(visualFuncs, function (visual, index) { +// var isLayout = visual.isLayout; +// if (layoutFilter == null +// || (layoutFilter === false && !isLayout) +// || (layoutFilter === true && isLayout) +// ) { +// visual.func(ecModel, api, payload); +// } +// }); +// } + +function clearColorPalette(ecModel) { + ecModel.clearColorPalette(); + ecModel.eachSeries(function (seriesModel) { + seriesModel.clearColorPalette(); + }); +} + +function render(ecIns, ecModel, api, payload) { + + renderComponents(ecIns, ecModel, api, payload); + + each(ecIns._chartsViews, function (chart) { + chart.__alive = false; + }); + + renderSeries(ecIns, ecModel, api, payload); + + // Remove groups of unrendered charts + each(ecIns._chartsViews, function (chart) { + if (!chart.__alive) { + chart.remove(ecModel, api); + } + }); +} + +function renderComponents(ecIns, ecModel, api, payload, dirtyList) { + each(dirtyList || ecIns._componentsViews, function (componentView) { + var componentModel = componentView.__model; + componentView.render(componentModel, ecModel, api, payload); + + updateZ(componentModel, componentView); + }); +} + +/** + * Render each chart and component + * @private + */ +function renderSeries(ecIns, ecModel, api, payload, dirtyMap) { + // Render all charts + var scheduler = ecIns._scheduler; + var unfinished; + ecModel.eachSeries(function (seriesModel) { + var chartView = ecIns._chartsMap[seriesModel.__viewId]; + chartView.__alive = true; + + var renderTask = chartView.renderTask; + scheduler.updatePayload(renderTask, payload); + + if (dirtyMap && dirtyMap.get(seriesModel.uid)) { + renderTask.dirty(); + } + + unfinished |= renderTask.perform(scheduler.getPerformArgs(renderTask)); + + chartView.group.silent = !!seriesModel.get('silent'); + + updateZ(seriesModel, chartView); + + updateBlend(seriesModel, chartView); + }); + scheduler.unfinished |= unfinished; + + // If use hover layer + updateHoverLayerStatus(ecIns._zr, ecModel); + + // Add aria + aria(ecIns._zr.dom, ecModel); +} + +function performPostUpdateFuncs(ecModel, api) { + each(postUpdateFuncs, function (func) { + func(ecModel, api); + }); +} + + +var MOUSE_EVENT_NAMES = [ + 'click', 'dblclick', 'mouseover', 'mouseout', 'mousemove', + 'mousedown', 'mouseup', 'globalout', 'contextmenu' +]; + +/** + * @private + */ +echartsProto._initEvents = function () { + each(MOUSE_EVENT_NAMES, function (eveName) { + var handler = function (e) { + var ecModel = this.getModel(); + var el = e.target; + var params; + var isGlobalOut = eveName === 'globalout'; + + // no e.target when 'globalout'. + if (isGlobalOut) { + params = {}; + } + else if (el && el.dataIndex != null) { + var dataModel = el.dataModel || ecModel.getSeriesByIndex(el.seriesIndex); + params = dataModel && dataModel.getDataParams(el.dataIndex, el.dataType, el) || {}; + } + // If element has custom eventData of components + else if (el && el.eventData) { + params = extend({}, el.eventData); + } + + // Contract: if params prepared in mouse event, + // these properties must be specified: + // { + // componentType: string (component main type) + // componentIndex: number + // } + // Otherwise event query can not work. + + if (params) { + var componentType = params.componentType; + var componentIndex = params.componentIndex; + // Special handling for historic reason: when trigger by + // markLine/markPoint/markArea, the componentType is + // 'markLine'/'markPoint'/'markArea', but we should better + // enable them to be queried by seriesIndex, since their + // option is set in each series. + if (componentType === 'markLine' + || componentType === 'markPoint' + || componentType === 'markArea' + ) { + componentType = 'series'; + componentIndex = params.seriesIndex; + } + var model = componentType && componentIndex != null + && ecModel.getComponent(componentType, componentIndex); + var view = model && this[ + model.mainType === 'series' ? '_chartsMap' : '_componentsMap' + ][model.__viewId]; + + if (__DEV__) { + // `event.componentType` and `event[componentTpype + 'Index']` must not + // be missed, otherwise there is no way to distinguish source component. + // See `dataFormat.getDataParams`. + if (!isGlobalOut && !(model && view)) { + console.warn('model or view can not be found by params'); + } + } + + params.event = e; + params.type = eveName; + + this._ecEventProcessor.eventInfo = { + targetEl: el, + packedEvent: params, + model: model, + view: view + }; + + this.trigger(eveName, params); + } + }; + // Consider that some component (like tooltip, brush, ...) + // register zr event handler, but user event handler might + // do anything, such as call `setOption` or `dispatchAction`, + // which probably update any of the content and probably + // cause problem if it is called previous other inner handlers. + handler.zrEventfulCallAtLast = true; + this._zr.on(eveName, handler, this); + }, this); + + each(eventActionMap, function (actionType, eventType) { + this._messageCenter.on(eventType, function (event) { + this.trigger(eventType, event); + }, this); + }, this); +}; + +/** + * @return {boolean} + */ +echartsProto.isDisposed = function () { + return this._disposed; +}; + +/** + * Clear + */ +echartsProto.clear = function () { + this.setOption({ series: [] }, true); +}; + +/** + * Dispose instance + */ +echartsProto.dispose = function () { + if (this._disposed) { + if (__DEV__) { + console.warn('Instance ' + this.id + ' has been disposed'); + } + return; + } + this._disposed = true; + + setAttribute(this.getDom(), DOM_ATTRIBUTE_KEY, ''); + + var api = this._api; + var ecModel = this._model; + + each(this._componentsViews, function (component) { + component.dispose(ecModel, api); + }); + each(this._chartsViews, function (chart) { + chart.dispose(ecModel, api); + }); + + // Dispose after all views disposed + this._zr.dispose(); + + delete instances[this.id]; +}; + +mixin(ECharts, Eventful); + +function updateHoverLayerStatus(zr, ecModel) { + var storage = zr.storage; + var elCount = 0; + storage.traverse(function (el) { + if (!el.isGroup) { + elCount++; + } + }); + if (elCount > ecModel.get('hoverLayerThreshold') && !env$1.node) { + storage.traverse(function (el) { + if (!el.isGroup) { + // Don't switch back. + el.useHoverLayer = true; + } + }); + } +} + +/** + * Update chart progressive and blend. + * @param {module:echarts/model/Series|module:echarts/model/Component} model + * @param {module:echarts/view/Component|module:echarts/view/Chart} view + */ +function updateBlend(seriesModel, chartView) { + var blendMode = seriesModel.get('blendMode') || null; + if (__DEV__) { + if (!env$1.canvasSupported && blendMode && blendMode !== 'source-over') { + console.warn('Only canvas support blendMode'); + } + } + chartView.group.traverse(function (el) { + // FIXME marker and other components + if (!el.isGroup) { + // Only set if blendMode is changed. In case element is incremental and don't wan't to rerender. + if (el.style.blend !== blendMode) { + el.setStyle('blend', blendMode); + } + } + if (el.eachPendingDisplayable) { + el.eachPendingDisplayable(function (displayable) { + displayable.setStyle('blend', blendMode); + }); + } + }); +} + +/** + * @param {module:echarts/model/Series|module:echarts/model/Component} model + * @param {module:echarts/view/Component|module:echarts/view/Chart} view + */ +function updateZ(model, view) { + var z = model.get('z'); + var zlevel = model.get('zlevel'); + // Set z and zlevel + view.group.traverse(function (el) { + if (el.type !== 'group') { + z != null && (el.z = z); + zlevel != null && (el.zlevel = zlevel); + } + }); +} + +function createExtensionAPI(ecInstance) { + var coordSysMgr = ecInstance._coordSysMgr; + return extend(new ExtensionAPI(ecInstance), { + // Inject methods + getCoordinateSystems: bind( + coordSysMgr.getCoordinateSystems, coordSysMgr + ), + getComponentByElement: function (el) { + while (el) { + var modelInfo = el.__ecComponentInfo; + if (modelInfo != null) { + return ecInstance._model.getComponent(modelInfo.mainType, modelInfo.index); + } + el = el.parent; + } + } + }); +} + + +/** + * @class + * Usage of query: + * `chart.on('click', query, handler);` + * The `query` can be: + * + The component type query string, only `mainType` or `mainType.subType`, + * like: 'xAxis', 'series', 'xAxis.category' or 'series.line'. + * + The component query object, like: + * `{seriesIndex: 2}`, `{seriesName: 'xx'}`, `{seriesId: 'some'}`, + * `{xAxisIndex: 2}`, `{xAxisName: 'xx'}`, `{xAxisId: 'some'}`. + * + The data query object, like: + * `{dataIndex: 123}`, `{dataType: 'link'}`, `{name: 'some'}`. + * + The other query object (cmponent customized query), like: + * `{element: 'some'}` (only available in custom series). + * + * Caveat: If a prop in the `query` object is `null/undefined`, it is the + * same as there is no such prop in the `query` object. + */ +function EventProcessor() { + // These info required: targetEl, packedEvent, model, view + this.eventInfo; +} +EventProcessor.prototype = { + constructor: EventProcessor, + + normalizeQuery: function (query) { + var cptQuery = {}; + var dataQuery = {}; + var otherQuery = {}; + + // `query` is `mainType` or `mainType.subType` of component. + if (isString(query)) { + var condCptType = parseClassType(query); + // `.main` and `.sub` may be ''. + cptQuery.mainType = condCptType.main || null; + cptQuery.subType = condCptType.sub || null; + } + // `query` is an object, convert to {mainType, index, name, id}. + else { + // `xxxIndex`, `xxxName`, `xxxId`, `name`, `dataIndex`, `dataType` is reserved, + // can not be used in `compomentModel.filterForExposedEvent`. + var suffixes = ['Index', 'Name', 'Id']; + var dataKeys = {name: 1, dataIndex: 1, dataType: 1}; + each$1(query, function (val, key) { + var reserved = false; + for (var i = 0; i < suffixes.length; i++) { + var propSuffix = suffixes[i]; + var suffixPos = key.lastIndexOf(propSuffix); + if (suffixPos > 0 && suffixPos === key.length - propSuffix.length) { + var mainType = key.slice(0, suffixPos); + // Consider `dataIndex`. + if (mainType !== 'data') { + cptQuery.mainType = mainType; + cptQuery[propSuffix.toLowerCase()] = val; + reserved = true; + } + } + } + if (dataKeys.hasOwnProperty(key)) { + dataQuery[key] = val; + reserved = true; + } + if (!reserved) { + otherQuery[key] = val; + } + }); + } + + return { + cptQuery: cptQuery, + dataQuery: dataQuery, + otherQuery: otherQuery + }; + }, + + filter: function (eventType, query, args) { + // They should be assigned before each trigger call. + var eventInfo = this.eventInfo; + + if (!eventInfo) { + return true; + } + + var targetEl = eventInfo.targetEl; + var packedEvent = eventInfo.packedEvent; + var model = eventInfo.model; + var view = eventInfo.view; + + // For event like 'globalout'. + if (!model || !view) { + return true; + } + + var cptQuery = query.cptQuery; + var dataQuery = query.dataQuery; + + return check(cptQuery, model, 'mainType') + && check(cptQuery, model, 'subType') + && check(cptQuery, model, 'index', 'componentIndex') + && check(cptQuery, model, 'name') + && check(cptQuery, model, 'id') + && check(dataQuery, packedEvent, 'name') + && check(dataQuery, packedEvent, 'dataIndex') + && check(dataQuery, packedEvent, 'dataType') + && (!view.filterForExposedEvent || view.filterForExposedEvent( + eventType, query.otherQuery, targetEl, packedEvent + )); + + function check(query, host, prop, propOnHost) { + return query[prop] == null || host[propOnHost || prop] === query[prop]; + } + }, + + afterTrigger: function () { + // Make sure the eventInfo wont be used in next trigger. + this.eventInfo = null; + } +}; + + +/** + * @type {Object} key: actionType. + * @inner + */ +var actions = {}; + +/** + * Map eventType to actionType + * @type {Object} + */ +var eventActionMap = {}; + +/** + * Data processor functions of each stage + * @type {Array.>} + * @inner + */ +var dataProcessorFuncs = []; + +/** + * @type {Array.} + * @inner + */ +var optionPreprocessorFuncs = []; + +/** + * @type {Array.} + * @inner + */ +var postUpdateFuncs = []; + +/** + * Visual encoding functions of each stage + * @type {Array.>} + */ +var visualFuncs = []; + +/** + * Theme storage + * @type {Object.} + */ +var themeStorage = {}; +/** + * Loading effects + */ +var loadingEffects = {}; + +var instances = {}; +var connectedGroups = {}; + +var idBase = new Date() - 0; +var groupIdBase = new Date() - 0; +var DOM_ATTRIBUTE_KEY = '_echarts_instance_'; + +function enableConnect(chart) { + var STATUS_PENDING = 0; + var STATUS_UPDATING = 1; + var STATUS_UPDATED = 2; + var STATUS_KEY = '__connectUpdateStatus'; + + function updateConnectedChartsStatus(charts, status) { + for (var i = 0; i < charts.length; i++) { + var otherChart = charts[i]; + otherChart[STATUS_KEY] = status; + } + } + + each(eventActionMap, function (actionType, eventType) { + chart._messageCenter.on(eventType, function (event) { + if (connectedGroups[chart.group] && chart[STATUS_KEY] !== STATUS_PENDING) { + if (event && event.escapeConnect) { + return; + } + + var action = chart.makeActionFromEvent(event); + var otherCharts = []; + + each(instances, function (otherChart) { + if (otherChart !== chart && otherChart.group === chart.group) { + otherCharts.push(otherChart); + } + }); + + updateConnectedChartsStatus(otherCharts, STATUS_PENDING); + each(otherCharts, function (otherChart) { + if (otherChart[STATUS_KEY] !== STATUS_UPDATING) { + otherChart.dispatchAction(action); + } + }); + updateConnectedChartsStatus(otherCharts, STATUS_UPDATED); + } + }); + }); +} + +/** + * @param {HTMLElement} dom + * @param {Object} [theme] + * @param {Object} opts + * @param {number} [opts.devicePixelRatio] Use window.devicePixelRatio by default + * @param {string} [opts.renderer] Currently only 'canvas' is supported. + * @param {number} [opts.width] Use clientWidth of the input `dom` by default. + * Can be 'auto' (the same as null/undefined) + * @param {number} [opts.height] Use clientHeight of the input `dom` by default. + * Can be 'auto' (the same as null/undefined) + */ +function init(dom, theme$$1, opts) { + if (__DEV__) { + // Check version + if ((version$1.replace('.', '') - 0) < (dependencies.zrender.replace('.', '') - 0)) { + throw new Error( + 'zrender/src ' + version$1 + + ' is too old for ECharts ' + version + + '. Current version need ZRender ' + + dependencies.zrender + '+' + ); + } + + if (!dom) { + throw new Error('Initialize failed: invalid dom.'); + } + } + + var existInstance = getInstanceByDom(dom); + if (existInstance) { + if (__DEV__) { + console.warn('There is a chart instance already initialized on the dom.'); + } + return existInstance; + } + + if (__DEV__) { + if (isDom(dom) + && dom.nodeName.toUpperCase() !== 'CANVAS' + && ( + (!dom.clientWidth && (!opts || opts.width == null)) + || (!dom.clientHeight && (!opts || opts.height == null)) + ) + ) { + console.warn('Can\'t get dom width or height'); + } + } + + var chart = new ECharts(dom, theme$$1, opts); + chart.id = 'ec_' + idBase++; + instances[chart.id] = chart; + + setAttribute(dom, DOM_ATTRIBUTE_KEY, chart.id); + + enableConnect(chart); + + return chart; +} + +/** + * @return {string|Array.} groupId + */ +function connect(groupId) { + // Is array of charts + if (isArray(groupId)) { + var charts = groupId; + groupId = null; + // If any chart has group + each(charts, function (chart) { + if (chart.group != null) { + groupId = chart.group; + } + }); + groupId = groupId || ('g_' + groupIdBase++); + each(charts, function (chart) { + chart.group = groupId; + }); + } + connectedGroups[groupId] = true; + return groupId; +} + +/** + * @DEPRECATED + * @return {string} groupId + */ +function disConnect(groupId) { + connectedGroups[groupId] = false; +} + +/** + * @return {string} groupId + */ +var disconnect = disConnect; + +/** + * Dispose a chart instance + * @param {module:echarts~ECharts|HTMLDomElement|string} chart + */ +function dispose(chart) { + if (typeof chart === 'string') { + chart = instances[chart]; + } + else if (!(chart instanceof ECharts)) { + // Try to treat as dom + chart = getInstanceByDom(chart); + } + if ((chart instanceof ECharts) && !chart.isDisposed()) { + chart.dispose(); + } +} + +/** + * @param {HTMLElement} dom + * @return {echarts~ECharts} + */ +function getInstanceByDom(dom) { + return instances[getAttribute(dom, DOM_ATTRIBUTE_KEY)]; +} + +/** + * @param {string} key + * @return {echarts~ECharts} + */ +function getInstanceById(key) { + return instances[key]; +} + +/** + * Register theme + */ +function registerTheme(name, theme$$1) { + themeStorage[name] = theme$$1; +} + +/** + * Register option preprocessor + * @param {Function} preprocessorFunc + */ +function registerPreprocessor(preprocessorFunc) { + optionPreprocessorFuncs.push(preprocessorFunc); +} + +/** + * @param {number} [priority=1000] + * @param {Object|Function} processor + */ +function registerProcessor(priority, processor) { + normalizeRegister(dataProcessorFuncs, priority, processor, PRIORITY_PROCESSOR_FILTER); +} + +/** + * Register postUpdater + * @param {Function} postUpdateFunc + */ +function registerPostUpdate(postUpdateFunc) { + postUpdateFuncs.push(postUpdateFunc); +} + +/** + * Usage: + * registerAction('someAction', 'someEvent', function () { ... }); + * registerAction('someAction', function () { ... }); + * registerAction( + * {type: 'someAction', event: 'someEvent', update: 'updateView'}, + * function () { ... } + * ); + * + * @param {(string|Object)} actionInfo + * @param {string} actionInfo.type + * @param {string} [actionInfo.event] + * @param {string} [actionInfo.update] + * @param {string} [eventName] + * @param {Function} action + */ +function registerAction(actionInfo, eventName, action) { + if (typeof eventName === 'function') { + action = eventName; + eventName = ''; + } + var actionType = isObject(actionInfo) + ? actionInfo.type + : ([actionInfo, actionInfo = { + event: eventName + }][0]); + + // Event name is all lowercase + actionInfo.event = (actionInfo.event || actionType).toLowerCase(); + eventName = actionInfo.event; + + // Validate action type and event name. + assert(ACTION_REG.test(actionType) && ACTION_REG.test(eventName)); + + if (!actions[actionType]) { + actions[actionType] = {action: action, actionInfo: actionInfo}; + } + eventActionMap[eventName] = actionType; +} + +/** + * @param {string} type + * @param {*} CoordinateSystem + */ +function registerCoordinateSystem(type, CoordinateSystem$$1) { + CoordinateSystemManager.register(type, CoordinateSystem$$1); +} + +/** + * Get dimensions of specified coordinate system. + * @param {string} type + * @return {Array.} + */ +function getCoordinateSystemDimensions(type) { + var coordSysCreator = CoordinateSystemManager.get(type); + if (coordSysCreator) { + return coordSysCreator.getDimensionsInfo + ? coordSysCreator.getDimensionsInfo() + : coordSysCreator.dimensions.slice(); + } +} + +/** + * Layout is a special stage of visual encoding + * Most visual encoding like color are common for different chart + * But each chart has it's own layout algorithm + * + * @param {number} [priority=1000] + * @param {Function} layoutTask + */ +function registerLayout(priority, layoutTask) { + normalizeRegister(visualFuncs, priority, layoutTask, PRIORITY_VISUAL_LAYOUT, 'layout'); +} + +/** + * @param {number} [priority=3000] + * @param {module:echarts/stream/Task} visualTask + */ +function registerVisual(priority, visualTask) { + normalizeRegister(visualFuncs, priority, visualTask, PRIORITY_VISUAL_CHART, 'visual'); +} + +/** + * @param {Object|Function} fn: {seriesType, createOnAllSeries, performRawSeries, reset} + */ +function normalizeRegister(targetList, priority, fn, defaultPriority, visualType) { + if (isFunction(priority) || isObject(priority)) { + fn = priority; + priority = defaultPriority; + } + + if (__DEV__) { + if (isNaN(priority) || priority == null) { + throw new Error('Illegal priority'); + } + // Check duplicate + each(targetList, function (wrap) { + assert(wrap.__raw !== fn); + }); + } + + var stageHandler = Scheduler.wrapStageHandler(fn, visualType); + + stageHandler.__prio = priority; + stageHandler.__raw = fn; + targetList.push(stageHandler); + + return stageHandler; +} + +/** + * @param {string} name + */ +function registerLoading(name, loadingFx) { + loadingEffects[name] = loadingFx; +} + +/** + * @param {Object} opts + * @param {string} [superClass] + */ +function extendComponentModel(opts/*, superClass*/) { + // var Clazz = ComponentModel; + // if (superClass) { + // var classType = parseClassType(superClass); + // Clazz = ComponentModel.getClass(classType.main, classType.sub, true); + // } + return ComponentModel.extend(opts); +} + +/** + * @param {Object} opts + * @param {string} [superClass] + */ +function extendComponentView(opts/*, superClass*/) { + // var Clazz = ComponentView; + // if (superClass) { + // var classType = parseClassType(superClass); + // Clazz = ComponentView.getClass(classType.main, classType.sub, true); + // } + return Component.extend(opts); +} + +/** + * @param {Object} opts + * @param {string} [superClass] + */ +function extendSeriesModel(opts/*, superClass*/) { + // var Clazz = SeriesModel; + // if (superClass) { + // superClass = 'series.' + superClass.replace('series.', ''); + // var classType = parseClassType(superClass); + // Clazz = ComponentModel.getClass(classType.main, classType.sub, true); + // } + return SeriesModel.extend(opts); +} + +/** + * @param {Object} opts + * @param {string} [superClass] + */ +function extendChartView(opts/*, superClass*/) { + // var Clazz = ChartView; + // if (superClass) { + // superClass = superClass.replace('series.', ''); + // var classType = parseClassType(superClass); + // Clazz = ChartView.getClass(classType.main, true); + // } + return Chart.extend(opts); +} + +/** + * ZRender need a canvas context to do measureText. + * But in node environment canvas may be created by node-canvas. + * So we need to specify how to create a canvas instead of using document.createElement('canvas') + * + * Be careful of using it in the browser. + * + * @param {Function} creator + * @example + * var Canvas = require('canvas'); + * var echarts = require('echarts'); + * echarts.setCanvasCreator(function () { + * // Small size is enough. + * return new Canvas(32, 32); + * }); + */ +function setCanvasCreator(creator) { + $override('createCanvas', creator); +} + +/** + * @param {string} mapName + * @param {Array.|Object|string} geoJson + * @param {Object} [specialAreas] + * + * @example GeoJSON + * $.get('USA.json', function (geoJson) { + * echarts.registerMap('USA', geoJson); + * // Or + * echarts.registerMap('USA', { + * geoJson: geoJson, + * specialAreas: {} + * }) + * }); + * + * $.get('airport.svg', function (svg) { + * echarts.registerMap('airport', { + * svg: svg + * } + * }); + * + * echarts.registerMap('eu', [ + * {svg: eu-topographic.svg}, + * {geoJSON: eu.json} + * ]) + */ +function registerMap(mapName, geoJson, specialAreas) { + mapDataStorage.registerMap(mapName, geoJson, specialAreas); +} + +/** + * @param {string} mapName + * @return {Object} + */ +function getMap(mapName) { + // For backward compatibility, only return the first one. + var records = mapDataStorage.retrieveMap(mapName); + return records && records[0] && { + geoJson: records[0].geoJSON, + specialAreas: records[0].specialAreas + }; +} + +registerVisual(PRIORITY_VISUAL_GLOBAL, seriesColor); +registerPreprocessor(backwardCompat); +registerProcessor(PRIORITY_PROCESSOR_STATISTIC, dataStack); +registerLoading('default', loadingDefault); + +// Default actions + +registerAction({ + type: 'highlight', + event: 'highlight', + update: 'highlight' +}, noop); + +registerAction({ + type: 'downplay', + event: 'downplay', + update: 'downplay' +}, noop); + +// Default theme +registerTheme('light', lightTheme); +registerTheme('dark', theme); + +// For backward compatibility, where the namespace `dataTool` will +// be mounted on `echarts` is the extension `dataTool` is imported. +var dataTool = {}; + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + + +function defaultKeyGetter(item) { + return item; +} + +/** + * @param {Array} oldArr + * @param {Array} newArr + * @param {Function} oldKeyGetter + * @param {Function} newKeyGetter + * @param {Object} [context] Can be visited by this.context in callback. + */ +function DataDiffer(oldArr, newArr, oldKeyGetter, newKeyGetter, context) { + this._old = oldArr; + this._new = newArr; + + this._oldKeyGetter = oldKeyGetter || defaultKeyGetter; + this._newKeyGetter = newKeyGetter || defaultKeyGetter; + + this.context = context; +} + +DataDiffer.prototype = { + + constructor: DataDiffer, + + /** + * Callback function when add a data + */ + add: function (func) { + this._add = func; + return this; + }, + + /** + * Callback function when update a data + */ + update: function (func) { + this._update = func; + return this; + }, + + /** + * Callback function when remove a data + */ + remove: function (func) { + this._remove = func; + return this; + }, + + execute: function () { + var oldArr = this._old; + var newArr = this._new; + + var oldDataIndexMap = {}; + var newDataIndexMap = {}; + var oldDataKeyArr = []; + var newDataKeyArr = []; + var i; + + initIndexMap(oldArr, oldDataIndexMap, oldDataKeyArr, '_oldKeyGetter', this); + initIndexMap(newArr, newDataIndexMap, newDataKeyArr, '_newKeyGetter', this); + + // Travel by inverted order to make sure order consistency + // when duplicate keys exists (consider newDataIndex.pop() below). + // For performance consideration, these code below do not look neat. + for (i = 0; i < oldArr.length; i++) { + var key = oldDataKeyArr[i]; + var idx = newDataIndexMap[key]; + + // idx can never be empty array here. see 'set null' logic below. + if (idx != null) { + // Consider there is duplicate key (for example, use dataItem.name as key). + // We should make sure every item in newArr and oldArr can be visited. + var len = idx.length; + if (len) { + len === 1 && (newDataIndexMap[key] = null); + idx = idx.unshift(); + } + else { + newDataIndexMap[key] = null; + } + this._update && this._update(idx, i); + } + else { + this._remove && this._remove(i); + } + } + + for (var i = 0; i < newDataKeyArr.length; i++) { + var key = newDataKeyArr[i]; + if (newDataIndexMap.hasOwnProperty(key)) { + var idx = newDataIndexMap[key]; + if (idx == null) { + continue; + } + // idx can never be empty array here. see 'set null' logic above. + if (!idx.length) { + this._add && this._add(idx); + } + else { + for (var j = 0, len = idx.length; j < len; j++) { + this._add && this._add(idx[j]); + } + } + } + } + } +}; + +function initIndexMap(arr, map, keyArr, keyGetterName, dataDiffer) { + for (var i = 0; i < arr.length; i++) { + // Add prefix to avoid conflict with Object.prototype. + var key = '_ec_' + dataDiffer[keyGetterName](arr[i], i); + var existence = map[key]; + if (existence == null) { + keyArr.push(key); + map[key] = i; + } + else { + if (!existence.length) { + map[key] = existence = [existence]; + } + existence.push(i); + } + } +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var OTHER_DIMENSIONS = createHashMap([ + 'tooltip', 'label', 'itemName', 'itemId', 'seriesName' +]); + +function summarizeDimensions(data) { + var summary = {}; + var encode = summary.encode = {}; + var notExtraCoordDimMap = createHashMap(); + var defaultedLabel = []; + var defaultedTooltip = []; + + each$1(data.dimensions, function (dimName) { + var dimItem = data.getDimensionInfo(dimName); + + var coordDim = dimItem.coordDim; + if (coordDim) { + if (__DEV__) { + assert$1(OTHER_DIMENSIONS.get(coordDim) == null); + } + var coordDimArr = encode[coordDim]; + if (!encode.hasOwnProperty(coordDim)) { + coordDimArr = encode[coordDim] = []; + } + coordDimArr[dimItem.coordDimIndex] = dimName; + + if (!dimItem.isExtraCoord) { + notExtraCoordDimMap.set(coordDim, 1); + + // Use the last coord dim (and label friendly) as default label, + // because when dataset is used, it is hard to guess which dimension + // can be value dimension. If both show x, y on label is not look good, + // and conventionally y axis is focused more. + if (mayLabelDimType(dimItem.type)) { + defaultedLabel[0] = dimName; + } + } + if (dimItem.defaultTooltip) { + defaultedTooltip.push(dimName); + } + } + + OTHER_DIMENSIONS.each(function (v, otherDim) { + var otherDimArr = encode[otherDim]; + if (!encode.hasOwnProperty(otherDim)) { + otherDimArr = encode[otherDim] = []; + } + + var dimIndex = dimItem.otherDims[otherDim]; + if (dimIndex != null && dimIndex !== false) { + otherDimArr[dimIndex] = dimItem.name; + } + }); + }); + + var dataDimsOnCoord = []; + var encodeFirstDimNotExtra = {}; + + notExtraCoordDimMap.each(function (v, coordDim) { + var dimArr = encode[coordDim]; + // ??? FIXME extra coord should not be set in dataDimsOnCoord. + // But should fix the case that radar axes: simplify the logic + // of `completeDimension`, remove `extraPrefix`. + encodeFirstDimNotExtra[coordDim] = dimArr[0]; + // Not necessary to remove duplicate, because a data + // dim canot on more than one coordDim. + dataDimsOnCoord = dataDimsOnCoord.concat(dimArr); + }); + + summary.dataDimsOnCoord = dataDimsOnCoord; + summary.encodeFirstDimNotExtra = encodeFirstDimNotExtra; + + var encodeLabel = encode.label; + // FIXME `encode.label` is not recommanded, because formatter can not be set + // in this way. Use label.formatter instead. May be remove this approach someday. + if (encodeLabel && encodeLabel.length) { + defaultedLabel = encodeLabel.slice(); + } + + var encodeTooltip = encode.tooltip; + if (encodeTooltip && encodeTooltip.length) { + defaultedTooltip = encodeTooltip.slice(); + } + else if (!defaultedTooltip.length) { + defaultedTooltip = defaultedLabel.slice(); + } + + encode.defaultedLabel = defaultedLabel; + encode.defaultedTooltip = defaultedTooltip; + + return summary; +} + +function getDimensionTypeByAxis(axisType) { + return axisType === 'category' + ? 'ordinal' + : axisType === 'time' + ? 'time' + : 'float'; +} + +function mayLabelDimType(dimType) { + // In most cases, ordinal and time do not suitable for label. + // Ordinal info can be displayed on axis. Time is too long. + return !(dimType === 'ordinal' || dimType === 'time'); +} + +// function findTheLastDimMayLabel(data) { +// // Get last value dim +// var dimensions = data.dimensions.slice(); +// var valueType; +// var valueDim; +// while (dimensions.length && ( +// valueDim = dimensions.pop(), +// valueType = data.getDimensionInfo(valueDim).type, +// valueType === 'ordinal' || valueType === 'time' +// )) {} // jshint ignore:line +// return valueDim; +// } + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/* global Float64Array, Int32Array, Uint32Array, Uint16Array */ + +/** + * List for data storage + * @module echarts/data/List + */ + +var isObject$4 = isObject$1; + +var UNDEFINED = 'undefined'; +var INDEX_NOT_FOUND = -1; + +// Use prefix to avoid index to be the same as otherIdList[idx], +// which will cause weird udpate animation. +var ID_PREFIX = 'e\0\0'; + +var dataCtors = { + 'float': typeof Float64Array === UNDEFINED + ? Array : Float64Array, + 'int': typeof Int32Array === UNDEFINED + ? Array : Int32Array, + // Ordinal data type can be string or int + 'ordinal': Array, + 'number': Array, + 'time': Array +}; + +// Caution: MUST not use `new CtorUint32Array(arr, 0, len)`, because the Ctor of array is +// different from the Ctor of typed array. +var CtorUint32Array = typeof Uint32Array === UNDEFINED ? Array : Uint32Array; +var CtorInt32Array = typeof Int32Array === UNDEFINED ? Array : Int32Array; +var CtorUint16Array = typeof Uint16Array === UNDEFINED ? Array : Uint16Array; + +function getIndicesCtor(list) { + // The possible max value in this._indicies is always this._rawCount despite of filtering. + return list._rawCount > 65535 ? CtorUint32Array : CtorUint16Array; +} + +function cloneChunk(originalChunk) { + var Ctor = originalChunk.constructor; + // Only shallow clone is enough when Array. + return Ctor === Array ? originalChunk.slice() : new Ctor(originalChunk); +} + +var TRANSFERABLE_PROPERTIES = [ + 'hasItemOption', '_nameList', '_idList', '_invertedIndicesMap', + '_rawData', '_chunkSize', '_chunkCount', '_dimValueGetter', + '_count', '_rawCount', '_nameDimIdx', '_idDimIdx' +]; +var CLONE_PROPERTIES = [ + '_extent', '_approximateExtent', '_rawExtent' +]; + +function transferProperties(target, source) { + each$1(TRANSFERABLE_PROPERTIES.concat(source.__wrappedMethods || []), function (propName) { + if (source.hasOwnProperty(propName)) { + target[propName] = source[propName]; + } + }); + + target.__wrappedMethods = source.__wrappedMethods; + + each$1(CLONE_PROPERTIES, function (propName) { + target[propName] = clone(source[propName]); + }); + + target._calculationInfo = extend(source._calculationInfo); +} + + + + + +/** + * @constructor + * @alias module:echarts/data/List + * + * @param {Array.} dimensions + * For example, ['someDimName', {name: 'someDimName', type: 'someDimType'}, ...]. + * Dimensions should be concrete names like x, y, z, lng, lat, angle, radius + * Spetial fields: { + * ordinalMeta: + * createInvertedIndices: + * } + * @param {module:echarts/model/Model} hostModel + */ +var List = function (dimensions, hostModel) { + + dimensions = dimensions || ['x', 'y']; + + var dimensionInfos = {}; + var dimensionNames = []; + var invertedIndicesMap = {}; + + for (var i = 0; i < dimensions.length; i++) { + // Use the original dimensions[i], where other flag props may exists. + var dimensionInfo = dimensions[i]; + + if (isString(dimensionInfo)) { + dimensionInfo = {name: dimensionInfo}; + } + + var dimensionName = dimensionInfo.name; + dimensionInfo.type = dimensionInfo.type || 'float'; + if (!dimensionInfo.coordDim) { + dimensionInfo.coordDim = dimensionName; + dimensionInfo.coordDimIndex = 0; + } + + dimensionInfo.otherDims = dimensionInfo.otherDims || {}; + dimensionNames.push(dimensionName); + dimensionInfos[dimensionName] = dimensionInfo; + + dimensionInfo.index = i; + + if (dimensionInfo.createInvertedIndices) { + invertedIndicesMap[dimensionName] = []; + } + } + + /** + * @readOnly + * @type {Array.} + */ + this.dimensions = dimensionNames; + + /** + * Infomation of each data dimension, like data type. + * @type {Object} + */ + this._dimensionInfos = dimensionInfos; + + /** + * @type {module:echarts/model/Model} + */ + this.hostModel = hostModel; + + /** + * @type {module:echarts/model/Model} + */ + this.dataType; + + /** + * Indices stores the indices of data subset after filtered. + * This data subset will be used in chart. + * @type {Array.} + * @readOnly + */ + this._indices = null; + + this._count = 0; + this._rawCount = 0; + + /** + * Data storage + * @type {Object.>} + * @private + */ + this._storage = {}; + + /** + * @type {Array.} + */ + this._nameList = []; + /** + * @type {Array.} + */ + this._idList = []; + + /** + * Models of data option is stored sparse for optimizing memory cost + * @type {Array.} + * @private + */ + this._optionModels = []; + + /** + * Global visual properties after visual coding + * @type {Object} + * @private + */ + this._visual = {}; + + /** + * Globel layout properties. + * @type {Object} + * @private + */ + this._layout = {}; + + /** + * Item visual properties after visual coding + * @type {Array.} + * @private + */ + this._itemVisuals = []; + + /** + * Key: visual type, Value: boolean + * @type {Object} + * @readOnly + */ + this.hasItemVisual = {}; + + /** + * Item layout properties after layout + * @type {Array.} + * @private + */ + this._itemLayouts = []; + + /** + * Graphic elemnents + * @type {Array.} + * @private + */ + this._graphicEls = []; + + /** + * Max size of each chunk. + * @type {number} + * @private + */ + this._chunkSize = 1e5; + + /** + * @type {number} + * @private + */ + this._chunkCount = 0; + + /** + * @type {Array.} + * @private + */ + this._rawData; + + /** + * Raw extent will not be cloned, but only transfered. + * It will not be calculated util needed. + * key: dim, + * value: {end: number, extent: Array.} + * @type {Object} + * @private + */ + this._rawExtent = {}; + + /** + * @type {Object} + * @private + */ + this._extent = {}; + + /** + * key: dim + * value: extent + * @type {Object} + * @private + */ + this._approximateExtent = {}; + + /** + * Cache summary info for fast visit. See "dimensionHelper". + * @type {Object} + * @private + */ + this._dimensionsSummary = summarizeDimensions(this); + + /** + * @type {Object.} + * @private + */ + this._invertedIndicesMap = invertedIndicesMap; + + /** + * @type {Object} + * @private + */ + this._calculationInfo = {}; +}; + +var listProto = List.prototype; + +listProto.type = 'list'; + +/** + * If each data item has it's own option + * @type {boolean} + */ +listProto.hasItemOption = true; + +/** + * Get dimension name + * @param {string|number} dim + * Dimension can be concrete names like x, y, z, lng, lat, angle, radius + * Or a ordinal number. For example getDimensionInfo(0) will return 'x' or 'lng' or 'radius' + * @return {string} Concrete dim name. + */ +listProto.getDimension = function (dim) { + if (!isNaN(dim)) { + dim = this.dimensions[dim] || dim; + } + return dim; +}; + +/** + * Get type and calculation info of particular dimension + * @param {string|number} dim + * Dimension can be concrete names like x, y, z, lng, lat, angle, radius + * Or a ordinal number. For example getDimensionInfo(0) will return 'x' or 'lng' or 'radius' + */ +listProto.getDimensionInfo = function (dim) { + // Do not clone, because there may be categories in dimInfo. + return this._dimensionInfos[this.getDimension(dim)]; +}; + +/** + * @return {Array.} concrete dimension name list on coord. + */ +listProto.getDimensionsOnCoord = function () { + return this._dimensionsSummary.dataDimsOnCoord.slice(); +}; + +/** + * @param {string} coordDim + * @param {number} [idx] A coordDim may map to more than one data dim. + * If idx is `true`, return a array of all mapped dims. + * If idx is not specified, return the first dim not extra. + * @return {string|Array.} concrete data dim. + * If idx is number, and not found, return null/undefined. + * If idx is `true`, and not found, return empty array (always return array). + */ +listProto.mapDimension = function (coordDim, idx) { + var dimensionsSummary = this._dimensionsSummary; + + if (idx == null) { + return dimensionsSummary.encodeFirstDimNotExtra[coordDim]; + } + + var dims = dimensionsSummary.encode[coordDim]; + return idx === true + // always return array if idx is `true` + ? (dims || []).slice() + : (dims && dims[idx]); +}; + +/** + * Initialize from data + * @param {Array.} data source or data or data provider. + * @param {Array.} [nameLIst] The name of a datum is used on data diff and + * defualt label/tooltip. + * A name can be specified in encode.itemName, + * or dataItem.name (only for series option data), + * or provided in nameList from outside. + * @param {Function} [dimValueGetter] (dataItem, dimName, dataIndex, dimIndex) => number + */ +listProto.initData = function (data, nameList, dimValueGetter) { + + var notProvider = Source.isInstance(data) || isArrayLike(data); + if (notProvider) { + data = new DefaultDataProvider(data, this.dimensions.length); + } + + if (__DEV__) { + if (!notProvider && (typeof data.getItem !== 'function' || typeof data.count !== 'function')) { + throw new Error('Inavlid data provider.'); + } + } + + this._rawData = data; + + // Clear + this._storage = {}; + this._indices = null; + + this._nameList = nameList || []; + + this._idList = []; + + this._nameRepeatCount = {}; + + if (!dimValueGetter) { + this.hasItemOption = false; + } + + /** + * @readOnly + */ + this.defaultDimValueGetter = defaultDimValueGetters[ + this._rawData.getSource().sourceFormat + ]; + // Default dim value getter + this._dimValueGetter = dimValueGetter = dimValueGetter + || this.defaultDimValueGetter; + this._dimValueGetterArrayRows = defaultDimValueGetters.arrayRows; + + // Reset raw extent. + this._rawExtent = {}; + + this._initDataFromProvider(0, data.count()); + + // If data has no item option. + if (data.pure) { + this.hasItemOption = false; + } +}; + +listProto.getProvider = function () { + return this._rawData; +}; + +/** + * Caution: Can be only called on raw data (before `this._indices` created). + */ +listProto.appendData = function (data) { + if (__DEV__) { + assert$1(!this._indices, 'appendData can only be called on raw data.'); + } + + var rawData = this._rawData; + var start = this.count(); + rawData.appendData(data); + var end = rawData.count(); + if (!rawData.persistent) { + end += start; + } + this._initDataFromProvider(start, end); +}; + +/** + * Caution: Can be only called on raw data (before `this._indices` created). + * This method does not modify `rawData` (`dataProvider`), but only + * add values to storage. + * + * The final count will be increased by `Math.max(values.length, names.length)`. + * + * @param {Array.>} values That is the SourceType: 'arrayRows', like + * [ + * [12, 33, 44], + * [NaN, 43, 1], + * ['-', 'asdf', 0] + * ] + * Each item is exaclty cooresponding to a dimension. + * @param {Array.} [names] + */ +listProto.appendValues = function (values, names) { + var chunkSize = this._chunkSize; + var storage = this._storage; + var dimensions = this.dimensions; + var dimLen = dimensions.length; + var rawExtent = this._rawExtent; + + var start = this.count(); + var end = start + Math.max(values.length, names ? names.length : 0); + var originalChunkCount = this._chunkCount; + + for (var i = 0; i < dimLen; i++) { + var dim = dimensions[i]; + if (!rawExtent[dim]) { + rawExtent[dim] = getInitialExtent(); + } + if (!storage[dim]) { + storage[dim] = []; + } + prepareChunks(storage, this._dimensionInfos[dim], chunkSize, originalChunkCount, end); + this._chunkCount = storage[dim].length; + } + + var emptyDataItem = new Array(dimLen); + for (var idx = start; idx < end; idx++) { + var sourceIdx = idx - start; + var chunkIndex = Math.floor(idx / chunkSize); + var chunkOffset = idx % chunkSize; + + // Store the data by dimensions + for (var k = 0; k < dimLen; k++) { + var dim = dimensions[k]; + var val = this._dimValueGetterArrayRows( + values[sourceIdx] || emptyDataItem, dim, sourceIdx, k + ); + storage[dim][chunkIndex][chunkOffset] = val; + + var dimRawExtent = rawExtent[dim]; + val < dimRawExtent[0] && (dimRawExtent[0] = val); + val > dimRawExtent[1] && (dimRawExtent[1] = val); + } + + if (names) { + this._nameList[idx] = names[sourceIdx]; + } + } + + this._rawCount = this._count = end; + + // Reset data extent + this._extent = {}; + + prepareInvertedIndex(this); +}; + +listProto._initDataFromProvider = function (start, end) { + // Optimize. + if (start >= end) { + return; + } + + var chunkSize = this._chunkSize; + var rawData = this._rawData; + var storage = this._storage; + var dimensions = this.dimensions; + var dimLen = dimensions.length; + var dimensionInfoMap = this._dimensionInfos; + var nameList = this._nameList; + var idList = this._idList; + var rawExtent = this._rawExtent; + var nameRepeatCount = this._nameRepeatCount = {}; + var nameDimIdx; + + var originalChunkCount = this._chunkCount; + for (var i = 0; i < dimLen; i++) { + var dim = dimensions[i]; + if (!rawExtent[dim]) { + rawExtent[dim] = getInitialExtent(); + } + + var dimInfo = dimensionInfoMap[dim]; + if (dimInfo.otherDims.itemName === 0) { + nameDimIdx = this._nameDimIdx = i; + } + if (dimInfo.otherDims.itemId === 0) { + this._idDimIdx = i; + } + + if (!storage[dim]) { + storage[dim] = []; + } + + prepareChunks(storage, dimInfo, chunkSize, originalChunkCount, end); + + this._chunkCount = storage[dim].length; + } + + var dataItem = new Array(dimLen); + for (var idx = start; idx < end; idx++) { + // NOTICE: Try not to write things into dataItem + dataItem = rawData.getItem(idx, dataItem); + // Each data item is value + // [1, 2] + // 2 + // Bar chart, line chart which uses category axis + // only gives the 'y' value. 'x' value is the indices of category + // Use a tempValue to normalize the value to be a (x, y) value + var chunkIndex = Math.floor(idx / chunkSize); + var chunkOffset = idx % chunkSize; + + // Store the data by dimensions + for (var k = 0; k < dimLen; k++) { + var dim = dimensions[k]; + var dimStorage = storage[dim][chunkIndex]; + // PENDING NULL is empty or zero + var val = this._dimValueGetter(dataItem, dim, idx, k); + dimStorage[chunkOffset] = val; + + var dimRawExtent = rawExtent[dim]; + val < dimRawExtent[0] && (dimRawExtent[0] = val); + val > dimRawExtent[1] && (dimRawExtent[1] = val); + } + + // ??? FIXME not check by pure but sourceFormat? + // TODO refactor these logic. + if (!rawData.pure) { + var name = nameList[idx]; + + if (dataItem && name == null) { + // If dataItem is {name: ...}, it has highest priority. + // That is appropriate for many common cases. + if (dataItem.name != null) { + // There is no other place to persistent dataItem.name, + // so save it to nameList. + nameList[idx] = name = dataItem.name; + } + else if (nameDimIdx != null) { + var nameDim = dimensions[nameDimIdx]; + var nameDimChunk = storage[nameDim][chunkIndex]; + if (nameDimChunk) { + name = nameDimChunk[chunkOffset]; + var ordinalMeta = dimensionInfoMap[nameDim].ordinalMeta; + if (ordinalMeta && ordinalMeta.categories.length) { + name = ordinalMeta.categories[name]; + } + } + } + } + + // Try using the id in option + // id or name is used on dynamical data, mapping old and new items. + var id = dataItem == null ? null : dataItem.id; + + if (id == null && name != null) { + // Use name as id and add counter to avoid same name + nameRepeatCount[name] = nameRepeatCount[name] || 0; + id = name; + if (nameRepeatCount[name] > 0) { + id += '__ec__' + nameRepeatCount[name]; + } + nameRepeatCount[name]++; + } + id != null && (idList[idx] = id); + } + } + + if (!rawData.persistent && rawData.clean) { + // Clean unused data if data source is typed array. + rawData.clean(); + } + + this._rawCount = this._count = end; + + // Reset data extent + this._extent = {}; + + prepareInvertedIndex(this); +}; + +function prepareChunks(storage, dimInfo, chunkSize, chunkCount, end) { + var DataCtor = dataCtors[dimInfo.type]; + var lastChunkIndex = chunkCount - 1; + var dim = dimInfo.name; + var resizeChunkArray = storage[dim][lastChunkIndex]; + if (resizeChunkArray && resizeChunkArray.length < chunkSize) { + var newStore = new DataCtor(Math.min(end - lastChunkIndex * chunkSize, chunkSize)); + // The cost of the copy is probably inconsiderable + // within the initial chunkSize. + for (var j = 0; j < resizeChunkArray.length; j++) { + newStore[j] = resizeChunkArray[j]; + } + storage[dim][lastChunkIndex] = newStore; + } + + // Create new chunks. + for (var k = chunkCount * chunkSize; k < end; k += chunkSize) { + storage[dim].push(new DataCtor(Math.min(end - k, chunkSize))); + } +} + +function prepareInvertedIndex(list) { + var invertedIndicesMap = list._invertedIndicesMap; + each$1(invertedIndicesMap, function (invertedIndices, dim) { + var dimInfo = list._dimensionInfos[dim]; + + // Currently, only dimensions that has ordinalMeta can create inverted indices. + var ordinalMeta = dimInfo.ordinalMeta; + if (ordinalMeta) { + invertedIndices = invertedIndicesMap[dim] = new CtorInt32Array( + ordinalMeta.categories.length + ); + // The default value of TypedArray is 0. To avoid miss + // mapping to 0, we should set it as INDEX_NOT_FOUND. + for (var i = 0; i < invertedIndices.length; i++) { + invertedIndices[i] = INDEX_NOT_FOUND; + } + for (var i = 0; i < list._count; i++) { + // Only support the case that all values are distinct. + invertedIndices[list.get(dim, i)] = i; + } + } + }); +} + +function getRawValueFromStore(list, dimIndex, rawIndex) { + var val; + if (dimIndex != null) { + var chunkSize = list._chunkSize; + var chunkIndex = Math.floor(rawIndex / chunkSize); + var chunkOffset = rawIndex % chunkSize; + var dim = list.dimensions[dimIndex]; + var chunk = list._storage[dim][chunkIndex]; + if (chunk) { + val = chunk[chunkOffset]; + var ordinalMeta = list._dimensionInfos[dim].ordinalMeta; + if (ordinalMeta && ordinalMeta.categories.length) { + val = ordinalMeta.categories[val]; + } + } + } + return val; +} + +/** + * @return {number} + */ +listProto.count = function () { + return this._count; +}; + +listProto.getIndices = function () { + var newIndices; + + var indices = this._indices; + if (indices) { + var Ctor = indices.constructor; + var thisCount = this._count; + // `new Array(a, b, c)` is different from `new Uint32Array(a, b, c)`. + if (Ctor === Array) { + newIndices = new Ctor(thisCount); + for (var i = 0; i < thisCount; i++) { + newIndices[i] = indices[i]; + } + } + else { + newIndices = new Ctor(indices.buffer, 0, thisCount); + } + } + else { + var Ctor = getIndicesCtor(this); + var newIndices = new Ctor(this.count()); + for (var i = 0; i < newIndices.length; i++) { + newIndices[i] = i; + } + } + + return newIndices; +}; + +/** + * Get value. Return NaN if idx is out of range. + * @param {string} dim Dim must be concrete name. + * @param {number} idx + * @param {boolean} stack + * @return {number} + */ +listProto.get = function (dim, idx /*, stack */) { + if (!(idx >= 0 && idx < this._count)) { + return NaN; + } + var storage = this._storage; + if (!storage[dim]) { + // TODO Warn ? + return NaN; + } + + idx = this.getRawIndex(idx); + + var chunkIndex = Math.floor(idx / this._chunkSize); + var chunkOffset = idx % this._chunkSize; + + var chunkStore = storage[dim][chunkIndex]; + var value = chunkStore[chunkOffset]; + // FIXME ordinal data type is not stackable + // if (stack) { + // var dimensionInfo = this._dimensionInfos[dim]; + // if (dimensionInfo && dimensionInfo.stackable) { + // var stackedOn = this.stackedOn; + // while (stackedOn) { + // // Get no stacked data of stacked on + // var stackedValue = stackedOn.get(dim, idx); + // // Considering positive stack, negative stack and empty data + // if ((value >= 0 && stackedValue > 0) // Positive stack + // || (value <= 0 && stackedValue < 0) // Negative stack + // ) { + // value += stackedValue; + // } + // stackedOn = stackedOn.stackedOn; + // } + // } + // } + + return value; +}; + +/** + * @param {string} dim concrete dim + * @param {number} rawIndex + * @return {number|string} + */ +listProto.getByRawIndex = function (dim, rawIdx) { + if (!(rawIdx >= 0 && rawIdx < this._rawCount)) { + return NaN; + } + var dimStore = this._storage[dim]; + if (!dimStore) { + // TODO Warn ? + return NaN; + } + + var chunkIndex = Math.floor(rawIdx / this._chunkSize); + var chunkOffset = rawIdx % this._chunkSize; + var chunkStore = dimStore[chunkIndex]; + return chunkStore[chunkOffset]; +}; + +/** + * FIXME Use `get` on chrome maybe slow(in filterSelf and selectRange). + * Hack a much simpler _getFast + * @private + */ +listProto._getFast = function (dim, rawIdx) { + var chunkIndex = Math.floor(rawIdx / this._chunkSize); + var chunkOffset = rawIdx % this._chunkSize; + var chunkStore = this._storage[dim][chunkIndex]; + return chunkStore[chunkOffset]; +}; + +/** + * Get value for multi dimensions. + * @param {Array.} [dimensions] If ignored, using all dimensions. + * @param {number} idx + * @return {number} + */ +listProto.getValues = function (dimensions, idx /*, stack */) { + var values = []; + + if (!isArray(dimensions)) { + // stack = idx; + idx = dimensions; + dimensions = this.dimensions; + } + + for (var i = 0, len = dimensions.length; i < len; i++) { + values.push(this.get(dimensions[i], idx /*, stack */)); + } + + return values; +}; + +/** + * If value is NaN. Inlcuding '-' + * Only check the coord dimensions. + * @param {string} dim + * @param {number} idx + * @return {number} + */ +listProto.hasValue = function (idx) { + var dataDimsOnCoord = this._dimensionsSummary.dataDimsOnCoord; + var dimensionInfos = this._dimensionInfos; + for (var i = 0, len = dataDimsOnCoord.length; i < len; i++) { + if ( + // Ordinal type can be string or number + dimensionInfos[dataDimsOnCoord[i]].type !== 'ordinal' + // FIXME check ordinal when using index? + && isNaN(this.get(dataDimsOnCoord[i], idx)) + ) { + return false; + } + } + return true; +}; + +/** + * Get extent of data in one dimension + * @param {string} dim + * @param {boolean} stack + */ +listProto.getDataExtent = function (dim /*, stack */) { + // Make sure use concrete dim as cache name. + dim = this.getDimension(dim); + var dimData = this._storage[dim]; + var initialExtent = getInitialExtent(); + + // stack = !!((stack || false) && this.getCalculationInfo(dim)); + + if (!dimData) { + return initialExtent; + } + + // Make more strict checkings to ensure hitting cache. + var currEnd = this.count(); + // var cacheName = [dim, !!stack].join('_'); + // var cacheName = dim; + + // Consider the most cases when using data zoom, `getDataExtent` + // happened before filtering. We cache raw extent, which is not + // necessary to be cleared and recalculated when restore data. + var useRaw = !this._indices; // && !stack; + var dimExtent; + + if (useRaw) { + return this._rawExtent[dim].slice(); + } + dimExtent = this._extent[dim]; + if (dimExtent) { + return dimExtent.slice(); + } + dimExtent = initialExtent; + + var min = dimExtent[0]; + var max = dimExtent[1]; + + for (var i = 0; i < currEnd; i++) { + // var value = stack ? this.get(dim, i, true) : this._getFast(dim, this.getRawIndex(i)); + var value = this._getFast(dim, this.getRawIndex(i)); + value < min && (min = value); + value > max && (max = value); + } + + dimExtent = [min, max]; + + this._extent[dim] = dimExtent; + + return dimExtent; +}; + +/** + * Optimize for the scenario that data is filtered by a given extent. + * Consider that if data amount is more than hundreds of thousand, + * extent calculation will cost more than 10ms and the cache will + * be erased because of the filtering. + */ +listProto.getApproximateExtent = function (dim /*, stack */) { + dim = this.getDimension(dim); + return this._approximateExtent[dim] || this.getDataExtent(dim /*, stack */); +}; + +listProto.setApproximateExtent = function (extent, dim /*, stack */) { + dim = this.getDimension(dim); + this._approximateExtent[dim] = extent.slice(); +}; + +/** + * @param {string} key + * @return {*} + */ +listProto.getCalculationInfo = function (key) { + return this._calculationInfo[key]; +}; + +/** + * @param {string|Object} key or k-v object + * @param {*} [value] + */ +listProto.setCalculationInfo = function (key, value) { + isObject$4(key) + ? extend(this._calculationInfo, key) + : (this._calculationInfo[key] = value); +}; + +/** + * Get sum of data in one dimension + * @param {string} dim + */ +listProto.getSum = function (dim /*, stack */) { + var dimData = this._storage[dim]; + var sum = 0; + if (dimData) { + for (var i = 0, len = this.count(); i < len; i++) { + var value = this.get(dim, i /*, stack */); + if (!isNaN(value)) { + sum += value; + } + } + } + return sum; +}; + +/** + * Get median of data in one dimension + * @param {string} dim + */ +listProto.getMedian = function (dim /*, stack */) { + var dimDataArray = []; + // map all data of one dimension + this.each(dim, function (val, idx) { + if (!isNaN(val)) { + dimDataArray.push(val); + } + }); + + // TODO + // Use quick select? + + // immutability & sort + var sortedDimDataArray = [].concat(dimDataArray).sort(function (a, b) { + return a - b; + }); + var len = this.count(); + // calculate median + return len === 0 + ? 0 + : len % 2 === 1 + ? sortedDimDataArray[(len - 1) / 2] + : (sortedDimDataArray[len / 2] + sortedDimDataArray[len / 2 - 1]) / 2; +}; + +// /** +// * Retreive the index with given value +// * @param {string} dim Concrete dimension. +// * @param {number} value +// * @return {number} +// */ +// Currently incorrect: should return dataIndex but not rawIndex. +// Do not fix it until this method is to be used somewhere. +// FIXME Precision of float value +// listProto.indexOf = function (dim, value) { +// var storage = this._storage; +// var dimData = storage[dim]; +// var chunkSize = this._chunkSize; +// if (dimData) { +// for (var i = 0, len = this.count(); i < len; i++) { +// var chunkIndex = Math.floor(i / chunkSize); +// var chunkOffset = i % chunkSize; +// if (dimData[chunkIndex][chunkOffset] === value) { +// return i; +// } +// } +// } +// return -1; +// }; + +/** + * Only support the dimension which inverted index created. + * Do not support other cases until required. + * @param {string} concrete dim + * @param {number|string} value + * @return {number} rawIndex + */ +listProto.rawIndexOf = function (dim, value) { + var invertedIndices = dim && this._invertedIndicesMap[dim]; + if (__DEV__) { + if (!invertedIndices) { + throw new Error('Do not supported yet'); + } + } + var rawIndex = invertedIndices[value]; + if (rawIndex == null || isNaN(rawIndex)) { + return INDEX_NOT_FOUND; + } + return rawIndex; +}; + +/** + * Retreive the index with given name + * @param {number} idx + * @param {number} name + * @return {number} + */ +listProto.indexOfName = function (name) { + for (var i = 0, len = this.count(); i < len; i++) { + if (this.getName(i) === name) { + return i; + } + } + + return -1; +}; + +/** + * Retreive the index with given raw data index + * @param {number} idx + * @param {number} name + * @return {number} + */ +listProto.indexOfRawIndex = function (rawIndex) { + if (!this._indices) { + return rawIndex; + } + + if (rawIndex >= this._rawCount || rawIndex < 0) { + return -1; + } + + // Indices are ascending + var indices = this._indices; + + // If rawIndex === dataIndex + var rawDataIndex = indices[rawIndex]; + if (rawDataIndex != null && rawDataIndex < this._count && rawDataIndex === rawIndex) { + return rawIndex; + } + + var left = 0; + var right = this._count - 1; + while (left <= right) { + var mid = (left + right) / 2 | 0; + if (indices[mid] < rawIndex) { + left = mid + 1; + } + else if (indices[mid] > rawIndex) { + right = mid - 1; + } + else { + return mid; + } + } + return -1; +}; + +/** + * Retreive the index of nearest value + * @param {string} dim + * @param {number} value + * @param {number} [maxDistance=Infinity] + * @return {Array.} Considere multiple points has the same value. + */ +listProto.indicesOfNearest = function (dim, value, maxDistance) { + var storage = this._storage; + var dimData = storage[dim]; + var nearestIndices = []; + + if (!dimData) { + return nearestIndices; + } + + if (maxDistance == null) { + maxDistance = Infinity; + } + + var minDist = Number.MAX_VALUE; + var minDiff = -1; + for (var i = 0, len = this.count(); i < len; i++) { + var diff = value - this.get(dim, i /*, stack */); + var dist = Math.abs(diff); + if (diff <= maxDistance && dist <= minDist) { + // For the case of two data are same on xAxis, which has sequence data. + // Show the nearest index + // https://github.com/ecomfe/echarts/issues/2869 + if (dist < minDist || (diff >= 0 && minDiff < 0)) { + minDist = dist; + minDiff = diff; + nearestIndices.length = 0; + } + nearestIndices.push(i); + } + } + return nearestIndices; +}; + +/** + * Get raw data index + * @param {number} idx + * @return {number} + */ +listProto.getRawIndex = getRawIndexWithoutIndices; + +function getRawIndexWithoutIndices(idx) { + return idx; +} + +function getRawIndexWithIndices(idx) { + if (idx < this._count && idx >= 0) { + return this._indices[idx]; + } + return -1; +} + +/** + * Get raw data item + * @param {number} idx + * @return {number} + */ +listProto.getRawDataItem = function (idx) { + if (!this._rawData.persistent) { + var val = []; + for (var i = 0; i < this.dimensions.length; i++) { + var dim = this.dimensions[i]; + val.push(this.get(dim, idx)); + } + return val; + } + else { + return this._rawData.getItem(this.getRawIndex(idx)); + } +}; + +/** + * @param {number} idx + * @param {boolean} [notDefaultIdx=false] + * @return {string} + */ +listProto.getName = function (idx) { + var rawIndex = this.getRawIndex(idx); + return this._nameList[rawIndex] + || getRawValueFromStore(this, this._nameDimIdx, rawIndex) + || ''; +}; + +/** + * @param {number} idx + * @param {boolean} [notDefaultIdx=false] + * @return {string} + */ +listProto.getId = function (idx) { + return getId(this, this.getRawIndex(idx)); +}; + +function getId(list, rawIndex) { + var id = list._idList[rawIndex]; + if (id == null) { + id = getRawValueFromStore(list, list._idDimIdx, rawIndex); + } + if (id == null) { + // FIXME Check the usage in graph, should not use prefix. + id = ID_PREFIX + rawIndex; + } + return id; +} + +function normalizeDimensions(dimensions) { + if (!isArray(dimensions)) { + dimensions = [dimensions]; + } + return dimensions; +} + +function validateDimensions(list, dims) { + for (var i = 0; i < dims.length; i++) { + // stroage may be empty when no data, so use + // dimensionInfos to check. + if (!list._dimensionInfos[dims[i]]) { + console.error('Unkown dimension ' + dims[i]); + } + } +} + +/** + * Data iteration + * @param {string|Array.} + * @param {Function} cb + * @param {*} [context=this] + * + * @example + * list.each('x', function (x, idx) {}); + * list.each(['x', 'y'], function (x, y, idx) {}); + * list.each(function (idx) {}) + */ +listProto.each = function (dims, cb, context, contextCompat) { + 'use strict'; + + if (!this._count) { + return; + } + + if (typeof dims === 'function') { + contextCompat = context; + context = cb; + cb = dims; + dims = []; + } + + // contextCompat just for compat echarts3 + context = context || contextCompat || this; + + dims = map(normalizeDimensions(dims), this.getDimension, this); + + if (__DEV__) { + validateDimensions(this, dims); + } + + var dimSize = dims.length; + + for (var i = 0; i < this.count(); i++) { + // Simple optimization + switch (dimSize) { + case 0: + cb.call(context, i); + break; + case 1: + cb.call(context, this.get(dims[0], i), i); + break; + case 2: + cb.call(context, this.get(dims[0], i), this.get(dims[1], i), i); + break; + default: + var k = 0; + var value = []; + for (; k < dimSize; k++) { + value[k] = this.get(dims[k], i); + } + // Index + value[k] = i; + cb.apply(context, value); + } + } +}; + +/** + * Data filter + * @param {string|Array.} + * @param {Function} cb + * @param {*} [context=this] + */ +listProto.filterSelf = function (dimensions, cb, context, contextCompat) { + 'use strict'; + + if (!this._count) { + return; + } + + if (typeof dimensions === 'function') { + contextCompat = context; + context = cb; + cb = dimensions; + dimensions = []; + } + + // contextCompat just for compat echarts3 + context = context || contextCompat || this; + + dimensions = map( + normalizeDimensions(dimensions), this.getDimension, this + ); + + if (__DEV__) { + validateDimensions(this, dimensions); + } + + + var count = this.count(); + var Ctor = getIndicesCtor(this); + var newIndices = new Ctor(count); + var value = []; + var dimSize = dimensions.length; + + var offset = 0; + var dim0 = dimensions[0]; + + for (var i = 0; i < count; i++) { + var keep; + var rawIdx = this.getRawIndex(i); + // Simple optimization + if (dimSize === 0) { + keep = cb.call(context, i); + } + else if (dimSize === 1) { + var val = this._getFast(dim0, rawIdx); + keep = cb.call(context, val, i); + } + else { + for (var k = 0; k < dimSize; k++) { + value[k] = this._getFast(dim0, rawIdx); + } + value[k] = i; + keep = cb.apply(context, value); + } + if (keep) { + newIndices[offset++] = rawIdx; + } + } + + // Set indices after filtered. + if (offset < count) { + this._indices = newIndices; + } + this._count = offset; + // Reset data extent + this._extent = {}; + + this.getRawIndex = this._indices ? getRawIndexWithIndices : getRawIndexWithoutIndices; + + return this; +}; + +/** + * Select data in range. (For optimization of filter) + * (Manually inline code, support 5 million data filtering in data zoom.) + */ +listProto.selectRange = function (range) { + 'use strict'; + + if (!this._count) { + return; + } + + var dimensions = []; + for (var dim in range) { + if (range.hasOwnProperty(dim)) { + dimensions.push(dim); + } + } + + if (__DEV__) { + validateDimensions(this, dimensions); + } + + var dimSize = dimensions.length; + if (!dimSize) { + return; + } + + var originalCount = this.count(); + var Ctor = getIndicesCtor(this); + var newIndices = new Ctor(originalCount); + + var offset = 0; + var dim0 = dimensions[0]; + + var min = range[dim0][0]; + var max = range[dim0][1]; + + var quickFinished = false; + if (!this._indices) { + // Extreme optimization for common case. About 2x faster in chrome. + var idx = 0; + if (dimSize === 1) { + var dimStorage = this._storage[dimensions[0]]; + for (var k = 0; k < this._chunkCount; k++) { + var chunkStorage = dimStorage[k]; + var len = Math.min(this._count - k * this._chunkSize, this._chunkSize); + for (var i = 0; i < len; i++) { + var val = chunkStorage[i]; + // NaN will not be filtered. Consider the case, in line chart, empty + // value indicates the line should be broken. But for the case like + // scatter plot, a data item with empty value will not be rendered, + // but the axis extent may be effected if some other dim of the data + // item has value. Fortunately it is not a significant negative effect. + if ( + (val >= min && val <= max) || isNaN(val) + ) { + newIndices[offset++] = idx; + } + idx++; + } + } + quickFinished = true; + } + else if (dimSize === 2) { + var dimStorage = this._storage[dim0]; + var dimStorage2 = this._storage[dimensions[1]]; + var min2 = range[dimensions[1]][0]; + var max2 = range[dimensions[1]][1]; + for (var k = 0; k < this._chunkCount; k++) { + var chunkStorage = dimStorage[k]; + var chunkStorage2 = dimStorage2[k]; + var len = Math.min(this._count - k * this._chunkSize, this._chunkSize); + for (var i = 0; i < len; i++) { + var val = chunkStorage[i]; + var val2 = chunkStorage2[i]; + // Do not filter NaN, see comment above. + if (( + (val >= min && val <= max) || isNaN(val) + ) + && ( + (val2 >= min2 && val2 <= max2) || isNaN(val2) + ) + ) { + newIndices[offset++] = idx; + } + idx++; + } + } + quickFinished = true; + } + } + if (!quickFinished) { + if (dimSize === 1) { + for (var i = 0; i < originalCount; i++) { + var rawIndex = this.getRawIndex(i); + var val = this._getFast(dim0, rawIndex); + // Do not filter NaN, see comment above. + if ( + (val >= min && val <= max) || isNaN(val) + ) { + newIndices[offset++] = rawIndex; + } + } + } + else { + for (var i = 0; i < originalCount; i++) { + var keep = true; + var rawIndex = this.getRawIndex(i); + for (var k = 0; k < dimSize; k++) { + var dimk = dimensions[k]; + var val = this._getFast(dim, rawIndex); + // Do not filter NaN, see comment above. + if (val < range[dimk][0] || val > range[dimk][1]) { + keep = false; + } + } + if (keep) { + newIndices[offset++] = this.getRawIndex(i); + } + } + } + } + + // Set indices after filtered. + if (offset < originalCount) { + this._indices = newIndices; + } + this._count = offset; + // Reset data extent + this._extent = {}; + + this.getRawIndex = this._indices ? getRawIndexWithIndices : getRawIndexWithoutIndices; + + return this; +}; + +/** + * Data mapping to a plain array + * @param {string|Array.} [dimensions] + * @param {Function} cb + * @param {*} [context=this] + * @return {Array} + */ +listProto.mapArray = function (dimensions, cb, context, contextCompat) { + 'use strict'; + + if (typeof dimensions === 'function') { + contextCompat = context; + context = cb; + cb = dimensions; + dimensions = []; + } + + // contextCompat just for compat echarts3 + context = context || contextCompat || this; + + var result = []; + this.each(dimensions, function () { + result.push(cb && cb.apply(this, arguments)); + }, context); + return result; +}; + +// Data in excludeDimensions is copied, otherwise transfered. +function cloneListForMapAndSample(original, excludeDimensions) { + var allDimensions = original.dimensions; + var list = new List( + map(allDimensions, original.getDimensionInfo, original), + original.hostModel + ); + // FIXME If needs stackedOn, value may already been stacked + transferProperties(list, original); + + var storage = list._storage = {}; + var originalStorage = original._storage; + + // Init storage + for (var i = 0; i < allDimensions.length; i++) { + var dim = allDimensions[i]; + if (originalStorage[dim]) { + // Notice that we do not reset invertedIndicesMap here, becuase + // there is no scenario of mapping or sampling ordinal dimension. + if (indexOf(excludeDimensions, dim) >= 0) { + storage[dim] = cloneDimStore(originalStorage[dim]); + list._rawExtent[dim] = getInitialExtent(); + list._extent[dim] = null; + } + else { + // Direct reference for other dimensions + storage[dim] = originalStorage[dim]; + } + } + } + return list; +} + +function cloneDimStore(originalDimStore) { + var newDimStore = new Array(originalDimStore.length); + for (var j = 0; j < originalDimStore.length; j++) { + newDimStore[j] = cloneChunk(originalDimStore[j]); + } + return newDimStore; +} + +function getInitialExtent() { + return [Infinity, -Infinity]; +} + +/** + * Data mapping to a new List with given dimensions + * @param {string|Array.} dimensions + * @param {Function} cb + * @param {*} [context=this] + * @return {Array} + */ +listProto.map = function (dimensions, cb, context, contextCompat) { + 'use strict'; + + // contextCompat just for compat echarts3 + context = context || contextCompat || this; + + dimensions = map( + normalizeDimensions(dimensions), this.getDimension, this + ); + + if (__DEV__) { + validateDimensions(this, dimensions); + } + + var list = cloneListForMapAndSample(this, dimensions); + + // Following properties are all immutable. + // So we can reference to the same value + list._indices = this._indices; + list.getRawIndex = list._indices ? getRawIndexWithIndices : getRawIndexWithoutIndices; + + var storage = list._storage; + + var tmpRetValue = []; + var chunkSize = this._chunkSize; + var dimSize = dimensions.length; + var dataCount = this.count(); + var values = []; + var rawExtent = list._rawExtent; + + for (var dataIndex = 0; dataIndex < dataCount; dataIndex++) { + for (var dimIndex = 0; dimIndex < dimSize; dimIndex++) { + values[dimIndex] = this.get(dimensions[dimIndex], dataIndex /*, stack */); + } + values[dimSize] = dataIndex; + + var retValue = cb && cb.apply(context, values); + if (retValue != null) { + // a number or string (in oridinal dimension)? + if (typeof retValue !== 'object') { + tmpRetValue[0] = retValue; + retValue = tmpRetValue; + } + + var rawIndex = this.getRawIndex(dataIndex); + var chunkIndex = Math.floor(rawIndex / chunkSize); + var chunkOffset = rawIndex % chunkSize; + + for (var i = 0; i < retValue.length; i++) { + var dim = dimensions[i]; + var val = retValue[i]; + var rawExtentOnDim = rawExtent[dim]; + + var dimStore = storage[dim]; + if (dimStore) { + dimStore[chunkIndex][chunkOffset] = val; + } + + if (val < rawExtentOnDim[0]) { + rawExtentOnDim[0] = val; + } + if (val > rawExtentOnDim[1]) { + rawExtentOnDim[1] = val; + } + } + } + } + + return list; +}; + +/** + * Large data down sampling on given dimension + * @param {string} dimension + * @param {number} rate + * @param {Function} sampleValue + * @param {Function} sampleIndex Sample index for name and id + */ +listProto.downSample = function (dimension, rate, sampleValue, sampleIndex) { + var list = cloneListForMapAndSample(this, [dimension]); + var targetStorage = list._storage; + + var frameValues = []; + var frameSize = Math.floor(1 / rate); + + var dimStore = targetStorage[dimension]; + var len = this.count(); + var chunkSize = this._chunkSize; + var rawExtentOnDim = list._rawExtent[dimension]; + + var newIndices = new (getIndicesCtor(this))(len); + + var offset = 0; + for (var i = 0; i < len; i += frameSize) { + // Last frame + if (frameSize > len - i) { + frameSize = len - i; + frameValues.length = frameSize; + } + for (var k = 0; k < frameSize; k++) { + var dataIdx = this.getRawIndex(i + k); + var originalChunkIndex = Math.floor(dataIdx / chunkSize); + var originalChunkOffset = dataIdx % chunkSize; + frameValues[k] = dimStore[originalChunkIndex][originalChunkOffset]; + } + var value = sampleValue(frameValues); + var sampleFrameIdx = this.getRawIndex( + Math.min(i + sampleIndex(frameValues, value) || 0, len - 1) + ); + var sampleChunkIndex = Math.floor(sampleFrameIdx / chunkSize); + var sampleChunkOffset = sampleFrameIdx % chunkSize; + // Only write value on the filtered data + dimStore[sampleChunkIndex][sampleChunkOffset] = value; + + if (value < rawExtentOnDim[0]) { + rawExtentOnDim[0] = value; + } + if (value > rawExtentOnDim[1]) { + rawExtentOnDim[1] = value; + } + + newIndices[offset++] = sampleFrameIdx; + } + + list._count = offset; + list._indices = newIndices; + + list.getRawIndex = getRawIndexWithIndices; + + return list; +}; + +/** + * Get model of one data item. + * + * @param {number} idx + */ +// FIXME Model proxy ? +listProto.getItemModel = function (idx) { + var hostModel = this.hostModel; + return new Model(this.getRawDataItem(idx), hostModel, hostModel && hostModel.ecModel); +}; + +/** + * Create a data differ + * @param {module:echarts/data/List} otherList + * @return {module:echarts/data/DataDiffer} + */ +listProto.diff = function (otherList) { + var thisList = this; + + return new DataDiffer( + otherList ? otherList.getIndices() : [], + this.getIndices(), + function (idx) { + return getId(otherList, idx); + }, + function (idx) { + return getId(thisList, idx); + } + ); +}; +/** + * Get visual property. + * @param {string} key + */ +listProto.getVisual = function (key) { + var visual = this._visual; + return visual && visual[key]; +}; + +/** + * Set visual property + * @param {string|Object} key + * @param {*} [value] + * + * @example + * setVisual('color', color); + * setVisual({ + * 'color': color + * }); + */ +listProto.setVisual = function (key, val) { + if (isObject$4(key)) { + for (var name in key) { + if (key.hasOwnProperty(name)) { + this.setVisual(name, key[name]); + } + } + return; + } + this._visual = this._visual || {}; + this._visual[key] = val; +}; + +/** + * Set layout property. + * @param {string|Object} key + * @param {*} [val] + */ +listProto.setLayout = function (key, val) { + if (isObject$4(key)) { + for (var name in key) { + if (key.hasOwnProperty(name)) { + this.setLayout(name, key[name]); + } + } + return; + } + this._layout[key] = val; +}; + +/** + * Get layout property. + * @param {string} key. + * @return {*} + */ +listProto.getLayout = function (key) { + return this._layout[key]; +}; + +/** + * Get layout of single data item + * @param {number} idx + */ +listProto.getItemLayout = function (idx) { + return this._itemLayouts[idx]; +}; + +/** + * Set layout of single data item + * @param {number} idx + * @param {Object} layout + * @param {boolean=} [merge=false] + */ +listProto.setItemLayout = function (idx, layout, merge$$1) { + this._itemLayouts[idx] = merge$$1 + ? extend(this._itemLayouts[idx] || {}, layout) + : layout; +}; + +/** + * Clear all layout of single data item + */ +listProto.clearItemLayouts = function () { + this._itemLayouts.length = 0; +}; + +/** + * Get visual property of single data item + * @param {number} idx + * @param {string} key + * @param {boolean} [ignoreParent=false] + */ +listProto.getItemVisual = function (idx, key, ignoreParent) { + var itemVisual = this._itemVisuals[idx]; + var val = itemVisual && itemVisual[key]; + if (val == null && !ignoreParent) { + // Use global visual property + return this.getVisual(key); + } + return val; +}; + +/** + * Set visual property of single data item + * + * @param {number} idx + * @param {string|Object} key + * @param {*} [value] + * + * @example + * setItemVisual(0, 'color', color); + * setItemVisual(0, { + * 'color': color + * }); + */ +listProto.setItemVisual = function (idx, key, value) { + var itemVisual = this._itemVisuals[idx] || {}; + var hasItemVisual = this.hasItemVisual; + this._itemVisuals[idx] = itemVisual; + + if (isObject$4(key)) { + for (var name in key) { + if (key.hasOwnProperty(name)) { + itemVisual[name] = key[name]; + hasItemVisual[name] = true; + } + } + return; + } + itemVisual[key] = value; + hasItemVisual[key] = true; +}; + +/** + * Clear itemVisuals and list visual. + */ +listProto.clearAllVisual = function () { + this._visual = {}; + this._itemVisuals = []; + this.hasItemVisual = {}; +}; + +var setItemDataAndSeriesIndex = function (child) { + child.seriesIndex = this.seriesIndex; + child.dataIndex = this.dataIndex; + child.dataType = this.dataType; +}; +/** + * Set graphic element relative to data. It can be set as null + * @param {number} idx + * @param {module:zrender/Element} [el] + */ +listProto.setItemGraphicEl = function (idx, el) { + var hostModel = this.hostModel; + + if (el) { + // Add data index and series index for indexing the data by element + // Useful in tooltip + el.dataIndex = idx; + el.dataType = this.dataType; + el.seriesIndex = hostModel && hostModel.seriesIndex; + if (el.type === 'group') { + el.traverse(setItemDataAndSeriesIndex, el); + } + } + + this._graphicEls[idx] = el; +}; + +/** + * @param {number} idx + * @return {module:zrender/Element} + */ +listProto.getItemGraphicEl = function (idx) { + return this._graphicEls[idx]; +}; + +/** + * @param {Function} cb + * @param {*} context + */ +listProto.eachItemGraphicEl = function (cb, context) { + each$1(this._graphicEls, function (el, idx) { + if (el) { + cb && cb.call(context, el, idx); + } + }); +}; + +/** + * Shallow clone a new list except visual and layout properties, and graph elements. + * New list only change the indices. + */ +listProto.cloneShallow = function (list) { + if (!list) { + var dimensionInfoList = map(this.dimensions, this.getDimensionInfo, this); + list = new List(dimensionInfoList, this.hostModel); + } + + // FIXME + list._storage = this._storage; + + transferProperties(list, this); + + // Clone will not change the data extent and indices + if (this._indices) { + var Ctor = this._indices.constructor; + list._indices = new Ctor(this._indices); + } + else { + list._indices = null; + } + list.getRawIndex = list._indices ? getRawIndexWithIndices : getRawIndexWithoutIndices; + + return list; +}; + +/** + * Wrap some method to add more feature + * @param {string} methodName + * @param {Function} injectFunction + */ +listProto.wrapMethod = function (methodName, injectFunction) { + var originalMethod = this[methodName]; + if (typeof originalMethod !== 'function') { + return; + } + this.__wrappedMethods = this.__wrappedMethods || []; + this.__wrappedMethods.push(methodName); + this[methodName] = function () { + var res = originalMethod.apply(this, arguments); + return injectFunction.apply(this, [res].concat(slice(arguments))); + }; +}; + +// Methods that create a new list based on this list should be listed here. +// Notice that those method should `RETURN` the new list. +listProto.TRANSFERABLE_METHODS = ['cloneShallow', 'downSample', 'map']; +// Methods that change indices of this list should be listed here. +listProto.CHANGABLE_METHODS = ['filterSelf', 'selectRange']; + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/** + * @deprecated + * Use `echarts/data/helper/createDimensions` instead. + */ + +/** + * @see {module:echarts/test/ut/spec/data/completeDimensions} + * + * Complete the dimensions array, by user defined `dimension` and `encode`, + * and guessing from the data structure. + * If no 'value' dimension specified, the first no-named dimension will be + * named as 'value'. + * + * @param {Array.} sysDims Necessary dimensions, like ['x', 'y'], which + * provides not only dim template, but also default order. + * properties: 'name', 'type', 'displayName'. + * `name` of each item provides default coord name. + * [{dimsDef: [string|Object, ...]}, ...] dimsDef of sysDim item provides default dim name, and + * provide dims count that the sysDim required. + * [{ordinalMeta}] can be specified. + * @param {module:echarts/data/Source|Array|Object} source or data (for compatibal with pervious) + * @param {Object} [opt] + * @param {Array.} [opt.dimsDef] option.series.dimensions User defined dimensions + * For example: ['asdf', {name, type}, ...]. + * @param {Object|HashMap} [opt.encodeDef] option.series.encode {x: 2, y: [3, 1], tooltip: [1, 2], label: 3} + * @param {string} [opt.generateCoord] Generate coord dim with the given name. + * If not specified, extra dim names will be: + * 'value', 'value0', 'value1', ... + * @param {number} [opt.generateCoordCount] By default, the generated dim name is `generateCoord`. + * If `generateCoordCount` specified, the generated dim names will be: + * `generateCoord` + 0, `generateCoord` + 1, ... + * can be Infinity, indicate that use all of the remain columns. + * @param {number} [opt.dimCount] If not specified, guess by the first data item. + * @param {number} [opt.encodeDefaulter] If not specified, auto find the next available data dim. + * @return {Array.} [{ + * name: string mandatory, + * displayName: string, the origin name in dimsDef, see source helper. + * If displayName given, the tooltip will displayed vertically. + * coordDim: string mandatory, + * coordDimIndex: number mandatory, + * type: string optional, + * otherDims: { never null/undefined + * tooltip: number optional, + * label: number optional, + * itemName: number optional, + * seriesName: number optional, + * }, + * isExtraCoord: boolean true if coord is generated + * (not specified in encode and not series specified) + * other props ... + * }] + */ +function completeDimensions(sysDims, source, opt) { + if (!Source.isInstance(source)) { + source = Source.seriesDataToSource(source); + } + + opt = opt || {}; + sysDims = (sysDims || []).slice(); + var dimsDef = (opt.dimsDef || []).slice(); + var encodeDef = createHashMap(opt.encodeDef); + var dataDimNameMap = createHashMap(); + var coordDimNameMap = createHashMap(); + // var valueCandidate; + var result = []; + + var dimCount = getDimCount(source, sysDims, dimsDef, opt.dimCount); + + // Apply user defined dims (`name` and `type`) and init result. + for (var i = 0; i < dimCount; i++) { + var dimDefItem = dimsDef[i] = extend( + {}, isObject$1(dimsDef[i]) ? dimsDef[i] : {name: dimsDef[i]} + ); + var userDimName = dimDefItem.name; + var resultItem = result[i] = {otherDims: {}}; + // Name will be applied later for avoiding duplication. + if (userDimName != null && dataDimNameMap.get(userDimName) == null) { + // Only if `series.dimensions` is defined in option + // displayName, will be set, and dimension will be diplayed vertically in + // tooltip by default. + resultItem.name = resultItem.displayName = userDimName; + dataDimNameMap.set(userDimName, i); + } + dimDefItem.type != null && (resultItem.type = dimDefItem.type); + dimDefItem.displayName != null && (resultItem.displayName = dimDefItem.displayName); + } + + // Set `coordDim` and `coordDimIndex` by `encodeDef` and normalize `encodeDef`. + encodeDef.each(function (dataDims, coordDim) { + dataDims = normalizeToArray(dataDims).slice(); + + // Note: It is allowed that `dataDims.length` is `0`, e.g., options is + // `{encode: {x: -1, y: 1}}`. Should not filter anything in + // this case. + if (dataDims.length === 1 && dataDims[0] < 0) { + encodeDef.set(coordDim, false); + return; + } + + var validDataDims = encodeDef.set(coordDim, []); + each$1(dataDims, function (resultDimIdx, idx) { + // The input resultDimIdx can be dim name or index. + isString(resultDimIdx) && (resultDimIdx = dataDimNameMap.get(resultDimIdx)); + if (resultDimIdx != null && resultDimIdx < dimCount) { + validDataDims[idx] = resultDimIdx; + applyDim(result[resultDimIdx], coordDim, idx); + } + }); + }); + + // Apply templetes and default order from `sysDims`. + var availDimIdx = 0; + each$1(sysDims, function (sysDimItem, sysDimIndex) { + var coordDim; + var sysDimItem; + var sysDimItemDimsDef; + var sysDimItemOtherDims; + if (isString(sysDimItem)) { + coordDim = sysDimItem; + sysDimItem = {}; + } + else { + coordDim = sysDimItem.name; + var ordinalMeta = sysDimItem.ordinalMeta; + sysDimItem.ordinalMeta = null; + sysDimItem = clone(sysDimItem); + sysDimItem.ordinalMeta = ordinalMeta; + // `coordDimIndex` should not be set directly. + sysDimItemDimsDef = sysDimItem.dimsDef; + sysDimItemOtherDims = sysDimItem.otherDims; + sysDimItem.name = sysDimItem.coordDim = sysDimItem.coordDimIndex + = sysDimItem.dimsDef = sysDimItem.otherDims = null; + } + + var dataDims = encodeDef.get(coordDim); + + // negative resultDimIdx means no need to mapping. + if (dataDims === false) { + return; + } + + var dataDims = normalizeToArray(dataDims); + + // dimensions provides default dim sequences. + if (!dataDims.length) { + for (var i = 0; i < (sysDimItemDimsDef && sysDimItemDimsDef.length || 1); i++) { + while (availDimIdx < result.length && result[availDimIdx].coordDim != null) { + availDimIdx++; + } + availDimIdx < result.length && dataDims.push(availDimIdx++); + } + } + + // Apply templates. + each$1(dataDims, function (resultDimIdx, coordDimIndex) { + var resultItem = result[resultDimIdx]; + applyDim(defaults(resultItem, sysDimItem), coordDim, coordDimIndex); + if (resultItem.name == null && sysDimItemDimsDef) { + var sysDimItemDimsDefItem = sysDimItemDimsDef[coordDimIndex]; + !isObject$1(sysDimItemDimsDefItem) && (sysDimItemDimsDefItem = {name: sysDimItemDimsDefItem}); + resultItem.name = resultItem.displayName = sysDimItemDimsDefItem.name; + resultItem.defaultTooltip = sysDimItemDimsDefItem.defaultTooltip; + } + // FIXME refactor, currently only used in case: {otherDims: {tooltip: false}} + sysDimItemOtherDims && defaults(resultItem.otherDims, sysDimItemOtherDims); + }); + }); + + function applyDim(resultItem, coordDim, coordDimIndex) { + if (OTHER_DIMENSIONS.get(coordDim) != null) { + resultItem.otherDims[coordDim] = coordDimIndex; + } + else { + resultItem.coordDim = coordDim; + resultItem.coordDimIndex = coordDimIndex; + coordDimNameMap.set(coordDim, true); + } + } + + // Make sure the first extra dim is 'value'. + var generateCoord = opt.generateCoord; + var generateCoordCount = opt.generateCoordCount; + var fromZero = generateCoordCount != null; + generateCoordCount = generateCoord ? (generateCoordCount || 1) : 0; + var extra = generateCoord || 'value'; + + // Set dim `name` and other `coordDim` and other props. + for (var resultDimIdx = 0; resultDimIdx < dimCount; resultDimIdx++) { + var resultItem = result[resultDimIdx] = result[resultDimIdx] || {}; + var coordDim = resultItem.coordDim; + + if (coordDim == null) { + resultItem.coordDim = genName( + extra, coordDimNameMap, fromZero + ); + resultItem.coordDimIndex = 0; + if (!generateCoord || generateCoordCount <= 0) { + resultItem.isExtraCoord = true; + } + generateCoordCount--; + } + + resultItem.name == null && (resultItem.name = genName( + resultItem.coordDim, + dataDimNameMap + )); + + if (resultItem.type == null && guessOrdinal(source, resultDimIdx, resultItem.name)) { + resultItem.type = 'ordinal'; + } + } + + return result; +} + +// ??? TODO +// Originally detect dimCount by data[0]. Should we +// optimize it to only by sysDims and dimensions and encode. +// So only necessary dims will be initialized. +// But +// (1) custom series should be considered. where other dims +// may be visited. +// (2) sometimes user need to calcualte bubble size or use visualMap +// on other dimensions besides coordSys needed. +// So, dims that is not used by system, should be shared in storage? +function getDimCount(source, sysDims, dimsDef, optDimCount) { + // Note that the result dimCount should not small than columns count + // of data, otherwise `dataDimNameMap` checking will be incorrect. + var dimCount = Math.max( + source.dimensionsDetectCount || 1, + sysDims.length, + dimsDef.length, + optDimCount || 0 + ); + each$1(sysDims, function (sysDimItem) { + var sysDimItemDimsDef = sysDimItem.dimsDef; + sysDimItemDimsDef && (dimCount = Math.max(dimCount, sysDimItemDimsDef.length)); + }); + return dimCount; +} + +function genName(name, map$$1, fromZero) { + if (fromZero || map$$1.get(name) != null) { + var i = 0; + while (map$$1.get(name + i) != null) { + i++; + } + name += i; + } + map$$1.set(name, true); + return name; +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/** + * Substitute `completeDimensions`. + * `completeDimensions` is to be deprecated. + */ +/** + * @param {module:echarts/data/Source|module:echarts/data/List} source or data. + * @param {Object|Array} [opt] + * @param {Array.} [opt.coordDimensions=[]] + * @param {number} [opt.dimensionsCount] + * @param {string} [opt.generateCoord] + * @param {string} [opt.generateCoordCount] + * @param {Array.} [opt.dimensionsDefine=source.dimensionsDefine] Overwrite source define. + * @param {Object|HashMap} [opt.encodeDefine=source.encodeDefine] Overwrite source define. + * @return {Array.} dimensionsInfo + */ +var createDimensions = function (source, opt) { + opt = opt || {}; + return completeDimensions(opt.coordDimensions || [], source, { + dimsDef: opt.dimensionsDefine || source.dimensionsDefine, + encodeDef: opt.encodeDefine || source.encodeDefine, + dimCount: opt.dimensionsCount, + generateCoord: opt.generateCoord, + generateCoordCount: opt.generateCoordCount + }); +}; + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/** + * Note that it is too complicated to support 3d stack by value + * (have to create two-dimension inverted index), so in 3d case + * we just support that stacked by index. + * + * @param {module:echarts/model/Series} seriesModel + * @param {Array.} dimensionInfoList The same as the input of . + * The input dimensionInfoList will be modified. + * @param {Object} [opt] + * @param {boolean} [opt.stackedCoordDimension=''] Specify a coord dimension if needed. + * @param {boolean} [opt.byIndex=false] + * @return {Object} calculationInfo + * { + * stackedDimension: string + * stackedByDimension: string + * isStackedByIndex: boolean + * stackedOverDimension: string + * stackResultDimension: string + * } + */ +function enableDataStack(seriesModel, dimensionInfoList, opt) { + opt = opt || {}; + var byIndex = opt.byIndex; + var stackedCoordDimension = opt.stackedCoordDimension; + + // Compatibal: when `stack` is set as '', do not stack. + var mayStack = !!(seriesModel && seriesModel.get('stack')); + var stackedByDimInfo; + var stackedDimInfo; + var stackResultDimension; + var stackedOverDimension; + + each$1(dimensionInfoList, function (dimensionInfo, index) { + if (isString(dimensionInfo)) { + dimensionInfoList[index] = dimensionInfo = {name: dimensionInfo}; + } + + if (mayStack && !dimensionInfo.isExtraCoord) { + // Find the first ordinal dimension as the stackedByDimInfo. + if (!byIndex && !stackedByDimInfo && dimensionInfo.ordinalMeta) { + stackedByDimInfo = dimensionInfo; + } + // Find the first stackable dimension as the stackedDimInfo. + if (!stackedDimInfo + && dimensionInfo.type !== 'ordinal' + && dimensionInfo.type !== 'time' + && (!stackedCoordDimension || stackedCoordDimension === dimensionInfo.coordDim) + ) { + stackedDimInfo = dimensionInfo; + } + } + }); + + if (stackedDimInfo && !byIndex && !stackedByDimInfo) { + // Compatible with previous design, value axis (time axis) only stack by index. + // It may make sense if the user provides elaborately constructed data. + byIndex = true; + } + + // Add stack dimension, they can be both calculated by coordinate system in `unionExtent`. + // That put stack logic in List is for using conveniently in echarts extensions, but it + // might not be a good way. + if (stackedDimInfo) { + // Use a weird name that not duplicated with other names. + stackResultDimension = '__\0ecstackresult'; + stackedOverDimension = '__\0ecstackedover'; + + // Create inverted index to fast query index by value. + if (stackedByDimInfo) { + stackedByDimInfo.createInvertedIndices = true; + } + + var stackedDimCoordDim = stackedDimInfo.coordDim; + var stackedDimType = stackedDimInfo.type; + var stackedDimCoordIndex = 0; + + each$1(dimensionInfoList, function (dimensionInfo) { + if (dimensionInfo.coordDim === stackedDimCoordDim) { + stackedDimCoordIndex++; + } + }); + + dimensionInfoList.push({ + name: stackResultDimension, + coordDim: stackedDimCoordDim, + coordDimIndex: stackedDimCoordIndex, + type: stackedDimType, + isExtraCoord: true, + isCalculationCoord: true + }); + + stackedDimCoordIndex++; + + dimensionInfoList.push({ + name: stackedOverDimension, + // This dimension contains stack base (generally, 0), so do not set it as + // `stackedDimCoordDim` to avoid extent calculation, consider log scale. + coordDim: stackedOverDimension, + coordDimIndex: stackedDimCoordIndex, + type: stackedDimType, + isExtraCoord: true, + isCalculationCoord: true + }); + } + + return { + stackedDimension: stackedDimInfo && stackedDimInfo.name, + stackedByDimension: stackedByDimInfo && stackedByDimInfo.name, + isStackedByIndex: byIndex, + stackedOverDimension: stackedOverDimension, + stackResultDimension: stackResultDimension + }; +} + +/** + * @param {module:echarts/data/List} data + * @param {string} stackedDim + */ +function isDimensionStacked(data, stackedDim /*, stackedByDim*/) { + // Each single series only maps to one pair of axis. So we do not need to + // check stackByDim, whatever stacked by a dimension or stacked by index. + return !!stackedDim && stackedDim === data.getCalculationInfo('stackedDimension'); + // && ( + // stackedByDim != null + // ? stackedByDim === data.getCalculationInfo('stackedByDimension') + // : data.getCalculationInfo('isStackedByIndex') + // ); +} + +/** + * @param {module:echarts/data/List} data + * @param {string} targetDim + * @param {string} [stackedByDim] If not input this parameter, check whether + * stacked by index. + * @return {string} dimension + */ +function getStackedDimension(data, targetDim) { + return isDimensionStacked(data, targetDim) + ? data.getCalculationInfo('stackResultDimension') + : targetDim; +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/** + * @param {module:echarts/data/Source|Array} source Or raw data. + * @param {module:echarts/model/Series} seriesModel + * @param {Object} [opt] + * @param {string} [opt.generateCoord] + */ +function createListFromArray(source, seriesModel, opt) { + opt = opt || {}; + + if (!Source.isInstance(source)) { + source = Source.seriesDataToSource(source); + } + + var coordSysName = seriesModel.get('coordinateSystem'); + var registeredCoordSys = CoordinateSystemManager.get(coordSysName); + + var coordSysDefine = getCoordSysDefineBySeries(seriesModel); + + var coordSysDimDefs; + + if (coordSysDefine) { + coordSysDimDefs = map(coordSysDefine.coordSysDims, function (dim) { + var dimInfo = {name: dim}; + var axisModel = coordSysDefine.axisMap.get(dim); + if (axisModel) { + var axisType = axisModel.get('type'); + dimInfo.type = getDimensionTypeByAxis(axisType); + // dimInfo.stackable = isStackable(axisType); + } + return dimInfo; + }); + } + + if (!coordSysDimDefs) { + // Get dimensions from registered coordinate system + coordSysDimDefs = (registeredCoordSys && ( + registeredCoordSys.getDimensionsInfo + ? registeredCoordSys.getDimensionsInfo() + : registeredCoordSys.dimensions.slice() + )) || ['x', 'y']; + } + + var dimInfoList = createDimensions(source, { + coordDimensions: coordSysDimDefs, + generateCoord: opt.generateCoord + }); + + var firstCategoryDimIndex; + var hasNameEncode; + coordSysDefine && each$1(dimInfoList, function (dimInfo, dimIndex) { + var coordDim = dimInfo.coordDim; + var categoryAxisModel = coordSysDefine.categoryAxisMap.get(coordDim); + if (categoryAxisModel) { + if (firstCategoryDimIndex == null) { + firstCategoryDimIndex = dimIndex; + } + dimInfo.ordinalMeta = categoryAxisModel.getOrdinalMeta(); + } + if (dimInfo.otherDims.itemName != null) { + hasNameEncode = true; + } + }); + if (!hasNameEncode && firstCategoryDimIndex != null) { + dimInfoList[firstCategoryDimIndex].otherDims.itemName = 0; + } + + var stackCalculationInfo = enableDataStack(seriesModel, dimInfoList); + + var list = new List(dimInfoList, seriesModel); + + list.setCalculationInfo(stackCalculationInfo); + + var dimValueGetter = (firstCategoryDimIndex != null && isNeedCompleteOrdinalData(source)) + ? function (itemOpt, dimName, dataIndex, dimIndex) { + // Use dataIndex as ordinal value in categoryAxis + return dimIndex === firstCategoryDimIndex + ? dataIndex + : this.defaultDimValueGetter(itemOpt, dimName, dataIndex, dimIndex); + } + : null; + + list.hasItemOption = false; + list.initData(source, null, dimValueGetter); + + return list; +} + +function isNeedCompleteOrdinalData(source) { + if (source.sourceFormat === SOURCE_FORMAT_ORIGINAL) { + var sampleItem = firstDataNotNull(source.data || []); + return sampleItem != null + && !isArray(getDataItemValue(sampleItem)); + } +} + +function firstDataNotNull(data) { + var i = 0; + while (i < data.length && data[i] == null) { + i++; + } + return data[i]; +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/** + * // Scale class management + * @module echarts/scale/Scale + */ + +/** + * @param {Object} [setting] + */ +function Scale(setting) { + this._setting = setting || {}; + + /** + * Extent + * @type {Array.} + * @protected + */ + this._extent = [Infinity, -Infinity]; + + /** + * Step is calculated in adjustExtent + * @type {Array.} + * @protected + */ + this._interval = 0; + + this.init && this.init.apply(this, arguments); +} + +/** + * Parse input val to valid inner number. + * @param {*} val + * @return {number} + */ +Scale.prototype.parse = function (val) { + // Notice: This would be a trap here, If the implementation + // of this method depends on extent, and this method is used + // before extent set (like in dataZoom), it would be wrong. + // Nevertheless, parse does not depend on extent generally. + return val; +}; + +Scale.prototype.getSetting = function (name) { + return this._setting[name]; +}; + +Scale.prototype.contain = function (val) { + var extent = this._extent; + return val >= extent[0] && val <= extent[1]; +}; + +/** + * Normalize value to linear [0, 1], return 0.5 if extent span is 0 + * @param {number} val + * @return {number} + */ +Scale.prototype.normalize = function (val) { + var extent = this._extent; + if (extent[1] === extent[0]) { + return 0.5; + } + return (val - extent[0]) / (extent[1] - extent[0]); +}; + +/** + * Scale normalized value + * @param {number} val + * @return {number} + */ +Scale.prototype.scale = function (val) { + var extent = this._extent; + return val * (extent[1] - extent[0]) + extent[0]; +}; + +/** + * Set extent from data + * @param {Array.} other + */ +Scale.prototype.unionExtent = function (other) { + var extent = this._extent; + other[0] < extent[0] && (extent[0] = other[0]); + other[1] > extent[1] && (extent[1] = other[1]); + // not setExtent because in log axis it may transformed to power + // this.setExtent(extent[0], extent[1]); +}; + +/** + * Set extent from data + * @param {module:echarts/data/List} data + * @param {string} dim + */ +Scale.prototype.unionExtentFromData = function (data, dim) { + this.unionExtent(data.getApproximateExtent(dim)); +}; + +/** + * Get extent + * @return {Array.} + */ +Scale.prototype.getExtent = function () { + return this._extent.slice(); +}; + +/** + * Set extent + * @param {number} start + * @param {number} end + */ +Scale.prototype.setExtent = function (start, end) { + var thisExtent = this._extent; + if (!isNaN(start)) { + thisExtent[0] = start; + } + if (!isNaN(end)) { + thisExtent[1] = end; + } +}; + +/** + * When axis extent depends on data and no data exists, + * axis ticks should not be drawn, which is named 'blank'. + */ +Scale.prototype.isBlank = function () { + return this._isBlank; +}, + +/** + * When axis extent depends on data and no data exists, + * axis ticks should not be drawn, which is named 'blank'. + */ +Scale.prototype.setBlank = function (isBlank) { + this._isBlank = isBlank; +}; + +/** + * @abstract + * @param {*} tick + * @return {string} label of the tick. + */ +Scale.prototype.getLabel = null; + + +enableClassExtend(Scale); +enableClassManagement(Scale, { + registerWhenExtend: true +}); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/** + * @constructor + * @param {Object} [opt] + * @param {Object} [opt.categories=[]] + * @param {Object} [opt.needCollect=false] + * @param {Object} [opt.deduplication=false] + */ +function OrdinalMeta(opt) { + + /** + * @readOnly + * @type {Array.} + */ + this.categories = opt.categories || []; + + /** + * @private + * @type {boolean} + */ + this._needCollect = opt.needCollect; + + /** + * @private + * @type {boolean} + */ + this._deduplication = opt.deduplication; + + /** + * @private + * @type {boolean} + */ + this._map; +} + +/** + * @param {module:echarts/model/Model} axisModel + * @return {module:echarts/data/OrdinalMeta} + */ +OrdinalMeta.createByAxisModel = function (axisModel) { + var option = axisModel.option; + var data = option.data; + var categories = data && map(data, getName); + + return new OrdinalMeta({ + categories: categories, + needCollect: !categories, + // deduplication is default in axis. + deduplication: option.dedplication !== false + }); +}; + +var proto$1 = OrdinalMeta.prototype; + +/** + * @param {string} category + * @return {number} ordinal + */ +proto$1.getOrdinal = function (category) { + return getOrCreateMap(this).get(category); +}; + +/** + * @param {*} category + * @return {number} The ordinal. If not found, return NaN. + */ +proto$1.parseAndCollect = function (category) { + var index; + var needCollect = this._needCollect; + + // The value of category dim can be the index of the given category set. + // This feature is only supported when !needCollect, because we should + // consider a common case: a value is 2017, which is a number but is + // expected to be tread as a category. This case usually happen in dataset, + // where it happent to be no need of the index feature. + if (typeof category !== 'string' && !needCollect) { + return category; + } + + // Optimize for the scenario: + // category is ['2012-01-01', '2012-01-02', ...], where the input + // data has been ensured not duplicate and is large data. + // Notice, if a dataset dimension provide categroies, usually echarts + // should remove duplication except user tell echarts dont do that + // (set axis.deduplication = false), because echarts do not know whether + // the values in the category dimension has duplication (consider the + // parallel-aqi example) + if (needCollect && !this._deduplication) { + index = this.categories.length; + this.categories[index] = category; + return index; + } + + var map$$1 = getOrCreateMap(this); + index = map$$1.get(category); + + if (index == null) { + if (needCollect) { + index = this.categories.length; + this.categories[index] = category; + map$$1.set(category, index); + } + else { + index = NaN; + } + } + + return index; +}; + +// Consider big data, do not create map until needed. +function getOrCreateMap(ordinalMeta) { + return ordinalMeta._map || ( + ordinalMeta._map = createHashMap(ordinalMeta.categories) + ); +} + +function getName(obj) { + if (isObject$1(obj) && obj.value != null) { + return obj.value; + } + else { + return obj + ''; + } +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/** + * Linear continuous scale + * @module echarts/coord/scale/Ordinal + * + * http://en.wikipedia.org/wiki/Level_of_measurement + */ + +// FIXME only one data + +var scaleProto = Scale.prototype; + +var OrdinalScale = Scale.extend({ + + type: 'ordinal', + + /** + * @param {module:echarts/data/OrdianlMeta|Array.} ordinalMeta + */ + init: function (ordinalMeta, extent) { + // Caution: Should not use instanceof, consider ec-extensions using + // import approach to get OrdinalMeta class. + if (!ordinalMeta || isArray(ordinalMeta)) { + ordinalMeta = new OrdinalMeta({categories: ordinalMeta}); + } + this._ordinalMeta = ordinalMeta; + this._extent = extent || [0, ordinalMeta.categories.length - 1]; + }, + + parse: function (val) { + return typeof val === 'string' + ? this._ordinalMeta.getOrdinal(val) + // val might be float. + : Math.round(val); + }, + + contain: function (rank) { + rank = this.parse(rank); + return scaleProto.contain.call(this, rank) + && this._ordinalMeta.categories[rank] != null; + }, + + /** + * Normalize given rank or name to linear [0, 1] + * @param {number|string} [val] + * @return {number} + */ + normalize: function (val) { + return scaleProto.normalize.call(this, this.parse(val)); + }, + + scale: function (val) { + return Math.round(scaleProto.scale.call(this, val)); + }, + + /** + * @return {Array} + */ + getTicks: function () { + var ticks = []; + var extent = this._extent; + var rank = extent[0]; + + while (rank <= extent[1]) { + ticks.push(rank); + rank++; + } + + return ticks; + }, + + /** + * Get item on rank n + * @param {number} n + * @return {string} + */ + getLabel: function (n) { + if (!this.isBlank()) { + // Note that if no data, ordinalMeta.categories is an empty array. + return this._ordinalMeta.categories[n]; + } + }, + + /** + * @return {number} + */ + count: function () { + return this._extent[1] - this._extent[0] + 1; + }, + + /** + * @override + */ + unionExtentFromData: function (data, dim) { + this.unionExtent(data.getApproximateExtent(dim)); + }, + + getOrdinalMeta: function () { + return this._ordinalMeta; + }, + + niceTicks: noop, + niceExtent: noop +}); + +/** + * @return {module:echarts/scale/Time} + */ +OrdinalScale.create = function () { + return new OrdinalScale(); +}; + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/** + * For testable. + */ + +var roundNumber$1 = round$2; + +/** + * @param {Array.} extent Both extent[0] and extent[1] should be valid number. + * Should be extent[0] < extent[1]. + * @param {number} splitNumber splitNumber should be >= 1. + * @param {number} [minInterval] + * @param {number} [maxInterval] + * @return {Object} {interval, intervalPrecision, niceTickExtent} + */ +function intervalScaleNiceTicks(extent, splitNumber, minInterval, maxInterval) { + var result = {}; + var span = extent[1] - extent[0]; + + var interval = result.interval = nice(span / splitNumber, true); + if (minInterval != null && interval < minInterval) { + interval = result.interval = minInterval; + } + if (maxInterval != null && interval > maxInterval) { + interval = result.interval = maxInterval; + } + // Tow more digital for tick. + var precision = result.intervalPrecision = getIntervalPrecision(interval); + // Niced extent inside original extent + var niceTickExtent = result.niceTickExtent = [ + roundNumber$1(Math.ceil(extent[0] / interval) * interval, precision), + roundNumber$1(Math.floor(extent[1] / interval) * interval, precision) + ]; + + fixExtent(niceTickExtent, extent); + + return result; +} + +/** + * @param {number} interval + * @return {number} interval precision + */ +function getIntervalPrecision(interval) { + // Tow more digital for tick. + return getPrecisionSafe(interval) + 2; +} + +function clamp(niceTickExtent, idx, extent) { + niceTickExtent[idx] = Math.max(Math.min(niceTickExtent[idx], extent[1]), extent[0]); +} + +// In some cases (e.g., splitNumber is 1), niceTickExtent may be out of extent. +function fixExtent(niceTickExtent, extent) { + !isFinite(niceTickExtent[0]) && (niceTickExtent[0] = extent[0]); + !isFinite(niceTickExtent[1]) && (niceTickExtent[1] = extent[1]); + clamp(niceTickExtent, 0, extent); + clamp(niceTickExtent, 1, extent); + if (niceTickExtent[0] > niceTickExtent[1]) { + niceTickExtent[0] = niceTickExtent[1]; + } +} + +function intervalScaleGetTicks(interval, extent, niceTickExtent, intervalPrecision) { + var ticks = []; + + // If interval is 0, return []; + if (!interval) { + return ticks; + } + + // Consider this case: using dataZoom toolbox, zoom and zoom. + var safeLimit = 10000; + + if (extent[0] < niceTickExtent[0]) { + ticks.push(extent[0]); + } + var tick = niceTickExtent[0]; + + while (tick <= niceTickExtent[1]) { + ticks.push(tick); + // Avoid rounding error + tick = roundNumber$1(tick + interval, intervalPrecision); + if (tick === ticks[ticks.length - 1]) { + // Consider out of safe float point, e.g., + // -3711126.9907707 + 2e-10 === -3711126.9907707 + break; + } + if (ticks.length > safeLimit) { + return []; + } + } + // Consider this case: the last item of ticks is smaller + // than niceTickExtent[1] and niceTickExtent[1] === extent[1]. + if (extent[1] > (ticks.length ? ticks[ticks.length - 1] : niceTickExtent[1])) { + ticks.push(extent[1]); + } + + return ticks; +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/** + * Interval scale + * @module echarts/scale/Interval + */ + + +var roundNumber = round$2; + +/** + * @alias module:echarts/coord/scale/Interval + * @constructor + */ +var IntervalScale = Scale.extend({ + + type: 'interval', + + _interval: 0, + + _intervalPrecision: 2, + + setExtent: function (start, end) { + var thisExtent = this._extent; + //start,end may be a Number like '25',so... + if (!isNaN(start)) { + thisExtent[0] = parseFloat(start); + } + if (!isNaN(end)) { + thisExtent[1] = parseFloat(end); + } + }, + + unionExtent: function (other) { + var extent = this._extent; + other[0] < extent[0] && (extent[0] = other[0]); + other[1] > extent[1] && (extent[1] = other[1]); + + // unionExtent may called by it's sub classes + IntervalScale.prototype.setExtent.call(this, extent[0], extent[1]); + }, + /** + * Get interval + */ + getInterval: function () { + return this._interval; + }, + + /** + * Set interval + */ + setInterval: function (interval) { + this._interval = interval; + // Dropped auto calculated niceExtent and use user setted extent + // We assume user wan't to set both interval, min, max to get a better result + this._niceExtent = this._extent.slice(); + + this._intervalPrecision = getIntervalPrecision(interval); + }, + + /** + * @return {Array.} + */ + getTicks: function () { + return intervalScaleGetTicks( + this._interval, this._extent, this._niceExtent, this._intervalPrecision + ); + }, + + /** + * @param {number} data + * @param {Object} [opt] + * @param {number|string} [opt.precision] If 'auto', use nice presision. + * @param {boolean} [opt.pad] returns 1.50 but not 1.5 if precision is 2. + * @return {string} + */ + getLabel: function (data, opt) { + if (data == null) { + return ''; + } + + var precision = opt && opt.precision; + + if (precision == null) { + precision = getPrecisionSafe(data) || 0; + } + else if (precision === 'auto') { + // Should be more precise then tick. + precision = this._intervalPrecision; + } + + // (1) If `precision` is set, 12.005 should be display as '12.00500'. + // (2) Use roundNumber (toFixed) to avoid scientific notation like '3.5e-7'. + data = roundNumber(data, precision, true); + + return addCommas(data); + }, + + /** + * Update interval and extent of intervals for nice ticks + * + * @param {number} [splitNumber = 5] Desired number of ticks + * @param {number} [minInterval] + * @param {number} [maxInterval] + */ + niceTicks: function (splitNumber, minInterval, maxInterval) { + splitNumber = splitNumber || 5; + var extent = this._extent; + var span = extent[1] - extent[0]; + if (!isFinite(span)) { + return; + } + // User may set axis min 0 and data are all negative + // FIXME If it needs to reverse ? + if (span < 0) { + span = -span; + extent.reverse(); + } + + var result = intervalScaleNiceTicks( + extent, splitNumber, minInterval, maxInterval + ); + + this._intervalPrecision = result.intervalPrecision; + this._interval = result.interval; + this._niceExtent = result.niceTickExtent; + }, + + /** + * Nice extent. + * @param {Object} opt + * @param {number} [opt.splitNumber = 5] Given approx tick number + * @param {boolean} [opt.fixMin=false] + * @param {boolean} [opt.fixMax=false] + * @param {boolean} [opt.minInterval] + * @param {boolean} [opt.maxInterval] + */ + niceExtent: function (opt) { + var extent = this._extent; + // If extent start and end are same, expand them + if (extent[0] === extent[1]) { + if (extent[0] !== 0) { + // Expand extent + var expandSize = extent[0]; + // In the fowllowing case + // Axis has been fixed max 100 + // Plus data are all 100 and axis extent are [100, 100]. + // Extend to the both side will cause expanded max is larger than fixed max. + // So only expand to the smaller side. + if (!opt.fixMax) { + extent[1] += expandSize / 2; + extent[0] -= expandSize / 2; + } + else { + extent[0] -= expandSize / 2; + } + } + else { + extent[1] = 1; + } + } + var span = extent[1] - extent[0]; + // If there are no data and extent are [Infinity, -Infinity] + if (!isFinite(span)) { + extent[0] = 0; + extent[1] = 1; + } + + this.niceTicks(opt.splitNumber, opt.minInterval, opt.maxInterval); + + // var extent = this._extent; + var interval = this._interval; + + if (!opt.fixMin) { + extent[0] = roundNumber(Math.floor(extent[0] / interval) * interval); + } + if (!opt.fixMax) { + extent[1] = roundNumber(Math.ceil(extent[1] / interval) * interval); + } + } +}); + +/** + * @return {module:echarts/scale/Time} + */ +IntervalScale.create = function () { + return new IntervalScale(); +}; + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/* global Float32Array */ + +var STACK_PREFIX = '__ec_stack_'; +var LARGE_BAR_MIN_WIDTH = 0.5; + +var LargeArr = typeof Float32Array !== 'undefined' ? Float32Array : Array; + +function getSeriesStackId(seriesModel) { + return seriesModel.get('stack') || STACK_PREFIX + seriesModel.seriesIndex; +} + +function getAxisKey(axis) { + return axis.dim + axis.index; +} + +/** + * @param {Object} opt + * @param {module:echarts/coord/Axis} opt.axis Only support category axis currently. + * @param {number} opt.count Positive interger. + * @param {number} [opt.barWidth] + * @param {number} [opt.barMaxWidth] + * @param {number} [opt.barGap] + * @param {number} [opt.barCategoryGap] + * @return {Object} {width, offset, offsetCenter} If axis.type is not 'category', return undefined. + */ +function getLayoutOnAxis(opt) { + var params = []; + var baseAxis = opt.axis; + var axisKey = 'axis0'; + + if (baseAxis.type !== 'category') { + return; + } + var bandWidth = baseAxis.getBandWidth(); + + for (var i = 0; i < opt.count || 0; i++) { + params.push(defaults({ + bandWidth: bandWidth, + axisKey: axisKey, + stackId: STACK_PREFIX + i + }, opt)); + } + var widthAndOffsets = doCalBarWidthAndOffset(params); + + var result = []; + for (var i = 0; i < opt.count; i++) { + var item = widthAndOffsets[axisKey][STACK_PREFIX + i]; + item.offsetCenter = item.offset + item.width / 2; + result.push(item); + } + + return result; +} + +function prepareLayoutBarSeries(seriesType, ecModel) { + var seriesModels = []; + ecModel.eachSeriesByType(seriesType, function (seriesModel) { + // Check series coordinate, do layout for cartesian2d only + if (isOnCartesian(seriesModel) && !isInLargeMode(seriesModel)) { + seriesModels.push(seriesModel); + } + }); + return seriesModels; +} + +function makeColumnLayout(barSeries) { + var seriesInfoList = []; + each$1(barSeries, function (seriesModel) { + var data = seriesModel.getData(); + var cartesian = seriesModel.coordinateSystem; + var baseAxis = cartesian.getBaseAxis(); + var axisExtent = baseAxis.getExtent(); + var bandWidth = baseAxis.type === 'category' + ? baseAxis.getBandWidth() + : (Math.abs(axisExtent[1] - axisExtent[0]) / data.count()); + + var barWidth = parsePercent$1( + seriesModel.get('barWidth'), bandWidth + ); + var barMaxWidth = parsePercent$1( + seriesModel.get('barMaxWidth'), bandWidth + ); + var barGap = seriesModel.get('barGap'); + var barCategoryGap = seriesModel.get('barCategoryGap'); + + seriesInfoList.push({ + bandWidth: bandWidth, + barWidth: barWidth, + barMaxWidth: barMaxWidth, + barGap: barGap, + barCategoryGap: barCategoryGap, + axisKey: getAxisKey(baseAxis), + stackId: getSeriesStackId(seriesModel) + }); + }); + + return doCalBarWidthAndOffset(seriesInfoList); +} + +function doCalBarWidthAndOffset(seriesInfoList) { + // Columns info on each category axis. Key is cartesian name + var columnsMap = {}; + + each$1(seriesInfoList, function (seriesInfo, idx) { + var axisKey = seriesInfo.axisKey; + var bandWidth = seriesInfo.bandWidth; + var columnsOnAxis = columnsMap[axisKey] || { + bandWidth: bandWidth, + remainedWidth: bandWidth, + autoWidthCount: 0, + categoryGap: '20%', + gap: '30%', + stacks: {} + }; + var stacks = columnsOnAxis.stacks; + columnsMap[axisKey] = columnsOnAxis; + + var stackId = seriesInfo.stackId; + + if (!stacks[stackId]) { + columnsOnAxis.autoWidthCount++; + } + stacks[stackId] = stacks[stackId] || { + width: 0, + maxWidth: 0 + }; + + // Caution: In a single coordinate system, these barGrid attributes + // will be shared by series. Consider that they have default values, + // only the attributes set on the last series will work. + // Do not change this fact unless there will be a break change. + + // TODO + var barWidth = seriesInfo.barWidth; + if (barWidth && !stacks[stackId].width) { + // See #6312, do not restrict width. + stacks[stackId].width = barWidth; + barWidth = Math.min(columnsOnAxis.remainedWidth, barWidth); + columnsOnAxis.remainedWidth -= barWidth; + } + + var barMaxWidth = seriesInfo.barMaxWidth; + barMaxWidth && (stacks[stackId].maxWidth = barMaxWidth); + var barGap = seriesInfo.barGap; + (barGap != null) && (columnsOnAxis.gap = barGap); + var barCategoryGap = seriesInfo.barCategoryGap; + (barCategoryGap != null) && (columnsOnAxis.categoryGap = barCategoryGap); + }); + + var result = {}; + + each$1(columnsMap, function (columnsOnAxis, coordSysName) { + + result[coordSysName] = {}; + + var stacks = columnsOnAxis.stacks; + var bandWidth = columnsOnAxis.bandWidth; + var categoryGap = parsePercent$1(columnsOnAxis.categoryGap, bandWidth); + var barGapPercent = parsePercent$1(columnsOnAxis.gap, 1); + + var remainedWidth = columnsOnAxis.remainedWidth; + var autoWidthCount = columnsOnAxis.autoWidthCount; + var autoWidth = (remainedWidth - categoryGap) + / (autoWidthCount + (autoWidthCount - 1) * barGapPercent); + autoWidth = Math.max(autoWidth, 0); + + // Find if any auto calculated bar exceeded maxBarWidth + each$1(stacks, function (column, stack) { + var maxWidth = column.maxWidth; + if (maxWidth && maxWidth < autoWidth) { + maxWidth = Math.min(maxWidth, remainedWidth); + if (column.width) { + maxWidth = Math.min(maxWidth, column.width); + } + remainedWidth -= maxWidth; + column.width = maxWidth; + autoWidthCount--; + } + }); + + // Recalculate width again + autoWidth = (remainedWidth - categoryGap) + / (autoWidthCount + (autoWidthCount - 1) * barGapPercent); + autoWidth = Math.max(autoWidth, 0); + + var widthSum = 0; + var lastColumn; + each$1(stacks, function (column, idx) { + if (!column.width) { + column.width = autoWidth; + } + lastColumn = column; + widthSum += column.width * (1 + barGapPercent); + }); + if (lastColumn) { + widthSum -= lastColumn.width * barGapPercent; + } + + var offset = -widthSum / 2; + each$1(stacks, function (column, stackId) { + result[coordSysName][stackId] = result[coordSysName][stackId] || { + offset: offset, + width: column.width + }; + + offset += column.width * (1 + barGapPercent); + }); + }); + + return result; +} + +/** + * @param {Object} barWidthAndOffset The result of makeColumnLayout + * @param {module:echarts/coord/Axis} axis + * @param {module:echarts/model/Series} [seriesModel] If not provided, return all. + * @return {Object} {stackId: {offset, width}} or {offset, width} if seriesModel provided. + */ +function retrieveColumnLayout(barWidthAndOffset, axis, seriesModel) { + if (barWidthAndOffset && axis) { + var result = barWidthAndOffset[getAxisKey(axis)]; + if (result != null && seriesModel != null) { + result = result[getSeriesStackId(seriesModel)]; + } + return result; + } +} + +/** + * @param {string} seriesType + * @param {module:echarts/model/Global} ecModel + */ +function layout(seriesType, ecModel) { + + var seriesModels = prepareLayoutBarSeries(seriesType, ecModel); + var barWidthAndOffset = makeColumnLayout(seriesModels); + + var lastStackCoords = {}; + each$1(seriesModels, function (seriesModel) { + + var data = seriesModel.getData(); + var cartesian = seriesModel.coordinateSystem; + var baseAxis = cartesian.getBaseAxis(); + + var stackId = getSeriesStackId(seriesModel); + var columnLayoutInfo = barWidthAndOffset[getAxisKey(baseAxis)][stackId]; + var columnOffset = columnLayoutInfo.offset; + var columnWidth = columnLayoutInfo.width; + var valueAxis = cartesian.getOtherAxis(baseAxis); + + var barMinHeight = seriesModel.get('barMinHeight') || 0; + + lastStackCoords[stackId] = lastStackCoords[stackId] || []; + data.setLayout({ + offset: columnOffset, + size: columnWidth + }); + + var valueDim = data.mapDimension(valueAxis.dim); + var baseDim = data.mapDimension(baseAxis.dim); + var stacked = isDimensionStacked(data, valueDim /*, baseDim*/); + var isValueAxisH = valueAxis.isHorizontal(); + + var valueAxisStart = getValueAxisStart(baseAxis, valueAxis, stacked); + + for (var idx = 0, len = data.count(); idx < len; idx++) { + var value = data.get(valueDim, idx); + var baseValue = data.get(baseDim, idx); + + if (isNaN(value)) { + continue; + } + + var sign = value >= 0 ? 'p' : 'n'; + var baseCoord = valueAxisStart; + + // Because of the barMinHeight, we can not use the value in + // stackResultDimension directly. + if (stacked) { + // Only ordinal axis can be stacked. + if (!lastStackCoords[stackId][baseValue]) { + lastStackCoords[stackId][baseValue] = { + p: valueAxisStart, // Positive stack + n: valueAxisStart // Negative stack + }; + } + // Should also consider #4243 + baseCoord = lastStackCoords[stackId][baseValue][sign]; + } + + var x; + var y; + var width; + var height; + + if (isValueAxisH) { + var coord = cartesian.dataToPoint([value, baseValue]); + x = baseCoord; + y = coord[1] + columnOffset; + width = coord[0] - valueAxisStart; + height = columnWidth; + + if (Math.abs(width) < barMinHeight) { + width = (width < 0 ? -1 : 1) * barMinHeight; + } + stacked && (lastStackCoords[stackId][baseValue][sign] += width); + } + else { + var coord = cartesian.dataToPoint([baseValue, value]); + x = coord[0] + columnOffset; + y = baseCoord; + width = columnWidth; + height = coord[1] - valueAxisStart; + + if (Math.abs(height) < barMinHeight) { + // Include zero to has a positive bar + height = (height <= 0 ? -1 : 1) * barMinHeight; + } + stacked && (lastStackCoords[stackId][baseValue][sign] += height); + } + + data.setItemLayout(idx, { + x: x, + y: y, + width: width, + height: height + }); + } + + }, this); +} + +// TODO: Do not support stack in large mode yet. +var largeLayout = { + + seriesType: 'bar', + + plan: createRenderPlanner(), + + reset: function (seriesModel) { + if (!isOnCartesian(seriesModel) || !isInLargeMode(seriesModel)) { + return; + } + + var data = seriesModel.getData(); + var cartesian = seriesModel.coordinateSystem; + var baseAxis = cartesian.getBaseAxis(); + var valueAxis = cartesian.getOtherAxis(baseAxis); + var valueDim = data.mapDimension(valueAxis.dim); + var baseDim = data.mapDimension(baseAxis.dim); + var valueAxisHorizontal = valueAxis.isHorizontal(); + var valueDimIdx = valueAxisHorizontal ? 0 : 1; + + var barWidth = retrieveColumnLayout( + makeColumnLayout([seriesModel]), baseAxis, seriesModel + ).width; + if (!(barWidth > LARGE_BAR_MIN_WIDTH)) { // jshint ignore:line + barWidth = LARGE_BAR_MIN_WIDTH; + } + + return {progress: progress}; + + function progress(params, data) { + var largePoints = new LargeArr(params.count * 2); + var dataIndex; + var coord = []; + var valuePair = []; + var offset = 0; + + while ((dataIndex = params.next()) != null) { + valuePair[valueDimIdx] = data.get(valueDim, dataIndex); + valuePair[1 - valueDimIdx] = data.get(baseDim, dataIndex); + + coord = cartesian.dataToPoint(valuePair, null, coord); + largePoints[offset++] = coord[0]; + largePoints[offset++] = coord[1]; + } + + data.setLayout({ + largePoints: largePoints, + barWidth: barWidth, + valueAxisStart: getValueAxisStart(baseAxis, valueAxis, false), + valueAxisHorizontal: valueAxisHorizontal + }); + } + } +}; + +function isOnCartesian(seriesModel) { + return seriesModel.coordinateSystem && seriesModel.coordinateSystem.type === 'cartesian2d'; +} + +function isInLargeMode(seriesModel) { + return seriesModel.pipelineContext && seriesModel.pipelineContext.large; +} + +// See cases in `test/bar-start.html` and `#7412`, `#8747`. +function getValueAxisStart(baseAxis, valueAxis, stacked) { + var extent = valueAxis.getGlobalExtent(); + var min; + var max; + if (extent[0] > extent[1]) { + min = extent[1]; + max = extent[0]; + } + else { + min = extent[0]; + max = extent[1]; + } + + var valueStart = valueAxis.toGlobalCoord(valueAxis.dataToCoord(0)); + valueStart < min && (valueStart = min); + valueStart > max && (valueStart = max); + + return valueStart; +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/* +* A third-party license is embeded for some of the code in this file: +* The "scaleLevels" was originally copied from "d3.js" with some +* modifications made for this project. +* (See more details in the comment on the definition of "scaleLevels" below.) +* The use of the source code of this file is also subject to the terms +* and consitions of the license of "d3.js" (BSD-3Clause, see +* ). +*/ + + +// [About UTC and local time zone]: +// In most cases, `number.parseDate` will treat input data string as local time +// (except time zone is specified in time string). And `format.formateTime` returns +// local time by default. option.useUTC is false by default. This design have +// concidered these common case: +// (1) Time that is persistent in server is in UTC, but it is needed to be diplayed +// in local time by default. +// (2) By default, the input data string (e.g., '2011-01-02') should be displayed +// as its original time, without any time difference. + +var intervalScaleProto = IntervalScale.prototype; + +var mathCeil = Math.ceil; +var mathFloor = Math.floor; +var ONE_SECOND = 1000; +var ONE_MINUTE = ONE_SECOND * 60; +var ONE_HOUR = ONE_MINUTE * 60; +var ONE_DAY = ONE_HOUR * 24; + +// FIXME 公用? +var bisect = function (a, x, lo, hi) { + while (lo < hi) { + var mid = lo + hi >>> 1; + if (a[mid][1] < x) { + lo = mid + 1; + } + else { + hi = mid; + } + } + return lo; +}; + +/** + * @alias module:echarts/coord/scale/Time + * @constructor + */ +var TimeScale = IntervalScale.extend({ + type: 'time', + + /** + * @override + */ + getLabel: function (val) { + var stepLvl = this._stepLvl; + + var date = new Date(val); + + return formatTime(stepLvl[0], date, this.getSetting('useUTC')); + }, + + /** + * @override + */ + niceExtent: function (opt) { + var extent = this._extent; + // If extent start and end are same, expand them + if (extent[0] === extent[1]) { + // Expand extent + extent[0] -= ONE_DAY; + extent[1] += ONE_DAY; + } + // If there are no data and extent are [Infinity, -Infinity] + if (extent[1] === -Infinity && extent[0] === Infinity) { + var d = new Date(); + extent[1] = +new Date(d.getFullYear(), d.getMonth(), d.getDate()); + extent[0] = extent[1] - ONE_DAY; + } + + this.niceTicks(opt.splitNumber, opt.minInterval, opt.maxInterval); + + // var extent = this._extent; + var interval = this._interval; + + if (!opt.fixMin) { + extent[0] = round$2(mathFloor(extent[0] / interval) * interval); + } + if (!opt.fixMax) { + extent[1] = round$2(mathCeil(extent[1] / interval) * interval); + } + }, + + /** + * @override + */ + niceTicks: function (approxTickNum, minInterval, maxInterval) { + approxTickNum = approxTickNum || 10; + + var extent = this._extent; + var span = extent[1] - extent[0]; + var approxInterval = span / approxTickNum; + + if (minInterval != null && approxInterval < minInterval) { + approxInterval = minInterval; + } + if (maxInterval != null && approxInterval > maxInterval) { + approxInterval = maxInterval; + } + + var scaleLevelsLen = scaleLevels.length; + var idx = bisect(scaleLevels, approxInterval, 0, scaleLevelsLen); + + var level = scaleLevels[Math.min(idx, scaleLevelsLen - 1)]; + var interval = level[1]; + // Same with interval scale if span is much larger than 1 year + if (level[0] === 'year') { + var yearSpan = span / interval; + + // From "Nice Numbers for Graph Labels" of Graphic Gems + // var niceYearSpan = numberUtil.nice(yearSpan, false); + var yearStep = nice(yearSpan / approxTickNum, true); + + interval *= yearStep; + } + + var timezoneOffset = this.getSetting('useUTC') + ? 0 : (new Date(+extent[0] || +extent[1])).getTimezoneOffset() * 60 * 1000; + var niceExtent = [ + Math.round(mathCeil((extent[0] - timezoneOffset) / interval) * interval + timezoneOffset), + Math.round(mathFloor((extent[1] - timezoneOffset) / interval) * interval + timezoneOffset) + ]; + + fixExtent(niceExtent, extent); + + this._stepLvl = level; + // Interval will be used in getTicks + this._interval = interval; + this._niceExtent = niceExtent; + }, + + parse: function (val) { + // val might be float. + return +parseDate(val); + } +}); + +each$1(['contain', 'normalize'], function (methodName) { + TimeScale.prototype[methodName] = function (val) { + return intervalScaleProto[methodName].call(this, this.parse(val)); + }; +}); + +/** + * This implementation was originally copied from "d3.js" + * + * with some modifications made for this program. + * See the license statement at the head of this file. + */ +var scaleLevels = [ + // Format interval + ['hh:mm:ss', ONE_SECOND], // 1s + ['hh:mm:ss', ONE_SECOND * 5], // 5s + ['hh:mm:ss', ONE_SECOND * 10], // 10s + ['hh:mm:ss', ONE_SECOND * 15], // 15s + ['hh:mm:ss', ONE_SECOND * 30], // 30s + ['hh:mm\nMM-dd', ONE_MINUTE], // 1m + ['hh:mm\nMM-dd', ONE_MINUTE * 5], // 5m + ['hh:mm\nMM-dd', ONE_MINUTE * 10], // 10m + ['hh:mm\nMM-dd', ONE_MINUTE * 15], // 15m + ['hh:mm\nMM-dd', ONE_MINUTE * 30], // 30m + ['hh:mm\nMM-dd', ONE_HOUR], // 1h + ['hh:mm\nMM-dd', ONE_HOUR * 2], // 2h + ['hh:mm\nMM-dd', ONE_HOUR * 6], // 6h + ['hh:mm\nMM-dd', ONE_HOUR * 12], // 12h + ['MM-dd\nyyyy', ONE_DAY], // 1d + ['MM-dd\nyyyy', ONE_DAY * 2], // 2d + ['MM-dd\nyyyy', ONE_DAY * 3], // 3d + ['MM-dd\nyyyy', ONE_DAY * 4], // 4d + ['MM-dd\nyyyy', ONE_DAY * 5], // 5d + ['MM-dd\nyyyy', ONE_DAY * 6], // 6d + ['week', ONE_DAY * 7], // 7d + ['MM-dd\nyyyy', ONE_DAY * 10], // 10d + ['week', ONE_DAY * 14], // 2w + ['week', ONE_DAY * 21], // 3w + ['month', ONE_DAY * 31], // 1M + ['week', ONE_DAY * 42], // 6w + ['month', ONE_DAY * 62], // 2M + ['week', ONE_DAY * 70], // 10w + ['quarter', ONE_DAY * 95], // 3M + ['month', ONE_DAY * 31 * 4], // 4M + ['month', ONE_DAY * 31 * 5], // 5M + ['half-year', ONE_DAY * 380 / 2], // 6M + ['month', ONE_DAY * 31 * 8], // 8M + ['month', ONE_DAY * 31 * 10], // 10M + ['year', ONE_DAY * 380] // 1Y +]; + +/** + * @param {module:echarts/model/Model} + * @return {module:echarts/scale/Time} + */ +TimeScale.create = function (model) { + return new TimeScale({useUTC: model.ecModel.get('useUTC')}); +}; + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/** + * Log scale + * @module echarts/scale/Log + */ + +// Use some method of IntervalScale +var scaleProto$1 = Scale.prototype; +var intervalScaleProto$1 = IntervalScale.prototype; + +var getPrecisionSafe$1 = getPrecisionSafe; +var roundingErrorFix = round$2; + +var mathFloor$1 = Math.floor; +var mathCeil$1 = Math.ceil; +var mathPow$1 = Math.pow; + +var mathLog = Math.log; + +var LogScale = Scale.extend({ + + type: 'log', + + base: 10, + + $constructor: function () { + Scale.apply(this, arguments); + this._originalScale = new IntervalScale(); + }, + + /** + * @return {Array.} + */ + getTicks: function () { + var originalScale = this._originalScale; + var extent = this._extent; + var originalExtent = originalScale.getExtent(); + + return map(intervalScaleProto$1.getTicks.call(this), function (val) { + var powVal = round$2(mathPow$1(this.base, val)); + + // Fix #4158 + powVal = (val === extent[0] && originalScale.__fixMin) + ? fixRoundingError(powVal, originalExtent[0]) + : powVal; + powVal = (val === extent[1] && originalScale.__fixMax) + ? fixRoundingError(powVal, originalExtent[1]) + : powVal; + + return powVal; + }, this); + }, + + /** + * @param {number} val + * @return {string} + */ + getLabel: intervalScaleProto$1.getLabel, + + /** + * @param {number} val + * @return {number} + */ + scale: function (val) { + val = scaleProto$1.scale.call(this, val); + return mathPow$1(this.base, val); + }, + + /** + * @param {number} start + * @param {number} end + */ + setExtent: function (start, end) { + var base = this.base; + start = mathLog(start) / mathLog(base); + end = mathLog(end) / mathLog(base); + intervalScaleProto$1.setExtent.call(this, start, end); + }, + + /** + * @return {number} end + */ + getExtent: function () { + var base = this.base; + var extent = scaleProto$1.getExtent.call(this); + extent[0] = mathPow$1(base, extent[0]); + extent[1] = mathPow$1(base, extent[1]); + + // Fix #4158 + var originalScale = this._originalScale; + var originalExtent = originalScale.getExtent(); + originalScale.__fixMin && (extent[0] = fixRoundingError(extent[0], originalExtent[0])); + originalScale.__fixMax && (extent[1] = fixRoundingError(extent[1], originalExtent[1])); + + return extent; + }, + + /** + * @param {Array.} extent + */ + unionExtent: function (extent) { + this._originalScale.unionExtent(extent); + + var base = this.base; + extent[0] = mathLog(extent[0]) / mathLog(base); + extent[1] = mathLog(extent[1]) / mathLog(base); + scaleProto$1.unionExtent.call(this, extent); + }, + + /** + * @override + */ + unionExtentFromData: function (data, dim) { + // TODO + // filter value that <= 0 + this.unionExtent(data.getApproximateExtent(dim)); + }, + + /** + * Update interval and extent of intervals for nice ticks + * @param {number} [approxTickNum = 10] Given approx tick number + */ + niceTicks: function (approxTickNum) { + approxTickNum = approxTickNum || 10; + var extent = this._extent; + var span = extent[1] - extent[0]; + if (span === Infinity || span <= 0) { + return; + } + + var interval = quantity(span); + var err = approxTickNum / span * interval; + + // Filter ticks to get closer to the desired count. + if (err <= 0.5) { + interval *= 10; + } + + // Interval should be integer + while (!isNaN(interval) && Math.abs(interval) < 1 && Math.abs(interval) > 0) { + interval *= 10; + } + + var niceExtent = [ + round$2(mathCeil$1(extent[0] / interval) * interval), + round$2(mathFloor$1(extent[1] / interval) * interval) + ]; + + this._interval = interval; + this._niceExtent = niceExtent; + }, + + /** + * Nice extent. + * @override + */ + niceExtent: function (opt) { + intervalScaleProto$1.niceExtent.call(this, opt); + + var originalScale = this._originalScale; + originalScale.__fixMin = opt.fixMin; + originalScale.__fixMax = opt.fixMax; + } + +}); + +each$1(['contain', 'normalize'], function (methodName) { + LogScale.prototype[methodName] = function (val) { + val = mathLog(val) / mathLog(this.base); + return scaleProto$1[methodName].call(this, val); + }; +}); + +LogScale.create = function () { + return new LogScale(); +}; + +function fixRoundingError(val, originalVal) { + return roundingErrorFix(val, getPrecisionSafe$1(originalVal)); +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/** + * Get axis scale extent before niced. + * Item of returned array can only be number (including Infinity and NaN). + */ +function getScaleExtent(scale, model) { + var scaleType = scale.type; + + var min = model.getMin(); + var max = model.getMax(); + var fixMin = min != null; + var fixMax = max != null; + var originalExtent = scale.getExtent(); + + var axisDataLen; + var boundaryGap; + var span; + if (scaleType === 'ordinal') { + axisDataLen = model.getCategories().length; + } + else { + boundaryGap = model.get('boundaryGap'); + if (!isArray(boundaryGap)) { + boundaryGap = [boundaryGap || 0, boundaryGap || 0]; + } + if (typeof boundaryGap[0] === 'boolean') { + if (__DEV__) { + console.warn('Boolean type for boundaryGap is only ' + + 'allowed for ordinal axis. Please use string in ' + + 'percentage instead, e.g., "20%". Currently, ' + + 'boundaryGap is set to be 0.'); + } + boundaryGap = [0, 0]; + } + boundaryGap[0] = parsePercent$1(boundaryGap[0], 1); + boundaryGap[1] = parsePercent$1(boundaryGap[1], 1); + span = (originalExtent[1] - originalExtent[0]) + || Math.abs(originalExtent[0]); + } + + // Notice: When min/max is not set (that is, when there are null/undefined, + // which is the most common case), these cases should be ensured: + // (1) For 'ordinal', show all axis.data. + // (2) For others: + // + `boundaryGap` is applied (if min/max set, boundaryGap is + // disabled). + // + If `needCrossZero`, min/max should be zero, otherwise, min/max should + // be the result that originalExtent enlarged by boundaryGap. + // (3) If no data, it should be ensured that `scale.setBlank` is set. + + // FIXME + // (1) When min/max is 'dataMin' or 'dataMax', should boundaryGap be able to used? + // (2) When `needCrossZero` and all data is positive/negative, should it be ensured + // that the results processed by boundaryGap are positive/negative? + + if (min == null) { + min = scaleType === 'ordinal' + ? (axisDataLen ? 0 : NaN) + : originalExtent[0] - boundaryGap[0] * span; + } + if (max == null) { + max = scaleType === 'ordinal' + ? (axisDataLen ? axisDataLen - 1 : NaN) + : originalExtent[1] + boundaryGap[1] * span; + } + + if (min === 'dataMin') { + min = originalExtent[0]; + } + else if (typeof min === 'function') { + min = min({ + min: originalExtent[0], + max: originalExtent[1] + }); + } + + if (max === 'dataMax') { + max = originalExtent[1]; + } + else if (typeof max === 'function') { + max = max({ + min: originalExtent[0], + max: originalExtent[1] + }); + } + + (min == null || !isFinite(min)) && (min = NaN); + (max == null || !isFinite(max)) && (max = NaN); + + scale.setBlank( + eqNaN(min) + || eqNaN(max) + || (scaleType === 'ordinal' && !scale.getOrdinalMeta().categories.length) + ); + + // Evaluate if axis needs cross zero + if (model.getNeedCrossZero()) { + // Axis is over zero and min is not set + if (min > 0 && max > 0 && !fixMin) { + min = 0; + } + // Axis is under zero and max is not set + if (min < 0 && max < 0 && !fixMax) { + max = 0; + } + } + + // If bars are placed on a base axis of type time or interval account for axis boundary overflow and current axis + // is base axis + // FIXME + // (1) Consider support value axis, where below zero and axis `onZero` should be handled properly. + // (2) Refactor the logic with `barGrid`. Is it not need to `makeBarWidthAndOffsetInfo` twice with different extent? + // Should not depend on series type `bar`? + // (3) Fix that might overlap when using dataZoom. + // (4) Consider other chart types using `barGrid`? + // See #6728, #4862, `test/bar-overflow-time-plot.html` + var ecModel = model.ecModel; + if (ecModel && (scaleType === 'time' /*|| scaleType === 'interval' */)) { + var barSeriesModels = prepareLayoutBarSeries('bar', ecModel); + var isBaseAxisAndHasBarSeries; + + each$1(barSeriesModels, function (seriesModel) { + isBaseAxisAndHasBarSeries |= seriesModel.getBaseAxis() === model.axis; + }); + + if (isBaseAxisAndHasBarSeries) { + // Calculate placement of bars on axis + var barWidthAndOffset = makeColumnLayout(barSeriesModels); + + // Adjust axis min and max to account for overflow + var adjustedScale = adjustScaleForOverflow(min, max, model, barWidthAndOffset); + min = adjustedScale.min; + max = adjustedScale.max; + } + } + + return [min, max]; +} + +function adjustScaleForOverflow(min, max, model, barWidthAndOffset) { + + // Get Axis Length + var axisExtent = model.axis.getExtent(); + var axisLength = axisExtent[1] - axisExtent[0]; + + // Get bars on current base axis and calculate min and max overflow + var barsOnCurrentAxis = retrieveColumnLayout(barWidthAndOffset, model.axis); + if (barsOnCurrentAxis === undefined) { + return {min: min, max: max}; + } + + var minOverflow = Infinity; + each$1(barsOnCurrentAxis, function (item) { + minOverflow = Math.min(item.offset, minOverflow); + }); + var maxOverflow = -Infinity; + each$1(barsOnCurrentAxis, function (item) { + maxOverflow = Math.max(item.offset + item.width, maxOverflow); + }); + minOverflow = Math.abs(minOverflow); + maxOverflow = Math.abs(maxOverflow); + var totalOverFlow = minOverflow + maxOverflow; + + // Calulate required buffer based on old range and overflow + var oldRange = max - min; + var oldRangePercentOfNew = (1 - (minOverflow + maxOverflow) / axisLength); + var overflowBuffer = ((oldRange / oldRangePercentOfNew) - oldRange); + + max += overflowBuffer * (maxOverflow / totalOverFlow); + min -= overflowBuffer * (minOverflow / totalOverFlow); + + return {min: min, max: max}; +} + +function niceScaleExtent(scale, model) { + var extent = getScaleExtent(scale, model); + var fixMin = model.getMin() != null; + var fixMax = model.getMax() != null; + var splitNumber = model.get('splitNumber'); + + if (scale.type === 'log') { + scale.base = model.get('logBase'); + } + + var scaleType = scale.type; + scale.setExtent(extent[0], extent[1]); + scale.niceExtent({ + splitNumber: splitNumber, + fixMin: fixMin, + fixMax: fixMax, + minInterval: (scaleType === 'interval' || scaleType === 'time') + ? model.get('minInterval') : null, + maxInterval: (scaleType === 'interval' || scaleType === 'time') + ? model.get('maxInterval') : null + }); + + // If some one specified the min, max. And the default calculated interval + // is not good enough. He can specify the interval. It is often appeared + // in angle axis with angle 0 - 360. Interval calculated in interval scale is hard + // to be 60. + // FIXME + var interval = model.get('interval'); + if (interval != null) { + scale.setInterval && scale.setInterval(interval); + } +} + +/** + * @param {module:echarts/model/Model} model + * @param {string} [axisType] Default retrieve from model.type + * @return {module:echarts/scale/*} + */ +function createScaleByModel(model, axisType) { + axisType = axisType || model.get('type'); + if (axisType) { + switch (axisType) { + // Buildin scale + case 'category': + return new OrdinalScale( + model.getOrdinalMeta + ? model.getOrdinalMeta() + : model.getCategories(), + [Infinity, -Infinity] + ); + case 'value': + return new IntervalScale(); + // Extended scale, like time and log + default: + return (Scale.getClass(axisType) || IntervalScale).create(model); + } + } +} + +/** + * Check if the axis corss 0 + */ +function ifAxisCrossZero(axis) { + var dataExtent = axis.scale.getExtent(); + var min = dataExtent[0]; + var max = dataExtent[1]; + return !((min > 0 && max > 0) || (min < 0 && max < 0)); +} + +/** + * @param {module:echarts/coord/Axis} axis + * @return {Function} Label formatter function. + * param: {number} tickValue, + * param: {number} idx, the index in all ticks. + * If category axis, this param is not requied. + * return: {string} label string. + */ +function makeLabelFormatter(axis) { + var labelFormatter = axis.getLabelModel().get('formatter'); + var categoryTickStart = axis.type === 'category' ? axis.scale.getExtent()[0] : null; + + if (typeof labelFormatter === 'string') { + labelFormatter = (function (tpl) { + return function (val) { + // For category axis, get raw value; for numeric axis, + // get foramtted label like '1,333,444'. + val = axis.scale.getLabel(val); + return tpl.replace('{value}', val != null ? val : ''); + }; + })(labelFormatter); + // Consider empty array + return labelFormatter; + } + else if (typeof labelFormatter === 'function') { + return function (tickValue, idx) { + // The original intention of `idx` is "the index of the tick in all ticks". + // But the previous implementation of category axis do not consider the + // `axisLabel.interval`, which cause that, for example, the `interval` is + // `1`, then the ticks "name5", "name7", "name9" are displayed, where the + // corresponding `idx` are `0`, `2`, `4`, but not `0`, `1`, `2`. So we keep + // the definition here for back compatibility. + if (categoryTickStart != null) { + idx = tickValue - categoryTickStart; + } + return labelFormatter(getAxisRawValue(axis, tickValue), idx); + }; + } + else { + return function (tick) { + return axis.scale.getLabel(tick); + }; + } +} + +function getAxisRawValue(axis, value) { + // In category axis with data zoom, tick is not the original + // index of axis.data. So tick should not be exposed to user + // in category axis. + return axis.type === 'category' ? axis.scale.getLabel(value) : value; +} + +/** + * @param {module:echarts/coord/Axis} axis + * @return {module:zrender/core/BoundingRect} Be null/undefined if no labels. + */ +function estimateLabelUnionRect(axis) { + var axisModel = axis.model; + var scale = axis.scale; + + if (!axisModel.get('axisLabel.show') || scale.isBlank()) { + return; + } + + var isCategory = axis.type === 'category'; + + var realNumberScaleTicks; + var tickCount; + var categoryScaleExtent = scale.getExtent(); + + // Optimize for large category data, avoid call `getTicks()`. + if (isCategory) { + tickCount = scale.count(); + } + else { + realNumberScaleTicks = scale.getTicks(); + tickCount = realNumberScaleTicks.length; + } + + var axisLabelModel = axis.getLabelModel(); + var labelFormatter = makeLabelFormatter(axis); + + var rect; + var step = 1; + // Simple optimization for large amount of labels + if (tickCount > 40) { + step = Math.ceil(tickCount / 40); + } + for (var i = 0; i < tickCount; i += step) { + var tickValue = realNumberScaleTicks ? realNumberScaleTicks[i] : categoryScaleExtent[0] + i; + var label = labelFormatter(tickValue); + var unrotatedSingleRect = axisLabelModel.getTextRect(label); + var singleRect = rotateTextRect(unrotatedSingleRect, axisLabelModel.get('rotate') || 0); + + rect ? rect.union(singleRect) : (rect = singleRect); + } + + return rect; +} + +function rotateTextRect(textRect, rotate) { + var rotateRadians = rotate * Math.PI / 180; + var boundingBox = textRect.plain(); + var beforeWidth = boundingBox.width; + var beforeHeight = boundingBox.height; + var afterWidth = beforeWidth * Math.cos(rotateRadians) + beforeHeight * Math.sin(rotateRadians); + var afterHeight = beforeWidth * Math.sin(rotateRadians) + beforeHeight * Math.cos(rotateRadians); + var rotatedRect = new BoundingRect(boundingBox.x, boundingBox.y, afterWidth, afterHeight); + + return rotatedRect; +} + +/** + * @param {module:echarts/src/model/Model} model axisLabelModel or axisTickModel + * @return {number|String} Can be null|'auto'|number|function + */ +function getOptionCategoryInterval(model) { + var interval = model.get('interval'); + return interval == null ? 'auto' : interval; +} + +/** + * Set `categoryInterval` as 0 implicitly indicates that + * show all labels reguardless of overlap. + * @param {Object} axis axisModel.axis + * @return {boolean} + */ +function shouldShowAllLabels(axis) { + return axis.type === 'category' + && getOptionCategoryInterval(axis.getLabelModel()) === 0; +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +// import * as axisHelper from './axisHelper'; + +var axisModelCommonMixin = { + + /** + * @param {boolean} origin + * @return {number|string} min value or 'dataMin' or null/undefined (means auto) or NaN + */ + getMin: function (origin) { + var option = this.option; + var min = (!origin && option.rangeStart != null) + ? option.rangeStart : option.min; + + if (this.axis + && min != null + && min !== 'dataMin' + && typeof min !== 'function' + && !eqNaN(min) + ) { + min = this.axis.scale.parse(min); + } + return min; + }, + + /** + * @param {boolean} origin + * @return {number|string} max value or 'dataMax' or null/undefined (means auto) or NaN + */ + getMax: function (origin) { + var option = this.option; + var max = (!origin && option.rangeEnd != null) + ? option.rangeEnd : option.max; + + if (this.axis + && max != null + && max !== 'dataMax' + && typeof max !== 'function' + && !eqNaN(max) + ) { + max = this.axis.scale.parse(max); + } + return max; + }, + + /** + * @return {boolean} + */ + getNeedCrossZero: function () { + var option = this.option; + return (option.rangeStart != null || option.rangeEnd != null) + ? false : !option.scale; + }, + + /** + * Should be implemented by each axis model if necessary. + * @return {module:echarts/model/Component} coordinate system model + */ + getCoordSysModel: noop, + + /** + * @param {number} rangeStart Can only be finite number or null/undefined or NaN. + * @param {number} rangeEnd Can only be finite number or null/undefined or NaN. + */ + setRange: function (rangeStart, rangeEnd) { + this.option.rangeStart = rangeStart; + this.option.rangeEnd = rangeEnd; + }, + + /** + * Reset range + */ + resetRange: function () { + // rangeStart and rangeEnd is readonly. + this.option.rangeStart = this.option.rangeEnd = null; + } +}; + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +// Symbol factory + +/** + * Triangle shape + * @inner + */ +var Triangle = extendShape({ + type: 'triangle', + shape: { + cx: 0, + cy: 0, + width: 0, + height: 0 + }, + buildPath: function (path, shape) { + var cx = shape.cx; + var cy = shape.cy; + var width = shape.width / 2; + var height = shape.height / 2; + path.moveTo(cx, cy - height); + path.lineTo(cx + width, cy + height); + path.lineTo(cx - width, cy + height); + path.closePath(); + } +}); + +/** + * Diamond shape + * @inner + */ +var Diamond = extendShape({ + type: 'diamond', + shape: { + cx: 0, + cy: 0, + width: 0, + height: 0 + }, + buildPath: function (path, shape) { + var cx = shape.cx; + var cy = shape.cy; + var width = shape.width / 2; + var height = shape.height / 2; + path.moveTo(cx, cy - height); + path.lineTo(cx + width, cy); + path.lineTo(cx, cy + height); + path.lineTo(cx - width, cy); + path.closePath(); + } +}); + +/** + * Pin shape + * @inner + */ +var Pin = extendShape({ + type: 'pin', + shape: { + // x, y on the cusp + x: 0, + y: 0, + width: 0, + height: 0 + }, + + buildPath: function (path, shape) { + var x = shape.x; + var y = shape.y; + var w = shape.width / 5 * 3; + // Height must be larger than width + var h = Math.max(w, shape.height); + var r = w / 2; + + // Dist on y with tangent point and circle center + var dy = r * r / (h - r); + var cy = y - h + r + dy; + var angle = Math.asin(dy / r); + // Dist on x with tangent point and circle center + var dx = Math.cos(angle) * r; + + var tanX = Math.sin(angle); + var tanY = Math.cos(angle); + + var cpLen = r * 0.6; + var cpLen2 = r * 0.7; + + path.moveTo(x - dx, cy + dy); + + path.arc( + x, cy, r, + Math.PI - angle, + Math.PI * 2 + angle + ); + path.bezierCurveTo( + x + dx - tanX * cpLen, cy + dy + tanY * cpLen, + x, y - cpLen2, + x, y + ); + path.bezierCurveTo( + x, y - cpLen2, + x - dx + tanX * cpLen, cy + dy + tanY * cpLen, + x - dx, cy + dy + ); + path.closePath(); + } +}); + +/** + * Arrow shape + * @inner + */ +var Arrow = extendShape({ + + type: 'arrow', + + shape: { + x: 0, + y: 0, + width: 0, + height: 0 + }, + + buildPath: function (ctx, shape) { + var height = shape.height; + var width = shape.width; + var x = shape.x; + var y = shape.y; + var dx = width / 3 * 2; + ctx.moveTo(x, y); + ctx.lineTo(x + dx, y + height); + ctx.lineTo(x, y + height / 4 * 3); + ctx.lineTo(x - dx, y + height); + ctx.lineTo(x, y); + ctx.closePath(); + } +}); + +/** + * Map of path contructors + * @type {Object.} + */ +var symbolCtors = { + + line: Line, + + rect: Rect, + + roundRect: Rect, + + square: Rect, + + circle: Circle, + + diamond: Diamond, + + pin: Pin, + + arrow: Arrow, + + triangle: Triangle +}; + +var symbolShapeMakers = { + + line: function (x, y, w, h, shape) { + // FIXME + shape.x1 = x; + shape.y1 = y + h / 2; + shape.x2 = x + w; + shape.y2 = y + h / 2; + }, + + rect: function (x, y, w, h, shape) { + shape.x = x; + shape.y = y; + shape.width = w; + shape.height = h; + }, + + roundRect: function (x, y, w, h, shape) { + shape.x = x; + shape.y = y; + shape.width = w; + shape.height = h; + shape.r = Math.min(w, h) / 4; + }, + + square: function (x, y, w, h, shape) { + var size = Math.min(w, h); + shape.x = x; + shape.y = y; + shape.width = size; + shape.height = size; + }, + + circle: function (x, y, w, h, shape) { + // Put circle in the center of square + shape.cx = x + w / 2; + shape.cy = y + h / 2; + shape.r = Math.min(w, h) / 2; + }, + + diamond: function (x, y, w, h, shape) { + shape.cx = x + w / 2; + shape.cy = y + h / 2; + shape.width = w; + shape.height = h; + }, + + pin: function (x, y, w, h, shape) { + shape.x = x + w / 2; + shape.y = y + h / 2; + shape.width = w; + shape.height = h; + }, + + arrow: function (x, y, w, h, shape) { + shape.x = x + w / 2; + shape.y = y + h / 2; + shape.width = w; + shape.height = h; + }, + + triangle: function (x, y, w, h, shape) { + shape.cx = x + w / 2; + shape.cy = y + h / 2; + shape.width = w; + shape.height = h; + } +}; + +var symbolBuildProxies = {}; +each$1(symbolCtors, function (Ctor, name) { + symbolBuildProxies[name] = new Ctor(); +}); + +var SymbolClz = extendShape({ + + type: 'symbol', + + shape: { + symbolType: '', + x: 0, + y: 0, + width: 0, + height: 0 + }, + + beforeBrush: function () { + var style = this.style; + var shape = this.shape; + // FIXME + if (shape.symbolType === 'pin' && style.textPosition === 'inside') { + style.textPosition = ['50%', '40%']; + style.textAlign = 'center'; + style.textVerticalAlign = 'middle'; + } + }, + + buildPath: function (ctx, shape, inBundle) { + var symbolType = shape.symbolType; + var proxySymbol = symbolBuildProxies[symbolType]; + if (shape.symbolType !== 'none') { + if (!proxySymbol) { + // Default rect + symbolType = 'rect'; + proxySymbol = symbolBuildProxies[symbolType]; + } + symbolShapeMakers[symbolType]( + shape.x, shape.y, shape.width, shape.height, proxySymbol.shape + ); + proxySymbol.buildPath(ctx, proxySymbol.shape, inBundle); + } + } +}); + +// Provide setColor helper method to avoid determine if set the fill or stroke outside +function symbolPathSetColor(color, innerColor) { + if (this.type !== 'image') { + var symbolStyle = this.style; + var symbolShape = this.shape; + if (symbolShape && symbolShape.symbolType === 'line') { + symbolStyle.stroke = color; + } + else if (this.__isEmptyBrush) { + symbolStyle.stroke = color; + symbolStyle.fill = innerColor || '#fff'; + } + else { + // FIXME 判断图形默认是填充还是描边,使用 onlyStroke ? + symbolStyle.fill && (symbolStyle.fill = color); + symbolStyle.stroke && (symbolStyle.stroke = color); + } + this.dirty(false); + } +} + +/** + * Create a symbol element with given symbol configuration: shape, x, y, width, height, color + * @param {string} symbolType + * @param {number} x + * @param {number} y + * @param {number} w + * @param {number} h + * @param {string} color + * @param {boolean} [keepAspect=false] whether to keep the ratio of w/h, + * for path and image only. + */ +function createSymbol(symbolType, x, y, w, h, color, keepAspect) { + // TODO Support image object, DynamicImage. + + var isEmpty = symbolType.indexOf('empty') === 0; + if (isEmpty) { + symbolType = symbolType.substr(5, 1).toLowerCase() + symbolType.substr(6); + } + var symbolPath; + + if (symbolType.indexOf('image://') === 0) { + symbolPath = makeImage( + symbolType.slice(8), + new BoundingRect(x, y, w, h), + keepAspect ? 'center' : 'cover' + ); + } + else if (symbolType.indexOf('path://') === 0) { + symbolPath = makePath( + symbolType.slice(7), + {}, + new BoundingRect(x, y, w, h), + keepAspect ? 'center' : 'cover' + ); + } + else { + symbolPath = new SymbolClz({ + shape: { + symbolType: symbolType, + x: x, + y: y, + width: w, + height: h + } + }); + } + + symbolPath.__isEmptyBrush = isEmpty; + + symbolPath.setColor = symbolPathSetColor; + + symbolPath.setColor(color); + + return symbolPath; +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +// import createGraphFromNodeEdge from './chart/helper/createGraphFromNodeEdge'; +/** + * Create a muti dimension List structure from seriesModel. + * @param {module:echarts/model/Model} seriesModel + * @return {module:echarts/data/List} list + */ +function createList(seriesModel) { + return createListFromArray(seriesModel.getSource(), seriesModel); +} + +var dataStack$1 = { + isDimensionStacked: isDimensionStacked, + enableDataStack: enableDataStack, + getStackedDimension: getStackedDimension +}; + +/** + * Create scale + * @param {Array.} dataExtent + * @param {Object|module:echarts/Model} option + */ +function createScale(dataExtent, option) { + var axisModel = option; + if (!Model.isInstance(option)) { + axisModel = new Model(option); + mixin(axisModel, axisModelCommonMixin); + } + + var scale = createScaleByModel(axisModel); + scale.setExtent(dataExtent[0], dataExtent[1]); + + niceScaleExtent(scale, axisModel); + return scale; +} + +/** + * Mixin common methods to axis model, + * + * Inlcude methods + * `getFormattedLabels() => Array.` + * `getCategories() => Array.` + * `getMin(origin: boolean) => number` + * `getMax(origin: boolean) => number` + * `getNeedCrossZero() => boolean` + * `setRange(start: number, end: number)` + * `resetRange()` + */ +function mixinAxisModelCommonMethods(Model$$1) { + mixin(Model$$1, axisModelCommonMixin); +} + +var helper = (Object.freeze || Object)({ + createList: createList, + getLayoutRect: getLayoutRect, + dataStack: dataStack$1, + createScale: createScale, + mixinAxisModelCommonMethods: mixinAxisModelCommonMethods, + completeDimensions: completeDimensions, + createDimensions: createDimensions, + createSymbol: createSymbol +}); + +var EPSILON$3 = 1e-8; + +function isAroundEqual$1(a, b) { + return Math.abs(a - b) < EPSILON$3; +} + +function contain$1(points, x, y) { + var w = 0; + var p = points[0]; + + if (!p) { + return false; + } + + for (var i = 1; i < points.length; i++) { + var p2 = points[i]; + w += windingLine(p[0], p[1], p2[0], p2[1], x, y); + p = p2; + } + + // Close polygon + var p0 = points[0]; + if (!isAroundEqual$1(p[0], p0[0]) || !isAroundEqual$1(p[1], p0[1])) { + w += windingLine(p[0], p[1], p0[0], p0[1], x, y); + } + + return w !== 0; +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/** + * @module echarts/coord/geo/Region + */ + +/** + * @param {string|Region} name + * @param {Array} geometries + * @param {Array.} cp + */ +function Region(name, geometries, cp) { + + /** + * @type {string} + * @readOnly + */ + this.name = name; + + /** + * @type {Array.} + * @readOnly + */ + this.geometries = geometries; + + if (!cp) { + var rect = this.getBoundingRect(); + cp = [ + rect.x + rect.width / 2, + rect.y + rect.height / 2 + ]; + } + else { + cp = [cp[0], cp[1]]; + } + /** + * @type {Array.} + */ + this.center = cp; +} + +Region.prototype = { + + constructor: Region, + + properties: null, + + /** + * @return {module:zrender/core/BoundingRect} + */ + getBoundingRect: function () { + var rect = this._rect; + if (rect) { + return rect; + } + + var MAX_NUMBER = Number.MAX_VALUE; + var min$$1 = [MAX_NUMBER, MAX_NUMBER]; + var max$$1 = [-MAX_NUMBER, -MAX_NUMBER]; + var min2 = []; + var max2 = []; + var geometries = this.geometries; + for (var i = 0; i < geometries.length; i++) { + // Only support polygon + if (geometries[i].type !== 'polygon') { + continue; + } + // Doesn't consider hole + var exterior = geometries[i].exterior; + fromPoints(exterior, min2, max2); + min(min$$1, min$$1, min2); + max(max$$1, max$$1, max2); + } + // No data + if (i === 0) { + min$$1[0] = min$$1[1] = max$$1[0] = max$$1[1] = 0; + } + + return (this._rect = new BoundingRect( + min$$1[0], min$$1[1], max$$1[0] - min$$1[0], max$$1[1] - min$$1[1] + )); + }, + + /** + * @param {} coord + * @return {boolean} + */ + contain: function (coord) { + var rect = this.getBoundingRect(); + var geometries = this.geometries; + if (!rect.contain(coord[0], coord[1])) { + return false; + } + loopGeo: for (var i = 0, len$$1 = geometries.length; i < len$$1; i++) { + // Only support polygon. + if (geometries[i].type !== 'polygon') { + continue; + } + var exterior = geometries[i].exterior; + var interiors = geometries[i].interiors; + if (contain$1(exterior, coord[0], coord[1])) { + // Not in the region if point is in the hole. + for (var k = 0; k < (interiors ? interiors.length : 0); k++) { + if (contain$1(interiors[k])) { + continue loopGeo; + } + } + return true; + } + } + return false; + }, + + transformTo: function (x, y, width, height) { + var rect = this.getBoundingRect(); + var aspect = rect.width / rect.height; + if (!width) { + width = aspect * height; + } + else if (!height) { + height = width / aspect; + } + var target = new BoundingRect(x, y, width, height); + var transform = rect.calculateTransform(target); + var geometries = this.geometries; + for (var i = 0; i < geometries.length; i++) { + // Only support polygon. + if (geometries[i].type !== 'polygon') { + continue; + } + var exterior = geometries[i].exterior; + var interiors = geometries[i].interiors; + for (var p = 0; p < exterior.length; p++) { + applyTransform(exterior[p], exterior[p], transform); + } + for (var h = 0; h < (interiors ? interiors.length : 0); h++) { + for (var p = 0; p < interiors[h].length; p++) { + applyTransform(interiors[h][p], interiors[h][p], transform); + } + } + } + rect = this._rect; + rect.copy(target); + // Update center + this.center = [ + rect.x + rect.width / 2, + rect.y + rect.height / 2 + ]; + }, + + cloneShallow: function (name) { + name == null && (name = this.name); + var newRegion = new Region(name, this.geometries, this.center); + newRegion._rect = this._rect; + newRegion.transformTo = null; // Simply avoid to be called. + return newRegion; + } +}; + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/** + * Parse and decode geo json + * @module echarts/coord/geo/parseGeoJson + */ + +function decode(json) { + if (!json.UTF8Encoding) { + return json; + } + var encodeScale = json.UTF8Scale; + if (encodeScale == null) { + encodeScale = 1024; + } + + var features = json.features; + + for (var f = 0; f < features.length; f++) { + var feature = features[f]; + var geometry = feature.geometry; + var coordinates = geometry.coordinates; + var encodeOffsets = geometry.encodeOffsets; + + for (var c = 0; c < coordinates.length; c++) { + var coordinate = coordinates[c]; + + if (geometry.type === 'Polygon') { + coordinates[c] = decodePolygon( + coordinate, + encodeOffsets[c], + encodeScale + ); + } + else if (geometry.type === 'MultiPolygon') { + for (var c2 = 0; c2 < coordinate.length; c2++) { + var polygon = coordinate[c2]; + coordinate[c2] = decodePolygon( + polygon, + encodeOffsets[c][c2], + encodeScale + ); + } + } + } + } + // Has been decoded + json.UTF8Encoding = false; + return json; +} + +function decodePolygon(coordinate, encodeOffsets, encodeScale) { + var result = []; + var prevX = encodeOffsets[0]; + var prevY = encodeOffsets[1]; + + for (var i = 0; i < coordinate.length; i += 2) { + var x = coordinate.charCodeAt(i) - 64; + var y = coordinate.charCodeAt(i + 1) - 64; + // ZigZag decoding + x = (x >> 1) ^ (-(x & 1)); + y = (y >> 1) ^ (-(y & 1)); + // Delta deocding + x += prevX; + y += prevY; + + prevX = x; + prevY = y; + // Dequantize + result.push([x / encodeScale, y / encodeScale]); + } + + return result; +} + +/** + * @alias module:echarts/coord/geo/parseGeoJson + * @param {Object} geoJson + * @return {module:zrender/container/Group} + */ +var parseGeoJson$1 = function (geoJson) { + + decode(geoJson); + + return map(filter(geoJson.features, function (featureObj) { + // Output of mapshaper may have geometry null + return featureObj.geometry + && featureObj.properties + && featureObj.geometry.coordinates.length > 0; + }), function (featureObj) { + var properties = featureObj.properties; + var geo = featureObj.geometry; + + var coordinates = geo.coordinates; + + var geometries = []; + if (geo.type === 'Polygon') { + geometries.push({ + type: 'polygon', + // According to the GeoJSON specification. + // First must be exterior, and the rest are all interior(holes). + exterior: coordinates[0], + interiors: coordinates.slice(1) + }); + } + if (geo.type === 'MultiPolygon') { + each$1(coordinates, function (item) { + if (item[0]) { + geometries.push({ + type: 'polygon', + exterior: item[0], + interiors: item.slice(1) + }); + } + }); + } + + var region = new Region( + properties.name, + geometries, + properties.cp + ); + region.properties = properties; + return region; + }); +}; + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var inner$6 = makeInner(); + +/** + * @param {module:echats/coord/Axis} axis + * @return {Object} { + * labels: [{ + * formattedLabel: string, + * rawLabel: string, + * tickValue: number + * }, ...], + * labelCategoryInterval: number + * } + */ +function createAxisLabels(axis) { + // Only ordinal scale support tick interval + return axis.type === 'category' + ? makeCategoryLabels(axis) + : makeRealNumberLabels(axis); +} + +/** + * @param {module:echats/coord/Axis} axis + * @param {module:echarts/model/Model} tickModel For example, can be axisTick, splitLine, splitArea. + * @return {Object} { + * ticks: Array. + * tickCategoryInterval: number + * } + */ +function createAxisTicks(axis, tickModel) { + // Only ordinal scale support tick interval + return axis.type === 'category' + ? makeCategoryTicks(axis, tickModel) + : {ticks: axis.scale.getTicks()}; +} + +function makeCategoryLabels(axis) { + var labelModel = axis.getLabelModel(); + var result = makeCategoryLabelsActually(axis, labelModel); + + return (!labelModel.get('show') || axis.scale.isBlank()) + ? {labels: [], labelCategoryInterval: result.labelCategoryInterval} + : result; +} + +function makeCategoryLabelsActually(axis, labelModel) { + var labelsCache = getListCache(axis, 'labels'); + var optionLabelInterval = getOptionCategoryInterval(labelModel); + var result = listCacheGet(labelsCache, optionLabelInterval); + + if (result) { + return result; + } + + var labels; + var numericLabelInterval; + + if (isFunction$1(optionLabelInterval)) { + labels = makeLabelsByCustomizedCategoryInterval(axis, optionLabelInterval); + } + else { + numericLabelInterval = optionLabelInterval === 'auto' + ? makeAutoCategoryInterval(axis) : optionLabelInterval; + labels = makeLabelsByNumericCategoryInterval(axis, numericLabelInterval); + } + + // Cache to avoid calling interval function repeatly. + return listCacheSet(labelsCache, optionLabelInterval, { + labels: labels, labelCategoryInterval: numericLabelInterval + }); +} + +function makeCategoryTicks(axis, tickModel) { + var ticksCache = getListCache(axis, 'ticks'); + var optionTickInterval = getOptionCategoryInterval(tickModel); + var result = listCacheGet(ticksCache, optionTickInterval); + + if (result) { + return result; + } + + var ticks; + var tickCategoryInterval; + + // Optimize for the case that large category data and no label displayed, + // we should not return all ticks. + if (!tickModel.get('show') || axis.scale.isBlank()) { + ticks = []; + } + + if (isFunction$1(optionTickInterval)) { + ticks = makeLabelsByCustomizedCategoryInterval(axis, optionTickInterval, true); + } + // Always use label interval by default despite label show. Consider this + // scenario, Use multiple grid with the xAxis sync, and only one xAxis shows + // labels. `splitLine` and `axisTick` should be consistent in this case. + else if (optionTickInterval === 'auto') { + var labelsResult = makeCategoryLabelsActually(axis, axis.getLabelModel()); + tickCategoryInterval = labelsResult.labelCategoryInterval; + ticks = map(labelsResult.labels, function (labelItem) { + return labelItem.tickValue; + }); + } + else { + tickCategoryInterval = optionTickInterval; + ticks = makeLabelsByNumericCategoryInterval(axis, tickCategoryInterval, true); + } + + // Cache to avoid calling interval function repeatly. + return listCacheSet(ticksCache, optionTickInterval, { + ticks: ticks, tickCategoryInterval: tickCategoryInterval + }); +} + +function makeRealNumberLabels(axis) { + var ticks = axis.scale.getTicks(); + var labelFormatter = makeLabelFormatter(axis); + return { + labels: map(ticks, function (tickValue, idx) { + return { + formattedLabel: labelFormatter(tickValue, idx), + rawLabel: axis.scale.getLabel(tickValue), + tickValue: tickValue + }; + }) + }; +} + +// Large category data calculation is performence sensitive, and ticks and label +// probably be fetched by multiple times. So we cache the result. +// axis is created each time during a ec process, so we do not need to clear cache. +function getListCache(axis, prop) { + // Because key can be funciton, and cache size always be small, we use array cache. + return inner$6(axis)[prop] || (inner$6(axis)[prop] = []); +} + +function listCacheGet(cache, key) { + for (var i = 0; i < cache.length; i++) { + if (cache[i].key === key) { + return cache[i].value; + } + } +} + +function listCacheSet(cache, key, value) { + cache.push({key: key, value: value}); + return value; +} + +function makeAutoCategoryInterval(axis) { + var result = inner$6(axis).autoInterval; + return result != null + ? result + : (inner$6(axis).autoInterval = axis.calculateCategoryInterval()); +} + +/** + * Calculate interval for category axis ticks and labels. + * To get precise result, at least one of `getRotate` and `isHorizontal` + * should be implemented in axis. + */ +function calculateCategoryInterval(axis) { + var params = fetchAutoCategoryIntervalCalculationParams(axis); + var labelFormatter = makeLabelFormatter(axis); + var rotation = (params.axisRotate - params.labelRotate) / 180 * Math.PI; + + var ordinalScale = axis.scale; + var ordinalExtent = ordinalScale.getExtent(); + // Providing this method is for optimization: + // avoid generating a long array by `getTicks` + // in large category data case. + var tickCount = ordinalScale.count(); + + if (ordinalExtent[1] - ordinalExtent[0] < 1) { + return 0; + } + + var step = 1; + // Simple optimization. Empirical value: tick count should less than 40. + if (tickCount > 40) { + step = Math.max(1, Math.floor(tickCount / 40)); + } + var tickValue = ordinalExtent[0]; + var unitSpan = axis.dataToCoord(tickValue + 1) - axis.dataToCoord(tickValue); + var unitW = Math.abs(unitSpan * Math.cos(rotation)); + var unitH = Math.abs(unitSpan * Math.sin(rotation)); + + var maxW = 0; + var maxH = 0; + + // Caution: Performance sensitive for large category data. + // Consider dataZoom, we should make appropriate step to avoid O(n) loop. + for (; tickValue <= ordinalExtent[1]; tickValue += step) { + var width = 0; + var height = 0; + + // Not precise, do not consider align and vertical align + // and each distance from axis line yet. + var rect = getBoundingRect( + labelFormatter(tickValue), params.font, 'center', 'top' + ); + // Magic number + width = rect.width * 1.3; + height = rect.height * 1.3; + + // Min size, void long loop. + maxW = Math.max(maxW, width, 7); + maxH = Math.max(maxH, height, 7); + } + + var dw = maxW / unitW; + var dh = maxH / unitH; + // 0/0 is NaN, 1/0 is Infinity. + isNaN(dw) && (dw = Infinity); + isNaN(dh) && (dh = Infinity); + var interval = Math.max(0, Math.floor(Math.min(dw, dh))); + + var cache = inner$6(axis.model); + var lastAutoInterval = cache.lastAutoInterval; + var lastTickCount = cache.lastTickCount; + + // Use cache to keep interval stable while moving zoom window, + // otherwise the calculated interval might jitter when the zoom + // window size is close to the interval-changing size. + if (lastAutoInterval != null + && lastTickCount != null + && Math.abs(lastAutoInterval - interval) <= 1 + && Math.abs(lastTickCount - tickCount) <= 1 + // Always choose the bigger one, otherwise the critical + // point is not the same when zooming in or zooming out. + && lastAutoInterval > interval + ) { + interval = lastAutoInterval; + } + // Only update cache if cache not used, otherwise the + // changing of interval is too insensitive. + else { + cache.lastTickCount = tickCount; + cache.lastAutoInterval = interval; + } + + return interval; +} + +function fetchAutoCategoryIntervalCalculationParams(axis) { + var labelModel = axis.getLabelModel(); + return { + axisRotate: axis.getRotate + ? axis.getRotate() + : (axis.isHorizontal && !axis.isHorizontal()) + ? 90 + : 0, + labelRotate: labelModel.get('rotate') || 0, + font: labelModel.getFont() + }; +} + +function makeLabelsByNumericCategoryInterval(axis, categoryInterval, onlyTick) { + var labelFormatter = makeLabelFormatter(axis); + var ordinalScale = axis.scale; + var ordinalExtent = ordinalScale.getExtent(); + var labelModel = axis.getLabelModel(); + var result = []; + + // TODO: axisType: ordinalTime, pick the tick from each month/day/year/... + + var step = Math.max((categoryInterval || 0) + 1, 1); + var startTick = ordinalExtent[0]; + var tickCount = ordinalScale.count(); + + // Calculate start tick based on zero if possible to keep label consistent + // while zooming and moving while interval > 0. Otherwise the selection + // of displayable ticks and symbols probably keep changing. + // 3 is empirical value. + if (startTick !== 0 && step > 1 && tickCount / step > 2) { + startTick = Math.round(Math.ceil(startTick / step) * step); + } + + // (1) Only add min max label here but leave overlap checking + // to render stage, which also ensure the returned list + // suitable for splitLine and splitArea rendering. + // (2) Scales except category always contain min max label so + // do not need to perform this process. + var showAllLabel = shouldShowAllLabels(axis); + var includeMinLabel = labelModel.get('showMinLabel') || showAllLabel; + var includeMaxLabel = labelModel.get('showMaxLabel') || showAllLabel; + + if (includeMinLabel && startTick !== ordinalExtent[0]) { + addItem(ordinalExtent[0]); + } + + // Optimize: avoid generating large array by `ordinalScale.getTicks()`. + var tickValue = startTick; + for (; tickValue <= ordinalExtent[1]; tickValue += step) { + addItem(tickValue); + } + + if (includeMaxLabel && tickValue !== ordinalExtent[1]) { + addItem(ordinalExtent[1]); + } + + function addItem(tVal) { + result.push(onlyTick + ? tVal + : { + formattedLabel: labelFormatter(tVal), + rawLabel: ordinalScale.getLabel(tVal), + tickValue: tVal + } + ); + } + + return result; +} + +// When interval is function, the result `false` means ignore the tick. +// It is time consuming for large category data. +function makeLabelsByCustomizedCategoryInterval(axis, categoryInterval, onlyTick) { + var ordinalScale = axis.scale; + var labelFormatter = makeLabelFormatter(axis); + var result = []; + + each$1(ordinalScale.getTicks(), function (tickValue) { + var rawLabel = ordinalScale.getLabel(tickValue); + if (categoryInterval(tickValue, rawLabel)) { + result.push(onlyTick + ? tickValue + : { + formattedLabel: labelFormatter(tickValue), + rawLabel: rawLabel, + tickValue: tickValue + } + ); + } + }); + + return result; +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var NORMALIZED_EXTENT = [0, 1]; + +/** + * Base class of Axis. + * @constructor + */ +var Axis = function (dim, scale, extent) { + + /** + * Axis dimension. Such as 'x', 'y', 'z', 'angle', 'radius'. + * @type {string} + */ + this.dim = dim; + + /** + * Axis scale + * @type {module:echarts/coord/scale/*} + */ + this.scale = scale; + + /** + * @type {Array.} + * @private + */ + this._extent = extent || [0, 0]; + + /** + * @type {boolean} + */ + this.inverse = false; + + /** + * Usually true when axis has a ordinal scale + * @type {boolean} + */ + this.onBand = false; +}; + +Axis.prototype = { + + constructor: Axis, + + /** + * If axis extent contain given coord + * @param {number} coord + * @return {boolean} + */ + contain: function (coord) { + var extent = this._extent; + var min = Math.min(extent[0], extent[1]); + var max = Math.max(extent[0], extent[1]); + return coord >= min && coord <= max; + }, + + /** + * If axis extent contain given data + * @param {number} data + * @return {boolean} + */ + containData: function (data) { + return this.contain(this.dataToCoord(data)); + }, + + /** + * Get coord extent. + * @return {Array.} + */ + getExtent: function () { + return this._extent.slice(); + }, + + /** + * Get precision used for formatting + * @param {Array.} [dataExtent] + * @return {number} + */ + getPixelPrecision: function (dataExtent) { + return getPixelPrecision( + dataExtent || this.scale.getExtent(), + this._extent + ); + }, + + /** + * Set coord extent + * @param {number} start + * @param {number} end + */ + setExtent: function (start, end) { + var extent = this._extent; + extent[0] = start; + extent[1] = end; + }, + + /** + * Convert data to coord. Data is the rank if it has an ordinal scale + * @param {number} data + * @param {boolean} clamp + * @return {number} + */ + dataToCoord: function (data, clamp) { + var extent = this._extent; + var scale = this.scale; + data = scale.normalize(data); + + if (this.onBand && scale.type === 'ordinal') { + extent = extent.slice(); + fixExtentWithBands(extent, scale.count()); + } + + return linearMap(data, NORMALIZED_EXTENT, extent, clamp); + }, + + /** + * Convert coord to data. Data is the rank if it has an ordinal scale + * @param {number} coord + * @param {boolean} clamp + * @return {number} + */ + coordToData: function (coord, clamp) { + var extent = this._extent; + var scale = this.scale; + + if (this.onBand && scale.type === 'ordinal') { + extent = extent.slice(); + fixExtentWithBands(extent, scale.count()); + } + + var t = linearMap(coord, extent, NORMALIZED_EXTENT, clamp); + + return this.scale.scale(t); + }, + + /** + * Convert pixel point to data in axis + * @param {Array.} point + * @param {boolean} clamp + * @return {number} data + */ + pointToData: function (point, clamp) { + // Should be implemented in derived class if necessary. + }, + + /** + * Different from `zrUtil.map(axis.getTicks(), axis.dataToCoord, axis)`, + * `axis.getTicksCoords` considers `onBand`, which is used by + * `boundaryGap:true` of category axis and splitLine and splitArea. + * @param {Object} [opt] + * @param {number} [opt.tickModel=axis.model.getModel('axisTick')] + * @param {boolean} [opt.clamp] If `true`, the first and the last + * tick must be at the axis end points. Otherwise, clip ticks + * that outside the axis extent. + * @return {Array.} [{ + * coord: ..., + * tickValue: ... + * }, ...] + */ + getTicksCoords: function (opt) { + opt = opt || {}; + + var tickModel = opt.tickModel || this.getTickModel(); + + var result = createAxisTicks(this, tickModel); + var ticks = result.ticks; + + var ticksCoords = map(ticks, function (tickValue) { + return { + coord: this.dataToCoord(tickValue), + tickValue: tickValue + }; + }, this); + + var alignWithLabel = tickModel.get('alignWithLabel'); + fixOnBandTicksCoords( + this, ticksCoords, result.tickCategoryInterval, alignWithLabel, opt.clamp + ); + + return ticksCoords; + }, + + /** + * @return {Array.} [{ + * formattedLabel: string, + * rawLabel: axis.scale.getLabel(tickValue) + * tickValue: number + * }, ...] + */ + getViewLabels: function () { + return createAxisLabels(this).labels; + }, + + /** + * @return {module:echarts/coord/model/Model} + */ + getLabelModel: function () { + return this.model.getModel('axisLabel'); + }, + + /** + * Notice here we only get the default tick model. For splitLine + * or splitArea, we should pass the splitLineModel or splitAreaModel + * manually when calling `getTicksCoords`. + * In GL, this method may be overrided to: + * `axisModel.getModel('axisTick', grid3DModel.getModel('axisTick'));` + * @return {module:echarts/coord/model/Model} + */ + getTickModel: function () { + return this.model.getModel('axisTick'); + }, + + /** + * Get width of band + * @return {number} + */ + getBandWidth: function () { + var axisExtent = this._extent; + var dataExtent = this.scale.getExtent(); + + var len = dataExtent[1] - dataExtent[0] + (this.onBand ? 1 : 0); + // Fix #2728, avoid NaN when only one data. + len === 0 && (len = 1); + + var size = Math.abs(axisExtent[1] - axisExtent[0]); + + return Math.abs(size) / len; + }, + + /** + * @abstract + * @return {boolean} Is horizontal + */ + isHorizontal: null, + + /** + * @abstract + * @return {number} Get axis rotate, by degree. + */ + getRotate: null, + + /** + * Only be called in category axis. + * Can be overrided, consider other axes like in 3D. + * @return {number} Auto interval for cateogry axis tick and label + */ + calculateCategoryInterval: function () { + return calculateCategoryInterval(this); + } + +}; + +function fixExtentWithBands(extent, nTick) { + var size = extent[1] - extent[0]; + var len = nTick; + var margin = size / len / 2; + extent[0] += margin; + extent[1] -= margin; +} + +// If axis has labels [1, 2, 3, 4]. Bands on the axis are +// |---1---|---2---|---3---|---4---|. +// So the displayed ticks and splitLine/splitArea should between +// each data item, otherwise cause misleading (e.g., split tow bars +// of a single data item when there are two bar series). +// Also consider if tickCategoryInterval > 0 and onBand, ticks and +// splitLine/spliteArea should layout appropriately corresponding +// to displayed labels. (So we should not use `getBandWidth` in this +// case). +function fixOnBandTicksCoords(axis, ticksCoords, tickCategoryInterval, alignWithLabel, clamp) { + var ticksLen = ticksCoords.length; + + if (!axis.onBand || alignWithLabel || !ticksLen) { + return; + } + + var axisExtent = axis.getExtent(); + var last; + if (ticksLen === 1) { + ticksCoords[0].coord = axisExtent[0]; + last = ticksCoords[1] = {coord: axisExtent[0]}; + } + else { + var shift = (ticksCoords[1].coord - ticksCoords[0].coord); + each$1(ticksCoords, function (ticksItem) { + ticksItem.coord -= shift / 2; + var tickCategoryInterval = tickCategoryInterval || 0; + // Avoid split a single data item when odd interval. + if (tickCategoryInterval % 2 > 0) { + ticksItem.coord -= shift / ((tickCategoryInterval + 1) * 2); + } + }); + last = {coord: ticksCoords[ticksLen - 1].coord + shift}; + ticksCoords.push(last); + } + + var inverse = axisExtent[0] > axisExtent[1]; + + if (littleThan(ticksCoords[0].coord, axisExtent[0])) { + clamp ? (ticksCoords[0].coord = axisExtent[0]) : ticksCoords.shift(); + } + if (clamp && littleThan(axisExtent[0], ticksCoords[0].coord)) { + ticksCoords.unshift({coord: axisExtent[0]}); + } + if (littleThan(axisExtent[1], last.coord)) { + clamp ? (last.coord = axisExtent[1]) : ticksCoords.pop(); + } + if (clamp && littleThan(last.coord, axisExtent[1])) { + ticksCoords.push({coord: axisExtent[1]}); + } + + function littleThan(a, b) { + return inverse ? a > b : a < b; + } +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/** + * Do not mount those modules on 'src/echarts' for better tree shaking. + */ + +var parseGeoJson = parseGeoJson$1; + +var ecUtil = {}; +each$1( + [ + 'map', 'each', 'filter', 'indexOf', 'inherits', 'reduce', 'filter', + 'bind', 'curry', 'isArray', 'isString', 'isObject', 'isFunction', + 'extend', 'defaults', 'clone', 'merge' + ], + function (name) { + ecUtil[name] = zrUtil[name]; + } +); +var graphic$1 = {}; +each$1( + [ + 'extendShape', 'extendPath', 'makePath', 'makeImage', + 'mergePath', 'resizePath', 'createIcon', + 'setHoverStyle', 'setLabelStyle', 'setTextStyle', 'setText', + 'getFont', 'updateProps', 'initProps', 'getTransform', + 'clipPointsByRect', 'clipRectByRect', + 'Group', + 'Image', + 'Text', + 'Circle', + 'Sector', + 'Ring', + 'Polygon', + 'Polyline', + 'Rect', + 'Line', + 'BezierCurve', + 'Arc', + 'IncrementalDisplayable', + 'CompoundPath', + 'LinearGradient', + 'RadialGradient', + 'BoundingRect' + ], + function (name) { + graphic$1[name] = graphic[name]; + } +); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +SeriesModel.extend({ + + type: 'series.line', + + dependencies: ['grid', 'polar'], + + getInitialData: function (option, ecModel) { + if (__DEV__) { + var coordSys = option.coordinateSystem; + if (coordSys !== 'polar' && coordSys !== 'cartesian2d') { + throw new Error('Line not support coordinateSystem besides cartesian and polar'); + } + } + return createListFromArray(this.getSource(), this); + }, + + defaultOption: { + zlevel: 0, + z: 2, + coordinateSystem: 'cartesian2d', + legendHoverLink: true, + + hoverAnimation: true, + // stack: null + // xAxisIndex: 0, + // yAxisIndex: 0, + + // polarIndex: 0, + + // If clip the overflow value + clipOverflow: true, + // cursor: null, + + label: { + position: 'top' + }, + // itemStyle: { + // }, + + lineStyle: { + width: 2, + type: 'solid' + }, + // areaStyle: { + // origin of areaStyle. Valid values: + // `'auto'/null/undefined`: from axisLine to data + // `'start'`: from min to data + // `'end'`: from data to max + // origin: 'auto' + // }, + // false, 'start', 'end', 'middle' + step: false, + + // Disabled if step is true + smooth: false, + smoothMonotone: null, + symbol: 'emptyCircle', + symbolSize: 4, + symbolRotate: null, + + showSymbol: true, + // `false`: follow the label interval strategy. + // `true`: show all symbols. + // `'auto'`: If possible, show all symbols, otherwise + // follow the label interval strategy. + showAllSymbol: 'auto', + + // Whether to connect break point. + connectNulls: false, + + // Sampling for large data. Can be: 'average', 'max', 'min', 'sum'. + sampling: 'none', + + animationEasing: 'linear', + + // Disable progressive + progressive: 0, + hoverLayerThreshold: Infinity + } +}); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/** + * @param {module:echarts/data/List} data + * @param {number} dataIndex + * @return {string} label string. Not null/undefined + */ +function getDefaultLabel(data, dataIndex) { + var labelDims = data.mapDimension('defaultedLabel', true); + var len = labelDims.length; + + // Simple optimization (in lots of cases, label dims length is 1) + if (len === 1) { + return retrieveRawValue(data, dataIndex, labelDims[0]); + } + else if (len) { + var vals = []; + for (var i = 0; i < labelDims.length; i++) { + var val = retrieveRawValue(data, dataIndex, labelDims[i]); + vals.push(val); + } + return vals.join(' '); + } +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/** + * @module echarts/chart/helper/Symbol + */ + +/** + * @constructor + * @alias {module:echarts/chart/helper/Symbol} + * @param {module:echarts/data/List} data + * @param {number} idx + * @extends {module:zrender/graphic/Group} + */ +function SymbolClz$1(data, idx, seriesScope) { + Group.call(this); + this.updateData(data, idx, seriesScope); +} + +var symbolProto = SymbolClz$1.prototype; + +/** + * @public + * @static + * @param {module:echarts/data/List} data + * @param {number} dataIndex + * @return {Array.} [width, height] + */ +var getSymbolSize = SymbolClz$1.getSymbolSize = function (data, idx) { + var symbolSize = data.getItemVisual(idx, 'symbolSize'); + return symbolSize instanceof Array + ? symbolSize.slice() + : [+symbolSize, +symbolSize]; +}; + +function getScale(symbolSize) { + return [symbolSize[0] / 2, symbolSize[1] / 2]; +} + +function driftSymbol(dx, dy) { + this.parent.drift(dx, dy); +} + +symbolProto._createSymbol = function ( + symbolType, + data, + idx, + symbolSize, + keepAspect +) { + // Remove paths created before + this.removeAll(); + + var color = data.getItemVisual(idx, 'color'); + + // var symbolPath = createSymbol( + // symbolType, -0.5, -0.5, 1, 1, color + // ); + // If width/height are set too small (e.g., set to 1) on ios10 + // and macOS Sierra, a circle stroke become a rect, no matter what + // the scale is set. So we set width/height as 2. See #4150. + var symbolPath = createSymbol( + symbolType, -1, -1, 2, 2, color, keepAspect + ); + + symbolPath.attr({ + z2: 100, + culling: true, + scale: getScale(symbolSize) + }); + // Rewrite drift method + symbolPath.drift = driftSymbol; + + this._symbolType = symbolType; + + this.add(symbolPath); +}; + +/** + * Stop animation + * @param {boolean} toLastFrame + */ +symbolProto.stopSymbolAnimation = function (toLastFrame) { + this.childAt(0).stopAnimation(toLastFrame); +}; + +/** + * FIXME: + * Caution: This method breaks the encapsulation of this module, + * but it indeed brings convenience. So do not use the method + * unless you detailedly know all the implements of `Symbol`, + * especially animation. + * + * Get symbol path element. + */ +symbolProto.getSymbolPath = function () { + return this.childAt(0); +}; + +/** + * Get scale(aka, current symbol size). + * Including the change caused by animation + */ +symbolProto.getScale = function () { + return this.childAt(0).scale; +}; + +/** + * Highlight symbol + */ +symbolProto.highlight = function () { + this.childAt(0).trigger('emphasis'); +}; + +/** + * Downplay symbol + */ +symbolProto.downplay = function () { + this.childAt(0).trigger('normal'); +}; + +/** + * @param {number} zlevel + * @param {number} z + */ +symbolProto.setZ = function (zlevel, z) { + var symbolPath = this.childAt(0); + symbolPath.zlevel = zlevel; + symbolPath.z = z; +}; + +symbolProto.setDraggable = function (draggable) { + var symbolPath = this.childAt(0); + symbolPath.draggable = draggable; + symbolPath.cursor = draggable ? 'move' : 'pointer'; +}; + +/** + * Update symbol properties + * @param {module:echarts/data/List} data + * @param {number} idx + * @param {Object} [seriesScope] + * @param {Object} [seriesScope.itemStyle] + * @param {Object} [seriesScope.hoverItemStyle] + * @param {Object} [seriesScope.symbolRotate] + * @param {Object} [seriesScope.symbolOffset] + * @param {module:echarts/model/Model} [seriesScope.labelModel] + * @param {module:echarts/model/Model} [seriesScope.hoverLabelModel] + * @param {boolean} [seriesScope.hoverAnimation] + * @param {Object} [seriesScope.cursorStyle] + * @param {module:echarts/model/Model} [seriesScope.itemModel] + * @param {string} [seriesScope.symbolInnerColor] + * @param {Object} [seriesScope.fadeIn=false] + */ +symbolProto.updateData = function (data, idx, seriesScope) { + this.silent = false; + + var symbolType = data.getItemVisual(idx, 'symbol') || 'circle'; + var seriesModel = data.hostModel; + var symbolSize = getSymbolSize(data, idx); + var isInit = symbolType !== this._symbolType; + + if (isInit) { + var keepAspect = data.getItemVisual(idx, 'symbolKeepAspect'); + this._createSymbol(symbolType, data, idx, symbolSize, keepAspect); + } + else { + var symbolPath = this.childAt(0); + symbolPath.silent = false; + updateProps(symbolPath, { + scale: getScale(symbolSize) + }, seriesModel, idx); + } + + this._updateCommon(data, idx, symbolSize, seriesScope); + + if (isInit) { + var symbolPath = this.childAt(0); + var fadeIn = seriesScope && seriesScope.fadeIn; + + var target = {scale: symbolPath.scale.slice()}; + fadeIn && (target.style = {opacity: symbolPath.style.opacity}); + + symbolPath.scale = [0, 0]; + fadeIn && (symbolPath.style.opacity = 0); + + initProps(symbolPath, target, seriesModel, idx); + } + + this._seriesModel = seriesModel; +}; + +// Update common properties +var normalStyleAccessPath = ['itemStyle']; +var emphasisStyleAccessPath = ['emphasis', 'itemStyle']; +var normalLabelAccessPath = ['label']; +var emphasisLabelAccessPath = ['emphasis', 'label']; + +/** + * @param {module:echarts/data/List} data + * @param {number} idx + * @param {Array.} symbolSize + * @param {Object} [seriesScope] + */ +symbolProto._updateCommon = function (data, idx, symbolSize, seriesScope) { + var symbolPath = this.childAt(0); + var seriesModel = data.hostModel; + var color = data.getItemVisual(idx, 'color'); + + // Reset style + if (symbolPath.type !== 'image') { + symbolPath.useStyle({ + strokeNoScale: true + }); + } + + var itemStyle = seriesScope && seriesScope.itemStyle; + var hoverItemStyle = seriesScope && seriesScope.hoverItemStyle; + var symbolRotate = seriesScope && seriesScope.symbolRotate; + var symbolOffset = seriesScope && seriesScope.symbolOffset; + var labelModel = seriesScope && seriesScope.labelModel; + var hoverLabelModel = seriesScope && seriesScope.hoverLabelModel; + var hoverAnimation = seriesScope && seriesScope.hoverAnimation; + var cursorStyle = seriesScope && seriesScope.cursorStyle; + + if (!seriesScope || data.hasItemOption) { + var itemModel = (seriesScope && seriesScope.itemModel) + ? seriesScope.itemModel : data.getItemModel(idx); + + // Color must be excluded. + // Because symbol provide setColor individually to set fill and stroke + itemStyle = itemModel.getModel(normalStyleAccessPath).getItemStyle(['color']); + hoverItemStyle = itemModel.getModel(emphasisStyleAccessPath).getItemStyle(); + + symbolRotate = itemModel.getShallow('symbolRotate'); + symbolOffset = itemModel.getShallow('symbolOffset'); + + labelModel = itemModel.getModel(normalLabelAccessPath); + hoverLabelModel = itemModel.getModel(emphasisLabelAccessPath); + hoverAnimation = itemModel.getShallow('hoverAnimation'); + cursorStyle = itemModel.getShallow('cursor'); + } + else { + hoverItemStyle = extend({}, hoverItemStyle); + } + + var elStyle = symbolPath.style; + + symbolPath.attr('rotation', (symbolRotate || 0) * Math.PI / 180 || 0); + + if (symbolOffset) { + symbolPath.attr('position', [ + parsePercent$1(symbolOffset[0], symbolSize[0]), + parsePercent$1(symbolOffset[1], symbolSize[1]) + ]); + } + + cursorStyle && symbolPath.attr('cursor', cursorStyle); + + // PENDING setColor before setStyle!!! + symbolPath.setColor(color, seriesScope && seriesScope.symbolInnerColor); + + symbolPath.setStyle(itemStyle); + + var opacity = data.getItemVisual(idx, 'opacity'); + if (opacity != null) { + elStyle.opacity = opacity; + } + + var liftZ = data.getItemVisual(idx, 'liftZ'); + var z2Origin = symbolPath.__z2Origin; + if (liftZ != null) { + if (z2Origin == null) { + symbolPath.__z2Origin = symbolPath.z2; + symbolPath.z2 += liftZ; + } + } + else if (z2Origin != null) { + symbolPath.z2 = z2Origin; + symbolPath.__z2Origin = null; + } + + var useNameLabel = seriesScope && seriesScope.useNameLabel; + + setLabelStyle( + elStyle, hoverItemStyle, labelModel, hoverLabelModel, + { + labelFetcher: seriesModel, + labelDataIndex: idx, + defaultText: getLabelDefaultText, + isRectText: true, + autoColor: color + } + ); + + // Do not execute util needed. + function getLabelDefaultText(idx, opt) { + return useNameLabel ? data.getName(idx) : getDefaultLabel(data, idx); + } + + symbolPath.off('mouseover') + .off('mouseout') + .off('emphasis') + .off('normal'); + + symbolPath.hoverStyle = hoverItemStyle; + + // FIXME + // Do not use symbol.trigger('emphasis'), but use symbol.highlight() instead. + setHoverStyle(symbolPath); + + symbolPath.__symbolOriginalScale = getScale(symbolSize); + + if (hoverAnimation && seriesModel.isAnimationEnabled()) { + // Note: consider `off`, should use static function here. + symbolPath.on('mouseover', onMouseOver) + .on('mouseout', onMouseOut) + .on('emphasis', onEmphasis) + .on('normal', onNormal); + } +}; + +function onMouseOver() { + // see comment in `graphic.isInEmphasis` + !isInEmphasis(this) && onEmphasis.call(this); +} + +function onMouseOut() { + // see comment in `graphic.isInEmphasis` + !isInEmphasis(this) && onNormal.call(this); +} + +function onEmphasis() { + // Do not support this hover animation util some scenario required. + // Animation can only be supported in hover layer when using `el.incremetal`. + if (this.incremental || this.useHoverLayer) { + return; + } + var scale = this.__symbolOriginalScale; + var ratio = scale[1] / scale[0]; + this.animateTo({ + scale: [ + Math.max(scale[0] * 1.1, scale[0] + 3), + Math.max(scale[1] * 1.1, scale[1] + 3 * ratio) + ] + }, 400, 'elasticOut'); +} + +function onNormal() { + if (this.incremental || this.useHoverLayer) { + return; + } + this.animateTo({ + scale: this.__symbolOriginalScale + }, 400, 'elasticOut'); +} + + +/** + * @param {Function} cb + * @param {Object} [opt] + * @param {Object} [opt.keepLabel=true] + */ +symbolProto.fadeOut = function (cb, opt) { + var symbolPath = this.childAt(0); + // Avoid mistaken hover when fading out + this.silent = symbolPath.silent = true; + // Not show text when animating + !(opt && opt.keepLabel) && (symbolPath.style.text = null); + + updateProps( + symbolPath, + { + style: {opacity: 0}, + scale: [0, 0] + }, + this._seriesModel, + this.dataIndex, + cb + ); +}; + +inherits(SymbolClz$1, Group); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/** + * @module echarts/chart/helper/SymbolDraw + */ + +/** + * @constructor + * @alias module:echarts/chart/helper/SymbolDraw + * @param {module:zrender/graphic/Group} [symbolCtor] + */ +function SymbolDraw(symbolCtor) { + this.group = new Group(); + + this._symbolCtor = symbolCtor || SymbolClz$1; +} + +var symbolDrawProto = SymbolDraw.prototype; + +function symbolNeedsDraw(data, point, idx, opt) { + return point && !isNaN(point[0]) && !isNaN(point[1]) + && !(opt.isIgnore && opt.isIgnore(idx)) + // We do not set clipShape on group, because it will cut part of + // the symbol element shape. We use the same clip shape here as + // the line clip. + && !(opt.clipShape && !opt.clipShape.contain(point[0], point[1])) + && data.getItemVisual(idx, 'symbol') !== 'none'; +} + +/** + * Update symbols draw by new data + * @param {module:echarts/data/List} data + * @param {Object} [opt] Or isIgnore + * @param {Function} [opt.isIgnore] + * @param {Object} [opt.clipShape] + */ +symbolDrawProto.updateData = function (data, opt) { + opt = normalizeUpdateOpt(opt); + + var group = this.group; + var seriesModel = data.hostModel; + var oldData = this._data; + var SymbolCtor = this._symbolCtor; + + var seriesScope = makeSeriesScope(data); + + // There is no oldLineData only when first rendering or switching from + // stream mode to normal mode, where previous elements should be removed. + if (!oldData) { + group.removeAll(); + } + + data.diff(oldData) + .add(function (newIdx) { + var point = data.getItemLayout(newIdx); + if (symbolNeedsDraw(data, point, newIdx, opt)) { + var symbolEl = new SymbolCtor(data, newIdx, seriesScope); + symbolEl.attr('position', point); + data.setItemGraphicEl(newIdx, symbolEl); + group.add(symbolEl); + } + }) + .update(function (newIdx, oldIdx) { + var symbolEl = oldData.getItemGraphicEl(oldIdx); + var point = data.getItemLayout(newIdx); + if (!symbolNeedsDraw(data, point, newIdx, opt)) { + group.remove(symbolEl); + return; + } + if (!symbolEl) { + symbolEl = new SymbolCtor(data, newIdx); + symbolEl.attr('position', point); + } + else { + symbolEl.updateData(data, newIdx, seriesScope); + updateProps(symbolEl, { + position: point + }, seriesModel); + } + + // Add back + group.add(symbolEl); + + data.setItemGraphicEl(newIdx, symbolEl); + }) + .remove(function (oldIdx) { + var el = oldData.getItemGraphicEl(oldIdx); + el && el.fadeOut(function () { + group.remove(el); + }); + }) + .execute(); + + this._data = data; +}; + +symbolDrawProto.isPersistent = function () { + return true; +}; + +symbolDrawProto.updateLayout = function () { + var data = this._data; + if (data) { + // Not use animation + data.eachItemGraphicEl(function (el, idx) { + var point = data.getItemLayout(idx); + el.attr('position', point); + }); + } +}; + +symbolDrawProto.incrementalPrepareUpdate = function (data) { + this._seriesScope = makeSeriesScope(data); + this._data = null; + this.group.removeAll(); +}; + +/** + * Update symbols draw by new data + * @param {module:echarts/data/List} data + * @param {Object} [opt] Or isIgnore + * @param {Function} [opt.isIgnore] + * @param {Object} [opt.clipShape] + */ +symbolDrawProto.incrementalUpdate = function (taskParams, data, opt) { + opt = normalizeUpdateOpt(opt); + + function updateIncrementalAndHover(el) { + if (!el.isGroup) { + el.incremental = el.useHoverLayer = true; + } + } + for (var idx = taskParams.start; idx < taskParams.end; idx++) { + var point = data.getItemLayout(idx); + if (symbolNeedsDraw(data, point, idx, opt)) { + var el = new this._symbolCtor(data, idx, this._seriesScope); + el.traverse(updateIncrementalAndHover); + el.attr('position', point); + this.group.add(el); + data.setItemGraphicEl(idx, el); + } + } +}; + +function normalizeUpdateOpt(opt) { + if (opt != null && !isObject$1(opt)) { + opt = {isIgnore: opt}; + } + return opt || {}; +} + +symbolDrawProto.remove = function (enableAnimation) { + var group = this.group; + var data = this._data; + // Incremental model do not have this._data. + if (data && enableAnimation) { + data.eachItemGraphicEl(function (el) { + el.fadeOut(function () { + group.remove(el); + }); + }); + } + else { + group.removeAll(); + } +}; + +function makeSeriesScope(data) { + var seriesModel = data.hostModel; + return { + itemStyle: seriesModel.getModel('itemStyle').getItemStyle(['color']), + hoverItemStyle: seriesModel.getModel('emphasis.itemStyle').getItemStyle(), + symbolRotate: seriesModel.get('symbolRotate'), + symbolOffset: seriesModel.get('symbolOffset'), + hoverAnimation: seriesModel.get('hoverAnimation'), + labelModel: seriesModel.getModel('label'), + hoverLabelModel: seriesModel.getModel('emphasis.label'), + cursorStyle: seriesModel.get('cursor') + }; +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/** + * @param {Object} coordSys + * @param {module:echarts/data/List} data + * @param {string} valueOrigin lineSeries.option.areaStyle.origin + */ +function prepareDataCoordInfo(coordSys, data, valueOrigin) { + var baseAxis = coordSys.getBaseAxis(); + var valueAxis = coordSys.getOtherAxis(baseAxis); + var valueStart = getValueStart(valueAxis, valueOrigin); + + var baseAxisDim = baseAxis.dim; + var valueAxisDim = valueAxis.dim; + var valueDim = data.mapDimension(valueAxisDim); + var baseDim = data.mapDimension(baseAxisDim); + var baseDataOffset = valueAxisDim === 'x' || valueAxisDim === 'radius' ? 1 : 0; + + var dims = map(coordSys.dimensions, function (coordDim) { + return data.mapDimension(coordDim); + }); + + var stacked; + var stackResultDim = data.getCalculationInfo('stackResultDimension'); + if (stacked |= isDimensionStacked(data, dims[0] /*, dims[1]*/)) { // jshint ignore:line + dims[0] = stackResultDim; + } + if (stacked |= isDimensionStacked(data, dims[1] /*, dims[0]*/)) { // jshint ignore:line + dims[1] = stackResultDim; + } + + return { + dataDimsForPoint: dims, + valueStart: valueStart, + valueAxisDim: valueAxisDim, + baseAxisDim: baseAxisDim, + stacked: !!stacked, + valueDim: valueDim, + baseDim: baseDim, + baseDataOffset: baseDataOffset, + stackedOverDimension: data.getCalculationInfo('stackedOverDimension') + }; +} + +function getValueStart(valueAxis, valueOrigin) { + var valueStart = 0; + var extent = valueAxis.scale.getExtent(); + + if (valueOrigin === 'start') { + valueStart = extent[0]; + } + else if (valueOrigin === 'end') { + valueStart = extent[1]; + } + // auto + else { + // Both positive + if (extent[0] > 0) { + valueStart = extent[0]; + } + // Both negative + else if (extent[1] < 0) { + valueStart = extent[1]; + } + // If is one positive, and one negative, onZero shall be true + } + + return valueStart; +} + +function getStackedOnPoint(dataCoordInfo, coordSys, data, idx) { + var value = NaN; + if (dataCoordInfo.stacked) { + value = data.get(data.getCalculationInfo('stackedOverDimension'), idx); + } + if (isNaN(value)) { + value = dataCoordInfo.valueStart; + } + + var baseDataOffset = dataCoordInfo.baseDataOffset; + var stackedData = []; + stackedData[baseDataOffset] = data.get(dataCoordInfo.baseDim, idx); + stackedData[1 - baseDataOffset] = value; + + return coordSys.dataToPoint(stackedData); +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +// var arrayDiff = require('zrender/src/core/arrayDiff'); +// 'zrender/src/core/arrayDiff' has been used before, but it did +// not do well in performance when roam with fixed dataZoom window. + +// function convertToIntId(newIdList, oldIdList) { +// // Generate int id instead of string id. +// // Compare string maybe slow in score function of arrDiff + +// // Assume id in idList are all unique +// var idIndicesMap = {}; +// var idx = 0; +// for (var i = 0; i < newIdList.length; i++) { +// idIndicesMap[newIdList[i]] = idx; +// newIdList[i] = idx++; +// } +// for (var i = 0; i < oldIdList.length; i++) { +// var oldId = oldIdList[i]; +// // Same with newIdList +// if (idIndicesMap[oldId]) { +// oldIdList[i] = idIndicesMap[oldId]; +// } +// else { +// oldIdList[i] = idx++; +// } +// } +// } + +function diffData(oldData, newData) { + var diffResult = []; + + newData.diff(oldData) + .add(function (idx) { + diffResult.push({cmd: '+', idx: idx}); + }) + .update(function (newIdx, oldIdx) { + diffResult.push({cmd: '=', idx: oldIdx, idx1: newIdx}); + }) + .remove(function (idx) { + diffResult.push({cmd: '-', idx: idx}); + }) + .execute(); + + return diffResult; +} + +var lineAnimationDiff = function ( + oldData, newData, + oldStackedOnPoints, newStackedOnPoints, + oldCoordSys, newCoordSys, + oldValueOrigin, newValueOrigin +) { + var diff = diffData(oldData, newData); + + // var newIdList = newData.mapArray(newData.getId); + // var oldIdList = oldData.mapArray(oldData.getId); + + // convertToIntId(newIdList, oldIdList); + + // // FIXME One data ? + // diff = arrayDiff(oldIdList, newIdList); + + var currPoints = []; + var nextPoints = []; + // Points for stacking base line + var currStackedPoints = []; + var nextStackedPoints = []; + + var status = []; + var sortedIndices = []; + var rawIndices = []; + + var newDataOldCoordInfo = prepareDataCoordInfo(oldCoordSys, newData, oldValueOrigin); + var oldDataNewCoordInfo = prepareDataCoordInfo(newCoordSys, oldData, newValueOrigin); + + for (var i = 0; i < diff.length; i++) { + var diffItem = diff[i]; + var pointAdded = true; + + // FIXME, animation is not so perfect when dataZoom window moves fast + // Which is in case remvoing or add more than one data in the tail or head + switch (diffItem.cmd) { + case '=': + var currentPt = oldData.getItemLayout(diffItem.idx); + var nextPt = newData.getItemLayout(diffItem.idx1); + // If previous data is NaN, use next point directly + if (isNaN(currentPt[0]) || isNaN(currentPt[1])) { + currentPt = nextPt.slice(); + } + currPoints.push(currentPt); + nextPoints.push(nextPt); + + currStackedPoints.push(oldStackedOnPoints[diffItem.idx]); + nextStackedPoints.push(newStackedOnPoints[diffItem.idx1]); + + rawIndices.push(newData.getRawIndex(diffItem.idx1)); + break; + case '+': + var idx = diffItem.idx; + currPoints.push( + oldCoordSys.dataToPoint([ + newData.get(newDataOldCoordInfo.dataDimsForPoint[0], idx), + newData.get(newDataOldCoordInfo.dataDimsForPoint[1], idx) + ]) + ); + + nextPoints.push(newData.getItemLayout(idx).slice()); + + currStackedPoints.push( + getStackedOnPoint(newDataOldCoordInfo, oldCoordSys, newData, idx) + ); + nextStackedPoints.push(newStackedOnPoints[idx]); + + rawIndices.push(newData.getRawIndex(idx)); + break; + case '-': + var idx = diffItem.idx; + var rawIndex = oldData.getRawIndex(idx); + // Data is replaced. In the case of dynamic data queue + // FIXME FIXME FIXME + if (rawIndex !== idx) { + currPoints.push(oldData.getItemLayout(idx)); + nextPoints.push(newCoordSys.dataToPoint([ + oldData.get(oldDataNewCoordInfo.dataDimsForPoint[0], idx), + oldData.get(oldDataNewCoordInfo.dataDimsForPoint[1], idx) + ])); + + currStackedPoints.push(oldStackedOnPoints[idx]); + nextStackedPoints.push( + getStackedOnPoint(oldDataNewCoordInfo, newCoordSys, oldData, idx) + ); + + rawIndices.push(rawIndex); + } + else { + pointAdded = false; + } + } + + // Original indices + if (pointAdded) { + status.push(diffItem); + sortedIndices.push(sortedIndices.length); + } + } + + // Diff result may be crossed if all items are changed + // Sort by data index + sortedIndices.sort(function (a, b) { + return rawIndices[a] - rawIndices[b]; + }); + + var sortedCurrPoints = []; + var sortedNextPoints = []; + + var sortedCurrStackedPoints = []; + var sortedNextStackedPoints = []; + + var sortedStatus = []; + for (var i = 0; i < sortedIndices.length; i++) { + var idx = sortedIndices[i]; + sortedCurrPoints[i] = currPoints[idx]; + sortedNextPoints[i] = nextPoints[idx]; + + sortedCurrStackedPoints[i] = currStackedPoints[idx]; + sortedNextStackedPoints[i] = nextStackedPoints[idx]; + + sortedStatus[i] = status[idx]; + } + + return { + current: sortedCurrPoints, + next: sortedNextPoints, + + stackedOnCurrent: sortedCurrStackedPoints, + stackedOnNext: sortedNextStackedPoints, + + status: sortedStatus + }; +}; + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +// Poly path support NaN point + +var vec2Min = min; +var vec2Max = max; + +var scaleAndAdd$1 = scaleAndAdd; +var v2Copy = copy; + +// Temporary variable +var v = []; +var cp0 = []; +var cp1 = []; + +function isPointNull(p) { + return isNaN(p[0]) || isNaN(p[1]); +} + +function drawSegment( + ctx, points, start, segLen, allLen, + dir, smoothMin, smoothMax, smooth, smoothMonotone, connectNulls +) { + // if (smoothMonotone == null) { + // if (isMono(points, 'x')) { + // return drawMono(ctx, points, start, segLen, allLen, + // dir, smoothMin, smoothMax, smooth, 'x', connectNulls); + // } + // else if (isMono(points, 'y')) { + // return drawMono(ctx, points, start, segLen, allLen, + // dir, smoothMin, smoothMax, smooth, 'y', connectNulls); + // } + // else { + // return drawNonMono.apply(this, arguments); + // } + // } + // else if (smoothMonotone !== 'none' && isMono(points, smoothMonotone)) { + // return drawMono.apply(this, arguments); + // } + // else { + // return drawNonMono.apply(this, arguments); + // } + if (smoothMonotone === 'none' || !smoothMonotone) { + return drawNonMono.apply(this, arguments); + } + else { + return drawMono.apply(this, arguments); + } +} + +/** + * Check if points is in monotone. + * + * @param {number[][]} points Array of points which is in [x, y] form + * @param {string} smoothMonotone 'x', 'y', or 'none', stating for which + * dimension that is checking. + * If is 'none', `drawNonMono` should be + * called. + * If is undefined, either being monotone + * in 'x' or 'y' will call `drawMono`. + */ +// function isMono(points, smoothMonotone) { +// if (points.length <= 1) { +// return true; +// } + +// var dim = smoothMonotone === 'x' ? 0 : 1; +// var last = points[0][dim]; +// var lastDiff = 0; +// for (var i = 1; i < points.length; ++i) { +// var diff = points[i][dim] - last; +// if (!isNaN(diff) && !isNaN(lastDiff) +// && diff !== 0 && lastDiff !== 0 +// && ((diff >= 0) !== (lastDiff >= 0)) +// ) { +// return false; +// } +// if (!isNaN(diff) && diff !== 0) { +// lastDiff = diff; +// last = points[i][dim]; +// } +// } +// return true; +// } + +/** + * Draw smoothed line in monotone, in which only vertical or horizontal bezier + * control points will be used. This should be used when points are monotone + * either in x or y dimension. + */ +function drawMono( + ctx, points, start, segLen, allLen, + dir, smoothMin, smoothMax, smooth, smoothMonotone, connectNulls +) { + var prevIdx = 0; + var idx = start; + for (var k = 0; k < segLen; k++) { + var p = points[idx]; + if (idx >= allLen || idx < 0) { + break; + } + if (isPointNull(p)) { + if (connectNulls) { + idx += dir; + continue; + } + break; + } + + if (idx === start) { + ctx[dir > 0 ? 'moveTo' : 'lineTo'](p[0], p[1]); + } + else { + if (smooth > 0) { + var prevP = points[prevIdx]; + var dim = smoothMonotone === 'y' ? 1 : 0; + + // Length of control point to p, either in x or y, but not both + var ctrlLen = (p[dim] - prevP[dim]) * smooth; + + v2Copy(cp0, prevP); + cp0[dim] = prevP[dim] + ctrlLen; + + v2Copy(cp1, p); + cp1[dim] = p[dim] - ctrlLen; + + ctx.bezierCurveTo( + cp0[0], cp0[1], + cp1[0], cp1[1], + p[0], p[1] + ); + } + else { + ctx.lineTo(p[0], p[1]); + } + } + + prevIdx = idx; + idx += dir; + } + + return k; +} + +/** + * Draw smoothed line in non-monotone, in may cause undesired curve in extreme + * situations. This should be used when points are non-monotone neither in x or + * y dimension. + */ +function drawNonMono( + ctx, points, start, segLen, allLen, + dir, smoothMin, smoothMax, smooth, smoothMonotone, connectNulls +) { + var prevIdx = 0; + var idx = start; + for (var k = 0; k < segLen; k++) { + var p = points[idx]; + if (idx >= allLen || idx < 0) { + break; + } + if (isPointNull(p)) { + if (connectNulls) { + idx += dir; + continue; + } + break; + } + + if (idx === start) { + ctx[dir > 0 ? 'moveTo' : 'lineTo'](p[0], p[1]); + v2Copy(cp0, p); + } + else { + if (smooth > 0) { + var nextIdx = idx + dir; + var nextP = points[nextIdx]; + if (connectNulls) { + // Find next point not null + while (nextP && isPointNull(points[nextIdx])) { + nextIdx += dir; + nextP = points[nextIdx]; + } + } + + var ratioNextSeg = 0.5; + var prevP = points[prevIdx]; + var nextP = points[nextIdx]; + // Last point + if (!nextP || isPointNull(nextP)) { + v2Copy(cp1, p); + } + else { + // If next data is null in not connect case + if (isPointNull(nextP) && !connectNulls) { + nextP = p; + } + + sub(v, nextP, prevP); + + var lenPrevSeg; + var lenNextSeg; + if (smoothMonotone === 'x' || smoothMonotone === 'y') { + var dim = smoothMonotone === 'x' ? 0 : 1; + lenPrevSeg = Math.abs(p[dim] - prevP[dim]); + lenNextSeg = Math.abs(p[dim] - nextP[dim]); + } + else { + lenPrevSeg = dist(p, prevP); + lenNextSeg = dist(p, nextP); + } + + // Use ratio of seg length + ratioNextSeg = lenNextSeg / (lenNextSeg + lenPrevSeg); + + scaleAndAdd$1(cp1, p, v, -smooth * (1 - ratioNextSeg)); + } + // Smooth constraint + vec2Min(cp0, cp0, smoothMax); + vec2Max(cp0, cp0, smoothMin); + vec2Min(cp1, cp1, smoothMax); + vec2Max(cp1, cp1, smoothMin); + + ctx.bezierCurveTo( + cp0[0], cp0[1], + cp1[0], cp1[1], + p[0], p[1] + ); + // cp0 of next segment + scaleAndAdd$1(cp0, p, v, smooth * ratioNextSeg); + } + else { + ctx.lineTo(p[0], p[1]); + } + } + + prevIdx = idx; + idx += dir; + } + + return k; +} + +function getBoundingBox(points, smoothConstraint) { + var ptMin = [Infinity, Infinity]; + var ptMax = [-Infinity, -Infinity]; + if (smoothConstraint) { + for (var i = 0; i < points.length; i++) { + var pt = points[i]; + if (pt[0] < ptMin[0]) { + ptMin[0] = pt[0]; + } + if (pt[1] < ptMin[1]) { + ptMin[1] = pt[1]; + } + if (pt[0] > ptMax[0]) { + ptMax[0] = pt[0]; + } + if (pt[1] > ptMax[1]) { + ptMax[1] = pt[1]; + } + } + } + return { + min: smoothConstraint ? ptMin : ptMax, + max: smoothConstraint ? ptMax : ptMin + }; +} + +var Polyline$1 = Path.extend({ + + type: 'ec-polyline', + + shape: { + points: [], + + smooth: 0, + + smoothConstraint: true, + + smoothMonotone: null, + + connectNulls: false + }, + + style: { + fill: null, + + stroke: '#000' + }, + + brush: fixClipWithShadow(Path.prototype.brush), + + buildPath: function (ctx, shape) { + var points = shape.points; + + var i = 0; + var len$$1 = points.length; + + var result = getBoundingBox(points, shape.smoothConstraint); + + if (shape.connectNulls) { + // Must remove first and last null values avoid draw error in polygon + for (; len$$1 > 0; len$$1--) { + if (!isPointNull(points[len$$1 - 1])) { + break; + } + } + for (; i < len$$1; i++) { + if (!isPointNull(points[i])) { + break; + } + } + } + while (i < len$$1) { + i += drawSegment( + ctx, points, i, len$$1, len$$1, + 1, result.min, result.max, shape.smooth, + shape.smoothMonotone, shape.connectNulls + ) + 1; + } + } +}); + +var Polygon$1 = Path.extend({ + + type: 'ec-polygon', + + shape: { + points: [], + + // Offset between stacked base points and points + stackedOnPoints: [], + + smooth: 0, + + stackedOnSmooth: 0, + + smoothConstraint: true, + + smoothMonotone: null, + + connectNulls: false + }, + + brush: fixClipWithShadow(Path.prototype.brush), + + buildPath: function (ctx, shape) { + var points = shape.points; + var stackedOnPoints = shape.stackedOnPoints; + + var i = 0; + var len$$1 = points.length; + var smoothMonotone = shape.smoothMonotone; + var bbox = getBoundingBox(points, shape.smoothConstraint); + var stackedOnBBox = getBoundingBox(stackedOnPoints, shape.smoothConstraint); + + if (shape.connectNulls) { + // Must remove first and last null values avoid draw error in polygon + for (; len$$1 > 0; len$$1--) { + if (!isPointNull(points[len$$1 - 1])) { + break; + } + } + for (; i < len$$1; i++) { + if (!isPointNull(points[i])) { + break; + } + } + } + while (i < len$$1) { + var k = drawSegment( + ctx, points, i, len$$1, len$$1, + 1, bbox.min, bbox.max, shape.smooth, + smoothMonotone, shape.connectNulls + ); + drawSegment( + ctx, stackedOnPoints, i + k - 1, k, len$$1, + -1, stackedOnBBox.min, stackedOnBBox.max, shape.stackedOnSmooth, + smoothMonotone, shape.connectNulls + ); + i += k + 1; + + ctx.closePath(); + } + } +}); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +// FIXME step not support polar + +function isPointsSame(points1, points2) { + if (points1.length !== points2.length) { + return; + } + for (var i = 0; i < points1.length; i++) { + var p1 = points1[i]; + var p2 = points2[i]; + if (p1[0] !== p2[0] || p1[1] !== p2[1]) { + return; + } + } + return true; +} + +function getSmooth(smooth) { + return typeof (smooth) === 'number' ? smooth : (smooth ? 0.5 : 0); +} + +function getAxisExtentWithGap(axis) { + var extent = axis.getGlobalExtent(); + if (axis.onBand) { + // Remove extra 1px to avoid line miter in clipped edge + var halfBandWidth = axis.getBandWidth() / 2 - 1; + var dir = extent[1] > extent[0] ? 1 : -1; + extent[0] += dir * halfBandWidth; + extent[1] -= dir * halfBandWidth; + } + return extent; +} + +/** + * @param {module:echarts/coord/cartesian/Cartesian2D|module:echarts/coord/polar/Polar} coordSys + * @param {module:echarts/data/List} data + * @param {Object} dataCoordInfo + * @param {Array.>} points + */ +function getStackedOnPoints(coordSys, data, dataCoordInfo) { + if (!dataCoordInfo.valueDim) { + return []; + } + + var points = []; + for (var idx = 0, len = data.count(); idx < len; idx++) { + points.push(getStackedOnPoint(dataCoordInfo, coordSys, data, idx)); + } + + return points; +} + +function createGridClipShape(cartesian, hasAnimation, forSymbol, seriesModel) { + var xExtent = getAxisExtentWithGap(cartesian.getAxis('x')); + var yExtent = getAxisExtentWithGap(cartesian.getAxis('y')); + var isHorizontal = cartesian.getBaseAxis().isHorizontal(); + + var x = Math.min(xExtent[0], xExtent[1]); + var y = Math.min(yExtent[0], yExtent[1]); + var width = Math.max(xExtent[0], xExtent[1]) - x; + var height = Math.max(yExtent[0], yExtent[1]) - y; + + // Avoid float number rounding error for symbol on the edge of axis extent. + // See #7913 and `test/dataZoom-clip.html`. + if (forSymbol) { + x -= 0.5; + width += 0.5; + y -= 0.5; + height += 0.5; + } + else { + var lineWidth = seriesModel.get('lineStyle.width') || 2; + // Expand clip shape to avoid clipping when line value exceeds axis + var expandSize = seriesModel.get('clipOverflow') ? lineWidth / 2 : Math.max(width, height); + if (isHorizontal) { + y -= expandSize; + height += expandSize * 2; + } + else { + x -= expandSize; + width += expandSize * 2; + } + } + + var clipPath = new Rect({ + shape: { + x: x, + y: y, + width: width, + height: height + } + }); + + if (hasAnimation) { + clipPath.shape[isHorizontal ? 'width' : 'height'] = 0; + initProps(clipPath, { + shape: { + width: width, + height: height + } + }, seriesModel); + } + + return clipPath; +} + +function createPolarClipShape(polar, hasAnimation, forSymbol, seriesModel) { + var angleAxis = polar.getAngleAxis(); + var radiusAxis = polar.getRadiusAxis(); + + var radiusExtent = radiusAxis.getExtent().slice(); + radiusExtent[0] > radiusExtent[1] && radiusExtent.reverse(); + var angleExtent = angleAxis.getExtent(); + + var RADIAN = Math.PI / 180; + + // Avoid float number rounding error for symbol on the edge of axis extent. + if (forSymbol) { + radiusExtent[0] -= 0.5; + radiusExtent[1] += 0.5; + } + + var clipPath = new Sector({ + shape: { + cx: round$2(polar.cx, 1), + cy: round$2(polar.cy, 1), + r0: round$2(radiusExtent[0], 1), + r: round$2(radiusExtent[1], 1), + startAngle: -angleExtent[0] * RADIAN, + endAngle: -angleExtent[1] * RADIAN, + clockwise: angleAxis.inverse + } + }); + + if (hasAnimation) { + clipPath.shape.endAngle = -angleExtent[0] * RADIAN; + initProps(clipPath, { + shape: { + endAngle: -angleExtent[1] * RADIAN + } + }, seriesModel); + } + + return clipPath; +} + +function createClipShape(coordSys, hasAnimation, forSymbol, seriesModel) { + return coordSys.type === 'polar' + ? createPolarClipShape(coordSys, hasAnimation, forSymbol, seriesModel) + : createGridClipShape(coordSys, hasAnimation, forSymbol, seriesModel); +} + +function turnPointsIntoStep(points, coordSys, stepTurnAt) { + var baseAxis = coordSys.getBaseAxis(); + var baseIndex = baseAxis.dim === 'x' || baseAxis.dim === 'radius' ? 0 : 1; + + var stepPoints = []; + for (var i = 0; i < points.length - 1; i++) { + var nextPt = points[i + 1]; + var pt = points[i]; + stepPoints.push(pt); + + var stepPt = []; + switch (stepTurnAt) { + case 'end': + stepPt[baseIndex] = nextPt[baseIndex]; + stepPt[1 - baseIndex] = pt[1 - baseIndex]; + // default is start + stepPoints.push(stepPt); + break; + case 'middle': + // default is start + var middle = (pt[baseIndex] + nextPt[baseIndex]) / 2; + var stepPt2 = []; + stepPt[baseIndex] = stepPt2[baseIndex] = middle; + stepPt[1 - baseIndex] = pt[1 - baseIndex]; + stepPt2[1 - baseIndex] = nextPt[1 - baseIndex]; + stepPoints.push(stepPt); + stepPoints.push(stepPt2); + break; + default: + stepPt[baseIndex] = pt[baseIndex]; + stepPt[1 - baseIndex] = nextPt[1 - baseIndex]; + // default is start + stepPoints.push(stepPt); + } + } + // Last points + points[i] && stepPoints.push(points[i]); + return stepPoints; +} + +function getVisualGradient(data, coordSys) { + var visualMetaList = data.getVisual('visualMeta'); + if (!visualMetaList || !visualMetaList.length || !data.count()) { + // When data.count() is 0, gradient range can not be calculated. + return; + } + + if (coordSys.type !== 'cartesian2d') { + if (__DEV__) { + console.warn('Visual map on line style is only supported on cartesian2d.'); + } + return; + } + + var coordDim; + var visualMeta; + + for (var i = visualMetaList.length - 1; i >= 0; i--) { + var dimIndex = visualMetaList[i].dimension; + var dimName = data.dimensions[dimIndex]; + var dimInfo = data.getDimensionInfo(dimName); + coordDim = dimInfo && dimInfo.coordDim; + // Can only be x or y + if (coordDim === 'x' || coordDim === 'y') { + visualMeta = visualMetaList[i]; + break; + } + } + + if (!visualMeta) { + if (__DEV__) { + console.warn('Visual map on line style only support x or y dimension.'); + } + return; + } + + // If the area to be rendered is bigger than area defined by LinearGradient, + // the canvas spec prescribes that the color of the first stop and the last + // stop should be used. But if two stops are added at offset 0, in effect + // browsers use the color of the second stop to render area outside + // LinearGradient. So we can only infinitesimally extend area defined in + // LinearGradient to render `outerColors`. + + var axis = coordSys.getAxis(coordDim); + + // dataToCoor mapping may not be linear, but must be monotonic. + var colorStops = map(visualMeta.stops, function (stop) { + return { + coord: axis.toGlobalCoord(axis.dataToCoord(stop.value)), + color: stop.color + }; + }); + var stopLen = colorStops.length; + var outerColors = visualMeta.outerColors.slice(); + + if (stopLen && colorStops[0].coord > colorStops[stopLen - 1].coord) { + colorStops.reverse(); + outerColors.reverse(); + } + + var tinyExtent = 10; // Arbitrary value: 10px + var minCoord = colorStops[0].coord - tinyExtent; + var maxCoord = colorStops[stopLen - 1].coord + tinyExtent; + var coordSpan = maxCoord - minCoord; + + if (coordSpan < 1e-3) { + return 'transparent'; + } + + each$1(colorStops, function (stop) { + stop.offset = (stop.coord - minCoord) / coordSpan; + }); + colorStops.push({ + offset: stopLen ? colorStops[stopLen - 1].offset : 0.5, + color: outerColors[1] || 'transparent' + }); + colorStops.unshift({ // notice colorStops.length have been changed. + offset: stopLen ? colorStops[0].offset : 0.5, + color: outerColors[0] || 'transparent' + }); + + // zrUtil.each(colorStops, function (colorStop) { + // // Make sure each offset has rounded px to avoid not sharp edge + // colorStop.offset = (Math.round(colorStop.offset * (end - start) + start) - start) / (end - start); + // }); + + var gradient = new LinearGradient(0, 0, 0, 0, colorStops, true); + gradient[coordDim] = minCoord; + gradient[coordDim + '2'] = maxCoord; + + return gradient; +} + +function getIsIgnoreFunc(seriesModel, data, coordSys) { + var showAllSymbol = seriesModel.get('showAllSymbol'); + var isAuto = showAllSymbol === 'auto'; + + if (showAllSymbol && !isAuto) { + return; + } + + var categoryAxis = coordSys.getAxesByScale('ordinal')[0]; + if (!categoryAxis) { + return; + } + + // Note that category label interval strategy might bring some weird effect + // in some scenario: users may wonder why some of the symbols are not + // displayed. So we show all symbols as possible as we can. + if (isAuto + // Simplify the logic, do not determine label overlap here. + && canShowAllSymbolForCategory(categoryAxis, data) + ) { + return; + } + + // Otherwise follow the label interval strategy on category axis. + var categoryDataDim = data.mapDimension(categoryAxis.dim); + var labelMap = {}; + + each$1(categoryAxis.getViewLabels(), function (labelItem) { + labelMap[labelItem.tickValue] = 1; + }); + + return function (dataIndex) { + return !labelMap.hasOwnProperty(data.get(categoryDataDim, dataIndex)); + }; +} + +function canShowAllSymbolForCategory(categoryAxis, data) { + // In mose cases, line is monotonous on category axis, and the label size + // is close with each other. So we check the symbol size and some of the + // label size alone with the category axis to estimate whether all symbol + // can be shown without overlap. + var axisExtent = categoryAxis.getExtent(); + var availSize = Math.abs(axisExtent[1] - axisExtent[0]) / categoryAxis.scale.count(); + isNaN(availSize) && (availSize = 0); // 0/0 is NaN. + + // Sampling some points, max 5. + var dataLen = data.count(); + var step = Math.max(1, Math.round(dataLen / 5)); + for (var dataIndex = 0; dataIndex < dataLen; dataIndex += step) { + if (SymbolClz$1.getSymbolSize( + data, dataIndex + // Only for cartesian, where `isHorizontal` exists. + )[categoryAxis.isHorizontal() ? 1 : 0] + // Empirical number + * 1.5 > availSize + ) { + return false; + } + } + + return true; +} + +Chart.extend({ + + type: 'line', + + init: function () { + var lineGroup = new Group(); + + var symbolDraw = new SymbolDraw(); + this.group.add(symbolDraw.group); + + this._symbolDraw = symbolDraw; + this._lineGroup = lineGroup; + }, + + render: function (seriesModel, ecModel, api) { + var coordSys = seriesModel.coordinateSystem; + var group = this.group; + var data = seriesModel.getData(); + var lineStyleModel = seriesModel.getModel('lineStyle'); + var areaStyleModel = seriesModel.getModel('areaStyle'); + + var points = data.mapArray(data.getItemLayout); + + var isCoordSysPolar = coordSys.type === 'polar'; + var prevCoordSys = this._coordSys; + + var symbolDraw = this._symbolDraw; + var polyline = this._polyline; + var polygon = this._polygon; + + var lineGroup = this._lineGroup; + + var hasAnimation = seriesModel.get('animation'); + + var isAreaChart = !areaStyleModel.isEmpty(); + + var valueOrigin = areaStyleModel.get('origin'); + var dataCoordInfo = prepareDataCoordInfo(coordSys, data, valueOrigin); + + var stackedOnPoints = getStackedOnPoints(coordSys, data, dataCoordInfo); + + var showSymbol = seriesModel.get('showSymbol'); + + var isIgnoreFunc = showSymbol && !isCoordSysPolar + && getIsIgnoreFunc(seriesModel, data, coordSys); + + // Remove temporary symbols + var oldData = this._data; + oldData && oldData.eachItemGraphicEl(function (el, idx) { + if (el.__temp) { + group.remove(el); + oldData.setItemGraphicEl(idx, null); + } + }); + + // Remove previous created symbols if showSymbol changed to false + if (!showSymbol) { + symbolDraw.remove(); + } + + group.add(lineGroup); + + // FIXME step not support polar + var step = !isCoordSysPolar && seriesModel.get('step'); + // Initialization animation or coordinate system changed + if ( + !(polyline && prevCoordSys.type === coordSys.type && step === this._step) + ) { + showSymbol && symbolDraw.updateData(data, { + isIgnore: isIgnoreFunc, + clipShape: createClipShape(coordSys, false, true, seriesModel) + }); + + if (step) { + // TODO If stacked series is not step + points = turnPointsIntoStep(points, coordSys, step); + stackedOnPoints = turnPointsIntoStep(stackedOnPoints, coordSys, step); + } + + polyline = this._newPolyline(points, coordSys, hasAnimation); + if (isAreaChart) { + polygon = this._newPolygon( + points, stackedOnPoints, + coordSys, hasAnimation + ); + } + lineGroup.setClipPath(createClipShape(coordSys, true, false, seriesModel)); + } + else { + if (isAreaChart && !polygon) { + // If areaStyle is added + polygon = this._newPolygon( + points, stackedOnPoints, + coordSys, hasAnimation + ); + } + else if (polygon && !isAreaChart) { + // If areaStyle is removed + lineGroup.remove(polygon); + polygon = this._polygon = null; + } + + // Update clipPath + lineGroup.setClipPath(createClipShape(coordSys, false, false, seriesModel)); + + // Always update, or it is wrong in the case turning on legend + // because points are not changed + showSymbol && symbolDraw.updateData(data, { + isIgnore: isIgnoreFunc, + clipShape: createClipShape(coordSys, false, true, seriesModel) + }); + + // Stop symbol animation and sync with line points + // FIXME performance? + data.eachItemGraphicEl(function (el) { + el.stopAnimation(true); + }); + + // In the case data zoom triggerred refreshing frequently + // Data may not change if line has a category axis. So it should animate nothing + if (!isPointsSame(this._stackedOnPoints, stackedOnPoints) + || !isPointsSame(this._points, points) + ) { + if (hasAnimation) { + this._updateAnimation( + data, stackedOnPoints, coordSys, api, step, valueOrigin + ); + } + else { + // Not do it in update with animation + if (step) { + // TODO If stacked series is not step + points = turnPointsIntoStep(points, coordSys, step); + stackedOnPoints = turnPointsIntoStep(stackedOnPoints, coordSys, step); + } + + polyline.setShape({ + points: points + }); + polygon && polygon.setShape({ + points: points, + stackedOnPoints: stackedOnPoints + }); + } + } + } + + var visualColor = getVisualGradient(data, coordSys) || data.getVisual('color'); + + polyline.useStyle(defaults( + // Use color in lineStyle first + lineStyleModel.getLineStyle(), + { + fill: 'none', + stroke: visualColor, + lineJoin: 'bevel' + } + )); + + var smooth = seriesModel.get('smooth'); + smooth = getSmooth(seriesModel.get('smooth')); + polyline.setShape({ + smooth: smooth, + smoothMonotone: seriesModel.get('smoothMonotone'), + connectNulls: seriesModel.get('connectNulls') + }); + + if (polygon) { + var stackedOnSeries = data.getCalculationInfo('stackedOnSeries'); + var stackedOnSmooth = 0; + + polygon.useStyle(defaults( + areaStyleModel.getAreaStyle(), + { + fill: visualColor, + opacity: 0.7, + lineJoin: 'bevel' + } + )); + + if (stackedOnSeries) { + stackedOnSmooth = getSmooth(stackedOnSeries.get('smooth')); + } + + polygon.setShape({ + smooth: smooth, + stackedOnSmooth: stackedOnSmooth, + smoothMonotone: seriesModel.get('smoothMonotone'), + connectNulls: seriesModel.get('connectNulls') + }); + } + + this._data = data; + // Save the coordinate system for transition animation when data changed + this._coordSys = coordSys; + this._stackedOnPoints = stackedOnPoints; + this._points = points; + this._step = step; + this._valueOrigin = valueOrigin; + }, + + dispose: function () {}, + + highlight: function (seriesModel, ecModel, api, payload) { + var data = seriesModel.getData(); + var dataIndex = queryDataIndex(data, payload); + + if (!(dataIndex instanceof Array) && dataIndex != null && dataIndex >= 0) { + var symbol = data.getItemGraphicEl(dataIndex); + if (!symbol) { + // Create a temporary symbol if it is not exists + var pt = data.getItemLayout(dataIndex); + if (!pt) { + // Null data + return; + } + symbol = new SymbolClz$1(data, dataIndex); + symbol.position = pt; + symbol.setZ( + seriesModel.get('zlevel'), + seriesModel.get('z') + ); + symbol.ignore = isNaN(pt[0]) || isNaN(pt[1]); + symbol.__temp = true; + data.setItemGraphicEl(dataIndex, symbol); + + // Stop scale animation + symbol.stopSymbolAnimation(true); + + this.group.add(symbol); + } + symbol.highlight(); + } + else { + // Highlight whole series + Chart.prototype.highlight.call( + this, seriesModel, ecModel, api, payload + ); + } + }, + + downplay: function (seriesModel, ecModel, api, payload) { + var data = seriesModel.getData(); + var dataIndex = queryDataIndex(data, payload); + if (dataIndex != null && dataIndex >= 0) { + var symbol = data.getItemGraphicEl(dataIndex); + if (symbol) { + if (symbol.__temp) { + data.setItemGraphicEl(dataIndex, null); + this.group.remove(symbol); + } + else { + symbol.downplay(); + } + } + } + else { + // FIXME + // can not downplay completely. + // Downplay whole series + Chart.prototype.downplay.call( + this, seriesModel, ecModel, api, payload + ); + } + }, + + /** + * @param {module:zrender/container/Group} group + * @param {Array.>} points + * @private + */ + _newPolyline: function (points) { + var polyline = this._polyline; + // Remove previous created polyline + if (polyline) { + this._lineGroup.remove(polyline); + } + + polyline = new Polyline$1({ + shape: { + points: points + }, + silent: true, + z2: 10 + }); + + this._lineGroup.add(polyline); + + this._polyline = polyline; + + return polyline; + }, + + /** + * @param {module:zrender/container/Group} group + * @param {Array.>} stackedOnPoints + * @param {Array.>} points + * @private + */ + _newPolygon: function (points, stackedOnPoints) { + var polygon = this._polygon; + // Remove previous created polygon + if (polygon) { + this._lineGroup.remove(polygon); + } + + polygon = new Polygon$1({ + shape: { + points: points, + stackedOnPoints: stackedOnPoints + }, + silent: true + }); + + this._lineGroup.add(polygon); + + this._polygon = polygon; + return polygon; + }, + + /** + * @private + */ + // FIXME Two value axis + _updateAnimation: function (data, stackedOnPoints, coordSys, api, step, valueOrigin) { + var polyline = this._polyline; + var polygon = this._polygon; + var seriesModel = data.hostModel; + + var diff = lineAnimationDiff( + this._data, data, + this._stackedOnPoints, stackedOnPoints, + this._coordSys, coordSys, + this._valueOrigin, valueOrigin + ); + + var current = diff.current; + var stackedOnCurrent = diff.stackedOnCurrent; + var next = diff.next; + var stackedOnNext = diff.stackedOnNext; + if (step) { + // TODO If stacked series is not step + current = turnPointsIntoStep(diff.current, coordSys, step); + stackedOnCurrent = turnPointsIntoStep(diff.stackedOnCurrent, coordSys, step); + next = turnPointsIntoStep(diff.next, coordSys, step); + stackedOnNext = turnPointsIntoStep(diff.stackedOnNext, coordSys, step); + } + // `diff.current` is subset of `current` (which should be ensured by + // turnPointsIntoStep), so points in `__points` can be updated when + // points in `current` are update during animation. + polyline.shape.__points = diff.current; + polyline.shape.points = current; + + updateProps(polyline, { + shape: { + points: next + } + }, seriesModel); + + if (polygon) { + polygon.setShape({ + points: current, + stackedOnPoints: stackedOnCurrent + }); + updateProps(polygon, { + shape: { + points: next, + stackedOnPoints: stackedOnNext + } + }, seriesModel); + } + + var updatedDataInfo = []; + var diffStatus = diff.status; + + for (var i = 0; i < diffStatus.length; i++) { + var cmd = diffStatus[i].cmd; + if (cmd === '=') { + var el = data.getItemGraphicEl(diffStatus[i].idx1); + if (el) { + updatedDataInfo.push({ + el: el, + ptIdx: i // Index of points + }); + } + } + } + + if (polyline.animators && polyline.animators.length) { + polyline.animators[0].during(function () { + for (var i = 0; i < updatedDataInfo.length; i++) { + var el = updatedDataInfo[i].el; + el.attr('position', polyline.shape.__points[updatedDataInfo[i].ptIdx]); + } + }); + } + }, + + remove: function (ecModel) { + var group = this.group; + var oldData = this._data; + this._lineGroup.removeAll(); + this._symbolDraw.remove(true); + // Remove temporary created elements when highlighting + oldData && oldData.eachItemGraphicEl(function (el, idx) { + if (el.__temp) { + group.remove(el); + oldData.setItemGraphicEl(idx, null); + } + }); + + this._polyline + = this._polygon + = this._coordSys + = this._points + = this._stackedOnPoints + = this._data = null; + } +}); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + + +var visualSymbol = function (seriesType, defaultSymbolType, legendSymbol) { + // Encoding visual for all series include which is filtered for legend drawing + return { + seriesType: seriesType, + + // For legend. + performRawSeries: true, + + reset: function (seriesModel, ecModel, api) { + var data = seriesModel.getData(); + + var symbolType = seriesModel.get('symbol') || defaultSymbolType; + var symbolSize = seriesModel.get('symbolSize'); + var keepAspect = seriesModel.get('symbolKeepAspect'); + + data.setVisual({ + legendSymbol: legendSymbol || symbolType, + symbol: symbolType, + symbolSize: symbolSize, + symbolKeepAspect: keepAspect + }); + + // Only visible series has each data be visual encoded + if (ecModel.isSeriesFiltered(seriesModel)) { + return; + } + + var hasCallback = typeof symbolSize === 'function'; + + function dataEach(data, idx) { + if (typeof symbolSize === 'function') { + var rawValue = seriesModel.getRawValue(idx); + // FIXME + var params = seriesModel.getDataParams(idx); + data.setItemVisual(idx, 'symbolSize', symbolSize(rawValue, params)); + } + + if (data.hasItemOption) { + var itemModel = data.getItemModel(idx); + var itemSymbolType = itemModel.getShallow('symbol', true); + var itemSymbolSize = itemModel.getShallow('symbolSize', + true); + var itemSymbolKeepAspect + = itemModel.getShallow('symbolKeepAspect', true); + + // If has item symbol + if (itemSymbolType != null) { + data.setItemVisual(idx, 'symbol', itemSymbolType); + } + if (itemSymbolSize != null) { + // PENDING Transform symbolSize ? + data.setItemVisual(idx, 'symbolSize', itemSymbolSize); + } + if (itemSymbolKeepAspect != null) { + data.setItemVisual(idx, 'symbolKeepAspect', + itemSymbolKeepAspect); + } + } + } + + return { dataEach: (data.hasItemOption || hasCallback) ? dataEach : null }; + } + }; +}; + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/* global Float32Array */ + +var pointsLayout = function (seriesType) { + return { + seriesType: seriesType, + + plan: createRenderPlanner(), + + reset: function (seriesModel) { + var data = seriesModel.getData(); + var coordSys = seriesModel.coordinateSystem; + var pipelineContext = seriesModel.pipelineContext; + var isLargeRender = pipelineContext.large; + + if (!coordSys) { + return; + } + + var dims = map(coordSys.dimensions, function (dim) { + return data.mapDimension(dim); + }).slice(0, 2); + var dimLen = dims.length; + + var stackResultDim = data.getCalculationInfo('stackResultDimension'); + if (isDimensionStacked(data, dims[0] /*, dims[1]*/)) { + dims[0] = stackResultDim; + } + if (isDimensionStacked(data, dims[1] /*, dims[0]*/)) { + dims[1] = stackResultDim; + } + + function progress(params, data) { + var segCount = params.end - params.start; + var points = isLargeRender && new Float32Array(segCount * dimLen); + + for (var i = params.start, offset = 0, tmpIn = [], tmpOut = []; i < params.end; i++) { + var point; + + if (dimLen === 1) { + var x = data.get(dims[0], i); + point = !isNaN(x) && coordSys.dataToPoint(x, null, tmpOut); + } + else { + var x = tmpIn[0] = data.get(dims[0], i); + var y = tmpIn[1] = data.get(dims[1], i); + // Also {Array.}, not undefined to avoid if...else... statement + point = !isNaN(x) && !isNaN(y) && coordSys.dataToPoint(tmpIn, null, tmpOut); + } + + if (isLargeRender) { + points[offset++] = point ? point[0] : NaN; + points[offset++] = point ? point[1] : NaN; + } + else { + data.setItemLayout(i, (point && point.slice()) || [NaN, NaN]); + } + } + + isLargeRender && data.setLayout('symbolPoints', points); + } + + return dimLen && {progress: progress}; + } + }; +}; + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + + +var samplers = { + average: function (frame) { + var sum = 0; + var count = 0; + for (var i = 0; i < frame.length; i++) { + if (!isNaN(frame[i])) { + sum += frame[i]; + count++; + } + } + // Return NaN if count is 0 + return count === 0 ? NaN : sum / count; + }, + sum: function (frame) { + var sum = 0; + for (var i = 0; i < frame.length; i++) { + // Ignore NaN + sum += frame[i] || 0; + } + return sum; + }, + max: function (frame) { + var max = -Infinity; + for (var i = 0; i < frame.length; i++) { + frame[i] > max && (max = frame[i]); + } + // NaN will cause illegal axis extent. + return isFinite(max) ? max : NaN; + }, + min: function (frame) { + var min = Infinity; + for (var i = 0; i < frame.length; i++) { + frame[i] < min && (min = frame[i]); + } + // NaN will cause illegal axis extent. + return isFinite(min) ? min : NaN; + }, + // TODO + // Median + nearest: function (frame) { + return frame[0]; + } +}; + +var indexSampler = function (frame, value) { + return Math.round(frame.length / 2); +}; + +var dataSample = function (seriesType) { + return { + + seriesType: seriesType, + + modifyOutputEnd: true, + + reset: function (seriesModel, ecModel, api) { + var data = seriesModel.getData(); + var sampling = seriesModel.get('sampling'); + var coordSys = seriesModel.coordinateSystem; + // Only cartesian2d support down sampling + if (coordSys.type === 'cartesian2d' && sampling) { + var baseAxis = coordSys.getBaseAxis(); + var valueAxis = coordSys.getOtherAxis(baseAxis); + var extent = baseAxis.getExtent(); + // Coordinste system has been resized + var size = extent[1] - extent[0]; + var rate = Math.round(data.count() / size); + if (rate > 1) { + var sampler; + if (typeof sampling === 'string') { + sampler = samplers[sampling]; + } + else if (typeof sampling === 'function') { + sampler = sampling; + } + if (sampler) { + // Only support sample the first dim mapped from value axis. + seriesModel.setData(data.downSample( + data.mapDimension(valueAxis.dim), 1 / rate, sampler, indexSampler + )); + } + } + } + } + }; +}; + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/** + * Cartesian coordinate system + * @module echarts/coord/Cartesian + * + */ + +function dimAxisMapper(dim) { + return this._axes[dim]; +} + +/** + * @alias module:echarts/coord/Cartesian + * @constructor + */ +var Cartesian = function (name) { + this._axes = {}; + + this._dimList = []; + + /** + * @type {string} + */ + this.name = name || ''; +}; + +Cartesian.prototype = { + + constructor: Cartesian, + + type: 'cartesian', + + /** + * Get axis + * @param {number|string} dim + * @return {module:echarts/coord/Cartesian~Axis} + */ + getAxis: function (dim) { + return this._axes[dim]; + }, + + /** + * Get axes list + * @return {Array.} + */ + getAxes: function () { + return map(this._dimList, dimAxisMapper, this); + }, + + /** + * Get axes list by given scale type + */ + getAxesByScale: function (scaleType) { + scaleType = scaleType.toLowerCase(); + return filter( + this.getAxes(), + function (axis) { + return axis.scale.type === scaleType; + } + ); + }, + + /** + * Add axis + * @param {module:echarts/coord/Cartesian.Axis} + */ + addAxis: function (axis) { + var dim = axis.dim; + + this._axes[dim] = axis; + + this._dimList.push(dim); + }, + + /** + * Convert data to coord in nd space + * @param {Array.|Object.} val + * @return {Array.|Object.} + */ + dataToCoord: function (val) { + return this._dataCoordConvert(val, 'dataToCoord'); + }, + + /** + * Convert coord in nd space to data + * @param {Array.|Object.} val + * @return {Array.|Object.} + */ + coordToData: function (val) { + return this._dataCoordConvert(val, 'coordToData'); + }, + + _dataCoordConvert: function (input, method) { + var dimList = this._dimList; + + var output = input instanceof Array ? [] : {}; + + for (var i = 0; i < dimList.length; i++) { + var dim = dimList[i]; + var axis = this._axes[dim]; + + output[dim] = axis[method](input[dim]); + } + + return output; + } +}; + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + + +function Cartesian2D(name) { + + Cartesian.call(this, name); +} + +Cartesian2D.prototype = { + + constructor: Cartesian2D, + + type: 'cartesian2d', + + /** + * @type {Array.} + * @readOnly + */ + dimensions: ['x', 'y'], + + /** + * Base axis will be used on stacking. + * + * @return {module:echarts/coord/cartesian/Axis2D} + */ + getBaseAxis: function () { + return this.getAxesByScale('ordinal')[0] + || this.getAxesByScale('time')[0] + || this.getAxis('x'); + }, + + /** + * If contain point + * @param {Array.} point + * @return {boolean} + */ + containPoint: function (point) { + var axisX = this.getAxis('x'); + var axisY = this.getAxis('y'); + return axisX.contain(axisX.toLocalCoord(point[0])) + && axisY.contain(axisY.toLocalCoord(point[1])); + }, + + /** + * If contain data + * @param {Array.} data + * @return {boolean} + */ + containData: function (data) { + return this.getAxis('x').containData(data[0]) + && this.getAxis('y').containData(data[1]); + }, + + /** + * @param {Array.} data + * @param {Array.} out + * @return {Array.} + */ + dataToPoint: function (data, reserved, out) { + var xAxis = this.getAxis('x'); + var yAxis = this.getAxis('y'); + out = out || []; + out[0] = xAxis.toGlobalCoord(xAxis.dataToCoord(data[0])); + out[1] = yAxis.toGlobalCoord(yAxis.dataToCoord(data[1])); + return out; + }, + + /** + * @param {Array.} data + * @param {Array.} out + * @return {Array.} + */ + clampData: function (data, out) { + var xScale = this.getAxis('x').scale; + var yScale = this.getAxis('y').scale; + var xAxisExtent = xScale.getExtent(); + var yAxisExtent = yScale.getExtent(); + var x = xScale.parse(data[0]); + var y = yScale.parse(data[1]); + out = out || []; + out[0] = Math.min( + Math.max(Math.min(xAxisExtent[0], xAxisExtent[1]), x), + Math.max(xAxisExtent[0], xAxisExtent[1]) + ); + out[1] = Math.min( + Math.max(Math.min(yAxisExtent[0], yAxisExtent[1]), y), + Math.max(yAxisExtent[0], yAxisExtent[1]) + ); + + return out; + }, + + /** + * @param {Array.} point + * @param {Array.} out + * @return {Array.} + */ + pointToData: function (point, out) { + var xAxis = this.getAxis('x'); + var yAxis = this.getAxis('y'); + out = out || []; + out[0] = xAxis.coordToData(xAxis.toLocalCoord(point[0])); + out[1] = yAxis.coordToData(yAxis.toLocalCoord(point[1])); + return out; + }, + + /** + * Get other axis + * @param {module:echarts/coord/cartesian/Axis2D} axis + */ + getOtherAxis: function (axis) { + return this.getAxis(axis.dim === 'x' ? 'y' : 'x'); + } + +}; + +inherits(Cartesian2D, Cartesian); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/** + * Extend axis 2d + * @constructor module:echarts/coord/cartesian/Axis2D + * @extends {module:echarts/coord/cartesian/Axis} + * @param {string} dim + * @param {*} scale + * @param {Array.} coordExtent + * @param {string} axisType + * @param {string} position + */ +var Axis2D = function (dim, scale, coordExtent, axisType, position) { + Axis.call(this, dim, scale, coordExtent); + /** + * Axis type + * - 'category' + * - 'value' + * - 'time' + * - 'log' + * @type {string} + */ + this.type = axisType || 'value'; + + /** + * Axis position + * - 'top' + * - 'bottom' + * - 'left' + * - 'right' + */ + this.position = position || 'bottom'; +}; + +Axis2D.prototype = { + + constructor: Axis2D, + + /** + * Index of axis, can be used as key + */ + index: 0, + + /** + * Implemented in . + * @return {Array.} + * If not on zero of other axis, return null/undefined. + * If no axes, return an empty array. + */ + getAxesOnZeroOf: null, + + /** + * Axis model + * @param {module:echarts/coord/cartesian/AxisModel} + */ + model: null, + + isHorizontal: function () { + var position = this.position; + return position === 'top' || position === 'bottom'; + }, + + /** + * Each item cooresponds to this.getExtent(), which + * means globalExtent[0] may greater than globalExtent[1], + * unless `asc` is input. + * + * @param {boolean} [asc] + * @return {Array.} + */ + getGlobalExtent: function (asc) { + var ret = this.getExtent(); + ret[0] = this.toGlobalCoord(ret[0]); + ret[1] = this.toGlobalCoord(ret[1]); + asc && ret[0] > ret[1] && ret.reverse(); + return ret; + }, + + getOtherAxis: function () { + this.grid.getOtherAxis(); + }, + + /** + * @override + */ + pointToData: function (point, clamp) { + return this.coordToData(this.toLocalCoord(point[this.dim === 'x' ? 0 : 1]), clamp); + }, + + /** + * Transform global coord to local coord, + * i.e. var localCoord = axis.toLocalCoord(80); + * designate by module:echarts/coord/cartesian/Grid. + * @type {Function} + */ + toLocalCoord: null, + + /** + * Transform global coord to local coord, + * i.e. var globalCoord = axis.toLocalCoord(40); + * designate by module:echarts/coord/cartesian/Grid. + * @type {Function} + */ + toGlobalCoord: null + +}; + +inherits(Axis2D, Axis); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var defaultOption = { + show: true, + zlevel: 0, + z: 0, + // Inverse the axis. + inverse: false, + + // Axis name displayed. + name: '', + // 'start' | 'middle' | 'end' + nameLocation: 'end', + // By degree. By defualt auto rotate by nameLocation. + nameRotate: null, + nameTruncate: { + maxWidth: null, + ellipsis: '...', + placeholder: '.' + }, + // Use global text style by default. + nameTextStyle: {}, + // The gap between axisName and axisLine. + nameGap: 15, + + // Default `false` to support tooltip. + silent: false, + // Default `false` to avoid legacy user event listener fail. + triggerEvent: false, + + tooltip: { + show: false + }, + + axisPointer: {}, + + axisLine: { + show: true, + onZero: true, + onZeroAxisIndex: null, + lineStyle: { + color: '#333', + width: 1, + type: 'solid' + }, + // The arrow at both ends the the axis. + symbol: ['none', 'none'], + symbolSize: [10, 15] + }, + axisTick: { + show: true, + // Whether axisTick is inside the grid or outside the grid. + inside: false, + // The length of axisTick. + length: 5, + lineStyle: { + width: 1 + } + }, + axisLabel: { + show: true, + // Whether axisLabel is inside the grid or outside the grid. + inside: false, + rotate: 0, + // true | false | null/undefined (auto) + showMinLabel: null, + // true | false | null/undefined (auto) + showMaxLabel: null, + margin: 8, + // formatter: null, + fontSize: 12 + }, + splitLine: { + show: true, + lineStyle: { + color: ['#ccc'], + width: 1, + type: 'solid' + } + }, + splitArea: { + show: false, + areaStyle: { + color: ['rgba(250,250,250,0.3)', 'rgba(200,200,200,0.3)'] + } + } +}; + +var axisDefault = {}; + +axisDefault.categoryAxis = merge({ + // The gap at both ends of the axis. For categoryAxis, boolean. + boundaryGap: true, + // Set false to faster category collection. + // Only usefull in the case like: category is + // ['2012-01-01', '2012-01-02', ...], where the input + // data has been ensured not duplicate and is large data. + // null means "auto": + // if axis.data provided, do not deduplication, + // else do deduplication. + deduplication: null, + // splitArea: { + // show: false + // }, + splitLine: { + show: false + }, + axisTick: { + // If tick is align with label when boundaryGap is true + alignWithLabel: false, + interval: 'auto' + }, + axisLabel: { + interval: 'auto' + } +}, defaultOption); + +axisDefault.valueAxis = merge({ + // The gap at both ends of the axis. For value axis, [GAP, GAP], where + // `GAP` can be an absolute pixel number (like `35`), or percent (like `'30%'`) + boundaryGap: [0, 0], + + // TODO + // min/max: [30, datamin, 60] or [20, datamin] or [datamin, 60] + + // Min value of the axis. can be: + // + a number + // + 'dataMin': use the min value in data. + // + null/undefined: auto decide min value (consider pretty look and boundaryGap). + // min: null, + + // Max value of the axis. can be: + // + a number + // + 'dataMax': use the max value in data. + // + null/undefined: auto decide max value (consider pretty look and boundaryGap). + // max: null, + + // Readonly prop, specifies start value of the range when using data zoom. + // rangeStart: null + + // Readonly prop, specifies end value of the range when using data zoom. + // rangeEnd: null + + // Optional value can be: + // + `false`: always include value 0. + // + `true`: the extent do not consider value 0. + // scale: false, + + // AxisTick and axisLabel and splitLine are caculated based on splitNumber. + splitNumber: 5 + + // Interval specifies the span of the ticks is mandatorily. + // interval: null + + // Specify min interval when auto calculate tick interval. + // minInterval: null + + // Specify max interval when auto calculate tick interval. + // maxInterval: null + +}, defaultOption); + +axisDefault.timeAxis = defaults({ + scale: true, + min: 'dataMin', + max: 'dataMax' +}, axisDefault.valueAxis); + +axisDefault.logAxis = defaults({ + scale: true, + logBase: 10 +}, axisDefault.valueAxis); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +// FIXME axisType is fixed ? +var AXIS_TYPES = ['value', 'category', 'time', 'log']; + +/** + * Generate sub axis model class + * @param {string} axisName 'x' 'y' 'radius' 'angle' 'parallel' + * @param {module:echarts/model/Component} BaseAxisModelClass + * @param {Function} axisTypeDefaulter + * @param {Object} [extraDefaultOption] + */ +var axisModelCreator = function (axisName, BaseAxisModelClass, axisTypeDefaulter, extraDefaultOption) { + + each$1(AXIS_TYPES, function (axisType) { + + BaseAxisModelClass.extend({ + + /** + * @readOnly + */ + type: axisName + 'Axis.' + axisType, + + mergeDefaultAndTheme: function (option, ecModel) { + var layoutMode = this.layoutMode; + var inputPositionParams = layoutMode + ? getLayoutParams(option) : {}; + + var themeModel = ecModel.getTheme(); + merge(option, themeModel.get(axisType + 'Axis')); + merge(option, this.getDefaultOption()); + + option.type = axisTypeDefaulter(axisName, option); + + if (layoutMode) { + mergeLayoutParam(option, inputPositionParams, layoutMode); + } + }, + + /** + * @override + */ + optionUpdated: function () { + var thisOption = this.option; + if (thisOption.type === 'category') { + this.__ordinalMeta = OrdinalMeta.createByAxisModel(this); + } + }, + + /** + * Should not be called before all of 'getInitailData' finished. + * Because categories are collected during initializing data. + */ + getCategories: function (rawData) { + var option = this.option; + // FIXME + // warning if called before all of 'getInitailData' finished. + if (option.type === 'category') { + if (rawData) { + return option.data; + } + return this.__ordinalMeta.categories; + } + }, + + getOrdinalMeta: function () { + return this.__ordinalMeta; + }, + + defaultOption: mergeAll( + [ + {}, + axisDefault[axisType + 'Axis'], + extraDefaultOption + ], + true + ) + }); + }); + + ComponentModel.registerSubTypeDefaulter( + axisName + 'Axis', + curry(axisTypeDefaulter, axisName) + ); +}; + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var AxisModel = ComponentModel.extend({ + + type: 'cartesian2dAxis', + + /** + * @type {module:echarts/coord/cartesian/Axis2D} + */ + axis: null, + + /** + * @override + */ + init: function () { + AxisModel.superApply(this, 'init', arguments); + this.resetRange(); + }, + + /** + * @override + */ + mergeOption: function () { + AxisModel.superApply(this, 'mergeOption', arguments); + this.resetRange(); + }, + + /** + * @override + */ + restoreData: function () { + AxisModel.superApply(this, 'restoreData', arguments); + this.resetRange(); + }, + + /** + * @override + * @return {module:echarts/model/Component} + */ + getCoordSysModel: function () { + return this.ecModel.queryComponents({ + mainType: 'grid', + index: this.option.gridIndex, + id: this.option.gridId + })[0]; + } + +}); + +function getAxisType(axisDim, option) { + // Default axis with data is category axis + return option.type || (option.data ? 'category' : 'value'); +} + +merge(AxisModel.prototype, axisModelCommonMixin); + +var extraOption = { + // gridIndex: 0, + // gridId: '', + + // Offset is for multiple axis on the same position + offset: 0 +}; + +axisModelCreator('x', AxisModel, getAxisType, extraOption); +axisModelCreator('y', AxisModel, getAxisType, extraOption); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +// Grid 是在有直角坐标系的时候必须要存在的 +// 所以这里也要被 Cartesian2D 依赖 + +ComponentModel.extend({ + + type: 'grid', + + dependencies: ['xAxis', 'yAxis'], + + layoutMode: 'box', + + /** + * @type {module:echarts/coord/cartesian/Grid} + */ + coordinateSystem: null, + + defaultOption: { + show: false, + zlevel: 0, + z: 0, + left: '10%', + top: 60, + right: '10%', + bottom: 60, + // If grid size contain label + containLabel: false, + // width: {totalWidth} - left - right, + // height: {totalHeight} - top - bottom, + backgroundColor: 'rgba(0,0,0,0)', + borderWidth: 1, + borderColor: '#ccc' + } +}); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/** + * Grid is a region which contains at most 4 cartesian systems + * + * TODO Default cartesian + */ + +// Depends on GridModel, AxisModel, which performs preprocess. +/** + * Check if the axis is used in the specified grid + * @inner + */ +function isAxisUsedInTheGrid(axisModel, gridModel, ecModel) { + return axisModel.getCoordSysModel() === gridModel; +} + +function Grid(gridModel, ecModel, api) { + /** + * @type {Object.} + * @private + */ + this._coordsMap = {}; + + /** + * @type {Array.} + * @private + */ + this._coordsList = []; + + /** + * @type {Object.} + * @private + */ + this._axesMap = {}; + + /** + * @type {Array.} + * @private + */ + this._axesList = []; + + this._initCartesian(gridModel, ecModel, api); + + this.model = gridModel; +} + +var gridProto = Grid.prototype; + +gridProto.type = 'grid'; + +gridProto.axisPointerEnabled = true; + +gridProto.getRect = function () { + return this._rect; +}; + +gridProto.update = function (ecModel, api) { + + var axesMap = this._axesMap; + + this._updateScale(ecModel, this.model); + + each$1(axesMap.x, function (xAxis) { + niceScaleExtent(xAxis.scale, xAxis.model); + }); + each$1(axesMap.y, function (yAxis) { + niceScaleExtent(yAxis.scale, yAxis.model); + }); + + // Key: axisDim_axisIndex, value: boolean, whether onZero target. + var onZeroRecords = {}; + + each$1(axesMap.x, function (xAxis) { + fixAxisOnZero(axesMap, 'y', xAxis, onZeroRecords); + }); + each$1(axesMap.y, function (yAxis) { + fixAxisOnZero(axesMap, 'x', yAxis, onZeroRecords); + }); + + // Resize again if containLabel is enabled + // FIXME It may cause getting wrong grid size in data processing stage + this.resize(this.model, api); +}; + +function fixAxisOnZero(axesMap, otherAxisDim, axis, onZeroRecords) { + + axis.getAxesOnZeroOf = function () { + // TODO: onZero of multiple axes. + return otherAxisOnZeroOf ? [otherAxisOnZeroOf] : []; + }; + + // onZero can not be enabled in these two situations: + // 1. When any other axis is a category axis. + // 2. When no axis is cross 0 point. + var otherAxes = axesMap[otherAxisDim]; + + var otherAxisOnZeroOf; + var axisModel = axis.model; + var onZero = axisModel.get('axisLine.onZero'); + var onZeroAxisIndex = axisModel.get('axisLine.onZeroAxisIndex'); + + if (!onZero) { + return; + } + + // If target axis is specified. + if (onZeroAxisIndex != null) { + if (canOnZeroToAxis(otherAxes[onZeroAxisIndex])) { + otherAxisOnZeroOf = otherAxes[onZeroAxisIndex]; + } + } + else { + // Find the first available other axis. + for (var idx in otherAxes) { + if (otherAxes.hasOwnProperty(idx) + && canOnZeroToAxis(otherAxes[idx]) + // Consider that two Y axes on one value axis, + // if both onZero, the two Y axes overlap. + && !onZeroRecords[getOnZeroRecordKey(otherAxes[idx])] + ) { + otherAxisOnZeroOf = otherAxes[idx]; + break; + } + } + } + + if (otherAxisOnZeroOf) { + onZeroRecords[getOnZeroRecordKey(otherAxisOnZeroOf)] = true; + } + + function getOnZeroRecordKey(axis) { + return axis.dim + '_' + axis.index; + } +} + +function canOnZeroToAxis(axis) { + return axis && axis.type !== 'category' && axis.type !== 'time' && ifAxisCrossZero(axis); +} + +/** + * Resize the grid + * @param {module:echarts/coord/cartesian/GridModel} gridModel + * @param {module:echarts/ExtensionAPI} api + */ +gridProto.resize = function (gridModel, api, ignoreContainLabel) { + + var gridRect = getLayoutRect( + gridModel.getBoxLayoutParams(), { + width: api.getWidth(), + height: api.getHeight() + }); + + this._rect = gridRect; + + var axesList = this._axesList; + + adjustAxes(); + + // Minus label size + if (!ignoreContainLabel && gridModel.get('containLabel')) { + each$1(axesList, function (axis) { + if (!axis.model.get('axisLabel.inside')) { + var labelUnionRect = estimateLabelUnionRect(axis); + if (labelUnionRect) { + var dim = axis.isHorizontal() ? 'height' : 'width'; + var margin = axis.model.get('axisLabel.margin'); + gridRect[dim] -= labelUnionRect[dim] + margin; + if (axis.position === 'top') { + gridRect.y += labelUnionRect.height + margin; + } + else if (axis.position === 'left') { + gridRect.x += labelUnionRect.width + margin; + } + } + } + }); + + adjustAxes(); + } + + function adjustAxes() { + each$1(axesList, function (axis) { + var isHorizontal = axis.isHorizontal(); + var extent = isHorizontal ? [0, gridRect.width] : [0, gridRect.height]; + var idx = axis.inverse ? 1 : 0; + axis.setExtent(extent[idx], extent[1 - idx]); + updateAxisTransform(axis, isHorizontal ? gridRect.x : gridRect.y); + }); + } +}; + +/** + * @param {string} axisType + * @param {number} [axisIndex] + */ +gridProto.getAxis = function (axisType, axisIndex) { + var axesMapOnDim = this._axesMap[axisType]; + if (axesMapOnDim != null) { + if (axisIndex == null) { + // Find first axis + for (var name in axesMapOnDim) { + if (axesMapOnDim.hasOwnProperty(name)) { + return axesMapOnDim[name]; + } + } + } + return axesMapOnDim[axisIndex]; + } +}; + +/** + * @return {Array.} + */ +gridProto.getAxes = function () { + return this._axesList.slice(); +}; + +/** + * Usage: + * grid.getCartesian(xAxisIndex, yAxisIndex); + * grid.getCartesian(xAxisIndex); + * grid.getCartesian(null, yAxisIndex); + * grid.getCartesian({xAxisIndex: ..., yAxisIndex: ...}); + * + * @param {number|Object} [xAxisIndex] + * @param {number} [yAxisIndex] + */ +gridProto.getCartesian = function (xAxisIndex, yAxisIndex) { + if (xAxisIndex != null && yAxisIndex != null) { + var key = 'x' + xAxisIndex + 'y' + yAxisIndex; + return this._coordsMap[key]; + } + + if (isObject$1(xAxisIndex)) { + yAxisIndex = xAxisIndex.yAxisIndex; + xAxisIndex = xAxisIndex.xAxisIndex; + } + // When only xAxisIndex or yAxisIndex given, find its first cartesian. + for (var i = 0, coordList = this._coordsList; i < coordList.length; i++) { + if (coordList[i].getAxis('x').index === xAxisIndex + || coordList[i].getAxis('y').index === yAxisIndex + ) { + return coordList[i]; + } + } +}; + +gridProto.getCartesians = function () { + return this._coordsList.slice(); +}; + +/** + * @implements + * see {module:echarts/CoodinateSystem} + */ +gridProto.convertToPixel = function (ecModel, finder, value) { + var target = this._findConvertTarget(ecModel, finder); + + return target.cartesian + ? target.cartesian.dataToPoint(value) + : target.axis + ? target.axis.toGlobalCoord(target.axis.dataToCoord(value)) + : null; +}; + +/** + * @implements + * see {module:echarts/CoodinateSystem} + */ +gridProto.convertFromPixel = function (ecModel, finder, value) { + var target = this._findConvertTarget(ecModel, finder); + + return target.cartesian + ? target.cartesian.pointToData(value) + : target.axis + ? target.axis.coordToData(target.axis.toLocalCoord(value)) + : null; +}; + +/** + * @inner + */ +gridProto._findConvertTarget = function (ecModel, finder) { + var seriesModel = finder.seriesModel; + var xAxisModel = finder.xAxisModel + || (seriesModel && seriesModel.getReferringComponents('xAxis')[0]); + var yAxisModel = finder.yAxisModel + || (seriesModel && seriesModel.getReferringComponents('yAxis')[0]); + var gridModel = finder.gridModel; + var coordsList = this._coordsList; + var cartesian; + var axis; + + if (seriesModel) { + cartesian = seriesModel.coordinateSystem; + indexOf(coordsList, cartesian) < 0 && (cartesian = null); + } + else if (xAxisModel && yAxisModel) { + cartesian = this.getCartesian(xAxisModel.componentIndex, yAxisModel.componentIndex); + } + else if (xAxisModel) { + axis = this.getAxis('x', xAxisModel.componentIndex); + } + else if (yAxisModel) { + axis = this.getAxis('y', yAxisModel.componentIndex); + } + // Lowest priority. + else if (gridModel) { + var grid = gridModel.coordinateSystem; + if (grid === this) { + cartesian = this._coordsList[0]; + } + } + + return {cartesian: cartesian, axis: axis}; +}; + +/** + * @implements + * see {module:echarts/CoodinateSystem} + */ +gridProto.containPoint = function (point) { + var coord = this._coordsList[0]; + if (coord) { + return coord.containPoint(point); + } +}; + +/** + * Initialize cartesian coordinate systems + * @private + */ +gridProto._initCartesian = function (gridModel, ecModel, api) { + var axisPositionUsed = { + left: false, + right: false, + top: false, + bottom: false + }; + + var axesMap = { + x: {}, + y: {} + }; + var axesCount = { + x: 0, + y: 0 + }; + + /// Create axis + ecModel.eachComponent('xAxis', createAxisCreator('x'), this); + ecModel.eachComponent('yAxis', createAxisCreator('y'), this); + + if (!axesCount.x || !axesCount.y) { + // Roll back when there no either x or y axis + this._axesMap = {}; + this._axesList = []; + return; + } + + this._axesMap = axesMap; + + /// Create cartesian2d + each$1(axesMap.x, function (xAxis, xAxisIndex) { + each$1(axesMap.y, function (yAxis, yAxisIndex) { + var key = 'x' + xAxisIndex + 'y' + yAxisIndex; + var cartesian = new Cartesian2D(key); + + cartesian.grid = this; + cartesian.model = gridModel; + + this._coordsMap[key] = cartesian; + this._coordsList.push(cartesian); + + cartesian.addAxis(xAxis); + cartesian.addAxis(yAxis); + }, this); + }, this); + + function createAxisCreator(axisType) { + return function (axisModel, idx) { + if (!isAxisUsedInTheGrid(axisModel, gridModel, ecModel)) { + return; + } + + var axisPosition = axisModel.get('position'); + if (axisType === 'x') { + // Fix position + if (axisPosition !== 'top' && axisPosition !== 'bottom') { + // Default bottom of X + axisPosition = 'bottom'; + if (axisPositionUsed[axisPosition]) { + axisPosition = axisPosition === 'top' ? 'bottom' : 'top'; + } + } + } + else { + // Fix position + if (axisPosition !== 'left' && axisPosition !== 'right') { + // Default left of Y + axisPosition = 'left'; + if (axisPositionUsed[axisPosition]) { + axisPosition = axisPosition === 'left' ? 'right' : 'left'; + } + } + } + axisPositionUsed[axisPosition] = true; + + var axis = new Axis2D( + axisType, createScaleByModel(axisModel), + [0, 0], + axisModel.get('type'), + axisPosition + ); + + var isCategory = axis.type === 'category'; + axis.onBand = isCategory && axisModel.get('boundaryGap'); + axis.inverse = axisModel.get('inverse'); + + // Inject axis into axisModel + axisModel.axis = axis; + + // Inject axisModel into axis + axis.model = axisModel; + + // Inject grid info axis + axis.grid = this; + + // Index of axis, can be used as key + axis.index = idx; + + this._axesList.push(axis); + + axesMap[axisType][idx] = axis; + axesCount[axisType]++; + }; + } +}; + +/** + * Update cartesian properties from series + * @param {module:echarts/model/Option} option + * @private + */ +gridProto._updateScale = function (ecModel, gridModel) { + // Reset scale + each$1(this._axesList, function (axis) { + axis.scale.setExtent(Infinity, -Infinity); + }); + ecModel.eachSeries(function (seriesModel) { + if (isCartesian2D(seriesModel)) { + var axesModels = findAxesModels(seriesModel, ecModel); + var xAxisModel = axesModels[0]; + var yAxisModel = axesModels[1]; + + if (!isAxisUsedInTheGrid(xAxisModel, gridModel, ecModel) + || !isAxisUsedInTheGrid(yAxisModel, gridModel, ecModel) + ) { + return; + } + + var cartesian = this.getCartesian( + xAxisModel.componentIndex, yAxisModel.componentIndex + ); + var data = seriesModel.getData(); + var xAxis = cartesian.getAxis('x'); + var yAxis = cartesian.getAxis('y'); + + if (data.type === 'list') { + unionExtent(data, xAxis, seriesModel); + unionExtent(data, yAxis, seriesModel); + } + } + }, this); + + function unionExtent(data, axis, seriesModel) { + each$1(data.mapDimension(axis.dim, true), function (dim) { + axis.scale.unionExtentFromData( + // For example, the extent of the orginal dimension + // is [0.1, 0.5], the extent of the `stackResultDimension` + // is [7, 9], the final extent should not include [0.1, 0.5]. + data, getStackedDimension(data, dim) + ); + }); + } +}; + +/** + * @param {string} [dim] 'x' or 'y' or 'auto' or null/undefined + * @return {Object} {baseAxes: [], otherAxes: []} + */ +gridProto.getTooltipAxes = function (dim) { + var baseAxes = []; + var otherAxes = []; + + each$1(this.getCartesians(), function (cartesian) { + var baseAxis = (dim != null && dim !== 'auto') + ? cartesian.getAxis(dim) : cartesian.getBaseAxis(); + var otherAxis = cartesian.getOtherAxis(baseAxis); + indexOf(baseAxes, baseAxis) < 0 && baseAxes.push(baseAxis); + indexOf(otherAxes, otherAxis) < 0 && otherAxes.push(otherAxis); + }); + + return {baseAxes: baseAxes, otherAxes: otherAxes}; +}; + +/** + * @inner + */ +function updateAxisTransform(axis, coordBase) { + var axisExtent = axis.getExtent(); + var axisExtentSum = axisExtent[0] + axisExtent[1]; + + // Fast transform + axis.toGlobalCoord = axis.dim === 'x' + ? function (coord) { + return coord + coordBase; + } + : function (coord) { + return axisExtentSum - coord + coordBase; + }; + axis.toLocalCoord = axis.dim === 'x' + ? function (coord) { + return coord - coordBase; + } + : function (coord) { + return axisExtentSum - coord + coordBase; + }; +} + +var axesTypes = ['xAxis', 'yAxis']; +/** + * @inner + */ +function findAxesModels(seriesModel, ecModel) { + return map(axesTypes, function (axisType) { + var axisModel = seriesModel.getReferringComponents(axisType)[0]; + + if (__DEV__) { + if (!axisModel) { + throw new Error(axisType + ' "' + retrieve( + seriesModel.get(axisType + 'Index'), + seriesModel.get(axisType + 'Id'), + 0 + ) + '" not found'); + } + } + return axisModel; + }); +} + +/** + * @inner + */ +function isCartesian2D(seriesModel) { + return seriesModel.get('coordinateSystem') === 'cartesian2d'; +} + +Grid.create = function (ecModel, api) { + var grids = []; + ecModel.eachComponent('grid', function (gridModel, idx) { + var grid = new Grid(gridModel, ecModel, api); + grid.name = 'grid_' + idx; + // dataSampling requires axis extent, so resize + // should be performed in create stage. + grid.resize(gridModel, api, true); + + gridModel.coordinateSystem = grid; + + grids.push(grid); + }); + + // Inject the coordinateSystems into seriesModel + ecModel.eachSeries(function (seriesModel) { + if (!isCartesian2D(seriesModel)) { + return; + } + + var axesModels = findAxesModels(seriesModel, ecModel); + var xAxisModel = axesModels[0]; + var yAxisModel = axesModels[1]; + + var gridModel = xAxisModel.getCoordSysModel(); + + if (__DEV__) { + if (!gridModel) { + throw new Error( + 'Grid "' + retrieve( + xAxisModel.get('gridIndex'), + xAxisModel.get('gridId'), + 0 + ) + '" not found' + ); + } + if (xAxisModel.getCoordSysModel() !== yAxisModel.getCoordSysModel()) { + throw new Error('xAxis and yAxis must use the same grid'); + } + } + + var grid = gridModel.coordinateSystem; + + seriesModel.coordinateSystem = grid.getCartesian( + xAxisModel.componentIndex, yAxisModel.componentIndex + ); + }); + + return grids; +}; + +// For deciding which dimensions to use when creating list data +Grid.dimensions = Grid.prototype.dimensions = Cartesian2D.prototype.dimensions; + +CoordinateSystemManager.register('cartesian2d', Grid); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var PI$2 = Math.PI; + +function makeAxisEventDataBase(axisModel) { + var eventData = { + componentType: axisModel.mainType, + componentIndex: axisModel.componentIndex + }; + eventData[axisModel.mainType + 'Index'] = axisModel.componentIndex; + return eventData; +} + +/** + * A final axis is translated and rotated from a "standard axis". + * So opt.position and opt.rotation is required. + * + * A standard axis is and axis from [0, 0] to [0, axisExtent[1]], + * for example: (0, 0) ------------> (0, 50) + * + * nameDirection or tickDirection or labelDirection is 1 means tick + * or label is below the standard axis, whereas is -1 means above + * the standard axis. labelOffset means offset between label and axis, + * which is useful when 'onZero', where axisLabel is in the grid and + * label in outside grid. + * + * Tips: like always, + * positive rotation represents anticlockwise, and negative rotation + * represents clockwise. + * The direction of position coordinate is the same as the direction + * of screen coordinate. + * + * Do not need to consider axis 'inverse', which is auto processed by + * axis extent. + * + * @param {module:zrender/container/Group} group + * @param {Object} axisModel + * @param {Object} opt Standard axis parameters. + * @param {Array.} opt.position [x, y] + * @param {number} opt.rotation by radian + * @param {number} [opt.nameDirection=1] 1 or -1 Used when nameLocation is 'middle' or 'center'. + * @param {number} [opt.tickDirection=1] 1 or -1 + * @param {number} [opt.labelDirection=1] 1 or -1 + * @param {number} [opt.labelOffset=0] Usefull when onZero. + * @param {string} [opt.axisLabelShow] default get from axisModel. + * @param {string} [opt.axisName] default get from axisModel. + * @param {number} [opt.axisNameAvailableWidth] + * @param {number} [opt.labelRotate] by degree, default get from axisModel. + * @param {number} [opt.strokeContainThreshold] Default label interval when label + * @param {number} [opt.nameTruncateMaxWidth] + */ +var AxisBuilder = function (axisModel, opt) { + + /** + * @readOnly + */ + this.opt = opt; + + /** + * @readOnly + */ + this.axisModel = axisModel; + + // Default value + defaults( + opt, + { + labelOffset: 0, + nameDirection: 1, + tickDirection: 1, + labelDirection: 1, + silent: true + } + ); + + /** + * @readOnly + */ + this.group = new Group(); + + // FIXME Not use a seperate text group? + var dumbGroup = new Group({ + position: opt.position.slice(), + rotation: opt.rotation + }); + + // this.group.add(dumbGroup); + // this._dumbGroup = dumbGroup; + + dumbGroup.updateTransform(); + this._transform = dumbGroup.transform; + + this._dumbGroup = dumbGroup; +}; + +AxisBuilder.prototype = { + + constructor: AxisBuilder, + + hasBuilder: function (name) { + return !!builders[name]; + }, + + add: function (name) { + builders[name].call(this); + }, + + getGroup: function () { + return this.group; + } + +}; + +var builders = { + + /** + * @private + */ + axisLine: function () { + var opt = this.opt; + var axisModel = this.axisModel; + + if (!axisModel.get('axisLine.show')) { + return; + } + + var extent = this.axisModel.axis.getExtent(); + + var matrix = this._transform; + var pt1 = [extent[0], 0]; + var pt2 = [extent[1], 0]; + if (matrix) { + applyTransform(pt1, pt1, matrix); + applyTransform(pt2, pt2, matrix); + } + + var lineStyle = extend( + { + lineCap: 'round' + }, + axisModel.getModel('axisLine.lineStyle').getLineStyle() + ); + + this.group.add(new Line(subPixelOptimizeLine({ + // Id for animation + anid: 'line', + + shape: { + x1: pt1[0], + y1: pt1[1], + x2: pt2[0], + y2: pt2[1] + }, + style: lineStyle, + strokeContainThreshold: opt.strokeContainThreshold || 5, + silent: true, + z2: 1 + }))); + + var arrows = axisModel.get('axisLine.symbol'); + var arrowSize = axisModel.get('axisLine.symbolSize'); + + var arrowOffset = axisModel.get('axisLine.symbolOffset') || 0; + if (typeof arrowOffset === 'number') { + arrowOffset = [arrowOffset, arrowOffset]; + } + + if (arrows != null) { + if (typeof arrows === 'string') { + // Use the same arrow for start and end point + arrows = [arrows, arrows]; + } + if (typeof arrowSize === 'string' + || typeof arrowSize === 'number' + ) { + // Use the same size for width and height + arrowSize = [arrowSize, arrowSize]; + } + + var symbolWidth = arrowSize[0]; + var symbolHeight = arrowSize[1]; + + each$1([{ + rotate: opt.rotation + Math.PI / 2, + offset: arrowOffset[0], + r: 0 + }, { + rotate: opt.rotation - Math.PI / 2, + offset: arrowOffset[1], + r: Math.sqrt((pt1[0] - pt2[0]) * (pt1[0] - pt2[0]) + + (pt1[1] - pt2[1]) * (pt1[1] - pt2[1])) + }], function (point, index) { + if (arrows[index] !== 'none' && arrows[index] != null) { + var symbol = createSymbol( + arrows[index], + -symbolWidth / 2, + -symbolHeight / 2, + symbolWidth, + symbolHeight, + lineStyle.stroke, + true + ); + + // Calculate arrow position with offset + var r = point.r + point.offset; + var pos = [ + pt1[0] + r * Math.cos(opt.rotation), + pt1[1] - r * Math.sin(opt.rotation) + ]; + + symbol.attr({ + rotation: point.rotate, + position: pos, + silent: true, + z2: 11 + }); + this.group.add(symbol); + } + }, this); + } + }, + + /** + * @private + */ + axisTickLabel: function () { + var axisModel = this.axisModel; + var opt = this.opt; + + var tickEls = buildAxisTick(this, axisModel, opt); + var labelEls = buildAxisLabel(this, axisModel, opt); + + fixMinMaxLabelShow(axisModel, labelEls, tickEls); + }, + + /** + * @private + */ + axisName: function () { + var opt = this.opt; + var axisModel = this.axisModel; + var name = retrieve(opt.axisName, axisModel.get('name')); + + if (!name) { + return; + } + + var nameLocation = axisModel.get('nameLocation'); + var nameDirection = opt.nameDirection; + var textStyleModel = axisModel.getModel('nameTextStyle'); + var gap = axisModel.get('nameGap') || 0; + + var extent = this.axisModel.axis.getExtent(); + var gapSignal = extent[0] > extent[1] ? -1 : 1; + var pos = [ + nameLocation === 'start' + ? extent[0] - gapSignal * gap + : nameLocation === 'end' + ? extent[1] + gapSignal * gap + : (extent[0] + extent[1]) / 2, // 'middle' + // Reuse labelOffset. + isNameLocationCenter(nameLocation) ? opt.labelOffset + nameDirection * gap : 0 + ]; + + var labelLayout; + + var nameRotation = axisModel.get('nameRotate'); + if (nameRotation != null) { + nameRotation = nameRotation * PI$2 / 180; // To radian. + } + + var axisNameAvailableWidth; + + if (isNameLocationCenter(nameLocation)) { + labelLayout = innerTextLayout( + opt.rotation, + nameRotation != null ? nameRotation : opt.rotation, // Adapt to axis. + nameDirection + ); + } + else { + labelLayout = endTextLayout( + opt, nameLocation, nameRotation || 0, extent + ); + + axisNameAvailableWidth = opt.axisNameAvailableWidth; + if (axisNameAvailableWidth != null) { + axisNameAvailableWidth = Math.abs( + axisNameAvailableWidth / Math.sin(labelLayout.rotation) + ); + !isFinite(axisNameAvailableWidth) && (axisNameAvailableWidth = null); + } + } + + var textFont = textStyleModel.getFont(); + + var truncateOpt = axisModel.get('nameTruncate', true) || {}; + var ellipsis = truncateOpt.ellipsis; + var maxWidth = retrieve( + opt.nameTruncateMaxWidth, truncateOpt.maxWidth, axisNameAvailableWidth + ); + // FIXME + // truncate rich text? (consider performance) + var truncatedText = (ellipsis != null && maxWidth != null) + ? truncateText$1( + name, maxWidth, textFont, ellipsis, + {minChar: 2, placeholder: truncateOpt.placeholder} + ) + : name; + + var tooltipOpt = axisModel.get('tooltip', true); + + var mainType = axisModel.mainType; + var formatterParams = { + componentType: mainType, + name: name, + $vars: ['name'] + }; + formatterParams[mainType + 'Index'] = axisModel.componentIndex; + + var textEl = new Text({ + // Id for animation + anid: 'name', + + __fullText: name, + __truncatedText: truncatedText, + + position: pos, + rotation: labelLayout.rotation, + silent: isSilent(axisModel), + z2: 1, + tooltip: (tooltipOpt && tooltipOpt.show) + ? extend({ + content: name, + formatter: function () { + return name; + }, + formatterParams: formatterParams + }, tooltipOpt) + : null + }); + + setTextStyle(textEl.style, textStyleModel, { + text: truncatedText, + textFont: textFont, + textFill: textStyleModel.getTextColor() + || axisModel.get('axisLine.lineStyle.color'), + textAlign: labelLayout.textAlign, + textVerticalAlign: labelLayout.textVerticalAlign + }); + + if (axisModel.get('triggerEvent')) { + textEl.eventData = makeAxisEventDataBase(axisModel); + textEl.eventData.targetType = 'axisName'; + textEl.eventData.name = name; + } + + // FIXME + this._dumbGroup.add(textEl); + textEl.updateTransform(); + + this.group.add(textEl); + + textEl.decomposeTransform(); + } + +}; + +/** + * @public + * @static + * @param {Object} opt + * @param {number} axisRotation in radian + * @param {number} textRotation in radian + * @param {number} direction + * @return {Object} { + * rotation, // according to axis + * textAlign, + * textVerticalAlign + * } + */ +var innerTextLayout = AxisBuilder.innerTextLayout = function (axisRotation, textRotation, direction) { + var rotationDiff = remRadian(textRotation - axisRotation); + var textAlign; + var textVerticalAlign; + + if (isRadianAroundZero(rotationDiff)) { // Label is parallel with axis line. + textVerticalAlign = direction > 0 ? 'top' : 'bottom'; + textAlign = 'center'; + } + else if (isRadianAroundZero(rotationDiff - PI$2)) { // Label is inverse parallel with axis line. + textVerticalAlign = direction > 0 ? 'bottom' : 'top'; + textAlign = 'center'; + } + else { + textVerticalAlign = 'middle'; + + if (rotationDiff > 0 && rotationDiff < PI$2) { + textAlign = direction > 0 ? 'right' : 'left'; + } + else { + textAlign = direction > 0 ? 'left' : 'right'; + } + } + + return { + rotation: rotationDiff, + textAlign: textAlign, + textVerticalAlign: textVerticalAlign + }; +}; + +function endTextLayout(opt, textPosition, textRotate, extent) { + var rotationDiff = remRadian(textRotate - opt.rotation); + var textAlign; + var textVerticalAlign; + var inverse = extent[0] > extent[1]; + var onLeft = (textPosition === 'start' && !inverse) + || (textPosition !== 'start' && inverse); + + if (isRadianAroundZero(rotationDiff - PI$2 / 2)) { + textVerticalAlign = onLeft ? 'bottom' : 'top'; + textAlign = 'center'; + } + else if (isRadianAroundZero(rotationDiff - PI$2 * 1.5)) { + textVerticalAlign = onLeft ? 'top' : 'bottom'; + textAlign = 'center'; + } + else { + textVerticalAlign = 'middle'; + if (rotationDiff < PI$2 * 1.5 && rotationDiff > PI$2 / 2) { + textAlign = onLeft ? 'left' : 'right'; + } + else { + textAlign = onLeft ? 'right' : 'left'; + } + } + + return { + rotation: rotationDiff, + textAlign: textAlign, + textVerticalAlign: textVerticalAlign + }; +} + +function isSilent(axisModel) { + var tooltipOpt = axisModel.get('tooltip'); + return axisModel.get('silent') + // Consider mouse cursor, add these restrictions. + || !( + axisModel.get('triggerEvent') || (tooltipOpt && tooltipOpt.show) + ); +} + +function fixMinMaxLabelShow(axisModel, labelEls, tickEls) { + if (shouldShowAllLabels(axisModel.axis)) { + return; + } + + // If min or max are user set, we need to check + // If the tick on min(max) are overlap on their neighbour tick + // If they are overlapped, we need to hide the min(max) tick label + var showMinLabel = axisModel.get('axisLabel.showMinLabel'); + var showMaxLabel = axisModel.get('axisLabel.showMaxLabel'); + + // FIXME + // Have not consider onBand yet, where tick els is more than label els. + + labelEls = labelEls || []; + tickEls = tickEls || []; + + var firstLabel = labelEls[0]; + var nextLabel = labelEls[1]; + var lastLabel = labelEls[labelEls.length - 1]; + var prevLabel = labelEls[labelEls.length - 2]; + + var firstTick = tickEls[0]; + var nextTick = tickEls[1]; + var lastTick = tickEls[tickEls.length - 1]; + var prevTick = tickEls[tickEls.length - 2]; + + if (showMinLabel === false) { + ignoreEl(firstLabel); + ignoreEl(firstTick); + } + else if (isTwoLabelOverlapped(firstLabel, nextLabel)) { + if (showMinLabel) { + ignoreEl(nextLabel); + ignoreEl(nextTick); + } + else { + ignoreEl(firstLabel); + ignoreEl(firstTick); + } + } + + if (showMaxLabel === false) { + ignoreEl(lastLabel); + ignoreEl(lastTick); + } + else if (isTwoLabelOverlapped(prevLabel, lastLabel)) { + if (showMaxLabel) { + ignoreEl(prevLabel); + ignoreEl(prevTick); + } + else { + ignoreEl(lastLabel); + ignoreEl(lastTick); + } + } +} + +function ignoreEl(el) { + el && (el.ignore = true); +} + +function isTwoLabelOverlapped(current, next, labelLayout) { + // current and next has the same rotation. + var firstRect = current && current.getBoundingRect().clone(); + var nextRect = next && next.getBoundingRect().clone(); + + if (!firstRect || !nextRect) { + return; + } + + // When checking intersect of two rotated labels, we use mRotationBack + // to avoid that boundingRect is enlarge when using `boundingRect.applyTransform`. + var mRotationBack = identity([]); + rotate(mRotationBack, mRotationBack, -current.rotation); + + firstRect.applyTransform(mul$1([], mRotationBack, current.getLocalTransform())); + nextRect.applyTransform(mul$1([], mRotationBack, next.getLocalTransform())); + + return firstRect.intersect(nextRect); +} + +function isNameLocationCenter(nameLocation) { + return nameLocation === 'middle' || nameLocation === 'center'; +} + +function buildAxisTick(axisBuilder, axisModel, opt) { + var axis = axisModel.axis; + + if (!axisModel.get('axisTick.show') || axis.scale.isBlank()) { + return; + } + + var tickModel = axisModel.getModel('axisTick'); + + var lineStyleModel = tickModel.getModel('lineStyle'); + var tickLen = tickModel.get('length'); + + var ticksCoords = axis.getTicksCoords(); + + var pt1 = []; + var pt2 = []; + var matrix = axisBuilder._transform; + + var tickEls = []; + + for (var i = 0; i < ticksCoords.length; i++) { + var tickCoord = ticksCoords[i].coord; + + pt1[0] = tickCoord; + pt1[1] = 0; + pt2[0] = tickCoord; + pt2[1] = opt.tickDirection * tickLen; + + if (matrix) { + applyTransform(pt1, pt1, matrix); + applyTransform(pt2, pt2, matrix); + } + // Tick line, Not use group transform to have better line draw + var tickEl = new Line(subPixelOptimizeLine({ + // Id for animation + anid: 'tick_' + ticksCoords[i].tickValue, + + shape: { + x1: pt1[0], + y1: pt1[1], + x2: pt2[0], + y2: pt2[1] + }, + style: defaults( + lineStyleModel.getLineStyle(), + { + stroke: axisModel.get('axisLine.lineStyle.color') + } + ), + z2: 2, + silent: true + })); + axisBuilder.group.add(tickEl); + tickEls.push(tickEl); + } + + return tickEls; +} + +function buildAxisLabel(axisBuilder, axisModel, opt) { + var axis = axisModel.axis; + var show = retrieve(opt.axisLabelShow, axisModel.get('axisLabel.show')); + + if (!show || axis.scale.isBlank()) { + return; + } + + var labelModel = axisModel.getModel('axisLabel'); + var labelMargin = labelModel.get('margin'); + var labels = axis.getViewLabels(); + + // Special label rotate. + var labelRotation = ( + retrieve(opt.labelRotate, labelModel.get('rotate')) || 0 + ) * PI$2 / 180; + + var labelLayout = innerTextLayout(opt.rotation, labelRotation, opt.labelDirection); + var rawCategoryData = axisModel.getCategories(true); + + var labelEls = []; + var silent = isSilent(axisModel); + var triggerEvent = axisModel.get('triggerEvent'); + + each$1(labels, function (labelItem, index) { + var tickValue = labelItem.tickValue; + var formattedLabel = labelItem.formattedLabel; + var rawLabel = labelItem.rawLabel; + + var itemLabelModel = labelModel; + if (rawCategoryData && rawCategoryData[tickValue] && rawCategoryData[tickValue].textStyle) { + itemLabelModel = new Model( + rawCategoryData[tickValue].textStyle, labelModel, axisModel.ecModel + ); + } + + var textColor = itemLabelModel.getTextColor() + || axisModel.get('axisLine.lineStyle.color'); + + var tickCoord = axis.dataToCoord(tickValue); + var pos = [ + tickCoord, + opt.labelOffset + opt.labelDirection * labelMargin + ]; + + var textEl = new Text({ + // Id for animation + anid: 'label_' + tickValue, + position: pos, + rotation: labelLayout.rotation, + silent: silent, + z2: 10 + }); + + setTextStyle(textEl.style, itemLabelModel, { + text: formattedLabel, + textAlign: itemLabelModel.getShallow('align', true) + || labelLayout.textAlign, + textVerticalAlign: itemLabelModel.getShallow('verticalAlign', true) + || itemLabelModel.getShallow('baseline', true) + || labelLayout.textVerticalAlign, + textFill: typeof textColor === 'function' + ? textColor( + // (1) In category axis with data zoom, tick is not the original + // index of axis.data. So tick should not be exposed to user + // in category axis. + // (2) Compatible with previous version, which always use formatted label as + // input. But in interval scale the formatted label is like '223,445', which + // maked user repalce ','. So we modify it to return original val but remain + // it as 'string' to avoid error in replacing. + axis.type === 'category' + ? rawLabel + : axis.type === 'value' + ? tickValue + '' + : tickValue, + index + ) + : textColor + }); + + // Pack data for mouse event + if (triggerEvent) { + textEl.eventData = makeAxisEventDataBase(axisModel); + textEl.eventData.targetType = 'axisLabel'; + textEl.eventData.value = rawLabel; + } + + // FIXME + axisBuilder._dumbGroup.add(textEl); + textEl.updateTransform(); + + labelEls.push(textEl); + axisBuilder.group.add(textEl); + + textEl.decomposeTransform(); + + }); + + return labelEls; +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var each$6 = each$1; +var curry$1 = curry; + +// Build axisPointerModel, mergin tooltip.axisPointer model for each axis. +// allAxesInfo should be updated when setOption performed. +function collect(ecModel, api) { + var result = { + /** + * key: makeKey(axis.model) + * value: { + * axis, + * coordSys, + * axisPointerModel, + * triggerTooltip, + * involveSeries, + * snap, + * seriesModels, + * seriesDataCount + * } + */ + axesInfo: {}, + seriesInvolved: false, + /** + * key: makeKey(coordSys.model) + * value: Object: key makeKey(axis.model), value: axisInfo + */ + coordSysAxesInfo: {}, + coordSysMap: {} + }; + + collectAxesInfo(result, ecModel, api); + + // Check seriesInvolved for performance, in case too many series in some chart. + result.seriesInvolved && collectSeriesInfo(result, ecModel); + + return result; +} + +function collectAxesInfo(result, ecModel, api) { + var globalTooltipModel = ecModel.getComponent('tooltip'); + var globalAxisPointerModel = ecModel.getComponent('axisPointer'); + // links can only be set on global. + var linksOption = globalAxisPointerModel.get('link', true) || []; + var linkGroups = []; + + // Collect axes info. + each$6(api.getCoordinateSystems(), function (coordSys) { + // Some coordinate system do not support axes, like geo. + if (!coordSys.axisPointerEnabled) { + return; + } + + var coordSysKey = makeKey(coordSys.model); + var axesInfoInCoordSys = result.coordSysAxesInfo[coordSysKey] = {}; + result.coordSysMap[coordSysKey] = coordSys; + + // Set tooltip (like 'cross') is a convienent way to show axisPointer + // for user. So we enable seting tooltip on coordSys model. + var coordSysModel = coordSys.model; + var baseTooltipModel = coordSysModel.getModel('tooltip', globalTooltipModel); + + each$6(coordSys.getAxes(), curry$1(saveTooltipAxisInfo, false, null)); + + // If axis tooltip used, choose tooltip axis for each coordSys. + // Notice this case: coordSys is `grid` but not `cartesian2D` here. + if (coordSys.getTooltipAxes + && globalTooltipModel + // If tooltip.showContent is set as false, tooltip will not + // show but axisPointer will show as normal. + && baseTooltipModel.get('show') + ) { + // Compatible with previous logic. But series.tooltip.trigger: 'axis' + // or series.data[n].tooltip.trigger: 'axis' are not support any more. + var triggerAxis = baseTooltipModel.get('trigger') === 'axis'; + var cross = baseTooltipModel.get('axisPointer.type') === 'cross'; + var tooltipAxes = coordSys.getTooltipAxes(baseTooltipModel.get('axisPointer.axis')); + if (triggerAxis || cross) { + each$6(tooltipAxes.baseAxes, curry$1( + saveTooltipAxisInfo, cross ? 'cross' : true, triggerAxis + )); + } + if (cross) { + each$6(tooltipAxes.otherAxes, curry$1(saveTooltipAxisInfo, 'cross', false)); + } + } + + // fromTooltip: true | false | 'cross' + // triggerTooltip: true | false | null + function saveTooltipAxisInfo(fromTooltip, triggerTooltip, axis) { + var axisPointerModel = axis.model.getModel('axisPointer', globalAxisPointerModel); + + var axisPointerShow = axisPointerModel.get('show'); + if (!axisPointerShow || ( + axisPointerShow === 'auto' + && !fromTooltip + && !isHandleTrigger(axisPointerModel) + )) { + return; + } + + if (triggerTooltip == null) { + triggerTooltip = axisPointerModel.get('triggerTooltip'); + } + + axisPointerModel = fromTooltip + ? makeAxisPointerModel( + axis, baseTooltipModel, globalAxisPointerModel, ecModel, + fromTooltip, triggerTooltip + ) + : axisPointerModel; + + var snap = axisPointerModel.get('snap'); + var key = makeKey(axis.model); + var involveSeries = triggerTooltip || snap || axis.type === 'category'; + + // If result.axesInfo[key] exist, override it (tooltip has higher priority). + var axisInfo = result.axesInfo[key] = { + key: key, + axis: axis, + coordSys: coordSys, + axisPointerModel: axisPointerModel, + triggerTooltip: triggerTooltip, + involveSeries: involveSeries, + snap: snap, + useHandle: isHandleTrigger(axisPointerModel), + seriesModels: [] + }; + axesInfoInCoordSys[key] = axisInfo; + result.seriesInvolved |= involveSeries; + + var groupIndex = getLinkGroupIndex(linksOption, axis); + if (groupIndex != null) { + var linkGroup = linkGroups[groupIndex] || (linkGroups[groupIndex] = {axesInfo: {}}); + linkGroup.axesInfo[key] = axisInfo; + linkGroup.mapper = linksOption[groupIndex].mapper; + axisInfo.linkGroup = linkGroup; + } + } + }); +} + +function makeAxisPointerModel( + axis, baseTooltipModel, globalAxisPointerModel, ecModel, fromTooltip, triggerTooltip +) { + var tooltipAxisPointerModel = baseTooltipModel.getModel('axisPointer'); + var volatileOption = {}; + + each$6( + [ + 'type', 'snap', 'lineStyle', 'shadowStyle', 'label', + 'animation', 'animationDurationUpdate', 'animationEasingUpdate', 'z' + ], + function (field) { + volatileOption[field] = clone(tooltipAxisPointerModel.get(field)); + } + ); + + // category axis do not auto snap, otherwise some tick that do not + // has value can not be hovered. value/time/log axis default snap if + // triggered from tooltip and trigger tooltip. + volatileOption.snap = axis.type !== 'category' && !!triggerTooltip; + + // Compatibel with previous behavior, tooltip axis do not show label by default. + // Only these properties can be overrided from tooltip to axisPointer. + if (tooltipAxisPointerModel.get('type') === 'cross') { + volatileOption.type = 'line'; + } + var labelOption = volatileOption.label || (volatileOption.label = {}); + // Follow the convention, do not show label when triggered by tooltip by default. + labelOption.show == null && (labelOption.show = false); + + if (fromTooltip === 'cross') { + // When 'cross', both axes show labels. + var tooltipAxisPointerLabelShow = tooltipAxisPointerModel.get('label.show'); + labelOption.show = tooltipAxisPointerLabelShow != null ? tooltipAxisPointerLabelShow : true; + // If triggerTooltip, this is a base axis, which should better not use cross style + // (cross style is dashed by default) + if (!triggerTooltip) { + var crossStyle = volatileOption.lineStyle = tooltipAxisPointerModel.get('crossStyle'); + crossStyle && defaults(labelOption, crossStyle.textStyle); + } + } + + return axis.model.getModel( + 'axisPointer', + new Model(volatileOption, globalAxisPointerModel, ecModel) + ); +} + +function collectSeriesInfo(result, ecModel) { + // Prepare data for axis trigger + ecModel.eachSeries(function (seriesModel) { + + // Notice this case: this coordSys is `cartesian2D` but not `grid`. + var coordSys = seriesModel.coordinateSystem; + var seriesTooltipTrigger = seriesModel.get('tooltip.trigger', true); + var seriesTooltipShow = seriesModel.get('tooltip.show', true); + if (!coordSys + || seriesTooltipTrigger === 'none' + || seriesTooltipTrigger === false + || seriesTooltipTrigger === 'item' + || seriesTooltipShow === false + || seriesModel.get('axisPointer.show', true) === false + ) { + return; + } + + each$6(result.coordSysAxesInfo[makeKey(coordSys.model)], function (axisInfo) { + var axis = axisInfo.axis; + if (coordSys.getAxis(axis.dim) === axis) { + axisInfo.seriesModels.push(seriesModel); + axisInfo.seriesDataCount == null && (axisInfo.seriesDataCount = 0); + axisInfo.seriesDataCount += seriesModel.getData().count(); + } + }); + + }, this); +} + +/** + * For example: + * { + * axisPointer: { + * links: [{ + * xAxisIndex: [2, 4], + * yAxisIndex: 'all' + * }, { + * xAxisId: ['a5', 'a7'], + * xAxisName: 'xxx' + * }] + * } + * } + */ +function getLinkGroupIndex(linksOption, axis) { + var axisModel = axis.model; + var dim = axis.dim; + for (var i = 0; i < linksOption.length; i++) { + var linkOption = linksOption[i] || {}; + if (checkPropInLink(linkOption[dim + 'AxisId'], axisModel.id) + || checkPropInLink(linkOption[dim + 'AxisIndex'], axisModel.componentIndex) + || checkPropInLink(linkOption[dim + 'AxisName'], axisModel.name) + ) { + return i; + } + } +} + +function checkPropInLink(linkPropValue, axisPropValue) { + return linkPropValue === 'all' + || (isArray(linkPropValue) && indexOf(linkPropValue, axisPropValue) >= 0) + || linkPropValue === axisPropValue; +} + +function fixValue(axisModel) { + var axisInfo = getAxisInfo(axisModel); + if (!axisInfo) { + return; + } + + var axisPointerModel = axisInfo.axisPointerModel; + var scale = axisInfo.axis.scale; + var option = axisPointerModel.option; + var status = axisPointerModel.get('status'); + var value = axisPointerModel.get('value'); + + // Parse init value for category and time axis. + if (value != null) { + value = scale.parse(value); + } + + var useHandle = isHandleTrigger(axisPointerModel); + // If `handle` used, `axisPointer` will always be displayed, so value + // and status should be initialized. + if (status == null) { + option.status = useHandle ? 'show' : 'hide'; + } + + var extent = scale.getExtent().slice(); + extent[0] > extent[1] && extent.reverse(); + + if (// Pick a value on axis when initializing. + value == null + // If both `handle` and `dataZoom` are used, value may be out of axis extent, + // where we should re-pick a value to keep `handle` displaying normally. + || value > extent[1] + ) { + // Make handle displayed on the end of the axis when init, which looks better. + value = extent[1]; + } + if (value < extent[0]) { + value = extent[0]; + } + + option.value = value; + + if (useHandle) { + option.status = axisInfo.axis.scale.isBlank() ? 'hide' : 'show'; + } +} + +function getAxisInfo(axisModel) { + var coordSysAxesInfo = (axisModel.ecModel.getComponent('axisPointer') || {}).coordSysAxesInfo; + return coordSysAxesInfo && coordSysAxesInfo.axesInfo[makeKey(axisModel)]; +} + +function getAxisPointerModel(axisModel) { + var axisInfo = getAxisInfo(axisModel); + return axisInfo && axisInfo.axisPointerModel; +} + +function isHandleTrigger(axisPointerModel) { + return !!axisPointerModel.get('handle.show'); +} + +/** + * @param {module:echarts/model/Model} model + * @return {string} unique key + */ +function makeKey(model) { + return model.type + '||' + model.id; +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/** + * Base class of AxisView. + */ +var AxisView = extendComponentView({ + + type: 'axis', + + /** + * @private + */ + _axisPointer: null, + + /** + * @protected + * @type {string} + */ + axisPointerClass: null, + + /** + * @override + */ + render: function (axisModel, ecModel, api, payload) { + // FIXME + // This process should proformed after coordinate systems updated + // (axis scale updated), and should be performed each time update. + // So put it here temporarily, although it is not appropriate to + // put a model-writing procedure in `view`. + this.axisPointerClass && fixValue(axisModel); + + AxisView.superApply(this, 'render', arguments); + + updateAxisPointer(this, axisModel, ecModel, api, payload, true); + }, + + /** + * Action handler. + * @public + * @param {module:echarts/coord/cartesian/AxisModel} axisModel + * @param {module:echarts/model/Global} ecModel + * @param {module:echarts/ExtensionAPI} api + * @param {Object} payload + */ + updateAxisPointer: function (axisModel, ecModel, api, payload, force) { + updateAxisPointer(this, axisModel, ecModel, api, payload, false); + }, + + /** + * @override + */ + remove: function (ecModel, api) { + var axisPointer = this._axisPointer; + axisPointer && axisPointer.remove(api); + AxisView.superApply(this, 'remove', arguments); + }, + + /** + * @override + */ + dispose: function (ecModel, api) { + disposeAxisPointer(this, api); + AxisView.superApply(this, 'dispose', arguments); + } + +}); + +function updateAxisPointer(axisView, axisModel, ecModel, api, payload, forceRender) { + var Clazz = AxisView.getAxisPointerClass(axisView.axisPointerClass); + if (!Clazz) { + return; + } + var axisPointerModel = getAxisPointerModel(axisModel); + axisPointerModel + ? (axisView._axisPointer || (axisView._axisPointer = new Clazz())) + .render(axisModel, axisPointerModel, api, forceRender) + : disposeAxisPointer(axisView, api); +} + +function disposeAxisPointer(axisView, ecModel, api) { + var axisPointer = axisView._axisPointer; + axisPointer && axisPointer.dispose(ecModel, api); + axisView._axisPointer = null; +} + +var axisPointerClazz = []; + +AxisView.registerAxisPointerClass = function (type, clazz) { + if (__DEV__) { + if (axisPointerClazz[type]) { + throw new Error('axisPointer ' + type + ' exists'); + } + } + axisPointerClazz[type] = clazz; +}; + +AxisView.getAxisPointerClass = function (type) { + return type && axisPointerClazz[type]; +}; + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/** + * Can only be called after coordinate system creation stage. + * (Can be called before coordinate system update stage). + * + * @param {Object} opt {labelInside} + * @return {Object} { + * position, rotation, labelDirection, labelOffset, + * tickDirection, labelRotate, z2 + * } + */ +function layout$1(gridModel, axisModel, opt) { + opt = opt || {}; + var grid = gridModel.coordinateSystem; + var axis = axisModel.axis; + var layout = {}; + var otherAxisOnZeroOf = axis.getAxesOnZeroOf()[0]; + + var rawAxisPosition = axis.position; + var axisPosition = otherAxisOnZeroOf ? 'onZero' : rawAxisPosition; + var axisDim = axis.dim; + + var rect = grid.getRect(); + var rectBound = [rect.x, rect.x + rect.width, rect.y, rect.y + rect.height]; + var idx = {left: 0, right: 1, top: 0, bottom: 1, onZero: 2}; + var axisOffset = axisModel.get('offset') || 0; + + var posBound = axisDim === 'x' + ? [rectBound[2] - axisOffset, rectBound[3] + axisOffset] + : [rectBound[0] - axisOffset, rectBound[1] + axisOffset]; + + if (otherAxisOnZeroOf) { + var onZeroCoord = otherAxisOnZeroOf.toGlobalCoord(otherAxisOnZeroOf.dataToCoord(0)); + posBound[idx.onZero] = Math.max(Math.min(onZeroCoord, posBound[1]), posBound[0]); + } + + // Axis position + layout.position = [ + axisDim === 'y' ? posBound[idx[axisPosition]] : rectBound[0], + axisDim === 'x' ? posBound[idx[axisPosition]] : rectBound[3] + ]; + + // Axis rotation + layout.rotation = Math.PI / 2 * (axisDim === 'x' ? 0 : 1); + + // Tick and label direction, x y is axisDim + var dirMap = {top: -1, bottom: 1, left: -1, right: 1}; + + layout.labelDirection = layout.tickDirection = layout.nameDirection = dirMap[rawAxisPosition]; + layout.labelOffset = otherAxisOnZeroOf ? posBound[idx[rawAxisPosition]] - posBound[idx.onZero] : 0; + + if (axisModel.get('axisTick.inside')) { + layout.tickDirection = -layout.tickDirection; + } + if (retrieve(opt.labelInside, axisModel.get('axisLabel.inside'))) { + layout.labelDirection = -layout.labelDirection; + } + + // Special label rotation + var labelRotate = axisModel.get('axisLabel.rotate'); + layout.labelRotate = axisPosition === 'top' ? -labelRotate : labelRotate; + + // Over splitLine and splitArea + layout.z2 = 1; + + return layout; +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var axisBuilderAttrs = [ + 'axisLine', 'axisTickLabel', 'axisName' +]; +var selfBuilderAttrs = [ + 'splitArea', 'splitLine' +]; + +// function getAlignWithLabel(model, axisModel) { +// var alignWithLabel = model.get('alignWithLabel'); +// if (alignWithLabel === 'auto') { +// alignWithLabel = axisModel.get('axisTick.alignWithLabel'); +// } +// return alignWithLabel; +// } + +var CartesianAxisView = AxisView.extend({ + + type: 'cartesianAxis', + + axisPointerClass: 'CartesianAxisPointer', + + /** + * @override + */ + render: function (axisModel, ecModel, api, payload) { + + this.group.removeAll(); + + var oldAxisGroup = this._axisGroup; + this._axisGroup = new Group(); + + this.group.add(this._axisGroup); + + if (!axisModel.get('show')) { + return; + } + + var gridModel = axisModel.getCoordSysModel(); + + var layout = layout$1(gridModel, axisModel); + + var axisBuilder = new AxisBuilder(axisModel, layout); + + each$1(axisBuilderAttrs, axisBuilder.add, axisBuilder); + + this._axisGroup.add(axisBuilder.getGroup()); + + each$1(selfBuilderAttrs, function (name) { + if (axisModel.get(name + '.show')) { + this['_' + name](axisModel, gridModel); + } + }, this); + + groupTransition(oldAxisGroup, this._axisGroup, axisModel); + + CartesianAxisView.superCall(this, 'render', axisModel, ecModel, api, payload); + }, + + remove: function () { + this._splitAreaColors = null; + }, + + /** + * @param {module:echarts/coord/cartesian/AxisModel} axisModel + * @param {module:echarts/coord/cartesian/GridModel} gridModel + * @private + */ + _splitLine: function (axisModel, gridModel) { + var axis = axisModel.axis; + + if (axis.scale.isBlank()) { + return; + } + + var splitLineModel = axisModel.getModel('splitLine'); + var lineStyleModel = splitLineModel.getModel('lineStyle'); + var lineColors = lineStyleModel.get('color'); + + lineColors = isArray(lineColors) ? lineColors : [lineColors]; + + var gridRect = gridModel.coordinateSystem.getRect(); + var isHorizontal = axis.isHorizontal(); + + var lineCount = 0; + + var ticksCoords = axis.getTicksCoords({ + tickModel: splitLineModel + }); + + var p1 = []; + var p2 = []; + + // Simple optimization + // Batching the lines if color are the same + var lineStyle = lineStyleModel.getLineStyle(); + for (var i = 0; i < ticksCoords.length; i++) { + var tickCoord = axis.toGlobalCoord(ticksCoords[i].coord); + + if (isHorizontal) { + p1[0] = tickCoord; + p1[1] = gridRect.y; + p2[0] = tickCoord; + p2[1] = gridRect.y + gridRect.height; + } + else { + p1[0] = gridRect.x; + p1[1] = tickCoord; + p2[0] = gridRect.x + gridRect.width; + p2[1] = tickCoord; + } + + var colorIndex = (lineCount++) % lineColors.length; + var tickValue = ticksCoords[i].tickValue; + this._axisGroup.add(new Line(subPixelOptimizeLine({ + anid: tickValue != null ? 'line_' + ticksCoords[i].tickValue : null, + shape: { + x1: p1[0], + y1: p1[1], + x2: p2[0], + y2: p2[1] + }, + style: defaults({ + stroke: lineColors[colorIndex] + }, lineStyle), + silent: true + }))); + } + }, + + /** + * @param {module:echarts/coord/cartesian/AxisModel} axisModel + * @param {module:echarts/coord/cartesian/GridModel} gridModel + * @private + */ + _splitArea: function (axisModel, gridModel) { + var axis = axisModel.axis; + + if (axis.scale.isBlank()) { + return; + } + + var splitAreaModel = axisModel.getModel('splitArea'); + var areaStyleModel = splitAreaModel.getModel('areaStyle'); + var areaColors = areaStyleModel.get('color'); + + var gridRect = gridModel.coordinateSystem.getRect(); + + var ticksCoords = axis.getTicksCoords({ + tickModel: splitAreaModel, + clamp: true + }); + + if (!ticksCoords.length) { + return; + } + + // For Making appropriate splitArea animation, the color and anid + // should be corresponding to previous one if possible. + var areaColorsLen = areaColors.length; + var lastSplitAreaColors = this._splitAreaColors; + var newSplitAreaColors = createHashMap(); + var colorIndex = 0; + if (lastSplitAreaColors) { + for (var i = 0; i < ticksCoords.length; i++) { + var cIndex = lastSplitAreaColors.get(ticksCoords[i].tickValue); + if (cIndex != null) { + colorIndex = (cIndex + (areaColorsLen - 1) * i) % areaColorsLen; + break; + } + } + } + + var prev = axis.toGlobalCoord(ticksCoords[0].coord); + + var areaStyle = areaStyleModel.getAreaStyle(); + areaColors = isArray(areaColors) ? areaColors : [areaColors]; + + for (var i = 1; i < ticksCoords.length; i++) { + var tickCoord = axis.toGlobalCoord(ticksCoords[i].coord); + + var x; + var y; + var width; + var height; + if (axis.isHorizontal()) { + x = prev; + y = gridRect.y; + width = tickCoord - x; + height = gridRect.height; + prev = x + width; + } + else { + x = gridRect.x; + y = prev; + width = gridRect.width; + height = tickCoord - y; + prev = y + height; + } + + var tickValue = ticksCoords[i - 1].tickValue; + tickValue != null && newSplitAreaColors.set(tickValue, colorIndex); + + this._axisGroup.add(new Rect({ + anid: tickValue != null ? 'area_' + tickValue : null, + shape: { + x: x, + y: y, + width: width, + height: height + }, + style: defaults({ + fill: areaColors[colorIndex] + }, areaStyle), + silent: true + })); + + colorIndex = (colorIndex + 1) % areaColorsLen; + } + + this._splitAreaColors = newSplitAreaColors; + } +}); + +CartesianAxisView.extend({ + type: 'xAxis' +}); +CartesianAxisView.extend({ + type: 'yAxis' +}); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +// Grid view +extendComponentView({ + + type: 'grid', + + render: function (gridModel, ecModel) { + this.group.removeAll(); + if (gridModel.get('show')) { + this.group.add(new Rect({ + shape: gridModel.coordinateSystem.getRect(), + style: defaults({ + fill: gridModel.get('backgroundColor') + }, gridModel.getItemStyle()), + silent: true, + z2: -1 + })); + } + } + +}); + +registerPreprocessor(function (option) { + // Only create grid when need + if (option.xAxis && option.yAxis && !option.grid) { + option.grid = {}; + } +}); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +// In case developer forget to include grid component +registerVisual(visualSymbol('line', 'circle', 'line')); +registerLayout(pointsLayout('line')); + +// Down sample after filter +registerProcessor( + PRIORITY.PROCESSOR.STATISTIC, + dataSample('line') +); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var BaseBarSeries = SeriesModel.extend({ + + type: 'series.__base_bar__', + + getInitialData: function (option, ecModel) { + return createListFromArray(this.getSource(), this); + }, + + getMarkerPosition: function (value) { + var coordSys = this.coordinateSystem; + if (coordSys) { + // PENDING if clamp ? + var pt = coordSys.dataToPoint(coordSys.clampData(value)); + var data = this.getData(); + var offset = data.getLayout('offset'); + var size = data.getLayout('size'); + var offsetIndex = coordSys.getBaseAxis().isHorizontal() ? 0 : 1; + pt[offsetIndex] += offset + size / 2; + return pt; + } + return [NaN, NaN]; + }, + + defaultOption: { + zlevel: 0, // 一级层叠 + z: 2, // 二级层叠 + coordinateSystem: 'cartesian2d', + legendHoverLink: true, + // stack: null + + // Cartesian coordinate system + // xAxisIndex: 0, + // yAxisIndex: 0, + + // 最小高度改为0 + barMinHeight: 0, + // 最小角度为0,仅对极坐标系下的柱状图有效 + barMinAngle: 0, + // cursor: null, + + large: false, + largeThreshold: 400, + progressive: 3e3, + progressiveChunkMode: 'mod', + + // barMaxWidth: null, + // 默认自适应 + // barWidth: null, + // 柱间距离,默认为柱形宽度的30%,可设固定值 + // barGap: '30%', + // 类目间柱形距离,默认为类目间距的20%,可设固定值 + // barCategoryGap: '20%', + // label: { + // show: false + // }, + itemStyle: {}, + emphasis: {} + } +}); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +BaseBarSeries.extend({ + + type: 'series.bar', + + dependencies: ['grid', 'polar'], + + brushSelector: 'rect', + + /** + * @override + */ + getProgressive: function () { + // Do not support progressive in normal mode. + return this.get('large') + ? this.get('progressive') + : false; + }, + + /** + * @override + */ + getProgressiveThreshold: function () { + // Do not support progressive in normal mode. + var progressiveThreshold = this.get('progressiveThreshold'); + var largeThreshold = this.get('largeThreshold'); + if (largeThreshold > progressiveThreshold) { + progressiveThreshold = largeThreshold; + } + return progressiveThreshold; + } + +}); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +function setLabel( + normalStyle, hoverStyle, itemModel, color, seriesModel, dataIndex, labelPositionOutside +) { + var labelModel = itemModel.getModel('label'); + var hoverLabelModel = itemModel.getModel('emphasis.label'); + + setLabelStyle( + normalStyle, hoverStyle, labelModel, hoverLabelModel, + { + labelFetcher: seriesModel, + labelDataIndex: dataIndex, + defaultText: getDefaultLabel(seriesModel.getData(), dataIndex), + isRectText: true, + autoColor: color + } + ); + + fixPosition(normalStyle); + fixPosition(hoverStyle); +} + +function fixPosition(style, labelPositionOutside) { + if (style.textPosition === 'outside') { + style.textPosition = labelPositionOutside; + } +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var getBarItemStyle = makeStyleMapper( + [ + ['fill', 'color'], + ['stroke', 'borderColor'], + ['lineWidth', 'borderWidth'], + // Compatitable with 2 + ['stroke', 'barBorderColor'], + ['lineWidth', 'barBorderWidth'], + ['opacity'], + ['shadowBlur'], + ['shadowOffsetX'], + ['shadowOffsetY'], + ['shadowColor'] + ] +); + +var barItemStyle = { + getBarItemStyle: function (excludes) { + var style = getBarItemStyle(this, excludes); + if (this.getBorderLineDash) { + var lineDash = this.getBorderLineDash(); + lineDash && (style.lineDash = lineDash); + } + return style; + } +}; + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var BAR_BORDER_WIDTH_QUERY = ['itemStyle', 'barBorderWidth']; + +// FIXME +// Just for compatible with ec2. +extend(Model.prototype, barItemStyle); + +extendChartView({ + + type: 'bar', + + render: function (seriesModel, ecModel, api) { + this._updateDrawMode(seriesModel); + + var coordinateSystemType = seriesModel.get('coordinateSystem'); + + if (coordinateSystemType === 'cartesian2d' + || coordinateSystemType === 'polar' + ) { + this._isLargeDraw + ? this._renderLarge(seriesModel, ecModel, api) + : this._renderNormal(seriesModel, ecModel, api); + } + else if (__DEV__) { + console.warn('Only cartesian2d and polar supported for bar.'); + } + + return this.group; + }, + + incrementalPrepareRender: function (seriesModel, ecModel, api) { + this._clear(); + this._updateDrawMode(seriesModel); + }, + + incrementalRender: function (params, seriesModel, ecModel, api) { + // Do not support progressive in normal mode. + this._incrementalRenderLarge(params, seriesModel); + }, + + _updateDrawMode: function (seriesModel) { + var isLargeDraw = seriesModel.pipelineContext.large; + if (this._isLargeDraw == null || isLargeDraw ^ this._isLargeDraw) { + this._isLargeDraw = isLargeDraw; + this._clear(); + } + }, + + _renderNormal: function (seriesModel, ecModel, api) { + var group = this.group; + var data = seriesModel.getData(); + var oldData = this._data; + + var coord = seriesModel.coordinateSystem; + var baseAxis = coord.getBaseAxis(); + var isHorizontalOrRadial; + + if (coord.type === 'cartesian2d') { + isHorizontalOrRadial = baseAxis.isHorizontal(); + } + else if (coord.type === 'polar') { + isHorizontalOrRadial = baseAxis.dim === 'angle'; + } + + var animationModel = seriesModel.isAnimationEnabled() ? seriesModel : null; + + data.diff(oldData) + .add(function (dataIndex) { + if (!data.hasValue(dataIndex)) { + return; + } + + var itemModel = data.getItemModel(dataIndex); + var layout = getLayout[coord.type](data, dataIndex, itemModel); + var el = elementCreator[coord.type]( + data, dataIndex, itemModel, layout, isHorizontalOrRadial, animationModel + ); + data.setItemGraphicEl(dataIndex, el); + group.add(el); + + updateStyle( + el, data, dataIndex, itemModel, layout, + seriesModel, isHorizontalOrRadial, coord.type === 'polar' + ); + }) + .update(function (newIndex, oldIndex) { + var el = oldData.getItemGraphicEl(oldIndex); + + if (!data.hasValue(newIndex)) { + group.remove(el); + return; + } + + var itemModel = data.getItemModel(newIndex); + var layout = getLayout[coord.type](data, newIndex, itemModel); + + if (el) { + updateProps(el, {shape: layout}, animationModel, newIndex); + } + else { + el = elementCreator[coord.type]( + data, newIndex, itemModel, layout, isHorizontalOrRadial, animationModel, true + ); + } + + data.setItemGraphicEl(newIndex, el); + // Add back + group.add(el); + + updateStyle( + el, data, newIndex, itemModel, layout, + seriesModel, isHorizontalOrRadial, coord.type === 'polar' + ); + }) + .remove(function (dataIndex) { + var el = oldData.getItemGraphicEl(dataIndex); + if (coord.type === 'cartesian2d') { + el && removeRect(dataIndex, animationModel, el); + } + else { + el && removeSector(dataIndex, animationModel, el); + } + }) + .execute(); + + this._data = data; + }, + + _renderLarge: function (seriesModel, ecModel, api) { + this._clear(); + createLarge(seriesModel, this.group); + }, + + _incrementalRenderLarge: function (params, seriesModel) { + createLarge(seriesModel, this.group, true); + }, + + dispose: noop, + + remove: function (ecModel) { + this._clear(ecModel); + }, + + _clear: function (ecModel) { + var group = this.group; + var data = this._data; + if (ecModel && ecModel.get('animation') && data && !this._isLargeDraw) { + data.eachItemGraphicEl(function (el) { + if (el.type === 'sector') { + removeSector(el.dataIndex, ecModel, el); + } + else { + removeRect(el.dataIndex, ecModel, el); + } + }); + } + else { + group.removeAll(); + } + this._data = null; + } + +}); + +var elementCreator = { + + cartesian2d: function ( + data, dataIndex, itemModel, layout, isHorizontal, + animationModel, isUpdate + ) { + var rect = new Rect({shape: extend({}, layout)}); + + // Animation + if (animationModel) { + var rectShape = rect.shape; + var animateProperty = isHorizontal ? 'height' : 'width'; + var animateTarget = {}; + rectShape[animateProperty] = 0; + animateTarget[animateProperty] = layout[animateProperty]; + graphic[isUpdate ? 'updateProps' : 'initProps'](rect, { + shape: animateTarget + }, animationModel, dataIndex); + } + + return rect; + }, + + polar: function ( + data, dataIndex, itemModel, layout, isRadial, + animationModel, isUpdate + ) { + // Keep the same logic with bar in catesion: use end value to control + // direction. Notice that if clockwise is true (by default), the sector + // will always draw clockwisely, no matter whether endAngle is greater + // or less than startAngle. + var clockwise = layout.startAngle < layout.endAngle; + var sector = new Sector({ + shape: defaults({clockwise: clockwise}, layout) + }); + + // Animation + if (animationModel) { + var sectorShape = sector.shape; + var animateProperty = isRadial ? 'r' : 'endAngle'; + var animateTarget = {}; + sectorShape[animateProperty] = isRadial ? 0 : layout.startAngle; + animateTarget[animateProperty] = layout[animateProperty]; + graphic[isUpdate ? 'updateProps' : 'initProps'](sector, { + shape: animateTarget + }, animationModel, dataIndex); + } + + return sector; + } +}; + +function removeRect(dataIndex, animationModel, el) { + // Not show text when animating + el.style.text = null; + updateProps(el, { + shape: { + width: 0 + } + }, animationModel, dataIndex, function () { + el.parent && el.parent.remove(el); + }); +} + +function removeSector(dataIndex, animationModel, el) { + // Not show text when animating + el.style.text = null; + updateProps(el, { + shape: { + r: el.shape.r0 + } + }, animationModel, dataIndex, function () { + el.parent && el.parent.remove(el); + }); +} + +var getLayout = { + cartesian2d: function (data, dataIndex, itemModel) { + var layout = data.getItemLayout(dataIndex); + var fixedLineWidth = getLineWidth(itemModel, layout); + + // fix layout with lineWidth + var signX = layout.width > 0 ? 1 : -1; + var signY = layout.height > 0 ? 1 : -1; + return { + x: layout.x + signX * fixedLineWidth / 2, + y: layout.y + signY * fixedLineWidth / 2, + width: layout.width - signX * fixedLineWidth, + height: layout.height - signY * fixedLineWidth + }; + }, + + polar: function (data, dataIndex, itemModel) { + var layout = data.getItemLayout(dataIndex); + return { + cx: layout.cx, + cy: layout.cy, + r0: layout.r0, + r: layout.r, + startAngle: layout.startAngle, + endAngle: layout.endAngle + }; + } +}; + +function updateStyle( + el, data, dataIndex, itemModel, layout, seriesModel, isHorizontal, isPolar +) { + var color = data.getItemVisual(dataIndex, 'color'); + var opacity = data.getItemVisual(dataIndex, 'opacity'); + var itemStyleModel = itemModel.getModel('itemStyle'); + var hoverStyle = itemModel.getModel('emphasis.itemStyle').getBarItemStyle(); + + if (!isPolar) { + el.setShape('r', itemStyleModel.get('barBorderRadius') || 0); + } + + el.useStyle(defaults( + { + fill: color, + opacity: opacity + }, + itemStyleModel.getBarItemStyle() + )); + + var cursorStyle = itemModel.getShallow('cursor'); + cursorStyle && el.attr('cursor', cursorStyle); + + var labelPositionOutside = isHorizontal + ? (layout.height > 0 ? 'bottom' : 'top') + : (layout.width > 0 ? 'left' : 'right'); + + if (!isPolar) { + setLabel( + el.style, hoverStyle, itemModel, color, + seriesModel, dataIndex, labelPositionOutside + ); + } + + setHoverStyle(el, hoverStyle); +} + +// In case width or height are too small. +function getLineWidth(itemModel, rawLayout) { + var lineWidth = itemModel.get(BAR_BORDER_WIDTH_QUERY) || 0; + return Math.min(lineWidth, Math.abs(rawLayout.width), Math.abs(rawLayout.height)); +} + + +var LargePath = Path.extend({ + + type: 'largeBar', + + shape: {points: []}, + + buildPath: function (ctx, shape) { + // Drawing lines is more efficient than drawing + // a whole line or drawing rects. + var points = shape.points; + var startPoint = this.__startPoint; + var valueIdx = this.__valueIdx; + + for (var i = 0; i < points.length; i += 2) { + startPoint[this.__valueIdx] = points[i + valueIdx]; + ctx.moveTo(startPoint[0], startPoint[1]); + ctx.lineTo(points[i], points[i + 1]); + } + } +}); + +function createLarge(seriesModel, group, incremental) { + // TODO support polar + var data = seriesModel.getData(); + var startPoint = []; + var valueIdx = data.getLayout('valueAxisHorizontal') ? 1 : 0; + startPoint[1 - valueIdx] = data.getLayout('valueAxisStart'); + + var el = new LargePath({ + shape: {points: data.getLayout('largePoints')}, + incremental: !!incremental, + __startPoint: startPoint, + __valueIdx: valueIdx + }); + group.add(el); + setLargeStyle(el, seriesModel, data); +} + +function setLargeStyle(el, seriesModel, data) { + var borderColor = data.getVisual('borderColor') || data.getVisual('color'); + var itemStyle = seriesModel.getModel('itemStyle').getItemStyle(['color', 'borderColor']); + + el.useStyle(itemStyle); + el.style.fill = null; + el.style.stroke = borderColor; + el.style.lineWidth = data.getLayout('barWidth'); +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +// In case developer forget to include grid component +registerLayout(curry(layout, 'bar')); +// Should after normal bar layout, otherwise it is blocked by normal bar layout. +registerLayout(largeLayout); + +registerVisual({ + seriesType: 'bar', + reset: function (seriesModel) { + // Visual coding for legend + seriesModel.getData().setVisual('legendSymbol', 'roundRect'); + } +}); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + + +/** + * [Usage]: + * (1) + * createListSimply(seriesModel, ['value']); + * (2) + * createListSimply(seriesModel, { + * coordDimensions: ['value'], + * dimensionsCount: 5 + * }); + * + * @param {module:echarts/model/Series} seriesModel + * @param {Object|Array.} opt opt or coordDimensions + * The options in opt, see `echarts/data/helper/createDimensions` + * @param {Array.} [nameList] + * @return {module:echarts/data/List} + */ +var createListSimply = function (seriesModel, opt, nameList) { + opt = isArray(opt) && {coordDimensions: opt} || extend({}, opt); + + var source = seriesModel.getSource(); + + var dimensionsInfo = createDimensions(source, opt); + + var list = new List(dimensionsInfo, seriesModel); + list.initData(source, nameList); + + return list; +}; + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/** + * Data selectable mixin for chart series. + * To eanble data select, option of series must have `selectedMode`. + * And each data item will use `selected` to toggle itself selected status + */ + +var selectableMixin = { + + /** + * @param {Array.} targetList [{name, value, selected}, ...] + * If targetList is an array, it should like [{name: ..., value: ...}, ...]. + * If targetList is a "List", it must have coordDim: 'value' dimension and name. + */ + updateSelectedMap: function (targetList) { + this._targetList = isArray(targetList) ? targetList.slice() : []; + + this._selectTargetMap = reduce(targetList || [], function (targetMap, target) { + targetMap.set(target.name, target); + return targetMap; + }, createHashMap()); + }, + + /** + * Either name or id should be passed as input here. + * If both of them are defined, id is used. + * + * @param {string|undefined} name name of data + * @param {number|undefined} id dataIndex of data + */ + // PENGING If selectedMode is null ? + select: function (name, id) { + var target = id != null + ? this._targetList[id] + : this._selectTargetMap.get(name); + var selectedMode = this.get('selectedMode'); + if (selectedMode === 'single') { + this._selectTargetMap.each(function (target) { + target.selected = false; + }); + } + target && (target.selected = true); + }, + + /** + * Either name or id should be passed as input here. + * If both of them are defined, id is used. + * + * @param {string|undefined} name name of data + * @param {number|undefined} id dataIndex of data + */ + unSelect: function (name, id) { + var target = id != null + ? this._targetList[id] + : this._selectTargetMap.get(name); + // var selectedMode = this.get('selectedMode'); + // selectedMode !== 'single' && target && (target.selected = false); + target && (target.selected = false); + }, + + /** + * Either name or id should be passed as input here. + * If both of them are defined, id is used. + * + * @param {string|undefined} name name of data + * @param {number|undefined} id dataIndex of data + */ + toggleSelected: function (name, id) { + var target = id != null + ? this._targetList[id] + : this._selectTargetMap.get(name); + if (target != null) { + this[target.selected ? 'unSelect' : 'select'](name, id); + return target.selected; + } + }, + + /** + * Either name or id should be passed as input here. + * If both of them are defined, id is used. + * + * @param {string|undefined} name name of data + * @param {number|undefined} id dataIndex of data + */ + isSelected: function (name, id) { + var target = id != null + ? this._targetList[id] + : this._selectTargetMap.get(name); + return target && target.selected; + } +}; + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var PieSeries = extendSeriesModel({ + + type: 'series.pie', + + // Overwrite + init: function (option) { + PieSeries.superApply(this, 'init', arguments); + + // Enable legend selection for each data item + // Use a function instead of direct access because data reference may changed + this.legendDataProvider = function () { + return this.getRawData(); + }; + + this.updateSelectedMap(this._createSelectableList()); + + this._defaultLabelLine(option); + }, + + // Overwrite + mergeOption: function (newOption) { + PieSeries.superCall(this, 'mergeOption', newOption); + + this.updateSelectedMap(this._createSelectableList()); + }, + + getInitialData: function (option, ecModel) { + return createListSimply(this, ['value']); + }, + + _createSelectableList: function () { + var data = this.getRawData(); + var valueDim = data.mapDimension('value'); + var targetList = []; + for (var i = 0, len = data.count(); i < len; i++) { + targetList.push({ + name: data.getName(i), + value: data.get(valueDim, i), + selected: retrieveRawAttr(data, i, 'selected') + }); + } + return targetList; + }, + + // Overwrite + getDataParams: function (dataIndex) { + var data = this.getData(); + var params = PieSeries.superCall(this, 'getDataParams', dataIndex); + // FIXME toFixed? + + var valueList = []; + data.each(data.mapDimension('value'), function (value) { + valueList.push(value); + }); + + params.percent = getPercentWithPrecision( + valueList, + dataIndex, + data.hostModel.get('percentPrecision') + ); + + params.$vars.push('percent'); + return params; + }, + + _defaultLabelLine: function (option) { + // Extend labelLine emphasis + defaultEmphasis(option, 'labelLine', ['show']); + + var labelLineNormalOpt = option.labelLine; + var labelLineEmphasisOpt = option.emphasis.labelLine; + // Not show label line if `label.normal.show = false` + labelLineNormalOpt.show = labelLineNormalOpt.show + && option.label.show; + labelLineEmphasisOpt.show = labelLineEmphasisOpt.show + && option.emphasis.label.show; + }, + + defaultOption: { + zlevel: 0, + z: 2, + legendHoverLink: true, + + hoverAnimation: true, + // 默认全局居中 + center: ['50%', '50%'], + radius: [0, '75%'], + // 默认顺时针 + clockwise: true, + startAngle: 90, + // 最小角度改为0 + minAngle: 0, + // 选中时扇区偏移量 + selectedOffset: 10, + // 高亮扇区偏移量 + hoverOffset: 10, + + // If use strategy to avoid label overlapping + avoidLabelOverlap: true, + // 选择模式,默认关闭,可选single,multiple + // selectedMode: false, + // 南丁格尔玫瑰图模式,'radius'(半径) | 'area'(面积) + // roseType: null, + + percentPrecision: 2, + + // If still show when all data zero. + stillShowZeroSum: true, + + // cursor: null, + + label: { + // If rotate around circle + rotate: false, + show: true, + // 'outer', 'inside', 'center' + position: 'outer' + // formatter: 标签文本格式器,同Tooltip.formatter,不支持异步回调 + // 默认使用全局文本样式,详见TEXTSTYLE + // distance: 当position为inner时有效,为label位置到圆心的距离与圆半径(环状图为内外半径和)的比例系数 + }, + // Enabled when label.normal.position is 'outer' + labelLine: { + show: true, + // 引导线两段中的第一段长度 + length: 15, + // 引导线两段中的第二段长度 + length2: 15, + smooth: false, + lineStyle: { + // color: 各异, + width: 1, + type: 'solid' + } + }, + itemStyle: { + borderWidth: 1 + }, + + // Animation type canbe expansion, scale + animationType: 'expansion', + + animationEasing: 'cubicOut' + } +}); + +mixin(PieSeries, selectableMixin); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/** + * @param {module:echarts/model/Series} seriesModel + * @param {boolean} hasAnimation + * @inner + */ +function updateDataSelected(uid, seriesModel, hasAnimation, api) { + var data = seriesModel.getData(); + var dataIndex = this.dataIndex; + var name = data.getName(dataIndex); + var selectedOffset = seriesModel.get('selectedOffset'); + + api.dispatchAction({ + type: 'pieToggleSelect', + from: uid, + name: name, + seriesId: seriesModel.id + }); + + data.each(function (idx) { + toggleItemSelected( + data.getItemGraphicEl(idx), + data.getItemLayout(idx), + seriesModel.isSelected(data.getName(idx)), + selectedOffset, + hasAnimation + ); + }); +} + +/** + * @param {module:zrender/graphic/Sector} el + * @param {Object} layout + * @param {boolean} isSelected + * @param {number} selectedOffset + * @param {boolean} hasAnimation + * @inner + */ +function toggleItemSelected(el, layout, isSelected, selectedOffset, hasAnimation) { + var midAngle = (layout.startAngle + layout.endAngle) / 2; + + var dx = Math.cos(midAngle); + var dy = Math.sin(midAngle); + + var offset = isSelected ? selectedOffset : 0; + var position = [dx * offset, dy * offset]; + + hasAnimation + // animateTo will stop revious animation like update transition + ? el.animate() + .when(200, { + position: position + }) + .start('bounceOut') + : el.attr('position', position); +} + +/** + * Piece of pie including Sector, Label, LabelLine + * @constructor + * @extends {module:zrender/graphic/Group} + */ +function PiePiece(data, idx) { + + Group.call(this); + + var sector = new Sector({ + z2: 2 + }); + var polyline = new Polyline(); + var text = new Text(); + this.add(sector); + this.add(polyline); + this.add(text); + + this.updateData(data, idx, true); + + // Hover to change label and labelLine + function onEmphasis() { + polyline.ignore = polyline.hoverIgnore; + text.ignore = text.hoverIgnore; + } + function onNormal() { + polyline.ignore = polyline.normalIgnore; + text.ignore = text.normalIgnore; + } + this.on('emphasis', onEmphasis) + .on('normal', onNormal) + .on('mouseover', onEmphasis) + .on('mouseout', onNormal); +} + +var piePieceProto = PiePiece.prototype; + +piePieceProto.updateData = function (data, idx, firstCreate) { + + var sector = this.childAt(0); + + var seriesModel = data.hostModel; + var itemModel = data.getItemModel(idx); + var layout = data.getItemLayout(idx); + var sectorShape = extend({}, layout); + sectorShape.label = null; + + if (firstCreate) { + sector.setShape(sectorShape); + + var animationType = seriesModel.getShallow('animationType'); + if (animationType === 'scale') { + sector.shape.r = layout.r0; + initProps(sector, { + shape: { + r: layout.r + } + }, seriesModel, idx); + } + // Expansion + else { + sector.shape.endAngle = layout.startAngle; + updateProps(sector, { + shape: { + endAngle: layout.endAngle + } + }, seriesModel, idx); + } + + } + else { + updateProps(sector, { + shape: sectorShape + }, seriesModel, idx); + } + + // Update common style + var visualColor = data.getItemVisual(idx, 'color'); + + sector.useStyle( + defaults( + { + lineJoin: 'bevel', + fill: visualColor + }, + itemModel.getModel('itemStyle').getItemStyle() + ) + ); + sector.hoverStyle = itemModel.getModel('emphasis.itemStyle').getItemStyle(); + + var cursorStyle = itemModel.getShallow('cursor'); + cursorStyle && sector.attr('cursor', cursorStyle); + + // Toggle selected + toggleItemSelected( + this, + data.getItemLayout(idx), + seriesModel.isSelected(null, idx), + seriesModel.get('selectedOffset'), + seriesModel.get('animation') + ); + + function onEmphasis() { + // Sector may has animation of updating data. Force to move to the last frame + // Or it may stopped on the wrong shape + sector.stopAnimation(true); + sector.animateTo({ + shape: { + r: layout.r + seriesModel.get('hoverOffset') + } + }, 300, 'elasticOut'); + } + function onNormal() { + sector.stopAnimation(true); + sector.animateTo({ + shape: { + r: layout.r + } + }, 300, 'elasticOut'); + } + sector.off('mouseover').off('mouseout').off('emphasis').off('normal'); + if (itemModel.get('hoverAnimation') && seriesModel.isAnimationEnabled()) { + sector + .on('mouseover', onEmphasis) + .on('mouseout', onNormal) + .on('emphasis', onEmphasis) + .on('normal', onNormal); + } + + this._updateLabel(data, idx); + + setHoverStyle(this); +}; + +piePieceProto._updateLabel = function (data, idx) { + + var labelLine = this.childAt(1); + var labelText = this.childAt(2); + + var seriesModel = data.hostModel; + var itemModel = data.getItemModel(idx); + var layout = data.getItemLayout(idx); + var labelLayout = layout.label; + var visualColor = data.getItemVisual(idx, 'color'); + + updateProps(labelLine, { + shape: { + points: labelLayout.linePoints || [ + [labelLayout.x, labelLayout.y], [labelLayout.x, labelLayout.y], [labelLayout.x, labelLayout.y] + ] + } + }, seriesModel, idx); + + updateProps(labelText, { + style: { + x: labelLayout.x, + y: labelLayout.y + } + }, seriesModel, idx); + labelText.attr({ + rotation: labelLayout.rotation, + origin: [labelLayout.x, labelLayout.y], + z2: 10 + }); + + var labelModel = itemModel.getModel('label'); + var labelHoverModel = itemModel.getModel('emphasis.label'); + var labelLineModel = itemModel.getModel('labelLine'); + var labelLineHoverModel = itemModel.getModel('emphasis.labelLine'); + var visualColor = data.getItemVisual(idx, 'color'); + + setLabelStyle( + labelText.style, labelText.hoverStyle = {}, labelModel, labelHoverModel, + { + labelFetcher: data.hostModel, + labelDataIndex: idx, + defaultText: data.getName(idx), + autoColor: visualColor, + useInsideStyle: !!labelLayout.inside + }, + { + textAlign: labelLayout.textAlign, + textVerticalAlign: labelLayout.verticalAlign, + opacity: data.getItemVisual(idx, 'opacity') + } + ); + + labelText.ignore = labelText.normalIgnore = !labelModel.get('show'); + labelText.hoverIgnore = !labelHoverModel.get('show'); + + labelLine.ignore = labelLine.normalIgnore = !labelLineModel.get('show'); + labelLine.hoverIgnore = !labelLineHoverModel.get('show'); + + // Default use item visual color + labelLine.setStyle({ + stroke: visualColor, + opacity: data.getItemVisual(idx, 'opacity') + }); + labelLine.setStyle(labelLineModel.getModel('lineStyle').getLineStyle()); + + labelLine.hoverStyle = labelLineHoverModel.getModel('lineStyle').getLineStyle(); + + var smooth = labelLineModel.get('smooth'); + if (smooth && smooth === true) { + smooth = 0.4; + } + labelLine.setShape({ + smooth: smooth + }); +}; + +inherits(PiePiece, Group); + + +// Pie view +var PieView = Chart.extend({ + + type: 'pie', + + init: function () { + var sectorGroup = new Group(); + this._sectorGroup = sectorGroup; + }, + + render: function (seriesModel, ecModel, api, payload) { + if (payload && (payload.from === this.uid)) { + return; + } + + var data = seriesModel.getData(); + var oldData = this._data; + var group = this.group; + + var hasAnimation = ecModel.get('animation'); + var isFirstRender = !oldData; + var animationType = seriesModel.get('animationType'); + + var onSectorClick = curry( + updateDataSelected, this.uid, seriesModel, hasAnimation, api + ); + + var selectedMode = seriesModel.get('selectedMode'); + + data.diff(oldData) + .add(function (idx) { + var piePiece = new PiePiece(data, idx); + // Default expansion animation + if (isFirstRender && animationType !== 'scale') { + piePiece.eachChild(function (child) { + child.stopAnimation(true); + }); + } + + selectedMode && piePiece.on('click', onSectorClick); + + data.setItemGraphicEl(idx, piePiece); + + group.add(piePiece); + }) + .update(function (newIdx, oldIdx) { + var piePiece = oldData.getItemGraphicEl(oldIdx); + + piePiece.updateData(data, newIdx); + + piePiece.off('click'); + selectedMode && piePiece.on('click', onSectorClick); + group.add(piePiece); + data.setItemGraphicEl(newIdx, piePiece); + }) + .remove(function (idx) { + var piePiece = oldData.getItemGraphicEl(idx); + group.remove(piePiece); + }) + .execute(); + + if ( + hasAnimation && isFirstRender && data.count() > 0 + // Default expansion animation + && animationType !== 'scale' + ) { + var shape = data.getItemLayout(0); + var r = Math.max(api.getWidth(), api.getHeight()) / 2; + + var removeClipPath = bind(group.removeClipPath, group); + group.setClipPath(this._createClipPath( + shape.cx, shape.cy, r, shape.startAngle, shape.clockwise, removeClipPath, seriesModel + )); + } + else { + // clipPath is used in first-time animation, so remove it when otherwise. See: #8994 + group.removeClipPath(); + } + + this._data = data; + }, + + dispose: function () {}, + + _createClipPath: function ( + cx, cy, r, startAngle, clockwise, cb, seriesModel + ) { + var clipPath = new Sector({ + shape: { + cx: cx, + cy: cy, + r0: 0, + r: r, + startAngle: startAngle, + endAngle: startAngle, + clockwise: clockwise + } + }); + + initProps(clipPath, { + shape: { + endAngle: startAngle + (clockwise ? 1 : -1) * Math.PI * 2 + } + }, seriesModel, cb); + + return clipPath; + }, + + /** + * @implement + */ + containPoint: function (point, seriesModel) { + var data = seriesModel.getData(); + var itemLayout = data.getItemLayout(0); + if (itemLayout) { + var dx = point[0] - itemLayout.cx; + var dy = point[1] - itemLayout.cy; + var radius = Math.sqrt(dx * dx + dy * dy); + return radius <= itemLayout.r && radius >= itemLayout.r0; + } + } + +}); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var createDataSelectAction = function (seriesType, actionInfos) { + each$1(actionInfos, function (actionInfo) { + actionInfo.update = 'updateView'; + /** + * @payload + * @property {string} seriesName + * @property {string} name + */ + registerAction(actionInfo, function (payload, ecModel) { + var selected = {}; + ecModel.eachComponent( + {mainType: 'series', subType: seriesType, query: payload}, + function (seriesModel) { + if (seriesModel[actionInfo.method]) { + seriesModel[actionInfo.method]( + payload.name, + payload.dataIndex + ); + } + var data = seriesModel.getData(); + // Create selected map + data.each(function (idx) { + var name = data.getName(idx); + selected[name] = seriesModel.isSelected(name) + || false; + }); + } + ); + return { + name: payload.name, + selected: selected + }; + }); + }); +}; + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +// Pick color from palette for each data item. +// Applicable for charts that require applying color palette +// in data level (like pie, funnel, chord). +var dataColor = function (seriesType) { + return { + getTargetSeries: function (ecModel) { + // Pie and funnel may use diferrent scope + var paletteScope = {}; + var seiresModelMap = createHashMap(); + + ecModel.eachSeriesByType(seriesType, function (seriesModel) { + seriesModel.__paletteScope = paletteScope; + seiresModelMap.set(seriesModel.uid, seriesModel); + }); + + return seiresModelMap; + }, + reset: function (seriesModel, ecModel) { + var dataAll = seriesModel.getRawData(); + var idxMap = {}; + var data = seriesModel.getData(); + + data.each(function (idx) { + var rawIdx = data.getRawIndex(idx); + idxMap[rawIdx] = idx; + }); + + dataAll.each(function (rawIdx) { + var filteredIdx = idxMap[rawIdx]; + + // If series.itemStyle.normal.color is a function. itemVisual may be encoded + var singleDataColor = filteredIdx != null + && data.getItemVisual(filteredIdx, 'color', true); + + if (!singleDataColor) { + // FIXME Performance + var itemModel = dataAll.getItemModel(rawIdx); + + var color = itemModel.get('itemStyle.color') + || seriesModel.getColorFromPalette( + dataAll.getName(rawIdx) || (rawIdx + ''), seriesModel.__paletteScope, + dataAll.count() + ); + // Legend may use the visual info in data before processed + dataAll.setItemVisual(rawIdx, 'color', color); + + // Data is not filtered + if (filteredIdx != null) { + data.setItemVisual(filteredIdx, 'color', color); + } + } + else { + // Set data all color for legend + dataAll.setItemVisual(rawIdx, 'color', singleDataColor); + } + }); + } + }; +}; + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +// FIXME emphasis label position is not same with normal label position + +function adjustSingleSide(list, cx, cy, r, dir, viewWidth, viewHeight) { + list.sort(function (a, b) { + return a.y - b.y; + }); + + function shiftDown(start, end, delta, dir) { + for (var j = start; j < end; j++) { + list[j].y += delta; + if (j > start + && j + 1 < end + && list[j + 1].y > list[j].y + list[j].height + ) { + shiftUp(j, delta / 2); + return; + } + } + + shiftUp(end - 1, delta / 2); + } + + function shiftUp(end, delta) { + for (var j = end; j >= 0; j--) { + list[j].y -= delta; + if (j > 0 + && list[j].y > list[j - 1].y + list[j - 1].height + ) { + break; + } + } + } + + function changeX(list, isDownList, cx, cy, r, dir) { + var lastDeltaX = dir > 0 + ? isDownList // right-side + ? Number.MAX_VALUE // down + : 0 // up + : isDownList // left-side + ? Number.MAX_VALUE // down + : 0; // up + + for (var i = 0, l = list.length; i < l; i++) { + var deltaY = Math.abs(list[i].y - cy); + var length = list[i].len; + var length2 = list[i].len2; + var deltaX = (deltaY < r + length) + ? Math.sqrt( + (r + length + length2) * (r + length + length2) + - deltaY * deltaY + ) + : Math.abs(list[i].x - cx); + if (isDownList && deltaX >= lastDeltaX) { + // right-down, left-down + deltaX = lastDeltaX - 10; + } + if (!isDownList && deltaX <= lastDeltaX) { + // right-up, left-up + deltaX = lastDeltaX + 10; + } + + list[i].x = cx + deltaX * dir; + lastDeltaX = deltaX; + } + } + + var lastY = 0; + var delta; + var len = list.length; + var upList = []; + var downList = []; + for (var i = 0; i < len; i++) { + delta = list[i].y - lastY; + if (delta < 0) { + shiftDown(i, len, -delta, dir); + } + lastY = list[i].y + list[i].height; + } + if (viewHeight - lastY < 0) { + shiftUp(len - 1, lastY - viewHeight); + } + for (var i = 0; i < len; i++) { + if (list[i].y >= cy) { + downList.push(list[i]); + } + else { + upList.push(list[i]); + } + } + changeX(upList, false, cx, cy, r, dir); + changeX(downList, true, cx, cy, r, dir); +} + +function avoidOverlap(labelLayoutList, cx, cy, r, viewWidth, viewHeight) { + var leftList = []; + var rightList = []; + for (var i = 0; i < labelLayoutList.length; i++) { + if (isPositionCenter(labelLayoutList[i])) { + continue; + } + if (labelLayoutList[i].x < cx) { + leftList.push(labelLayoutList[i]); + } + else { + rightList.push(labelLayoutList[i]); + } + } + + adjustSingleSide(rightList, cx, cy, r, 1, viewWidth, viewHeight); + adjustSingleSide(leftList, cx, cy, r, -1, viewWidth, viewHeight); + + for (var i = 0; i < labelLayoutList.length; i++) { + if (isPositionCenter(labelLayoutList[i])) { + continue; + } + var linePoints = labelLayoutList[i].linePoints; + if (linePoints) { + var dist = linePoints[1][0] - linePoints[2][0]; + if (labelLayoutList[i].x < cx) { + linePoints[2][0] = labelLayoutList[i].x + 3; + } + else { + linePoints[2][0] = labelLayoutList[i].x - 3; + } + linePoints[1][1] = linePoints[2][1] = labelLayoutList[i].y; + linePoints[1][0] = linePoints[2][0] + dist; + } + } +} + +function isPositionCenter(layout) { + // Not change x for center label + return layout.position === 'center'; +} + +var labelLayout = function (seriesModel, r, viewWidth, viewHeight) { + var data = seriesModel.getData(); + var labelLayoutList = []; + var cx; + var cy; + var hasLabelRotate = false; + + data.each(function (idx) { + var layout = data.getItemLayout(idx); + + var itemModel = data.getItemModel(idx); + var labelModel = itemModel.getModel('label'); + // Use position in normal or emphasis + var labelPosition = labelModel.get('position') || itemModel.get('emphasis.label.position'); + + var labelLineModel = itemModel.getModel('labelLine'); + var labelLineLen = labelLineModel.get('length'); + var labelLineLen2 = labelLineModel.get('length2'); + + var midAngle = (layout.startAngle + layout.endAngle) / 2; + var dx = Math.cos(midAngle); + var dy = Math.sin(midAngle); + + var textX; + var textY; + var linePoints; + var textAlign; + + cx = layout.cx; + cy = layout.cy; + + var isLabelInside = labelPosition === 'inside' || labelPosition === 'inner'; + if (labelPosition === 'center') { + textX = layout.cx; + textY = layout.cy; + textAlign = 'center'; + } + else { + var x1 = (isLabelInside ? (layout.r + layout.r0) / 2 * dx : layout.r * dx) + cx; + var y1 = (isLabelInside ? (layout.r + layout.r0) / 2 * dy : layout.r * dy) + cy; + + textX = x1 + dx * 3; + textY = y1 + dy * 3; + + if (!isLabelInside) { + // For roseType + var x2 = x1 + dx * (labelLineLen + r - layout.r); + var y2 = y1 + dy * (labelLineLen + r - layout.r); + var x3 = x2 + ((dx < 0 ? -1 : 1) * labelLineLen2); + var y3 = y2; + + textX = x3 + (dx < 0 ? -5 : 5); + textY = y3; + linePoints = [[x1, y1], [x2, y2], [x3, y3]]; + } + + textAlign = isLabelInside ? 'center' : (dx > 0 ? 'left' : 'right'); + } + var font = labelModel.getFont(); + + var labelRotate = labelModel.get('rotate') + ? (dx < 0 ? -midAngle + Math.PI : -midAngle) : 0; + var text = seriesModel.getFormattedLabel(idx, 'normal') + || data.getName(idx); + var textRect = getBoundingRect( + text, font, textAlign, 'top' + ); + hasLabelRotate = !!labelRotate; + layout.label = { + x: textX, + y: textY, + position: labelPosition, + height: textRect.height, + len: labelLineLen, + len2: labelLineLen2, + linePoints: linePoints, + textAlign: textAlign, + verticalAlign: 'middle', + rotation: labelRotate, + inside: isLabelInside + }; + + // Not layout the inside label + if (!isLabelInside) { + labelLayoutList.push(layout.label); + } + }); + if (!hasLabelRotate && seriesModel.get('avoidLabelOverlap')) { + avoidOverlap(labelLayoutList, cx, cy, r, viewWidth, viewHeight); + } +}; + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + + +var PI2$4 = Math.PI * 2; +var RADIAN = Math.PI / 180; + +var pieLayout = function (seriesType, ecModel, api, payload) { + ecModel.eachSeriesByType(seriesType, function (seriesModel) { + var data = seriesModel.getData(); + var valueDim = data.mapDimension('value'); + + var center = seriesModel.get('center'); + var radius = seriesModel.get('radius'); + + if (!isArray(radius)) { + radius = [0, radius]; + } + if (!isArray(center)) { + center = [center, center]; + } + + var width = api.getWidth(); + var height = api.getHeight(); + var size = Math.min(width, height); + var cx = parsePercent$1(center[0], width); + var cy = parsePercent$1(center[1], height); + var r0 = parsePercent$1(radius[0], size / 2); + var r = parsePercent$1(radius[1], size / 2); + + var startAngle = -seriesModel.get('startAngle') * RADIAN; + + var minAngle = seriesModel.get('minAngle') * RADIAN; + + var validDataCount = 0; + data.each(valueDim, function (value) { + !isNaN(value) && validDataCount++; + }); + + var sum = data.getSum(valueDim); + // Sum may be 0 + var unitRadian = Math.PI / (sum || validDataCount) * 2; + + var clockwise = seriesModel.get('clockwise'); + + var roseType = seriesModel.get('roseType'); + var stillShowZeroSum = seriesModel.get('stillShowZeroSum'); + + // [0...max] + var extent = data.getDataExtent(valueDim); + extent[0] = 0; + + // In the case some sector angle is smaller than minAngle + var restAngle = PI2$4; + var valueSumLargerThanMinAngle = 0; + + var currentAngle = startAngle; + var dir = clockwise ? 1 : -1; + + data.each(valueDim, function (value, idx) { + var angle; + if (isNaN(value)) { + data.setItemLayout(idx, { + angle: NaN, + startAngle: NaN, + endAngle: NaN, + clockwise: clockwise, + cx: cx, + cy: cy, + r0: r0, + r: roseType + ? NaN + : r + }); + return; + } + + // FIXME 兼容 2.0 但是 roseType 是 area 的时候才是这样? + if (roseType !== 'area') { + angle = (sum === 0 && stillShowZeroSum) + ? unitRadian : (value * unitRadian); + } + else { + angle = PI2$4 / validDataCount; + } + + if (angle < minAngle) { + angle = minAngle; + restAngle -= minAngle; + } + else { + valueSumLargerThanMinAngle += value; + } + + var endAngle = currentAngle + dir * angle; + data.setItemLayout(idx, { + angle: angle, + startAngle: currentAngle, + endAngle: endAngle, + clockwise: clockwise, + cx: cx, + cy: cy, + r0: r0, + r: roseType + ? linearMap(value, extent, [r0, r]) + : r + }); + + currentAngle = endAngle; + }); + + // Some sector is constrained by minAngle + // Rest sectors needs recalculate angle + if (restAngle < PI2$4 && validDataCount) { + // Average the angle if rest angle is not enough after all angles is + // Constrained by minAngle + if (restAngle <= 1e-3) { + var angle = PI2$4 / validDataCount; + data.each(valueDim, function (value, idx) { + if (!isNaN(value)) { + var layout = data.getItemLayout(idx); + layout.angle = angle; + layout.startAngle = startAngle + dir * idx * angle; + layout.endAngle = startAngle + dir * (idx + 1) * angle; + } + }); + } + else { + unitRadian = restAngle / valueSumLargerThanMinAngle; + currentAngle = startAngle; + data.each(valueDim, function (value, idx) { + if (!isNaN(value)) { + var layout = data.getItemLayout(idx); + var angle = layout.angle === minAngle + ? minAngle : value * unitRadian; + layout.startAngle = currentAngle; + layout.endAngle = currentAngle + dir * angle; + currentAngle += dir * angle; + } + }); + } + } + + labelLayout(seriesModel, r, width, height); + }); +}; + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var dataFilter = function (seriesType) { + return { + seriesType: seriesType, + reset: function (seriesModel, ecModel) { + var legendModels = ecModel.findComponents({ + mainType: 'legend' + }); + if (!legendModels || !legendModels.length) { + return; + } + var data = seriesModel.getData(); + data.filterSelf(function (idx) { + var name = data.getName(idx); + // If in any legend component the status is not selected. + for (var i = 0; i < legendModels.length; i++) { + if (!legendModels[i].isSelected(name)) { + return false; + } + } + return true; + }); + } + }; +}; + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +createDataSelectAction('pie', [{ + type: 'pieToggleSelect', + event: 'pieselectchanged', + method: 'toggleSelected' +}, { + type: 'pieSelect', + event: 'pieselected', + method: 'select' +}, { + type: 'pieUnSelect', + event: 'pieunselected', + method: 'unSelect' +}]); + +registerVisual(dataColor('pie')); +registerLayout(curry(pieLayout, 'pie')); +registerProcessor(dataFilter('pie')); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +SeriesModel.extend({ + + type: 'series.scatter', + + dependencies: ['grid', 'polar', 'geo', 'singleAxis', 'calendar'], + + getInitialData: function (option, ecModel) { + return createListFromArray(this.getSource(), this); + }, + + brushSelector: 'point', + + getProgressive: function () { + var progressive = this.option.progressive; + if (progressive == null) { + // PENDING + return this.option.large ? 5e3 : this.get('progressive'); + } + return progressive; + }, + + getProgressiveThreshold: function () { + var progressiveThreshold = this.option.progressiveThreshold; + if (progressiveThreshold == null) { + // PENDING + return this.option.large ? 1e4 : this.get('progressiveThreshold'); + } + return progressiveThreshold; + }, + + defaultOption: { + coordinateSystem: 'cartesian2d', + zlevel: 0, + z: 2, + legendHoverLink: true, + + hoverAnimation: true, + // Cartesian coordinate system + // xAxisIndex: 0, + // yAxisIndex: 0, + + // Polar coordinate system + // polarIndex: 0, + + // Geo coordinate system + // geoIndex: 0, + + // symbol: null, // 图形类型 + symbolSize: 10, // 图形大小,半宽(半径)参数,当图形为方向或菱形则总宽度为symbolSize * 2 + // symbolRotate: null, // 图形旋转控制 + + large: false, + // Available when large is true + largeThreshold: 2000, + // cursor: null, + + // label: { + // show: false + // distance: 5, + // formatter: 标签文本格式器,同Tooltip.formatter,不支持异步回调 + // position: 默认自适应,水平布局为'top',垂直布局为'right',可选为 + // 'inside'|'left'|'right'|'top'|'bottom' + // 默认使用全局文本样式,详见TEXTSTYLE + // }, + itemStyle: { + opacity: 0.8 + // color: 各异 + } + + // progressive: null + } + +}); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/* global Float32Array */ + +// TODO Batch by color + +var BOOST_SIZE_THRESHOLD = 4; + +var LargeSymbolPath = extendShape({ + + shape: { + points: null + }, + + symbolProxy: null, + + buildPath: function (path, shape) { + var points = shape.points; + var size = shape.size; + + var symbolProxy = this.symbolProxy; + var symbolProxyShape = symbolProxy.shape; + var ctx = path.getContext ? path.getContext() : path; + var canBoost = ctx && size[0] < BOOST_SIZE_THRESHOLD; + + // Do draw in afterBrush. + if (canBoost) { + return; + } + + for (var i = 0; i < points.length;) { + var x = points[i++]; + var y = points[i++]; + + if (isNaN(x) || isNaN(y)) { + continue; + } + + symbolProxyShape.x = x - size[0] / 2; + symbolProxyShape.y = y - size[1] / 2; + symbolProxyShape.width = size[0]; + symbolProxyShape.height = size[1]; + + symbolProxy.buildPath(path, symbolProxyShape, true); + } + }, + + afterBrush: function (ctx) { + var shape = this.shape; + var points = shape.points; + var size = shape.size; + var canBoost = size[0] < BOOST_SIZE_THRESHOLD; + + if (!canBoost) { + return; + } + + this.setTransform(ctx); + // PENDING If style or other canvas status changed? + for (var i = 0; i < points.length;) { + var x = points[i++]; + var y = points[i++]; + if (isNaN(x) || isNaN(y)) { + continue; + } + // fillRect is faster than building a rect path and draw. + // And it support light globalCompositeOperation. + ctx.fillRect( + x - size[0] / 2, y - size[1] / 2, + size[0], size[1] + ); + } + + this.restoreTransform(ctx); + }, + + findDataIndex: function (x, y) { + // TODO ??? + // Consider transform + + var shape = this.shape; + var points = shape.points; + var size = shape.size; + + var w = Math.max(size[0], 4); + var h = Math.max(size[1], 4); + + // Not consider transform + // Treat each element as a rect + // top down traverse + for (var idx = points.length / 2 - 1; idx >= 0; idx--) { + var i = idx * 2; + var x0 = points[i] - w / 2; + var y0 = points[i + 1] - h / 2; + if (x >= x0 && y >= y0 && x <= x0 + w && y <= y0 + h) { + return idx; + } + } + + return -1; + } +}); + +function LargeSymbolDraw() { + this.group = new Group(); +} + +var largeSymbolProto = LargeSymbolDraw.prototype; + +largeSymbolProto.isPersistent = function () { + return !this._incremental; +}; + +/** + * Update symbols draw by new data + * @param {module:echarts/data/List} data + */ +largeSymbolProto.updateData = function (data) { + this.group.removeAll(); + var symbolEl = new LargeSymbolPath({ + rectHover: true, + cursor: 'default' + }); + + symbolEl.setShape({ + points: data.getLayout('symbolPoints') + }); + this._setCommon(symbolEl, data); + this.group.add(symbolEl); + + this._incremental = null; +}; + +largeSymbolProto.updateLayout = function (data) { + if (this._incremental) { + return; + } + + var points = data.getLayout('symbolPoints'); + this.group.eachChild(function (child) { + if (child.startIndex != null) { + var len = (child.endIndex - child.startIndex) * 2; + var byteOffset = child.startIndex * 4 * 2; + points = new Float32Array(points.buffer, byteOffset, len); + } + child.setShape('points', points); + }); +}; + +largeSymbolProto.incrementalPrepareUpdate = function (data) { + this.group.removeAll(); + + this._clearIncremental(); + // Only use incremental displayables when data amount is larger than 2 million. + // PENDING Incremental data? + if (data.count() > 2e6) { + if (!this._incremental) { + this._incremental = new IncrementalDisplayble({ + silent: true + }); + } + this.group.add(this._incremental); + } + else { + this._incremental = null; + } +}; + +largeSymbolProto.incrementalUpdate = function (taskParams, data) { + var symbolEl; + if (this._incremental) { + symbolEl = new LargeSymbolPath(); + this._incremental.addDisplayable(symbolEl, true); + } + else { + symbolEl = new LargeSymbolPath({ + rectHover: true, + cursor: 'default', + startIndex: taskParams.start, + endIndex: taskParams.end + }); + symbolEl.incremental = true; + this.group.add(symbolEl); + } + + symbolEl.setShape({ + points: data.getLayout('symbolPoints') + }); + this._setCommon(symbolEl, data, !!this._incremental); +}; + +largeSymbolProto._setCommon = function (symbolEl, data, isIncremental) { + var hostModel = data.hostModel; + + // TODO + // if (data.hasItemVisual.symbolSize) { + // // TODO typed array? + // symbolEl.setShape('sizes', data.mapArray( + // function (idx) { + // var size = data.getItemVisual(idx, 'symbolSize'); + // return (size instanceof Array) ? size : [size, size]; + // } + // )); + // } + // else { + var size = data.getVisual('symbolSize'); + symbolEl.setShape('size', (size instanceof Array) ? size : [size, size]); + // } + + // Create symbolProxy to build path for each data + symbolEl.symbolProxy = createSymbol( + data.getVisual('symbol'), 0, 0, 0, 0 + ); + // Use symbolProxy setColor method + symbolEl.setColor = symbolEl.symbolProxy.setColor; + + var extrudeShadow = symbolEl.shape.size[0] < BOOST_SIZE_THRESHOLD; + symbolEl.useStyle( + // Draw shadow when doing fillRect is extremely slow. + hostModel.getModel('itemStyle').getItemStyle(extrudeShadow ? ['color', 'shadowBlur', 'shadowColor'] : ['color']) + ); + + var visualColor = data.getVisual('color'); + if (visualColor) { + symbolEl.setColor(visualColor); + } + + if (!isIncremental) { + // Enable tooltip + // PENDING May have performance issue when path is extremely large + symbolEl.seriesIndex = hostModel.seriesIndex; + symbolEl.on('mousemove', function (e) { + symbolEl.dataIndex = null; + var dataIndex = symbolEl.findDataIndex(e.offsetX, e.offsetY); + if (dataIndex >= 0) { + // Provide dataIndex for tooltip + symbolEl.dataIndex = dataIndex + (symbolEl.startIndex || 0); + } + }); + } +}; + +largeSymbolProto.remove = function () { + this._clearIncremental(); + this._incremental = null; + this.group.removeAll(); +}; + +largeSymbolProto._clearIncremental = function () { + var incremental = this._incremental; + if (incremental) { + incremental.clearDisplaybles(); + } +}; + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +extendChartView({ + + type: 'scatter', + + render: function (seriesModel, ecModel, api) { + var data = seriesModel.getData(); + + var symbolDraw = this._updateSymbolDraw(data, seriesModel); + symbolDraw.updateData(data); + + this._finished = true; + }, + + incrementalPrepareRender: function (seriesModel, ecModel, api) { + var data = seriesModel.getData(); + var symbolDraw = this._updateSymbolDraw(data, seriesModel); + + symbolDraw.incrementalPrepareUpdate(data); + + this._finished = false; + }, + + incrementalRender: function (taskParams, seriesModel, ecModel) { + this._symbolDraw.incrementalUpdate(taskParams, seriesModel.getData()); + + this._finished = taskParams.end === seriesModel.getData().count(); + }, + + updateTransform: function (seriesModel, ecModel, api) { + var data = seriesModel.getData(); + // Must mark group dirty and make sure the incremental layer will be cleared + // PENDING + this.group.dirty(); + + if (!this._finished || data.count() > 1e4 || !this._symbolDraw.isPersistent()) { + return { + update: true + }; + } + else { + var res = pointsLayout().reset(seriesModel); + if (res.progress) { + res.progress({ start: 0, end: data.count() }, data); + } + + this._symbolDraw.updateLayout(data); + } + }, + + _updateSymbolDraw: function (data, seriesModel) { + var symbolDraw = this._symbolDraw; + var pipelineContext = seriesModel.pipelineContext; + var isLargeDraw = pipelineContext.large; + + if (!symbolDraw || isLargeDraw !== this._isLargeDraw) { + symbolDraw && symbolDraw.remove(); + symbolDraw = this._symbolDraw = isLargeDraw + ? new LargeSymbolDraw() + : new SymbolDraw(); + this._isLargeDraw = isLargeDraw; + this.group.removeAll(); + } + + this.group.add(symbolDraw.group); + + return symbolDraw; + }, + + remove: function (ecModel, api) { + this._symbolDraw && this._symbolDraw.remove(true); + this._symbolDraw = null; + }, + + dispose: function () {} +}); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +// import * as zrUtil from 'zrender/src/core/util'; + +// In case developer forget to include grid component +registerVisual(visualSymbol('scatter', 'circle')); +registerLayout(pointsLayout('scatter')); + +// echarts.registerProcessor(function (ecModel, api) { +// ecModel.eachSeriesByType('scatter', function (seriesModel) { +// var data = seriesModel.getData(); +// var coordSys = seriesModel.coordinateSystem; +// if (coordSys.type !== 'geo') { +// return; +// } +// var startPt = coordSys.pointToData([0, 0]); +// var endPt = coordSys.pointToData([api.getWidth(), api.getHeight()]); + +// var dims = zrUtil.map(coordSys.dimensions, function (dim) { +// return data.mapDimension(dim); +// }); +// var range = {}; +// range[dims[0]] = [Math.min(startPt[0], endPt[0]), Math.max(startPt[0], endPt[0])]; +// range[dims[1]] = [Math.min(startPt[1], endPt[1]), Math.max(startPt[1], endPt[1])]; + +// data.selectRange(range); +// }); +// }); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +function IndicatorAxis(dim, scale, radiusExtent) { + Axis.call(this, dim, scale, radiusExtent); + + /** + * Axis type + * - 'category' + * - 'value' + * - 'time' + * - 'log' + * @type {string} + */ + this.type = 'value'; + + this.angle = 0; + + /** + * Indicator name + * @type {string} + */ + this.name = ''; + /** + * @type {module:echarts/model/Model} + */ + this.model; +} + +inherits(IndicatorAxis, Axis); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +// TODO clockwise + +function Radar(radarModel, ecModel, api) { + + this._model = radarModel; + /** + * Radar dimensions + * @type {Array.} + */ + this.dimensions = []; + + this._indicatorAxes = map(radarModel.getIndicatorModels(), function (indicatorModel, idx) { + var dim = 'indicator_' + idx; + var indicatorAxis = new IndicatorAxis(dim, new IntervalScale()); + indicatorAxis.name = indicatorModel.get('name'); + // Inject model and axis + indicatorAxis.model = indicatorModel; + indicatorModel.axis = indicatorAxis; + this.dimensions.push(dim); + return indicatorAxis; + }, this); + + this.resize(radarModel, api); + + /** + * @type {number} + * @readOnly + */ + this.cx; + /** + * @type {number} + * @readOnly + */ + this.cy; + /** + * @type {number} + * @readOnly + */ + this.r; + /** + * @type {number} + * @readOnly + */ + this.r0; + /** + * @type {number} + * @readOnly + */ + this.startAngle; +} + +Radar.prototype.getIndicatorAxes = function () { + return this._indicatorAxes; +}; + +Radar.prototype.dataToPoint = function (value, indicatorIndex) { + var indicatorAxis = this._indicatorAxes[indicatorIndex]; + + return this.coordToPoint(indicatorAxis.dataToCoord(value), indicatorIndex); +}; + +Radar.prototype.coordToPoint = function (coord, indicatorIndex) { + var indicatorAxis = this._indicatorAxes[indicatorIndex]; + var angle = indicatorAxis.angle; + var x = this.cx + coord * Math.cos(angle); + var y = this.cy - coord * Math.sin(angle); + return [x, y]; +}; + +Radar.prototype.pointToData = function (pt) { + var dx = pt[0] - this.cx; + var dy = pt[1] - this.cy; + var radius = Math.sqrt(dx * dx + dy * dy); + dx /= radius; + dy /= radius; + + var radian = Math.atan2(-dy, dx); + + // Find the closest angle + // FIXME index can calculated directly + var minRadianDiff = Infinity; + var closestAxis; + var closestAxisIdx = -1; + for (var i = 0; i < this._indicatorAxes.length; i++) { + var indicatorAxis = this._indicatorAxes[i]; + var diff = Math.abs(radian - indicatorAxis.angle); + if (diff < minRadianDiff) { + closestAxis = indicatorAxis; + closestAxisIdx = i; + minRadianDiff = diff; + } + } + + return [closestAxisIdx, +(closestAxis && closestAxis.coodToData(radius))]; +}; + +Radar.prototype.resize = function (radarModel, api) { + var center = radarModel.get('center'); + var viewWidth = api.getWidth(); + var viewHeight = api.getHeight(); + var viewSize = Math.min(viewWidth, viewHeight) / 2; + this.cx = parsePercent$1(center[0], viewWidth); + this.cy = parsePercent$1(center[1], viewHeight); + + this.startAngle = radarModel.get('startAngle') * Math.PI / 180; + + // radius may be single value like `20`, `'80%'`, or array like `[10, '80%']` + var radius = radarModel.get('radius'); + if (typeof radius === 'string' || typeof radius === 'number') { + radius = [0, radius]; + } + this.r0 = parsePercent$1(radius[0], viewSize); + this.r = parsePercent$1(radius[1], viewSize); + + each$1(this._indicatorAxes, function (indicatorAxis, idx) { + indicatorAxis.setExtent(this.r0, this.r); + var angle = (this.startAngle + idx * Math.PI * 2 / this._indicatorAxes.length); + // Normalize to [-PI, PI] + angle = Math.atan2(Math.sin(angle), Math.cos(angle)); + indicatorAxis.angle = angle; + }, this); +}; + +Radar.prototype.update = function (ecModel, api) { + var indicatorAxes = this._indicatorAxes; + var radarModel = this._model; + each$1(indicatorAxes, function (indicatorAxis) { + indicatorAxis.scale.setExtent(Infinity, -Infinity); + }); + ecModel.eachSeriesByType('radar', function (radarSeries, idx) { + if (radarSeries.get('coordinateSystem') !== 'radar' + || ecModel.getComponent('radar', radarSeries.get('radarIndex')) !== radarModel + ) { + return; + } + var data = radarSeries.getData(); + each$1(indicatorAxes, function (indicatorAxis) { + indicatorAxis.scale.unionExtentFromData(data, data.mapDimension(indicatorAxis.dim)); + }); + }, this); + + var splitNumber = radarModel.get('splitNumber'); + + function increaseInterval(interval) { + var exp10 = Math.pow(10, Math.floor(Math.log(interval) / Math.LN10)); + // Increase interval + var f = interval / exp10; + if (f === 2) { + f = 5; + } + else { // f is 2 or 5 + f *= 2; + } + return f * exp10; + } + // Force all the axis fixing the maxSplitNumber. + each$1(indicatorAxes, function (indicatorAxis, idx) { + var rawExtent = getScaleExtent(indicatorAxis.scale, indicatorAxis.model); + niceScaleExtent(indicatorAxis.scale, indicatorAxis.model); + + var axisModel = indicatorAxis.model; + var scale = indicatorAxis.scale; + var fixedMin = axisModel.getMin(); + var fixedMax = axisModel.getMax(); + var interval = scale.getInterval(); + + if (fixedMin != null && fixedMax != null) { + // User set min, max, divide to get new interval + scale.setExtent(+fixedMin, +fixedMax); + scale.setInterval( + (fixedMax - fixedMin) / splitNumber + ); + } + else if (fixedMin != null) { + var max; + // User set min, expand extent on the other side + do { + max = fixedMin + interval * splitNumber; + scale.setExtent(+fixedMin, max); + // Interval must been set after extent + // FIXME + scale.setInterval(interval); + + interval = increaseInterval(interval); + } while (max < rawExtent[1] && isFinite(max) && isFinite(rawExtent[1])); + } + else if (fixedMax != null) { + var min; + // User set min, expand extent on the other side + do { + min = fixedMax - interval * splitNumber; + scale.setExtent(min, +fixedMax); + scale.setInterval(interval); + interval = increaseInterval(interval); + } while (min > rawExtent[0] && isFinite(min) && isFinite(rawExtent[0])); + } + else { + var nicedSplitNumber = scale.getTicks().length - 1; + if (nicedSplitNumber > splitNumber) { + interval = increaseInterval(interval); + } + // PENDING + var center = Math.round((rawExtent[0] + rawExtent[1]) / 2 / interval) * interval; + var halfSplitNumber = Math.round(splitNumber / 2); + scale.setExtent( + round$2(center - halfSplitNumber * interval), + round$2(center + (splitNumber - halfSplitNumber) * interval) + ); + scale.setInterval(interval); + } + }); +}; + +/** + * Radar dimensions is based on the data + * @type {Array} + */ +Radar.dimensions = []; + +Radar.create = function (ecModel, api) { + var radarList = []; + ecModel.eachComponent('radar', function (radarModel) { + var radar = new Radar(radarModel, ecModel, api); + radarList.push(radar); + radarModel.coordinateSystem = radar; + }); + ecModel.eachSeriesByType('radar', function (radarSeries) { + if (radarSeries.get('coordinateSystem') === 'radar') { + // Inject coordinate system + radarSeries.coordinateSystem = radarList[radarSeries.get('radarIndex') || 0]; + } + }); + return radarList; +}; + +CoordinateSystemManager.register('radar', Radar); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var valueAxisDefault = axisDefault.valueAxis; + +function defaultsShow(opt, show) { + return defaults({ + show: show + }, opt); +} + +var RadarModel = extendComponentModel({ + + type: 'radar', + + optionUpdated: function () { + var boundaryGap = this.get('boundaryGap'); + var splitNumber = this.get('splitNumber'); + var scale = this.get('scale'); + var axisLine = this.get('axisLine'); + var axisTick = this.get('axisTick'); + var axisLabel = this.get('axisLabel'); + var nameTextStyle = this.get('name'); + var showName = this.get('name.show'); + var nameFormatter = this.get('name.formatter'); + var nameGap = this.get('nameGap'); + var triggerEvent = this.get('triggerEvent'); + + var indicatorModels = map(this.get('indicator') || [], function (indicatorOpt) { + // PENDING + if (indicatorOpt.max != null && indicatorOpt.max > 0 && !indicatorOpt.min) { + indicatorOpt.min = 0; + } + else if (indicatorOpt.min != null && indicatorOpt.min < 0 && !indicatorOpt.max) { + indicatorOpt.max = 0; + } + var iNameTextStyle = nameTextStyle; + if (indicatorOpt.color != null) { + iNameTextStyle = defaults({color: indicatorOpt.color}, nameTextStyle); + } + // Use same configuration + indicatorOpt = merge(clone(indicatorOpt), { + boundaryGap: boundaryGap, + splitNumber: splitNumber, + scale: scale, + axisLine: axisLine, + axisTick: axisTick, + axisLabel: axisLabel, + // Competitable with 2 and use text + name: indicatorOpt.text, + nameLocation: 'end', + nameGap: nameGap, + // min: 0, + nameTextStyle: iNameTextStyle, + triggerEvent: triggerEvent + }, false); + if (!showName) { + indicatorOpt.name = ''; + } + if (typeof nameFormatter === 'string') { + var indName = indicatorOpt.name; + indicatorOpt.name = nameFormatter.replace('{value}', indName != null ? indName : ''); + } + else if (typeof nameFormatter === 'function') { + indicatorOpt.name = nameFormatter( + indicatorOpt.name, indicatorOpt + ); + } + var model = extend( + new Model(indicatorOpt, null, this.ecModel), + axisModelCommonMixin + ); + + // For triggerEvent. + model.mainType = 'radar'; + model.componentIndex = this.componentIndex; + + return model; + }, this); + + this.getIndicatorModels = function () { + return indicatorModels; + }; + }, + + defaultOption: { + + zlevel: 0, + + z: 0, + + center: ['50%', '50%'], + + radius: '75%', + + startAngle: 90, + + name: { + show: true + // formatter: null + // textStyle: {} + }, + + boundaryGap: [0, 0], + + splitNumber: 5, + + nameGap: 15, + + scale: false, + + // Polygon or circle + shape: 'polygon', + + axisLine: merge( + { + lineStyle: { + color: '#bbb' + } + }, + valueAxisDefault.axisLine + ), + axisLabel: defaultsShow(valueAxisDefault.axisLabel, false), + axisTick: defaultsShow(valueAxisDefault.axisTick, false), + splitLine: defaultsShow(valueAxisDefault.splitLine, true), + splitArea: defaultsShow(valueAxisDefault.splitArea, true), + + // {text, min, max} + indicator: [] + } +}); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var axisBuilderAttrs$1 = [ + 'axisLine', 'axisTickLabel', 'axisName' +]; + +extendComponentView({ + + type: 'radar', + + render: function (radarModel, ecModel, api) { + var group = this.group; + group.removeAll(); + + this._buildAxes(radarModel); + this._buildSplitLineAndArea(radarModel); + }, + + _buildAxes: function (radarModel) { + var radar = radarModel.coordinateSystem; + var indicatorAxes = radar.getIndicatorAxes(); + var axisBuilders = map(indicatorAxes, function (indicatorAxis) { + var axisBuilder = new AxisBuilder(indicatorAxis.model, { + position: [radar.cx, radar.cy], + rotation: indicatorAxis.angle, + labelDirection: -1, + tickDirection: -1, + nameDirection: 1 + }); + return axisBuilder; + }); + + each$1(axisBuilders, function (axisBuilder) { + each$1(axisBuilderAttrs$1, axisBuilder.add, axisBuilder); + this.group.add(axisBuilder.getGroup()); + }, this); + }, + + _buildSplitLineAndArea: function (radarModel) { + var radar = radarModel.coordinateSystem; + var indicatorAxes = radar.getIndicatorAxes(); + if (!indicatorAxes.length) { + return; + } + var shape = radarModel.get('shape'); + var splitLineModel = radarModel.getModel('splitLine'); + var splitAreaModel = radarModel.getModel('splitArea'); + var lineStyleModel = splitLineModel.getModel('lineStyle'); + var areaStyleModel = splitAreaModel.getModel('areaStyle'); + + var showSplitLine = splitLineModel.get('show'); + var showSplitArea = splitAreaModel.get('show'); + var splitLineColors = lineStyleModel.get('color'); + var splitAreaColors = areaStyleModel.get('color'); + + splitLineColors = isArray(splitLineColors) ? splitLineColors : [splitLineColors]; + splitAreaColors = isArray(splitAreaColors) ? splitAreaColors : [splitAreaColors]; + + var splitLines = []; + var splitAreas = []; + + function getColorIndex(areaOrLine, areaOrLineColorList, idx) { + var colorIndex = idx % areaOrLineColorList.length; + areaOrLine[colorIndex] = areaOrLine[colorIndex] || []; + return colorIndex; + } + + if (shape === 'circle') { + var ticksRadius = indicatorAxes[0].getTicksCoords(); + var cx = radar.cx; + var cy = radar.cy; + for (var i = 0; i < ticksRadius.length; i++) { + if (showSplitLine) { + var colorIndex = getColorIndex(splitLines, splitLineColors, i); + splitLines[colorIndex].push(new Circle({ + shape: { + cx: cx, + cy: cy, + r: ticksRadius[i].coord + } + })); + } + if (showSplitArea && i < ticksRadius.length - 1) { + var colorIndex = getColorIndex(splitAreas, splitAreaColors, i); + splitAreas[colorIndex].push(new Ring({ + shape: { + cx: cx, + cy: cy, + r0: ticksRadius[i].coord, + r: ticksRadius[i + 1].coord + } + })); + } + } + } + // Polyyon + else { + var realSplitNumber; + var axesTicksPoints = map(indicatorAxes, function (indicatorAxis, idx) { + var ticksCoords = indicatorAxis.getTicksCoords(); + realSplitNumber = realSplitNumber == null + ? ticksCoords.length - 1 + : Math.min(ticksCoords.length - 1, realSplitNumber); + return map(ticksCoords, function (tickCoord) { + return radar.coordToPoint(tickCoord.coord, idx); + }); + }); + + var prevPoints = []; + for (var i = 0; i <= realSplitNumber; i++) { + var points = []; + for (var j = 0; j < indicatorAxes.length; j++) { + points.push(axesTicksPoints[j][i]); + } + // Close + if (points[0]) { + points.push(points[0].slice()); + } + else { + if (__DEV__) { + console.error('Can\'t draw value axis ' + i); + } + } + + if (showSplitLine) { + var colorIndex = getColorIndex(splitLines, splitLineColors, i); + splitLines[colorIndex].push(new Polyline({ + shape: { + points: points + } + })); + } + if (showSplitArea && prevPoints) { + var colorIndex = getColorIndex(splitAreas, splitAreaColors, i - 1); + splitAreas[colorIndex].push(new Polygon({ + shape: { + points: points.concat(prevPoints) + } + })); + } + prevPoints = points.slice().reverse(); + } + } + + var lineStyle = lineStyleModel.getLineStyle(); + var areaStyle = areaStyleModel.getAreaStyle(); + // Add splitArea before splitLine + each$1(splitAreas, function (splitAreas, idx) { + this.group.add(mergePath( + splitAreas, { + style: defaults({ + stroke: 'none', + fill: splitAreaColors[idx % splitAreaColors.length] + }, areaStyle), + silent: true + } + )); + }, this); + + each$1(splitLines, function (splitLines, idx) { + this.group.add(mergePath( + splitLines, { + style: defaults({ + fill: 'none', + stroke: splitLineColors[idx % splitLineColors.length] + }, lineStyle), + silent: true + } + )); + }, this); + + } +}); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var RadarSeries = SeriesModel.extend({ + + type: 'series.radar', + + dependencies: ['radar'], + + + // Overwrite + init: function (option) { + RadarSeries.superApply(this, 'init', arguments); + + // Enable legend selection for each data item + // Use a function instead of direct access because data reference may changed + this.legendDataProvider = function () { + return this.getRawData(); + }; + }, + + getInitialData: function (option, ecModel) { + return createListSimply(this, { + generateCoord: 'indicator_', + generateCoordCount: Infinity + }); + }, + + formatTooltip: function (dataIndex) { + var data = this.getData(); + var coordSys = this.coordinateSystem; + var indicatorAxes = coordSys.getIndicatorAxes(); + var name = this.getData().getName(dataIndex); + return encodeHTML(name === '' ? this.name : name) + '
' + + map(indicatorAxes, function (axis, idx) { + var val = data.get(data.mapDimension(axis.dim), dataIndex); + return encodeHTML(axis.name + ' : ' + val); + }).join('
'); + }, + + defaultOption: { + zlevel: 0, + z: 2, + coordinateSystem: 'radar', + legendHoverLink: true, + radarIndex: 0, + lineStyle: { + width: 2, + type: 'solid' + }, + label: { + position: 'top' + }, + // areaStyle: { + // }, + // itemStyle: {} + symbol: 'emptyCircle', + symbolSize: 4 + // symbolRotate: null + } +}); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +function normalizeSymbolSize(symbolSize) { + if (!isArray(symbolSize)) { + symbolSize = [+symbolSize, +symbolSize]; + } + return symbolSize; +} + +extendChartView({ + + type: 'radar', + + render: function (seriesModel, ecModel, api) { + var polar = seriesModel.coordinateSystem; + var group = this.group; + + var data = seriesModel.getData(); + var oldData = this._data; + + function createSymbol$$1(data, idx) { + var symbolType = data.getItemVisual(idx, 'symbol') || 'circle'; + var color = data.getItemVisual(idx, 'color'); + if (symbolType === 'none') { + return; + } + var symbolSize = normalizeSymbolSize( + data.getItemVisual(idx, 'symbolSize') + ); + var symbolPath = createSymbol( + symbolType, -1, -1, 2, 2, color + ); + symbolPath.attr({ + style: { + strokeNoScale: true + }, + z2: 100, + scale: [symbolSize[0] / 2, symbolSize[1] / 2] + }); + return symbolPath; + } + + function updateSymbols(oldPoints, newPoints, symbolGroup, data, idx, isInit) { + // Simply rerender all + symbolGroup.removeAll(); + for (var i = 0; i < newPoints.length - 1; i++) { + var symbolPath = createSymbol$$1(data, idx); + if (symbolPath) { + symbolPath.__dimIdx = i; + if (oldPoints[i]) { + symbolPath.attr('position', oldPoints[i]); + graphic[isInit ? 'initProps' : 'updateProps']( + symbolPath, { + position: newPoints[i] + }, seriesModel, idx + ); + } + else { + symbolPath.attr('position', newPoints[i]); + } + symbolGroup.add(symbolPath); + } + } + } + + function getInitialPoints(points) { + return map(points, function (pt) { + return [polar.cx, polar.cy]; + }); + } + data.diff(oldData) + .add(function (idx) { + var points = data.getItemLayout(idx); + if (!points) { + return; + } + var polygon = new Polygon(); + var polyline = new Polyline(); + var target = { + shape: { + points: points + } + }; + polygon.shape.points = getInitialPoints(points); + polyline.shape.points = getInitialPoints(points); + initProps(polygon, target, seriesModel, idx); + initProps(polyline, target, seriesModel, idx); + + var itemGroup = new Group(); + var symbolGroup = new Group(); + itemGroup.add(polyline); + itemGroup.add(polygon); + itemGroup.add(symbolGroup); + + updateSymbols( + polyline.shape.points, points, symbolGroup, data, idx, true + ); + + data.setItemGraphicEl(idx, itemGroup); + }) + .update(function (newIdx, oldIdx) { + var itemGroup = oldData.getItemGraphicEl(oldIdx); + var polyline = itemGroup.childAt(0); + var polygon = itemGroup.childAt(1); + var symbolGroup = itemGroup.childAt(2); + var target = { + shape: { + points: data.getItemLayout(newIdx) + } + }; + if (!target.shape.points) { + return; + } + updateSymbols( + polyline.shape.points, target.shape.points, symbolGroup, data, newIdx, false + ); + + updateProps(polyline, target, seriesModel); + updateProps(polygon, target, seriesModel); + + data.setItemGraphicEl(newIdx, itemGroup); + }) + .remove(function (idx) { + group.remove(oldData.getItemGraphicEl(idx)); + }) + .execute(); + + data.eachItemGraphicEl(function (itemGroup, idx) { + var itemModel = data.getItemModel(idx); + var polyline = itemGroup.childAt(0); + var polygon = itemGroup.childAt(1); + var symbolGroup = itemGroup.childAt(2); + var color = data.getItemVisual(idx, 'color'); + + group.add(itemGroup); + + polyline.useStyle( + defaults( + itemModel.getModel('lineStyle').getLineStyle(), + { + fill: 'none', + stroke: color + } + ) + ); + polyline.hoverStyle = itemModel.getModel('emphasis.lineStyle').getLineStyle(); + + var areaStyleModel = itemModel.getModel('areaStyle'); + var hoverAreaStyleModel = itemModel.getModel('emphasis.areaStyle'); + var polygonIgnore = areaStyleModel.isEmpty() && areaStyleModel.parentModel.isEmpty(); + var hoverPolygonIgnore = hoverAreaStyleModel.isEmpty() && hoverAreaStyleModel.parentModel.isEmpty(); + + hoverPolygonIgnore = hoverPolygonIgnore && polygonIgnore; + polygon.ignore = polygonIgnore; + + polygon.useStyle( + defaults( + areaStyleModel.getAreaStyle(), + { + fill: color, + opacity: 0.7 + } + ) + ); + polygon.hoverStyle = hoverAreaStyleModel.getAreaStyle(); + + var itemStyle = itemModel.getModel('itemStyle').getItemStyle(['color']); + var itemHoverStyle = itemModel.getModel('emphasis.itemStyle').getItemStyle(); + var labelModel = itemModel.getModel('label'); + var labelHoverModel = itemModel.getModel('emphasis.label'); + symbolGroup.eachChild(function (symbolPath) { + symbolPath.setStyle(itemStyle); + symbolPath.hoverStyle = clone(itemHoverStyle); + + setLabelStyle( + symbolPath.style, symbolPath.hoverStyle, labelModel, labelHoverModel, + { + labelFetcher: data.hostModel, + labelDataIndex: idx, + labelDimIndex: symbolPath.__dimIdx, + defaultText: data.get(data.dimensions[symbolPath.__dimIdx], idx), + autoColor: color, + isRectText: true + } + ); + }); + + function onEmphasis() { + polygon.attr('ignore', hoverPolygonIgnore); + } + + function onNormal() { + polygon.attr('ignore', polygonIgnore); + } + + itemGroup.off('mouseover').off('mouseout').off('normal').off('emphasis'); + itemGroup.on('emphasis', onEmphasis) + .on('mouseover', onEmphasis) + .on('normal', onNormal) + .on('mouseout', onNormal); + + setHoverStyle(itemGroup); + }); + + this._data = data; + }, + + remove: function () { + this.group.removeAll(); + this._data = null; + }, + + dispose: function () {} +}); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + + +var radarLayout = function (ecModel) { + ecModel.eachSeriesByType('radar', function (seriesModel) { + var data = seriesModel.getData(); + var points = []; + var coordSys = seriesModel.coordinateSystem; + if (!coordSys) { + return; + } + + function pointsConverter(val, idx) { + points[idx] = points[idx] || []; + points[idx][i] = coordSys.dataToPoint(val, i); + } + var axes = coordSys.getIndicatorAxes(); + for (var i = 0; i < axes.length; i++) { + data.each(data.mapDimension(axes[i].dim), pointsConverter); + } + + data.each(function (idx) { + // Close polygon + points[idx][0] && points[idx].push(points[idx][0].slice()); + data.setItemLayout(idx, points[idx]); + }); + }); +}; + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +// Backward compat for radar chart in 2 +var backwardCompat$1 = function (option) { + var polarOptArr = option.polar; + if (polarOptArr) { + if (!isArray(polarOptArr)) { + polarOptArr = [polarOptArr]; + } + var polarNotRadar = []; + each$1(polarOptArr, function (polarOpt, idx) { + if (polarOpt.indicator) { + if (polarOpt.type && !polarOpt.shape) { + polarOpt.shape = polarOpt.type; + } + option.radar = option.radar || []; + if (!isArray(option.radar)) { + option.radar = [option.radar]; + } + option.radar.push(polarOpt); + } + else { + polarNotRadar.push(polarOpt); + } + }); + option.polar = polarNotRadar; + } + each$1(option.series, function (seriesOpt) { + if (seriesOpt && seriesOpt.type === 'radar' && seriesOpt.polarIndex) { + seriesOpt.radarIndex = seriesOpt.polarIndex; + } + }); +}; + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + + +// Must use radar component +registerVisual(dataColor('radar')); +registerVisual(visualSymbol('radar', 'circle')); +registerLayout(radarLayout); +registerProcessor(dataFilter('radar')); +registerPreprocessor(backwardCompat$1); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +// Fix for 南海诸岛 + +var geoCoord = [126, 25]; + +var points$1 = [ + [[0, 3.5], [7, 11.2], [15, 11.9], [30, 7], [42, 0.7], [52, 0.7], + [56, 7.7], [59, 0.7], [64, 0.7], [64, 0], [5, 0], [0, 3.5]], + [[13, 16.1], [19, 14.7], [16, 21.7], [11, 23.1], [13, 16.1]], + [[12, 32.2], [14, 38.5], [15, 38.5], [13, 32.2], [12, 32.2]], + [[16, 47.6], [12, 53.2], [13, 53.2], [18, 47.6], [16, 47.6]], + [[6, 64.4], [8, 70], [9, 70], [8, 64.4], [6, 64.4]], + [[23, 82.6], [29, 79.8], [30, 79.8], [25, 82.6], [23, 82.6]], + [[37, 70.7], [43, 62.3], [44, 62.3], [39, 70.7], [37, 70.7]], + [[48, 51.1], [51, 45.5], [53, 45.5], [50, 51.1], [48, 51.1]], + [[51, 35], [51, 28.7], [53, 28.7], [53, 35], [51, 35]], + [[52, 22.4], [55, 17.5], [56, 17.5], [53, 22.4], [52, 22.4]], + [[58, 12.6], [62, 7], [63, 7], [60, 12.6], [58, 12.6]], + [[0, 3.5], [0, 93.1], [64, 93.1], [64, 0], [63, 0], [63, 92.4], + [1, 92.4], [1, 3.5], [0, 3.5]] +]; + +for (var i$1 = 0; i$1 < points$1.length; i$1++) { + for (var k = 0; k < points$1[i$1].length; k++) { + points$1[i$1][k][0] /= 10.5; + points$1[i$1][k][1] /= -10.5 / 0.75; + + points$1[i$1][k][0] += geoCoord[0]; + points$1[i$1][k][1] += geoCoord[1]; + } +} + +var fixNanhai = function (mapType, regions) { + if (mapType === 'china') { + regions.push(new Region( + '南海诸岛', + map(points$1, function (exterior) { + return { + type: 'polygon', + exterior: exterior + }; + }), geoCoord + )); + } +}; + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var coordsOffsetMap = { + '南海诸岛': [32, 80], + // 全国 + '广东': [0, -10], + '香港': [10, 5], + '澳门': [-10, 10], + //'北京': [-10, 0], + '天津': [5, 5] +}; + +var fixTextCoord = function (mapType, region) { + if (mapType === 'china') { + var coordFix = coordsOffsetMap[region.name]; + if (coordFix) { + var cp = region.center; + cp[0] += coordFix[0] / 10.5; + cp[1] += -coordFix[1] / (10.5 / 0.75); + } + } +}; + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var geoCoordMap = { + 'Russia': [100, 60], + 'United States': [-99, 38], + 'United States of America': [-99, 38] +}; + +var fixGeoCoord = function (mapType, region) { + if (mapType === 'world') { + var geoCoord = geoCoordMap[region.name]; + if (geoCoord) { + var cp = region.center; + cp[0] = geoCoord[0]; + cp[1] = geoCoord[1]; + } + } +}; + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +// Fix for 钓鱼岛 + +// var Region = require('../Region'); +// var zrUtil = require('zrender/src/core/util'); + +// var geoCoord = [126, 25]; + +var points$2 = [ + [ + [123.45165252685547, 25.73527164402261], + [123.49731445312499, 25.73527164402261], + [123.49731445312499, 25.750734064600884], + [123.45165252685547, 25.750734064600884], + [123.45165252685547, 25.73527164402261] + ] +]; + +var fixDiaoyuIsland = function (mapType, region) { + if (mapType === 'china' && region.name === '台湾') { + region.geometries.push({ + type: 'polygon', + exterior: points$2[0] + }); + } +}; + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +// Built-in GEO fixer. +var inner$7 = makeInner(); + +var geoJSONLoader = { + + /** + * @param {string} mapName + * @param {Object} mapRecord {specialAreas, geoJSON} + * @return {Object} {regions, boundingRect} + */ + load: function (mapName, mapRecord) { + + var parsed = inner$7(mapRecord).parsed; + + if (parsed) { + return parsed; + } + + var specialAreas = mapRecord.specialAreas || {}; + var geoJSON = mapRecord.geoJSON; + var regions; + + // https://jsperf.com/try-catch-performance-overhead + try { + regions = geoJSON ? parseGeoJson$1(geoJSON) : []; + } + catch (e) { + throw new Error('Invalid geoJson format\n' + e.message); + } + + each$1(regions, function (region) { + var regionName = region.name; + + fixTextCoord(mapName, region); + fixGeoCoord(mapName, region); + fixDiaoyuIsland(mapName, region); + + // Some area like Alaska in USA map needs to be tansformed + // to look better + var specialArea = specialAreas[regionName]; + if (specialArea) { + region.transformTo( + specialArea.left, specialArea.top, specialArea.width, specialArea.height + ); + } + }); + + fixNanhai(mapName, regions); + + return (inner$7(mapRecord).parsed = { + regions: regions, + boundingRect: getBoundingRect$1(regions) + }); + } +}; + +function getBoundingRect$1(regions) { + var rect; + for (var i = 0; i < regions.length; i++) { + var regionRect = regions[i].getBoundingRect(); + rect = rect || regionRect.clone(); + rect.union(regionRect); + } + return rect; +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var inner$8 = makeInner(); + +var geoSVGLoader = { + + /** + * @param {string} mapName + * @param {Object} mapRecord {specialAreas, geoJSON} + * @return {Object} {root, boundingRect} + */ + load: function (mapName, mapRecord) { + var originRoot = inner$8(mapRecord).originRoot; + if (originRoot) { + return { + root: originRoot, + boundingRect: inner$8(mapRecord).boundingRect + }; + } + + var graphic = buildGraphic(mapRecord); + + inner$8(mapRecord).originRoot = graphic.root; + inner$8(mapRecord).boundingRect = graphic.boundingRect; + + return graphic; + }, + + makeGraphic: function (mapName, mapRecord, hostKey) { + // For performance consideration (in large SVG), graphic only maked + // when necessary and reuse them according to hostKey. + var field = inner$8(mapRecord); + var rootMap = field.rootMap || (field.rootMap = createHashMap()); + + var root = rootMap.get(hostKey); + if (root) { + return root; + } + + var originRoot = field.originRoot; + var boundingRect = field.boundingRect; + + // For performance, if originRoot is not used by a view, + // assign it to a view, but not reproduce graphic elements. + if (!field.originRootHostKey) { + field.originRootHostKey = hostKey; + root = originRoot; + } + else { + root = buildGraphic(mapRecord, boundingRect).root; + } + + return rootMap.set(hostKey, root); + }, + + removeGraphic: function (mapName, mapRecord, hostKey) { + var field = inner$8(mapRecord); + var rootMap = field.rootMap; + rootMap && rootMap.removeKey(hostKey); + if (hostKey === field.originRootHostKey) { + field.originRootHostKey = null; + } + } +}; + +function buildGraphic(mapRecord, boundingRect) { + var svgXML = mapRecord.svgXML; + var result; + var root; + + try { + result = svgXML && parseSVG(svgXML, { + ignoreViewBox: true, + ignoreRootClip: true + }) || {}; + root = result.root; + assert$1(root != null); + } + catch (e) { + throw new Error('Invalid svg format\n' + e.message); + } + + var svgWidth = result.width; + var svgHeight = result.height; + var viewBoxRect = result.viewBoxRect; + + if (!boundingRect) { + boundingRect = (svgWidth == null || svgHeight == null) + // If svg width / height not specified, calculate + // bounding rect as the width / height + ? root.getBoundingRect() + : new BoundingRect(0, 0, 0, 0); + + if (svgWidth != null) { + boundingRect.width = svgWidth; + } + if (svgHeight != null) { + boundingRect.height = svgHeight; + } + } + + if (viewBoxRect) { + var viewBoxTransform = makeViewBoxTransform(viewBoxRect, boundingRect.width, boundingRect.height); + var elRoot = root; + root = new Group(); + root.add(elRoot); + elRoot.scale = viewBoxTransform.scale; + elRoot.position = viewBoxTransform.position; + } + + root.setClipPath(new Rect({ + shape: boundingRect.plain() + })); + + return { + root: root, + boundingRect: boundingRect + }; +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var loaders = { + geoJSON: geoJSONLoader, + svg: geoSVGLoader +}; + +var geoSourceManager = { + + /** + * @param {string} mapName + * @param {Object} nameMap + * @return {Object} source {regions, regionsMap, nameCoordMap, boundingRect} + */ + load: function (mapName, nameMap) { + var regions = []; + var regionsMap = createHashMap(); + var nameCoordMap = createHashMap(); + var boundingRect; + var mapRecords = retrieveMap(mapName); + + each$1(mapRecords, function (record) { + var singleSource = loaders[record.type].load(mapName, record); + + each$1(singleSource.regions, function (region) { + var regionName = region.name; + + // Try use the alias in geoNameMap + if (nameMap && nameMap.hasOwnProperty(regionName)) { + region = region.cloneShallow(regionName = nameMap[regionName]); + } + + regions.push(region); + regionsMap.set(regionName, region); + nameCoordMap.set(regionName, region.center); + }); + + var rect = singleSource.boundingRect; + if (rect) { + boundingRect + ? boundingRect.union(rect) + : (boundingRect = rect.clone()); + } + }); + + return { + regions: regions, + regionsMap: regionsMap, + nameCoordMap: nameCoordMap, + // FIXME Always return new ? + boundingRect: boundingRect || new BoundingRect(0, 0, 0, 0) + }; + }, + + /** + * @param {string} mapName + * @param {string} hostKey For cache. + * @return {Array.} Roots. + */ + makeGraphic: makeInvoker('makeGraphic'), + + /** + * @param {string} mapName + * @param {string} hostKey For cache. + */ + removeGraphic: makeInvoker('removeGraphic') +}; + +function makeInvoker(methodName) { + return function (mapName, hostKey) { + var mapRecords = retrieveMap(mapName); + var results = []; + + each$1(mapRecords, function (record) { + var method = loaders[record.type][methodName]; + method && results.push(method(mapName, record, hostKey)); + }); + + return results; + }; +} + +function mapNotExistsError(mapName) { + if (__DEV__) { + console.error( + 'Map ' + mapName + ' not exists. You can download map file on http://echarts.baidu.com/download-map.html' + ); + } +} + +function retrieveMap(mapName) { + var mapRecords = mapDataStorage.retrieveMap(mapName) || []; + + if (__DEV__) { + if (!mapRecords.length) { + mapNotExistsError(mapName); + } + } + + return mapRecords; +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var MapSeries = SeriesModel.extend({ + + type: 'series.map', + + dependencies: ['geo'], + + layoutMode: 'box', + + /** + * Only first map series of same mapType will drawMap + * @type {boolean} + */ + needsDrawMap: false, + + /** + * Group of all map series with same mapType + * @type {boolean} + */ + seriesGroup: [], + + getInitialData: function (option) { + var data = createListSimply(this, ['value']); + var valueDim = data.mapDimension('value'); + var dataNameMap = createHashMap(); + var selectTargetList = []; + var toAppendNames = []; + + for (var i = 0, len = data.count(); i < len; i++) { + var name = data.getName(i); + dataNameMap.set(name, true); + selectTargetList.push({ + name: name, + value: data.get(valueDim, i), + selected: retrieveRawAttr(data, i, 'selected') + }); + } + + var geoSource = geoSourceManager.load(this.getMapType(), this.option.nameMap); + each$1(geoSource.regions, function (region) { + var name = region.name; + if (!dataNameMap.get(name)) { + selectTargetList.push({name: name}); + toAppendNames.push(name); + } + }); + + this.updateSelectedMap(selectTargetList); + + // Complete data with missing regions. The consequent processes (like visual + // map and render) can not be performed without a "full data". For example, + // find `dataIndex` by name. + data.appendValues([], toAppendNames); + + return data; + }, + + /** + * If no host geo model, return null, which means using a + * inner exclusive geo model. + */ + getHostGeoModel: function () { + var geoIndex = this.option.geoIndex; + return geoIndex != null + ? this.dependentModels.geo[geoIndex] + : null; + }, + + getMapType: function () { + return (this.getHostGeoModel() || this).option.map; + }, + + // _fillOption: function (option, mapName) { + // Shallow clone + // option = zrUtil.extend({}, option); + + // option.data = geoCreator.getFilledRegions(option.data, mapName, option.nameMap); + + // return option; + // }, + + getRawValue: function (dataIndex) { + // Use value stored in data instead because it is calculated from multiple series + // FIXME Provide all value of multiple series ? + var data = this.getData(); + return data.get(data.mapDimension('value'), dataIndex); + }, + + /** + * Get model of region + * @param {string} name + * @return {module:echarts/model/Model} + */ + getRegionModel: function (regionName) { + var data = this.getData(); + return data.getItemModel(data.indexOfName(regionName)); + }, + + /** + * Map tooltip formatter + * + * @param {number} dataIndex + */ + formatTooltip: function (dataIndex) { + // FIXME orignalData and data is a bit confusing + var data = this.getData(); + var formattedValue = addCommas(this.getRawValue(dataIndex)); + var name = data.getName(dataIndex); + + var seriesGroup = this.seriesGroup; + var seriesNames = []; + for (var i = 0; i < seriesGroup.length; i++) { + var otherIndex = seriesGroup[i].originalData.indexOfName(name); + var valueDim = data.mapDimension('value'); + if (!isNaN(seriesGroup[i].originalData.get(valueDim, otherIndex))) { + seriesNames.push( + encodeHTML(seriesGroup[i].name) + ); + } + } + + return seriesNames.join(', ') + '
' + + encodeHTML(name + ' : ' + formattedValue); + }, + + /** + * @implement + */ + getTooltipPosition: function (dataIndex) { + if (dataIndex != null) { + var name = this.getData().getName(dataIndex); + var geo = this.coordinateSystem; + var region = geo.getRegion(name); + + return region && geo.dataToPoint(region.center); + } + }, + + setZoom: function (zoom) { + this.option.zoom = zoom; + }, + + setCenter: function (center) { + this.option.center = center; + }, + + defaultOption: { + // 一级层叠 + zlevel: 0, + // 二级层叠 + z: 2, + + coordinateSystem: 'geo', + + // map should be explicitly specified since ec3. + map: '', + + // If `geoIndex` is not specified, a exclusive geo will be + // created. Otherwise use the specified geo component, and + // `map` and `mapType` are ignored. + // geoIndex: 0, + + // 'center' | 'left' | 'right' | 'x%' | {number} + left: 'center', + // 'center' | 'top' | 'bottom' | 'x%' | {number} + top: 'center', + // right + // bottom + // width: + // height + + // Aspect is width / height. Inited to be geoJson bbox aspect + // This parameter is used for scale this aspect + aspectScale: 0.75, + + ///// Layout with center and size + // If you wan't to put map in a fixed size box with right aspect ratio + // This two properties may more conveninet + // layoutCenter: [50%, 50%] + // layoutSize: 100 + + + // 数值合并方式,默认加和,可选为: + // 'sum' | 'average' | 'max' | 'min' + // mapValueCalculation: 'sum', + // 地图数值计算结果小数精度 + // mapValuePrecision: 0, + + + // 显示图例颜色标识(系列标识的小圆点),图例开启时有效 + showLegendSymbol: true, + // 选择模式,默认关闭,可选single,multiple + // selectedMode: false, + dataRangeHoverLink: true, + // 是否开启缩放及漫游模式 + // roam: false, + + // Define left-top, right-bottom coords to control view + // For example, [ [180, 90], [-180, -90] ], + // higher priority than center and zoom + boundingCoords: null, + + // Default on center of map + center: null, + + zoom: 1, + + scaleLimit: null, + + label: { + show: false, + color: '#000' + }, + // scaleLimit: null, + itemStyle: { + borderWidth: 0.5, + borderColor: '#444', + areaColor: '#eee' + }, + + emphasis: { + label: { + show: true, + color: 'rgb(100,0,0)' + }, + itemStyle: { + areaColor: 'rgba(255,215,0,0.8)' + } + } + } + +}); + +mixin(MapSeries, selectableMixin); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var ATTR = '\0_ec_interaction_mutex'; + +function take(zr, resourceKey, userKey) { + var store = getStore(zr); + store[resourceKey] = userKey; +} + +function release(zr, resourceKey, userKey) { + var store = getStore(zr); + var uKey = store[resourceKey]; + + if (uKey === userKey) { + store[resourceKey] = null; + } +} + +function isTaken(zr, resourceKey) { + return !!getStore(zr)[resourceKey]; +} + +function getStore(zr) { + return zr[ATTR] || (zr[ATTR] = {}); +} + +/** + * payload: { + * type: 'takeGlobalCursor', + * key: 'dataZoomSelect', or 'brush', or ..., + * If no userKey, release global cursor. + * } + */ +registerAction( + {type: 'takeGlobalCursor', event: 'globalCursorTaken', update: 'update'}, + function () {} +); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/** + * @alias module:echarts/component/helper/RoamController + * @constructor + * @mixin {module:zrender/mixin/Eventful} + * + * @param {module:zrender/zrender~ZRender} zr + */ +function RoamController(zr) { + + /** + * @type {Function} + */ + this.pointerChecker; + + /** + * @type {module:zrender} + */ + this._zr = zr; + + /** + * @type {Object} + */ + this._opt = {}; + + // Avoid two roamController bind the same handler + var bind$$1 = bind; + var mousedownHandler = bind$$1(mousedown, this); + var mousemoveHandler = bind$$1(mousemove, this); + var mouseupHandler = bind$$1(mouseup, this); + var mousewheelHandler = bind$$1(mousewheel, this); + var pinchHandler = bind$$1(pinch, this); + + Eventful.call(this); + + /** + * @param {Function} pointerChecker + * input: x, y + * output: boolean + */ + this.setPointerChecker = function (pointerChecker) { + this.pointerChecker = pointerChecker; + }; + + /** + * Notice: only enable needed types. For example, if 'zoom' + * is not needed, 'zoom' should not be enabled, otherwise + * default mousewheel behaviour (scroll page) will be disabled. + * + * @param {boolean|string} [controlType=true] Specify the control type, + * which can be null/undefined or true/false + * or 'pan/move' or 'zoom'/'scale' + * @param {Object} [opt] + * @param {Object} [opt.zoomOnMouseWheel=true] The value can be: true / false / 'shift' / 'ctrl' / 'alt'. + * @param {Object} [opt.moveOnMouseMove=true] The value can be: true / false / 'shift' / 'ctrl' / 'alt'. + * @param {Object} [opt.moveOnMouseWheel=false] The value can be: true / false / 'shift' / 'ctrl' / 'alt'. + * @param {Object} [opt.preventDefaultMouseMove=true] When pan. + */ + this.enable = function (controlType, opt) { + + // Disable previous first + this.disable(); + + this._opt = defaults(clone(opt) || {}, { + zoomOnMouseWheel: true, + moveOnMouseMove: true, + // By default, wheel do not trigger move. + moveOnMouseWheel: false, + preventDefaultMouseMove: true + }); + + if (controlType == null) { + controlType = true; + } + + if (controlType === true || (controlType === 'move' || controlType === 'pan')) { + zr.on('mousedown', mousedownHandler); + zr.on('mousemove', mousemoveHandler); + zr.on('mouseup', mouseupHandler); + } + if (controlType === true || (controlType === 'scale' || controlType === 'zoom')) { + zr.on('mousewheel', mousewheelHandler); + zr.on('pinch', pinchHandler); + } + }; + + this.disable = function () { + zr.off('mousedown', mousedownHandler); + zr.off('mousemove', mousemoveHandler); + zr.off('mouseup', mouseupHandler); + zr.off('mousewheel', mousewheelHandler); + zr.off('pinch', pinchHandler); + }; + + this.dispose = this.disable; + + this.isDragging = function () { + return this._dragging; + }; + + this.isPinching = function () { + return this._pinching; + }; +} + +mixin(RoamController, Eventful); + + +function mousedown(e) { + if (isMiddleOrRightButtonOnMouseUpDown(e) + || (e.target && e.target.draggable) + ) { + return; + } + + var x = e.offsetX; + var y = e.offsetY; + + // Only check on mosedown, but not mousemove. + // Mouse can be out of target when mouse moving. + if (this.pointerChecker && this.pointerChecker(e, x, y)) { + this._x = x; + this._y = y; + this._dragging = true; + } +} + +function mousemove(e) { + if (!this._dragging + || !isAvailableBehavior('moveOnMouseMove', e, this._opt) + || e.gestureEvent === 'pinch' + || isTaken(this._zr, 'globalPan') + ) { + return; + } + + var x = e.offsetX; + var y = e.offsetY; + + var oldX = this._x; + var oldY = this._y; + + var dx = x - oldX; + var dy = y - oldY; + + this._x = x; + this._y = y; + + this._opt.preventDefaultMouseMove && stop(e.event); + + trigger(this, 'pan', 'moveOnMouseMove', e, { + dx: dx, dy: dy, oldX: oldX, oldY: oldY, newX: x, newY: y + }); +} + +function mouseup(e) { + if (!isMiddleOrRightButtonOnMouseUpDown(e)) { + this._dragging = false; + } +} + +function mousewheel(e) { + var shouldZoom = isAvailableBehavior('zoomOnMouseWheel', e, this._opt); + var shouldMove = isAvailableBehavior('moveOnMouseWheel', e, this._opt); + var wheelDelta = e.wheelDelta; + var absWheelDeltaDelta = Math.abs(wheelDelta); + var originX = e.offsetX; + var originY = e.offsetY; + + // wheelDelta maybe -0 in chrome mac. + if (wheelDelta === 0 || (!shouldZoom && !shouldMove)) { + return; + } + + // If both `shouldZoom` and `shouldMove` is true, trigger + // their event both, and the final behavior is determined + // by event listener themselves. + + if (shouldZoom) { + // Convenience: + // Mac and VM Windows on Mac: scroll up: zoom out. + // Windows: scroll up: zoom in. + + // FIXME: Should do more test in different environment. + // wheelDelta is too complicated in difference nvironment + // (https://developer.mozilla.org/en-US/docs/Web/Events/mousewheel), + // although it has been normallized by zrender. + // wheelDelta of mouse wheel is bigger than touch pad. + var factor = absWheelDeltaDelta > 3 ? 1.4 : absWheelDeltaDelta > 1 ? 1.2 : 1.1; + var scale = wheelDelta > 0 ? factor : 1 / factor; + checkPointerAndTrigger(this, 'zoom', 'zoomOnMouseWheel', e, { + scale: scale, originX: originX, originY: originY + }); + } + + if (shouldMove) { + // FIXME: Should do more test in different environment. + var absDelta = Math.abs(wheelDelta); + // wheelDelta of mouse wheel is bigger than touch pad. + var scrollDelta = (wheelDelta > 0 ? 1 : -1) * (absDelta > 3 ? 0.4 : absDelta > 1 ? 0.15 : 0.05); + checkPointerAndTrigger(this, 'scrollMove', 'moveOnMouseWheel', e, { + scrollDelta: scrollDelta, originX: originX, originY: originY + }); + } +} + +function pinch(e) { + if (isTaken(this._zr, 'globalPan')) { + return; + } + var scale = e.pinchScale > 1 ? 1.1 : 1 / 1.1; + checkPointerAndTrigger(this, 'zoom', null, e, { + scale: scale, originX: e.pinchX, originY: e.pinchY + }); +} + +function checkPointerAndTrigger(controller, eventName, behaviorToCheck, e, contollerEvent) { + if (controller.pointerChecker + && controller.pointerChecker(e, contollerEvent.originX, contollerEvent.originY) + ) { + // When mouse is out of roamController rect, + // default befavoius should not be be disabled, otherwise + // page sliding is disabled, contrary to expectation. + stop(e.event); + + trigger(controller, eventName, behaviorToCheck, e, contollerEvent); + } +} + +function trigger(controller, eventName, behaviorToCheck, e, contollerEvent) { + // Also provide behavior checker for event listener, for some case that + // multiple components share one listener. + contollerEvent.isAvailableBehavior = bind(isAvailableBehavior, null, behaviorToCheck, e); + controller.trigger(eventName, contollerEvent); +} + +// settings: { +// zoomOnMouseWheel +// moveOnMouseMove +// moveOnMouseWheel +// } +// The value can be: true / false / 'shift' / 'ctrl' / 'alt'. +function isAvailableBehavior(behaviorToCheck, e, settings) { + var setting = settings[behaviorToCheck]; + return !behaviorToCheck || ( + setting && (!isString(setting) || e.event[setting + 'Key']) + ); +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + + +/** + * For geo and graph. + * + * @param {Object} controllerHost + * @param {module:zrender/Element} controllerHost.target + */ +function updateViewOnPan(controllerHost, dx, dy) { + var target = controllerHost.target; + var pos = target.position; + pos[0] += dx; + pos[1] += dy; + target.dirty(); +} + +/** + * For geo and graph. + * + * @param {Object} controllerHost + * @param {module:zrender/Element} controllerHost.target + * @param {number} controllerHost.zoom + * @param {number} controllerHost.zoomLimit like: {min: 1, max: 2} + */ +function updateViewOnZoom(controllerHost, zoomDelta, zoomX, zoomY) { + var target = controllerHost.target; + var zoomLimit = controllerHost.zoomLimit; + var pos = target.position; + var scale = target.scale; + + var newZoom = controllerHost.zoom = controllerHost.zoom || 1; + newZoom *= zoomDelta; + if (zoomLimit) { + var zoomMin = zoomLimit.min || 0; + var zoomMax = zoomLimit.max || Infinity; + newZoom = Math.max( + Math.min(zoomMax, newZoom), + zoomMin + ); + } + var zoomScale = newZoom / controllerHost.zoom; + controllerHost.zoom = newZoom; + // Keep the mouse center when scaling + pos[0] -= (zoomX - pos[0]) * (zoomScale - 1); + pos[1] -= (zoomY - pos[1]) * (zoomScale - 1); + scale[0] *= zoomScale; + scale[1] *= zoomScale; + + target.dirty(); +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + + +var IRRELEVANT_EXCLUDES = {'axisPointer': 1, 'tooltip': 1, 'brush': 1}; + +/** + * Avoid that: mouse click on a elements that is over geo or graph, + * but roam is triggered. + */ +function onIrrelevantElement(e, api, targetCoordSysModel) { + var model = api.getComponentByElement(e.topTarget); + // If model is axisModel, it works only if it is injected with coordinateSystem. + var coordSys = model && model.coordinateSystem; + return model + && model !== targetCoordSysModel + && !IRRELEVANT_EXCLUDES[model.mainType] + && (coordSys && coordSys.model !== targetCoordSysModel); +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +function getFixedItemStyle(model, scale) { + var itemStyle = model.getItemStyle(); + var areaColor = model.get('areaColor'); + + // If user want the color not to be changed when hover, + // they should both set areaColor and color to be null. + if (areaColor != null) { + itemStyle.fill = areaColor; + } + + return itemStyle; +} + +function updateMapSelectHandler(mapDraw, mapOrGeoModel, regionsGroup, api, fromView) { + regionsGroup.off('click'); + regionsGroup.off('mousedown'); + + if (mapOrGeoModel.get('selectedMode')) { + + regionsGroup.on('mousedown', function () { + mapDraw._mouseDownFlag = true; + }); + + regionsGroup.on('click', function (e) { + if (!mapDraw._mouseDownFlag) { + return; + } + mapDraw._mouseDownFlag = false; + + var el = e.target; + while (!el.__regions) { + el = el.parent; + } + if (!el) { + return; + } + + var action = { + type: (mapOrGeoModel.mainType === 'geo' ? 'geo' : 'map') + 'ToggleSelect', + batch: map(el.__regions, function (region) { + return { + name: region.name, + from: fromView.uid + }; + }) + }; + action[mapOrGeoModel.mainType + 'Id'] = mapOrGeoModel.id; + + api.dispatchAction(action); + + updateMapSelected(mapOrGeoModel, regionsGroup); + }); + } +} + +function updateMapSelected(mapOrGeoModel, regionsGroup) { + // FIXME + regionsGroup.eachChild(function (otherRegionEl) { + each$1(otherRegionEl.__regions, function (region) { + otherRegionEl.trigger(mapOrGeoModel.isSelected(region.name) ? 'emphasis' : 'normal'); + }); + }); +} + +/** + * @alias module:echarts/component/helper/MapDraw + * @param {module:echarts/ExtensionAPI} api + * @param {boolean} updateGroup + */ +function MapDraw(api, updateGroup) { + + var group = new Group(); + + /** + * @type {string} + * @private + */ + this.uid = getUID('ec_map_draw'); + + /** + * @type {module:echarts/component/helper/RoamController} + * @private + */ + this._controller = new RoamController(api.getZr()); + + /** + * @type {Object} {target, zoom, zoomLimit} + * @private + */ + this._controllerHost = {target: updateGroup ? group : null}; + + /** + * @type {module:zrender/container/Group} + * @readOnly + */ + this.group = group; + + /** + * @type {boolean} + * @private + */ + this._updateGroup = updateGroup; + + /** + * This flag is used to make sure that only one among + * `pan`, `zoom`, `click` can occurs, otherwise 'selected' + * action may be triggered when `pan`, which is unexpected. + * @type {booelan} + */ + this._mouseDownFlag; + + /** + * @type {string} + */ + this._mapName; + + /** + * @type {boolean} + */ + this._initialized; + + /** + * @type {module:zrender/container/Group} + */ + group.add(this._regionsGroup = new Group()); + + /** + * @type {module:zrender/container/Group} + */ + group.add(this._backgroundGroup = new Group()); +} + +MapDraw.prototype = { + + constructor: MapDraw, + + draw: function (mapOrGeoModel, ecModel, api, fromView, payload) { + + var isGeo = mapOrGeoModel.mainType === 'geo'; + + // Map series has data. GEO model that controlled by map series + // will be assigned with map data. Other GEO model has no data. + var data = mapOrGeoModel.getData && mapOrGeoModel.getData(); + isGeo && ecModel.eachComponent({mainType: 'series', subType: 'map'}, function (mapSeries) { + if (!data && mapSeries.getHostGeoModel() === mapOrGeoModel) { + data = mapSeries.getData(); + } + }); + + var geo = mapOrGeoModel.coordinateSystem; + + this._updateBackground(geo); + + var regionsGroup = this._regionsGroup; + var group = this.group; + + var scale = geo.scale; + var transform = { + position: geo.position, + scale: scale + }; + + // No animation when first draw or in action + if (!regionsGroup.childAt(0) || payload) { + group.attr(transform); + } + else { + updateProps(group, transform, mapOrGeoModel); + } + + regionsGroup.removeAll(); + + var itemStyleAccessPath = ['itemStyle']; + var hoverItemStyleAccessPath = ['emphasis', 'itemStyle']; + var labelAccessPath = ['label']; + var hoverLabelAccessPath = ['emphasis', 'label']; + var nameMap = createHashMap(); + + each$1(geo.regions, function (region) { + + // Consider in GeoJson properties.name may be duplicated, for example, + // there is multiple region named "United Kindom" or "France" (so many + // colonies). And it is not appropriate to merge them in geo, which + // will make them share the same label and bring trouble in label + // location calculation. + var regionGroup = nameMap.get(region.name) + || nameMap.set(region.name, new Group()); + + var compoundPath = new CompoundPath({ + shape: { + paths: [] + } + }); + regionGroup.add(compoundPath); + + var regionModel = mapOrGeoModel.getRegionModel(region.name) || mapOrGeoModel; + + var itemStyleModel = regionModel.getModel(itemStyleAccessPath); + var hoverItemStyleModel = regionModel.getModel(hoverItemStyleAccessPath); + var itemStyle = getFixedItemStyle(itemStyleModel, scale); + var hoverItemStyle = getFixedItemStyle(hoverItemStyleModel, scale); + + var labelModel = regionModel.getModel(labelAccessPath); + var hoverLabelModel = regionModel.getModel(hoverLabelAccessPath); + + var dataIdx; + // Use the itemStyle in data if has data + if (data) { + dataIdx = data.indexOfName(region.name); + // Only visual color of each item will be used. It can be encoded by dataRange + // But visual color of series is used in symbol drawing + // + // Visual color for each series is for the symbol draw + var visualColor = data.getItemVisual(dataIdx, 'color', true); + if (visualColor) { + itemStyle.fill = visualColor; + } + } + + each$1(region.geometries, function (geometry) { + if (geometry.type !== 'polygon') { + return; + } + compoundPath.shape.paths.push(new Polygon({ + shape: { + points: geometry.exterior + } + })); + + for (var i = 0; i < (geometry.interiors ? geometry.interiors.length : 0); i++) { + compoundPath.shape.paths.push(new Polygon({ + shape: { + points: geometry.interiors[i] + } + })); + } + }); + + compoundPath.setStyle(itemStyle); + compoundPath.style.strokeNoScale = true; + compoundPath.culling = true; + // Label + var showLabel = labelModel.get('show'); + var hoverShowLabel = hoverLabelModel.get('show'); + + var isDataNaN = data && isNaN(data.get(data.mapDimension('value'), dataIdx)); + var itemLayout = data && data.getItemLayout(dataIdx); + // In the following cases label will be drawn + // 1. In map series and data value is NaN + // 2. In geo component + // 4. Region has no series legendSymbol, which will be add a showLabel flag in mapSymbolLayout + if ( + (isGeo || isDataNaN && (showLabel || hoverShowLabel)) + || (itemLayout && itemLayout.showLabel) + ) { + var query = !isGeo ? dataIdx : region.name; + var labelFetcher; + + // Consider dataIdx not found. + if (!data || dataIdx >= 0) { + labelFetcher = mapOrGeoModel; + } + + var textEl = new Text({ + position: region.center.slice(), + // FIXME + // label rotation is not support yet in geo or regions of series-map + // that has no data. The rotation will be effected by this `scale`. + // So needed to change to RectText? + scale: [1 / scale[0], 1 / scale[1]], + z2: 10, + silent: true + }); + + setLabelStyle( + textEl.style, textEl.hoverStyle = {}, labelModel, hoverLabelModel, + { + labelFetcher: labelFetcher, + labelDataIndex: query, + defaultText: region.name, + useInsideStyle: false + }, + { + textAlign: 'center', + textVerticalAlign: 'middle' + } + ); + + regionGroup.add(textEl); + } + + // setItemGraphicEl, setHoverStyle after all polygons and labels + // are added to the rigionGroup + if (data) { + data.setItemGraphicEl(dataIdx, regionGroup); + } + else { + var regionModel = mapOrGeoModel.getRegionModel(region.name); + // Package custom mouse event for geo component + compoundPath.eventData = { + componentType: 'geo', + componentIndex: mapOrGeoModel.componentIndex, + geoIndex: mapOrGeoModel.componentIndex, + name: region.name, + region: (regionModel && regionModel.option) || {} + }; + } + + var groupRegions = regionGroup.__regions || (regionGroup.__regions = []); + groupRegions.push(region); + + setHoverStyle( + regionGroup, + hoverItemStyle, + {hoverSilentOnTouch: !!mapOrGeoModel.get('selectedMode')} + ); + + regionsGroup.add(regionGroup); + }); + + this._updateController(mapOrGeoModel, ecModel, api); + + updateMapSelectHandler(this, mapOrGeoModel, regionsGroup, api, fromView); + + updateMapSelected(mapOrGeoModel, regionsGroup); + }, + + remove: function () { + this._regionsGroup.removeAll(); + this._backgroundGroup.removeAll(); + this._controller.dispose(); + this._mapName && geoSourceManager.removeGraphic(this._mapName, this.uid); + this._mapName = null; + this._controllerHost = {}; + }, + + _updateBackground: function (geo) { + var mapName = geo.map; + + if (this._mapName !== mapName) { + each$1(geoSourceManager.makeGraphic(mapName, this.uid), function (root) { + this._backgroundGroup.add(root); + }, this); + } + + this._mapName = mapName; + }, + + _updateController: function (mapOrGeoModel, ecModel, api) { + var geo = mapOrGeoModel.coordinateSystem; + var controller = this._controller; + var controllerHost = this._controllerHost; + + controllerHost.zoomLimit = mapOrGeoModel.get('scaleLimit'); + controllerHost.zoom = geo.getZoom(); + + // roamType is will be set default true if it is null + controller.enable(mapOrGeoModel.get('roam') || false); + var mainType = mapOrGeoModel.mainType; + + function makeActionBase() { + var action = { + type: 'geoRoam', + componentType: mainType + }; + action[mainType + 'Id'] = mapOrGeoModel.id; + return action; + } + + controller.off('pan').on('pan', function (e) { + this._mouseDownFlag = false; + + updateViewOnPan(controllerHost, e.dx, e.dy); + + api.dispatchAction(extend(makeActionBase(), { + dx: e.dx, + dy: e.dy + })); + }, this); + + controller.off('zoom').on('zoom', function (e) { + this._mouseDownFlag = false; + + updateViewOnZoom(controllerHost, e.scale, e.originX, e.originY); + + api.dispatchAction(extend(makeActionBase(), { + zoom: e.scale, + originX: e.originX, + originY: e.originY + })); + + if (this._updateGroup) { + var scale = this.group.scale; + this._regionsGroup.traverse(function (el) { + if (el.type === 'text') { + el.attr('scale', [1 / scale[0], 1 / scale[1]]); + } + }); + } + }, this); + + controller.setPointerChecker(function (e, x, y) { + return geo.getViewRectAfterRoam().contain(x, y) + && !onIrrelevantElement(e, api, mapOrGeoModel); + }); + } +}; + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var HIGH_DOWN_PROP = '__seriesMapHighDown'; +var RECORD_VERSION_PROP = '__seriesMapCallKey'; + +extendChartView({ + + type: 'map', + + render: function (mapModel, ecModel, api, payload) { + // Not render if it is an toggleSelect action from self + if (payload && payload.type === 'mapToggleSelect' + && payload.from === this.uid + ) { + return; + } + + var group = this.group; + group.removeAll(); + + if (mapModel.getHostGeoModel()) { + return; + } + + // Not update map if it is an roam action from self + if (!(payload && payload.type === 'geoRoam' + && payload.componentType === 'series' + && payload.seriesId === mapModel.id + ) + ) { + if (mapModel.needsDrawMap) { + var mapDraw = this._mapDraw || new MapDraw(api, true); + group.add(mapDraw.group); + + mapDraw.draw(mapModel, ecModel, api, this, payload); + + this._mapDraw = mapDraw; + } + else { + // Remove drawed map + this._mapDraw && this._mapDraw.remove(); + this._mapDraw = null; + } + } + else { + var mapDraw = this._mapDraw; + mapDraw && group.add(mapDraw.group); + } + + mapModel.get('showLegendSymbol') && ecModel.getComponent('legend') + && this._renderSymbols(mapModel, ecModel, api); + }, + + remove: function () { + this._mapDraw && this._mapDraw.remove(); + this._mapDraw = null; + this.group.removeAll(); + }, + + dispose: function () { + this._mapDraw && this._mapDraw.remove(); + this._mapDraw = null; + }, + + _renderSymbols: function (mapModel, ecModel, api) { + var originalData = mapModel.originalData; + var group = this.group; + + originalData.each(originalData.mapDimension('value'), function (value, originalDataIndex) { + if (isNaN(value)) { + return; + } + + var layout = originalData.getItemLayout(originalDataIndex); + + if (!layout || !layout.point) { + // Not exists in map + return; + } + + var point = layout.point; + var offset = layout.offset; + + var circle = new Circle({ + style: { + // Because the special of map draw. + // Which needs statistic of multiple series and draw on one map. + // And each series also need a symbol with legend color + // + // Layout and visual are put one the different data + fill: mapModel.getData().getVisual('color') + }, + shape: { + cx: point[0] + offset * 9, + cy: point[1], + r: 3 + }, + silent: true, + // Do not overlap the first series, on which labels are displayed. + z2: 8 + (!offset ? Z2_EMPHASIS_LIFT + 1 : 0) + }); + + // Only the series that has the first value on the same region is in charge of rendering the label. + // But consider the case: + // series: [ + // {id: 'X', type: 'map', map: 'm', {data: [{name: 'A', value: 11}, {name: 'B', {value: 22}]}, + // {id: 'Y', type: 'map', map: 'm', {data: [{name: 'A', value: 21}, {name: 'C', {value: 33}]} + // ] + // The offset `0` of item `A` is at series `X`, but of item `C` is at series `Y`. + // For backward compatibility, we follow the rule that render label `A` by the + // settings on series `X` but render label `C` by the settings on series `Y`. + if (!offset) { + + var fullData = mapModel.mainSeries.getData(); + var name = originalData.getName(originalDataIndex); + + var fullIndex = fullData.indexOfName(name); + + var itemModel = originalData.getItemModel(originalDataIndex); + var labelModel = itemModel.getModel('label'); + var hoverLabelModel = itemModel.getModel('emphasis.label'); + + var regionGroup = fullData.getItemGraphicEl(fullIndex); + + // `getFormattedLabel` needs to use `getData` inside. Here + // `mapModel.getData()` is shallow cloned from `mainSeries.getData()`. + // FIXME + // If this is not the `mainSeries`, the item model (like label formatter) + // set on original data item will never get. But it has been working + // like that from the begining, and this scenario is rarely encountered. + // So it won't be fixed until have to. + var normalText = retrieve2( + mapModel.getFormattedLabel(fullIndex, 'normal'), + name + ); + var emphasisText = retrieve2( + mapModel.getFormattedLabel(fullIndex, 'emphasis'), + normalText + ); + + var highDownRecord = regionGroup[HIGH_DOWN_PROP]; + var recordVersion = Math.random(); + + // Prevent from register listeners duplicatedly when roaming. + if (!highDownRecord) { + highDownRecord = regionGroup[HIGH_DOWN_PROP] = {}; + var onEmphasis = curry(onRegionHighDown, true); + var onNormal = curry(onRegionHighDown, false); + regionGroup.on('mouseover', onEmphasis) + .on('mouseout', onNormal) + .on('emphasis', onEmphasis) + .on('normal', onNormal); + } + + // Prevent removed regions effect current grapics. + regionGroup[RECORD_VERSION_PROP] = recordVersion; + extend(highDownRecord, { + recordVersion: recordVersion, + circle: circle, + labelModel: labelModel, + hoverLabelModel: hoverLabelModel, + emphasisText: emphasisText, + normalText: normalText + }); + + // FIXME + // Consider set option when emphasis. + enterRegionHighDown(highDownRecord, false); + } + + group.add(circle); + }); + } +}); + +function onRegionHighDown(toHighOrDown) { + var highDownRecord = this[HIGH_DOWN_PROP]; + if (highDownRecord && highDownRecord.recordVersion === this[RECORD_VERSION_PROP]) { + enterRegionHighDown(highDownRecord, toHighOrDown); + } +} + +function enterRegionHighDown(highDownRecord, toHighOrDown) { + var circle = highDownRecord.circle; + var labelModel = highDownRecord.labelModel; + var hoverLabelModel = highDownRecord.hoverLabelModel; + var emphasisText = highDownRecord.emphasisText; + var normalText = highDownRecord.normalText; + + if (toHighOrDown) { + circle.style.extendFrom( + setTextStyle({}, hoverLabelModel, { + text: hoverLabelModel.get('show') ? emphasisText : null + }, {isRectText: true, useInsideStyle: false}, true) + ); + // Make label upper than others if overlaps. + circle.__mapOriginalZ2 = circle.z2; + circle.z2 += Z2_EMPHASIS_LIFT; + } + else { + setTextStyle(circle.style, labelModel, { + text: labelModel.get('show') ? normalText : null, + textPosition: labelModel.getShallow('position') || 'bottom' + }, {isRectText: true, useInsideStyle: false}); + // Trigger normalize style like padding. + circle.dirty(false); + + if (circle.__mapOriginalZ2 != null) { + circle.z2 = circle.__mapOriginalZ2; + circle.__mapOriginalZ2 = null; + } + } +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/** + * @param {module:echarts/coord/View} view + * @param {Object} payload + * @param {Object} [zoomLimit] + */ +function updateCenterAndZoom( + view, payload, zoomLimit +) { + var previousZoom = view.getZoom(); + var center = view.getCenter(); + var zoom = payload.zoom; + + var point = view.dataToPoint(center); + + if (payload.dx != null && payload.dy != null) { + point[0] -= payload.dx; + point[1] -= payload.dy; + + var center = view.pointToData(point); + view.setCenter(center); + } + if (zoom != null) { + if (zoomLimit) { + var zoomMin = zoomLimit.min || 0; + var zoomMax = zoomLimit.max || Infinity; + zoom = Math.max( + Math.min(previousZoom * zoom, zoomMax), + zoomMin + ) / previousZoom; + } + + // Zoom on given point(originX, originY) + view.scale[0] *= zoom; + view.scale[1] *= zoom; + var position = view.position; + var fixX = (payload.originX - position[0]) * (zoom - 1); + var fixY = (payload.originY - position[1]) * (zoom - 1); + + position[0] -= fixX; + position[1] -= fixY; + + view.updateTransform(); + // Get the new center + var center = view.pointToData(point); + view.setCenter(center); + view.setZoom(zoom * previousZoom); + } + + return { + center: view.getCenter(), + zoom: view.getZoom() + }; +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/** + * @payload + * @property {string} [componentType=series] + * @property {number} [dx] + * @property {number} [dy] + * @property {number} [zoom] + * @property {number} [originX] + * @property {number} [originY] + */ +registerAction({ + type: 'geoRoam', + event: 'geoRoam', + update: 'updateTransform' +}, function (payload, ecModel) { + var componentType = payload.componentType || 'series'; + + ecModel.eachComponent( + { mainType: componentType, query: payload }, + function (componentModel) { + var geo = componentModel.coordinateSystem; + if (geo.type !== 'geo') { + return; + } + + var res = updateCenterAndZoom( + geo, payload, componentModel.get('scaleLimit') + ); + + componentModel.setCenter + && componentModel.setCenter(res.center); + + componentModel.setZoom + && componentModel.setZoom(res.zoom); + + // All map series with same `map` use the same geo coordinate system + // So the center and zoom must be in sync. Include the series not selected by legend + if (componentType === 'series') { + each$1(componentModel.seriesGroup, function (seriesModel) { + seriesModel.setCenter(res.center); + seriesModel.setZoom(res.zoom); + }); + } + } + ); +}); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/** + * Simple view coordinate system + * Mapping given x, y to transformd view x, y + */ + +var v2ApplyTransform$1 = applyTransform; + +// Dummy transform node +function TransformDummy() { + Transformable.call(this); +} +mixin(TransformDummy, Transformable); + +function View(name) { + /** + * @type {string} + */ + this.name = name; + + /** + * @type {Object} + */ + this.zoomLimit; + + Transformable.call(this); + + this._roamTransformable = new TransformDummy(); + + this._rawTransformable = new TransformDummy(); + + this._center; + this._zoom; +} + +View.prototype = { + + constructor: View, + + type: 'view', + + /** + * @param {Array.} + * @readOnly + */ + dimensions: ['x', 'y'], + + /** + * Set bounding rect + * @param {number} x + * @param {number} y + * @param {number} width + * @param {number} height + */ + + // PENDING to getRect + setBoundingRect: function (x, y, width, height) { + this._rect = new BoundingRect(x, y, width, height); + return this._rect; + }, + + /** + * @return {module:zrender/core/BoundingRect} + */ + // PENDING to getRect + getBoundingRect: function () { + return this._rect; + }, + + /** + * @param {number} x + * @param {number} y + * @param {number} width + * @param {number} height + */ + setViewRect: function (x, y, width, height) { + this.transformTo(x, y, width, height); + this._viewRect = new BoundingRect(x, y, width, height); + }, + + /** + * Transformed to particular position and size + * @param {number} x + * @param {number} y + * @param {number} width + * @param {number} height + */ + transformTo: function (x, y, width, height) { + var rect = this.getBoundingRect(); + var rawTransform = this._rawTransformable; + + rawTransform.transform = rect.calculateTransform( + new BoundingRect(x, y, width, height) + ); + + rawTransform.decomposeTransform(); + + this._updateTransform(); + }, + + /** + * Set center of view + * @param {Array.} [centerCoord] + */ + setCenter: function (centerCoord) { + if (!centerCoord) { + return; + } + this._center = centerCoord; + + this._updateCenterAndZoom(); + }, + + /** + * @param {number} zoom + */ + setZoom: function (zoom) { + zoom = zoom || 1; + + var zoomLimit = this.zoomLimit; + if (zoomLimit) { + if (zoomLimit.max != null) { + zoom = Math.min(zoomLimit.max, zoom); + } + if (zoomLimit.min != null) { + zoom = Math.max(zoomLimit.min, zoom); + } + } + this._zoom = zoom; + + this._updateCenterAndZoom(); + }, + + /** + * Get default center without roam + */ + getDefaultCenter: function () { + // Rect before any transform + var rawRect = this.getBoundingRect(); + var cx = rawRect.x + rawRect.width / 2; + var cy = rawRect.y + rawRect.height / 2; + + return [cx, cy]; + }, + + getCenter: function () { + return this._center || this.getDefaultCenter(); + }, + + getZoom: function () { + return this._zoom || 1; + }, + + /** + * @return {Array.} data + * @param {boolean} noRoam + * @param {Array.} [out] + * @return {Array.} + */ + dataToPoint: function (data, noRoam, out) { + var transform = noRoam ? this._rawTransform : this.transform; + out = out || []; + return transform + ? v2ApplyTransform$1(out, data, transform) + : copy(out, data); + }, + + /** + * Convert a (x, y) point to (lon, lat) data + * @param {Array.} point + * @return {Array.} + */ + pointToData: function (point) { + var invTransform = this.invTransform; + return invTransform + ? v2ApplyTransform$1([], point, invTransform) + : [point[0], point[1]]; + }, + + /** + * @implements + * see {module:echarts/CoodinateSystem} + */ + convertToPixel: curry(doConvert$1, 'dataToPoint'), + + /** + * @implements + * see {module:echarts/CoodinateSystem} + */ + convertFromPixel: curry(doConvert$1, 'pointToData'), + + /** + * @implements + * see {module:echarts/CoodinateSystem} + */ + containPoint: function (point) { + return this.getViewRectAfterRoam().contain(point[0], point[1]); + } + + /** + * @return {number} + */ + // getScalarScale: function () { + // // Use determinant square root of transform to mutiply scalar + // var m = this.transform; + // var det = Math.sqrt(Math.abs(m[0] * m[3] - m[2] * m[1])); + // return det; + // } +}; + +mixin(View, Transformable); + +function doConvert$1(methodName, ecModel, finder, value) { + var seriesModel = finder.seriesModel; + var coordSys = seriesModel ? seriesModel.coordinateSystem : null; // e.g., graph. + return coordSys === this ? coordSys[methodName](value) : null; +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/** + * [Geo description] + * For backward compatibility, the orginal interface: + * `name, map, geoJson, specialAreas, nameMap` is kept. + * + * @param {string|Object} name + * @param {string} map Map type + * Specify the positioned areas by left, top, width, height + * @param {Object.} [nameMap] + * Specify name alias + * @param {boolean} [invertLongitute=true] + */ +function Geo(name, map$$1, nameMap, invertLongitute) { + + View.call(this, name); + + /** + * Map type + * @type {string} + */ + this.map = map$$1; + + var source = geoSourceManager.load(map$$1, nameMap); + + this._nameCoordMap = source.nameCoordMap; + this._regionsMap = source.regionsMap; + this._invertLongitute = invertLongitute == null ? true : invertLongitute; + + /** + * @readOnly + */ + this.regions = source.regions; + + /** + * @type {module:zrender/src/core/BoundingRect} + */ + this._rect = source.boundingRect; +} + +Geo.prototype = { + + constructor: Geo, + + type: 'geo', + + /** + * @param {Array.} + * @readOnly + */ + dimensions: ['lng', 'lat'], + + /** + * If contain given lng,lat coord + * @param {Array.} + * @readOnly + */ + containCoord: function (coord) { + var regions = this.regions; + for (var i = 0; i < regions.length; i++) { + if (regions[i].contain(coord)) { + return true; + } + } + return false; + }, + + /** + * @override + */ + transformTo: function (x, y, width, height) { + var rect = this.getBoundingRect(); + var invertLongitute = this._invertLongitute; + + rect = rect.clone(); + + if (invertLongitute) { + // Longitute is inverted + rect.y = -rect.y - rect.height; + } + + var rawTransformable = this._rawTransformable; + + rawTransformable.transform = rect.calculateTransform( + new BoundingRect(x, y, width, height) + ); + + rawTransformable.decomposeTransform(); + + if (invertLongitute) { + var scale = rawTransformable.scale; + scale[1] = -scale[1]; + } + + rawTransformable.updateTransform(); + + this._updateTransform(); + }, + + /** + * @param {string} name + * @return {module:echarts/coord/geo/Region} + */ + getRegion: function (name) { + return this._regionsMap.get(name); + }, + + getRegionByCoord: function (coord) { + var regions = this.regions; + for (var i = 0; i < regions.length; i++) { + if (regions[i].contain(coord)) { + return regions[i]; + } + } + }, + + /** + * Add geoCoord for indexing by name + * @param {string} name + * @param {Array.} geoCoord + */ + addGeoCoord: function (name, geoCoord) { + this._nameCoordMap.set(name, geoCoord); + }, + + /** + * Get geoCoord by name + * @param {string} name + * @return {Array.} + */ + getGeoCoord: function (name) { + return this._nameCoordMap.get(name); + }, + + /** + * @override + */ + getBoundingRect: function () { + return this._rect; + }, + + /** + * @param {string|Array.} data + * @param {boolean} noRoam + * @param {Array.} [out] + * @return {Array.} + */ + dataToPoint: function (data, noRoam, out) { + if (typeof data === 'string') { + // Map area name to geoCoord + data = this.getGeoCoord(data); + } + if (data) { + return View.prototype.dataToPoint.call(this, data, noRoam, out); + } + }, + + /** + * @override + */ + convertToPixel: curry(doConvert, 'dataToPoint'), + + /** + * @override + */ + convertFromPixel: curry(doConvert, 'pointToData') + +}; + +mixin(Geo, View); + +function doConvert(methodName, ecModel, finder, value) { + var geoModel = finder.geoModel; + var seriesModel = finder.seriesModel; + + var coordSys = geoModel + ? geoModel.coordinateSystem + : seriesModel + ? ( + seriesModel.coordinateSystem // For map. + || (seriesModel.getReferringComponents('geo')[0] || {}).coordinateSystem + ) + : null; + + return coordSys === this ? coordSys[methodName](value) : null; +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/** + * Resize method bound to the geo + * @param {module:echarts/coord/geo/GeoModel|module:echarts/chart/map/MapModel} geoModel + * @param {module:echarts/ExtensionAPI} api + */ +function resizeGeo(geoModel, api) { + + var boundingCoords = geoModel.get('boundingCoords'); + if (boundingCoords != null) { + var leftTop = boundingCoords[0]; + var rightBottom = boundingCoords[1]; + if (isNaN(leftTop[0]) || isNaN(leftTop[1]) || isNaN(rightBottom[0]) || isNaN(rightBottom[1])) { + if (__DEV__) { + console.error('Invalid boundingCoords'); + } + } + else { + this.setBoundingRect(leftTop[0], leftTop[1], rightBottom[0] - leftTop[0], rightBottom[1] - leftTop[1]); + } + } + + var rect = this.getBoundingRect(); + + var boxLayoutOption; + + var center = geoModel.get('layoutCenter'); + var size = geoModel.get('layoutSize'); + + var viewWidth = api.getWidth(); + var viewHeight = api.getHeight(); + + var aspect = rect.width / rect.height * this.aspectScale; + + var useCenterAndSize = false; + + if (center && size) { + center = [ + parsePercent$1(center[0], viewWidth), + parsePercent$1(center[1], viewHeight) + ]; + size = parsePercent$1(size, Math.min(viewWidth, viewHeight)); + + if (!isNaN(center[0]) && !isNaN(center[1]) && !isNaN(size)) { + useCenterAndSize = true; + } + else { + if (__DEV__) { + console.warn('Given layoutCenter or layoutSize data are invalid. Use left/top/width/height instead.'); + } + } + } + + var viewRect; + if (useCenterAndSize) { + var viewRect = {}; + if (aspect > 1) { + // Width is same with size + viewRect.width = size; + viewRect.height = size / aspect; + } + else { + viewRect.height = size; + viewRect.width = size * aspect; + } + viewRect.y = center[1] - viewRect.height / 2; + viewRect.x = center[0] - viewRect.width / 2; + } + else { + // Use left/top/width/height + boxLayoutOption = geoModel.getBoxLayoutParams(); + + // 0.75 rate + boxLayoutOption.aspect = aspect; + + viewRect = getLayoutRect(boxLayoutOption, { + width: viewWidth, + height: viewHeight + }); + } + + this.setViewRect(viewRect.x, viewRect.y, viewRect.width, viewRect.height); + + this.setCenter(geoModel.get('center')); + this.setZoom(geoModel.get('zoom')); +} + +/** + * @param {module:echarts/coord/Geo} geo + * @param {module:echarts/model/Model} model + * @inner + */ +function setGeoCoords(geo, model) { + each$1(model.get('geoCoord'), function (geoCoord, name) { + geo.addGeoCoord(name, geoCoord); + }); +} + +var geoCreator = { + + // For deciding which dimensions to use when creating list data + dimensions: Geo.prototype.dimensions, + + create: function (ecModel, api) { + var geoList = []; + + // FIXME Create each time may be slow + ecModel.eachComponent('geo', function (geoModel, idx) { + var name = geoModel.get('map'); + + var aspectScale = geoModel.get('aspectScale'); + var invertLongitute = true; + var mapRecords = mapDataStorage.retrieveMap(name); + if (mapRecords && mapRecords[0] && mapRecords[0].type === 'svg') { + aspectScale == null && (aspectScale = 1); + invertLongitute = false; + } + else { + aspectScale == null && (aspectScale = 0.75); + } + + var geo = new Geo(name + idx, name, geoModel.get('nameMap'), invertLongitute); + + geo.aspectScale = aspectScale; + geo.zoomLimit = geoModel.get('scaleLimit'); + geoList.push(geo); + + setGeoCoords(geo, geoModel); + + geoModel.coordinateSystem = geo; + geo.model = geoModel; + + // Inject resize method + geo.resize = resizeGeo; + + geo.resize(geoModel, api); + }); + + ecModel.eachSeries(function (seriesModel) { + var coordSys = seriesModel.get('coordinateSystem'); + if (coordSys === 'geo') { + var geoIndex = seriesModel.get('geoIndex') || 0; + seriesModel.coordinateSystem = geoList[geoIndex]; + } + }); + + // If has map series + var mapModelGroupBySeries = {}; + + ecModel.eachSeriesByType('map', function (seriesModel) { + if (!seriesModel.getHostGeoModel()) { + var mapType = seriesModel.getMapType(); + mapModelGroupBySeries[mapType] = mapModelGroupBySeries[mapType] || []; + mapModelGroupBySeries[mapType].push(seriesModel); + } + }); + + each$1(mapModelGroupBySeries, function (mapSeries, mapType) { + var nameMapList = map(mapSeries, function (singleMapSeries) { + return singleMapSeries.get('nameMap'); + }); + var geo = new Geo(mapType, mapType, mergeAll(nameMapList)); + + geo.zoomLimit = retrieve.apply(null, map(mapSeries, function (singleMapSeries) { + return singleMapSeries.get('scaleLimit'); + })); + geoList.push(geo); + + // Inject resize method + geo.resize = resizeGeo; + geo.aspectScale = mapSeries[0].get('aspectScale'); + + geo.resize(mapSeries[0], api); + + each$1(mapSeries, function (singleMapSeries) { + singleMapSeries.coordinateSystem = geo; + + setGeoCoords(geo, singleMapSeries); + }); + }); + + return geoList; + }, + + /** + * Fill given regions array + * @param {Array.} originRegionArr + * @param {string} mapName + * @param {Object} [nameMap] + * @return {Array} + */ + getFilledRegions: function (originRegionArr, mapName, nameMap) { + // Not use the original + var regionsArr = (originRegionArr || []).slice(); + + var dataNameMap = createHashMap(); + for (var i = 0; i < regionsArr.length; i++) { + dataNameMap.set(regionsArr[i].name, regionsArr[i]); + } + + var source = geoSourceManager.load(mapName, nameMap); + each$1(source.regions, function (region) { + var name = region.name; + !dataNameMap.get(name) && regionsArr.push({name: name}); + }); + + return regionsArr; + } +}; + +registerCoordinateSystem('geo', geoCreator); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var mapSymbolLayout = function (ecModel) { + + var processedMapType = {}; + + ecModel.eachSeriesByType('map', function (mapSeries) { + var mapType = mapSeries.getMapType(); + if (mapSeries.getHostGeoModel() || processedMapType[mapType]) { + return; + } + + var mapSymbolOffsets = {}; + + each$1(mapSeries.seriesGroup, function (subMapSeries) { + var geo = subMapSeries.coordinateSystem; + var data = subMapSeries.originalData; + if (subMapSeries.get('showLegendSymbol') && ecModel.getComponent('legend')) { + data.each(data.mapDimension('value'), function (value, idx) { + var name = data.getName(idx); + var region = geo.getRegion(name); + + // If input series.data is [11, 22, '-'/null/undefined, 44], + // it will be filled with NaN: [11, 22, NaN, 44] and NaN will + // not be drawn. So here must validate if value is NaN. + if (!region || isNaN(value)) { + return; + } + + var offset = mapSymbolOffsets[name] || 0; + + var point = geo.dataToPoint(region.center); + + mapSymbolOffsets[name] = offset + 1; + + data.setItemLayout(idx, { + point: point, + offset: offset + }); + }); + } + }); + + // Show label of those region not has legendSymbol(which is offset 0) + var data = mapSeries.getData(); + data.each(function (idx) { + var name = data.getName(idx); + var layout = data.getItemLayout(idx) || {}; + layout.showLabel = !mapSymbolOffsets[name]; + data.setItemLayout(idx, layout); + }); + + processedMapType[mapType] = true; + }); +}; + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + + +var mapVisual = function (ecModel) { + ecModel.eachSeriesByType('map', function (seriesModel) { + var colorList = seriesModel.get('color'); + var itemStyleModel = seriesModel.getModel('itemStyle'); + + var areaColor = itemStyleModel.get('areaColor'); + var color = itemStyleModel.get('color') + || colorList[seriesModel.seriesIndex % colorList.length]; + + seriesModel.getData().setVisual({ + 'areaColor': areaColor, + 'color': color + }); + }); +}; + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +// FIXME 公用? +/** + * @param {Array.} datas + * @param {string} statisticType 'average' 'sum' + * @inner + */ +function dataStatistics(datas, statisticType) { + var dataNameMap = {}; + + each$1(datas, function (data) { + data.each(data.mapDimension('value'), function (value, idx) { + // Add prefix to avoid conflict with Object.prototype. + var mapKey = 'ec-' + data.getName(idx); + dataNameMap[mapKey] = dataNameMap[mapKey] || []; + if (!isNaN(value)) { + dataNameMap[mapKey].push(value); + } + }); + }); + + return datas[0].map(datas[0].mapDimension('value'), function (value, idx) { + var mapKey = 'ec-' + datas[0].getName(idx); + var sum = 0; + var min = Infinity; + var max = -Infinity; + var len = dataNameMap[mapKey].length; + for (var i = 0; i < len; i++) { + min = Math.min(min, dataNameMap[mapKey][i]); + max = Math.max(max, dataNameMap[mapKey][i]); + sum += dataNameMap[mapKey][i]; + } + var result; + if (statisticType === 'min') { + result = min; + } + else if (statisticType === 'max') { + result = max; + } + else if (statisticType === 'average') { + result = sum / len; + } + else { + result = sum; + } + return len === 0 ? NaN : result; + }); +} + +var mapDataStatistic = function (ecModel) { + var seriesGroups = {}; + ecModel.eachSeriesByType('map', function (seriesModel) { + var hostGeoModel = seriesModel.getHostGeoModel(); + var key = hostGeoModel ? 'o' + hostGeoModel.id : 'i' + seriesModel.getMapType(); + (seriesGroups[key] = seriesGroups[key] || []).push(seriesModel); + }); + + each$1(seriesGroups, function (seriesList, key) { + var data = dataStatistics( + map(seriesList, function (seriesModel) { + return seriesModel.getData(); + }), + seriesList[0].get('mapValueCalculation') + ); + + for (var i = 0; i < seriesList.length; i++) { + seriesList[i].originalData = seriesList[i].getData(); + } + + // FIXME Put where? + for (var i = 0; i < seriesList.length; i++) { + seriesList[i].seriesGroup = seriesList; + seriesList[i].needsDrawMap = i === 0 && !seriesList[i].getHostGeoModel(); + + seriesList[i].setData(data.cloneShallow()); + seriesList[i].mainSeries = seriesList[0]; + } + }); +}; + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var backwardCompat$2 = function (option) { + // Save geoCoord + var mapSeries = []; + each$1(option.series, function (seriesOpt) { + if (seriesOpt && seriesOpt.type === 'map') { + mapSeries.push(seriesOpt); + seriesOpt.map = seriesOpt.map || seriesOpt.mapType; + // Put x, y, width, height, x2, y2 in the top level + defaults(seriesOpt, seriesOpt.mapLocation); + } + }); +}; + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +registerLayout(mapSymbolLayout); +registerVisual(mapVisual); +registerProcessor(PRIORITY.PROCESSOR.STATISTIC, mapDataStatistic); +registerPreprocessor(backwardCompat$2); + +createDataSelectAction('map', [{ + type: 'mapToggleSelect', + event: 'mapselectchanged', + method: 'toggleSelected' +}, { + type: 'mapSelect', + event: 'mapselected', + method: 'select' +}, { + type: 'mapUnSelect', + event: 'mapunselected', + method: 'unSelect' +}]); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/** + * Link lists and struct (graph or tree) + */ + +var each$7 = each$1; + +var DATAS = '\0__link_datas'; +var MAIN_DATA = '\0__link_mainData'; + +// Caution: +// In most case, either list or its shallow clones (see list.cloneShallow) +// is active in echarts process. So considering heap memory consumption, +// we do not clone tree or graph, but share them among list and its shallow clones. +// But in some rare case, we have to keep old list (like do animation in chart). So +// please take care that both the old list and the new list share the same tree/graph. + +/** + * @param {Object} opt + * @param {module:echarts/data/List} opt.mainData + * @param {Object} [opt.struct] For example, instance of Graph or Tree. + * @param {string} [opt.structAttr] designation: list[structAttr] = struct; + * @param {Object} [opt.datas] {dataType: data}, + * like: {node: nodeList, edge: edgeList}. + * Should contain mainData. + * @param {Object} [opt.datasAttr] {dataType: attr}, + * designation: struct[datasAttr[dataType]] = list; + */ +function linkList(opt) { + var mainData = opt.mainData; + var datas = opt.datas; + + if (!datas) { + datas = {main: mainData}; + opt.datasAttr = {main: 'data'}; + } + opt.datas = opt.mainData = null; + + linkAll(mainData, datas, opt); + + // Porxy data original methods. + each$7(datas, function (data) { + each$7(mainData.TRANSFERABLE_METHODS, function (methodName) { + data.wrapMethod(methodName, curry(transferInjection, opt)); + }); + + }); + + // Beyond transfer, additional features should be added to `cloneShallow`. + mainData.wrapMethod('cloneShallow', curry(cloneShallowInjection, opt)); + + // Only mainData trigger change, because struct.update may trigger + // another changable methods, which may bring about dead lock. + each$7(mainData.CHANGABLE_METHODS, function (methodName) { + mainData.wrapMethod(methodName, curry(changeInjection, opt)); + }); + + // Make sure datas contains mainData. + assert$1(datas[mainData.dataType] === mainData); +} + +function transferInjection(opt, res) { + if (isMainData(this)) { + // Transfer datas to new main data. + var datas = extend({}, this[DATAS]); + datas[this.dataType] = res; + linkAll(res, datas, opt); + } + else { + // Modify the reference in main data to point newData. + linkSingle(res, this.dataType, this[MAIN_DATA], opt); + } + return res; +} + +function changeInjection(opt, res) { + opt.struct && opt.struct.update(this); + return res; +} + +function cloneShallowInjection(opt, res) { + // cloneShallow, which brings about some fragilities, may be inappropriate + // to be exposed as an API. So for implementation simplicity we can make + // the restriction that cloneShallow of not-mainData should not be invoked + // outside, but only be invoked here. + each$7(res[DATAS], function (data, dataType) { + data !== res && linkSingle(data.cloneShallow(), dataType, res, opt); + }); + return res; +} + +/** + * Supplement method to List. + * + * @public + * @param {string} [dataType] If not specified, return mainData. + * @return {module:echarts/data/List} + */ +function getLinkedData(dataType) { + var mainData = this[MAIN_DATA]; + return (dataType == null || mainData == null) + ? mainData + : mainData[DATAS][dataType]; +} + +function isMainData(data) { + return data[MAIN_DATA] === data; +} + +function linkAll(mainData, datas, opt) { + mainData[DATAS] = {}; + each$7(datas, function (data, dataType) { + linkSingle(data, dataType, mainData, opt); + }); +} + +function linkSingle(data, dataType, mainData, opt) { + mainData[DATAS][dataType] = data; + data[MAIN_DATA] = mainData; + data.dataType = dataType; + + if (opt.struct) { + data[opt.structAttr] = opt.struct; + opt.struct[opt.datasAttr[dataType]] = data; + } + + // Supplement method. + data.getLinkedData = getLinkedData; +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/** + * Tree data structure + * + * @module echarts/data/Tree + */ + +/** + * @constructor module:echarts/data/Tree~TreeNode + * @param {string} name + * @param {module:echarts/data/Tree} hostTree + */ +var TreeNode = function (name, hostTree) { + /** + * @type {string} + */ + this.name = name || ''; + + /** + * Depth of node + * + * @type {number} + * @readOnly + */ + this.depth = 0; + + /** + * Height of the subtree rooted at this node. + * @type {number} + * @readOnly + */ + this.height = 0; + + /** + * @type {module:echarts/data/Tree~TreeNode} + * @readOnly + */ + this.parentNode = null; + + /** + * Reference to list item. + * Do not persistent dataIndex outside, + * besause it may be changed by list. + * If dataIndex -1, + * this node is logical deleted (filtered) in list. + * + * @type {Object} + * @readOnly + */ + this.dataIndex = -1; + + /** + * @type {Array.} + * @readOnly + */ + this.children = []; + + /** + * @type {Array.} + * @pubilc + */ + this.viewChildren = []; + + /** + * @type {moduel:echarts/data/Tree} + * @readOnly + */ + this.hostTree = hostTree; +}; + +TreeNode.prototype = { + + constructor: TreeNode, + + /** + * The node is removed. + * @return {boolean} is removed. + */ + isRemoved: function () { + return this.dataIndex < 0; + }, + + /** + * Travel this subtree (include this node). + * Usage: + * node.eachNode(function () { ... }); // preorder + * node.eachNode('preorder', function () { ... }); // preorder + * node.eachNode('postorder', function () { ... }); // postorder + * node.eachNode( + * {order: 'postorder', attr: 'viewChildren'}, + * function () { ... } + * ); // postorder + * + * @param {(Object|string)} options If string, means order. + * @param {string=} options.order 'preorder' or 'postorder' + * @param {string=} options.attr 'children' or 'viewChildren' + * @param {Function} cb If in preorder and return false, + * its subtree will not be visited. + * @param {Object} [context] + */ + eachNode: function (options, cb, context) { + if (typeof options === 'function') { + context = cb; + cb = options; + options = null; + } + + options = options || {}; + if (isString(options)) { + options = {order: options}; + } + + var order = options.order || 'preorder'; + var children = this[options.attr || 'children']; + + var suppressVisitSub; + order === 'preorder' && (suppressVisitSub = cb.call(context, this)); + + for (var i = 0; !suppressVisitSub && i < children.length; i++) { + children[i].eachNode(options, cb, context); + } + + order === 'postorder' && cb.call(context, this); + }, + + /** + * Update depth and height of this subtree. + * + * @param {number} depth + */ + updateDepthAndHeight: function (depth) { + var height = 0; + this.depth = depth; + for (var i = 0; i < this.children.length; i++) { + var child = this.children[i]; + child.updateDepthAndHeight(depth + 1); + if (child.height > height) { + height = child.height; + } + } + this.height = height + 1; + }, + + /** + * @param {string} id + * @return {module:echarts/data/Tree~TreeNode} + */ + getNodeById: function (id) { + if (this.getId() === id) { + return this; + } + for (var i = 0, children = this.children, len = children.length; i < len; i++) { + var res = children[i].getNodeById(id); + if (res) { + return res; + } + } + }, + + /** + * @param {module:echarts/data/Tree~TreeNode} node + * @return {boolean} + */ + contains: function (node) { + if (node === this) { + return true; + } + for (var i = 0, children = this.children, len = children.length; i < len; i++) { + var res = children[i].contains(node); + if (res) { + return res; + } + } + }, + + /** + * @param {boolean} includeSelf Default false. + * @return {Array.} order: [root, child, grandchild, ...] + */ + getAncestors: function (includeSelf) { + var ancestors = []; + var node = includeSelf ? this : this.parentNode; + while (node) { + ancestors.push(node); + node = node.parentNode; + } + ancestors.reverse(); + return ancestors; + }, + + /** + * @param {string|Array=} [dimension='value'] Default 'value'. can be 0, 1, 2, 3 + * @return {number} Value. + */ + getValue: function (dimension) { + var data = this.hostTree.data; + return data.get(data.getDimension(dimension || 'value'), this.dataIndex); + }, + + /** + * @param {Object} layout + * @param {boolean=} [merge=false] + */ + setLayout: function (layout, merge$$1) { + this.dataIndex >= 0 + && this.hostTree.data.setItemLayout(this.dataIndex, layout, merge$$1); + }, + + /** + * @return {Object} layout + */ + getLayout: function () { + return this.hostTree.data.getItemLayout(this.dataIndex); + }, + + /** + * @param {string} [path] + * @return {module:echarts/model/Model} + */ + getModel: function (path) { + if (this.dataIndex < 0) { + return; + } + var hostTree = this.hostTree; + var itemModel = hostTree.data.getItemModel(this.dataIndex); + var levelModel = this.getLevelModel(); + var leavesModel; + if (!levelModel && (this.children.length === 0 || (this.children.length !== 0 && this.isExpand === false))) { + leavesModel = this.getLeavesModel(); + } + return itemModel.getModel(path, (levelModel || leavesModel || hostTree.hostModel).getModel(path)); + }, + + /** + * @return {module:echarts/model/Model} + */ + getLevelModel: function () { + return (this.hostTree.levelModels || [])[this.depth]; + }, + + /** + * @return {module:echarts/model/Model} + */ + getLeavesModel: function () { + return this.hostTree.leavesModel; + }, + + /** + * @example + * setItemVisual('color', color); + * setItemVisual({ + * 'color': color + * }); + */ + setVisual: function (key, value) { + this.dataIndex >= 0 + && this.hostTree.data.setItemVisual(this.dataIndex, key, value); + }, + + /** + * Get item visual + */ + getVisual: function (key, ignoreParent) { + return this.hostTree.data.getItemVisual(this.dataIndex, key, ignoreParent); + }, + + /** + * @public + * @return {number} + */ + getRawIndex: function () { + return this.hostTree.data.getRawIndex(this.dataIndex); + }, + + /** + * @public + * @return {string} + */ + getId: function () { + return this.hostTree.data.getId(this.dataIndex); + }, + + /** + * if this is an ancestor of another node + * + * @public + * @param {TreeNode} node another node + * @return {boolean} if is ancestor + */ + isAncestorOf: function (node) { + var parent = node.parentNode; + while (parent) { + if (parent === this) { + return true; + } + parent = parent.parentNode; + } + return false; + }, + + /** + * if this is an descendant of another node + * + * @public + * @param {TreeNode} node another node + * @return {boolean} if is descendant + */ + isDescendantOf: function (node) { + return node !== this && node.isAncestorOf(this); + } +}; + +/** + * @constructor + * @alias module:echarts/data/Tree + * @param {module:echarts/model/Model} hostModel + * @param {Array.} levelOptions + * @param {Object} leavesOption + */ +function Tree(hostModel, levelOptions, leavesOption) { + /** + * @type {module:echarts/data/Tree~TreeNode} + * @readOnly + */ + this.root; + + /** + * @type {module:echarts/data/List} + * @readOnly + */ + this.data; + + /** + * Index of each item is the same as the raw index of coresponding list item. + * @private + * @type {Array.} treeOptions.levels + * @param {Array.} treeOptions.leaves + * @return module:echarts/data/Tree + */ +Tree.createTree = function (dataRoot, hostModel, treeOptions) { + + var tree = new Tree(hostModel, treeOptions.levels, treeOptions.leaves); + var listData = []; + var dimMax = 1; + + buildHierarchy(dataRoot); + + function buildHierarchy(dataNode, parentNode) { + var value = dataNode.value; + dimMax = Math.max(dimMax, isArray(value) ? value.length : 1); + + listData.push(dataNode); + + var node = new TreeNode(dataNode.name, tree); + parentNode + ? addChild(node, parentNode) + : (tree.root = node); + + tree._nodes.push(node); + + var children = dataNode.children; + if (children) { + for (var i = 0; i < children.length; i++) { + buildHierarchy(children[i], node); + } + } + } + + tree.root.updateDepthAndHeight(0); + + var dimensionsInfo = createDimensions(listData, { + coordDimensions: ['value'], + dimensionsCount: dimMax + }); + + var list = new List(dimensionsInfo, hostModel); + list.initData(listData); + + linkList({ + mainData: list, + struct: tree, + structAttr: 'tree' + }); + + tree.update(); + + return tree; +}; + +/** + * It is needed to consider the mess of 'list', 'hostModel' when creating a TreeNote, + * so this function is not ready and not necessary to be public. + * + * @param {(module:echarts/data/Tree~TreeNode|Object)} child + */ +function addChild(child, node) { + var children = node.children; + if (child.parentNode === node) { + return; + } + + children.push(child); + child.parentNode = node; +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/** + * @file Create data struct and define tree view's series model + * @author Deqing Li(annong035@gmail.com) + */ + +SeriesModel.extend({ + + type: 'series.tree', + + layoutInfo: null, + + // can support the position parameters 'left', 'top','right','bottom', 'width', + // 'height' in the setOption() with 'merge' mode normal. + layoutMode: 'box', + + /** + * Init a tree data structure from data in option series + * @param {Object} option the object used to config echarts view + * @return {module:echarts/data/List} storage initial data + */ + getInitialData: function (option) { + + //create an virtual root + var root = {name: option.name, children: option.data}; + + var leaves = option.leaves || {}; + + var treeOption = {}; + + treeOption.leaves = leaves; + + var tree = Tree.createTree(root, this, treeOption); + + var treeDepth = 0; + + tree.eachNode('preorder', function (node) { + if (node.depth > treeDepth) { + treeDepth = node.depth; + } + }); + + var expandAndCollapse = option.expandAndCollapse; + var expandTreeDepth = (expandAndCollapse && option.initialTreeDepth >= 0) + ? option.initialTreeDepth : treeDepth; + + tree.root.eachNode('preorder', function (node) { + var item = node.hostTree.data.getRawDataItem(node.dataIndex); + // Add item.collapsed != null, because users can collapse node original in the series.data. + node.isExpand = (item && item.collapsed != null) + ? !item.collapsed + : node.depth <= expandTreeDepth; + }); + + return tree.data; + }, + + /** + * Make the configuration 'orient' backward compatibly, with 'horizontal = LR', 'vertical = TB'. + * @returns {string} orient + */ + getOrient: function () { + var orient = this.get('orient'); + if (orient === 'horizontal') { + orient = 'LR'; + } + else if (orient === 'vertical') { + orient = 'TB'; + } + return orient; + }, + + setZoom: function (zoom) { + this.option.zoom = zoom; + }, + + setCenter: function (center) { + this.option.center = center; + }, + + /** + * @override + * @param {number} dataIndex + */ + formatTooltip: function (dataIndex) { + var tree = this.getData().tree; + var realRoot = tree.root.children[0]; + var node = tree.getNodeByDataIndex(dataIndex); + var value = node.getValue(); + var name = node.name; + while (node && (node !== realRoot)) { + name = node.parentNode.name + '.' + name; + node = node.parentNode; + } + return encodeHTML(name + ( + (isNaN(value) || value == null) ? '' : ' : ' + value + )); + }, + + defaultOption: { + zlevel: 0, + z: 2, + coordinateSystem: 'view', + + // the position of the whole view + left: '12%', + top: '12%', + right: '12%', + bottom: '12%', + + // the layout of the tree, two value can be selected, 'orthogonal' or 'radial' + layout: 'orthogonal', + + roam: false, // true | false | 'move' | 'scale', see module:component/helper/RoamController. + // Symbol size scale ratio in roam + nodeScaleRatio: 0.4, + + // Default on center of graph + center: null, + + zoom: 1, + + // The orient of orthoginal layout, can be setted to 'LR', 'TB', 'RL', 'BT'. + // and the backward compatibility configuration 'horizontal = LR', 'vertical = TB'. + orient: 'LR', + + symbol: 'emptyCircle', + + symbolSize: 7, + + expandAndCollapse: true, + + initialTreeDepth: 2, + + lineStyle: { + color: '#ccc', + width: 1.5, + curveness: 0.5 + }, + + itemStyle: { + color: 'lightsteelblue', + borderColor: '#c23531', + borderWidth: 1.5 + }, + + label: { + show: true, + color: '#555' + }, + + leaves: { + label: { + show: true + } + }, + + animationEasing: 'linear', + + animationDuration: 700, + + animationDurationUpdate: 1000 + } +}); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/* +* A third-party license is embeded for some of the code in this file: +* The tree layoutHelper implementation was originally copied from +* "d3.js"(https://github.com/d3/d3-hierarchy) with +* some modifications made for this project. +* (see more details in the comment of the specific method below.) +* The use of the source code of this file is also subject to the terms +* and consitions of the licence of "d3.js" (BSD-3Clause, see +* ). +*/ + +/** + * @file The layout algorithm of node-link tree diagrams. Here we using Reingold-Tilford algorithm to drawing + * the tree. + */ + +/** + * Initialize all computational message for following algorithm. + * + * @param {module:echarts/data/Tree~TreeNode} root The virtual root of the tree. + */ +function init$2(root) { + root.hierNode = { + defaultAncestor: null, + ancestor: root, + prelim: 0, + modifier: 0, + change: 0, + shift: 0, + i: 0, + thread: null + }; + + var nodes = [root]; + var node; + var children; + + while (node = nodes.pop()) { // jshint ignore:line + children = node.children; + if (node.isExpand && children.length) { + var n = children.length; + for (var i = n - 1; i >= 0; i--) { + var child = children[i]; + child.hierNode = { + defaultAncestor: null, + ancestor: child, + prelim: 0, + modifier: 0, + change: 0, + shift: 0, + i: i, + thread: null + }; + nodes.push(child); + } + } + } +} + +/** + * The implementation of this function was originally copied from "d3.js" + * + * with some modifications made for this program. + * See the license statement at the head of this file. + * + * Computes a preliminary x coordinate for node. Before that, this function is + * applied recursively to the children of node, as well as the function + * apportion(). After spacing out the children by calling executeShifts(), the + * node is placed to the midpoint of its outermost children. + * + * @param {module:echarts/data/Tree~TreeNode} node + * @param {Function} separation + */ +function firstWalk(node, separation) { + var children = node.isExpand ? node.children : []; + var siblings = node.parentNode.children; + var subtreeW = node.hierNode.i ? siblings[node.hierNode.i - 1] : null; + if (children.length) { + executeShifts(node); + var midPoint = (children[0].hierNode.prelim + children[children.length - 1].hierNode.prelim) / 2; + if (subtreeW) { + node.hierNode.prelim = subtreeW.hierNode.prelim + separation(node, subtreeW); + node.hierNode.modifier = node.hierNode.prelim - midPoint; + } + else { + node.hierNode.prelim = midPoint; + } + } + else if (subtreeW) { + node.hierNode.prelim = subtreeW.hierNode.prelim + separation(node, subtreeW); + } + node.parentNode.hierNode.defaultAncestor = apportion( + node, + subtreeW, + node.parentNode.hierNode.defaultAncestor || siblings[0], + separation + ); +} + + +/** + * The implementation of this function was originally copied from "d3.js" + * + * with some modifications made for this program. + * See the license statement at the head of this file. + * + * Computes all real x-coordinates by summing up the modifiers recursively. + * + * @param {module:echarts/data/Tree~TreeNode} node + */ +function secondWalk(node) { + var nodeX = node.hierNode.prelim + node.parentNode.hierNode.modifier; + node.setLayout({x: nodeX}, true); + node.hierNode.modifier += node.parentNode.hierNode.modifier; +} + + +function separation(cb) { + return arguments.length ? cb : defaultSeparation; +} + +/** + * Transform the common coordinate to radial coordinate. + * + * @param {number} x + * @param {number} y + * @return {Object} + */ +function radialCoordinate(x, y) { + var radialCoor = {}; + x -= Math.PI / 2; + radialCoor.x = y * Math.cos(x); + radialCoor.y = y * Math.sin(x); + return radialCoor; +} + +/** + * Get the layout position of the whole view. + * + * @param {module:echarts/model/Series} seriesModel the model object of sankey series + * @param {module:echarts/ExtensionAPI} api provide the API list that the developer can call + * @return {module:zrender/core/BoundingRect} size of rect to draw the sankey view + */ +function getViewRect(seriesModel, api) { + return getLayoutRect( + seriesModel.getBoxLayoutParams(), { + width: api.getWidth(), + height: api.getHeight() + } + ); +} + +/** + * All other shifts, applied to the smaller subtrees between w- and w+, are + * performed by this function. + * + * The implementation of this function was originally copied from "d3.js" + * + * with some modifications made for this program. + * See the license statement at the head of this file. + * + * @param {module:echarts/data/Tree~TreeNode} node + */ +function executeShifts(node) { + var children = node.children; + var n = children.length; + var shift = 0; + var change = 0; + while (--n >= 0) { + var child = children[n]; + child.hierNode.prelim += shift; + child.hierNode.modifier += shift; + change += child.hierNode.change; + shift += child.hierNode.shift + change; + } +} + +/** + * The implementation of this function was originally copied from "d3.js" + * + * with some modifications made for this program. + * See the license statement at the head of this file. + * + * The core of the algorithm. Here, a new subtree is combined with the + * previous subtrees. Threads are used to traverse the inside and outside + * contours of the left and right subtree up to the highest common level. + * Whenever two nodes of the inside contours conflict, we compute the left + * one of the greatest uncommon ancestors using the function nextAncestor() + * and call moveSubtree() to shift the subtree and prepare the shifts of + * smaller subtrees. Finally, we add a new thread (if necessary). + * + * @param {module:echarts/data/Tree~TreeNode} subtreeV + * @param {module:echarts/data/Tree~TreeNode} subtreeW + * @param {module:echarts/data/Tree~TreeNode} ancestor + * @param {Function} separation + * @return {module:echarts/data/Tree~TreeNode} + */ +function apportion(subtreeV, subtreeW, ancestor, separation) { + + if (subtreeW) { + var nodeOutRight = subtreeV; + var nodeInRight = subtreeV; + var nodeOutLeft = nodeInRight.parentNode.children[0]; + var nodeInLeft = subtreeW; + + var sumOutRight = nodeOutRight.hierNode.modifier; + var sumInRight = nodeInRight.hierNode.modifier; + var sumOutLeft = nodeOutLeft.hierNode.modifier; + var sumInLeft = nodeInLeft.hierNode.modifier; + + while (nodeInLeft = nextRight(nodeInLeft), nodeInRight = nextLeft(nodeInRight), nodeInLeft && nodeInRight) { + nodeOutRight = nextRight(nodeOutRight); + nodeOutLeft = nextLeft(nodeOutLeft); + nodeOutRight.hierNode.ancestor = subtreeV; + var shift = nodeInLeft.hierNode.prelim + sumInLeft - nodeInRight.hierNode.prelim + - sumInRight + separation(nodeInLeft, nodeInRight); + if (shift > 0) { + moveSubtree(nextAncestor(nodeInLeft, subtreeV, ancestor), subtreeV, shift); + sumInRight += shift; + sumOutRight += shift; + } + sumInLeft += nodeInLeft.hierNode.modifier; + sumInRight += nodeInRight.hierNode.modifier; + sumOutRight += nodeOutRight.hierNode.modifier; + sumOutLeft += nodeOutLeft.hierNode.modifier; + } + if (nodeInLeft && !nextRight(nodeOutRight)) { + nodeOutRight.hierNode.thread = nodeInLeft; + nodeOutRight.hierNode.modifier += sumInLeft - sumOutRight; + + } + if (nodeInRight && !nextLeft(nodeOutLeft)) { + nodeOutLeft.hierNode.thread = nodeInRight; + nodeOutLeft.hierNode.modifier += sumInRight - sumOutLeft; + ancestor = subtreeV; + } + } + return ancestor; +} + +/** + * This function is used to traverse the right contour of a subtree. + * It returns the rightmost child of node or the thread of node. The function + * returns null if and only if node is on the highest depth of its subtree. + * + * @param {module:echarts/data/Tree~TreeNode} node + * @return {module:echarts/data/Tree~TreeNode} + */ +function nextRight(node) { + var children = node.children; + return children.length && node.isExpand ? children[children.length - 1] : node.hierNode.thread; +} + +/** + * This function is used to traverse the left contour of a subtree (or a subforest). + * It returns the leftmost child of node or the thread of node. The function + * returns null if and only if node is on the highest depth of its subtree. + * + * @param {module:echarts/data/Tree~TreeNode} node + * @return {module:echarts/data/Tree~TreeNode} + */ +function nextLeft(node) { + var children = node.children; + return children.length && node.isExpand ? children[0] : node.hierNode.thread; +} + +/** + * If nodeInLeft’s ancestor is a sibling of node, returns nodeInLeft’s ancestor. + * Otherwise, returns the specified ancestor. + * + * @param {module:echarts/data/Tree~TreeNode} nodeInLeft + * @param {module:echarts/data/Tree~TreeNode} node + * @param {module:echarts/data/Tree~TreeNode} ancestor + * @return {module:echarts/data/Tree~TreeNode} + */ +function nextAncestor(nodeInLeft, node, ancestor) { + return nodeInLeft.hierNode.ancestor.parentNode === node.parentNode + ? nodeInLeft.hierNode.ancestor : ancestor; +} + +/** + * The implementation of this function was originally copied from "d3.js" + * + * with some modifications made for this program. + * See the license statement at the head of this file. + * + * Shifts the current subtree rooted at wr. + * This is done by increasing prelim(w+) and modifier(w+) by shift. + * + * @param {module:echarts/data/Tree~TreeNode} wl + * @param {module:echarts/data/Tree~TreeNode} wr + * @param {number} shift [description] + */ +function moveSubtree(wl, wr, shift) { + var change = shift / (wr.hierNode.i - wl.hierNode.i); + wr.hierNode.change -= change; + wr.hierNode.shift += shift; + wr.hierNode.modifier += shift; + wr.hierNode.prelim += shift; + wl.hierNode.change += change; +} + +/** + * The implementation of this function was originally copied from "d3.js" + * + * with some modifications made for this program. + * See the license statement at the head of this file. + */ +function defaultSeparation(node1, node2) { + return node1.parentNode === node2.parentNode ? 1 : 2; +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/** + * @file This file used to draw tree view. + * @author Deqing Li(annong035@gmail.com) + */ + +extendChartView({ + + type: 'tree', + + /** + * Init the chart + * @override + * @param {module:echarts/model/Global} ecModel + * @param {module:echarts/ExtensionAPI} api + */ + init: function (ecModel, api) { + + /** + * @private + * @type {module:echarts/data/Tree} + */ + this._oldTree; + + /** + * @private + * @type {module:zrender/container/Group} + */ + this._mainGroup = new Group(); + + /** + * @private + * @type {module:echarts/componet/helper/RoamController} + */ + this._controller = new RoamController(api.getZr()); + + this._controllerHost = {target: this.group}; + + this.group.add(this._mainGroup); + }, + + render: function (seriesModel, ecModel, api, payload) { + var data = seriesModel.getData(); + + var layoutInfo = seriesModel.layoutInfo; + + var group = this._mainGroup; + + var layout = seriesModel.get('layout'); + + if (layout === 'radial') { + group.attr('position', [layoutInfo.x + layoutInfo.width / 2, layoutInfo.y + layoutInfo.height / 2]); + } + else { + group.attr('position', [layoutInfo.x, layoutInfo.y]); + } + + this._updateViewCoordSys(seriesModel); + this._updateController(seriesModel, ecModel, api); + + var oldData = this._data; + + var seriesScope = { + expandAndCollapse: seriesModel.get('expandAndCollapse'), + layout: layout, + orient: seriesModel.getOrient(), + curvature: seriesModel.get('lineStyle.curveness'), + symbolRotate: seriesModel.get('symbolRotate'), + symbolOffset: seriesModel.get('symbolOffset'), + hoverAnimation: seriesModel.get('hoverAnimation'), + useNameLabel: true, + fadeIn: true + }; + + data.diff(oldData) + .add(function (newIdx) { + if (symbolNeedsDraw$1(data, newIdx)) { + // Create node and edge + updateNode(data, newIdx, null, group, seriesModel, seriesScope); + } + }) + .update(function (newIdx, oldIdx) { + var symbolEl = oldData.getItemGraphicEl(oldIdx); + if (!symbolNeedsDraw$1(data, newIdx)) { + symbolEl && removeNode(oldData, oldIdx, symbolEl, group, seriesModel, seriesScope); + return; + } + // Update node and edge + updateNode(data, newIdx, symbolEl, group, seriesModel, seriesScope); + }) + .remove(function (oldIdx) { + var symbolEl = oldData.getItemGraphicEl(oldIdx); + // When remove a collapsed node of subtree, since the collapsed + // node haven't been initialized with a symbol element, + // you can't found it's symbol element through index. + // so if we want to remove the symbol element we should insure + // that the symbol element is not null. + if (symbolEl) { + removeNode(oldData, oldIdx, symbolEl, group, seriesModel, seriesScope); + } + }) + .execute(); + + this._nodeScaleRatio = seriesModel.get('nodeScaleRatio'); + + this._updateNodeAndLinkScale(seriesModel); + + if (seriesScope.expandAndCollapse === true) { + data.eachItemGraphicEl(function (el, dataIndex) { + el.off('click').on('click', function () { + api.dispatchAction({ + type: 'treeExpandAndCollapse', + seriesId: seriesModel.id, + dataIndex: dataIndex + }); + }); + }); + } + this._data = data; + }, + + _updateViewCoordSys: function (seriesModel) { + var data = seriesModel.getData(); + var points = []; + data.each(function (idx) { + var layout = data.getItemLayout(idx); + if (layout && !isNaN(layout.x) && !isNaN(layout.y)) { + points.push([+layout.x, +layout.y]); + } + }); + var min = []; + var max = []; + fromPoints(points, min, max); + // If width or height is 0 + if (max[0] - min[0] === 0) { + max[0] += 1; + min[0] -= 1; + } + if (max[1] - min[1] === 0) { + max[1] += 1; + min[1] -= 1; + } + + var viewCoordSys = seriesModel.coordinateSystem = new View(); + viewCoordSys.zoomLimit = seriesModel.get('scaleLimit'); + + viewCoordSys.setBoundingRect(min[0], min[1], max[0] - min[0], max[1] - min[1]); + + viewCoordSys.setCenter(seriesModel.get('center')); + viewCoordSys.setZoom(seriesModel.get('zoom')); + + // Here we use viewCoordSys just for computing the 'position' and 'scale' of the group + this.group.attr({ + position: viewCoordSys.position, + scale: viewCoordSys.scale + }); + + this._viewCoordSys = viewCoordSys; + }, + + _updateController: function (seriesModel, ecModel, api) { + var controller = this._controller; + var controllerHost = this._controllerHost; + var group = this.group; + controller.setPointerChecker(function (e, x, y) { + var rect = group.getBoundingRect(); + rect.applyTransform(group.transform); + return rect.contain(x, y) + && !onIrrelevantElement(e, api, seriesModel); + }); + + controller.enable(seriesModel.get('roam')); + controllerHost.zoomLimit = seriesModel.get('scaleLimit'); + controllerHost.zoom = seriesModel.coordinateSystem.getZoom(); + + controller + .off('pan') + .off('zoom') + .on('pan', function (e) { + updateViewOnPan(controllerHost, e.dx, e.dy); + api.dispatchAction({ + seriesId: seriesModel.id, + type: 'treeRoam', + dx: e.dx, + dy: e.dy + }); + }, this) + .on('zoom', function (e) { + updateViewOnZoom(controllerHost, e.scale, e.originX, e.originY); + api.dispatchAction({ + seriesId: seriesModel.id, + type: 'treeRoam', + zoom: e.scale, + originX: e.originX, + originY: e.originY + }); + this._updateNodeAndLinkScale(seriesModel); + }, this); + }, + + _updateNodeAndLinkScale: function (seriesModel) { + var data = seriesModel.getData(); + + var nodeScale = this._getNodeGlobalScale(seriesModel); + var invScale = [nodeScale, nodeScale]; + + data.eachItemGraphicEl(function (el, idx) { + el.attr('scale', invScale); + }); + }, + + _getNodeGlobalScale: function (seriesModel) { + var coordSys = seriesModel.coordinateSystem; + if (coordSys.type !== 'view') { + return 1; + } + + var nodeScaleRatio = this._nodeScaleRatio; + + var groupScale = coordSys.scale; + var groupZoom = (groupScale && groupScale[0]) || 1; + // Scale node when zoom changes + var roamZoom = coordSys.getZoom(); + var nodeScale = (roamZoom - 1) * nodeScaleRatio + 1; + + return nodeScale / groupZoom; + }, + + dispose: function () { + this._controller && this._controller.dispose(); + this._controllerHost = {}; + }, + + remove: function () { + this._mainGroup.removeAll(); + this._data = null; + } + +}); + +function symbolNeedsDraw$1(data, dataIndex) { + var layout = data.getItemLayout(dataIndex); + + return layout + && !isNaN(layout.x) && !isNaN(layout.y) + && data.getItemVisual(dataIndex, 'symbol') !== 'none'; +} + +function getTreeNodeStyle(node, itemModel, seriesScope) { + seriesScope.itemModel = itemModel; + seriesScope.itemStyle = itemModel.getModel('itemStyle').getItemStyle(); + seriesScope.hoverItemStyle = itemModel.getModel('emphasis.itemStyle').getItemStyle(); + seriesScope.lineStyle = itemModel.getModel('lineStyle').getLineStyle(); + seriesScope.labelModel = itemModel.getModel('label'); + seriesScope.hoverLabelModel = itemModel.getModel('emphasis.label'); + + if (node.isExpand === false && node.children.length !== 0) { + seriesScope.symbolInnerColor = seriesScope.itemStyle.fill; + } + else { + seriesScope.symbolInnerColor = '#fff'; + } + + return seriesScope; +} + +function updateNode(data, dataIndex, symbolEl, group, seriesModel, seriesScope) { + var isInit = !symbolEl; + var node = data.tree.getNodeByDataIndex(dataIndex); + var itemModel = node.getModel(); + var seriesScope = getTreeNodeStyle(node, itemModel, seriesScope); + var virtualRoot = data.tree.root; + + var source = node.parentNode === virtualRoot ? node : node.parentNode || node; + var sourceSymbolEl = data.getItemGraphicEl(source.dataIndex); + var sourceLayout = source.getLayout(); + var sourceOldLayout = sourceSymbolEl + ? { + x: sourceSymbolEl.position[0], + y: sourceSymbolEl.position[1], + rawX: sourceSymbolEl.__radialOldRawX, + rawY: sourceSymbolEl.__radialOldRawY + } + : sourceLayout; + var targetLayout = node.getLayout(); + + if (isInit) { + symbolEl = new SymbolClz$1(data, dataIndex, seriesScope); + symbolEl.attr('position', [sourceOldLayout.x, sourceOldLayout.y]); + } + else { + symbolEl.updateData(data, dataIndex, seriesScope); + } + + symbolEl.__radialOldRawX = symbolEl.__radialRawX; + symbolEl.__radialOldRawY = symbolEl.__radialRawY; + symbolEl.__radialRawX = targetLayout.rawX; + symbolEl.__radialRawY = targetLayout.rawY; + + group.add(symbolEl); + data.setItemGraphicEl(dataIndex, symbolEl); + updateProps(symbolEl, { + position: [targetLayout.x, targetLayout.y] + }, seriesModel); + + var symbolPath = symbolEl.getSymbolPath(); + + if (seriesScope.layout === 'radial') { + var realRoot = virtualRoot.children[0]; + var rootLayout = realRoot.getLayout(); + var length = realRoot.children.length; + var rad; + var isLeft; + + if (targetLayout.x === rootLayout.x && node.isExpand === true) { + var center = {}; + center.x = (realRoot.children[0].getLayout().x + realRoot.children[length - 1].getLayout().x) / 2; + center.y = (realRoot.children[0].getLayout().y + realRoot.children[length - 1].getLayout().y) / 2; + rad = Math.atan2(center.y - rootLayout.y, center.x - rootLayout.x); + if (rad < 0) { + rad = Math.PI * 2 + rad; + } + isLeft = center.x < rootLayout.x; + if (isLeft) { + rad = rad - Math.PI; + } + } + else { + rad = Math.atan2(targetLayout.y - rootLayout.y, targetLayout.x - rootLayout.x); + if (rad < 0) { + rad = Math.PI * 2 + rad; + } + if (node.children.length === 0 || (node.children.length !== 0 && node.isExpand === false)) { + isLeft = targetLayout.x < rootLayout.x; + if (isLeft) { + rad = rad - Math.PI; + } + } + else { + isLeft = targetLayout.x > rootLayout.x; + if (!isLeft) { + rad = rad - Math.PI; + } + } + } + + var textPosition = isLeft ? 'left' : 'right'; + symbolPath.setStyle({ + textPosition: textPosition, + textRotation: -rad, + textOrigin: 'center', + verticalAlign: 'middle' + }); + } + + if (node.parentNode && node.parentNode !== virtualRoot) { + var edge = symbolEl.__edge; + if (!edge) { + edge = symbolEl.__edge = new BezierCurve({ + shape: getEdgeShape(seriesScope, sourceOldLayout, sourceOldLayout), + style: defaults({opacity: 0, strokeNoScale: true}, seriesScope.lineStyle) + }); + } + + updateProps(edge, { + shape: getEdgeShape(seriesScope, sourceLayout, targetLayout), + style: {opacity: 1} + }, seriesModel); + + group.add(edge); + } +} + +function removeNode(data, dataIndex, symbolEl, group, seriesModel, seriesScope) { + var node = data.tree.getNodeByDataIndex(dataIndex); + var virtualRoot = data.tree.root; + var itemModel = node.getModel(); + var seriesScope = getTreeNodeStyle(node, itemModel, seriesScope); + + var source = node.parentNode === virtualRoot ? node : node.parentNode || node; + var sourceLayout; + while (sourceLayout = source.getLayout(), sourceLayout == null) { + source = source.parentNode === virtualRoot ? source : source.parentNode || source; + } + + updateProps(symbolEl, { + position: [sourceLayout.x + 1, sourceLayout.y + 1] + }, seriesModel, function () { + group.remove(symbolEl); + data.setItemGraphicEl(dataIndex, null); + }); + + symbolEl.fadeOut(null, {keepLabel: true}); + + var edge = symbolEl.__edge; + if (edge) { + updateProps(edge, { + shape: getEdgeShape(seriesScope, sourceLayout, sourceLayout), + style: { + opacity: 0 + } + }, seriesModel, function () { + group.remove(edge); + }); + } +} + +function getEdgeShape(seriesScope, sourceLayout, targetLayout) { + var cpx1; + var cpy1; + var cpx2; + var cpy2; + var orient = seriesScope.orient; + var x1; + var x2; + var y1; + var y2; + + if (seriesScope.layout === 'radial') { + x1 = sourceLayout.rawX; + y1 = sourceLayout.rawY; + x2 = targetLayout.rawX; + y2 = targetLayout.rawY; + + var radialCoor1 = radialCoordinate(x1, y1); + var radialCoor2 = radialCoordinate(x1, y1 + (y2 - y1) * seriesScope.curvature); + var radialCoor3 = radialCoordinate(x2, y2 + (y1 - y2) * seriesScope.curvature); + var radialCoor4 = radialCoordinate(x2, y2); + + return { + x1: radialCoor1.x, + y1: radialCoor1.y, + x2: radialCoor4.x, + y2: radialCoor4.y, + cpx1: radialCoor2.x, + cpy1: radialCoor2.y, + cpx2: radialCoor3.x, + cpy2: radialCoor3.y + }; + } + else { + x1 = sourceLayout.x; + y1 = sourceLayout.y; + x2 = targetLayout.x; + y2 = targetLayout.y; + + if (orient === 'LR' || orient === 'RL') { + cpx1 = x1 + (x2 - x1) * seriesScope.curvature; + cpy1 = y1; + cpx2 = x2 + (x1 - x2) * seriesScope.curvature; + cpy2 = y2; + } + if (orient === 'TB' || orient === 'BT') { + cpx1 = x1; + cpy1 = y1 + (y2 - y1) * seriesScope.curvature; + cpx2 = x2; + cpy2 = y2 + (y1 - y2) * seriesScope.curvature; + } + } + + return { + x1: x1, + y1: y1, + x2: x2, + y2: y2, + cpx1: cpx1, + cpy1: cpy1, + cpx2: cpx2, + cpy2: cpy2 + }; + +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/** + * @file Register the actions of the tree + * @author Deqing Li(annong035@gmail.com) + */ + +registerAction({ + type: 'treeExpandAndCollapse', + event: 'treeExpandAndCollapse', + update: 'update' +}, function (payload, ecModel) { + ecModel.eachComponent({mainType: 'series', subType: 'tree', query: payload}, function (seriesModel) { + var dataIndex = payload.dataIndex; + var tree = seriesModel.getData().tree; + var node = tree.getNodeByDataIndex(dataIndex); + node.isExpand = !node.isExpand; + + }); +}); + +registerAction({ + type: 'treeRoam', + event: 'treeRoam', + // Here we set 'none' instead of 'update', because roam action + // just need to update the transform matrix without having to recalculate + // the layout. So don't need to go through the whole update process, such + // as 'dataPrcocess', 'coordSystemUpdate', 'layout' and so on. + update: 'none' +}, function (payload, ecModel) { + ecModel.eachComponent({mainType: 'series', subType: 'tree', query: payload}, function (seriesModel) { + var coordSys = seriesModel.coordinateSystem; + var res = updateCenterAndZoom(coordSys, payload); + + seriesModel.setCenter + && seriesModel.setCenter(res.center); + + seriesModel.setZoom + && seriesModel.setZoom(res.zoom); + }); +}); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + + +/** + * Traverse the tree from bottom to top and do something + * @param {module:echarts/data/Tree~TreeNode} root The real root of the tree + * @param {Function} callback + */ +function eachAfter(root, callback, separation) { + var nodes = [root]; + var next = []; + var node; + + while (node = nodes.pop()) { // jshint ignore:line + next.push(node); + if (node.isExpand) { + var children = node.children; + if (children.length) { + for (var i = 0; i < children.length; i++) { + nodes.push(children[i]); + } + } + } + } + + while (node = next.pop()) { // jshint ignore:line + callback(node, separation); + } +} + +/** + * Traverse the tree from top to bottom and do something + * @param {module:echarts/data/Tree~TreeNode} root The real root of the tree + * @param {Function} callback + */ +function eachBefore(root, callback) { + var nodes = [root]; + var node; + while (node = nodes.pop()) { // jshint ignore:line + callback(node); + if (node.isExpand) { + var children = node.children; + if (children.length) { + for (var i = children.length - 1; i >= 0; i--) { + nodes.push(children[i]); + } + } + } + } +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var treeLayout = function (ecModel, api) { + ecModel.eachSeriesByType('tree', function (seriesModel) { + commonLayout(seriesModel, api); + }); +}; + +function commonLayout(seriesModel, api) { + var layoutInfo = getViewRect(seriesModel, api); + seriesModel.layoutInfo = layoutInfo; + var layout = seriesModel.get('layout'); + var width = 0; + var height = 0; + var separation$$1 = null; + + if (layout === 'radial') { + width = 2 * Math.PI; + height = Math.min(layoutInfo.height, layoutInfo.width) / 2; + separation$$1 = separation(function (node1, node2) { + return (node1.parentNode === node2.parentNode ? 1 : 2) / node1.depth; + }); + } + else { + width = layoutInfo.width; + height = layoutInfo.height; + separation$$1 = separation(); + } + + var virtualRoot = seriesModel.getData().tree.root; + var realRoot = virtualRoot.children[0]; + + if (realRoot) { + init$2(virtualRoot); + eachAfter(realRoot, firstWalk, separation$$1); + virtualRoot.hierNode.modifier = -realRoot.hierNode.prelim; + eachBefore(realRoot, secondWalk); + + var left = realRoot; + var right = realRoot; + var bottom = realRoot; + eachBefore(realRoot, function (node) { + var x = node.getLayout().x; + if (x < left.getLayout().x) { + left = node; + } + if (x > right.getLayout().x) { + right = node; + } + if (node.depth > bottom.depth) { + bottom = node; + } + }); + + var delta = left === right ? 1 : separation$$1(left, right) / 2; + var tx = delta - left.getLayout().x; + var kx = 0; + var ky = 0; + var coorX = 0; + var coorY = 0; + if (layout === 'radial') { + kx = width / (right.getLayout().x + delta + tx); + // here we use (node.depth - 1), bucause the real root's depth is 1 + ky = height / ((bottom.depth - 1) || 1); + eachBefore(realRoot, function (node) { + coorX = (node.getLayout().x + tx) * kx; + coorY = (node.depth - 1) * ky; + var finalCoor = radialCoordinate(coorX, coorY); + node.setLayout({x: finalCoor.x, y: finalCoor.y, rawX: coorX, rawY: coorY}, true); + }); + } + else { + var orient = seriesModel.getOrient(); + if (orient === 'RL' || orient === 'LR') { + ky = height / (right.getLayout().x + delta + tx); + kx = width / ((bottom.depth - 1) || 1); + eachBefore(realRoot, function (node) { + coorY = (node.getLayout().x + tx) * ky; + coorX = orient === 'LR' + ? (node.depth - 1) * kx + : width - (node.depth - 1) * kx; + node.setLayout({x: coorX, y: coorY}, true); + }); + } + else if (orient === 'TB' || orient === 'BT') { + kx = width / (right.getLayout().x + delta + tx); + ky = height / ((bottom.depth - 1) || 1); + eachBefore(realRoot, function (node) { + coorX = (node.getLayout().x + tx) * kx; + coorY = orient === 'TB' + ? (node.depth - 1) * ky + : height - (node.depth - 1) * ky; + node.setLayout({x: coorX, y: coorY}, true); + }); + } + } + } +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +registerVisual(visualSymbol('tree', 'circle')); +registerLayout(treeLayout); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +function retrieveTargetInfo(payload, validPayloadTypes, seriesModel) { + if (payload && indexOf(validPayloadTypes, payload.type) >= 0) { + var root = seriesModel.getData().tree.root; + var targetNode = payload.targetNode; + + if (typeof targetNode === 'string') { + targetNode = root.getNodeById(targetNode); + } + + if (targetNode && root.contains(targetNode)) { + return {node: targetNode}; + } + + var targetNodeId = payload.targetNodeId; + if (targetNodeId != null && (targetNode = root.getNodeById(targetNodeId))) { + return {node: targetNode}; + } + } +} + +// Not includes the given node at the last item. +function getPathToRoot(node) { + var path = []; + while (node) { + node = node.parentNode; + node && path.push(node); + } + return path.reverse(); +} + +function aboveViewRoot(viewRoot, node) { + var viewPath = getPathToRoot(viewRoot); + return indexOf(viewPath, node) >= 0; +} + +// From root to the input node (the input node will be included). +function wrapTreePathInfo(node, seriesModel) { + var treePathInfo = []; + + while (node) { + var nodeDataIndex = node.dataIndex; + treePathInfo.push({ + name: node.name, + dataIndex: nodeDataIndex, + value: seriesModel.getRawValue(nodeDataIndex) + }); + node = node.parentNode; + } + + treePathInfo.reverse(); + + return treePathInfo; +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +SeriesModel.extend({ + + type: 'series.treemap', + + layoutMode: 'box', + + dependencies: ['grid', 'polar'], + + /** + * @type {module:echarts/data/Tree~Node} + */ + _viewRoot: null, + + defaultOption: { + // Disable progressive rendering + progressive: 0, + hoverLayerThreshold: Infinity, + // center: ['50%', '50%'], // not supported in ec3. + // size: ['80%', '80%'], // deprecated, compatible with ec2. + left: 'center', + top: 'middle', + right: null, + bottom: null, + width: '80%', + height: '80%', + sort: true, // Can be null or false or true + // (order by desc default, asc not supported yet (strange effect)) + clipWindow: 'origin', // Size of clipped window when zooming. 'origin' or 'fullscreen' + squareRatio: 0.5 * (1 + Math.sqrt(5)), // golden ratio + leafDepth: null, // Nodes on depth from root are regarded as leaves. + // Count from zero (zero represents only view root). + drillDownIcon: '▶', // Use html character temporarily because it is complicated + // to align specialized icon. ▷▶❒❐▼✚ + + zoomToNodeRatio: 0.32 * 0.32, // Be effective when using zoomToNode. Specify the proportion of the + // target node area in the view area. + roam: true, // true, false, 'scale' or 'zoom', 'move'. + nodeClick: 'zoomToNode', // Leaf node click behaviour: 'zoomToNode', 'link', false. + // If leafDepth is set and clicking a node which has children but + // be on left depth, the behaviour would be changing root. Otherwise + // use behavious defined above. + animation: true, + animationDurationUpdate: 900, + animationEasing: 'quinticInOut', + breadcrumb: { + show: true, + height: 22, + left: 'center', + top: 'bottom', + // right + // bottom + emptyItemWidth: 25, // Width of empty node. + itemStyle: { + color: 'rgba(0,0,0,0.7)', //'#5793f3', + borderColor: 'rgba(255,255,255,0.7)', + borderWidth: 1, + shadowColor: 'rgba(150,150,150,1)', + shadowBlur: 3, + shadowOffsetX: 0, + shadowOffsetY: 0, + textStyle: { + color: '#fff' + } + }, + emphasis: { + textStyle: {} + } + }, + label: { + show: true, + // Do not use textDistance, for ellipsis rect just the same as treemap node rect. + distance: 0, + padding: 5, + position: 'inside', // Can be [5, '5%'] or position stirng like 'insideTopLeft', ... + // formatter: null, + color: '#fff', + ellipsis: true + // align + // verticalAlign + }, + upperLabel: { // Label when node is parent. + show: false, + position: [0, '50%'], + height: 20, + // formatter: null, + color: '#fff', + ellipsis: true, + // align: null, + verticalAlign: 'middle' + }, + itemStyle: { + color: null, // Can be 'none' if not necessary. + colorAlpha: null, // Can be 'none' if not necessary. + colorSaturation: null, // Can be 'none' if not necessary. + borderWidth: 0, + gapWidth: 0, + borderColor: '#fff', + borderColorSaturation: null // If specified, borderColor will be ineffective, and the + // border color is evaluated by color of current node and + // borderColorSaturation. + }, + emphasis: { + upperLabel: { + show: true, + position: [0, '50%'], + color: '#fff', + ellipsis: true, + verticalAlign: 'middle' + } + }, + + visualDimension: 0, // Can be 0, 1, 2, 3. + visualMin: null, + visualMax: null, + + color: [], // + treemapSeries.color should not be modified. Please only modified + // level[n].color (if necessary). + // + Specify color list of each level. level[0].color would be global + // color list if not specified. (see method `setDefault`). + // + But set as a empty array to forbid fetch color from global palette + // when using nodeModel.get('color'), otherwise nodes on deep level + // will always has color palette set and are not able to inherit color + // from parent node. + // + TreemapSeries.color can not be set as 'none', otherwise effect + // legend color fetching (see seriesColor.js). + colorAlpha: null, // Array. Specify color alpha range of each level, like [0.2, 0.8] + colorSaturation: null, // Array. Specify color saturation of each level, like [0.2, 0.5] + colorMappingBy: 'index', // 'value' or 'index' or 'id'. + visibleMin: 10, // If area less than this threshold (unit: pixel^2), node will not + // be rendered. Only works when sort is 'asc' or 'desc'. + childrenVisibleMin: null, // If area of a node less than this threshold (unit: pixel^2), + // grandchildren will not show. + // Why grandchildren? If not grandchildren but children, + // some siblings show children and some not, + // the appearance may be mess and not consistent, + levels: [] // Each item: { + // visibleMin, itemStyle, visualDimension, label + // } + // data: { + // value: [], + // children: [], + // link: 'http://xxx.xxx.xxx', + // target: 'blank' or 'self' + // } + }, + + /** + * @override + */ + getInitialData: function (option, ecModel) { + // Create a virtual root. + var root = {name: option.name, children: option.data}; + + completeTreeValue(root); + + var levels = option.levels || []; + + levels = option.levels = setDefault(levels, ecModel); + + var treeOption = {}; + + treeOption.levels = levels; + + // Make sure always a new tree is created when setOption, + // in TreemapView, we check whether oldTree === newTree + // to choose mappings approach among old shapes and new shapes. + return Tree.createTree(root, this, treeOption).data; + }, + + optionUpdated: function () { + this.resetViewRoot(); + }, + + /** + * @override + * @param {number} dataIndex + * @param {boolean} [mutipleSeries=false] + */ + formatTooltip: function (dataIndex) { + var data = this.getData(); + var value = this.getRawValue(dataIndex); + var formattedValue = isArray(value) + ? addCommas(value[0]) : addCommas(value); + var name = data.getName(dataIndex); + + return encodeHTML(name + ': ' + formattedValue); + }, + + /** + * Add tree path to tooltip param + * + * @override + * @param {number} dataIndex + * @return {Object} + */ + getDataParams: function (dataIndex) { + var params = SeriesModel.prototype.getDataParams.apply(this, arguments); + + var node = this.getData().tree.getNodeByDataIndex(dataIndex); + params.treePathInfo = wrapTreePathInfo(node, this); + + return params; + }, + + /** + * @public + * @param {Object} layoutInfo { + * x: containerGroup x + * y: containerGroup y + * width: containerGroup width + * height: containerGroup height + * } + */ + setLayoutInfo: function (layoutInfo) { + /** + * @readOnly + * @type {Object} + */ + this.layoutInfo = this.layoutInfo || {}; + extend(this.layoutInfo, layoutInfo); + }, + + /** + * @param {string} id + * @return {number} index + */ + mapIdToIndex: function (id) { + // A feature is implemented: + // index is monotone increasing with the sequence of + // input id at the first time. + // This feature can make sure that each data item and its + // mapped color have the same index between data list and + // color list at the beginning, which is useful for user + // to adjust data-color mapping. + + /** + * @private + * @type {Object} + */ + var idIndexMap = this._idIndexMap; + + if (!idIndexMap) { + idIndexMap = this._idIndexMap = createHashMap(); + /** + * @private + * @type {number} + */ + this._idIndexMapCount = 0; + } + + var index = idIndexMap.get(id); + if (index == null) { + idIndexMap.set(id, index = this._idIndexMapCount++); + } + + return index; + }, + + getViewRoot: function () { + return this._viewRoot; + }, + + /** + * @param {module:echarts/data/Tree~Node} [viewRoot] + */ + resetViewRoot: function (viewRoot) { + viewRoot + ? (this._viewRoot = viewRoot) + : (viewRoot = this._viewRoot); + + var root = this.getRawData().tree.root; + + if (!viewRoot + || (viewRoot !== root && !root.contains(viewRoot)) + ) { + this._viewRoot = root; + } + } +}); + +/** + * @param {Object} dataNode + */ +function completeTreeValue(dataNode) { + // Postorder travel tree. + // If value of none-leaf node is not set, + // calculate it by suming up the value of all children. + var sum = 0; + + each$1(dataNode.children, function (child) { + + completeTreeValue(child); + + var childValue = child.value; + isArray(childValue) && (childValue = childValue[0]); + + sum += childValue; + }); + + var thisValue = dataNode.value; + if (isArray(thisValue)) { + thisValue = thisValue[0]; + } + + if (thisValue == null || isNaN(thisValue)) { + thisValue = sum; + } + // Value should not less than 0. + if (thisValue < 0) { + thisValue = 0; + } + + isArray(dataNode.value) + ? (dataNode.value[0] = thisValue) + : (dataNode.value = thisValue); +} + +/** + * set default to level configuration + */ +function setDefault(levels, ecModel) { + var globalColorList = ecModel.get('color'); + + if (!globalColorList) { + return; + } + + levels = levels || []; + var hasColorDefine; + each$1(levels, function (levelDefine) { + var model = new Model(levelDefine); + var modelColor = model.get('color'); + + if (model.get('itemStyle.color') + || (modelColor && modelColor !== 'none') + ) { + hasColorDefine = true; + } + }); + + if (!hasColorDefine) { + var level0 = levels[0] || (levels[0] = {}); + level0.color = globalColorList.slice(); + } + + return levels; +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var TEXT_PADDING = 8; +var ITEM_GAP = 8; +var ARRAY_LENGTH = 5; + +function Breadcrumb(containerGroup) { + /** + * @private + * @type {module:zrender/container/Group} + */ + this.group = new Group(); + + containerGroup.add(this.group); +} + +Breadcrumb.prototype = { + + constructor: Breadcrumb, + + render: function (seriesModel, api, targetNode, onSelect) { + var model = seriesModel.getModel('breadcrumb'); + var thisGroup = this.group; + + thisGroup.removeAll(); + + if (!model.get('show') || !targetNode) { + return; + } + + var normalStyleModel = model.getModel('itemStyle'); + // var emphasisStyleModel = model.getModel('emphasis.itemStyle'); + var textStyleModel = normalStyleModel.getModel('textStyle'); + + var layoutParam = { + pos: { + left: model.get('left'), + right: model.get('right'), + top: model.get('top'), + bottom: model.get('bottom') + }, + box: { + width: api.getWidth(), + height: api.getHeight() + }, + emptyItemWidth: model.get('emptyItemWidth'), + totalWidth: 0, + renderList: [] + }; + + this._prepare(targetNode, layoutParam, textStyleModel); + this._renderContent(seriesModel, layoutParam, normalStyleModel, textStyleModel, onSelect); + + positionElement(thisGroup, layoutParam.pos, layoutParam.box); + }, + + /** + * Prepare render list and total width + * @private + */ + _prepare: function (targetNode, layoutParam, textStyleModel) { + for (var node = targetNode; node; node = node.parentNode) { + var text = node.getModel().get('name'); + var textRect = textStyleModel.getTextRect(text); + var itemWidth = Math.max( + textRect.width + TEXT_PADDING * 2, + layoutParam.emptyItemWidth + ); + layoutParam.totalWidth += itemWidth + ITEM_GAP; + layoutParam.renderList.push({node: node, text: text, width: itemWidth}); + } + }, + + /** + * @private + */ + _renderContent: function ( + seriesModel, layoutParam, normalStyleModel, textStyleModel, onSelect + ) { + // Start rendering. + var lastX = 0; + var emptyItemWidth = layoutParam.emptyItemWidth; + var height = seriesModel.get('breadcrumb.height'); + var availableSize = getAvailableSize(layoutParam.pos, layoutParam.box); + var totalWidth = layoutParam.totalWidth; + var renderList = layoutParam.renderList; + + for (var i = renderList.length - 1; i >= 0; i--) { + var item = renderList[i]; + var itemNode = item.node; + var itemWidth = item.width; + var text = item.text; + + // Hdie text and shorten width if necessary. + if (totalWidth > availableSize.width) { + totalWidth -= itemWidth - emptyItemWidth; + itemWidth = emptyItemWidth; + text = null; + } + + var el = new Polygon({ + shape: { + points: makeItemPoints( + lastX, 0, itemWidth, height, + i === renderList.length - 1, i === 0 + ) + }, + style: defaults( + normalStyleModel.getItemStyle(), + { + lineJoin: 'bevel', + text: text, + textFill: textStyleModel.getTextColor(), + textFont: textStyleModel.getFont() + } + ), + z: 10, + onclick: curry(onSelect, itemNode) + }); + this.group.add(el); + + packEventData(el, seriesModel, itemNode); + + lastX += itemWidth + ITEM_GAP; + } + }, + + /** + * @override + */ + remove: function () { + this.group.removeAll(); + } +}; + +function makeItemPoints(x, y, itemWidth, itemHeight, head, tail) { + var points = [ + [head ? x : x - ARRAY_LENGTH, y], + [x + itemWidth, y], + [x + itemWidth, y + itemHeight], + [head ? x : x - ARRAY_LENGTH, y + itemHeight] + ]; + !tail && points.splice(2, 0, [x + itemWidth + ARRAY_LENGTH, y + itemHeight / 2]); + !head && points.push([x, y + itemHeight / 2]); + return points; +} + +// Package custom mouse event. +function packEventData(el, seriesModel, itemNode) { + el.eventData = { + componentType: 'series', + componentSubType: 'treemap', + componentIndex: seriesModel.componentIndex, + seriesIndex: seriesModel.componentIndex, + seriesName: seriesModel.name, + seriesType: 'treemap', + selfType: 'breadcrumb', // Distinguish with click event on treemap node. + nodeData: { + dataIndex: itemNode && itemNode.dataIndex, + name: itemNode && itemNode.name + }, + treePathInfo: itemNode && wrapTreePathInfo(itemNode, seriesModel) + }; +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/** + * @param {number} [time=500] Time in ms + * @param {string} [easing='linear'] + * @param {number} [delay=0] + * @param {Function} [callback] + * + * @example + * // Animate position + * animation + * .createWrap() + * .add(el1, {position: [10, 10]}) + * .add(el2, {shape: {width: 500}, style: {fill: 'red'}}, 400) + * .done(function () { // done }) + * .start('cubicOut'); + */ +function createWrap() { + + var storage = []; + var elExistsMap = {}; + var doneCallback; + + return { + + /** + * Caution: a el can only be added once, otherwise 'done' + * might not be called. This method checks this (by el.id), + * suppresses adding and returns false when existing el found. + * + * @param {modele:zrender/Element} el + * @param {Object} target + * @param {number} [time=500] + * @param {number} [delay=0] + * @param {string} [easing='linear'] + * @return {boolean} Whether adding succeeded. + * + * @example + * add(el, target, time, delay, easing); + * add(el, target, time, easing); + * add(el, target, time); + * add(el, target); + */ + add: function (el, target, time, delay, easing) { + if (isString(delay)) { + easing = delay; + delay = 0; + } + + if (elExistsMap[el.id]) { + return false; + } + elExistsMap[el.id] = 1; + + storage.push( + {el: el, target: target, time: time, delay: delay, easing: easing} + ); + + return true; + }, + + /** + * Only execute when animation finished. Will not execute when any + * of 'stop' or 'stopAnimation' called. + * + * @param {Function} callback + */ + done: function (callback) { + doneCallback = callback; + return this; + }, + + /** + * Will stop exist animation firstly. + */ + start: function () { + var count = storage.length; + + for (var i = 0, len = storage.length; i < len; i++) { + var item = storage[i]; + item.el.animateTo(item.target, item.time, item.delay, item.easing, done); + } + + return this; + + function done() { + count--; + if (!count) { + storage.length = 0; + elExistsMap = {}; + doneCallback && doneCallback(); + } + } + } + }; +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var bind$1 = bind; +var Group$2 = Group; +var Rect$1 = Rect; +var each$8 = each$1; + +var DRAG_THRESHOLD = 3; +var PATH_LABEL_NOAMAL = ['label']; +var PATH_LABEL_EMPHASIS = ['emphasis', 'label']; +var PATH_UPPERLABEL_NORMAL = ['upperLabel']; +var PATH_UPPERLABEL_EMPHASIS = ['emphasis', 'upperLabel']; +var Z_BASE = 10; // Should bigger than every z. +var Z_BG = 1; +var Z_CONTENT = 2; + +var getItemStyleEmphasis = makeStyleMapper([ + ['fill', 'color'], + // `borderColor` and `borderWidth` has been occupied, + // so use `stroke` to indicate the stroke of the rect. + ['stroke', 'strokeColor'], + ['lineWidth', 'strokeWidth'], + ['shadowBlur'], + ['shadowOffsetX'], + ['shadowOffsetY'], + ['shadowColor'] +]); +var getItemStyleNormal = function (model) { + // Normal style props should include emphasis style props. + var itemStyle = getItemStyleEmphasis(model); + // Clear styles set by emphasis. + itemStyle.stroke = itemStyle.fill = itemStyle.lineWidth = null; + return itemStyle; +}; + +extendChartView({ + + type: 'treemap', + + /** + * @override + */ + init: function (o, api) { + + /** + * @private + * @type {module:zrender/container/Group} + */ + this._containerGroup; + + /** + * @private + * @type {Object.>} + */ + this._storage = createStorage(); + + /** + * @private + * @type {module:echarts/data/Tree} + */ + this._oldTree; + + /** + * @private + * @type {module:echarts/chart/treemap/Breadcrumb} + */ + this._breadcrumb; + + /** + * @private + * @type {module:echarts/component/helper/RoamController} + */ + this._controller; + + /** + * 'ready', 'animating' + * @private + */ + this._state = 'ready'; + }, + + /** + * @override + */ + render: function (seriesModel, ecModel, api, payload) { + + var models = ecModel.findComponents({ + mainType: 'series', subType: 'treemap', query: payload + }); + if (indexOf(models, seriesModel) < 0) { + return; + } + + this.seriesModel = seriesModel; + this.api = api; + this.ecModel = ecModel; + + var types = ['treemapZoomToNode', 'treemapRootToNode']; + var targetInfo = retrieveTargetInfo(payload, types, seriesModel); + var payloadType = payload && payload.type; + var layoutInfo = seriesModel.layoutInfo; + var isInit = !this._oldTree; + var thisStorage = this._storage; + + // Mark new root when action is treemapRootToNode. + var reRoot = (payloadType === 'treemapRootToNode' && targetInfo && thisStorage) + ? { + rootNodeGroup: thisStorage.nodeGroup[targetInfo.node.getRawIndex()], + direction: payload.direction + } + : null; + + var containerGroup = this._giveContainerGroup(layoutInfo); + + var renderResult = this._doRender(containerGroup, seriesModel, reRoot); + ( + !isInit && ( + !payloadType + || payloadType === 'treemapZoomToNode' + || payloadType === 'treemapRootToNode' + ) + ) + ? this._doAnimation(containerGroup, renderResult, seriesModel, reRoot) + : renderResult.renderFinally(); + + this._resetController(api); + + this._renderBreadcrumb(seriesModel, api, targetInfo); + }, + + /** + * @private + */ + _giveContainerGroup: function (layoutInfo) { + var containerGroup = this._containerGroup; + if (!containerGroup) { + // FIXME + // 加一层containerGroup是为了clip,但是现在clip功能并没有实现。 + containerGroup = this._containerGroup = new Group$2(); + this._initEvents(containerGroup); + this.group.add(containerGroup); + } + containerGroup.attr('position', [layoutInfo.x, layoutInfo.y]); + + return containerGroup; + }, + + /** + * @private + */ + _doRender: function (containerGroup, seriesModel, reRoot) { + var thisTree = seriesModel.getData().tree; + var oldTree = this._oldTree; + + // Clear last shape records. + var lastsForAnimation = createStorage(); + var thisStorage = createStorage(); + var oldStorage = this._storage; + var willInvisibleEls = []; + var doRenderNode = curry( + renderNode, seriesModel, + thisStorage, oldStorage, reRoot, + lastsForAnimation, willInvisibleEls + ); + + // Notice: when thisTree and oldTree are the same tree (see list.cloneShallow), + // the oldTree is actually losted, so we can not find all of the old graphic + // elements from tree. So we use this stragegy: make element storage, move + // from old storage to new storage, clear old storage. + + dualTravel( + thisTree.root ? [thisTree.root] : [], + (oldTree && oldTree.root) ? [oldTree.root] : [], + containerGroup, + thisTree === oldTree || !oldTree, + 0 + ); + + // Process all removing. + var willDeleteEls = clearStorage(oldStorage); + + this._oldTree = thisTree; + this._storage = thisStorage; + + return { + lastsForAnimation: lastsForAnimation, + willDeleteEls: willDeleteEls, + renderFinally: renderFinally + }; + + function dualTravel(thisViewChildren, oldViewChildren, parentGroup, sameTree, depth) { + // When 'render' is triggered by action, + // 'this' and 'old' may be the same tree, + // we use rawIndex in that case. + if (sameTree) { + oldViewChildren = thisViewChildren; + each$8(thisViewChildren, function (child, index) { + !child.isRemoved() && processNode(index, index); + }); + } + // Diff hierarchically (diff only in each subtree, but not whole). + // because, consistency of view is important. + else { + (new DataDiffer(oldViewChildren, thisViewChildren, getKey, getKey)) + .add(processNode) + .update(processNode) + .remove(curry(processNode, null)) + .execute(); + } + + function getKey(node) { + // Identify by name or raw index. + return node.getId(); + } + + function processNode(newIndex, oldIndex) { + var thisNode = newIndex != null ? thisViewChildren[newIndex] : null; + var oldNode = oldIndex != null ? oldViewChildren[oldIndex] : null; + + var group = doRenderNode(thisNode, oldNode, parentGroup, depth); + + group && dualTravel( + thisNode && thisNode.viewChildren || [], + oldNode && oldNode.viewChildren || [], + group, + sameTree, + depth + 1 + ); + } + } + + function clearStorage(storage) { + var willDeleteEls = createStorage(); + storage && each$8(storage, function (store, storageName) { + var delEls = willDeleteEls[storageName]; + each$8(store, function (el) { + el && (delEls.push(el), el.__tmWillDelete = 1); + }); + }); + return willDeleteEls; + } + + function renderFinally() { + each$8(willDeleteEls, function (els) { + each$8(els, function (el) { + el.parent && el.parent.remove(el); + }); + }); + each$8(willInvisibleEls, function (el) { + el.invisible = true; + // Setting invisible is for optimizing, so no need to set dirty, + // just mark as invisible. + el.dirty(); + }); + } + }, + + /** + * @private + */ + _doAnimation: function (containerGroup, renderResult, seriesModel, reRoot) { + if (!seriesModel.get('animation')) { + return; + } + + var duration = seriesModel.get('animationDurationUpdate'); + var easing = seriesModel.get('animationEasing'); + var animationWrap = createWrap(); + + // Make delete animations. + each$8(renderResult.willDeleteEls, function (store, storageName) { + each$8(store, function (el, rawIndex) { + if (el.invisible) { + return; + } + + var parent = el.parent; // Always has parent, and parent is nodeGroup. + var target; + + if (reRoot && reRoot.direction === 'drillDown') { + target = parent === reRoot.rootNodeGroup + // This is the content element of view root. + // Only `content` will enter this branch, because + // `background` and `nodeGroup` will not be deleted. + ? { + shape: { + x: 0, + y: 0, + width: parent.__tmNodeWidth, + height: parent.__tmNodeHeight + }, + style: { + opacity: 0 + } + } + // Others. + : {style: {opacity: 0}}; + } + else { + var targetX = 0; + var targetY = 0; + + if (!parent.__tmWillDelete) { + // Let node animate to right-bottom corner, cooperating with fadeout, + // which is appropriate for user understanding. + // Divided by 2 for reRoot rolling up effect. + targetX = parent.__tmNodeWidth / 2; + targetY = parent.__tmNodeHeight / 2; + } + + target = storageName === 'nodeGroup' + ? {position: [targetX, targetY], style: {opacity: 0}} + : { + shape: {x: targetX, y: targetY, width: 0, height: 0}, + style: {opacity: 0} + }; + } + + target && animationWrap.add(el, target, duration, easing); + }); + }); + + // Make other animations + each$8(this._storage, function (store, storageName) { + each$8(store, function (el, rawIndex) { + var last = renderResult.lastsForAnimation[storageName][rawIndex]; + var target = {}; + + if (!last) { + return; + } + + if (storageName === 'nodeGroup') { + if (last.old) { + target.position = el.position.slice(); + el.attr('position', last.old); + } + } + else { + if (last.old) { + target.shape = extend({}, el.shape); + el.setShape(last.old); + } + + if (last.fadein) { + el.setStyle('opacity', 0); + target.style = {opacity: 1}; + } + // When animation is stopped for succedent animation starting, + // el.style.opacity might not be 1 + else if (el.style.opacity !== 1) { + target.style = {opacity: 1}; + } + } + + animationWrap.add(el, target, duration, easing); + }); + }, this); + + this._state = 'animating'; + + animationWrap + .done(bind$1(function () { + this._state = 'ready'; + renderResult.renderFinally(); + }, this)) + .start(); + }, + + /** + * @private + */ + _resetController: function (api) { + var controller = this._controller; + + // Init controller. + if (!controller) { + controller = this._controller = new RoamController(api.getZr()); + controller.enable(this.seriesModel.get('roam')); + controller.on('pan', bind$1(this._onPan, this)); + controller.on('zoom', bind$1(this._onZoom, this)); + } + + var rect = new BoundingRect(0, 0, api.getWidth(), api.getHeight()); + controller.setPointerChecker(function (e, x, y) { + return rect.contain(x, y); + }); + }, + + /** + * @private + */ + _clearController: function () { + var controller = this._controller; + if (controller) { + controller.dispose(); + controller = null; + } + }, + + /** + * @private + */ + _onPan: function (e) { + if (this._state !== 'animating' + && (Math.abs(e.dx) > DRAG_THRESHOLD || Math.abs(e.dy) > DRAG_THRESHOLD) + ) { + // These param must not be cached. + var root = this.seriesModel.getData().tree.root; + + if (!root) { + return; + } + + var rootLayout = root.getLayout(); + + if (!rootLayout) { + return; + } + + this.api.dispatchAction({ + type: 'treemapMove', + from: this.uid, + seriesId: this.seriesModel.id, + rootRect: { + x: rootLayout.x + e.dx, y: rootLayout.y + e.dy, + width: rootLayout.width, height: rootLayout.height + } + }); + } + }, + + /** + * @private + */ + _onZoom: function (e) { + var mouseX = e.originX; + var mouseY = e.originY; + + if (this._state !== 'animating') { + // These param must not be cached. + var root = this.seriesModel.getData().tree.root; + + if (!root) { + return; + } + + var rootLayout = root.getLayout(); + + if (!rootLayout) { + return; + } + + var rect = new BoundingRect( + rootLayout.x, rootLayout.y, rootLayout.width, rootLayout.height + ); + var layoutInfo = this.seriesModel.layoutInfo; + + // Transform mouse coord from global to containerGroup. + mouseX -= layoutInfo.x; + mouseY -= layoutInfo.y; + + // Scale root bounding rect. + var m = create$1(); + translate(m, m, [-mouseX, -mouseY]); + scale$1(m, m, [e.scale, e.scale]); + translate(m, m, [mouseX, mouseY]); + + rect.applyTransform(m); + + this.api.dispatchAction({ + type: 'treemapRender', + from: this.uid, + seriesId: this.seriesModel.id, + rootRect: { + x: rect.x, y: rect.y, + width: rect.width, height: rect.height + } + }); + } + }, + + /** + * @private + */ + _initEvents: function (containerGroup) { + containerGroup.on('click', function (e) { + if (this._state !== 'ready') { + return; + } + + var nodeClick = this.seriesModel.get('nodeClick', true); + + if (!nodeClick) { + return; + } + + var targetInfo = this.findTarget(e.offsetX, e.offsetY); + + if (!targetInfo) { + return; + } + + var node = targetInfo.node; + if (node.getLayout().isLeafRoot) { + this._rootToNode(targetInfo); + } + else { + if (nodeClick === 'zoomToNode') { + this._zoomToNode(targetInfo); + } + else if (nodeClick === 'link') { + var itemModel = node.hostTree.data.getItemModel(node.dataIndex); + var link = itemModel.get('link', true); + var linkTarget = itemModel.get('target', true) || 'blank'; + link && window.open(link, linkTarget); + } + } + + }, this); + }, + + /** + * @private + */ + _renderBreadcrumb: function (seriesModel, api, targetInfo) { + if (!targetInfo) { + targetInfo = seriesModel.get('leafDepth', true) != null + ? {node: seriesModel.getViewRoot()} + // FIXME + // better way? + // Find breadcrumb tail on center of containerGroup. + : this.findTarget(api.getWidth() / 2, api.getHeight() / 2); + + if (!targetInfo) { + targetInfo = {node: seriesModel.getData().tree.root}; + } + } + + (this._breadcrumb || (this._breadcrumb = new Breadcrumb(this.group))) + .render(seriesModel, api, targetInfo.node, bind$1(onSelect, this)); + + function onSelect(node) { + if (this._state !== 'animating') { + aboveViewRoot(seriesModel.getViewRoot(), node) + ? this._rootToNode({node: node}) + : this._zoomToNode({node: node}); + } + } + }, + + /** + * @override + */ + remove: function () { + this._clearController(); + this._containerGroup && this._containerGroup.removeAll(); + this._storage = createStorage(); + this._state = 'ready'; + this._breadcrumb && this._breadcrumb.remove(); + }, + + dispose: function () { + this._clearController(); + }, + + /** + * @private + */ + _zoomToNode: function (targetInfo) { + this.api.dispatchAction({ + type: 'treemapZoomToNode', + from: this.uid, + seriesId: this.seriesModel.id, + targetNode: targetInfo.node + }); + }, + + /** + * @private + */ + _rootToNode: function (targetInfo) { + this.api.dispatchAction({ + type: 'treemapRootToNode', + from: this.uid, + seriesId: this.seriesModel.id, + targetNode: targetInfo.node + }); + }, + + /** + * @public + * @param {number} x Global coord x. + * @param {number} y Global coord y. + * @return {Object} info If not found, return undefined; + * @return {number} info.node Target node. + * @return {number} info.offsetX x refer to target node. + * @return {number} info.offsetY y refer to target node. + */ + findTarget: function (x, y) { + var targetInfo; + var viewRoot = this.seriesModel.getViewRoot(); + + viewRoot.eachNode({attr: 'viewChildren', order: 'preorder'}, function (node) { + var bgEl = this._storage.background[node.getRawIndex()]; + // If invisible, there might be no element. + if (bgEl) { + var point = bgEl.transformCoordToLocal(x, y); + var shape = bgEl.shape; + + // For performance consideration, dont use 'getBoundingRect'. + if (shape.x <= point[0] + && point[0] <= shape.x + shape.width + && shape.y <= point[1] + && point[1] <= shape.y + shape.height + ) { + targetInfo = {node: node, offsetX: point[0], offsetY: point[1]}; + } + else { + return false; // Suppress visit subtree. + } + } + }, this); + + return targetInfo; + } + +}); + +/** + * @inner + */ +function createStorage() { + return {nodeGroup: [], background: [], content: []}; +} + +/** + * @inner + * @return Return undefined means do not travel further. + */ +function renderNode( + seriesModel, thisStorage, oldStorage, reRoot, + lastsForAnimation, willInvisibleEls, + thisNode, oldNode, parentGroup, depth +) { + // Whether under viewRoot. + if (!thisNode) { + // Deleting nodes will be performed finally. This method just find + // element from old storage, or create new element, set them to new + // storage, and set styles. + return; + } + + // ------------------------------------------------------------------- + // Start of closure variables available in "Procedures in renderNode". + + var thisLayout = thisNode.getLayout(); + + if (!thisLayout || !thisLayout.isInView) { + return; + } + + var thisWidth = thisLayout.width; + var thisHeight = thisLayout.height; + var borderWidth = thisLayout.borderWidth; + var thisInvisible = thisLayout.invisible; + + var thisRawIndex = thisNode.getRawIndex(); + var oldRawIndex = oldNode && oldNode.getRawIndex(); + + var thisViewChildren = thisNode.viewChildren; + var upperHeight = thisLayout.upperHeight; + var isParent = thisViewChildren && thisViewChildren.length; + var itemStyleNormalModel = thisNode.getModel('itemStyle'); + var itemStyleEmphasisModel = thisNode.getModel('emphasis.itemStyle'); + + // End of closure ariables available in "Procedures in renderNode". + // ----------------------------------------------------------------- + + // Node group + var group = giveGraphic('nodeGroup', Group$2); + + if (!group) { + return; + } + + parentGroup.add(group); + // x,y are not set when el is above view root. + group.attr('position', [thisLayout.x || 0, thisLayout.y || 0]); + group.__tmNodeWidth = thisWidth; + group.__tmNodeHeight = thisHeight; + + if (thisLayout.isAboveViewRoot) { + return group; + } + + // Background + var bg = giveGraphic('background', Rect$1, depth, Z_BG); + bg && renderBackground(group, bg, isParent && thisLayout.upperHeight); + + // No children, render content. + if (!isParent) { + var content = giveGraphic('content', Rect$1, depth, Z_CONTENT); + content && renderContent(group, content); + } + + return group; + + // ---------------------------- + // | Procedures in renderNode | + // ---------------------------- + + function renderBackground(group, bg, useUpperLabel) { + // For tooltip. + bg.dataIndex = thisNode.dataIndex; + bg.seriesIndex = seriesModel.seriesIndex; + + bg.setShape({x: 0, y: 0, width: thisWidth, height: thisHeight}); + var visualBorderColor = thisNode.getVisual('borderColor', true); + var emphasisBorderColor = itemStyleEmphasisModel.get('borderColor'); + + updateStyle(bg, function () { + var normalStyle = getItemStyleNormal(itemStyleNormalModel); + normalStyle.fill = visualBorderColor; + var emphasisStyle = getItemStyleEmphasis(itemStyleEmphasisModel); + emphasisStyle.fill = emphasisBorderColor; + + if (useUpperLabel) { + var upperLabelWidth = thisWidth - 2 * borderWidth; + + prepareText( + normalStyle, emphasisStyle, visualBorderColor, upperLabelWidth, upperHeight, + {x: borderWidth, y: 0, width: upperLabelWidth, height: upperHeight} + ); + } + // For old bg. + else { + normalStyle.text = emphasisStyle.text = null; + } + + bg.setStyle(normalStyle); + setHoverStyle(bg, emphasisStyle); + }); + + group.add(bg); + } + + function renderContent(group, content) { + // For tooltip. + content.dataIndex = thisNode.dataIndex; + content.seriesIndex = seriesModel.seriesIndex; + + var contentWidth = Math.max(thisWidth - 2 * borderWidth, 0); + var contentHeight = Math.max(thisHeight - 2 * borderWidth, 0); + + content.culling = true; + content.setShape({ + x: borderWidth, + y: borderWidth, + width: contentWidth, + height: contentHeight + }); + + var visualColor = thisNode.getVisual('color', true); + updateStyle(content, function () { + var normalStyle = getItemStyleNormal(itemStyleNormalModel); + normalStyle.fill = visualColor; + var emphasisStyle = getItemStyleEmphasis(itemStyleEmphasisModel); + + prepareText(normalStyle, emphasisStyle, visualColor, contentWidth, contentHeight); + + content.setStyle(normalStyle); + setHoverStyle(content, emphasisStyle); + }); + + group.add(content); + } + + function updateStyle(element, cb) { + if (!thisInvisible) { + // If invisible, do not set visual, otherwise the element will + // change immediately before animation. We think it is OK to + // remain its origin color when moving out of the view window. + cb(); + + if (!element.__tmWillVisible) { + element.invisible = false; + } + } + else { + // Delay invisible setting utill animation finished, + // avoid element vanish suddenly before animation. + !element.invisible && willInvisibleEls.push(element); + } + } + + function prepareText(normalStyle, emphasisStyle, visualColor, width, height, upperLabelRect) { + var nodeModel = thisNode.getModel(); + var text = retrieve( + seriesModel.getFormattedLabel( + thisNode.dataIndex, 'normal', null, null, upperLabelRect ? 'upperLabel' : 'label' + ), + nodeModel.get('name') + ); + if (!upperLabelRect && thisLayout.isLeafRoot) { + var iconChar = seriesModel.get('drillDownIcon', true); + text = iconChar ? iconChar + ' ' + text : text; + } + + var normalLabelModel = nodeModel.getModel( + upperLabelRect ? PATH_UPPERLABEL_NORMAL : PATH_LABEL_NOAMAL + ); + var emphasisLabelModel = nodeModel.getModel( + upperLabelRect ? PATH_UPPERLABEL_EMPHASIS : PATH_LABEL_EMPHASIS + ); + + var isShow = normalLabelModel.getShallow('show'); + + setLabelStyle( + normalStyle, emphasisStyle, normalLabelModel, emphasisLabelModel, + { + defaultText: isShow ? text : null, + autoColor: visualColor, + isRectText: true + } + ); + + upperLabelRect && (normalStyle.textRect = clone(upperLabelRect)); + + normalStyle.truncate = (isShow && normalLabelModel.get('ellipsis')) + ? { + outerWidth: width, + outerHeight: height, + minChar: 2 + } + : null; + } + + function giveGraphic(storageName, Ctor, depth, z) { + var element = oldRawIndex != null && oldStorage[storageName][oldRawIndex]; + var lasts = lastsForAnimation[storageName]; + + if (element) { + // Remove from oldStorage + oldStorage[storageName][oldRawIndex] = null; + prepareAnimationWhenHasOld(lasts, element, storageName); + } + // If invisible and no old element, do not create new element (for optimizing). + else if (!thisInvisible) { + element = new Ctor({z: calculateZ(depth, z)}); + element.__tmDepth = depth; + element.__tmStorageName = storageName; + prepareAnimationWhenNoOld(lasts, element, storageName); + } + + // Set to thisStorage + return (thisStorage[storageName][thisRawIndex] = element); + } + + function prepareAnimationWhenHasOld(lasts, element, storageName) { + var lastCfg = lasts[thisRawIndex] = {}; + lastCfg.old = storageName === 'nodeGroup' + ? element.position.slice() + : extend({}, element.shape); + } + + // If a element is new, we need to find the animation start point carefully, + // otherwise it will looks strange when 'zoomToNode'. + function prepareAnimationWhenNoOld(lasts, element, storageName) { + var lastCfg = lasts[thisRawIndex] = {}; + var parentNode = thisNode.parentNode; + + if (parentNode && (!reRoot || reRoot.direction === 'drillDown')) { + var parentOldX = 0; + var parentOldY = 0; + + // New nodes appear from right-bottom corner in 'zoomToNode' animation. + // For convenience, get old bounding rect from background. + var parentOldBg = lastsForAnimation.background[parentNode.getRawIndex()]; + if (!reRoot && parentOldBg && parentOldBg.old) { + parentOldX = parentOldBg.old.width; + parentOldY = parentOldBg.old.height; + } + + // When no parent old shape found, its parent is new too, + // so we can just use {x:0, y:0}. + lastCfg.old = storageName === 'nodeGroup' + ? [0, parentOldY] + : {x: parentOldX, y: parentOldY, width: 0, height: 0}; + } + + // Fade in, user can be aware that these nodes are new. + lastCfg.fadein = storageName !== 'nodeGroup'; + } +} + +// We can not set all backgroud with the same z, Because the behaviour of +// drill down and roll up differ background creation sequence from tree +// hierarchy sequence, which cause that lowser background element overlap +// upper ones. So we calculate z based on depth. +// Moreover, we try to shrink down z interval to [0, 1] to avoid that +// treemap with large z overlaps other components. +function calculateZ(depth, zInLevel) { + var zb = depth * Z_BASE + zInLevel; + return (zb - 1) / zb; +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/** + * @file Treemap action + */ + +var noop$1 = function () {}; + +var actionTypes = [ + 'treemapZoomToNode', + 'treemapRender', + 'treemapMove' +]; + +for (var i$2 = 0; i$2 < actionTypes.length; i$2++) { + registerAction({type: actionTypes[i$2], update: 'updateView'}, noop$1); +} + +registerAction( + {type: 'treemapRootToNode', update: 'updateView'}, + function (payload, ecModel) { + + ecModel.eachComponent( + {mainType: 'series', subType: 'treemap', query: payload}, + handleRootToNode + ); + + function handleRootToNode(model, index) { + var types = ['treemapZoomToNode', 'treemapRootToNode']; + var targetInfo = retrieveTargetInfo(payload, types, model); + + if (targetInfo) { + var originViewRoot = model.getViewRoot(); + if (originViewRoot) { + payload.direction = aboveViewRoot(originViewRoot, targetInfo.node) + ? 'rollUp' : 'drillDown'; + } + model.resetViewRoot(targetInfo.node); + } + } + } +); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var each$9 = each$1; +var isObject$5 = isObject$1; + +var CATEGORY_DEFAULT_VISUAL_INDEX = -1; + +/** + * @param {Object} option + * @param {string} [option.type] See visualHandlers. + * @param {string} [option.mappingMethod] 'linear' or 'piecewise' or 'category' or 'fixed' + * @param {Array.=} [option.dataExtent] [minExtent, maxExtent], + * required when mappingMethod is 'linear' + * @param {Array.=} [option.pieceList] [ + * {value: someValue}, + * {interval: [min1, max1], visual: {...}}, + * {interval: [min2, max2]} + * ], + * required when mappingMethod is 'piecewise'. + * Visual for only each piece can be specified. + * @param {Array.=} [option.categories] ['cate1', 'cate2'] + * required when mappingMethod is 'category'. + * If no option.categories, categories is set + * as [0, 1, 2, ...]. + * @param {boolean} [option.loop=false] Whether loop mapping when mappingMethod is 'category'. + * @param {(Array|Object|*)} [option.visual] Visual data. + * when mappingMethod is 'category', + * visual data can be array or object + * (like: {cate1: '#222', none: '#fff'}) + * or primary types (which represents + * defualt category visual), otherwise visual + * can be array or primary (which will be + * normalized to array). + * + */ +var VisualMapping = function (option) { + var mappingMethod = option.mappingMethod; + var visualType = option.type; + + /** + * @readOnly + * @type {Object} + */ + var thisOption = this.option = clone(option); + + /** + * @readOnly + * @type {string} + */ + this.type = visualType; + + /** + * @readOnly + * @type {string} + */ + this.mappingMethod = mappingMethod; + + /** + * @private + * @type {Function} + */ + this._normalizeData = normalizers[mappingMethod]; + + var visualHandler = visualHandlers[visualType]; + + /** + * @public + * @type {Function} + */ + this.applyVisual = visualHandler.applyVisual; + + /** + * @public + * @type {Function} + */ + this.getColorMapper = visualHandler.getColorMapper; + + /** + * @private + * @type {Function} + */ + this._doMap = visualHandler._doMap[mappingMethod]; + + if (mappingMethod === 'piecewise') { + normalizeVisualRange(thisOption); + preprocessForPiecewise(thisOption); + } + else if (mappingMethod === 'category') { + thisOption.categories + ? preprocessForSpecifiedCategory(thisOption) + // categories is ordinal when thisOption.categories not specified, + // which need no more preprocess except normalize visual. + : normalizeVisualRange(thisOption, true); + } + else { // mappingMethod === 'linear' or 'fixed' + assert$1(mappingMethod !== 'linear' || thisOption.dataExtent); + normalizeVisualRange(thisOption); + } +}; + +VisualMapping.prototype = { + + constructor: VisualMapping, + + mapValueToVisual: function (value) { + var normalized = this._normalizeData(value); + return this._doMap(normalized, value); + }, + + getNormalizer: function () { + return bind(this._normalizeData, this); + } +}; + +var visualHandlers = VisualMapping.visualHandlers = { + + color: { + + applyVisual: makeApplyVisual('color'), + + /** + * Create a mapper function + * @return {Function} + */ + getColorMapper: function () { + var thisOption = this.option; + + return bind( + thisOption.mappingMethod === 'category' + ? function (value, isNormalized) { + !isNormalized && (value = this._normalizeData(value)); + return doMapCategory.call(this, value); + } + : function (value, isNormalized, out) { + // If output rgb array + // which will be much faster and useful in pixel manipulation + var returnRGBArray = !!out; + !isNormalized && (value = this._normalizeData(value)); + out = fastLerp(value, thisOption.parsedVisual, out); + return returnRGBArray ? out : stringify(out, 'rgba'); + }, + this + ); + }, + + _doMap: { + linear: function (normalized) { + return stringify( + fastLerp(normalized, this.option.parsedVisual), + 'rgba' + ); + }, + category: doMapCategory, + piecewise: function (normalized, value) { + var result = getSpecifiedVisual.call(this, value); + if (result == null) { + result = stringify( + fastLerp(normalized, this.option.parsedVisual), + 'rgba' + ); + } + return result; + }, + fixed: doMapFixed + } + }, + + colorHue: makePartialColorVisualHandler(function (color, value) { + return modifyHSL(color, value); + }), + + colorSaturation: makePartialColorVisualHandler(function (color, value) { + return modifyHSL(color, null, value); + }), + + colorLightness: makePartialColorVisualHandler(function (color, value) { + return modifyHSL(color, null, null, value); + }), + + colorAlpha: makePartialColorVisualHandler(function (color, value) { + return modifyAlpha(color, value); + }), + + opacity: { + applyVisual: makeApplyVisual('opacity'), + _doMap: makeDoMap([0, 1]) + }, + + liftZ: { + applyVisual: makeApplyVisual('liftZ'), + _doMap: { + linear: doMapFixed, + category: doMapFixed, + piecewise: doMapFixed, + fixed: doMapFixed + } + }, + + symbol: { + applyVisual: function (value, getter, setter) { + var symbolCfg = this.mapValueToVisual(value); + if (isString(symbolCfg)) { + setter('symbol', symbolCfg); + } + else if (isObject$5(symbolCfg)) { + for (var name in symbolCfg) { + if (symbolCfg.hasOwnProperty(name)) { + setter(name, symbolCfg[name]); + } + } + } + }, + _doMap: { + linear: doMapToArray, + category: doMapCategory, + piecewise: function (normalized, value) { + var result = getSpecifiedVisual.call(this, value); + if (result == null) { + result = doMapToArray.call(this, normalized); + } + return result; + }, + fixed: doMapFixed + } + }, + + symbolSize: { + applyVisual: makeApplyVisual('symbolSize'), + _doMap: makeDoMap([0, 1]) + } +}; + + +function preprocessForPiecewise(thisOption) { + var pieceList = thisOption.pieceList; + thisOption.hasSpecialVisual = false; + + each$1(pieceList, function (piece, index) { + piece.originIndex = index; + // piece.visual is "result visual value" but not + // a visual range, so it does not need to be normalized. + if (piece.visual != null) { + thisOption.hasSpecialVisual = true; + } + }); +} + +function preprocessForSpecifiedCategory(thisOption) { + // Hash categories. + var categories = thisOption.categories; + var visual = thisOption.visual; + + var categoryMap = thisOption.categoryMap = {}; + each$9(categories, function (cate, index) { + categoryMap[cate] = index; + }); + + // Process visual map input. + if (!isArray(visual)) { + var visualArr = []; + + if (isObject$1(visual)) { + each$9(visual, function (v, cate) { + var index = categoryMap[cate]; + visualArr[index != null ? index : CATEGORY_DEFAULT_VISUAL_INDEX] = v; + }); + } + else { // Is primary type, represents default visual. + visualArr[CATEGORY_DEFAULT_VISUAL_INDEX] = visual; + } + + visual = setVisualToOption(thisOption, visualArr); + } + + // Remove categories that has no visual, + // then we can mapping them to CATEGORY_DEFAULT_VISUAL_INDEX. + for (var i = categories.length - 1; i >= 0; i--) { + if (visual[i] == null) { + delete categoryMap[categories[i]]; + categories.pop(); + } + } +} + +function normalizeVisualRange(thisOption, isCategory) { + var visual = thisOption.visual; + var visualArr = []; + + if (isObject$1(visual)) { + each$9(visual, function (v) { + visualArr.push(v); + }); + } + else if (visual != null) { + visualArr.push(visual); + } + + var doNotNeedPair = {color: 1, symbol: 1}; + + if (!isCategory + && visualArr.length === 1 + && !doNotNeedPair.hasOwnProperty(thisOption.type) + ) { + // Do not care visualArr.length === 0, which is illegal. + visualArr[1] = visualArr[0]; + } + + setVisualToOption(thisOption, visualArr); +} + +function makePartialColorVisualHandler(applyValue) { + return { + applyVisual: function (value, getter, setter) { + value = this.mapValueToVisual(value); + // Must not be array value + setter('color', applyValue(getter('color'), value)); + }, + _doMap: makeDoMap([0, 1]) + }; +} + +function doMapToArray(normalized) { + var visual = this.option.visual; + return visual[ + Math.round(linearMap(normalized, [0, 1], [0, visual.length - 1], true)) + ] || {}; +} + +function makeApplyVisual(visualType) { + return function (value, getter, setter) { + setter(visualType, this.mapValueToVisual(value)); + }; +} + +function doMapCategory(normalized) { + var visual = this.option.visual; + return visual[ + (this.option.loop && normalized !== CATEGORY_DEFAULT_VISUAL_INDEX) + ? normalized % visual.length + : normalized + ]; +} + +function doMapFixed() { + return this.option.visual[0]; +} + +function makeDoMap(sourceExtent) { + return { + linear: function (normalized) { + return linearMap(normalized, sourceExtent, this.option.visual, true); + }, + category: doMapCategory, + piecewise: function (normalized, value) { + var result = getSpecifiedVisual.call(this, value); + if (result == null) { + result = linearMap(normalized, sourceExtent, this.option.visual, true); + } + return result; + }, + fixed: doMapFixed + }; +} + +function getSpecifiedVisual(value) { + var thisOption = this.option; + var pieceList = thisOption.pieceList; + if (thisOption.hasSpecialVisual) { + var pieceIndex = VisualMapping.findPieceIndex(value, pieceList); + var piece = pieceList[pieceIndex]; + if (piece && piece.visual) { + return piece.visual[this.type]; + } + } +} + +function setVisualToOption(thisOption, visualArr) { + thisOption.visual = visualArr; + if (thisOption.type === 'color') { + thisOption.parsedVisual = map(visualArr, function (item) { + return parse(item); + }); + } + return visualArr; +} + + +/** + * Normalizers by mapping methods. + */ +var normalizers = { + + linear: function (value) { + return linearMap(value, this.option.dataExtent, [0, 1], true); + }, + + piecewise: function (value) { + var pieceList = this.option.pieceList; + var pieceIndex = VisualMapping.findPieceIndex(value, pieceList, true); + if (pieceIndex != null) { + return linearMap(pieceIndex, [0, pieceList.length - 1], [0, 1], true); + } + }, + + category: function (value) { + var index = this.option.categories + ? this.option.categoryMap[value] + : value; // ordinal + return index == null ? CATEGORY_DEFAULT_VISUAL_INDEX : index; + }, + + fixed: noop +}; + + + +/** + * List available visual types. + * + * @public + * @return {Array.} + */ +VisualMapping.listVisualTypes = function () { + var visualTypes = []; + each$1(visualHandlers, function (handler, key) { + visualTypes.push(key); + }); + return visualTypes; +}; + +/** + * @public + */ +VisualMapping.addVisualHandler = function (name, handler) { + visualHandlers[name] = handler; +}; + +/** + * @public + */ +VisualMapping.isValidType = function (visualType) { + return visualHandlers.hasOwnProperty(visualType); +}; + +/** + * Convinent method. + * Visual can be Object or Array or primary type. + * + * @public + */ +VisualMapping.eachVisual = function (visual, callback, context) { + if (isObject$1(visual)) { + each$1(visual, callback, context); + } + else { + callback.call(context, visual); + } +}; + +VisualMapping.mapVisual = function (visual, callback, context) { + var isPrimary; + var newVisual = isArray(visual) + ? [] + : isObject$1(visual) + ? {} + : (isPrimary = true, null); + + VisualMapping.eachVisual(visual, function (v, key) { + var newVal = callback.call(context, v, key); + isPrimary ? (newVisual = newVal) : (newVisual[key] = newVal); + }); + return newVisual; +}; + +/** + * @public + * @param {Object} obj + * @return {Object} new object containers visual values. + * If no visuals, return null. + */ +VisualMapping.retrieveVisuals = function (obj) { + var ret = {}; + var hasVisual; + + obj && each$9(visualHandlers, function (h, visualType) { + if (obj.hasOwnProperty(visualType)) { + ret[visualType] = obj[visualType]; + hasVisual = true; + } + }); + + return hasVisual ? ret : null; +}; + +/** + * Give order to visual types, considering colorSaturation, colorAlpha depends on color. + * + * @public + * @param {(Object|Array)} visualTypes If Object, like: {color: ..., colorSaturation: ...} + * IF Array, like: ['color', 'symbol', 'colorSaturation'] + * @return {Array.} Sorted visual types. + */ +VisualMapping.prepareVisualTypes = function (visualTypes) { + if (isObject$5(visualTypes)) { + var types = []; + each$9(visualTypes, function (item, type) { + types.push(type); + }); + visualTypes = types; + } + else if (isArray(visualTypes)) { + visualTypes = visualTypes.slice(); + } + else { + return []; + } + + visualTypes.sort(function (type1, type2) { + // color should be front of colorSaturation, colorAlpha, ... + // symbol and symbolSize do not matter. + return (type2 === 'color' && type1 !== 'color' && type1.indexOf('color') === 0) + ? 1 : -1; + }); + + return visualTypes; +}; + +/** + * 'color', 'colorSaturation', 'colorAlpha', ... are depends on 'color'. + * Other visuals are only depends on themself. + * + * @public + * @param {string} visualType1 + * @param {string} visualType2 + * @return {boolean} + */ +VisualMapping.dependsOn = function (visualType1, visualType2) { + return visualType2 === 'color' + ? !!(visualType1 && visualType1.indexOf(visualType2) === 0) + : visualType1 === visualType2; +}; + +/** + * @param {number} value + * @param {Array.} pieceList [{value: ..., interval: [min, max]}, ...] + * Always from small to big. + * @param {boolean} [findClosestWhenOutside=false] + * @return {number} index + */ +VisualMapping.findPieceIndex = function (value, pieceList, findClosestWhenOutside) { + var possibleI; + var abs = Infinity; + + // value has the higher priority. + for (var i = 0, len = pieceList.length; i < len; i++) { + var pieceValue = pieceList[i].value; + if (pieceValue != null) { + if (pieceValue === value + // FIXME + // It is supposed to compare value according to value type of dimension, + // but currently value type can exactly be string or number. + // Compromise for numeric-like string (like '12'), especially + // in the case that visualMap.categories is ['22', '33']. + || (typeof pieceValue === 'string' && pieceValue === value + '') + ) { + return i; + } + findClosestWhenOutside && updatePossible(pieceValue, i); + } + } + + for (var i = 0, len = pieceList.length; i < len; i++) { + var piece = pieceList[i]; + var interval = piece.interval; + var close = piece.close; + + if (interval) { + if (interval[0] === -Infinity) { + if (littleThan(close[1], value, interval[1])) { + return i; + } + } + else if (interval[1] === Infinity) { + if (littleThan(close[0], interval[0], value)) { + return i; + } + } + else if ( + littleThan(close[0], interval[0], value) + && littleThan(close[1], value, interval[1]) + ) { + return i; + } + findClosestWhenOutside && updatePossible(interval[0], i); + findClosestWhenOutside && updatePossible(interval[1], i); + } + } + + if (findClosestWhenOutside) { + return value === Infinity + ? pieceList.length - 1 + : value === -Infinity + ? 0 + : possibleI; + } + + function updatePossible(val, index) { + var newAbs = Math.abs(val - value); + if (newAbs < abs) { + abs = newAbs; + possibleI = index; + } + } + +}; + +function littleThan(close, a, b) { + return close ? a <= b : a < b; +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var isArray$2 = isArray; + +var ITEM_STYLE_NORMAL = 'itemStyle'; + +var treemapVisual = { + seriesType: 'treemap', + reset: function (seriesModel, ecModel, api, payload) { + var tree = seriesModel.getData().tree; + var root = tree.root; + var seriesItemStyleModel = seriesModel.getModel(ITEM_STYLE_NORMAL); + + if (root.isRemoved()) { + return; + } + + var levelItemStyles = map(tree.levelModels, function (levelModel) { + return levelModel ? levelModel.get(ITEM_STYLE_NORMAL) : null; + }); + + travelTree( + root, // Visual should calculate from tree root but not view root. + {}, + levelItemStyles, + seriesItemStyleModel, + seriesModel.getViewRoot().getAncestors(), + seriesModel + ); + } +}; + +function travelTree( + node, designatedVisual, levelItemStyles, seriesItemStyleModel, + viewRootAncestors, seriesModel +) { + var nodeModel = node.getModel(); + var nodeLayout = node.getLayout(); + + // Optimize + if (!nodeLayout || nodeLayout.invisible || !nodeLayout.isInView) { + return; + } + + var nodeItemStyleModel = node.getModel(ITEM_STYLE_NORMAL); + var levelItemStyle = levelItemStyles[node.depth]; + var visuals = buildVisuals( + nodeItemStyleModel, designatedVisual, levelItemStyle, seriesItemStyleModel + ); + + // calculate border color + var borderColor = nodeItemStyleModel.get('borderColor'); + var borderColorSaturation = nodeItemStyleModel.get('borderColorSaturation'); + var thisNodeColor; + if (borderColorSaturation != null) { + // For performance, do not always execute 'calculateColor'. + thisNodeColor = calculateColor(visuals, node); + borderColor = calculateBorderColor(borderColorSaturation, thisNodeColor); + } + node.setVisual('borderColor', borderColor); + + var viewChildren = node.viewChildren; + if (!viewChildren || !viewChildren.length) { + thisNodeColor = calculateColor(visuals, node); + // Apply visual to this node. + node.setVisual('color', thisNodeColor); + } + else { + var mapping = buildVisualMapping( + node, nodeModel, nodeLayout, nodeItemStyleModel, visuals, viewChildren + ); + + // Designate visual to children. + each$1(viewChildren, function (child, index) { + // If higher than viewRoot, only ancestors of viewRoot is needed to visit. + if (child.depth >= viewRootAncestors.length + || child === viewRootAncestors[child.depth] + ) { + var childVisual = mapVisual$1( + nodeModel, visuals, child, index, mapping, seriesModel + ); + travelTree( + child, childVisual, levelItemStyles, seriesItemStyleModel, + viewRootAncestors, seriesModel + ); + } + }); + } +} + +function buildVisuals( + nodeItemStyleModel, designatedVisual, levelItemStyle, seriesItemStyleModel +) { + var visuals = extend({}, designatedVisual); + + each$1(['color', 'colorAlpha', 'colorSaturation'], function (visualName) { + // Priority: thisNode > thisLevel > parentNodeDesignated > seriesModel + var val = nodeItemStyleModel.get(visualName, true); // Ignore parent + val == null && levelItemStyle && (val = levelItemStyle[visualName]); + val == null && (val = designatedVisual[visualName]); + val == null && (val = seriesItemStyleModel.get(visualName)); + + val != null && (visuals[visualName] = val); + }); + + return visuals; +} + +function calculateColor(visuals) { + var color = getValueVisualDefine(visuals, 'color'); + + if (color) { + var colorAlpha = getValueVisualDefine(visuals, 'colorAlpha'); + var colorSaturation = getValueVisualDefine(visuals, 'colorSaturation'); + if (colorSaturation) { + color = modifyHSL(color, null, null, colorSaturation); + } + if (colorAlpha) { + color = modifyAlpha(color, colorAlpha); + } + + return color; + } +} + +function calculateBorderColor(borderColorSaturation, thisNodeColor) { + return thisNodeColor != null + ? modifyHSL(thisNodeColor, null, null, borderColorSaturation) + : null; +} + +function getValueVisualDefine(visuals, name) { + var value = visuals[name]; + if (value != null && value !== 'none') { + return value; + } +} + +function buildVisualMapping( + node, nodeModel, nodeLayout, nodeItemStyleModel, visuals, viewChildren +) { + if (!viewChildren || !viewChildren.length) { + return; + } + + var rangeVisual = getRangeVisual(nodeModel, 'color') + || ( + visuals.color != null + && visuals.color !== 'none' + && ( + getRangeVisual(nodeModel, 'colorAlpha') + || getRangeVisual(nodeModel, 'colorSaturation') + ) + ); + + if (!rangeVisual) { + return; + } + + var visualMin = nodeModel.get('visualMin'); + var visualMax = nodeModel.get('visualMax'); + var dataExtent = nodeLayout.dataExtent.slice(); + visualMin != null && visualMin < dataExtent[0] && (dataExtent[0] = visualMin); + visualMax != null && visualMax > dataExtent[1] && (dataExtent[1] = visualMax); + + var colorMappingBy = nodeModel.get('colorMappingBy'); + var opt = { + type: rangeVisual.name, + dataExtent: dataExtent, + visual: rangeVisual.range + }; + if (opt.type === 'color' + && (colorMappingBy === 'index' || colorMappingBy === 'id') + ) { + opt.mappingMethod = 'category'; + opt.loop = true; + // categories is ordinal, so do not set opt.categories. + } + else { + opt.mappingMethod = 'linear'; + } + + var mapping = new VisualMapping(opt); + mapping.__drColorMappingBy = colorMappingBy; + + return mapping; +} + +// Notice: If we dont have the attribute 'colorRange', but only use +// attribute 'color' to represent both concepts of 'colorRange' and 'color', +// (It means 'colorRange' when 'color' is Array, means 'color' when not array), +// this problem will be encountered: +// If a level-1 node dont have children, and its siblings has children, +// and colorRange is set on level-1, then the node can not be colored. +// So we separate 'colorRange' and 'color' to different attributes. +function getRangeVisual(nodeModel, name) { + // 'colorRange', 'colorARange', 'colorSRange'. + // If not exsits on this node, fetch from levels and series. + var range = nodeModel.get(name); + return (isArray$2(range) && range.length) ? {name: name, range: range} : null; +} + +function mapVisual$1(nodeModel, visuals, child, index, mapping, seriesModel) { + var childVisuals = extend({}, visuals); + + if (mapping) { + var mappingType = mapping.type; + var colorMappingBy = mappingType === 'color' && mapping.__drColorMappingBy; + var value = colorMappingBy === 'index' + ? index + : colorMappingBy === 'id' + ? seriesModel.mapIdToIndex(child.getId()) + : child.getValue(nodeModel.get('visualDimension')); + + childVisuals[mappingType] = mapping.mapValueToVisual(value); + } + + return childVisuals; +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/* +* A third-party license is embeded for some of the code in this file: +* The treemap layout implementation was originally copied from +* "d3.js" with some modifications made for this project. +* (See more details in the comment of the method "squarify" below.) +* The use of the source code of this file is also subject to the terms +* and consitions of the license of "d3.js" (BSD-3Clause, see +* ). +*/ + +var mathMax$4 = Math.max; +var mathMin$4 = Math.min; +var retrieveValue = retrieve; +var each$10 = each$1; + +var PATH_BORDER_WIDTH = ['itemStyle', 'borderWidth']; +var PATH_GAP_WIDTH = ['itemStyle', 'gapWidth']; +var PATH_UPPER_LABEL_SHOW = ['upperLabel', 'show']; +var PATH_UPPER_LABEL_HEIGHT = ['upperLabel', 'height']; + +/** + * @public + */ +var treemapLayout = { + seriesType: 'treemap', + reset: function (seriesModel, ecModel, api, payload) { + // Layout result in each node: + // {x, y, width, height, area, borderWidth} + var ecWidth = api.getWidth(); + var ecHeight = api.getHeight(); + var seriesOption = seriesModel.option; + + var layoutInfo = getLayoutRect( + seriesModel.getBoxLayoutParams(), + { + width: api.getWidth(), + height: api.getHeight() + } + ); + + var size = seriesOption.size || []; // Compatible with ec2. + var containerWidth = parsePercent$1( + retrieveValue(layoutInfo.width, size[0]), + ecWidth + ); + var containerHeight = parsePercent$1( + retrieveValue(layoutInfo.height, size[1]), + ecHeight + ); + + // Fetch payload info. + var payloadType = payload && payload.type; + var types = ['treemapZoomToNode', 'treemapRootToNode']; + var targetInfo = retrieveTargetInfo(payload, types, seriesModel); + var rootRect = (payloadType === 'treemapRender' || payloadType === 'treemapMove') + ? payload.rootRect : null; + var viewRoot = seriesModel.getViewRoot(); + var viewAbovePath = getPathToRoot(viewRoot); + + if (payloadType !== 'treemapMove') { + var rootSize = payloadType === 'treemapZoomToNode' + ? estimateRootSize( + seriesModel, targetInfo, viewRoot, containerWidth, containerHeight + ) + : rootRect + ? [rootRect.width, rootRect.height] + : [containerWidth, containerHeight]; + + var sort = seriesOption.sort; + if (sort && sort !== 'asc' && sort !== 'desc') { + sort = 'desc'; + } + var options = { + squareRatio: seriesOption.squareRatio, + sort: sort, + leafDepth: seriesOption.leafDepth + }; + + // layout should be cleared because using updateView but not update. + viewRoot.hostTree.clearLayouts(); + + // TODO + // optimize: if out of view clip, do not layout. + // But take care that if do not render node out of view clip, + // how to calculate start po + + var viewRootLayout = { + x: 0, y: 0, + width: rootSize[0], height: rootSize[1], + area: rootSize[0] * rootSize[1] + }; + viewRoot.setLayout(viewRootLayout); + + squarify(viewRoot, options, false, 0); + // Supplement layout. + var viewRootLayout = viewRoot.getLayout(); + each$10(viewAbovePath, function (node, index) { + var childValue = (viewAbovePath[index + 1] || viewRoot).getValue(); + node.setLayout(extend( + {dataExtent: [childValue, childValue], borderWidth: 0, upperHeight: 0}, + viewRootLayout + )); + }); + } + + var treeRoot = seriesModel.getData().tree.root; + + treeRoot.setLayout( + calculateRootPosition(layoutInfo, rootRect, targetInfo), + true + ); + + seriesModel.setLayoutInfo(layoutInfo); + + // FIXME + // 现在没有clip功能,暂时取ec高宽。 + prunning( + treeRoot, + // Transform to base element coordinate system. + new BoundingRect(-layoutInfo.x, -layoutInfo.y, ecWidth, ecHeight), + viewAbovePath, + viewRoot, + 0 + ); + } +}; + +/** + * Layout treemap with squarify algorithm. + * The original presentation of this algorithm + * was made by Mark Bruls, Kees Huizing, and Jarke J. van Wijk + * . + * The implementation of this algorithm was originally copied from "d3.js" + * + * with some modifications made for this program. + * See the license statement at the head of this file. + * + * @protected + * @param {module:echarts/data/Tree~TreeNode} node + * @param {Object} options + * @param {string} options.sort 'asc' or 'desc' + * @param {number} options.squareRatio + * @param {boolean} hideChildren + * @param {number} depth + */ +function squarify(node, options, hideChildren, depth) { + var width; + var height; + + if (node.isRemoved()) { + return; + } + + var thisLayout = node.getLayout(); + width = thisLayout.width; + height = thisLayout.height; + + // Considering border and gap + var nodeModel = node.getModel(); + var borderWidth = nodeModel.get(PATH_BORDER_WIDTH); + var halfGapWidth = nodeModel.get(PATH_GAP_WIDTH) / 2; + var upperLabelHeight = getUpperLabelHeight(nodeModel); + var upperHeight = Math.max(borderWidth, upperLabelHeight); + var layoutOffset = borderWidth - halfGapWidth; + var layoutOffsetUpper = upperHeight - halfGapWidth; + var nodeModel = node.getModel(); + + node.setLayout({ + borderWidth: borderWidth, + upperHeight: upperHeight, + upperLabelHeight: upperLabelHeight + }, true); + + width = mathMax$4(width - 2 * layoutOffset, 0); + height = mathMax$4(height - layoutOffset - layoutOffsetUpper, 0); + + var totalArea = width * height; + var viewChildren = initChildren( + node, nodeModel, totalArea, options, hideChildren, depth + ); + + if (!viewChildren.length) { + return; + } + + var rect = {x: layoutOffset, y: layoutOffsetUpper, width: width, height: height}; + var rowFixedLength = mathMin$4(width, height); + var best = Infinity; // the best row score so far + var row = []; + row.area = 0; + + for (var i = 0, len = viewChildren.length; i < len;) { + var child = viewChildren[i]; + + row.push(child); + row.area += child.getLayout().area; + var score = worst(row, rowFixedLength, options.squareRatio); + + // continue with this orientation + if (score <= best) { + i++; + best = score; + } + // abort, and try a different orientation + else { + row.area -= row.pop().getLayout().area; + position(row, rowFixedLength, rect, halfGapWidth, false); + rowFixedLength = mathMin$4(rect.width, rect.height); + row.length = row.area = 0; + best = Infinity; + } + } + + if (row.length) { + position(row, rowFixedLength, rect, halfGapWidth, true); + } + + if (!hideChildren) { + var childrenVisibleMin = nodeModel.get('childrenVisibleMin'); + if (childrenVisibleMin != null && totalArea < childrenVisibleMin) { + hideChildren = true; + } + } + + for (var i = 0, len = viewChildren.length; i < len; i++) { + squarify(viewChildren[i], options, hideChildren, depth + 1); + } +} + +/** + * Set area to each child, and calculate data extent for visual coding. + */ +function initChildren(node, nodeModel, totalArea, options, hideChildren, depth) { + var viewChildren = node.children || []; + var orderBy = options.sort; + orderBy !== 'asc' && orderBy !== 'desc' && (orderBy = null); + + var overLeafDepth = options.leafDepth != null && options.leafDepth <= depth; + + // leafDepth has higher priority. + if (hideChildren && !overLeafDepth) { + return (node.viewChildren = []); + } + + // Sort children, order by desc. + viewChildren = filter(viewChildren, function (child) { + return !child.isRemoved(); + }); + + sort$1(viewChildren, orderBy); + + var info = statistic(nodeModel, viewChildren, orderBy); + + if (info.sum === 0) { + return (node.viewChildren = []); + } + + info.sum = filterByThreshold(nodeModel, totalArea, info.sum, orderBy, viewChildren); + + if (info.sum === 0) { + return (node.viewChildren = []); + } + + // Set area to each child. + for (var i = 0, len = viewChildren.length; i < len; i++) { + var area = viewChildren[i].getValue() / info.sum * totalArea; + // Do not use setLayout({...}, true), because it is needed to clear last layout. + viewChildren[i].setLayout({area: area}); + } + + if (overLeafDepth) { + viewChildren.length && node.setLayout({isLeafRoot: true}, true); + viewChildren.length = 0; + } + + node.viewChildren = viewChildren; + node.setLayout({dataExtent: info.dataExtent}, true); + + return viewChildren; +} + +/** + * Consider 'visibleMin'. Modify viewChildren and get new sum. + */ +function filterByThreshold(nodeModel, totalArea, sum, orderBy, orderedChildren) { + + // visibleMin is not supported yet when no option.sort. + if (!orderBy) { + return sum; + } + + var visibleMin = nodeModel.get('visibleMin'); + var len = orderedChildren.length; + var deletePoint = len; + + // Always travel from little value to big value. + for (var i = len - 1; i >= 0; i--) { + var value = orderedChildren[ + orderBy === 'asc' ? len - i - 1 : i + ].getValue(); + + if (value / sum * totalArea < visibleMin) { + deletePoint = i; + sum -= value; + } + } + + orderBy === 'asc' + ? orderedChildren.splice(0, len - deletePoint) + : orderedChildren.splice(deletePoint, len - deletePoint); + + return sum; +} + +/** + * Sort + */ +function sort$1(viewChildren, orderBy) { + if (orderBy) { + viewChildren.sort(function (a, b) { + var diff = orderBy === 'asc' + ? a.getValue() - b.getValue() : b.getValue() - a.getValue(); + return diff === 0 + ? (orderBy === 'asc' + ? a.dataIndex - b.dataIndex : b.dataIndex - a.dataIndex + ) + : diff; + }); + } + return viewChildren; +} + +/** + * Statistic + */ +function statistic(nodeModel, children, orderBy) { + // Calculate sum. + var sum = 0; + for (var i = 0, len = children.length; i < len; i++) { + sum += children[i].getValue(); + } + + // Statistic data extent for latter visual coding. + // Notice: data extent should be calculate based on raw children + // but not filtered view children, otherwise visual mapping will not + // be stable when zoom (where children is filtered by visibleMin). + + var dimension = nodeModel.get('visualDimension'); + var dataExtent; + + // The same as area dimension. + if (!children || !children.length) { + dataExtent = [NaN, NaN]; + } + else if (dimension === 'value' && orderBy) { + dataExtent = [ + children[children.length - 1].getValue(), + children[0].getValue() + ]; + orderBy === 'asc' && dataExtent.reverse(); + } + // Other dimension. + else { + var dataExtent = [Infinity, -Infinity]; + each$10(children, function (child) { + var value = child.getValue(dimension); + value < dataExtent[0] && (dataExtent[0] = value); + value > dataExtent[1] && (dataExtent[1] = value); + }); + } + + return {sum: sum, dataExtent: dataExtent}; +} + +/** + * Computes the score for the specified row, + * as the worst aspect ratio. + */ +function worst(row, rowFixedLength, ratio) { + var areaMax = 0; + var areaMin = Infinity; + + for (var i = 0, area, len = row.length; i < len; i++) { + area = row[i].getLayout().area; + if (area) { + area < areaMin && (areaMin = area); + area > areaMax && (areaMax = area); + } + } + + var squareArea = row.area * row.area; + var f = rowFixedLength * rowFixedLength * ratio; + + return squareArea + ? mathMax$4( + (f * areaMax) / squareArea, + squareArea / (f * areaMin) + ) + : Infinity; +} + +/** + * Positions the specified row of nodes. Modifies `rect`. + */ +function position(row, rowFixedLength, rect, halfGapWidth, flush) { + // When rowFixedLength === rect.width, + // it is horizontal subdivision, + // rowFixedLength is the width of the subdivision, + // rowOtherLength is the height of the subdivision, + // and nodes will be positioned from left to right. + + // wh[idx0WhenH] means: when horizontal, + // wh[idx0WhenH] => wh[0] => 'width'. + // xy[idx1WhenH] => xy[1] => 'y'. + var idx0WhenH = rowFixedLength === rect.width ? 0 : 1; + var idx1WhenH = 1 - idx0WhenH; + var xy = ['x', 'y']; + var wh = ['width', 'height']; + + var last = rect[xy[idx0WhenH]]; + var rowOtherLength = rowFixedLength + ? row.area / rowFixedLength : 0; + + if (flush || rowOtherLength > rect[wh[idx1WhenH]]) { + rowOtherLength = rect[wh[idx1WhenH]]; // over+underflow + } + for (var i = 0, rowLen = row.length; i < rowLen; i++) { + var node = row[i]; + var nodeLayout = {}; + var step = rowOtherLength + ? node.getLayout().area / rowOtherLength : 0; + + var wh1 = nodeLayout[wh[idx1WhenH]] = mathMax$4(rowOtherLength - 2 * halfGapWidth, 0); + + // We use Math.max/min to avoid negative width/height when considering gap width. + var remain = rect[xy[idx0WhenH]] + rect[wh[idx0WhenH]] - last; + var modWH = (i === rowLen - 1 || remain < step) ? remain : step; + var wh0 = nodeLayout[wh[idx0WhenH]] = mathMax$4(modWH - 2 * halfGapWidth, 0); + + nodeLayout[xy[idx1WhenH]] = rect[xy[idx1WhenH]] + mathMin$4(halfGapWidth, wh1 / 2); + nodeLayout[xy[idx0WhenH]] = last + mathMin$4(halfGapWidth, wh0 / 2); + + last += modWH; + node.setLayout(nodeLayout, true); + } + + rect[xy[idx1WhenH]] += rowOtherLength; + rect[wh[idx1WhenH]] -= rowOtherLength; +} + +// Return [containerWidth, containerHeight] as defualt. +function estimateRootSize(seriesModel, targetInfo, viewRoot, containerWidth, containerHeight) { + // If targetInfo.node exists, we zoom to the node, + // so estimate whold width and heigth by target node. + var currNode = (targetInfo || {}).node; + var defaultSize = [containerWidth, containerHeight]; + + if (!currNode || currNode === viewRoot) { + return defaultSize; + } + + var parent; + var viewArea = containerWidth * containerHeight; + var area = viewArea * seriesModel.option.zoomToNodeRatio; + + while (parent = currNode.parentNode) { // jshint ignore:line + var sum = 0; + var siblings = parent.children; + + for (var i = 0, len = siblings.length; i < len; i++) { + sum += siblings[i].getValue(); + } + var currNodeValue = currNode.getValue(); + if (currNodeValue === 0) { + return defaultSize; + } + area *= sum / currNodeValue; + + // Considering border, suppose aspect ratio is 1. + var parentModel = parent.getModel(); + var borderWidth = parentModel.get(PATH_BORDER_WIDTH); + var upperHeight = Math.max(borderWidth, getUpperLabelHeight(parentModel, borderWidth)); + area += 4 * borderWidth * borderWidth + + (3 * borderWidth + upperHeight) * Math.pow(area, 0.5); + + area > MAX_SAFE_INTEGER && (area = MAX_SAFE_INTEGER); + + currNode = parent; + } + + area < viewArea && (area = viewArea); + var scale = Math.pow(area / viewArea, 0.5); + + return [containerWidth * scale, containerHeight * scale]; +} + +// Root postion base on coord of containerGroup +function calculateRootPosition(layoutInfo, rootRect, targetInfo) { + if (rootRect) { + return {x: rootRect.x, y: rootRect.y}; + } + + var defaultPosition = {x: 0, y: 0}; + if (!targetInfo) { + return defaultPosition; + } + + // If targetInfo is fetched by 'retrieveTargetInfo', + // old tree and new tree are the same tree, + // so the node still exists and we can visit it. + + var targetNode = targetInfo.node; + var layout = targetNode.getLayout(); + + if (!layout) { + return defaultPosition; + } + + // Transform coord from local to container. + var targetCenter = [layout.width / 2, layout.height / 2]; + var node = targetNode; + while (node) { + var nodeLayout = node.getLayout(); + targetCenter[0] += nodeLayout.x; + targetCenter[1] += nodeLayout.y; + node = node.parentNode; + } + + return { + x: layoutInfo.width / 2 - targetCenter[0], + y: layoutInfo.height / 2 - targetCenter[1] + }; +} + +// Mark nodes visible for prunning when visual coding and rendering. +// Prunning depends on layout and root position, so we have to do it after layout. +function prunning(node, clipRect, viewAbovePath, viewRoot, depth) { + var nodeLayout = node.getLayout(); + var nodeInViewAbovePath = viewAbovePath[depth]; + var isAboveViewRoot = nodeInViewAbovePath && nodeInViewAbovePath === node; + + if ( + (nodeInViewAbovePath && !isAboveViewRoot) + || (depth === viewAbovePath.length && node !== viewRoot) + ) { + return; + } + + node.setLayout({ + // isInView means: viewRoot sub tree + viewAbovePath + isInView: true, + // invisible only means: outside view clip so that the node can not + // see but still layout for animation preparation but not render. + invisible: !isAboveViewRoot && !clipRect.intersect(nodeLayout), + isAboveViewRoot: isAboveViewRoot + }, true); + + // Transform to child coordinate. + var childClipRect = new BoundingRect( + clipRect.x - nodeLayout.x, + clipRect.y - nodeLayout.y, + clipRect.width, + clipRect.height + ); + + each$10(node.viewChildren || [], function (child) { + prunning(child, childClipRect, viewAbovePath, viewRoot, depth + 1); + }); +} + +function getUpperLabelHeight(model) { + return model.get(PATH_UPPER_LABEL_SHOW) ? model.get(PATH_UPPER_LABEL_HEIGHT) : 0; +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +registerVisual(treemapVisual); +registerLayout(treemapLayout); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/** + * Graph data structure + * + * @module echarts/data/Graph + * @author Yi Shen(https://www.github.com/pissang) + */ + +// id may be function name of Object, add a prefix to avoid this problem. +function generateNodeKey(id) { + return '_EC_' + id; +} +/** + * @alias module:echarts/data/Graph + * @constructor + * @param {boolean} directed + */ +var Graph = function (directed) { + /** + * 是否是有向图 + * @type {boolean} + * @private + */ + this._directed = directed || false; + + /** + * @type {Array.} + * @readOnly + */ + this.nodes = []; + + /** + * @type {Array.} + * @readOnly + */ + this.edges = []; + + /** + * @type {Object.} + * @private + */ + this._nodesMap = {}; + /** + * @type {Object.} + * @private + */ + this._edgesMap = {}; + + /** + * @type {module:echarts/data/List} + * @readOnly + */ + this.data; + + /** + * @type {module:echarts/data/List} + * @readOnly + */ + this.edgeData; +}; + +var graphProto = Graph.prototype; +/** + * @type {string} + */ +graphProto.type = 'graph'; + +/** + * If is directed graph + * @return {boolean} + */ +graphProto.isDirected = function () { + return this._directed; +}; + +/** + * Add a new node + * @param {string} id + * @param {number} [dataIndex] + */ +graphProto.addNode = function (id, dataIndex) { + id = id || ('' + dataIndex); + + var nodesMap = this._nodesMap; + + if (nodesMap[generateNodeKey(id)]) { + if (__DEV__) { + console.error('Graph nodes have duplicate name or id'); + } + return; + } + + var node = new Node(id, dataIndex); + node.hostGraph = this; + + this.nodes.push(node); + + nodesMap[generateNodeKey(id)] = node; + return node; +}; + +/** + * Get node by data index + * @param {number} dataIndex + * @return {module:echarts/data/Graph~Node} + */ +graphProto.getNodeByIndex = function (dataIndex) { + var rawIdx = this.data.getRawIndex(dataIndex); + return this.nodes[rawIdx]; +}; +/** + * Get node by id + * @param {string} id + * @return {module:echarts/data/Graph.Node} + */ +graphProto.getNodeById = function (id) { + return this._nodesMap[generateNodeKey(id)]; +}; + +/** + * Add a new edge + * @param {number|string|module:echarts/data/Graph.Node} n1 + * @param {number|string|module:echarts/data/Graph.Node} n2 + * @param {number} [dataIndex=-1] + * @return {module:echarts/data/Graph.Edge} + */ +graphProto.addEdge = function (n1, n2, dataIndex) { + var nodesMap = this._nodesMap; + var edgesMap = this._edgesMap; + + // PNEDING + if (typeof n1 === 'number') { + n1 = this.nodes[n1]; + } + if (typeof n2 === 'number') { + n2 = this.nodes[n2]; + } + + if (!Node.isInstance(n1)) { + n1 = nodesMap[generateNodeKey(n1)]; + } + if (!Node.isInstance(n2)) { + n2 = nodesMap[generateNodeKey(n2)]; + } + if (!n1 || !n2) { + return; + } + + var key = n1.id + '-' + n2.id; + // PENDING + if (edgesMap[key]) { + return; + } + + var edge = new Edge(n1, n2, dataIndex); + edge.hostGraph = this; + + if (this._directed) { + n1.outEdges.push(edge); + n2.inEdges.push(edge); + } + n1.edges.push(edge); + if (n1 !== n2) { + n2.edges.push(edge); + } + + this.edges.push(edge); + edgesMap[key] = edge; + + return edge; +}; + +/** + * Get edge by data index + * @param {number} dataIndex + * @return {module:echarts/data/Graph~Node} + */ +graphProto.getEdgeByIndex = function (dataIndex) { + var rawIdx = this.edgeData.getRawIndex(dataIndex); + return this.edges[rawIdx]; +}; +/** + * Get edge by two linked nodes + * @param {module:echarts/data/Graph.Node|string} n1 + * @param {module:echarts/data/Graph.Node|string} n2 + * @return {module:echarts/data/Graph.Edge} + */ +graphProto.getEdge = function (n1, n2) { + if (Node.isInstance(n1)) { + n1 = n1.id; + } + if (Node.isInstance(n2)) { + n2 = n2.id; + } + + var edgesMap = this._edgesMap; + + if (this._directed) { + return edgesMap[n1 + '-' + n2]; + } + else { + return edgesMap[n1 + '-' + n2] + || edgesMap[n2 + '-' + n1]; + } +}; + +/** + * Iterate all nodes + * @param {Function} cb + * @param {*} [context] + */ +graphProto.eachNode = function (cb, context) { + var nodes = this.nodes; + var len = nodes.length; + for (var i = 0; i < len; i++) { + if (nodes[i].dataIndex >= 0) { + cb.call(context, nodes[i], i); + } + } +}; + +/** + * Iterate all edges + * @param {Function} cb + * @param {*} [context] + */ +graphProto.eachEdge = function (cb, context) { + var edges = this.edges; + var len = edges.length; + for (var i = 0; i < len; i++) { + if (edges[i].dataIndex >= 0 + && edges[i].node1.dataIndex >= 0 + && edges[i].node2.dataIndex >= 0 + ) { + cb.call(context, edges[i], i); + } + } +}; + +/** + * Breadth first traverse + * @param {Function} cb + * @param {module:echarts/data/Graph.Node} startNode + * @param {string} [direction='none'] 'none'|'in'|'out' + * @param {*} [context] + */ +graphProto.breadthFirstTraverse = function ( + cb, startNode, direction, context +) { + if (!Node.isInstance(startNode)) { + startNode = this._nodesMap[generateNodeKey(startNode)]; + } + if (!startNode) { + return; + } + + var edgeType = direction === 'out' + ? 'outEdges' : (direction === 'in' ? 'inEdges' : 'edges'); + + for (var i = 0; i < this.nodes.length; i++) { + this.nodes[i].__visited = false; + } + + if (cb.call(context, startNode, null)) { + return; + } + + var queue = [startNode]; + while (queue.length) { + var currentNode = queue.shift(); + var edges = currentNode[edgeType]; + + for (var i = 0; i < edges.length; i++) { + var e = edges[i]; + var otherNode = e.node1 === currentNode + ? e.node2 : e.node1; + if (!otherNode.__visited) { + if (cb.call(context, otherNode, currentNode)) { + // Stop traversing + return; + } + queue.push(otherNode); + otherNode.__visited = true; + } + } + } +}; + +// TODO +// graphProto.depthFirstTraverse = function ( +// cb, startNode, direction, context +// ) { + +// }; + +// Filter update +graphProto.update = function () { + var data = this.data; + var edgeData = this.edgeData; + var nodes = this.nodes; + var edges = this.edges; + + for (var i = 0, len = nodes.length; i < len; i++) { + nodes[i].dataIndex = -1; + } + for (var i = 0, len = data.count(); i < len; i++) { + nodes[data.getRawIndex(i)].dataIndex = i; + } + + edgeData.filterSelf(function (idx) { + var edge = edges[edgeData.getRawIndex(idx)]; + return edge.node1.dataIndex >= 0 && edge.node2.dataIndex >= 0; + }); + + // Update edge + for (var i = 0, len = edges.length; i < len; i++) { + edges[i].dataIndex = -1; + } + for (var i = 0, len = edgeData.count(); i < len; i++) { + edges[edgeData.getRawIndex(i)].dataIndex = i; + } +}; + +/** + * @return {module:echarts/data/Graph} + */ +graphProto.clone = function () { + var graph = new Graph(this._directed); + var nodes = this.nodes; + var edges = this.edges; + for (var i = 0; i < nodes.length; i++) { + graph.addNode(nodes[i].id, nodes[i].dataIndex); + } + for (var i = 0; i < edges.length; i++) { + var e = edges[i]; + graph.addEdge(e.node1.id, e.node2.id, e.dataIndex); + } + return graph; +}; + + +/** + * @alias module:echarts/data/Graph.Node + */ +function Node(id, dataIndex) { + /** + * @type {string} + */ + this.id = id == null ? '' : id; + + /** + * @type {Array.} + */ + this.inEdges = []; + /** + * @type {Array.} + */ + this.outEdges = []; + /** + * @type {Array.} + */ + this.edges = []; + /** + * @type {module:echarts/data/Graph} + */ + this.hostGraph; + + /** + * @type {number} + */ + this.dataIndex = dataIndex == null ? -1 : dataIndex; +} + +Node.prototype = { + + constructor: Node, + + /** + * @return {number} + */ + degree: function () { + return this.edges.length; + }, + + /** + * @return {number} + */ + inDegree: function () { + return this.inEdges.length; + }, + + /** + * @return {number} + */ + outDegree: function () { + return this.outEdges.length; + }, + + /** + * @param {string} [path] + * @return {module:echarts/model/Model} + */ + getModel: function (path) { + if (this.dataIndex < 0) { + return; + } + var graph = this.hostGraph; + var itemModel = graph.data.getItemModel(this.dataIndex); + + return itemModel.getModel(path); + } +}; + +/** + * 图边 + * @alias module:echarts/data/Graph.Edge + * @param {module:echarts/data/Graph.Node} n1 + * @param {module:echarts/data/Graph.Node} n2 + * @param {number} [dataIndex=-1] + */ +function Edge(n1, n2, dataIndex) { + + /** + * 节点1,如果是有向图则为源节点 + * @type {module:echarts/data/Graph.Node} + */ + this.node1 = n1; + + /** + * 节点2,如果是有向图则为目标节点 + * @type {module:echarts/data/Graph.Node} + */ + this.node2 = n2; + + this.dataIndex = dataIndex == null ? -1 : dataIndex; +} + +/** + * @param {string} [path] + * @return {module:echarts/model/Model} + */ +Edge.prototype.getModel = function (path) { + if (this.dataIndex < 0) { + return; + } + var graph = this.hostGraph; + var itemModel = graph.edgeData.getItemModel(this.dataIndex); + + return itemModel.getModel(path); +}; + +var createGraphDataProxyMixin = function (hostName, dataName) { + return { + /** + * @param {string=} [dimension='value'] Default 'value'. can be 'a', 'b', 'c', 'd', 'e'. + * @return {number} + */ + getValue: function (dimension) { + var data = this[hostName][dataName]; + return data.get(data.getDimension(dimension || 'value'), this.dataIndex); + }, + + /** + * @param {Object|string} key + * @param {*} [value] + */ + setVisual: function (key, value) { + this.dataIndex >= 0 + && this[hostName][dataName].setItemVisual(this.dataIndex, key, value); + }, + + /** + * @param {string} key + * @return {boolean} + */ + getVisual: function (key, ignoreParent) { + return this[hostName][dataName].getItemVisual(this.dataIndex, key, ignoreParent); + }, + + /** + * @param {Object} layout + * @return {boolean} [merge=false] + */ + setLayout: function (layout, merge$$1) { + this.dataIndex >= 0 + && this[hostName][dataName].setItemLayout(this.dataIndex, layout, merge$$1); + }, + + /** + * @return {Object} + */ + getLayout: function () { + return this[hostName][dataName].getItemLayout(this.dataIndex); + }, + + /** + * @return {module:zrender/Element} + */ + getGraphicEl: function () { + return this[hostName][dataName].getItemGraphicEl(this.dataIndex); + }, + + /** + * @return {number} + */ + getRawIndex: function () { + return this[hostName][dataName].getRawIndex(this.dataIndex); + } + }; +}; + +mixin(Node, createGraphDataProxyMixin('hostGraph', 'data')); +mixin(Edge, createGraphDataProxyMixin('hostGraph', 'edgeData')); + +Graph.Node = Node; +Graph.Edge = Edge; + +enableClassCheck(Node); +enableClassCheck(Edge); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var createGraphFromNodeEdge = function (nodes, edges, seriesModel, directed, beforeLink) { + // ??? TODO + // support dataset? + var graph = new Graph(directed); + for (var i = 0; i < nodes.length; i++) { + graph.addNode(retrieve( + // Id, name, dataIndex + nodes[i].id, nodes[i].name, i + ), i); + } + + var linkNameList = []; + var validEdges = []; + var linkCount = 0; + for (var i = 0; i < edges.length; i++) { + var link = edges[i]; + var source = link.source; + var target = link.target; + // addEdge may fail when source or target not exists + if (graph.addEdge(source, target, linkCount)) { + validEdges.push(link); + linkNameList.push(retrieve(link.id, source + ' > ' + target)); + linkCount++; + } + } + + var coordSys = seriesModel.get('coordinateSystem'); + var nodeData; + if (coordSys === 'cartesian2d' || coordSys === 'polar') { + nodeData = createListFromArray(nodes, seriesModel); + } + else { + var coordSysCtor = CoordinateSystemManager.get(coordSys); + var coordDimensions = (coordSysCtor && coordSysCtor.type !== 'view') + ? (coordSysCtor.dimensions || []) : []; + // FIXME: Some geo do not need `value` dimenson, whereas `calendar` needs + // `value` dimension, but graph need `value` dimension. It's better to + // uniform this behavior. + if (indexOf(coordDimensions, 'value') < 0) { + coordDimensions.concat(['value']); + } + + var dimensionNames = createDimensions(nodes, { + coordDimensions: coordDimensions + }); + nodeData = new List(dimensionNames, seriesModel); + nodeData.initData(nodes); + } + + var edgeData = new List(['value'], seriesModel); + edgeData.initData(validEdges, linkNameList); + + beforeLink && beforeLink(nodeData, edgeData); + + linkList({ + mainData: nodeData, + struct: graph, + structAttr: 'graph', + datas: {node: nodeData, edge: edgeData}, + datasAttr: {node: 'data', edge: 'edgeData'} + }); + + // Update dataIndex of nodes and edges because invalid edge may be removed + graph.update(); + + return graph; +}; + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var GraphSeries = extendSeriesModel({ + + type: 'series.graph', + + init: function (option) { + GraphSeries.superApply(this, 'init', arguments); + + // Provide data for legend select + this.legendDataProvider = function () { + return this._categoriesData; + }; + + this.fillDataTextStyle(option.edges || option.links); + + this._updateCategoriesData(); + }, + + mergeOption: function (option) { + GraphSeries.superApply(this, 'mergeOption', arguments); + + this.fillDataTextStyle(option.edges || option.links); + + this._updateCategoriesData(); + }, + + mergeDefaultAndTheme: function (option) { + GraphSeries.superApply(this, 'mergeDefaultAndTheme', arguments); + defaultEmphasis(option, ['edgeLabel'], ['show']); + }, + + getInitialData: function (option, ecModel) { + var edges = option.edges || option.links || []; + var nodes = option.data || option.nodes || []; + var self = this; + + if (nodes && edges) { + return createGraphFromNodeEdge(nodes, edges, this, true, beforeLink).data; + } + + function beforeLink(nodeData, edgeData) { + // Overwrite nodeData.getItemModel to + nodeData.wrapMethod('getItemModel', function (model) { + var categoriesModels = self._categoriesModels; + var categoryIdx = model.getShallow('category'); + var categoryModel = categoriesModels[categoryIdx]; + if (categoryModel) { + categoryModel.parentModel = model.parentModel; + model.parentModel = categoryModel; + } + return model; + }); + + var edgeLabelModel = self.getModel('edgeLabel'); + // For option `edgeLabel` can be found by label.xxx.xxx on item mode. + var fakeSeriesModel = new Model( + {label: edgeLabelModel.option}, + edgeLabelModel.parentModel, + ecModel + ); + var emphasisEdgeLabelModel = self.getModel('emphasis.edgeLabel'); + var emphasisFakeSeriesModel = new Model( + {emphasis: {label: emphasisEdgeLabelModel.option}}, + emphasisEdgeLabelModel.parentModel, + ecModel + ); + + edgeData.wrapMethod('getItemModel', function (model) { + model.customizeGetParent(edgeGetParent); + return model; + }); + + function edgeGetParent(path) { + path = this.parsePath(path); + return (path && path[0] === 'label') + ? fakeSeriesModel + : (path && path[0] === 'emphasis' && path[1] === 'label') + ? emphasisFakeSeriesModel + : this.parentModel; + } + } + }, + + /** + * @return {module:echarts/data/Graph} + */ + getGraph: function () { + return this.getData().graph; + }, + + /** + * @return {module:echarts/data/List} + */ + getEdgeData: function () { + return this.getGraph().edgeData; + }, + + /** + * @return {module:echarts/data/List} + */ + getCategoriesData: function () { + return this._categoriesData; + }, + + /** + * @override + */ + formatTooltip: function (dataIndex, multipleSeries, dataType) { + if (dataType === 'edge') { + var nodeData = this.getData(); + var params = this.getDataParams(dataIndex, dataType); + var edge = nodeData.graph.getEdgeByIndex(dataIndex); + var sourceName = nodeData.getName(edge.node1.dataIndex); + var targetName = nodeData.getName(edge.node2.dataIndex); + + var html = []; + sourceName != null && html.push(sourceName); + targetName != null && html.push(targetName); + html = encodeHTML(html.join(' > ')); + + if (params.value) { + html += ' : ' + encodeHTML(params.value); + } + return html; + } + else { // dataType === 'node' or empty + return GraphSeries.superApply(this, 'formatTooltip', arguments); + } + }, + + _updateCategoriesData: function () { + var categories = map(this.option.categories || [], function (category) { + // Data must has value + return category.value != null ? category : extend({ + value: 0 + }, category); + }); + var categoriesData = new List(['value'], this); + categoriesData.initData(categories); + + this._categoriesData = categoriesData; + + this._categoriesModels = categoriesData.mapArray(function (idx) { + return categoriesData.getItemModel(idx, true); + }); + }, + + setZoom: function (zoom) { + this.option.zoom = zoom; + }, + + setCenter: function (center) { + this.option.center = center; + }, + + isAnimationEnabled: function () { + return GraphSeries.superCall(this, 'isAnimationEnabled') + // Not enable animation when do force layout + && !(this.get('layout') === 'force' && this.get('force.layoutAnimation')); + }, + + defaultOption: { + zlevel: 0, + z: 2, + + coordinateSystem: 'view', + + // Default option for all coordinate systems + // xAxisIndex: 0, + // yAxisIndex: 0, + // polarIndex: 0, + // geoIndex: 0, + + legendHoverLink: true, + + hoverAnimation: true, + + layout: null, + + focusNodeAdjacency: false, + + // Configuration of circular layout + circular: { + rotateLabel: false + }, + // Configuration of force directed layout + force: { + initLayout: null, + // Node repulsion. Can be an array to represent range. + repulsion: [0, 50], + gravity: 0.1, + + // Edge length. Can be an array to represent range. + edgeLength: 30, + + layoutAnimation: true + }, + + left: 'center', + top: 'center', + // right: null, + // bottom: null, + // width: '80%', + // height: '80%', + + symbol: 'circle', + symbolSize: 10, + + edgeSymbol: ['none', 'none'], + edgeSymbolSize: 10, + edgeLabel: { + position: 'middle' + }, + + draggable: false, + + roam: false, + + // Default on center of graph + center: null, + + zoom: 1, + // Symbol size scale ratio in roam + nodeScaleRatio: 0.6, + // cursor: null, + + // categories: [], + + // data: [] + // Or + // nodes: [] + // + // links: [] + // Or + // edges: [] + + label: { + show: false, + formatter: '{b}' + }, + + itemStyle: {}, + + lineStyle: { + color: '#aaa', + width: 1, + curveness: 0, + opacity: 0.5 + }, + emphasis: { + label: { + show: true + } + } + } +}); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/** + * Line path for bezier and straight line draw + */ + +var straightLineProto = Line.prototype; +var bezierCurveProto = BezierCurve.prototype; + +function isLine(shape) { + return isNaN(+shape.cpx1) || isNaN(+shape.cpy1); +} + +var LinePath = extendShape({ + + type: 'ec-line', + + style: { + stroke: '#000', + fill: null + }, + + shape: { + x1: 0, + y1: 0, + x2: 0, + y2: 0, + percent: 1, + cpx1: null, + cpy1: null + }, + + buildPath: function (ctx, shape) { + (isLine(shape) ? straightLineProto : bezierCurveProto).buildPath(ctx, shape); + }, + + pointAt: function (t) { + return isLine(this.shape) + ? straightLineProto.pointAt.call(this, t) + : bezierCurveProto.pointAt.call(this, t); + }, + + tangentAt: function (t) { + var shape = this.shape; + var p = isLine(shape) + ? [shape.x2 - shape.x1, shape.y2 - shape.y1] + : bezierCurveProto.tangentAt.call(this, t); + return normalize(p, p); + } +}); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/** + * @module echarts/chart/helper/Line + */ + +var SYMBOL_CATEGORIES = ['fromSymbol', 'toSymbol']; + +function makeSymbolTypeKey(symbolCategory) { + return '_' + symbolCategory + 'Type'; +} +/** + * @inner + */ +function createSymbol$1(name, lineData, idx) { + var color = lineData.getItemVisual(idx, 'color'); + var symbolType = lineData.getItemVisual(idx, name); + var symbolSize = lineData.getItemVisual(idx, name + 'Size'); + + if (!symbolType || symbolType === 'none') { + return; + } + + if (!isArray(symbolSize)) { + symbolSize = [symbolSize, symbolSize]; + } + var symbolPath = createSymbol( + symbolType, -symbolSize[0] / 2, -symbolSize[1] / 2, + symbolSize[0], symbolSize[1], color + ); + + symbolPath.name = name; + + return symbolPath; +} + +function createLine(points) { + var line = new LinePath({ + name: 'line' + }); + setLinePoints(line.shape, points); + return line; +} + +function setLinePoints(targetShape, points) { + var p1 = points[0]; + var p2 = points[1]; + var cp1 = points[2]; + targetShape.x1 = p1[0]; + targetShape.y1 = p1[1]; + targetShape.x2 = p2[0]; + targetShape.y2 = p2[1]; + targetShape.percent = 1; + + if (cp1) { + targetShape.cpx1 = cp1[0]; + targetShape.cpy1 = cp1[1]; + } + else { + targetShape.cpx1 = NaN; + targetShape.cpy1 = NaN; + } +} + +function updateSymbolAndLabelBeforeLineUpdate() { + var lineGroup = this; + var symbolFrom = lineGroup.childOfName('fromSymbol'); + var symbolTo = lineGroup.childOfName('toSymbol'); + var label = lineGroup.childOfName('label'); + // Quick reject + if (!symbolFrom && !symbolTo && label.ignore) { + return; + } + + var invScale = 1; + var parentNode = this.parent; + while (parentNode) { + if (parentNode.scale) { + invScale /= parentNode.scale[0]; + } + parentNode = parentNode.parent; + } + + var line = lineGroup.childOfName('line'); + // If line not changed + // FIXME Parent scale changed + if (!this.__dirty && !line.__dirty) { + return; + } + + var percent = line.shape.percent; + var fromPos = line.pointAt(0); + var toPos = line.pointAt(percent); + + var d = sub([], toPos, fromPos); + normalize(d, d); + + if (symbolFrom) { + symbolFrom.attr('position', fromPos); + var tangent = line.tangentAt(0); + symbolFrom.attr('rotation', Math.PI / 2 - Math.atan2( + tangent[1], tangent[0] + )); + symbolFrom.attr('scale', [invScale * percent, invScale * percent]); + } + if (symbolTo) { + symbolTo.attr('position', toPos); + var tangent = line.tangentAt(1); + symbolTo.attr('rotation', -Math.PI / 2 - Math.atan2( + tangent[1], tangent[0] + )); + symbolTo.attr('scale', [invScale * percent, invScale * percent]); + } + + if (!label.ignore) { + label.attr('position', toPos); + + var textPosition; + var textAlign; + var textVerticalAlign; + + var distance$$1 = 5 * invScale; + // End + if (label.__position === 'end') { + textPosition = [d[0] * distance$$1 + toPos[0], d[1] * distance$$1 + toPos[1]]; + textAlign = d[0] > 0.8 ? 'left' : (d[0] < -0.8 ? 'right' : 'center'); + textVerticalAlign = d[1] > 0.8 ? 'top' : (d[1] < -0.8 ? 'bottom' : 'middle'); + } + // Middle + else if (label.__position === 'middle') { + var halfPercent = percent / 2; + var tangent = line.tangentAt(halfPercent); + var n = [tangent[1], -tangent[0]]; + var cp = line.pointAt(halfPercent); + if (n[1] > 0) { + n[0] = -n[0]; + n[1] = -n[1]; + } + textPosition = [cp[0] + n[0] * distance$$1, cp[1] + n[1] * distance$$1]; + textAlign = 'center'; + textVerticalAlign = 'bottom'; + var rotation = -Math.atan2(tangent[1], tangent[0]); + if (toPos[0] < fromPos[0]) { + rotation = Math.PI + rotation; + } + label.attr('rotation', rotation); + } + // Start + else { + textPosition = [-d[0] * distance$$1 + fromPos[0], -d[1] * distance$$1 + fromPos[1]]; + textAlign = d[0] > 0.8 ? 'right' : (d[0] < -0.8 ? 'left' : 'center'); + textVerticalAlign = d[1] > 0.8 ? 'bottom' : (d[1] < -0.8 ? 'top' : 'middle'); + } + label.attr({ + style: { + // Use the user specified text align and baseline first + textVerticalAlign: label.__verticalAlign || textVerticalAlign, + textAlign: label.__textAlign || textAlign + }, + position: textPosition, + scale: [invScale, invScale] + }); + } +} + +/** + * @constructor + * @extends {module:zrender/graphic/Group} + * @alias {module:echarts/chart/helper/Line} + */ +function Line$1(lineData, idx, seriesScope) { + Group.call(this); + + this._createLine(lineData, idx, seriesScope); +} + +var lineProto = Line$1.prototype; + +// Update symbol position and rotation +lineProto.beforeUpdate = updateSymbolAndLabelBeforeLineUpdate; + +lineProto._createLine = function (lineData, idx, seriesScope) { + var seriesModel = lineData.hostModel; + var linePoints = lineData.getItemLayout(idx); + + var line = createLine(linePoints); + line.shape.percent = 0; + initProps(line, { + shape: { + percent: 1 + } + }, seriesModel, idx); + + this.add(line); + + var label = new Text({ + name: 'label', + // FIXME + // Temporary solution for `focusNodeAdjacency`. + // line label do not use the opacity of lineStyle. + lineLabelOriginalOpacity: 1 + }); + this.add(label); + + each$1(SYMBOL_CATEGORIES, function (symbolCategory) { + var symbol = createSymbol$1(symbolCategory, lineData, idx); + // symbols must added after line to make sure + // it will be updated after line#update. + // Or symbol position and rotation update in line#beforeUpdate will be one frame slow + this.add(symbol); + this[makeSymbolTypeKey(symbolCategory)] = lineData.getItemVisual(idx, symbolCategory); + }, this); + + this._updateCommonStl(lineData, idx, seriesScope); +}; + +lineProto.updateData = function (lineData, idx, seriesScope) { + var seriesModel = lineData.hostModel; + + var line = this.childOfName('line'); + var linePoints = lineData.getItemLayout(idx); + var target = { + shape: {} + }; + setLinePoints(target.shape, linePoints); + updateProps(line, target, seriesModel, idx); + + each$1(SYMBOL_CATEGORIES, function (symbolCategory) { + var symbolType = lineData.getItemVisual(idx, symbolCategory); + var key = makeSymbolTypeKey(symbolCategory); + // Symbol changed + if (this[key] !== symbolType) { + this.remove(this.childOfName(symbolCategory)); + var symbol = createSymbol$1(symbolCategory, lineData, idx); + this.add(symbol); + } + this[key] = symbolType; + }, this); + + this._updateCommonStl(lineData, idx, seriesScope); +}; + +lineProto._updateCommonStl = function (lineData, idx, seriesScope) { + var seriesModel = lineData.hostModel; + + var line = this.childOfName('line'); + + var lineStyle = seriesScope && seriesScope.lineStyle; + var hoverLineStyle = seriesScope && seriesScope.hoverLineStyle; + var labelModel = seriesScope && seriesScope.labelModel; + var hoverLabelModel = seriesScope && seriesScope.hoverLabelModel; + + // Optimization for large dataset + if (!seriesScope || lineData.hasItemOption) { + var itemModel = lineData.getItemModel(idx); + + lineStyle = itemModel.getModel('lineStyle').getLineStyle(); + hoverLineStyle = itemModel.getModel('emphasis.lineStyle').getLineStyle(); + + labelModel = itemModel.getModel('label'); + hoverLabelModel = itemModel.getModel('emphasis.label'); + } + + var visualColor = lineData.getItemVisual(idx, 'color'); + var visualOpacity = retrieve3( + lineData.getItemVisual(idx, 'opacity'), + lineStyle.opacity, + 1 + ); + + line.useStyle(defaults( + { + strokeNoScale: true, + fill: 'none', + stroke: visualColor, + opacity: visualOpacity + }, + lineStyle + )); + line.hoverStyle = hoverLineStyle; + + // Update symbol + each$1(SYMBOL_CATEGORIES, function (symbolCategory) { + var symbol = this.childOfName(symbolCategory); + if (symbol) { + symbol.setColor(visualColor); + symbol.setStyle({ + opacity: visualOpacity + }); + } + }, this); + + var showLabel = labelModel.getShallow('show'); + var hoverShowLabel = hoverLabelModel.getShallow('show'); + + var label = this.childOfName('label'); + var defaultLabelColor; + var baseText; + + // FIXME: the logic below probably should be merged to `graphic.setLabelStyle`. + if (showLabel || hoverShowLabel) { + defaultLabelColor = visualColor || '#000'; + + baseText = seriesModel.getFormattedLabel(idx, 'normal', lineData.dataType); + if (baseText == null) { + var rawVal = seriesModel.getRawValue(idx); + baseText = rawVal == null + ? lineData.getName(idx) + : isFinite(rawVal) + ? round$2(rawVal) + : rawVal; + } + } + var normalText = showLabel ? baseText : null; + var emphasisText = hoverShowLabel + ? retrieve2( + seriesModel.getFormattedLabel(idx, 'emphasis', lineData.dataType), + baseText + ) + : null; + + var labelStyle = label.style; + + // Always set `textStyle` even if `normalStyle.text` is null, because default + // values have to be set on `normalStyle`. + if (normalText != null || emphasisText != null) { + setTextStyle(label.style, labelModel, { + text: normalText + }, { + autoColor: defaultLabelColor + }); + + label.__textAlign = labelStyle.textAlign; + label.__verticalAlign = labelStyle.textVerticalAlign; + // 'start', 'middle', 'end' + label.__position = labelModel.get('position') || 'middle'; + } + + if (emphasisText != null) { + // Only these properties supported in this emphasis style here. + label.hoverStyle = { + text: emphasisText, + textFill: hoverLabelModel.getTextColor(true), + // For merging hover style to normal style, do not use + // `hoverLabelModel.getFont()` here. + fontStyle: hoverLabelModel.getShallow('fontStyle'), + fontWeight: hoverLabelModel.getShallow('fontWeight'), + fontSize: hoverLabelModel.getShallow('fontSize'), + fontFamily: hoverLabelModel.getShallow('fontFamily') + }; + } + else { + label.hoverStyle = { + text: null + }; + } + + label.ignore = !showLabel && !hoverShowLabel; + + setHoverStyle(this); +}; + +lineProto.highlight = function () { + this.trigger('emphasis'); +}; + +lineProto.downplay = function () { + this.trigger('normal'); +}; + +lineProto.updateLayout = function (lineData, idx) { + this.setLinePoints(lineData.getItemLayout(idx)); +}; + +lineProto.setLinePoints = function (points) { + var linePath = this.childOfName('line'); + setLinePoints(linePath.shape, points); + linePath.dirty(); +}; + +inherits(Line$1, Group); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/** + * @module echarts/chart/helper/LineDraw + */ + +// import IncrementalDisplayable from 'zrender/src/graphic/IncrementalDisplayable'; + +/** + * @alias module:echarts/component/marker/LineDraw + * @constructor + */ +function LineDraw(ctor) { + this._ctor = ctor || Line$1; + + this.group = new Group(); +} + +var lineDrawProto = LineDraw.prototype; + +lineDrawProto.isPersistent = function () { + return true; +}; + +/** + * @param {module:echarts/data/List} lineData + */ +lineDrawProto.updateData = function (lineData) { + var lineDraw = this; + var group = lineDraw.group; + + var oldLineData = lineDraw._lineData; + lineDraw._lineData = lineData; + + // There is no oldLineData only when first rendering or switching from + // stream mode to normal mode, where previous elements should be removed. + if (!oldLineData) { + group.removeAll(); + } + + var seriesScope = makeSeriesScope$1(lineData); + + lineData.diff(oldLineData) + .add(function (idx) { + doAdd(lineDraw, lineData, idx, seriesScope); + }) + .update(function (newIdx, oldIdx) { + doUpdate(lineDraw, oldLineData, lineData, oldIdx, newIdx, seriesScope); + }) + .remove(function (idx) { + group.remove(oldLineData.getItemGraphicEl(idx)); + }) + .execute(); +}; + +function doAdd(lineDraw, lineData, idx, seriesScope) { + var itemLayout = lineData.getItemLayout(idx); + + if (!lineNeedsDraw(itemLayout)) { + return; + } + + var el = new lineDraw._ctor(lineData, idx, seriesScope); + lineData.setItemGraphicEl(idx, el); + lineDraw.group.add(el); +} + +function doUpdate(lineDraw, oldLineData, newLineData, oldIdx, newIdx, seriesScope) { + var itemEl = oldLineData.getItemGraphicEl(oldIdx); + + if (!lineNeedsDraw(newLineData.getItemLayout(newIdx))) { + lineDraw.group.remove(itemEl); + return; + } + + if (!itemEl) { + itemEl = new lineDraw._ctor(newLineData, newIdx, seriesScope); + } + else { + itemEl.updateData(newLineData, newIdx, seriesScope); + } + + newLineData.setItemGraphicEl(newIdx, itemEl); + + lineDraw.group.add(itemEl); +} + +lineDrawProto.updateLayout = function () { + var lineData = this._lineData; + + // Do not support update layout in incremental mode. + if (!lineData) { + return; + } + + lineData.eachItemGraphicEl(function (el, idx) { + el.updateLayout(lineData, idx); + }, this); +}; + +lineDrawProto.incrementalPrepareUpdate = function (lineData) { + this._seriesScope = makeSeriesScope$1(lineData); + this._lineData = null; + this.group.removeAll(); +}; + +lineDrawProto.incrementalUpdate = function (taskParams, lineData) { + function updateIncrementalAndHover(el) { + if (!el.isGroup) { + el.incremental = el.useHoverLayer = true; + } + } + + for (var idx = taskParams.start; idx < taskParams.end; idx++) { + var itemLayout = lineData.getItemLayout(idx); + + if (lineNeedsDraw(itemLayout)) { + var el = new this._ctor(lineData, idx, this._seriesScope); + el.traverse(updateIncrementalAndHover); + + this.group.add(el); + lineData.setItemGraphicEl(idx, el); + } + } +}; + +function makeSeriesScope$1(lineData) { + var hostModel = lineData.hostModel; + return { + lineStyle: hostModel.getModel('lineStyle').getLineStyle(), + hoverLineStyle: hostModel.getModel('emphasis.lineStyle').getLineStyle(), + labelModel: hostModel.getModel('label'), + hoverLabelModel: hostModel.getModel('emphasis.label') + }; +} + +lineDrawProto.remove = function () { + this._clearIncremental(); + this._incremental = null; + this.group.removeAll(); +}; + +lineDrawProto._clearIncremental = function () { + var incremental = this._incremental; + if (incremental) { + incremental.clearDisplaybles(); + } +}; + +function isPointNaN(pt) { + return isNaN(pt[0]) || isNaN(pt[1]); +} + +function lineNeedsDraw(pts) { + return !isPointNaN(pts[0]) && !isPointNaN(pts[1]); +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var v1 = []; +var v2 = []; +var v3 = []; +var quadraticAt$1 = quadraticAt; +var v2DistSquare = distSquare; +var mathAbs$1 = Math.abs; +function intersectCurveCircle(curvePoints, center, radius) { + var p0 = curvePoints[0]; + var p1 = curvePoints[1]; + var p2 = curvePoints[2]; + + var d = Infinity; + var t; + var radiusSquare = radius * radius; + var interval = 0.1; + + for (var _t = 0.1; _t <= 0.9; _t += 0.1) { + v1[0] = quadraticAt$1(p0[0], p1[0], p2[0], _t); + v1[1] = quadraticAt$1(p0[1], p1[1], p2[1], _t); + var diff = mathAbs$1(v2DistSquare(v1, center) - radiusSquare); + if (diff < d) { + d = diff; + t = _t; + } + } + + // Assume the segment is monotone,Find root through Bisection method + // At most 32 iteration + for (var i = 0; i < 32; i++) { + // var prev = t - interval; + var next = t + interval; + // v1[0] = quadraticAt(p0[0], p1[0], p2[0], prev); + // v1[1] = quadraticAt(p0[1], p1[1], p2[1], prev); + v2[0] = quadraticAt$1(p0[0], p1[0], p2[0], t); + v2[1] = quadraticAt$1(p0[1], p1[1], p2[1], t); + v3[0] = quadraticAt$1(p0[0], p1[0], p2[0], next); + v3[1] = quadraticAt$1(p0[1], p1[1], p2[1], next); + + var diff = v2DistSquare(v2, center) - radiusSquare; + if (mathAbs$1(diff) < 1e-2) { + break; + } + + // var prevDiff = v2DistSquare(v1, center) - radiusSquare; + var nextDiff = v2DistSquare(v3, center) - radiusSquare; + + interval /= 2; + if (diff < 0) { + if (nextDiff >= 0) { + t = t + interval; + } + else { + t = t - interval; + } + } + else { + if (nextDiff >= 0) { + t = t - interval; + } + else { + t = t + interval; + } + } + } + + return t; +} + +// Adjust edge to avoid +var adjustEdge = function (graph, scale$$1) { + var tmp0 = []; + var quadraticSubdivide$$1 = quadraticSubdivide; + var pts = [[], [], []]; + var pts2 = [[], []]; + var v = []; + scale$$1 /= 2; + + function getSymbolSize(node) { + var symbolSize = node.getVisual('symbolSize'); + if (symbolSize instanceof Array) { + symbolSize = (symbolSize[0] + symbolSize[1]) / 2; + } + return symbolSize; + } + graph.eachEdge(function (edge, idx) { + var linePoints = edge.getLayout(); + var fromSymbol = edge.getVisual('fromSymbol'); + var toSymbol = edge.getVisual('toSymbol'); + + if (!linePoints.__original) { + linePoints.__original = [ + clone$1(linePoints[0]), + clone$1(linePoints[1]) + ]; + if (linePoints[2]) { + linePoints.__original.push(clone$1(linePoints[2])); + } + } + var originalPoints = linePoints.__original; + // Quadratic curve + if (linePoints[2] != null) { + copy(pts[0], originalPoints[0]); + copy(pts[1], originalPoints[2]); + copy(pts[2], originalPoints[1]); + if (fromSymbol && fromSymbol !== 'none') { + var symbolSize = getSymbolSize(edge.node1); + + var t = intersectCurveCircle(pts, originalPoints[0], symbolSize * scale$$1); + // Subdivide and get the second + quadraticSubdivide$$1(pts[0][0], pts[1][0], pts[2][0], t, tmp0); + pts[0][0] = tmp0[3]; + pts[1][0] = tmp0[4]; + quadraticSubdivide$$1(pts[0][1], pts[1][1], pts[2][1], t, tmp0); + pts[0][1] = tmp0[3]; + pts[1][1] = tmp0[4]; + } + if (toSymbol && toSymbol !== 'none') { + var symbolSize = getSymbolSize(edge.node2); + + var t = intersectCurveCircle(pts, originalPoints[1], symbolSize * scale$$1); + // Subdivide and get the first + quadraticSubdivide$$1(pts[0][0], pts[1][0], pts[2][0], t, tmp0); + pts[1][0] = tmp0[1]; + pts[2][0] = tmp0[2]; + quadraticSubdivide$$1(pts[0][1], pts[1][1], pts[2][1], t, tmp0); + pts[1][1] = tmp0[1]; + pts[2][1] = tmp0[2]; + } + // Copy back to layout + copy(linePoints[0], pts[0]); + copy(linePoints[1], pts[2]); + copy(linePoints[2], pts[1]); + } + // Line + else { + copy(pts2[0], originalPoints[0]); + copy(pts2[1], originalPoints[1]); + + sub(v, pts2[1], pts2[0]); + normalize(v, v); + if (fromSymbol && fromSymbol !== 'none') { + + var symbolSize = getSymbolSize(edge.node1); + + scaleAndAdd(pts2[0], pts2[0], v, symbolSize * scale$$1); + } + if (toSymbol && toSymbol !== 'none') { + var symbolSize = getSymbolSize(edge.node2); + + scaleAndAdd(pts2[1], pts2[1], v, -symbolSize * scale$$1); + } + copy(linePoints[0], pts2[0]); + copy(linePoints[1], pts2[1]); + } + }); +}; + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var FOCUS_ADJACENCY = '__focusNodeAdjacency'; +var UNFOCUS_ADJACENCY = '__unfocusNodeAdjacency'; + +var nodeOpacityPath = ['itemStyle', 'opacity']; +var lineOpacityPath = ['lineStyle', 'opacity']; + +function getItemOpacity(item, opacityPath) { + return item.getVisual('opacity') || item.getModel().get(opacityPath); +} + +function fadeOutItem(item, opacityPath, opacityRatio) { + var el = item.getGraphicEl(); + + var opacity = getItemOpacity(item, opacityPath); + if (opacityRatio != null) { + opacity == null && (opacity = 1); + opacity *= opacityRatio; + } + + el.downplay && el.downplay(); + el.traverse(function (child) { + if (child.type !== 'group') { + var opct = child.lineLabelOriginalOpacity; + if (opct == null || opacityRatio != null) { + opct = opacity; + } + child.setStyle('opacity', opct); + } + }); +} + +function fadeInItem(item, opacityPath) { + var opacity = getItemOpacity(item, opacityPath); + var el = item.getGraphicEl(); + + el.highlight && el.highlight(); + el.traverse(function (child) { + if (child.type !== 'group') { + child.setStyle('opacity', opacity); + } + }); +} + +extendChartView({ + + type: 'graph', + + init: function (ecModel, api) { + var symbolDraw = new SymbolDraw(); + var lineDraw = new LineDraw(); + var group = this.group; + + this._controller = new RoamController(api.getZr()); + this._controllerHost = {target: group}; + + group.add(symbolDraw.group); + group.add(lineDraw.group); + + this._symbolDraw = symbolDraw; + this._lineDraw = lineDraw; + + this._firstRender = true; + }, + + render: function (seriesModel, ecModel, api) { + var coordSys = seriesModel.coordinateSystem; + + this._model = seriesModel; + this._nodeScaleRatio = seriesModel.get('nodeScaleRatio'); + + var symbolDraw = this._symbolDraw; + var lineDraw = this._lineDraw; + + var group = this.group; + + if (coordSys.type === 'view') { + var groupNewProp = { + position: coordSys.position, + scale: coordSys.scale + }; + if (this._firstRender) { + group.attr(groupNewProp); + } + else { + updateProps(group, groupNewProp, seriesModel); + } + } + // Fix edge contact point with node + adjustEdge(seriesModel.getGraph(), this._getNodeGlobalScale(seriesModel)); + + var data = seriesModel.getData(); + symbolDraw.updateData(data); + + var edgeData = seriesModel.getEdgeData(); + lineDraw.updateData(edgeData); + + this._updateNodeAndLinkScale(); + + this._updateController(seriesModel, ecModel, api); + + clearTimeout(this._layoutTimeout); + var forceLayout = seriesModel.forceLayout; + var layoutAnimation = seriesModel.get('force.layoutAnimation'); + if (forceLayout) { + this._startForceLayoutIteration(forceLayout, layoutAnimation); + } + + data.eachItemGraphicEl(function (el, idx) { + var itemModel = data.getItemModel(idx); + // Update draggable + el.off('drag').off('dragend'); + var draggable = itemModel.get('draggable'); + if (draggable) { + el.on('drag', function () { + if (forceLayout) { + forceLayout.warmUp(); + !this._layouting + && this._startForceLayoutIteration(forceLayout, layoutAnimation); + forceLayout.setFixed(idx); + // Write position back to layout + data.setItemLayout(idx, el.position); + } + }, this).on('dragend', function () { + if (forceLayout) { + forceLayout.setUnfixed(idx); + } + }, this); + } + el.setDraggable(draggable && forceLayout); + + el[FOCUS_ADJACENCY] && el.off('mouseover', el[FOCUS_ADJACENCY]); + el[UNFOCUS_ADJACENCY] && el.off('mouseout', el[UNFOCUS_ADJACENCY]); + + if (itemModel.get('focusNodeAdjacency')) { + el.on('mouseover', el[FOCUS_ADJACENCY] = function () { + api.dispatchAction({ + type: 'focusNodeAdjacency', + seriesId: seriesModel.id, + dataIndex: el.dataIndex + }); + }); + el.on('mouseout', el[UNFOCUS_ADJACENCY] = function () { + api.dispatchAction({ + type: 'unfocusNodeAdjacency', + seriesId: seriesModel.id + }); + }); + } + + }, this); + + data.graph.eachEdge(function (edge) { + var el = edge.getGraphicEl(); + + el[FOCUS_ADJACENCY] && el.off('mouseover', el[FOCUS_ADJACENCY]); + el[UNFOCUS_ADJACENCY] && el.off('mouseout', el[UNFOCUS_ADJACENCY]); + + if (edge.getModel().get('focusNodeAdjacency')) { + el.on('mouseover', el[FOCUS_ADJACENCY] = function () { + api.dispatchAction({ + type: 'focusNodeAdjacency', + seriesId: seriesModel.id, + edgeDataIndex: edge.dataIndex + }); + }); + el.on('mouseout', el[UNFOCUS_ADJACENCY] = function () { + api.dispatchAction({ + type: 'unfocusNodeAdjacency', + seriesId: seriesModel.id + }); + }); + } + }); + + var circularRotateLabel = seriesModel.get('layout') === 'circular' + && seriesModel.get('circular.rotateLabel'); + var cx = data.getLayout('cx'); + var cy = data.getLayout('cy'); + data.eachItemGraphicEl(function (el, idx) { + var symbolPath = el.getSymbolPath(); + if (circularRotateLabel) { + var pos = data.getItemLayout(idx); + var rad = Math.atan2(pos[1] - cy, pos[0] - cx); + if (rad < 0) { + rad = Math.PI * 2 + rad; + } + var isLeft = pos[0] < cx; + if (isLeft) { + rad = rad - Math.PI; + } + var textPosition = isLeft ? 'left' : 'right'; + symbolPath.setStyle({ + textRotation: -rad, + textPosition: textPosition, + textOrigin: 'center' + }); + symbolPath.hoverStyle && (symbolPath.hoverStyle.textPosition = textPosition); + } + else { + symbolPath.setStyle({ + textRotation: 0 + }); + } + }); + + this._firstRender = false; + }, + + dispose: function () { + this._controller && this._controller.dispose(); + this._controllerHost = {}; + }, + + focusNodeAdjacency: function (seriesModel, ecModel, api, payload) { + var data = this._model.getData(); + var graph = data.graph; + var dataIndex = payload.dataIndex; + var edgeDataIndex = payload.edgeDataIndex; + + var node = graph.getNodeByIndex(dataIndex); + var edge = graph.getEdgeByIndex(edgeDataIndex); + + if (!node && !edge) { + return; + } + + graph.eachNode(function (node) { + fadeOutItem(node, nodeOpacityPath, 0.1); + }); + graph.eachEdge(function (edge) { + fadeOutItem(edge, lineOpacityPath, 0.1); + }); + + if (node) { + fadeInItem(node, nodeOpacityPath); + each$1(node.edges, function (adjacentEdge) { + if (adjacentEdge.dataIndex < 0) { + return; + } + fadeInItem(adjacentEdge, lineOpacityPath); + fadeInItem(adjacentEdge.node1, nodeOpacityPath); + fadeInItem(adjacentEdge.node2, nodeOpacityPath); + }); + } + if (edge) { + fadeInItem(edge, lineOpacityPath); + fadeInItem(edge.node1, nodeOpacityPath); + fadeInItem(edge.node2, nodeOpacityPath); + } + }, + + unfocusNodeAdjacency: function (seriesModel, ecModel, api, payload) { + var graph = this._model.getData().graph; + + graph.eachNode(function (node) { + fadeOutItem(node, nodeOpacityPath); + }); + graph.eachEdge(function (edge) { + fadeOutItem(edge, lineOpacityPath); + }); + }, + + _startForceLayoutIteration: function (forceLayout, layoutAnimation) { + var self = this; + (function step() { + forceLayout.step(function (stopped) { + self.updateLayout(self._model); + (self._layouting = !stopped) && ( + layoutAnimation + ? (self._layoutTimeout = setTimeout(step, 16)) + : step() + ); + }); + })(); + }, + + _updateController: function (seriesModel, ecModel, api) { + var controller = this._controller; + var controllerHost = this._controllerHost; + var group = this.group; + + controller.setPointerChecker(function (e, x, y) { + var rect = group.getBoundingRect(); + rect.applyTransform(group.transform); + return rect.contain(x, y) + && !onIrrelevantElement(e, api, seriesModel); + }); + + if (seriesModel.coordinateSystem.type !== 'view') { + controller.disable(); + return; + } + controller.enable(seriesModel.get('roam')); + controllerHost.zoomLimit = seriesModel.get('scaleLimit'); + controllerHost.zoom = seriesModel.coordinateSystem.getZoom(); + + controller + .off('pan') + .off('zoom') + .on('pan', function (e) { + updateViewOnPan(controllerHost, e.dx, e.dy); + api.dispatchAction({ + seriesId: seriesModel.id, + type: 'graphRoam', + dx: e.dx, + dy: e.dy + }); + }) + .on('zoom', function (e) { + updateViewOnZoom(controllerHost, e.scale, e.originX, e.originY); + api.dispatchAction({ + seriesId: seriesModel.id, + type: 'graphRoam', + zoom: e.scale, + originX: e.originX, + originY: e.originY + }); + this._updateNodeAndLinkScale(); + adjustEdge(seriesModel.getGraph(), this._getNodeGlobalScale(seriesModel)); + this._lineDraw.updateLayout(); + }, this); + }, + + _updateNodeAndLinkScale: function () { + var seriesModel = this._model; + var data = seriesModel.getData(); + + var nodeScale = this._getNodeGlobalScale(seriesModel); + var invScale = [nodeScale, nodeScale]; + + data.eachItemGraphicEl(function (el, idx) { + el.attr('scale', invScale); + }); + }, + + _getNodeGlobalScale: function (seriesModel) { + var coordSys = seriesModel.coordinateSystem; + if (coordSys.type !== 'view') { + return 1; + } + + var nodeScaleRatio = this._nodeScaleRatio; + + var groupScale = coordSys.scale; + var groupZoom = (groupScale && groupScale[0]) || 1; + // Scale node when zoom changes + var roamZoom = coordSys.getZoom(); + var nodeScale = (roamZoom - 1) * nodeScaleRatio + 1; + + return nodeScale / groupZoom; + }, + + updateLayout: function (seriesModel) { + adjustEdge(seriesModel.getGraph(), this._getNodeGlobalScale(seriesModel)); + + this._symbolDraw.updateLayout(); + this._lineDraw.updateLayout(); + }, + + remove: function (ecModel, api) { + this._symbolDraw && this._symbolDraw.remove(); + this._lineDraw && this._lineDraw.remove(); + } +}); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/** + * @payload + * @property {number} [seriesIndex] + * @property {string} [seriesId] + * @property {string} [seriesName] + * @property {number} [dataIndex] + */ +registerAction({ + type: 'focusNodeAdjacency', + event: 'focusNodeAdjacency', + update: 'series:focusNodeAdjacency' +}, function () {}); + +/** + * @payload + * @property {number} [seriesIndex] + * @property {string} [seriesId] + * @property {string} [seriesName] + */ +registerAction({ + type: 'unfocusNodeAdjacency', + event: 'unfocusNodeAdjacency', + update: 'series:unfocusNodeAdjacency' +}, function () {}); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var actionInfo = { + type: 'graphRoam', + event: 'graphRoam', + update: 'none' +}; + +/** + * @payload + * @property {string} name Series name + * @property {number} [dx] + * @property {number} [dy] + * @property {number} [zoom] + * @property {number} [originX] + * @property {number} [originY] + */ +registerAction(actionInfo, function (payload, ecModel) { + ecModel.eachComponent({mainType: 'series', query: payload}, function (seriesModel) { + var coordSys = seriesModel.coordinateSystem; + + var res = updateCenterAndZoom(coordSys, payload); + + seriesModel.setCenter + && seriesModel.setCenter(res.center); + + seriesModel.setZoom + && seriesModel.setZoom(res.zoom); + }); +}); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + + +var categoryFilter = function (ecModel) { + var legendModels = ecModel.findComponents({ + mainType: 'legend' + }); + if (!legendModels || !legendModels.length) { + return; + } + ecModel.eachSeriesByType('graph', function (graphSeries) { + var categoriesData = graphSeries.getCategoriesData(); + var graph = graphSeries.getGraph(); + var data = graph.data; + + var categoryNames = categoriesData.mapArray(categoriesData.getName); + + data.filterSelf(function (idx) { + var model = data.getItemModel(idx); + var category = model.getShallow('category'); + if (category != null) { + if (typeof category === 'number') { + category = categoryNames[category]; + } + // If in any legend component the status is not selected. + for (var i = 0; i < legendModels.length; i++) { + if (!legendModels[i].isSelected(category)) { + return false; + } + } + } + return true; + }); + }, this); +}; + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + + +var categoryVisual = function (ecModel) { + + var paletteScope = {}; + ecModel.eachSeriesByType('graph', function (seriesModel) { + var categoriesData = seriesModel.getCategoriesData(); + var data = seriesModel.getData(); + + var categoryNameIdxMap = {}; + + categoriesData.each(function (idx) { + var name = categoriesData.getName(idx); + // Add prefix to avoid conflict with Object.prototype. + categoryNameIdxMap['ec-' + name] = idx; + + var itemModel = categoriesData.getItemModel(idx); + var color = itemModel.get('itemStyle.color') + || seriesModel.getColorFromPalette(name, paletteScope); + categoriesData.setItemVisual(idx, 'color', color); + }); + + // Assign category color to visual + if (categoriesData.count()) { + data.each(function (idx) { + var model = data.getItemModel(idx); + var category = model.getShallow('category'); + if (category != null) { + if (typeof category === 'string') { + category = categoryNameIdxMap['ec-' + category]; + } + if (!data.getItemVisual(idx, 'color', true)) { + data.setItemVisual( + idx, 'color', + categoriesData.getItemVisual(category, 'color') + ); + } + } + }); + } + }); +}; + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + + +function normalize$1(a) { + if (!(a instanceof Array)) { + a = [a, a]; + } + return a; +} + +var edgeVisual = function (ecModel) { + ecModel.eachSeriesByType('graph', function (seriesModel) { + var graph = seriesModel.getGraph(); + var edgeData = seriesModel.getEdgeData(); + var symbolType = normalize$1(seriesModel.get('edgeSymbol')); + var symbolSize = normalize$1(seriesModel.get('edgeSymbolSize')); + + var colorQuery = 'lineStyle.color'.split('.'); + var opacityQuery = 'lineStyle.opacity'.split('.'); + + edgeData.setVisual('fromSymbol', symbolType && symbolType[0]); + edgeData.setVisual('toSymbol', symbolType && symbolType[1]); + edgeData.setVisual('fromSymbolSize', symbolSize && symbolSize[0]); + edgeData.setVisual('toSymbolSize', symbolSize && symbolSize[1]); + edgeData.setVisual('color', seriesModel.get(colorQuery)); + edgeData.setVisual('opacity', seriesModel.get(opacityQuery)); + + edgeData.each(function (idx) { + var itemModel = edgeData.getItemModel(idx); + var edge = graph.getEdgeByIndex(idx); + var symbolType = normalize$1(itemModel.getShallow('symbol', true)); + var symbolSize = normalize$1(itemModel.getShallow('symbolSize', true)); + // Edge visual must after node visual + var color = itemModel.get(colorQuery); + var opacity = itemModel.get(opacityQuery); + switch (color) { + case 'source': + color = edge.node1.getVisual('color'); + break; + case 'target': + color = edge.node2.getVisual('color'); + break; + } + + symbolType[0] && edge.setVisual('fromSymbol', symbolType[0]); + symbolType[1] && edge.setVisual('toSymbol', symbolType[1]); + symbolSize[0] && edge.setVisual('fromSymbolSize', symbolSize[0]); + symbolSize[1] && edge.setVisual('toSymbolSize', symbolSize[1]); + + edge.setVisual('color', color); + edge.setVisual('opacity', opacity); + }); + }); +}; + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +function simpleLayout$1(seriesModel) { + var coordSys = seriesModel.coordinateSystem; + if (coordSys && coordSys.type !== 'view') { + return; + } + var graph = seriesModel.getGraph(); + + graph.eachNode(function (node) { + var model = node.getModel(); + node.setLayout([+model.get('x'), +model.get('y')]); + }); + + simpleLayoutEdge(graph); +} + +function simpleLayoutEdge(graph) { + graph.eachEdge(function (edge) { + var curveness = edge.getModel().get('lineStyle.curveness') || 0; + var p1 = clone$1(edge.node1.getLayout()); + var p2 = clone$1(edge.node2.getLayout()); + var points = [p1, p2]; + if (+curveness) { + points.push([ + (p1[0] + p2[0]) / 2 - (p1[1] - p2[1]) * curveness, + (p1[1] + p2[1]) / 2 - (p2[0] - p1[0]) * curveness + ]); + } + edge.setLayout(points); + }); +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var simpleLayout = function (ecModel, api) { + ecModel.eachSeriesByType('graph', function (seriesModel) { + var layout = seriesModel.get('layout'); + var coordSys = seriesModel.coordinateSystem; + if (coordSys && coordSys.type !== 'view') { + var data = seriesModel.getData(); + + var dimensions = []; + each$1(coordSys.dimensions, function (coordDim) { + dimensions = dimensions.concat(data.mapDimension(coordDim, true)); + }); + + for (var dataIndex = 0; dataIndex < data.count(); dataIndex++) { + var value = []; + var hasValue = false; + for (var i = 0; i < dimensions.length; i++) { + var val = data.get(dimensions[i], dataIndex); + if (!isNaN(val)) { + hasValue = true; + } + value.push(val); + } + if (hasValue) { + data.setItemLayout(dataIndex, coordSys.dataToPoint(value)); + } + else { + // Also {Array.}, not undefined to avoid if...else... statement + data.setItemLayout(dataIndex, [NaN, NaN]); + } + } + + simpleLayoutEdge(data.graph); + } + else if (!layout || layout === 'none') { + simpleLayout$1(seriesModel); + } + }); +}; + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +function circularLayout$1(seriesModel) { + var coordSys = seriesModel.coordinateSystem; + if (coordSys && coordSys.type !== 'view') { + return; + } + + var rect = coordSys.getBoundingRect(); + + var nodeData = seriesModel.getData(); + var graph = nodeData.graph; + + var angle = 0; + var sum = nodeData.getSum('value'); + var unitAngle = Math.PI * 2 / (sum || nodeData.count()); + + var cx = rect.width / 2 + rect.x; + var cy = rect.height / 2 + rect.y; + + var r = Math.min(rect.width, rect.height) / 2; + + graph.eachNode(function (node) { + var value = node.getValue('value'); + + angle += unitAngle * (sum ? value : 1) / 2; + + node.setLayout([ + r * Math.cos(angle) + cx, + r * Math.sin(angle) + cy + ]); + + angle += unitAngle * (sum ? value : 1) / 2; + }); + + nodeData.setLayout({ + cx: cx, + cy: cy + }); + + graph.eachEdge(function (edge) { + var curveness = edge.getModel().get('lineStyle.curveness') || 0; + var p1 = clone$1(edge.node1.getLayout()); + var p2 = clone$1(edge.node2.getLayout()); + var cp1; + var x12 = (p1[0] + p2[0]) / 2; + var y12 = (p1[1] + p2[1]) / 2; + if (+curveness) { + curveness *= 3; + cp1 = [ + cx * curveness + x12 * (1 - curveness), + cy * curveness + y12 * (1 - curveness) + ]; + } + edge.setLayout([p1, p2, cp1]); + }); +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var circularLayout = function (ecModel) { + ecModel.eachSeriesByType('graph', function (seriesModel) { + if (seriesModel.get('layout') === 'circular') { + circularLayout$1(seriesModel); + } + }); +}; + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/* +* A third-party license is embeded for some of the code in this file: +* Some formulas were originally copied from "d3.js" with some +* modifications made for this project. +* (See more details in the comment of the method "step" below.) +* The use of the source code of this file is also subject to the terms +* and consitions of the license of "d3.js" (BSD-3Clause, see +* ). +*/ + +var scaleAndAdd$2 = scaleAndAdd; + +// function adjacentNode(n, e) { +// return e.n1 === n ? e.n2 : e.n1; +// } + +function forceLayout$1(nodes, edges, opts) { + var rect = opts.rect; + var width = rect.width; + var height = rect.height; + var center = [rect.x + width / 2, rect.y + height / 2]; + // var scale = opts.scale || 1; + var gravity = opts.gravity == null ? 0.1 : opts.gravity; + + // for (var i = 0; i < edges.length; i++) { + // var e = edges[i]; + // var n1 = e.n1; + // var n2 = e.n2; + // n1.edges = n1.edges || []; + // n2.edges = n2.edges || []; + // n1.edges.push(e); + // n2.edges.push(e); + // } + // Init position + for (var i = 0; i < nodes.length; i++) { + var n = nodes[i]; + if (!n.p) { + n.p = create( + width * (Math.random() - 0.5) + center[0], + height * (Math.random() - 0.5) + center[1] + ); + } + n.pp = clone$1(n.p); + n.edges = null; + } + + // Formula in 'Graph Drawing by Force-directed Placement' + // var k = scale * Math.sqrt(width * height / nodes.length); + // var k2 = k * k; + + var friction = 0.6; + + return { + warmUp: function () { + friction = 0.5; + }, + + setFixed: function (idx) { + nodes[idx].fixed = true; + }, + + setUnfixed: function (idx) { + nodes[idx].fixed = false; + }, + + /** + * Some formulas were originally copied from "d3.js" + * https://github.com/d3/d3/blob/b516d77fb8566b576088e73410437494717ada26/src/layout/force.js + * with some modifications made for this project. + * See the license statement at the head of this file. + */ + step: function (cb) { + var v12 = []; + var nLen = nodes.length; + for (var i = 0; i < edges.length; i++) { + var e = edges[i]; + var n1 = e.n1; + var n2 = e.n2; + + sub(v12, n2.p, n1.p); + var d = len(v12) - e.d; + var w = n2.w / (n1.w + n2.w); + + if (isNaN(w)) { + w = 0; + } + + normalize(v12, v12); + + !n1.fixed && scaleAndAdd$2(n1.p, n1.p, v12, w * d * friction); + !n2.fixed && scaleAndAdd$2(n2.p, n2.p, v12, -(1 - w) * d * friction); + } + // Gravity + for (var i = 0; i < nLen; i++) { + var n = nodes[i]; + if (!n.fixed) { + sub(v12, center, n.p); + // var d = vec2.len(v12); + // vec2.scale(v12, v12, 1 / d); + // var gravityFactor = gravity; + scaleAndAdd$2(n.p, n.p, v12, gravity * friction); + } + } + + // Repulsive + // PENDING + for (var i = 0; i < nLen; i++) { + var n1 = nodes[i]; + for (var j = i + 1; j < nLen; j++) { + var n2 = nodes[j]; + sub(v12, n2.p, n1.p); + var d = len(v12); + if (d === 0) { + // Random repulse + set(v12, Math.random() - 0.5, Math.random() - 0.5); + d = 1; + } + var repFact = (n1.rep + n2.rep) / d / d; + !n1.fixed && scaleAndAdd$2(n1.pp, n1.pp, v12, repFact); + !n2.fixed && scaleAndAdd$2(n2.pp, n2.pp, v12, -repFact); + } + } + var v = []; + for (var i = 0; i < nLen; i++) { + var n = nodes[i]; + if (!n.fixed) { + sub(v, n.p, n.pp); + scaleAndAdd$2(n.p, n.p, v, friction); + copy(n.pp, n.p); + } + } + + friction = friction * 0.992; + + cb && cb(nodes, edges, friction < 0.01); + } + }; +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var forceLayout = function (ecModel) { + ecModel.eachSeriesByType('graph', function (graphSeries) { + var coordSys = graphSeries.coordinateSystem; + if (coordSys && coordSys.type !== 'view') { + return; + } + if (graphSeries.get('layout') === 'force') { + var preservedPoints = graphSeries.preservedPoints || {}; + var graph = graphSeries.getGraph(); + var nodeData = graph.data; + var edgeData = graph.edgeData; + var forceModel = graphSeries.getModel('force'); + var initLayout = forceModel.get('initLayout'); + if (graphSeries.preservedPoints) { + nodeData.each(function (idx) { + var id = nodeData.getId(idx); + nodeData.setItemLayout(idx, preservedPoints[id] || [NaN, NaN]); + }); + } + else if (!initLayout || initLayout === 'none') { + simpleLayout$1(graphSeries); + } + else if (initLayout === 'circular') { + circularLayout$1(graphSeries); + } + + var nodeDataExtent = nodeData.getDataExtent('value'); + var edgeDataExtent = edgeData.getDataExtent('value'); + // var edgeDataExtent = edgeData.getDataExtent('value'); + var repulsion = forceModel.get('repulsion'); + var edgeLength = forceModel.get('edgeLength'); + if (!isArray(repulsion)) { + repulsion = [repulsion, repulsion]; + } + if (!isArray(edgeLength)) { + edgeLength = [edgeLength, edgeLength]; + } + // Larger value has smaller length + edgeLength = [edgeLength[1], edgeLength[0]]; + + var nodes = nodeData.mapArray('value', function (value, idx) { + var point = nodeData.getItemLayout(idx); + var rep = linearMap(value, nodeDataExtent, repulsion); + if (isNaN(rep)) { + rep = (repulsion[0] + repulsion[1]) / 2; + } + return { + w: rep, + rep: rep, + fixed: nodeData.getItemModel(idx).get('fixed'), + p: (!point || isNaN(point[0]) || isNaN(point[1])) ? null : point + }; + }); + var edges = edgeData.mapArray('value', function (value, idx) { + var edge = graph.getEdgeByIndex(idx); + var d = linearMap(value, edgeDataExtent, edgeLength); + if (isNaN(d)) { + d = (edgeLength[0] + edgeLength[1]) / 2; + } + return { + n1: nodes[edge.node1.dataIndex], + n2: nodes[edge.node2.dataIndex], + d: d, + curveness: edge.getModel().get('lineStyle.curveness') || 0 + }; + }); + + var coordSys = graphSeries.coordinateSystem; + var rect = coordSys.getBoundingRect(); + var forceInstance = forceLayout$1(nodes, edges, { + rect: rect, + gravity: forceModel.get('gravity') + }); + var oldStep = forceInstance.step; + forceInstance.step = function (cb) { + for (var i = 0, l = nodes.length; i < l; i++) { + if (nodes[i].fixed) { + // Write back to layout instance + copy(nodes[i].p, graph.getNodeByIndex(i).getLayout()); + } + } + oldStep(function (nodes, edges, stopped) { + for (var i = 0, l = nodes.length; i < l; i++) { + if (!nodes[i].fixed) { + graph.getNodeByIndex(i).setLayout(nodes[i].p); + } + preservedPoints[nodeData.getId(i)] = nodes[i].p; + } + for (var i = 0, l = edges.length; i < l; i++) { + var e = edges[i]; + var edge = graph.getEdgeByIndex(i); + var p1 = e.n1.p; + var p2 = e.n2.p; + var points = edge.getLayout(); + points = points ? points.slice() : []; + points[0] = points[0] || []; + points[1] = points[1] || []; + copy(points[0], p1); + copy(points[1], p2); + if (+e.curveness) { + points[2] = [ + (p1[0] + p2[0]) / 2 - (p1[1] - p2[1]) * e.curveness, + (p1[1] + p2[1]) / 2 - (p2[0] - p1[0]) * e.curveness + ]; + } + edge.setLayout(points); + } + // Update layout + + cb && cb(stopped); + }); + }; + graphSeries.forceLayout = forceInstance; + graphSeries.preservedPoints = preservedPoints; + + // Step to get the layout + forceInstance.step(); + } + else { + // Remove prev injected forceLayout instance + graphSeries.forceLayout = null; + } + }); +}; + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +// FIXME Where to create the simple view coordinate system +function getViewRect$1(seriesModel, api, aspect) { + var option = seriesModel.getBoxLayoutParams(); + option.aspect = aspect; + return getLayoutRect(option, { + width: api.getWidth(), + height: api.getHeight() + }); +} + +var createView = function (ecModel, api) { + var viewList = []; + ecModel.eachSeriesByType('graph', function (seriesModel) { + var coordSysType = seriesModel.get('coordinateSystem'); + if (!coordSysType || coordSysType === 'view') { + + var data = seriesModel.getData(); + var positions = data.mapArray(function (idx) { + var itemModel = data.getItemModel(idx); + return [+itemModel.get('x'), +itemModel.get('y')]; + }); + + var min = []; + var max = []; + + fromPoints(positions, min, max); + + // If width or height is 0 + if (max[0] - min[0] === 0) { + max[0] += 1; + min[0] -= 1; + } + if (max[1] - min[1] === 0) { + max[1] += 1; + min[1] -= 1; + } + var aspect = (max[0] - min[0]) / (max[1] - min[1]); + // FIXME If get view rect after data processed? + var viewRect = getViewRect$1(seriesModel, api, aspect); + // Position may be NaN, use view rect instead + if (isNaN(aspect)) { + min = [viewRect.x, viewRect.y]; + max = [viewRect.x + viewRect.width, viewRect.y + viewRect.height]; + } + + var bbWidth = max[0] - min[0]; + var bbHeight = max[1] - min[1]; + + var viewWidth = viewRect.width; + var viewHeight = viewRect.height; + + var viewCoordSys = seriesModel.coordinateSystem = new View(); + viewCoordSys.zoomLimit = seriesModel.get('scaleLimit'); + + viewCoordSys.setBoundingRect( + min[0], min[1], bbWidth, bbHeight + ); + viewCoordSys.setViewRect( + viewRect.x, viewRect.y, viewWidth, viewHeight + ); + + // Update roam info + viewCoordSys.setCenter(seriesModel.get('center')); + viewCoordSys.setZoom(seriesModel.get('zoom')); + + viewList.push(viewCoordSys); + } + }); + + return viewList; +}; + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +registerProcessor(categoryFilter); + +registerVisual(visualSymbol('graph', 'circle', null)); +registerVisual(categoryVisual); +registerVisual(edgeVisual); + +registerLayout(simpleLayout); +registerLayout(circularLayout); +registerLayout(forceLayout); + +// Graph view coordinate system +registerCoordinateSystem('graphView', { + create: createView +}); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var GaugeSeries = SeriesModel.extend({ + + type: 'series.gauge', + + getInitialData: function (option, ecModel) { + var dataOpt = option.data || []; + if (!isArray(dataOpt)) { + dataOpt = [dataOpt]; + } + option.data = dataOpt; + return createListSimply(this, ['value']); + }, + + defaultOption: { + zlevel: 0, + z: 2, + // 默认全局居中 + center: ['50%', '50%'], + legendHoverLink: true, + radius: '75%', + startAngle: 225, + endAngle: -45, + clockwise: true, + // 最小值 + min: 0, + // 最大值 + max: 100, + // 分割段数,默认为10 + splitNumber: 10, + // 坐标轴线 + axisLine: { + // 默认显示,属性show控制显示与否 + show: true, + lineStyle: { // 属性lineStyle控制线条样式 + color: [[0.2, '#91c7ae'], [0.8, '#63869e'], [1, '#c23531']], + width: 30 + } + }, + // 分隔线 + splitLine: { + // 默认显示,属性show控制显示与否 + show: true, + // 属性length控制线长 + length: 30, + // 属性lineStyle(详见lineStyle)控制线条样式 + lineStyle: { + color: '#eee', + width: 2, + type: 'solid' + } + }, + // 坐标轴小标记 + axisTick: { + // 属性show控制显示与否,默认不显示 + show: true, + // 每份split细分多少段 + splitNumber: 5, + // 属性length控制线长 + length: 8, + // 属性lineStyle控制线条样式 + lineStyle: { + color: '#eee', + width: 1, + type: 'solid' + } + }, + axisLabel: { + show: true, + distance: 5, + // formatter: null, + color: 'auto' + }, + pointer: { + show: true, + length: '80%', + width: 8 + }, + itemStyle: { + color: 'auto' + }, + title: { + show: true, + // x, y,单位px + offsetCenter: [0, '-40%'], + // 其余属性默认使用全局文本样式,详见TEXTSTYLE + color: '#333', + fontSize: 15 + }, + detail: { + show: true, + backgroundColor: 'rgba(0,0,0,0)', + borderWidth: 0, + borderColor: '#ccc', + width: 100, + height: null, // self-adaption + padding: [5, 10], + // x, y,单位px + offsetCenter: [0, '40%'], + // formatter: null, + // 其余属性默认使用全局文本样式,详见TEXTSTYLE + color: 'auto', + fontSize: 30 + } + } +}); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var PointerPath = Path.extend({ + + type: 'echartsGaugePointer', + + shape: { + angle: 0, + + width: 10, + + r: 10, + + x: 0, + + y: 0 + }, + + buildPath: function (ctx, shape) { + var mathCos = Math.cos; + var mathSin = Math.sin; + + var r = shape.r; + var width = shape.width; + var angle = shape.angle; + var x = shape.x - mathCos(angle) * width * (width >= r / 3 ? 1 : 2); + var y = shape.y - mathSin(angle) * width * (width >= r / 3 ? 1 : 2); + + angle = shape.angle - Math.PI / 2; + ctx.moveTo(x, y); + ctx.lineTo( + shape.x + mathCos(angle) * width, + shape.y + mathSin(angle) * width + ); + ctx.lineTo( + shape.x + mathCos(shape.angle) * r, + shape.y + mathSin(shape.angle) * r + ); + ctx.lineTo( + shape.x - mathCos(angle) * width, + shape.y - mathSin(angle) * width + ); + ctx.lineTo(x, y); + return; + } +}); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +function parsePosition(seriesModel, api) { + var center = seriesModel.get('center'); + var width = api.getWidth(); + var height = api.getHeight(); + var size = Math.min(width, height); + var cx = parsePercent$1(center[0], api.getWidth()); + var cy = parsePercent$1(center[1], api.getHeight()); + var r = parsePercent$1(seriesModel.get('radius'), size / 2); + + return { + cx: cx, + cy: cy, + r: r + }; +} + +function formatLabel(label, labelFormatter) { + if (labelFormatter) { + if (typeof labelFormatter === 'string') { + label = labelFormatter.replace('{value}', label != null ? label : ''); + } + else if (typeof labelFormatter === 'function') { + label = labelFormatter(label); + } + } + + return label; +} + +var PI2$5 = Math.PI * 2; + +var GaugeView = Chart.extend({ + + type: 'gauge', + + render: function (seriesModel, ecModel, api) { + + this.group.removeAll(); + + var colorList = seriesModel.get('axisLine.lineStyle.color'); + var posInfo = parsePosition(seriesModel, api); + + this._renderMain( + seriesModel, ecModel, api, colorList, posInfo + ); + }, + + dispose: function () {}, + + _renderMain: function (seriesModel, ecModel, api, colorList, posInfo) { + var group = this.group; + + var axisLineModel = seriesModel.getModel('axisLine'); + var lineStyleModel = axisLineModel.getModel('lineStyle'); + + var clockwise = seriesModel.get('clockwise'); + var startAngle = -seriesModel.get('startAngle') / 180 * Math.PI; + var endAngle = -seriesModel.get('endAngle') / 180 * Math.PI; + + var angleRangeSpan = (endAngle - startAngle) % PI2$5; + + var prevEndAngle = startAngle; + var axisLineWidth = lineStyleModel.get('width'); + + for (var i = 0; i < colorList.length; i++) { + // Clamp + var percent = Math.min(Math.max(colorList[i][0], 0), 1); + var endAngle = startAngle + angleRangeSpan * percent; + var sector = new Sector({ + shape: { + startAngle: prevEndAngle, + endAngle: endAngle, + cx: posInfo.cx, + cy: posInfo.cy, + clockwise: clockwise, + r0: posInfo.r - axisLineWidth, + r: posInfo.r + }, + silent: true + }); + + sector.setStyle({ + fill: colorList[i][1] + }); + + sector.setStyle(lineStyleModel.getLineStyle( + // Because we use sector to simulate arc + // so the properties for stroking are useless + ['color', 'borderWidth', 'borderColor'] + )); + + group.add(sector); + + prevEndAngle = endAngle; + } + + var getColor = function (percent) { + // Less than 0 + if (percent <= 0) { + return colorList[0][1]; + } + for (var i = 0; i < colorList.length; i++) { + if (colorList[i][0] >= percent + && (i === 0 ? 0 : colorList[i - 1][0]) < percent + ) { + return colorList[i][1]; + } + } + // More than 1 + return colorList[i - 1][1]; + }; + + if (!clockwise) { + var tmp = startAngle; + startAngle = endAngle; + endAngle = tmp; + } + + this._renderTicks( + seriesModel, ecModel, api, getColor, posInfo, + startAngle, endAngle, clockwise + ); + + this._renderPointer( + seriesModel, ecModel, api, getColor, posInfo, + startAngle, endAngle, clockwise + ); + + this._renderTitle( + seriesModel, ecModel, api, getColor, posInfo + ); + this._renderDetail( + seriesModel, ecModel, api, getColor, posInfo + ); + }, + + _renderTicks: function ( + seriesModel, ecModel, api, getColor, posInfo, + startAngle, endAngle, clockwise + ) { + var group = this.group; + var cx = posInfo.cx; + var cy = posInfo.cy; + var r = posInfo.r; + + var minVal = +seriesModel.get('min'); + var maxVal = +seriesModel.get('max'); + + var splitLineModel = seriesModel.getModel('splitLine'); + var tickModel = seriesModel.getModel('axisTick'); + var labelModel = seriesModel.getModel('axisLabel'); + + var splitNumber = seriesModel.get('splitNumber'); + var subSplitNumber = tickModel.get('splitNumber'); + + var splitLineLen = parsePercent$1( + splitLineModel.get('length'), r + ); + var tickLen = parsePercent$1( + tickModel.get('length'), r + ); + + var angle = startAngle; + var step = (endAngle - startAngle) / splitNumber; + var subStep = step / subSplitNumber; + + var splitLineStyle = splitLineModel.getModel('lineStyle').getLineStyle(); + var tickLineStyle = tickModel.getModel('lineStyle').getLineStyle(); + + for (var i = 0; i <= splitNumber; i++) { + var unitX = Math.cos(angle); + var unitY = Math.sin(angle); + // Split line + if (splitLineModel.get('show')) { + var splitLine = new Line({ + shape: { + x1: unitX * r + cx, + y1: unitY * r + cy, + x2: unitX * (r - splitLineLen) + cx, + y2: unitY * (r - splitLineLen) + cy + }, + style: splitLineStyle, + silent: true + }); + if (splitLineStyle.stroke === 'auto') { + splitLine.setStyle({ + stroke: getColor(i / splitNumber) + }); + } + + group.add(splitLine); + } + + // Label + if (labelModel.get('show')) { + var label = formatLabel( + round$2(i / splitNumber * (maxVal - minVal) + minVal), + labelModel.get('formatter') + ); + var distance = labelModel.get('distance'); + var autoColor = getColor(i / splitNumber); + + group.add(new Text({ + style: setTextStyle({}, labelModel, { + text: label, + x: unitX * (r - splitLineLen - distance) + cx, + y: unitY * (r - splitLineLen - distance) + cy, + textVerticalAlign: unitY < -0.4 ? 'top' : (unitY > 0.4 ? 'bottom' : 'middle'), + textAlign: unitX < -0.4 ? 'left' : (unitX > 0.4 ? 'right' : 'center') + }, {autoColor: autoColor}), + silent: true + })); + } + + // Axis tick + if (tickModel.get('show') && i !== splitNumber) { + for (var j = 0; j <= subSplitNumber; j++) { + var unitX = Math.cos(angle); + var unitY = Math.sin(angle); + var tickLine = new Line({ + shape: { + x1: unitX * r + cx, + y1: unitY * r + cy, + x2: unitX * (r - tickLen) + cx, + y2: unitY * (r - tickLen) + cy + }, + silent: true, + style: tickLineStyle + }); + + if (tickLineStyle.stroke === 'auto') { + tickLine.setStyle({ + stroke: getColor((i + j / subSplitNumber) / splitNumber) + }); + } + + group.add(tickLine); + angle += subStep; + } + angle -= subStep; + } + else { + angle += step; + } + } + }, + + _renderPointer: function ( + seriesModel, ecModel, api, getColor, posInfo, + startAngle, endAngle, clockwise + ) { + + var group = this.group; + var oldData = this._data; + + if (!seriesModel.get('pointer.show')) { + // Remove old element + oldData && oldData.eachItemGraphicEl(function (el) { + group.remove(el); + }); + return; + } + + var valueExtent = [+seriesModel.get('min'), +seriesModel.get('max')]; + var angleExtent = [startAngle, endAngle]; + + var data = seriesModel.getData(); + var valueDim = data.mapDimension('value'); + + data.diff(oldData) + .add(function (idx) { + var pointer = new PointerPath({ + shape: { + angle: startAngle + } + }); + + initProps(pointer, { + shape: { + angle: linearMap(data.get(valueDim, idx), valueExtent, angleExtent, true) + } + }, seriesModel); + + group.add(pointer); + data.setItemGraphicEl(idx, pointer); + }) + .update(function (newIdx, oldIdx) { + var pointer = oldData.getItemGraphicEl(oldIdx); + + updateProps(pointer, { + shape: { + angle: linearMap(data.get(valueDim, newIdx), valueExtent, angleExtent, true) + } + }, seriesModel); + + group.add(pointer); + data.setItemGraphicEl(newIdx, pointer); + }) + .remove(function (idx) { + var pointer = oldData.getItemGraphicEl(idx); + group.remove(pointer); + }) + .execute(); + + data.eachItemGraphicEl(function (pointer, idx) { + var itemModel = data.getItemModel(idx); + var pointerModel = itemModel.getModel('pointer'); + + pointer.setShape({ + x: posInfo.cx, + y: posInfo.cy, + width: parsePercent$1( + pointerModel.get('width'), posInfo.r + ), + r: parsePercent$1(pointerModel.get('length'), posInfo.r) + }); + + pointer.useStyle(itemModel.getModel('itemStyle').getItemStyle()); + + if (pointer.style.fill === 'auto') { + pointer.setStyle('fill', getColor( + linearMap(data.get(valueDim, idx), valueExtent, [0, 1], true) + )); + } + + setHoverStyle( + pointer, itemModel.getModel('emphasis.itemStyle').getItemStyle() + ); + }); + + this._data = data; + }, + + _renderTitle: function ( + seriesModel, ecModel, api, getColor, posInfo + ) { + var data = seriesModel.getData(); + var valueDim = data.mapDimension('value'); + var titleModel = seriesModel.getModel('title'); + if (titleModel.get('show')) { + var offsetCenter = titleModel.get('offsetCenter'); + var x = posInfo.cx + parsePercent$1(offsetCenter[0], posInfo.r); + var y = posInfo.cy + parsePercent$1(offsetCenter[1], posInfo.r); + + var minVal = +seriesModel.get('min'); + var maxVal = +seriesModel.get('max'); + var value = seriesModel.getData().get(valueDim, 0); + var autoColor = getColor( + linearMap(value, [minVal, maxVal], [0, 1], true) + ); + + this.group.add(new Text({ + silent: true, + style: setTextStyle({}, titleModel, { + x: x, + y: y, + // FIXME First data name ? + text: data.getName(0), + textAlign: 'center', + textVerticalAlign: 'middle' + }, {autoColor: autoColor, forceRich: true}) + })); + } + }, + + _renderDetail: function ( + seriesModel, ecModel, api, getColor, posInfo + ) { + var detailModel = seriesModel.getModel('detail'); + var minVal = +seriesModel.get('min'); + var maxVal = +seriesModel.get('max'); + if (detailModel.get('show')) { + var offsetCenter = detailModel.get('offsetCenter'); + var x = posInfo.cx + parsePercent$1(offsetCenter[0], posInfo.r); + var y = posInfo.cy + parsePercent$1(offsetCenter[1], posInfo.r); + var width = parsePercent$1(detailModel.get('width'), posInfo.r); + var height = parsePercent$1(detailModel.get('height'), posInfo.r); + var data = seriesModel.getData(); + var value = data.get(data.mapDimension('value'), 0); + var autoColor = getColor( + linearMap(value, [minVal, maxVal], [0, 1], true) + ); + + this.group.add(new Text({ + silent: true, + style: setTextStyle({}, detailModel, { + x: x, + y: y, + text: formatLabel( + // FIXME First data name ? + value, detailModel.get('formatter') + ), + textWidth: isNaN(width) ? null : width, + textHeight: isNaN(height) ? null : height, + textAlign: 'center', + textVerticalAlign: 'middle' + }, {autoColor: autoColor, forceRich: true}) + })); + } + } +}); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var FunnelSeries = extendSeriesModel({ + + type: 'series.funnel', + + init: function (option) { + FunnelSeries.superApply(this, 'init', arguments); + + // Enable legend selection for each data item + // Use a function instead of direct access because data reference may changed + this.legendDataProvider = function () { + return this.getRawData(); + }; + // Extend labelLine emphasis + this._defaultLabelLine(option); + }, + + getInitialData: function (option, ecModel) { + return createListSimply(this, ['value']); + }, + + _defaultLabelLine: function (option) { + // Extend labelLine emphasis + defaultEmphasis(option, 'labelLine', ['show']); + + var labelLineNormalOpt = option.labelLine; + var labelLineEmphasisOpt = option.emphasis.labelLine; + // Not show label line if `label.normal.show = false` + labelLineNormalOpt.show = labelLineNormalOpt.show + && option.label.show; + labelLineEmphasisOpt.show = labelLineEmphasisOpt.show + && option.emphasis.label.show; + }, + + // Overwrite + getDataParams: function (dataIndex) { + var data = this.getData(); + var params = FunnelSeries.superCall(this, 'getDataParams', dataIndex); + var valueDim = data.mapDimension('value'); + var sum = data.getSum(valueDim); + // Percent is 0 if sum is 0 + params.percent = !sum ? 0 : +(data.get(valueDim, dataIndex) / sum * 100).toFixed(2); + + params.$vars.push('percent'); + return params; + }, + + defaultOption: { + zlevel: 0, // 一级层叠 + z: 2, // 二级层叠 + legendHoverLink: true, + left: 80, + top: 60, + right: 80, + bottom: 60, + // width: {totalWidth} - left - right, + // height: {totalHeight} - top - bottom, + + // 默认取数据最小最大值 + // min: 0, + // max: 100, + minSize: '0%', + maxSize: '100%', + sort: 'descending', // 'ascending', 'descending' + gap: 0, + funnelAlign: 'center', + label: { + show: true, + position: 'outer' + // formatter: 标签文本格式器,同Tooltip.formatter,不支持异步回调 + }, + labelLine: { + show: true, + length: 20, + lineStyle: { + // color: 各异, + width: 1, + type: 'solid' + } + }, + itemStyle: { + // color: 各异, + borderColor: '#fff', + borderWidth: 1 + }, + emphasis: { + label: { + show: true + } + } + } +}); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/** + * Piece of pie including Sector, Label, LabelLine + * @constructor + * @extends {module:zrender/graphic/Group} + */ +function FunnelPiece(data, idx) { + + Group.call(this); + + var polygon = new Polygon(); + var labelLine = new Polyline(); + var text = new Text(); + this.add(polygon); + this.add(labelLine); + this.add(text); + + this.updateData(data, idx, true); + + // Hover to change label and labelLine + function onEmphasis() { + labelLine.ignore = labelLine.hoverIgnore; + text.ignore = text.hoverIgnore; + } + function onNormal() { + labelLine.ignore = labelLine.normalIgnore; + text.ignore = text.normalIgnore; + } + this.on('emphasis', onEmphasis) + .on('normal', onNormal) + .on('mouseover', onEmphasis) + .on('mouseout', onNormal); +} + +var funnelPieceProto = FunnelPiece.prototype; + +var opacityAccessPath = ['itemStyle', 'opacity']; +funnelPieceProto.updateData = function (data, idx, firstCreate) { + + var polygon = this.childAt(0); + + var seriesModel = data.hostModel; + var itemModel = data.getItemModel(idx); + var layout = data.getItemLayout(idx); + var opacity = data.getItemModel(idx).get(opacityAccessPath); + opacity = opacity == null ? 1 : opacity; + + // Reset style + polygon.useStyle({}); + + if (firstCreate) { + polygon.setShape({ + points: layout.points + }); + polygon.setStyle({opacity: 0}); + initProps(polygon, { + style: { + opacity: opacity + } + }, seriesModel, idx); + } + else { + updateProps(polygon, { + style: { + opacity: opacity + }, + shape: { + points: layout.points + } + }, seriesModel, idx); + } + + // Update common style + var itemStyleModel = itemModel.getModel('itemStyle'); + var visualColor = data.getItemVisual(idx, 'color'); + + polygon.setStyle( + defaults( + { + lineJoin: 'round', + fill: visualColor + }, + itemStyleModel.getItemStyle(['opacity']) + ) + ); + polygon.hoverStyle = itemStyleModel.getModel('emphasis').getItemStyle(); + + this._updateLabel(data, idx); + + setHoverStyle(this); +}; + +funnelPieceProto._updateLabel = function (data, idx) { + + var labelLine = this.childAt(1); + var labelText = this.childAt(2); + + var seriesModel = data.hostModel; + var itemModel = data.getItemModel(idx); + var layout = data.getItemLayout(idx); + var labelLayout = layout.label; + var visualColor = data.getItemVisual(idx, 'color'); + + updateProps(labelLine, { + shape: { + points: labelLayout.linePoints || labelLayout.linePoints + } + }, seriesModel, idx); + + updateProps(labelText, { + style: { + x: labelLayout.x, + y: labelLayout.y + } + }, seriesModel, idx); + labelText.attr({ + rotation: labelLayout.rotation, + origin: [labelLayout.x, labelLayout.y], + z2: 10 + }); + + var labelModel = itemModel.getModel('label'); + var labelHoverModel = itemModel.getModel('emphasis.label'); + var labelLineModel = itemModel.getModel('labelLine'); + var labelLineHoverModel = itemModel.getModel('emphasis.labelLine'); + var visualColor = data.getItemVisual(idx, 'color'); + + setLabelStyle( + labelText.style, labelText.hoverStyle = {}, labelModel, labelHoverModel, + { + labelFetcher: data.hostModel, + labelDataIndex: idx, + defaultText: data.getName(idx), + autoColor: visualColor, + useInsideStyle: !!labelLayout.inside + }, + { + textAlign: labelLayout.textAlign, + textVerticalAlign: labelLayout.verticalAlign + } + ); + + labelText.ignore = labelText.normalIgnore = !labelModel.get('show'); + labelText.hoverIgnore = !labelHoverModel.get('show'); + + labelLine.ignore = labelLine.normalIgnore = !labelLineModel.get('show'); + labelLine.hoverIgnore = !labelLineHoverModel.get('show'); + + // Default use item visual color + labelLine.setStyle({ + stroke: visualColor + }); + labelLine.setStyle(labelLineModel.getModel('lineStyle').getLineStyle()); + + labelLine.hoverStyle = labelLineHoverModel.getModel('lineStyle').getLineStyle(); +}; + +inherits(FunnelPiece, Group); + + +var FunnelView = Chart.extend({ + + type: 'funnel', + + render: function (seriesModel, ecModel, api) { + var data = seriesModel.getData(); + var oldData = this._data; + + var group = this.group; + + data.diff(oldData) + .add(function (idx) { + var funnelPiece = new FunnelPiece(data, idx); + + data.setItemGraphicEl(idx, funnelPiece); + + group.add(funnelPiece); + }) + .update(function (newIdx, oldIdx) { + var piePiece = oldData.getItemGraphicEl(oldIdx); + + piePiece.updateData(data, newIdx); + + group.add(piePiece); + data.setItemGraphicEl(newIdx, piePiece); + }) + .remove(function (idx) { + var piePiece = oldData.getItemGraphicEl(idx); + group.remove(piePiece); + }) + .execute(); + + this._data = data; + }, + + remove: function () { + this.group.removeAll(); + this._data = null; + }, + + dispose: function () {} +}); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +function getViewRect$2(seriesModel, api) { + return getLayoutRect( + seriesModel.getBoxLayoutParams(), { + width: api.getWidth(), + height: api.getHeight() + } + ); +} + +function getSortedIndices(data, sort) { + var valueDim = data.mapDimension('value'); + var valueArr = data.mapArray(valueDim, function (val) { + return val; + }); + var indices = []; + var isAscending = sort === 'ascending'; + for (var i = 0, len = data.count(); i < len; i++) { + indices[i] = i; + } + + // Add custom sortable function & none sortable opetion by "options.sort" + if (typeof sort === 'function') { + indices.sort(sort); + } + else if (sort !== 'none') { + indices.sort(function (a, b) { + return isAscending ? valueArr[a] - valueArr[b] : valueArr[b] - valueArr[a]; + }); + } + return indices; +} + +function labelLayout$1(data) { + data.each(function (idx) { + var itemModel = data.getItemModel(idx); + var labelModel = itemModel.getModel('label'); + var labelPosition = labelModel.get('position'); + + var labelLineModel = itemModel.getModel('labelLine'); + + var layout = data.getItemLayout(idx); + var points = layout.points; + + var isLabelInside = labelPosition === 'inner' + || labelPosition === 'inside' || labelPosition === 'center'; + + var textAlign; + var textX; + var textY; + var linePoints; + + if (isLabelInside) { + textX = (points[0][0] + points[1][0] + points[2][0] + points[3][0]) / 4; + textY = (points[0][1] + points[1][1] + points[2][1] + points[3][1]) / 4; + textAlign = 'center'; + linePoints = [ + [textX, textY], [textX, textY] + ]; + } + else { + var x1; + var y1; + var x2; + var labelLineLen = labelLineModel.get('length'); + if (labelPosition === 'left') { + // Left side + x1 = (points[3][0] + points[0][0]) / 2; + y1 = (points[3][1] + points[0][1]) / 2; + x2 = x1 - labelLineLen; + textX = x2 - 5; + textAlign = 'right'; + } + else { + // Right side + x1 = (points[1][0] + points[2][0]) / 2; + y1 = (points[1][1] + points[2][1]) / 2; + x2 = x1 + labelLineLen; + textX = x2 + 5; + textAlign = 'left'; + } + var y2 = y1; + + linePoints = [[x1, y1], [x2, y2]]; + textY = y2; + } + + layout.label = { + linePoints: linePoints, + x: textX, + y: textY, + verticalAlign: 'middle', + textAlign: textAlign, + inside: isLabelInside + }; + }); +} + +var funnelLayout = function (ecModel, api, payload) { + ecModel.eachSeriesByType('funnel', function (seriesModel) { + var data = seriesModel.getData(); + var valueDim = data.mapDimension('value'); + var sort = seriesModel.get('sort'); + var viewRect = getViewRect$2(seriesModel, api); + var indices = getSortedIndices(data, sort); + + var sizeExtent = [ + parsePercent$1(seriesModel.get('minSize'), viewRect.width), + parsePercent$1(seriesModel.get('maxSize'), viewRect.width) + ]; + var dataExtent = data.getDataExtent(valueDim); + var min = seriesModel.get('min'); + var max = seriesModel.get('max'); + if (min == null) { + min = Math.min(dataExtent[0], 0); + } + if (max == null) { + max = dataExtent[1]; + } + + var funnelAlign = seriesModel.get('funnelAlign'); + var gap = seriesModel.get('gap'); + var itemHeight = (viewRect.height - gap * (data.count() - 1)) / data.count(); + + var y = viewRect.y; + + var getLinePoints = function (idx, offY) { + // End point index is data.count() and we assign it 0 + var val = data.get(valueDim, idx) || 0; + var itemWidth = linearMap(val, [min, max], sizeExtent, true); + var x0; + switch (funnelAlign) { + case 'left': + x0 = viewRect.x; + break; + case 'center': + x0 = viewRect.x + (viewRect.width - itemWidth) / 2; + break; + case 'right': + x0 = viewRect.x + viewRect.width - itemWidth; + break; + } + return [ + [x0, offY], + [x0 + itemWidth, offY] + ]; + }; + + if (sort === 'ascending') { + // From bottom to top + itemHeight = -itemHeight; + gap = -gap; + y += viewRect.height; + indices = indices.reverse(); + } + + for (var i = 0; i < indices.length; i++) { + var idx = indices[i]; + var nextIdx = indices[i + 1]; + + var itemModel = data.getItemModel(idx); + var height = itemModel.get('itemStyle.height'); + if (height == null) { + height = itemHeight; + } + else { + height = parsePercent$1(height, viewRect.height); + if (sort === 'ascending') { + height = -height; + } + } + + var start = getLinePoints(idx, y); + var end = getLinePoints(nextIdx, y + height); + + y += height + gap; + + data.setItemLayout(idx, { + points: start.concat(end.slice().reverse()) + }); + } + + labelLayout$1(data); + }); +}; + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +registerVisual(dataColor('funnel')); +registerLayout(funnelLayout); +registerProcessor(dataFilter('funnel')); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var parallelPreprocessor = function (option) { + createParallelIfNeeded(option); + mergeAxisOptionFromParallel(option); +}; + +/** + * Create a parallel coordinate if not exists. + * @inner + */ +function createParallelIfNeeded(option) { + if (option.parallel) { + return; + } + + var hasParallelSeries = false; + + each$1(option.series, function (seriesOpt) { + if (seriesOpt && seriesOpt.type === 'parallel') { + hasParallelSeries = true; + } + }); + + if (hasParallelSeries) { + option.parallel = [{}]; + } +} + +/** + * Merge aixs definition from parallel option (if exists) to axis option. + * @inner + */ +function mergeAxisOptionFromParallel(option) { + var axes = normalizeToArray(option.parallelAxis); + + each$1(axes, function (axisOption) { + if (!isObject$1(axisOption)) { + return; + } + + var parallelIndex = axisOption.parallelIndex || 0; + var parallelOption = normalizeToArray(option.parallel)[parallelIndex]; + + if (parallelOption && parallelOption.parallelAxisDefault) { + merge(axisOption, parallelOption.parallelAxisDefault, false); + } + }); +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/** + * @constructor module:echarts/coord/parallel/ParallelAxis + * @extends {module:echarts/coord/Axis} + * @param {string} dim + * @param {*} scale + * @param {Array.} coordExtent + * @param {string} axisType + */ +var ParallelAxis = function (dim, scale, coordExtent, axisType, axisIndex) { + + Axis.call(this, dim, scale, coordExtent); + + /** + * Axis type + * - 'category' + * - 'value' + * - 'time' + * - 'log' + * @type {string} + */ + this.type = axisType || 'value'; + + /** + * @type {number} + * @readOnly + */ + this.axisIndex = axisIndex; +}; + +ParallelAxis.prototype = { + + constructor: ParallelAxis, + + /** + * Axis model + * @param {module:echarts/coord/parallel/AxisModel} + */ + model: null, + + /** + * @override + */ + isHorizontal: function () { + return this.coordinateSystem.getModel().get('layout') !== 'horizontal'; + } + +}; + +inherits(ParallelAxis, Axis); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/** + * Calculate slider move result. + * Usage: + * (1) If both handle0 and handle1 are needed to be moved, set minSpan the same as + * maxSpan and the same as `Math.abs(handleEnd[1] - handleEnds[0])`. + * (2) If handle0 is forbidden to cross handle1, set minSpan as `0`. + * + * @param {number} delta Move length. + * @param {Array.} handleEnds handleEnds[0] can be bigger then handleEnds[1]. + * handleEnds will be modified in this method. + * @param {Array.} extent handleEnds is restricted by extent. + * extent[0] should less or equals than extent[1]. + * @param {number|string} handleIndex Can be 'all', means that both move the two handleEnds, + * where the input minSpan and maxSpan will not work. + * @param {number} [minSpan] The range of dataZoom can not be smaller than that. + * If not set, handle0 and cross handle1. If set as a non-negative + * number (including `0`), handles will push each other when reaching + * the minSpan. + * @param {number} [maxSpan] The range of dataZoom can not be larger than that. + * @return {Array.} The input handleEnds. + */ +var sliderMove = function (delta, handleEnds, extent, handleIndex, minSpan, maxSpan) { + // Normalize firstly. + handleEnds[0] = restrict$1(handleEnds[0], extent); + handleEnds[1] = restrict$1(handleEnds[1], extent); + + delta = delta || 0; + + var extentSpan = extent[1] - extent[0]; + + // Notice maxSpan and minSpan can be null/undefined. + if (minSpan != null) { + minSpan = restrict$1(minSpan, [0, extentSpan]); + } + if (maxSpan != null) { + maxSpan = Math.max(maxSpan, minSpan != null ? minSpan : 0); + } + if (handleIndex === 'all') { + minSpan = maxSpan = Math.abs(handleEnds[1] - handleEnds[0]); + handleIndex = 0; + } + + var originalDistSign = getSpanSign(handleEnds, handleIndex); + + handleEnds[handleIndex] += delta; + + // Restrict in extent. + var extentMinSpan = minSpan || 0; + var realExtent = extent.slice(); + originalDistSign.sign < 0 ? (realExtent[0] += extentMinSpan) : (realExtent[1] -= extentMinSpan); + handleEnds[handleIndex] = restrict$1(handleEnds[handleIndex], realExtent); + + // Expand span. + var currDistSign = getSpanSign(handleEnds, handleIndex); + if (minSpan != null && ( + currDistSign.sign !== originalDistSign.sign || currDistSign.span < minSpan + )) { + // If minSpan exists, 'cross' is forbinden. + handleEnds[1 - handleIndex] = handleEnds[handleIndex] + originalDistSign.sign * minSpan; + } + + // Shrink span. + var currDistSign = getSpanSign(handleEnds, handleIndex); + if (maxSpan != null && currDistSign.span > maxSpan) { + handleEnds[1 - handleIndex] = handleEnds[handleIndex] + currDistSign.sign * maxSpan; + } + + return handleEnds; +}; + +function getSpanSign(handleEnds, handleIndex) { + var dist = handleEnds[handleIndex] - handleEnds[1 - handleIndex]; + // If `handleEnds[0] === handleEnds[1]`, always believe that handleEnd[0] + // is at left of handleEnds[1] for non-cross case. + return {span: Math.abs(dist), sign: dist > 0 ? -1 : dist < 0 ? 1 : handleIndex ? -1 : 1}; +} + +function restrict$1(value, extend) { + return Math.min(extend[1], Math.max(extend[0], value)); +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/** + * Parallel Coordinates + * + */ + +var each$11 = each$1; +var mathMin$5 = Math.min; +var mathMax$5 = Math.max; +var mathFloor$2 = Math.floor; +var mathCeil$2 = Math.ceil; +var round$3 = round$2; + +var PI$3 = Math.PI; + +function Parallel(parallelModel, ecModel, api) { + + /** + * key: dimension + * @type {Object.} + * @private + */ + this._axesMap = createHashMap(); + + /** + * key: dimension + * value: {position: [], rotation, } + * @type {Object.} + * @private + */ + this._axesLayout = {}; + + /** + * Always follow axis order. + * @type {Array.} + * @readOnly + */ + this.dimensions = parallelModel.dimensions; + + /** + * @type {module:zrender/core/BoundingRect} + */ + this._rect; + + /** + * @type {module:echarts/coord/parallel/ParallelModel} + */ + this._model = parallelModel; + + this._init(parallelModel, ecModel, api); +} + +Parallel.prototype = { + + type: 'parallel', + + constructor: Parallel, + + /** + * Initialize cartesian coordinate systems + * @private + */ + _init: function (parallelModel, ecModel, api) { + + var dimensions = parallelModel.dimensions; + var parallelAxisIndex = parallelModel.parallelAxisIndex; + + each$11(dimensions, function (dim, idx) { + + var axisIndex = parallelAxisIndex[idx]; + var axisModel = ecModel.getComponent('parallelAxis', axisIndex); + + var axis = this._axesMap.set(dim, new ParallelAxis( + dim, + createScaleByModel(axisModel), + [0, 0], + axisModel.get('type'), + axisIndex + )); + + var isCategory = axis.type === 'category'; + axis.onBand = isCategory && axisModel.get('boundaryGap'); + axis.inverse = axisModel.get('inverse'); + + // Injection + axisModel.axis = axis; + axis.model = axisModel; + axis.coordinateSystem = axisModel.coordinateSystem = this; + + }, this); + }, + + /** + * Update axis scale after data processed + * @param {module:echarts/model/Global} ecModel + * @param {module:echarts/ExtensionAPI} api + */ + update: function (ecModel, api) { + this._updateAxesFromSeries(this._model, ecModel); + }, + + /** + * @override + */ + containPoint: function (point) { + var layoutInfo = this._makeLayoutInfo(); + var axisBase = layoutInfo.axisBase; + var layoutBase = layoutInfo.layoutBase; + var pixelDimIndex = layoutInfo.pixelDimIndex; + var pAxis = point[1 - pixelDimIndex]; + var pLayout = point[pixelDimIndex]; + + return pAxis >= axisBase + && pAxis <= axisBase + layoutInfo.axisLength + && pLayout >= layoutBase + && pLayout <= layoutBase + layoutInfo.layoutLength; + }, + + getModel: function () { + return this._model; + }, + + /** + * Update properties from series + * @private + */ + _updateAxesFromSeries: function (parallelModel, ecModel) { + ecModel.eachSeries(function (seriesModel) { + + if (!parallelModel.contains(seriesModel, ecModel)) { + return; + } + + var data = seriesModel.getData(); + + each$11(this.dimensions, function (dim) { + var axis = this._axesMap.get(dim); + axis.scale.unionExtentFromData(data, data.mapDimension(dim)); + niceScaleExtent(axis.scale, axis.model); + }, this); + }, this); + }, + + /** + * Resize the parallel coordinate system. + * @param {module:echarts/coord/parallel/ParallelModel} parallelModel + * @param {module:echarts/ExtensionAPI} api + */ + resize: function (parallelModel, api) { + this._rect = getLayoutRect( + parallelModel.getBoxLayoutParams(), + { + width: api.getWidth(), + height: api.getHeight() + } + ); + + this._layoutAxes(); + }, + + /** + * @return {module:zrender/core/BoundingRect} + */ + getRect: function () { + return this._rect; + }, + + /** + * @private + */ + _makeLayoutInfo: function () { + var parallelModel = this._model; + var rect = this._rect; + var xy = ['x', 'y']; + var wh = ['width', 'height']; + var layout = parallelModel.get('layout'); + var pixelDimIndex = layout === 'horizontal' ? 0 : 1; + var layoutLength = rect[wh[pixelDimIndex]]; + var layoutExtent = [0, layoutLength]; + var axisCount = this.dimensions.length; + + var axisExpandWidth = restrict(parallelModel.get('axisExpandWidth'), layoutExtent); + var axisExpandCount = restrict(parallelModel.get('axisExpandCount') || 0, [0, axisCount]); + var axisExpandable = parallelModel.get('axisExpandable') + && axisCount > 3 + && axisCount > axisExpandCount + && axisExpandCount > 1 + && axisExpandWidth > 0 + && layoutLength > 0; + + // `axisExpandWindow` is According to the coordinates of [0, axisExpandLength], + // for sake of consider the case that axisCollapseWidth is 0 (when screen is narrow), + // where collapsed axes should be overlapped. + var axisExpandWindow = parallelModel.get('axisExpandWindow'); + var winSize; + if (!axisExpandWindow) { + winSize = restrict(axisExpandWidth * (axisExpandCount - 1), layoutExtent); + var axisExpandCenter = parallelModel.get('axisExpandCenter') || mathFloor$2(axisCount / 2); + axisExpandWindow = [axisExpandWidth * axisExpandCenter - winSize / 2]; + axisExpandWindow[1] = axisExpandWindow[0] + winSize; + } + else { + winSize = restrict(axisExpandWindow[1] - axisExpandWindow[0], layoutExtent); + axisExpandWindow[1] = axisExpandWindow[0] + winSize; + } + + var axisCollapseWidth = (layoutLength - winSize) / (axisCount - axisExpandCount); + // Avoid axisCollapseWidth is too small. + axisCollapseWidth < 3 && (axisCollapseWidth = 0); + + // Find the first and last indices > ewin[0] and < ewin[1]. + var winInnerIndices = [ + mathFloor$2(round$3(axisExpandWindow[0] / axisExpandWidth, 1)) + 1, + mathCeil$2(round$3(axisExpandWindow[1] / axisExpandWidth, 1)) - 1 + ]; + + // Pos in ec coordinates. + var axisExpandWindow0Pos = axisCollapseWidth / axisExpandWidth * axisExpandWindow[0]; + + return { + layout: layout, + pixelDimIndex: pixelDimIndex, + layoutBase: rect[xy[pixelDimIndex]], + layoutLength: layoutLength, + axisBase: rect[xy[1 - pixelDimIndex]], + axisLength: rect[wh[1 - pixelDimIndex]], + axisExpandable: axisExpandable, + axisExpandWidth: axisExpandWidth, + axisCollapseWidth: axisCollapseWidth, + axisExpandWindow: axisExpandWindow, + axisCount: axisCount, + winInnerIndices: winInnerIndices, + axisExpandWindow0Pos: axisExpandWindow0Pos + }; + }, + + /** + * @private + */ + _layoutAxes: function () { + var rect = this._rect; + var axes = this._axesMap; + var dimensions = this.dimensions; + var layoutInfo = this._makeLayoutInfo(); + var layout = layoutInfo.layout; + + axes.each(function (axis) { + var axisExtent = [0, layoutInfo.axisLength]; + var idx = axis.inverse ? 1 : 0; + axis.setExtent(axisExtent[idx], axisExtent[1 - idx]); + }); + + each$11(dimensions, function (dim, idx) { + var posInfo = (layoutInfo.axisExpandable + ? layoutAxisWithExpand : layoutAxisWithoutExpand + )(idx, layoutInfo); + + var positionTable = { + horizontal: { + x: posInfo.position, + y: layoutInfo.axisLength + }, + vertical: { + x: 0, + y: posInfo.position + } + }; + var rotationTable = { + horizontal: PI$3 / 2, + vertical: 0 + }; + + var position = [ + positionTable[layout].x + rect.x, + positionTable[layout].y + rect.y + ]; + + var rotation = rotationTable[layout]; + var transform = create$1(); + rotate(transform, transform, rotation); + translate(transform, transform, position); + + // TODO + // tick等排布信息。 + + // TODO + // 根据axis order 更新 dimensions顺序。 + + this._axesLayout[dim] = { + position: position, + rotation: rotation, + transform: transform, + axisNameAvailableWidth: posInfo.axisNameAvailableWidth, + axisLabelShow: posInfo.axisLabelShow, + nameTruncateMaxWidth: posInfo.nameTruncateMaxWidth, + tickDirection: 1, + labelDirection: 1 + }; + }, this); + }, + + /** + * Get axis by dim. + * @param {string} dim + * @return {module:echarts/coord/parallel/ParallelAxis} [description] + */ + getAxis: function (dim) { + return this._axesMap.get(dim); + }, + + /** + * Convert a dim value of a single item of series data to Point. + * @param {*} value + * @param {string} dim + * @return {Array} + */ + dataToPoint: function (value, dim) { + return this.axisCoordToPoint( + this._axesMap.get(dim).dataToCoord(value), + dim + ); + }, + + /** + * Travel data for one time, get activeState of each data item. + * @param {module:echarts/data/List} data + * @param {Functio} cb param: {string} activeState 'active' or 'inactive' or 'normal' + * {number} dataIndex + * @param {number} [start=0] the start dataIndex that travel from. + * @param {number} [end=data.count()] the next dataIndex of the last dataIndex will be travel. + */ + eachActiveState: function (data, callback, start, end) { + start == null && (start = 0); + end == null && (end = data.count()); + + var axesMap = this._axesMap; + var dimensions = this.dimensions; + var dataDimensions = []; + var axisModels = []; + + each$1(dimensions, function (axisDim) { + dataDimensions.push(data.mapDimension(axisDim)); + axisModels.push(axesMap.get(axisDim).model); + }); + + var hasActiveSet = this.hasAxisBrushed(); + + for (var dataIndex = start; dataIndex < end; dataIndex++) { + var activeState; + + if (!hasActiveSet) { + activeState = 'normal'; + } + else { + activeState = 'active'; + var values = data.getValues(dataDimensions, dataIndex); + for (var j = 0, lenj = dimensions.length; j < lenj; j++) { + var state = axisModels[j].getActiveState(values[j]); + + if (state === 'inactive') { + activeState = 'inactive'; + break; + } + } + } + + callback(activeState, dataIndex); + } + }, + + /** + * Whether has any activeSet. + * @return {boolean} + */ + hasAxisBrushed: function () { + var dimensions = this.dimensions; + var axesMap = this._axesMap; + var hasActiveSet = false; + + for (var j = 0, lenj = dimensions.length; j < lenj; j++) { + if (axesMap.get(dimensions[j]).model.getActiveState() !== 'normal') { + hasActiveSet = true; + } + } + + return hasActiveSet; + }, + + /** + * Convert coords of each axis to Point. + * Return point. For example: [10, 20] + * @param {Array.} coords + * @param {string} dim + * @return {Array.} + */ + axisCoordToPoint: function (coord, dim) { + var axisLayout = this._axesLayout[dim]; + return applyTransform$1([coord, 0], axisLayout.transform); + }, + + /** + * Get axis layout. + */ + getAxisLayout: function (dim) { + return clone(this._axesLayout[dim]); + }, + + /** + * @param {Array.} point + * @return {Object} {axisExpandWindow, delta, behavior: 'jump' | 'slide' | 'none'}. + */ + getSlidedAxisExpandWindow: function (point) { + var layoutInfo = this._makeLayoutInfo(); + var pixelDimIndex = layoutInfo.pixelDimIndex; + var axisExpandWindow = layoutInfo.axisExpandWindow.slice(); + var winSize = axisExpandWindow[1] - axisExpandWindow[0]; + var extent = [0, layoutInfo.axisExpandWidth * (layoutInfo.axisCount - 1)]; + + // Out of the area of coordinate system. + if (!this.containPoint(point)) { + return {behavior: 'none', axisExpandWindow: axisExpandWindow}; + } + + // Conver the point from global to expand coordinates. + var pointCoord = point[pixelDimIndex] - layoutInfo.layoutBase - layoutInfo.axisExpandWindow0Pos; + + // For dragging operation convenience, the window should not be + // slided when mouse is the center area of the window. + var delta; + var behavior = 'slide'; + var axisCollapseWidth = layoutInfo.axisCollapseWidth; + var triggerArea = this._model.get('axisExpandSlideTriggerArea'); + // But consider touch device, jump is necessary. + var useJump = triggerArea[0] != null; + + if (axisCollapseWidth) { + if (useJump && axisCollapseWidth && pointCoord < winSize * triggerArea[0]) { + behavior = 'jump'; + delta = pointCoord - winSize * triggerArea[2]; + } + else if (useJump && axisCollapseWidth && pointCoord > winSize * (1 - triggerArea[0])) { + behavior = 'jump'; + delta = pointCoord - winSize * (1 - triggerArea[2]); + } + else { + (delta = pointCoord - winSize * triggerArea[1]) >= 0 + && (delta = pointCoord - winSize * (1 - triggerArea[1])) <= 0 + && (delta = 0); + } + delta *= layoutInfo.axisExpandWidth / axisCollapseWidth; + delta + ? sliderMove(delta, axisExpandWindow, extent, 'all') + // Avoid nonsense triger on mousemove. + : (behavior = 'none'); + } + // When screen is too narrow, make it visible and slidable, although it is hard to interact. + else { + var winSize = axisExpandWindow[1] - axisExpandWindow[0]; + var pos = extent[1] * pointCoord / winSize; + axisExpandWindow = [mathMax$5(0, pos - winSize / 2)]; + axisExpandWindow[1] = mathMin$5(extent[1], axisExpandWindow[0] + winSize); + axisExpandWindow[0] = axisExpandWindow[1] - winSize; + } + + return { + axisExpandWindow: axisExpandWindow, + behavior: behavior + }; + } +}; + +function restrict(len, extent) { + return mathMin$5(mathMax$5(len, extent[0]), extent[1]); +} + +function layoutAxisWithoutExpand(axisIndex, layoutInfo) { + var step = layoutInfo.layoutLength / (layoutInfo.axisCount - 1); + return { + position: step * axisIndex, + axisNameAvailableWidth: step, + axisLabelShow: true + }; +} + +function layoutAxisWithExpand(axisIndex, layoutInfo) { + var layoutLength = layoutInfo.layoutLength; + var axisExpandWidth = layoutInfo.axisExpandWidth; + var axisCount = layoutInfo.axisCount; + var axisCollapseWidth = layoutInfo.axisCollapseWidth; + var winInnerIndices = layoutInfo.winInnerIndices; + + var position; + var axisNameAvailableWidth = axisCollapseWidth; + var axisLabelShow = false; + var nameTruncateMaxWidth; + + if (axisIndex < winInnerIndices[0]) { + position = axisIndex * axisCollapseWidth; + nameTruncateMaxWidth = axisCollapseWidth; + } + else if (axisIndex <= winInnerIndices[1]) { + position = layoutInfo.axisExpandWindow0Pos + + axisIndex * axisExpandWidth - layoutInfo.axisExpandWindow[0]; + axisNameAvailableWidth = axisExpandWidth; + axisLabelShow = true; + } + else { + position = layoutLength - (axisCount - 1 - axisIndex) * axisCollapseWidth; + nameTruncateMaxWidth = axisCollapseWidth; + } + + return { + position: position, + axisNameAvailableWidth: axisNameAvailableWidth, + axisLabelShow: axisLabelShow, + nameTruncateMaxWidth: nameTruncateMaxWidth + }; +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/** + * Parallel coordinate system creater. + */ + +function create$2(ecModel, api) { + var coordSysList = []; + + ecModel.eachComponent('parallel', function (parallelModel, idx) { + var coordSys = new Parallel(parallelModel, ecModel, api); + + coordSys.name = 'parallel_' + idx; + coordSys.resize(parallelModel, api); + + parallelModel.coordinateSystem = coordSys; + coordSys.model = parallelModel; + + coordSysList.push(coordSys); + }); + + // Inject the coordinateSystems into seriesModel + ecModel.eachSeries(function (seriesModel) { + if (seriesModel.get('coordinateSystem') === 'parallel') { + var parallelModel = ecModel.queryComponents({ + mainType: 'parallel', + index: seriesModel.get('parallelIndex'), + id: seriesModel.get('parallelId') + })[0]; + seriesModel.coordinateSystem = parallelModel.coordinateSystem; + } + }); + + return coordSysList; +} + +CoordinateSystemManager.register('parallel', {create: create$2}); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var AxisModel$2 = ComponentModel.extend({ + + type: 'baseParallelAxis', + + /** + * @type {module:echarts/coord/parallel/Axis} + */ + axis: null, + + /** + * @type {Array.} + * @readOnly + */ + activeIntervals: [], + + /** + * @return {Object} + */ + getAreaSelectStyle: function () { + return makeStyleMapper( + [ + ['fill', 'color'], + ['lineWidth', 'borderWidth'], + ['stroke', 'borderColor'], + ['width', 'width'], + ['opacity', 'opacity'] + ] + )(this.getModel('areaSelectStyle')); + }, + + /** + * The code of this feature is put on AxisModel but not ParallelAxis, + * because axisModel can be alive after echarts updating but instance of + * ParallelAxis having been disposed. this._activeInterval should be kept + * when action dispatched (i.e. legend click). + * + * @param {Array.>} intervals interval.length === 0 + * means set all active. + * @public + */ + setActiveIntervals: function (intervals) { + var activeIntervals = this.activeIntervals = clone(intervals); + + // Normalize + if (activeIntervals) { + for (var i = activeIntervals.length - 1; i >= 0; i--) { + asc(activeIntervals[i]); + } + } + }, + + /** + * @param {number|string} [value] When attempting to detect 'no activeIntervals set', + * value can not be input. + * @return {string} 'normal': no activeIntervals set, + * 'active', + * 'inactive'. + * @public + */ + getActiveState: function (value) { + var activeIntervals = this.activeIntervals; + + if (!activeIntervals.length) { + return 'normal'; + } + + if (value == null || isNaN(value)) { + return 'inactive'; + } + + // Simple optimization + if (activeIntervals.length === 1) { + var interval = activeIntervals[0]; + if (interval[0] <= value && value <= interval[1]) { + return 'active'; + } + } + else { + for (var i = 0, len = activeIntervals.length; i < len; i++) { + if (activeIntervals[i][0] <= value && value <= activeIntervals[i][1]) { + return 'active'; + } + } + } + + return 'inactive'; + } + +}); + +var defaultOption$1 = { + + type: 'value', + + /** + * @type {Array.} + */ + dim: null, // 0, 1, 2, ... + + // parallelIndex: null, + + areaSelectStyle: { + width: 20, + borderWidth: 1, + borderColor: 'rgba(160,197,232)', + color: 'rgba(160,197,232)', + opacity: 0.3 + }, + + realtime: true, // Whether realtime update view when select. + + z: 10 +}; + +merge(AxisModel$2.prototype, axisModelCommonMixin); + +function getAxisType$1(axisName, option) { + return option.type || (option.data ? 'category' : 'value'); +} + +axisModelCreator('parallel', AxisModel$2, getAxisType$1, defaultOption$1); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +ComponentModel.extend({ + + type: 'parallel', + + dependencies: ['parallelAxis'], + + /** + * @type {module:echarts/coord/parallel/Parallel} + */ + coordinateSystem: null, + + /** + * Each item like: 'dim0', 'dim1', 'dim2', ... + * @type {Array.} + * @readOnly + */ + dimensions: null, + + /** + * Coresponding to dimensions. + * @type {Array.} + * @readOnly + */ + parallelAxisIndex: null, + + layoutMode: 'box', + + defaultOption: { + zlevel: 0, + z: 0, + left: 80, + top: 60, + right: 80, + bottom: 60, + // width: {totalWidth} - left - right, + // height: {totalHeight} - top - bottom, + + layout: 'horizontal', // 'horizontal' or 'vertical' + + // FIXME + // naming? + axisExpandable: false, + axisExpandCenter: null, + axisExpandCount: 0, + axisExpandWidth: 50, // FIXME '10%' ? + axisExpandRate: 17, + axisExpandDebounce: 50, + // [out, in, jumpTarget]. In percentage. If use [null, 0.05], null means full. + // Do not doc to user until necessary. + axisExpandSlideTriggerArea: [-0.15, 0.05, 0.4], + axisExpandTriggerOn: 'click', // 'mousemove' or 'click' + + parallelAxisDefault: null + }, + + /** + * @override + */ + init: function () { + ComponentModel.prototype.init.apply(this, arguments); + + this.mergeOption({}); + }, + + /** + * @override + */ + mergeOption: function (newOption) { + var thisOption = this.option; + + newOption && merge(thisOption, newOption, true); + + this._initDimensions(); + }, + + /** + * Whether series or axis is in this coordinate system. + * @param {module:echarts/model/Series|module:echarts/coord/parallel/AxisModel} model + * @param {module:echarts/model/Global} ecModel + */ + contains: function (model, ecModel) { + var parallelIndex = model.get('parallelIndex'); + return parallelIndex != null + && ecModel.getComponent('parallel', parallelIndex) === this; + }, + + setAxisExpand: function (opt) { + each$1( + ['axisExpandable', 'axisExpandCenter', 'axisExpandCount', 'axisExpandWidth', 'axisExpandWindow'], + function (name) { + if (opt.hasOwnProperty(name)) { + this.option[name] = opt[name]; + } + }, + this + ); + }, + + /** + * @private + */ + _initDimensions: function () { + var dimensions = this.dimensions = []; + var parallelAxisIndex = this.parallelAxisIndex = []; + + var axisModels = filter(this.dependentModels.parallelAxis, function (axisModel) { + // Can not use this.contains here, because + // initialization has not been completed yet. + return (axisModel.get('parallelIndex') || 0) === this.componentIndex; + }, this); + + each$1(axisModels, function (axisModel) { + dimensions.push('dim' + axisModel.get('dim')); + parallelAxisIndex.push(axisModel.componentIndex); + }); + } + +}); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/** + * @payload + * @property {string} parallelAxisId + * @property {Array.>} intervals + */ +var actionInfo$1 = { + type: 'axisAreaSelect', + event: 'axisAreaSelected' + // update: 'updateVisual' +}; + +registerAction(actionInfo$1, function (payload, ecModel) { + ecModel.eachComponent( + {mainType: 'parallelAxis', query: payload}, + function (parallelAxisModel) { + parallelAxisModel.axis.model.setActiveIntervals(payload.intervals); + } + ); +}); + +/** + * @payload + */ +registerAction('parallelAxisExpand', function (payload, ecModel) { + ecModel.eachComponent( + {mainType: 'parallel', query: payload}, + function (parallelModel) { + parallelModel.setAxisExpand(payload); + } + ); + +}); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var curry$2 = curry; +var each$12 = each$1; +var map$2 = map; +var mathMin$6 = Math.min; +var mathMax$6 = Math.max; +var mathPow$2 = Math.pow; + +var COVER_Z = 10000; +var UNSELECT_THRESHOLD = 6; +var MIN_RESIZE_LINE_WIDTH = 6; +var MUTEX_RESOURCE_KEY = 'globalPan'; + +var DIRECTION_MAP = { + w: [0, 0], + e: [0, 1], + n: [1, 0], + s: [1, 1] +}; +var CURSOR_MAP = { + w: 'ew', + e: 'ew', + n: 'ns', + s: 'ns', + ne: 'nesw', + sw: 'nesw', + nw: 'nwse', + se: 'nwse' +}; +var DEFAULT_BRUSH_OPT = { + brushStyle: { + lineWidth: 2, + stroke: 'rgba(0,0,0,0.3)', + fill: 'rgba(0,0,0,0.1)' + }, + transformable: true, + brushMode: 'single', + removeOnClick: false +}; + +var baseUID = 0; + +/** + * @alias module:echarts/component/helper/BrushController + * @constructor + * @mixin {module:zrender/mixin/Eventful} + * @event module:echarts/component/helper/BrushController#brush + * params: + * areas: Array., coord relates to container group, + * If no container specified, to global. + * opt { + * isEnd: boolean, + * removeOnClick: boolean + * } + * + * @param {module:zrender/zrender~ZRender} zr + */ +function BrushController(zr) { + + if (__DEV__) { + assert$1(zr); + } + + Eventful.call(this); + + /** + * @type {module:zrender/zrender~ZRender} + * @private + */ + this._zr = zr; + + /** + * @type {module:zrender/container/Group} + * @readOnly + */ + this.group = new Group(); + + /** + * Only for drawing (after enabledBrush). + * 'line', 'rect', 'polygon' or false + * If passing false/null/undefined, disable brush. + * If passing 'auto', determined by panel.defaultBrushType + * @private + * @type {string} + */ + this._brushType; + + /** + * Only for drawing (after enabledBrush). + * + * @private + * @type {Object} + */ + this._brushOption; + + /** + * @private + * @type {Object} + */ + this._panels; + + /** + * @private + * @type {Array.} + */ + this._track = []; + + /** + * @private + * @type {boolean} + */ + this._dragging; + + /** + * @private + * @type {Array} + */ + this._covers = []; + + /** + * @private + * @type {moudule:zrender/container/Group} + */ + this._creatingCover; + + /** + * `true` means global panel + * @private + * @type {module:zrender/container/Group|boolean} + */ + this._creatingPanel; + + /** + * @private + * @type {boolean} + */ + this._enableGlobalPan; + + /** + * @private + * @type {boolean} + */ + if (__DEV__) { + this._mounted; + } + + /** + * @private + * @type {string} + */ + this._uid = 'brushController_' + baseUID++; + + /** + * @private + * @type {Object} + */ + this._handlers = {}; + each$12(mouseHandlers, function (handler, eventName) { + this._handlers[eventName] = bind(handler, this); + }, this); +} + +BrushController.prototype = { + + constructor: BrushController, + + /** + * If set to null/undefined/false, select disabled. + * @param {Object} brushOption + * @param {string|boolean} brushOption.brushType 'line', 'rect', 'polygon' or false + * If passing false/null/undefined, disable brush. + * If passing 'auto', determined by panel.defaultBrushType. + * ('auto' can not be used in global panel) + * @param {number} [brushOption.brushMode='single'] 'single' or 'multiple' + * @param {boolean} [brushOption.transformable=true] + * @param {boolean} [brushOption.removeOnClick=false] + * @param {Object} [brushOption.brushStyle] + * @param {number} [brushOption.brushStyle.width] + * @param {number} [brushOption.brushStyle.lineWidth] + * @param {string} [brushOption.brushStyle.stroke] + * @param {string} [brushOption.brushStyle.fill] + * @param {number} [brushOption.z] + */ + enableBrush: function (brushOption) { + if (__DEV__) { + assert$1(this._mounted); + } + + this._brushType && doDisableBrush(this); + brushOption.brushType && doEnableBrush(this, brushOption); + + return this; + }, + + /** + * @param {Array.} panelOpts If not pass, it is global brush. + * Each items: { + * panelId, // mandatory. + * clipPath, // mandatory. function. + * isTargetByCursor, // mandatory. function. + * defaultBrushType, // optional, only used when brushType is 'auto'. + * getLinearBrushOtherExtent, // optional. function. + * } + */ + setPanels: function (panelOpts) { + if (panelOpts && panelOpts.length) { + var panels = this._panels = {}; + each$1(panelOpts, function (panelOpts) { + panels[panelOpts.panelId] = clone(panelOpts); + }); + } + else { + this._panels = null; + } + return this; + }, + + /** + * @param {Object} [opt] + * @return {boolean} [opt.enableGlobalPan=false] + */ + mount: function (opt) { + opt = opt || {}; + + if (__DEV__) { + this._mounted = true; // should be at first. + } + + this._enableGlobalPan = opt.enableGlobalPan; + + var thisGroup = this.group; + this._zr.add(thisGroup); + + thisGroup.attr({ + position: opt.position || [0, 0], + rotation: opt.rotation || 0, + scale: opt.scale || [1, 1] + }); + this._transform = thisGroup.getLocalTransform(); + + return this; + }, + + eachCover: function (cb, context) { + each$12(this._covers, cb, context); + }, + + /** + * Update covers. + * @param {Array.} brushOptionList Like: + * [ + * {id: 'xx', brushType: 'line', range: [23, 44], brushStyle, transformable}, + * {id: 'yy', brushType: 'rect', range: [[23, 44], [23, 54]]}, + * ... + * ] + * `brushType` is required in each cover info. (can not be 'auto') + * `id` is not mandatory. + * `brushStyle`, `transformable` is not mandatory, use DEFAULT_BRUSH_OPT by default. + * If brushOptionList is null/undefined, all covers removed. + */ + updateCovers: function (brushOptionList) { + if (__DEV__) { + assert$1(this._mounted); + } + + brushOptionList = map(brushOptionList, function (brushOption) { + return merge(clone(DEFAULT_BRUSH_OPT), brushOption, true); + }); + + var tmpIdPrefix = '\0-brush-index-'; + var oldCovers = this._covers; + var newCovers = this._covers = []; + var controller = this; + var creatingCover = this._creatingCover; + + (new DataDiffer(oldCovers, brushOptionList, oldGetKey, getKey)) + .add(addOrUpdate) + .update(addOrUpdate) + .remove(remove) + .execute(); + + return this; + + function getKey(brushOption, index) { + return (brushOption.id != null ? brushOption.id : tmpIdPrefix + index) + + '-' + brushOption.brushType; + } + + function oldGetKey(cover, index) { + return getKey(cover.__brushOption, index); + } + + function addOrUpdate(newIndex, oldIndex) { + var newBrushOption = brushOptionList[newIndex]; + // Consider setOption in event listener of brushSelect, + // where updating cover when creating should be forbiden. + if (oldIndex != null && oldCovers[oldIndex] === creatingCover) { + newCovers[newIndex] = oldCovers[oldIndex]; + } + else { + var cover = newCovers[newIndex] = oldIndex != null + ? ( + oldCovers[oldIndex].__brushOption = newBrushOption, + oldCovers[oldIndex] + ) + : endCreating(controller, createCover(controller, newBrushOption)); + updateCoverAfterCreation(controller, cover); + } + } + + function remove(oldIndex) { + if (oldCovers[oldIndex] !== creatingCover) { + controller.group.remove(oldCovers[oldIndex]); + } + } + }, + + unmount: function () { + if (__DEV__) { + if (!this._mounted) { + return; + } + } + + this.enableBrush(false); + + // container may 'removeAll' outside. + clearCovers(this); + this._zr.remove(this.group); + + if (__DEV__) { + this._mounted = false; // should be at last. + } + + return this; + }, + + dispose: function () { + this.unmount(); + this.off(); + } +}; + +mixin(BrushController, Eventful); + +function doEnableBrush(controller, brushOption) { + var zr = controller._zr; + + // Consider roam, which takes globalPan too. + if (!controller._enableGlobalPan) { + take(zr, MUTEX_RESOURCE_KEY, controller._uid); + } + + each$12(controller._handlers, function (handler, eventName) { + zr.on(eventName, handler); + }); + + controller._brushType = brushOption.brushType; + controller._brushOption = merge(clone(DEFAULT_BRUSH_OPT), brushOption, true); +} + +function doDisableBrush(controller) { + var zr = controller._zr; + + release(zr, MUTEX_RESOURCE_KEY, controller._uid); + + each$12(controller._handlers, function (handler, eventName) { + zr.off(eventName, handler); + }); + + controller._brushType = controller._brushOption = null; +} + +function createCover(controller, brushOption) { + var cover = coverRenderers[brushOption.brushType].createCover(controller, brushOption); + cover.__brushOption = brushOption; + updateZ$1(cover, brushOption); + controller.group.add(cover); + return cover; +} + +function endCreating(controller, creatingCover) { + var coverRenderer = getCoverRenderer(creatingCover); + if (coverRenderer.endCreating) { + coverRenderer.endCreating(controller, creatingCover); + updateZ$1(creatingCover, creatingCover.__brushOption); + } + return creatingCover; +} + +function updateCoverShape(controller, cover) { + var brushOption = cover.__brushOption; + getCoverRenderer(cover).updateCoverShape( + controller, cover, brushOption.range, brushOption + ); +} + +function updateZ$1(cover, brushOption) { + var z = brushOption.z; + z == null && (z = COVER_Z); + cover.traverse(function (el) { + el.z = z; + el.z2 = z; // Consider in given container. + }); +} + +function updateCoverAfterCreation(controller, cover) { + getCoverRenderer(cover).updateCommon(controller, cover); + updateCoverShape(controller, cover); +} + +function getCoverRenderer(cover) { + return coverRenderers[cover.__brushOption.brushType]; +} + +// return target panel or `true` (means global panel) +function getPanelByPoint(controller, e, localCursorPoint) { + var panels = controller._panels; + if (!panels) { + return true; // Global panel + } + var panel; + var transform = controller._transform; + each$12(panels, function (pn) { + pn.isTargetByCursor(e, localCursorPoint, transform) && (panel = pn); + }); + return panel; +} + +// Return a panel or true +function getPanelByCover(controller, cover) { + var panels = controller._panels; + if (!panels) { + return true; // Global panel + } + var panelId = cover.__brushOption.panelId; + // User may give cover without coord sys info, + // which is then treated as global panel. + return panelId != null ? panels[panelId] : true; +} + +function clearCovers(controller) { + var covers = controller._covers; + var originalLength = covers.length; + each$12(covers, function (cover) { + controller.group.remove(cover); + }, controller); + covers.length = 0; + + return !!originalLength; +} + +function trigger$1(controller, opt) { + var areas = map$2(controller._covers, function (cover) { + var brushOption = cover.__brushOption; + var range = clone(brushOption.range); + return { + brushType: brushOption.brushType, + panelId: brushOption.panelId, + range: range + }; + }); + + controller.trigger('brush', areas, { + isEnd: !!opt.isEnd, + removeOnClick: !!opt.removeOnClick + }); +} + +function shouldShowCover(controller) { + var track = controller._track; + + if (!track.length) { + return false; + } + + var p2 = track[track.length - 1]; + var p1 = track[0]; + var dx = p2[0] - p1[0]; + var dy = p2[1] - p1[1]; + var dist = mathPow$2(dx * dx + dy * dy, 0.5); + + return dist > UNSELECT_THRESHOLD; +} + +function getTrackEnds(track) { + var tail = track.length - 1; + tail < 0 && (tail = 0); + return [track[0], track[tail]]; +} + +function createBaseRectCover(doDrift, controller, brushOption, edgeNames) { + var cover = new Group(); + + cover.add(new Rect({ + name: 'main', + style: makeStyle(brushOption), + silent: true, + draggable: true, + cursor: 'move', + drift: curry$2(doDrift, controller, cover, 'nswe'), + ondragend: curry$2(trigger$1, controller, {isEnd: true}) + })); + + each$12( + edgeNames, + function (name) { + cover.add(new Rect({ + name: name, + style: {opacity: 0}, + draggable: true, + silent: true, + invisible: true, + drift: curry$2(doDrift, controller, cover, name), + ondragend: curry$2(trigger$1, controller, {isEnd: true}) + })); + } + ); + + return cover; +} + +function updateBaseRect(controller, cover, localRange, brushOption) { + var lineWidth = brushOption.brushStyle.lineWidth || 0; + var handleSize = mathMax$6(lineWidth, MIN_RESIZE_LINE_WIDTH); + var x = localRange[0][0]; + var y = localRange[1][0]; + var xa = x - lineWidth / 2; + var ya = y - lineWidth / 2; + var x2 = localRange[0][1]; + var y2 = localRange[1][1]; + var x2a = x2 - handleSize + lineWidth / 2; + var y2a = y2 - handleSize + lineWidth / 2; + var width = x2 - x; + var height = y2 - y; + var widtha = width + lineWidth; + var heighta = height + lineWidth; + + updateRectShape(controller, cover, 'main', x, y, width, height); + + if (brushOption.transformable) { + updateRectShape(controller, cover, 'w', xa, ya, handleSize, heighta); + updateRectShape(controller, cover, 'e', x2a, ya, handleSize, heighta); + updateRectShape(controller, cover, 'n', xa, ya, widtha, handleSize); + updateRectShape(controller, cover, 's', xa, y2a, widtha, handleSize); + + updateRectShape(controller, cover, 'nw', xa, ya, handleSize, handleSize); + updateRectShape(controller, cover, 'ne', x2a, ya, handleSize, handleSize); + updateRectShape(controller, cover, 'sw', xa, y2a, handleSize, handleSize); + updateRectShape(controller, cover, 'se', x2a, y2a, handleSize, handleSize); + } +} + +function updateCommon(controller, cover) { + var brushOption = cover.__brushOption; + var transformable = brushOption.transformable; + + var mainEl = cover.childAt(0); + mainEl.useStyle(makeStyle(brushOption)); + mainEl.attr({ + silent: !transformable, + cursor: transformable ? 'move' : 'default' + }); + + each$12( + ['w', 'e', 'n', 's', 'se', 'sw', 'ne', 'nw'], + function (name) { + var el = cover.childOfName(name); + var globalDir = getGlobalDirection(controller, name); + + el && el.attr({ + silent: !transformable, + invisible: !transformable, + cursor: transformable ? CURSOR_MAP[globalDir] + '-resize' : null + }); + } + ); +} + +function updateRectShape(controller, cover, name, x, y, w, h) { + var el = cover.childOfName(name); + el && el.setShape(pointsToRect( + clipByPanel(controller, cover, [[x, y], [x + w, y + h]]) + )); +} + +function makeStyle(brushOption) { + return defaults({strokeNoScale: true}, brushOption.brushStyle); +} + +function formatRectRange(x, y, x2, y2) { + var min = [mathMin$6(x, x2), mathMin$6(y, y2)]; + var max = [mathMax$6(x, x2), mathMax$6(y, y2)]; + + return [ + [min[0], max[0]], // x range + [min[1], max[1]] // y range + ]; +} + +function getTransform$1(controller) { + return getTransform(controller.group); +} + +function getGlobalDirection(controller, localDirection) { + if (localDirection.length > 1) { + localDirection = localDirection.split(''); + var globalDir = [ + getGlobalDirection(controller, localDirection[0]), + getGlobalDirection(controller, localDirection[1]) + ]; + (globalDir[0] === 'e' || globalDir[0] === 'w') && globalDir.reverse(); + return globalDir.join(''); + } + else { + var map$$1 = {w: 'left', e: 'right', n: 'top', s: 'bottom'}; + var inverseMap = {left: 'w', right: 'e', top: 'n', bottom: 's'}; + var globalDir = transformDirection( + map$$1[localDirection], getTransform$1(controller) + ); + return inverseMap[globalDir]; + } +} + +function driftRect(toRectRange, fromRectRange, controller, cover, name, dx, dy, e) { + var brushOption = cover.__brushOption; + var rectRange = toRectRange(brushOption.range); + var localDelta = toLocalDelta(controller, dx, dy); + + each$12(name.split(''), function (namePart) { + var ind = DIRECTION_MAP[namePart]; + rectRange[ind[0]][ind[1]] += localDelta[ind[0]]; + }); + + brushOption.range = fromRectRange(formatRectRange( + rectRange[0][0], rectRange[1][0], rectRange[0][1], rectRange[1][1] + )); + + updateCoverAfterCreation(controller, cover); + trigger$1(controller, {isEnd: false}); +} + +function driftPolygon(controller, cover, dx, dy, e) { + var range = cover.__brushOption.range; + var localDelta = toLocalDelta(controller, dx, dy); + + each$12(range, function (point) { + point[0] += localDelta[0]; + point[1] += localDelta[1]; + }); + + updateCoverAfterCreation(controller, cover); + trigger$1(controller, {isEnd: false}); +} + +function toLocalDelta(controller, dx, dy) { + var thisGroup = controller.group; + var localD = thisGroup.transformCoordToLocal(dx, dy); + var localZero = thisGroup.transformCoordToLocal(0, 0); + + return [localD[0] - localZero[0], localD[1] - localZero[1]]; +} + +function clipByPanel(controller, cover, data) { + var panel = getPanelByCover(controller, cover); + + return (panel && panel !== true) + ? panel.clipPath(data, controller._transform) + : clone(data); +} + +function pointsToRect(points) { + var xmin = mathMin$6(points[0][0], points[1][0]); + var ymin = mathMin$6(points[0][1], points[1][1]); + var xmax = mathMax$6(points[0][0], points[1][0]); + var ymax = mathMax$6(points[0][1], points[1][1]); + + return { + x: xmin, + y: ymin, + width: xmax - xmin, + height: ymax - ymin + }; +} + +function resetCursor(controller, e, localCursorPoint) { + // Check active + if (!controller._brushType) { + return; + } + + var zr = controller._zr; + var covers = controller._covers; + var currPanel = getPanelByPoint(controller, e, localCursorPoint); + + // Check whether in covers. + if (!controller._dragging) { + for (var i = 0; i < covers.length; i++) { + var brushOption = covers[i].__brushOption; + if (currPanel + && (currPanel === true || brushOption.panelId === currPanel.panelId) + && coverRenderers[brushOption.brushType].contain( + covers[i], localCursorPoint[0], localCursorPoint[1] + ) + ) { + // Use cursor style set on cover. + return; + } + } + } + + currPanel && zr.setCursorStyle('crosshair'); +} + +function preventDefault(e) { + var rawE = e.event; + rawE.preventDefault && rawE.preventDefault(); +} + +function mainShapeContain(cover, x, y) { + return cover.childOfName('main').contain(x, y); +} + +function updateCoverByMouse(controller, e, localCursorPoint, isEnd) { + var creatingCover = controller._creatingCover; + var panel = controller._creatingPanel; + var thisBrushOption = controller._brushOption; + var eventParams; + + controller._track.push(localCursorPoint.slice()); + + if (shouldShowCover(controller) || creatingCover) { + + if (panel && !creatingCover) { + thisBrushOption.brushMode === 'single' && clearCovers(controller); + var brushOption = clone(thisBrushOption); + brushOption.brushType = determineBrushType(brushOption.brushType, panel); + brushOption.panelId = panel === true ? null : panel.panelId; + creatingCover = controller._creatingCover = createCover(controller, brushOption); + controller._covers.push(creatingCover); + } + + if (creatingCover) { + var coverRenderer = coverRenderers[determineBrushType(controller._brushType, panel)]; + var coverBrushOption = creatingCover.__brushOption; + + coverBrushOption.range = coverRenderer.getCreatingRange( + clipByPanel(controller, creatingCover, controller._track) + ); + + if (isEnd) { + endCreating(controller, creatingCover); + coverRenderer.updateCommon(controller, creatingCover); + } + + updateCoverShape(controller, creatingCover); + + eventParams = {isEnd: isEnd}; + } + } + else if ( + isEnd + && thisBrushOption.brushMode === 'single' + && thisBrushOption.removeOnClick + ) { + // Help user to remove covers easily, only by a tiny drag, in 'single' mode. + // But a single click do not clear covers, because user may have casual + // clicks (for example, click on other component and do not expect covers + // disappear). + // Only some cover removed, trigger action, but not every click trigger action. + if (getPanelByPoint(controller, e, localCursorPoint) && clearCovers(controller)) { + eventParams = {isEnd: isEnd, removeOnClick: true}; + } + } + + return eventParams; +} + +function determineBrushType(brushType, panel) { + if (brushType === 'auto') { + if (__DEV__) { + assert$1( + panel && panel.defaultBrushType, + 'MUST have defaultBrushType when brushType is "atuo"' + ); + } + return panel.defaultBrushType; + } + return brushType; +} + +var mouseHandlers = { + + mousedown: function (e) { + if (this._dragging) { + // In case some browser do not support globalOut, + // and release mose out side the browser. + handleDragEnd.call(this, e); + } + else if (!e.target || !e.target.draggable) { + + preventDefault(e); + + var localCursorPoint = this.group.transformCoordToLocal(e.offsetX, e.offsetY); + + this._creatingCover = null; + var panel = this._creatingPanel = getPanelByPoint(this, e, localCursorPoint); + + if (panel) { + this._dragging = true; + this._track = [localCursorPoint.slice()]; + } + } + }, + + mousemove: function (e) { + var localCursorPoint = this.group.transformCoordToLocal(e.offsetX, e.offsetY); + + resetCursor(this, e, localCursorPoint); + + if (this._dragging) { + + preventDefault(e); + + var eventParams = updateCoverByMouse(this, e, localCursorPoint, false); + + eventParams && trigger$1(this, eventParams); + } + }, + + mouseup: handleDragEnd //, + + // FIXME + // in tooltip, globalout should not be triggered. + // globalout: handleDragEnd +}; + +function handleDragEnd(e) { + if (this._dragging) { + + preventDefault(e); + + var localCursorPoint = this.group.transformCoordToLocal(e.offsetX, e.offsetY); + var eventParams = updateCoverByMouse(this, e, localCursorPoint, true); + + this._dragging = false; + this._track = []; + this._creatingCover = null; + + // trigger event shoule be at final, after procedure will be nested. + eventParams && trigger$1(this, eventParams); + } +} + +/** + * key: brushType + * @type {Object} + */ +var coverRenderers = { + + lineX: getLineRenderer(0), + + lineY: getLineRenderer(1), + + rect: { + createCover: function (controller, brushOption) { + return createBaseRectCover( + curry$2( + driftRect, + function (range) { + return range; + }, + function (range) { + return range; + } + ), + controller, + brushOption, + ['w', 'e', 'n', 's', 'se', 'sw', 'ne', 'nw'] + ); + }, + getCreatingRange: function (localTrack) { + var ends = getTrackEnds(localTrack); + return formatRectRange(ends[1][0], ends[1][1], ends[0][0], ends[0][1]); + }, + updateCoverShape: function (controller, cover, localRange, brushOption) { + updateBaseRect(controller, cover, localRange, brushOption); + }, + updateCommon: updateCommon, + contain: mainShapeContain + }, + + polygon: { + createCover: function (controller, brushOption) { + var cover = new Group(); + + // Do not use graphic.Polygon because graphic.Polyline do not close the + // border of the shape when drawing, which is a better experience for user. + cover.add(new Polyline({ + name: 'main', + style: makeStyle(brushOption), + silent: true + })); + + return cover; + }, + getCreatingRange: function (localTrack) { + return localTrack; + }, + endCreating: function (controller, cover) { + cover.remove(cover.childAt(0)); + // Use graphic.Polygon close the shape. + cover.add(new Polygon({ + name: 'main', + draggable: true, + drift: curry$2(driftPolygon, controller, cover), + ondragend: curry$2(trigger$1, controller, {isEnd: true}) + })); + }, + updateCoverShape: function (controller, cover, localRange, brushOption) { + cover.childAt(0).setShape({ + points: clipByPanel(controller, cover, localRange) + }); + }, + updateCommon: updateCommon, + contain: mainShapeContain + } +}; + +function getLineRenderer(xyIndex) { + return { + createCover: function (controller, brushOption) { + return createBaseRectCover( + curry$2( + driftRect, + function (range) { + var rectRange = [range, [0, 100]]; + xyIndex && rectRange.reverse(); + return rectRange; + }, + function (rectRange) { + return rectRange[xyIndex]; + } + ), + controller, + brushOption, + [['w', 'e'], ['n', 's']][xyIndex] + ); + }, + getCreatingRange: function (localTrack) { + var ends = getTrackEnds(localTrack); + var min = mathMin$6(ends[0][xyIndex], ends[1][xyIndex]); + var max = mathMax$6(ends[0][xyIndex], ends[1][xyIndex]); + + return [min, max]; + }, + updateCoverShape: function (controller, cover, localRange, brushOption) { + var otherExtent; + // If brushWidth not specified, fit the panel. + var panel = getPanelByCover(controller, cover); + if (panel !== true && panel.getLinearBrushOtherExtent) { + otherExtent = panel.getLinearBrushOtherExtent( + xyIndex, controller._transform + ); + } + else { + var zr = controller._zr; + otherExtent = [0, [zr.getWidth(), zr.getHeight()][1 - xyIndex]]; + } + var rectRange = [localRange, otherExtent]; + xyIndex && rectRange.reverse(); + + updateBaseRect(controller, cover, rectRange, brushOption); + }, + updateCommon: updateCommon, + contain: mainShapeContain + }; +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +function makeRectPanelClipPath(rect) { + rect = normalizeRect(rect); + return function (localPoints, transform) { + return clipPointsByRect(localPoints, rect); + }; +} + +function makeLinearBrushOtherExtent(rect, specifiedXYIndex) { + rect = normalizeRect(rect); + return function (xyIndex) { + var idx = specifiedXYIndex != null ? specifiedXYIndex : xyIndex; + var brushWidth = idx ? rect.width : rect.height; + var base = idx ? rect.x : rect.y; + return [base, base + (brushWidth || 0)]; + }; +} + +function makeRectIsTargetByCursor(rect, api, targetModel) { + rect = normalizeRect(rect); + return function (e, localCursorPoint, transform) { + return rect.contain(localCursorPoint[0], localCursorPoint[1]) + && !onIrrelevantElement(e, api, targetModel); + }; +} + +// Consider width/height is negative. +function normalizeRect(rect) { + return BoundingRect.create(rect); +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var elementList = ['axisLine', 'axisTickLabel', 'axisName']; + +var AxisView$2 = extendComponentView({ + + type: 'parallelAxis', + + /** + * @override + */ + init: function (ecModel, api) { + AxisView$2.superApply(this, 'init', arguments); + + /** + * @type {module:echarts/component/helper/BrushController} + */ + (this._brushController = new BrushController(api.getZr())) + .on('brush', bind(this._onBrush, this)); + }, + + /** + * @override + */ + render: function (axisModel, ecModel, api, payload) { + if (fromAxisAreaSelect(axisModel, ecModel, payload)) { + return; + } + + this.axisModel = axisModel; + this.api = api; + + this.group.removeAll(); + + var oldAxisGroup = this._axisGroup; + this._axisGroup = new Group(); + this.group.add(this._axisGroup); + + if (!axisModel.get('show')) { + return; + } + + var coordSysModel = getCoordSysModel(axisModel, ecModel); + var coordSys = coordSysModel.coordinateSystem; + + var areaSelectStyle = axisModel.getAreaSelectStyle(); + var areaWidth = areaSelectStyle.width; + + var dim = axisModel.axis.dim; + var axisLayout = coordSys.getAxisLayout(dim); + + var builderOpt = extend( + {strokeContainThreshold: areaWidth}, + axisLayout + ); + + var axisBuilder = new AxisBuilder(axisModel, builderOpt); + + each$1(elementList, axisBuilder.add, axisBuilder); + + this._axisGroup.add(axisBuilder.getGroup()); + + this._refreshBrushController( + builderOpt, areaSelectStyle, axisModel, coordSysModel, areaWidth, api + ); + + var animationModel = (payload && payload.animation === false) ? null : axisModel; + groupTransition(oldAxisGroup, this._axisGroup, animationModel); + }, + + // /** + // * @override + // */ + // updateVisual: function (axisModel, ecModel, api, payload) { + // this._brushController && this._brushController + // .updateCovers(getCoverInfoList(axisModel)); + // }, + + _refreshBrushController: function ( + builderOpt, areaSelectStyle, axisModel, coordSysModel, areaWidth, api + ) { + // After filtering, axis may change, select area needs to be update. + var extent = axisModel.axis.getExtent(); + var extentLen = extent[1] - extent[0]; + var extra = Math.min(30, Math.abs(extentLen) * 0.1); // Arbitrary value. + + // width/height might be negative, which will be + // normalized in BoundingRect. + var rect = BoundingRect.create({ + x: extent[0], + y: -areaWidth / 2, + width: extentLen, + height: areaWidth + }); + rect.x -= extra; + rect.width += 2 * extra; + + this._brushController + .mount({ + enableGlobalPan: true, + rotation: builderOpt.rotation, + position: builderOpt.position + }) + .setPanels([{ + panelId: 'pl', + clipPath: makeRectPanelClipPath(rect), + isTargetByCursor: makeRectIsTargetByCursor(rect, api, coordSysModel), + getLinearBrushOtherExtent: makeLinearBrushOtherExtent(rect, 0) + }]) + .enableBrush({ + brushType: 'lineX', + brushStyle: areaSelectStyle, + removeOnClick: true + }) + .updateCovers(getCoverInfoList(axisModel)); + }, + + _onBrush: function (coverInfoList, opt) { + // Do not cache these object, because the mey be changed. + var axisModel = this.axisModel; + var axis = axisModel.axis; + var intervals = map(coverInfoList, function (coverInfo) { + return [ + axis.coordToData(coverInfo.range[0], true), + axis.coordToData(coverInfo.range[1], true) + ]; + }); + + // If realtime is true, action is not dispatched on drag end, because + // the drag end emits the same params with the last drag move event, + // and may have some delay when using touch pad. + if (!axisModel.option.realtime === opt.isEnd || opt.removeOnClick) { // jshint ignore:line + this.api.dispatchAction({ + type: 'axisAreaSelect', + parallelAxisId: axisModel.id, + intervals: intervals + }); + } + }, + + /** + * @override + */ + dispose: function () { + this._brushController.dispose(); + } +}); + +function fromAxisAreaSelect(axisModel, ecModel, payload) { + return payload + && payload.type === 'axisAreaSelect' + && ecModel.findComponents( + {mainType: 'parallelAxis', query: payload} + )[0] === axisModel; +} + +function getCoverInfoList(axisModel) { + var axis = axisModel.axis; + return map(axisModel.activeIntervals, function (interval) { + return { + brushType: 'lineX', + panelId: 'pl', + range: [ + axis.dataToCoord(interval[0], true), + axis.dataToCoord(interval[1], true) + ] + }; + }); +} + +function getCoordSysModel(axisModel, ecModel) { + return ecModel.getComponent( + 'parallel', axisModel.get('parallelIndex') + ); +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var CLICK_THRESHOLD = 5; // > 4 + +// Parallel view +extendComponentView({ + type: 'parallel', + + render: function (parallelModel, ecModel, api) { + this._model = parallelModel; + this._api = api; + + if (!this._handlers) { + this._handlers = {}; + each$1(handlers, function (handler, eventName) { + api.getZr().on(eventName, this._handlers[eventName] = bind(handler, this)); + }, this); + } + + createOrUpdate( + this, + '_throttledDispatchExpand', + parallelModel.get('axisExpandRate'), + 'fixRate' + ); + }, + + dispose: function (ecModel, api) { + each$1(this._handlers, function (handler, eventName) { + api.getZr().off(eventName, handler); + }); + this._handlers = null; + }, + + /** + * @param {Object} [opt] If null, cancle the last action triggering for debounce. + */ + _throttledDispatchExpand: function (opt) { + this._dispatchExpand(opt); + }, + + _dispatchExpand: function (opt) { + opt && this._api.dispatchAction( + extend({type: 'parallelAxisExpand'}, opt) + ); + } + +}); + +var handlers = { + + mousedown: function (e) { + if (checkTrigger(this, 'click')) { + this._mouseDownPoint = [e.offsetX, e.offsetY]; + } + }, + + mouseup: function (e) { + var mouseDownPoint = this._mouseDownPoint; + + if (checkTrigger(this, 'click') && mouseDownPoint) { + var point = [e.offsetX, e.offsetY]; + var dist = Math.pow(mouseDownPoint[0] - point[0], 2) + + Math.pow(mouseDownPoint[1] - point[1], 2); + + if (dist > CLICK_THRESHOLD) { + return; + } + + var result = this._model.coordinateSystem.getSlidedAxisExpandWindow( + [e.offsetX, e.offsetY] + ); + + result.behavior !== 'none' && this._dispatchExpand({ + axisExpandWindow: result.axisExpandWindow + }); + } + + this._mouseDownPoint = null; + }, + + mousemove: function (e) { + // Should do nothing when brushing. + if (this._mouseDownPoint || !checkTrigger(this, 'mousemove')) { + return; + } + var model = this._model; + var result = model.coordinateSystem.getSlidedAxisExpandWindow( + [e.offsetX, e.offsetY] + ); + + var behavior = result.behavior; + behavior === 'jump' && this._throttledDispatchExpand.debounceNextCall(model.get('axisExpandDebounce')); + this._throttledDispatchExpand( + behavior === 'none' + ? null // Cancle the last trigger, in case that mouse slide out of the area quickly. + : { + axisExpandWindow: result.axisExpandWindow, + // Jumping uses animation, and sliding suppresses animation. + animation: behavior === 'jump' ? null : false + } + ); + } +}; + +function checkTrigger(view, triggerOn) { + var model = view._model; + return model.get('axisExpandable') && model.get('axisExpandTriggerOn') === triggerOn; +} + +registerPreprocessor(parallelPreprocessor); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +SeriesModel.extend({ + + type: 'series.parallel', + + dependencies: ['parallel'], + + visualColorAccessPath: 'lineStyle.color', + + getInitialData: function (option, ecModel) { + var source = this.getSource(); + + setEncodeAndDimensions(source, this); + + return createListFromArray(source, this); + }, + + /** + * User can get data raw indices on 'axisAreaSelected' event received. + * + * @public + * @param {string} activeState 'active' or 'inactive' or 'normal' + * @return {Array.} Raw indices + */ + getRawIndicesByActiveState: function (activeState) { + var coordSys = this.coordinateSystem; + var data = this.getData(); + var indices = []; + + coordSys.eachActiveState(data, function (theActiveState, dataIndex) { + if (activeState === theActiveState) { + indices.push(data.getRawIndex(dataIndex)); + } + }); + + return indices; + }, + + defaultOption: { + zlevel: 0, // 一级层叠 + z: 2, // 二级层叠 + + coordinateSystem: 'parallel', + parallelIndex: 0, + + label: { + show: false + }, + + inactiveOpacity: 0.05, + activeOpacity: 1, + + lineStyle: { + width: 1, + opacity: 0.45, + type: 'solid' + }, + emphasis: { + label: { + show: false + } + }, + + progressive: 500, + smooth: false, // true | false | number + + animationEasing: 'linear' + } +}); + +function setEncodeAndDimensions(source, seriesModel) { + // The mapping of parallelAxis dimension to data dimension can + // be specified in parallelAxis.option.dim. For example, if + // parallelAxis.option.dim is 'dim3', it mapping to the third + // dimension of data. But `data.encode` has higher priority. + // Moreover, parallelModel.dimension should not be regarded as data + // dimensions. Consider dimensions = ['dim4', 'dim2', 'dim6']; + + if (source.encodeDefine) { + return; + } + + var parallelModel = seriesModel.ecModel.getComponent( + 'parallel', seriesModel.get('parallelIndex') + ); + if (!parallelModel) { + return; + } + + var encodeDefine = source.encodeDefine = createHashMap(); + each$1(parallelModel.dimensions, function (axisDim) { + var dataDimIndex = convertDimNameToNumber(axisDim); + encodeDefine.set(axisDim, dataDimIndex); + }); +} + +function convertDimNameToNumber(dimName) { + return +dimName.replace('dim', ''); +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var DEFAULT_SMOOTH = 0.3; + +var ParallelView = Chart.extend({ + + type: 'parallel', + + init: function () { + + /** + * @type {module:zrender/container/Group} + * @private + */ + this._dataGroup = new Group(); + + this.group.add(this._dataGroup); + + /** + * @type {module:echarts/data/List} + */ + this._data; + + /** + * @type {boolean} + */ + this._initialized; + }, + + /** + * @override + */ + render: function (seriesModel, ecModel, api, payload) { + var dataGroup = this._dataGroup; + var data = seriesModel.getData(); + var oldData = this._data; + var coordSys = seriesModel.coordinateSystem; + var dimensions = coordSys.dimensions; + var seriesScope = makeSeriesScope$2(seriesModel); + + data.diff(oldData) + .add(add) + .update(update) + .remove(remove) + .execute(); + + function add(newDataIndex) { + var line = addEl(data, dataGroup, newDataIndex, dimensions, coordSys); + updateElCommon(line, data, newDataIndex, seriesScope); + } + + function update(newDataIndex, oldDataIndex) { + var line = oldData.getItemGraphicEl(oldDataIndex); + var points = createLinePoints(data, newDataIndex, dimensions, coordSys); + data.setItemGraphicEl(newDataIndex, line); + var animationModel = (payload && payload.animation === false) ? null : seriesModel; + updateProps(line, {shape: {points: points}}, animationModel, newDataIndex); + + updateElCommon(line, data, newDataIndex, seriesScope); + } + + function remove(oldDataIndex) { + var line = oldData.getItemGraphicEl(oldDataIndex); + dataGroup.remove(line); + } + + // First create + if (!this._initialized) { + this._initialized = true; + var clipPath = createGridClipShape$1( + coordSys, seriesModel, function () { + // Callback will be invoked immediately if there is no animation + setTimeout(function () { + dataGroup.removeClipPath(); + }); + } + ); + dataGroup.setClipPath(clipPath); + } + + this._data = data; + }, + + incrementalPrepareRender: function (seriesModel, ecModel, api) { + this._initialized = true; + this._data = null; + this._dataGroup.removeAll(); + }, + + incrementalRender: function (taskParams, seriesModel, ecModel) { + var data = seriesModel.getData(); + var coordSys = seriesModel.coordinateSystem; + var dimensions = coordSys.dimensions; + var seriesScope = makeSeriesScope$2(seriesModel); + + for (var dataIndex = taskParams.start; dataIndex < taskParams.end; dataIndex++) { + var line = addEl(data, this._dataGroup, dataIndex, dimensions, coordSys); + line.incremental = true; + updateElCommon(line, data, dataIndex, seriesScope); + } + }, + + dispose: function () {}, + + // _renderForProgressive: function (seriesModel) { + // var dataGroup = this._dataGroup; + // var data = seriesModel.getData(); + // var oldData = this._data; + // var coordSys = seriesModel.coordinateSystem; + // var dimensions = coordSys.dimensions; + // var option = seriesModel.option; + // var progressive = option.progressive; + // var smooth = option.smooth ? SMOOTH : null; + + // // In progressive animation is disabled, so use simple data diff, + // // which effects performance less. + // // (Typically performance for data with length 7000+ like: + // // simpleDiff: 60ms, addEl: 184ms, + // // in RMBP 2.4GHz intel i7, OSX 10.9 chrome 50.0.2661.102 (64-bit)) + // if (simpleDiff(oldData, data, dimensions)) { + // dataGroup.removeAll(); + // data.each(function (dataIndex) { + // addEl(data, dataGroup, dataIndex, dimensions, coordSys); + // }); + // } + + // updateElCommon(data, progressive, smooth); + + // // Consider switch between progressive and not. + // data.__plProgressive = true; + // this._data = data; + // }, + + /** + * @override + */ + remove: function () { + this._dataGroup && this._dataGroup.removeAll(); + this._data = null; + } +}); + +function createGridClipShape$1(coordSys, seriesModel, cb) { + var parallelModel = coordSys.model; + var rect = coordSys.getRect(); + var rectEl = new Rect({ + shape: { + x: rect.x, + y: rect.y, + width: rect.width, + height: rect.height + } + }); + + var dim = parallelModel.get('layout') === 'horizontal' ? 'width' : 'height'; + rectEl.setShape(dim, 0); + initProps(rectEl, { + shape: { + width: rect.width, + height: rect.height + } + }, seriesModel, cb); + return rectEl; +} + +function createLinePoints(data, dataIndex, dimensions, coordSys) { + var points = []; + for (var i = 0; i < dimensions.length; i++) { + var dimName = dimensions[i]; + var value = data.get(data.mapDimension(dimName), dataIndex); + if (!isEmptyValue(value, coordSys.getAxis(dimName).type)) { + points.push(coordSys.dataToPoint(value, dimName)); + } + } + return points; +} + +function addEl(data, dataGroup, dataIndex, dimensions, coordSys) { + var points = createLinePoints(data, dataIndex, dimensions, coordSys); + var line = new Polyline({ + shape: {points: points}, + silent: true, + z2: 10 + }); + dataGroup.add(line); + data.setItemGraphicEl(dataIndex, line); + return line; +} + +function makeSeriesScope$2(seriesModel) { + var smooth = seriesModel.get('smooth', true); + smooth === true && (smooth = DEFAULT_SMOOTH); + return { + lineStyle: seriesModel.getModel('lineStyle').getLineStyle(), + smooth: smooth != null ? smooth : DEFAULT_SMOOTH + }; +} + +function updateElCommon(el, data, dataIndex, seriesScope) { + var lineStyle = seriesScope.lineStyle; + + if (data.hasItemOption) { + var lineStyleModel = data.getItemModel(dataIndex).getModel('lineStyle'); + lineStyle = lineStyleModel.getLineStyle(); + } + + el.useStyle(lineStyle); + + var elStyle = el.style; + elStyle.fill = null; + // lineStyle.color have been set to itemVisual in module:echarts/visual/seriesColor. + elStyle.stroke = data.getItemVisual(dataIndex, 'color'); + // lineStyle.opacity have been set to itemVisual in parallelVisual. + elStyle.opacity = data.getItemVisual(dataIndex, 'opacity'); + + seriesScope.smooth && (el.shape.smooth = seriesScope.smooth); +} + +// function simpleDiff(oldData, newData, dimensions) { +// var oldLen; +// if (!oldData +// || !oldData.__plProgressive +// || (oldLen = oldData.count()) !== newData.count() +// ) { +// return true; +// } + +// var dimLen = dimensions.length; +// for (var i = 0; i < oldLen; i++) { +// for (var j = 0; j < dimLen; j++) { +// if (oldData.get(dimensions[j], i) !== newData.get(dimensions[j], i)) { +// return true; +// } +// } +// } + +// return false; +// } + +// FIXME +// 公用方法? +function isEmptyValue(val, axisType) { + return axisType === 'category' + ? val == null + : (val == null || isNaN(val)); // axisType === 'value' +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + + +var opacityAccessPath$1 = ['lineStyle', 'normal', 'opacity']; + +var parallelVisual = { + + seriesType: 'parallel', + + reset: function (seriesModel, ecModel, api) { + + var itemStyleModel = seriesModel.getModel('itemStyle'); + var lineStyleModel = seriesModel.getModel('lineStyle'); + var globalColors = ecModel.get('color'); + + var color = lineStyleModel.get('color') + || itemStyleModel.get('color') + || globalColors[seriesModel.seriesIndex % globalColors.length]; + var inactiveOpacity = seriesModel.get('inactiveOpacity'); + var activeOpacity = seriesModel.get('activeOpacity'); + var lineStyle = seriesModel.getModel('lineStyle').getLineStyle(); + + var coordSys = seriesModel.coordinateSystem; + var data = seriesModel.getData(); + + var opacityMap = { + normal: lineStyle.opacity, + active: activeOpacity, + inactive: inactiveOpacity + }; + + data.setVisual('color', color); + + function progress(params, data) { + coordSys.eachActiveState(data, function (activeState, dataIndex) { + var opacity = opacityMap[activeState]; + if (activeState === 'normal' && data.hasItemOption) { + var itemOpacity = data.getItemModel(dataIndex).get(opacityAccessPath$1, true); + itemOpacity != null && (opacity = itemOpacity); + } + data.setItemVisual(dataIndex, 'opacity', opacity); + }, params.start, params.end); + } + + return {progress: progress}; + } +}; + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +registerVisual(parallelVisual); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/** + * @file Get initial data and define sankey view's series model + * @author Deqing Li(annong035@gmail.com) + */ + +var SankeySeries = SeriesModel.extend({ + + type: 'series.sankey', + + layoutInfo: null, + + /** + * Init a graph data structure from data in option series + * + * @param {Object} option the object used to config echarts view + * @return {module:echarts/data/List} storage initial data + */ + getInitialData: function (option) { + var links = option.edges || option.links; + var nodes = option.data || option.nodes; + if (nodes && links) { + var graph = createGraphFromNodeEdge(nodes, links, this, true); + return graph.data; + } + }, + + setNodePosition: function (dataIndex, localPosition) { + var dataItem = this.option.data[dataIndex]; + dataItem.localX = localPosition[0]; + dataItem.localY = localPosition[1]; + }, + + /** + * Return the graphic data structure + * + * @return {module:echarts/data/Graph} graphic data structure + */ + getGraph: function () { + return this.getData().graph; + }, + + /** + * Get edge data of graphic data structure + * + * @return {module:echarts/data/List} data structure of list + */ + getEdgeData: function () { + return this.getGraph().edgeData; + }, + + /** + * @override + */ + formatTooltip: function (dataIndex, multipleSeries, dataType) { + // dataType === 'node' or empty do not show tooltip by default + if (dataType === 'edge') { + var params = this.getDataParams(dataIndex, dataType); + var rawDataOpt = params.data; + var html = rawDataOpt.source + ' -- ' + rawDataOpt.target; + if (params.value) { + html += ' : ' + params.value; + } + return encodeHTML(html); + } + + return SankeySeries.superCall(this, 'formatTooltip', dataIndex, multipleSeries); + }, + + optionUpdated: function () { + var option = this.option; + if (option.focusNodeAdjacency === true) { + option.focusNodeAdjacency = 'allEdges'; + } + }, + + defaultOption: { + zlevel: 0, + z: 2, + + coordinateSystem: 'view', + + layout: null, + + // The position of the whole view + left: '5%', + top: '5%', + right: '20%', + bottom: '5%', + + // Value can be 'vertical' + orient: 'horizontal', + + // The dx of the node + nodeWidth: 20, + + // The vertical distance between two nodes + nodeGap: 8, + + // Control if the node can move or not + draggable: true, + + // Value can be 'inEdges', 'outEdges', 'allEdges', true (the same as 'allEdges'). + focusNodeAdjacency: false, + + // The number of iterations to change the position of the node + layoutIterations: 32, + + label: { + show: true, + position: 'right', + color: '#000', + fontSize: 12 + }, + + itemStyle: { + borderWidth: 1, + borderColor: '#333' + }, + + lineStyle: { + color: '#314656', + opacity: 0.2, + curveness: 0.5 + }, + + emphasis: { + label: { + show: true + }, + lineStyle: { + opacity: 0.6 + } + }, + + animationEasing: 'linear', + + animationDuration: 1000 + } + +}); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/** + * @file The file used to draw sankey view + * @author Deqing Li(annong035@gmail.com) + */ + +var nodeOpacityPath$1 = ['itemStyle', 'opacity']; +var lineOpacityPath$1 = ['lineStyle', 'opacity']; + +function getItemOpacity$1(item, opacityPath) { + return item.getVisual('opacity') || item.getModel().get(opacityPath); +} + +function fadeOutItem$1(item, opacityPath, opacityRatio) { + var el = item.getGraphicEl(); + + var opacity = getItemOpacity$1(item, opacityPath); + if (opacityRatio != null) { + opacity == null && (opacity = 1); + opacity *= opacityRatio; + } + + el.downplay && el.downplay(); + el.traverse(function (child) { + if (child.type !== 'group') { + child.setStyle('opacity', opacity); + } + }); +} + +function fadeInItem$1(item, opacityPath) { + var opacity = getItemOpacity$1(item, opacityPath); + var el = item.getGraphicEl(); + + el.highlight && el.highlight(); + el.traverse(function (child) { + if (child.type !== 'group') { + child.setStyle('opacity', opacity); + } + }); +} + +var SankeyShape = extendShape({ + shape: { + x1: 0, y1: 0, + x2: 0, y2: 0, + cpx1: 0, cpy1: 0, + cpx2: 0, cpy2: 0, + extent: 0, + orient: '' + }, + + buildPath: function (ctx, shape) { + var extent = shape.extent; + var orient = shape.orient; + if (orient === 'vertical') { + ctx.moveTo(shape.x1, shape.y1); + ctx.bezierCurveTo( + shape.cpx1, shape.cpy1, + shape.cpx2, shape.cpy2, + shape.x2, shape.y2 + ); + ctx.lineTo(shape.x2 + extent, shape.y2); + ctx.bezierCurveTo( + shape.cpx2 + extent, shape.cpy2, + shape.cpx1 + extent, shape.cpy1, + shape.x1 + extent, shape.y1 + ); + } + else { + ctx.moveTo(shape.x1, shape.y1); + ctx.bezierCurveTo( + shape.cpx1, shape.cpy1, + shape.cpx2, shape.cpy2, + shape.x2, shape.y2 + ); + ctx.lineTo(shape.x2, shape.y2 + extent); + ctx.bezierCurveTo( + shape.cpx2, shape.cpy2 + extent, + shape.cpx1, shape.cpy1 + extent, + shape.x1, shape.y1 + extent + ); + } + ctx.closePath(); + } +}); + +extendChartView({ + + type: 'sankey', + + /** + * @private + * @type {module:echarts/chart/sankey/SankeySeries} + */ + _model: null, + + /** + * @private + * @type {boolean} + */ + _focusAdjacencyDisabled: false, + + render: function (seriesModel, ecModel, api) { + var sankeyView = this; + var graph = seriesModel.getGraph(); + var group = this.group; + var layoutInfo = seriesModel.layoutInfo; + // view width + var width = layoutInfo.width; + // view height + var height = layoutInfo.height; + var nodeData = seriesModel.getData(); + var edgeData = seriesModel.getData('edge'); + var orient = seriesModel.get('orient'); + + this._model = seriesModel; + + group.removeAll(); + + group.attr('position', [layoutInfo.x, layoutInfo.y]); + + // generate a bezire Curve for each edge + graph.eachEdge(function (edge) { + var curve = new SankeyShape(); + curve.dataIndex = edge.dataIndex; + curve.seriesIndex = seriesModel.seriesIndex; + curve.dataType = 'edge'; + var lineStyleModel = edge.getModel('lineStyle'); + var curvature = lineStyleModel.get('curveness'); + var n1Layout = edge.node1.getLayout(); + var node1Model = edge.node1.getModel(); + var dragX1 = node1Model.get('localX'); + var dragY1 = node1Model.get('localY'); + var n2Layout = edge.node2.getLayout(); + var node2Model = edge.node2.getModel(); + var dragX2 = node2Model.get('localX'); + var dragY2 = node2Model.get('localY'); + var edgeLayout = edge.getLayout(); + var x1; + var y1; + var x2; + var y2; + var cpx1; + var cpy1; + var cpx2; + var cpy2; + + curve.shape.extent = Math.max(1, edgeLayout.dy); + curve.shape.orient = orient; + + if (orient === 'vertical') { + x1 = (dragX1 != null ? dragX1 * width : n1Layout.x) + edgeLayout.sy; + y1 = (dragY1 != null ? dragY1 * height : n1Layout.y) + n1Layout.dy; + x2 = (dragX2 != null ? dragX2 * width : n2Layout.x) + edgeLayout.ty; + y2 = dragY2 != null ? dragY2 * height : n2Layout.y; + cpx1 = x1; + cpy1 = y1 * (1 - curvature) + y2 * curvature; + cpx2 = x2; + cpy2 = y1 * curvature + y2 * (1 - curvature); + } + else { + x1 = (dragX1 != null ? dragX1 * width : n1Layout.x) + n1Layout.dx; + y1 = (dragY1 != null ? dragY1 * height : n1Layout.y) + edgeLayout.sy; + x2 = dragX2 != null ? dragX2 * width : n2Layout.x; + y2 = (dragY2 != null ? dragY2 * height : n2Layout.y) + edgeLayout.ty; + cpx1 = x1 * (1 - curvature) + x2 * curvature; + cpy1 = y1; + cpx2 = x1 * curvature + x2 * (1 - curvature); + cpy2 = y2; + } + + curve.setShape({ + x1: x1, + y1: y1, + x2: x2, + y2: y2, + cpx1: cpx1, + cpy1: cpy1, + cpx2: cpx2, + cpy2: cpy2 + }); + + curve.setStyle(lineStyleModel.getItemStyle()); + // Special color, use source node color or target node color + switch (curve.style.fill) { + case 'source': + curve.style.fill = edge.node1.getVisual('color'); + break; + case 'target': + curve.style.fill = edge.node2.getVisual('color'); + break; + } + + setHoverStyle(curve, edge.getModel('emphasis.lineStyle').getItemStyle()); + + group.add(curve); + + edgeData.setItemGraphicEl(edge.dataIndex, curve); + }); + + // Generate a rect for each node + graph.eachNode(function (node) { + var layout = node.getLayout(); + var itemModel = node.getModel(); + var dragX = itemModel.get('localX'); + var dragY = itemModel.get('localY'); + var labelModel = itemModel.getModel('label'); + var labelHoverModel = itemModel.getModel('emphasis.label'); + + var rect = new Rect({ + shape: { + x: dragX != null ? dragX * width : layout.x, + y: dragY != null ? dragY * height : layout.y, + width: layout.dx, + height: layout.dy + }, + style: itemModel.getModel('itemStyle').getItemStyle() + }); + + var hoverStyle = node.getModel('emphasis.itemStyle').getItemStyle(); + + setLabelStyle( + rect.style, hoverStyle, labelModel, labelHoverModel, + { + labelFetcher: seriesModel, + labelDataIndex: node.dataIndex, + defaultText: node.id, + isRectText: true + } + ); + + rect.setStyle('fill', node.getVisual('color')); + + setHoverStyle(rect, hoverStyle); + + group.add(rect); + + nodeData.setItemGraphicEl(node.dataIndex, rect); + + rect.dataType = 'node'; + }); + + nodeData.eachItemGraphicEl(function (el, dataIndex) { + var itemModel = nodeData.getItemModel(dataIndex); + if (itemModel.get('draggable')) { + el.drift = function (dx, dy) { + sankeyView._focusAdjacencyDisabled = true; + this.shape.x += dx; + this.shape.y += dy; + this.dirty(); + api.dispatchAction({ + type: 'dragNode', + seriesId: seriesModel.id, + dataIndex: nodeData.getRawIndex(dataIndex), + localX: this.shape.x / width, + localY: this.shape.y / height + }); + }; + el.ondragend = function () { + sankeyView._focusAdjacencyDisabled = false; + }; + el.draggable = true; + el.cursor = 'move'; + } + + if (itemModel.get('focusNodeAdjacency')) { + el.off('mouseover').on('mouseover', function () { + if (!sankeyView._focusAdjacencyDisabled) { + api.dispatchAction({ + type: 'focusNodeAdjacency', + seriesId: seriesModel.id, + dataIndex: el.dataIndex + }); + } + }); + el.off('mouseout').on('mouseout', function () { + if (!sankeyView._focusAdjacencyDisabled) { + api.dispatchAction({ + type: 'unfocusNodeAdjacency', + seriesId: seriesModel.id + }); + } + }); + } + }); + + edgeData.eachItemGraphicEl(function (el, dataIndex) { + var edgeModel = edgeData.getItemModel(dataIndex); + if (edgeModel.get('focusNodeAdjacency')) { + el.off('mouseover').on('mouseover', function () { + if (!sankeyView._focusAdjacencyDisabled) { + api.dispatchAction({ + type: 'focusNodeAdjacency', + seriesId: seriesModel.id, + edgeDataIndex: el.dataIndex + }); + } + }); + el.off('mouseout').on('mouseout', function () { + if (!sankeyView._focusAdjacencyDisabled) { + api.dispatchAction({ + type: 'unfocusNodeAdjacency', + seriesId: seriesModel.id + }); + } + }); + } + }); + + if (!this._data && seriesModel.get('animation')) { + group.setClipPath(createGridClipShape$2(group.getBoundingRect(), seriesModel, function () { + group.removeClipPath(); + })); + } + + this._data = seriesModel.getData(); + }, + + dispose: function () {}, + + focusNodeAdjacency: function (seriesModel, ecModel, api, payload) { + var data = this._model.getData(); + var graph = data.graph; + var dataIndex = payload.dataIndex; + var itemModel = data.getItemModel(dataIndex); + var edgeDataIndex = payload.edgeDataIndex; + + if (dataIndex == null && edgeDataIndex == null) { + return; + } + var node = graph.getNodeByIndex(dataIndex); + var edge = graph.getEdgeByIndex(edgeDataIndex); + + graph.eachNode(function (node) { + fadeOutItem$1(node, nodeOpacityPath$1, 0.1); + }); + graph.eachEdge(function (edge) { + fadeOutItem$1(edge, lineOpacityPath$1, 0.1); + }); + + if (node) { + fadeInItem$1(node, nodeOpacityPath$1); + var focusNodeAdj = itemModel.get('focusNodeAdjacency'); + if (focusNodeAdj === 'outEdges') { + each$1(node.outEdges, function (edge) { + if (edge.dataIndex < 0) { + return; + } + fadeInItem$1(edge, lineOpacityPath$1); + fadeInItem$1(edge.node2, nodeOpacityPath$1); + }); + } + else if (focusNodeAdj === 'inEdges') { + each$1(node.inEdges, function (edge) { + if (edge.dataIndex < 0) { + return; + } + fadeInItem$1(edge, lineOpacityPath$1); + fadeInItem$1(edge.node1, nodeOpacityPath$1); + }); + } + else if (focusNodeAdj === 'allEdges') { + each$1(node.edges, function (edge) { + if (edge.dataIndex < 0) { + return; + } + fadeInItem$1(edge, lineOpacityPath$1); + fadeInItem$1(edge.node1, nodeOpacityPath$1); + fadeInItem$1(edge.node2, nodeOpacityPath$1); + }); + } + } + if (edge) { + fadeInItem$1(edge, lineOpacityPath$1); + fadeInItem$1(edge.node1, nodeOpacityPath$1); + fadeInItem$1(edge.node2, nodeOpacityPath$1); + } + }, + + unfocusNodeAdjacency: function (seriesModel, ecModel, api, payload) { + var graph = this._model.getGraph(); + + graph.eachNode(function (node) { + fadeOutItem$1(node, nodeOpacityPath$1); + }); + graph.eachEdge(function (edge) { + fadeOutItem$1(edge, lineOpacityPath$1); + }); + } +}); + +// Add animation to the view +function createGridClipShape$2(rect, seriesModel, cb) { + var rectEl = new Rect({ + shape: { + x: rect.x - 10, + y: rect.y - 10, + width: 0, + height: rect.height + 20 + } + }); + initProps(rectEl, { + shape: { + width: rect.width + 20, + height: rect.height + 20 + } + }, seriesModel, cb); + + return rectEl; +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/** + * @file The interactive action of sankey view + * @author Deqing Li(annong035@gmail.com) + */ + +registerAction({ + type: 'dragNode', + event: 'dragNode', + // here can only use 'update' now, other value is not support in echarts. + update: 'update' +}, function (payload, ecModel) { + ecModel.eachComponent({mainType: 'series', subType: 'sankey', query: payload}, function (seriesModel) { + seriesModel.setNodePosition(payload.dataIndex, [payload.localX, payload.localY]); + }); +}); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/** + * @file The layout algorithm of sankey view + * @author Deqing Li(annong035@gmail.com) + */ + +var sankeyLayout = function (ecModel, api, payload) { + + ecModel.eachSeriesByType('sankey', function (seriesModel) { + + var nodeWidth = seriesModel.get('nodeWidth'); + var nodeGap = seriesModel.get('nodeGap'); + + var layoutInfo = getViewRect$3(seriesModel, api); + + seriesModel.layoutInfo = layoutInfo; + + var width = layoutInfo.width; + var height = layoutInfo.height; + + var graph = seriesModel.getGraph(); + + var nodes = graph.nodes; + var edges = graph.edges; + + computeNodeValues(nodes); + + var filteredNodes = filter(nodes, function (node) { + return node.getLayout().value === 0; + }); + + var iterations = filteredNodes.length !== 0 + ? 0 : seriesModel.get('layoutIterations'); + + var orient = seriesModel.get('orient'); + + layoutSankey(nodes, edges, nodeWidth, nodeGap, width, height, iterations, orient); + }); +}; + +/** + * Get the layout position of the whole view + * + * @param {module:echarts/model/Series} seriesModel the model object of sankey series + * @param {module:echarts/ExtensionAPI} api provide the API list that the developer can call + * @return {module:zrender/core/BoundingRect} size of rect to draw the sankey view + */ +function getViewRect$3(seriesModel, api) { + return getLayoutRect( + seriesModel.getBoxLayoutParams(), { + width: api.getWidth(), + height: api.getHeight() + } + ); +} + +function layoutSankey(nodes, edges, nodeWidth, nodeGap, width, height, iterations, orient) { + computeNodeBreadths(nodes, edges, nodeWidth, width, height, orient); + computeNodeDepths(nodes, edges, height, width, nodeGap, iterations, orient); + computeEdgeDepths(nodes, orient); +} + +/** + * Compute the value of each node by summing the associated edge's value + * + * @param {module:echarts/data/Graph~Node} nodes node of sankey view + */ +function computeNodeValues(nodes) { + each$1(nodes, function (node) { + var value1 = sum(node.outEdges, getEdgeValue); + var value2 = sum(node.inEdges, getEdgeValue); + var value = Math.max(value1, value2); + node.setLayout({value: value}, true); + }); +} + +/** + * Compute the x-position for each node. + * + * Here we use Kahn algorithm to detect cycle when we traverse + * the node to computer the initial x position. + * + * @param {module:echarts/data/Graph~Node} nodes node of sankey view + * @param {number} nodeWidth the dx of the node + * @param {number} width the whole width of the area to draw the view + */ +function computeNodeBreadths(nodes, edges, nodeWidth, width, height, orient) { + // Used to mark whether the edge is deleted. if it is deleted, + // the value is 0, otherwise it is 1. + var remainEdges = []; + + // Storage each node's indegree. + var indegreeArr = []; + + //Used to storage the node with indegree is equal to 0. + var zeroIndegrees = []; + + var nextNode = []; + var x = 0; + var kx = 0; + + for (var i = 0; i < edges.length; i++) { + remainEdges[i] = 1; + } + + for (i = 0; i < nodes.length; i++) { + indegreeArr[i] = nodes[i].inEdges.length; + if (indegreeArr[i] === 0) { + zeroIndegrees.push(nodes[i]); + } + } + + while (zeroIndegrees.length) { + for (var idx = 0; idx < zeroIndegrees.length; idx++) { + var node = zeroIndegrees[idx]; + if (orient === 'vertical') { + node.setLayout({y: x}, true); + node.setLayout({dy: nodeWidth}, true); + } + else { + node.setLayout({x: x}, true); + node.setLayout({dx: nodeWidth}, true); + } + for (var oidx = 0; oidx < node.outEdges.length; oidx++) { + var edge = node.outEdges[oidx]; + var indexEdge = edges.indexOf(edge); + remainEdges[indexEdge] = 0; + var targetNode = edge.node2; + var nodeIndex = nodes.indexOf(targetNode); + if (--indegreeArr[nodeIndex] === 0) { + nextNode.push(targetNode); + } + } + } + ++x; + zeroIndegrees = nextNode; + nextNode = []; + } + + for (i = 0; i < remainEdges.length; i++) { + if (__DEV__) { + if (remainEdges[i] === 1) { + throw new Error('Sankey is a DAG, the original data has cycle!'); + } + } + } + + moveSinksRight(nodes, x, orient); + + if (orient === 'vertical') { + kx = (height - nodeWidth) / (x - 1); + } + else { + kx = (width - nodeWidth) / (x - 1); + } + scaleNodeBreadths(nodes, kx, orient); +} + +/** + * All the node without outEgdes are assigned maximum x-position and + * be aligned in the last column. + * + * @param {module:echarts/data/Graph~Node} nodes node of sankey view + * @param {number} x value (x-1) use to assign to node without outEdges + * as x-position + */ +function moveSinksRight(nodes, x, orient) { + each$1(nodes, function (node) { + if (!node.outEdges.length) { + if (orient === 'vertical') { + node.setLayout({y: x - 1}, true); + } + else { + node.setLayout({x: x - 1}, true); + } + } + }); +} + +/** + * Scale node x-position to the width + * + * @param {module:echarts/data/Graph~Node} nodes node of sankey view + * @param {number} kx multiple used to scale nodes + */ +function scaleNodeBreadths(nodes, kx, orient) { + each$1(nodes, function (node) { + if (orient === 'vertical') { + var nodeY = node.getLayout().y * kx; + node.setLayout({y: nodeY}, true); + } + else { + var nodeX = node.getLayout().x * kx; + node.setLayout({x: nodeX}, true); + } + }); +} + +/** + * Using Gauss-Seidel iterations method to compute the node depth(y-position) + * + * @param {module:echarts/data/Graph~Node} nodes node of sankey view + * @param {module:echarts/data/Graph~Edge} edges edge of sankey view + * @param {number} height the whole height of the area to draw the view + * @param {number} nodeGap the vertical distance between two nodes + * in the same column. + * @param {number} iterations the number of iterations for the algorithm + */ +function computeNodeDepths(nodes, edges, height, width, nodeGap, iterations, orient) { + var nodesByBreadth = prepareNodesByBreadth(nodes, orient); + + initializeNodeDepth(nodes, nodesByBreadth, edges, height, width, nodeGap, orient); + resolveCollisions(nodesByBreadth, nodeGap, height, width, orient); + + for (var alpha = 1; iterations > 0; iterations--) { + // 0.99 is a experience parameter, ensure that each iterations of + // changes as small as possible. + alpha *= 0.99; + relaxRightToLeft(nodesByBreadth, alpha, orient); + resolveCollisions(nodesByBreadth, nodeGap, height, width, orient); + relaxLeftToRight(nodesByBreadth, alpha, orient); + resolveCollisions(nodesByBreadth, nodeGap, height, width, orient); + } +} + +function prepareNodesByBreadth(nodes, orient) { + var nodesByBreadth = []; + var keyAttr = orient === 'vertical' ? 'y' : 'x'; + + var groupResult = groupData(nodes, function (node) { + return node.getLayout()[keyAttr]; + }); + groupResult.keys.sort(function (a, b) { + return a - b; + }); + each$1(groupResult.keys, function (key) { + nodesByBreadth.push(groupResult.buckets.get(key)); + }); + + return nodesByBreadth; +} + +/** + * Compute the original y-position for each node + * + * @param {module:echarts/data/Graph~Node} nodes node of sankey view + * @param {Array.>} nodesByBreadth + * group by the array of all sankey nodes based on the nodes x-position. + * @param {module:echarts/data/Graph~Edge} edges edge of sankey view + * @param {number} height the whole height of the area to draw the view + * @param {number} nodeGap the vertical distance between two nodes + */ +function initializeNodeDepth(nodes, nodesByBreadth, edges, height, width, nodeGap, orient) { + var kyArray = []; + each$1(nodesByBreadth, function (nodes) { + var n = nodes.length; + var sum = 0; + var ky = 0; + each$1(nodes, function (node) { + sum += node.getLayout().value; + }); + if (orient === 'vertical') { + ky = (width - (n - 1) * nodeGap) / sum; + } + else { + ky = (height - (n - 1) * nodeGap) / sum; + } + kyArray.push(ky); + }); + + kyArray.sort(function (a, b) { + return a - b; + }); + var ky0 = kyArray[0]; + + each$1(nodesByBreadth, function (nodes) { + each$1(nodes, function (node, i) { + var nodeDy = node.getLayout().value * ky0; + if (orient === 'vertical') { + node.setLayout({x: i}, true); + node.setLayout({dx: nodeDy}, true); + } + else { + node.setLayout({y: i}, true); + node.setLayout({dy: nodeDy}, true); + } + + }); + }); + + each$1(edges, function (edge) { + var edgeDy = +edge.getValue() * ky0; + edge.setLayout({dy: edgeDy}, true); + }); +} + +/** + * Resolve the collision of initialized depth (y-position) + * + * @param {Array.>} nodesByBreadth + * group by the array of all sankey nodes based on the nodes x-position. + * @param {number} nodeGap the vertical distance between two nodes + * @param {number} height the whole height of the area to draw the view + */ +function resolveCollisions(nodesByBreadth, nodeGap, height, width, orient) { + each$1(nodesByBreadth, function (nodes) { + var node; + var dy; + var y0 = 0; + var n = nodes.length; + var i; + + if (orient === 'vertical') { + var nodeX; + nodes.sort(function (a, b) { + return a.getLayout().x - b.getLayout().x; + }); + for (i = 0; i < n; i++) { + node = nodes[i]; + dy = y0 - node.getLayout().x; + if (dy > 0) { + nodeX = node.getLayout().x + dy; + node.setLayout({x: nodeX}, true); + } + y0 = node.getLayout().x + node.getLayout().dx + nodeGap; + } + // If the bottommost node goes outside the bounds, push it back up + dy = y0 - nodeGap - width; + if (dy > 0) { + nodeX = node.getLayout().x - dy; + node.setLayout({x: nodeX}, true); + y0 = nodeX; + for (i = n - 2; i >= 0; --i) { + node = nodes[i]; + dy = node.getLayout().x + node.getLayout().dx + nodeGap - y0; + if (dy > 0) { + nodeX = node.getLayout().x - dy; + node.setLayout({x: nodeX}, true); + } + y0 = node.getLayout().x; + } + } + } + else { + var nodeY; + nodes.sort(function (a, b) { + return a.getLayout().y - b.getLayout().y; + }); + for (i = 0; i < n; i++) { + node = nodes[i]; + dy = y0 - node.getLayout().y; + if (dy > 0) { + nodeY = node.getLayout().y + dy; + node.setLayout({y: nodeY}, true); + } + y0 = node.getLayout().y + node.getLayout().dy + nodeGap; + } + // If the bottommost node goes outside the bounds, push it back up + dy = y0 - nodeGap - height; + if (dy > 0) { + nodeY = node.getLayout().y - dy; + node.setLayout({y: nodeY}, true); + y0 = nodeY; + for (i = n - 2; i >= 0; --i) { + node = nodes[i]; + dy = node.getLayout().y + node.getLayout().dy + nodeGap - y0; + if (dy > 0) { + nodeY = node.getLayout().y - dy; + node.setLayout({y: nodeY}, true); + } + y0 = node.getLayout().y; + } + } + } + }); +} + +/** + * Change the y-position of the nodes, except most the right side nodes + * + * @param {Array.>} nodesByBreadth + * group by the array of all sankey nodes based on the node x-position. + * @param {number} alpha parameter used to adjust the nodes y-position + */ +function relaxRightToLeft(nodesByBreadth, alpha, orient) { + each$1(nodesByBreadth.slice().reverse(), function (nodes) { + each$1(nodes, function (node) { + if (node.outEdges.length) { + var y = sum(node.outEdges, weightedTarget, orient) / sum(node.outEdges, getEdgeValue, orient); + if (orient === 'vertical') { + var nodeX = node.getLayout().x + (y - center$1(node, orient)) * alpha; + node.setLayout({x: nodeX}, true); + } + else { + var nodeY = node.getLayout().y + (y - center$1(node, orient)) * alpha; + node.setLayout({y: nodeY}, true); + } + } + }); + }); +} + +function weightedTarget(edge, orient) { + return center$1(edge.node2, orient) * edge.getValue(); +} + +function weightedSource(edge, orient) { + return center$1(edge.node1, orient) * edge.getValue(); +} + +function center$1(node, orient) { + if (orient === 'vertical') { + return node.getLayout().x + node.getLayout().dx / 2; + } + return node.getLayout().y + node.getLayout().dy / 2; +} + +function getEdgeValue(edge) { + return edge.getValue(); +} + +function sum(array, f, orient) { + var sum = 0; + var len = array.length; + var i = -1; + while (++i < len) { + var value = +f.call(array, array[i], orient); + if (!isNaN(value)) { + sum += value; + } + } + return sum; +} + +/** + * Change the y-position of the nodes, except most the left side nodes + * + * @param {Array.>} nodesByBreadth + * group by the array of all sankey nodes based on the node x-position. + * @param {number} alpha parameter used to adjust the nodes y-position + */ +function relaxLeftToRight(nodesByBreadth, alpha, orient) { + each$1(nodesByBreadth, function (nodes) { + each$1(nodes, function (node) { + if (node.inEdges.length) { + var y = sum(node.inEdges, weightedSource, orient) / sum(node.inEdges, getEdgeValue, orient); + if (orient === 'vertical') { + var nodeX = node.getLayout().x + (y - center$1(node, orient)) * alpha; + node.setLayout({x: nodeX}, true); + } + else { + var nodeY = node.getLayout().y + (y - center$1(node, orient)) * alpha; + node.setLayout({y: nodeY}, true); + } + } + }); + }); +} + +/** + * Compute the depth(y-position) of each edge + * + * @param {module:echarts/data/Graph~Node} nodes node of sankey view + */ +function computeEdgeDepths(nodes, orient) { + each$1(nodes, function (node) { + if (orient === 'vertical') { + node.outEdges.sort(function (a, b) { + return a.node2.getLayout().x - b.node2.getLayout().x; + }); + node.inEdges.sort(function (a, b) { + return a.node1.getLayout().x - b.node1.getLayout().x; + }); + } + else { + node.outEdges.sort(function (a, b) { + return a.node2.getLayout().y - b.node2.getLayout().y; + }); + node.inEdges.sort(function (a, b) { + return a.node1.getLayout().y - b.node1.getLayout().y; + }); + } + }); + each$1(nodes, function (node) { + var sy = 0; + var ty = 0; + each$1(node.outEdges, function (edge) { + edge.setLayout({sy: sy}, true); + sy += edge.getLayout().dy; + }); + each$1(node.inEdges, function (edge) { + edge.setLayout({ty: ty}, true); + ty += edge.getLayout().dy; + }); + }); +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/** + * @file Visual encoding for sankey view + * @author Deqing Li(annong035@gmail.com) + */ + +var sankeyVisual = function (ecModel, payload) { + ecModel.eachSeriesByType('sankey', function (seriesModel) { + var graph = seriesModel.getGraph(); + var nodes = graph.nodes; + if (nodes.length) { + var minValue = Infinity; + var maxValue = -Infinity; + each$1(nodes, function (node) { + var nodeValue = node.getLayout().value; + if (nodeValue < minValue) { + minValue = nodeValue; + } + if (nodeValue > maxValue) { + maxValue = nodeValue; + } + }); + + each$1(nodes, function (node) { + var mapping = new VisualMapping({ + type: 'color', + mappingMethod: 'linear', + dataExtent: [minValue, maxValue], + visual: seriesModel.get('color') + }); + + var mapValueToColor = mapping.mapValueToVisual(node.getLayout().value); + node.setVisual('color', mapValueToColor); + // If set itemStyle.normal.color + var itemModel = node.getModel(); + var customColor = itemModel.get('itemStyle.color'); + if (customColor != null) { + node.setVisual('color', customColor); + } + }); + } + }); +}; + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +registerLayout(sankeyLayout); +registerVisual(sankeyVisual); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + + +var seriesModelMixin = { + + /** + * @private + * @type {string} + */ + _baseAxisDim: null, + + /** + * @override + */ + getInitialData: function (option, ecModel) { + // When both types of xAxis and yAxis are 'value', layout is + // needed to be specified by user. Otherwise, layout can be + // judged by which axis is category. + + var ordinalMeta; + + var xAxisModel = ecModel.getComponent('xAxis', this.get('xAxisIndex')); + var yAxisModel = ecModel.getComponent('yAxis', this.get('yAxisIndex')); + var xAxisType = xAxisModel.get('type'); + var yAxisType = yAxisModel.get('type'); + var addOrdinal; + + // FIXME + // 考虑时间轴 + + if (xAxisType === 'category') { + option.layout = 'horizontal'; + ordinalMeta = xAxisModel.getOrdinalMeta(); + addOrdinal = true; + } + else if (yAxisType === 'category') { + option.layout = 'vertical'; + ordinalMeta = yAxisModel.getOrdinalMeta(); + addOrdinal = true; + } + else { + option.layout = option.layout || 'horizontal'; + } + + var coordDims = ['x', 'y']; + var baseAxisDimIndex = option.layout === 'horizontal' ? 0 : 1; + var baseAxisDim = this._baseAxisDim = coordDims[baseAxisDimIndex]; + var otherAxisDim = coordDims[1 - baseAxisDimIndex]; + var axisModels = [xAxisModel, yAxisModel]; + var baseAxisType = axisModels[baseAxisDimIndex].get('type'); + var otherAxisType = axisModels[1 - baseAxisDimIndex].get('type'); + var data = option.data; + + // ??? FIXME make a stage to perform data transfrom. + // MUST create a new data, consider setOption({}) again. + if (data && addOrdinal) { + var newOptionData = []; + each$1(data, function (item, index) { + var newItem; + if (item.value && isArray(item.value)) { + newItem = item.value.slice(); + item.value.unshift(index); + } + else if (isArray(item)) { + newItem = item.slice(); + item.unshift(index); + } + else { + newItem = item; + } + newOptionData.push(newItem); + }); + option.data = newOptionData; + } + + var defaultValueDimensions = this.defaultValueDimensions; + + return createListSimply( + this, + { + coordDimensions: [{ + name: baseAxisDim, + type: getDimensionTypeByAxis(baseAxisType), + ordinalMeta: ordinalMeta, + otherDims: { + tooltip: false, + itemName: 0 + }, + dimsDef: ['base'] + }, { + name: otherAxisDim, + type: getDimensionTypeByAxis(otherAxisType), + dimsDef: defaultValueDimensions.slice() + }], + dimensionsCount: defaultValueDimensions.length + 1 + } + ); + }, + + /** + * If horizontal, base axis is x, otherwise y. + * @override + */ + getBaseAxis: function () { + var dim = this._baseAxisDim; + return this.ecModel.getComponent(dim + 'Axis', this.get(dim + 'AxisIndex')).axis; + } + +}; + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var BoxplotSeries = SeriesModel.extend({ + + type: 'series.boxplot', + + dependencies: ['xAxis', 'yAxis', 'grid'], + + // TODO + // box width represents group size, so dimension should have 'size'. + + /** + * @see + * The meanings of 'min' and 'max' depend on user, + * and echarts do not need to know it. + * @readOnly + */ + defaultValueDimensions: [ + {name: 'min', defaultTooltip: true}, + {name: 'Q1', defaultTooltip: true}, + {name: 'median', defaultTooltip: true}, + {name: 'Q3', defaultTooltip: true}, + {name: 'max', defaultTooltip: true} + ], + + /** + * @type {Array.} + * @readOnly + */ + dimensions: null, + + /** + * @override + */ + defaultOption: { + zlevel: 0, // 一级层叠 + z: 2, // 二级层叠 + coordinateSystem: 'cartesian2d', + legendHoverLink: true, + + hoverAnimation: true, + + // xAxisIndex: 0, + // yAxisIndex: 0, + + layout: null, // 'horizontal' or 'vertical' + boxWidth: [7, 50], // [min, max] can be percent of band width. + + itemStyle: { + color: '#fff', + borderWidth: 1 + }, + + emphasis: { + itemStyle: { + borderWidth: 2, + shadowBlur: 5, + shadowOffsetX: 2, + shadowOffsetY: 2, + shadowColor: 'rgba(0,0,0,0.4)' + } + }, + + animationEasing: 'elasticOut', + animationDuration: 800 + } +}); + +mixin(BoxplotSeries, seriesModelMixin, true); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +// Update common properties +var NORMAL_ITEM_STYLE_PATH = ['itemStyle']; +var EMPHASIS_ITEM_STYLE_PATH = ['emphasis', 'itemStyle']; + +var BoxplotView = Chart.extend({ + + type: 'boxplot', + + render: function (seriesModel, ecModel, api) { + var data = seriesModel.getData(); + var group = this.group; + var oldData = this._data; + + // There is no old data only when first rendering or switching from + // stream mode to normal mode, where previous elements should be removed. + if (!this._data) { + group.removeAll(); + } + + var constDim = seriesModel.get('layout') === 'horizontal' ? 1 : 0; + + data.diff(oldData) + .add(function (newIdx) { + if (data.hasValue(newIdx)) { + var itemLayout = data.getItemLayout(newIdx); + var symbolEl = createNormalBox(itemLayout, data, newIdx, constDim, true); + data.setItemGraphicEl(newIdx, symbolEl); + group.add(symbolEl); + } + }) + .update(function (newIdx, oldIdx) { + var symbolEl = oldData.getItemGraphicEl(oldIdx); + + // Empty data + if (!data.hasValue(newIdx)) { + group.remove(symbolEl); + return; + } + + var itemLayout = data.getItemLayout(newIdx); + if (!symbolEl) { + symbolEl = createNormalBox(itemLayout, data, newIdx, constDim); + } + else { + updateNormalBoxData(itemLayout, symbolEl, data, newIdx); + } + + group.add(symbolEl); + + data.setItemGraphicEl(newIdx, symbolEl); + }) + .remove(function (oldIdx) { + var el = oldData.getItemGraphicEl(oldIdx); + el && group.remove(el); + }) + .execute(); + + this._data = data; + }, + + remove: function (ecModel) { + var group = this.group; + var data = this._data; + this._data = null; + data && data.eachItemGraphicEl(function (el) { + el && group.remove(el); + }); + }, + + dispose: noop + +}); + + +var BoxPath = Path.extend({ + + type: 'boxplotBoxPath', + + shape: {}, + + buildPath: function (ctx, shape) { + var ends = shape.points; + + var i = 0; + ctx.moveTo(ends[i][0], ends[i][1]); + i++; + for (; i < 4; i++) { + ctx.lineTo(ends[i][0], ends[i][1]); + } + ctx.closePath(); + + for (; i < ends.length; i++) { + ctx.moveTo(ends[i][0], ends[i][1]); + i++; + ctx.lineTo(ends[i][0], ends[i][1]); + } + } +}); + + +function createNormalBox(itemLayout, data, dataIndex, constDim, isInit) { + var ends = itemLayout.ends; + + var el = new BoxPath({ + shape: { + points: isInit + ? transInit(ends, constDim, itemLayout) + : ends + } + }); + + updateNormalBoxData(itemLayout, el, data, dataIndex, isInit); + + return el; +} + +function updateNormalBoxData(itemLayout, el, data, dataIndex, isInit) { + var seriesModel = data.hostModel; + var updateMethod = graphic[isInit ? 'initProps' : 'updateProps']; + + updateMethod( + el, + {shape: {points: itemLayout.ends}}, + seriesModel, + dataIndex + ); + + var itemModel = data.getItemModel(dataIndex); + var normalItemStyleModel = itemModel.getModel(NORMAL_ITEM_STYLE_PATH); + var borderColor = data.getItemVisual(dataIndex, 'color'); + + // Exclude borderColor. + var itemStyle = normalItemStyleModel.getItemStyle(['borderColor']); + itemStyle.stroke = borderColor; + itemStyle.strokeNoScale = true; + el.useStyle(itemStyle); + + el.z2 = 100; + + var hoverStyle = itemModel.getModel(EMPHASIS_ITEM_STYLE_PATH).getItemStyle(); + setHoverStyle(el, hoverStyle); +} + +function transInit(points, dim, itemLayout) { + return map(points, function (point) { + point = point.slice(); + point[dim] = itemLayout.initBaseline; + return point; + }); +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + + +var borderColorQuery = ['itemStyle', 'borderColor']; + +var boxplotVisual = function (ecModel, api) { + + var globalColors = ecModel.get('color'); + + ecModel.eachRawSeriesByType('boxplot', function (seriesModel) { + + var defaulColor = globalColors[seriesModel.seriesIndex % globalColors.length]; + var data = seriesModel.getData(); + + data.setVisual({ + legendSymbol: 'roundRect', + // Use name 'color' but not 'borderColor' for legend usage and + // visual coding from other component like dataRange. + color: seriesModel.get(borderColorQuery) || defaulColor + }); + + // Only visible series has each data be visual encoded + if (!ecModel.isSeriesFiltered(seriesModel)) { + data.each(function (idx) { + var itemModel = data.getItemModel(idx); + data.setItemVisual( + idx, + {color: itemModel.get(borderColorQuery, true)} + ); + }); + } + }); + +}; + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var each$13 = each$1; + +var boxplotLayout = function (ecModel) { + + var groupResult = groupSeriesByAxis(ecModel); + + each$13(groupResult, function (groupItem) { + var seriesModels = groupItem.seriesModels; + + if (!seriesModels.length) { + return; + } + + calculateBase(groupItem); + + each$13(seriesModels, function (seriesModel, idx) { + layoutSingleSeries( + seriesModel, + groupItem.boxOffsetList[idx], + groupItem.boxWidthList[idx] + ); + }); + }); +}; + +/** + * Group series by axis. + */ +function groupSeriesByAxis(ecModel) { + var result = []; + var axisList = []; + + ecModel.eachSeriesByType('boxplot', function (seriesModel) { + var baseAxis = seriesModel.getBaseAxis(); + var idx = indexOf(axisList, baseAxis); + + if (idx < 0) { + idx = axisList.length; + axisList[idx] = baseAxis; + result[idx] = {axis: baseAxis, seriesModels: []}; + } + + result[idx].seriesModels.push(seriesModel); + }); + + return result; +} + +/** + * Calculate offset and box width for each series. + */ +function calculateBase(groupItem) { + var extent; + var baseAxis = groupItem.axis; + var seriesModels = groupItem.seriesModels; + var seriesCount = seriesModels.length; + + var boxWidthList = groupItem.boxWidthList = []; + var boxOffsetList = groupItem.boxOffsetList = []; + var boundList = []; + + var bandWidth; + if (baseAxis.type === 'category') { + bandWidth = baseAxis.getBandWidth(); + } + else { + var maxDataCount = 0; + each$13(seriesModels, function (seriesModel) { + maxDataCount = Math.max(maxDataCount, seriesModel.getData().count()); + }); + extent = baseAxis.getExtent(), + Math.abs(extent[1] - extent[0]) / maxDataCount; + } + + each$13(seriesModels, function (seriesModel) { + var boxWidthBound = seriesModel.get('boxWidth'); + if (!isArray(boxWidthBound)) { + boxWidthBound = [boxWidthBound, boxWidthBound]; + } + boundList.push([ + parsePercent$1(boxWidthBound[0], bandWidth) || 0, + parsePercent$1(boxWidthBound[1], bandWidth) || 0 + ]); + }); + + var availableWidth = bandWidth * 0.8 - 2; + var boxGap = availableWidth / seriesCount * 0.3; + var boxWidth = (availableWidth - boxGap * (seriesCount - 1)) / seriesCount; + var base = boxWidth / 2 - availableWidth / 2; + + each$13(seriesModels, function (seriesModel, idx) { + boxOffsetList.push(base); + base += boxGap + boxWidth; + + boxWidthList.push( + Math.min(Math.max(boxWidth, boundList[idx][0]), boundList[idx][1]) + ); + }); +} + +/** + * Calculate points location for each series. + */ +function layoutSingleSeries(seriesModel, offset, boxWidth) { + var coordSys = seriesModel.coordinateSystem; + var data = seriesModel.getData(); + var halfWidth = boxWidth / 2; + var cDimIdx = seriesModel.get('layout') === 'horizontal' ? 0 : 1; + var vDimIdx = 1 - cDimIdx; + var coordDims = ['x', 'y']; + var cDim = data.mapDimension(coordDims[cDimIdx]); + var vDims = data.mapDimension(coordDims[vDimIdx], true); + + if (cDim == null || vDims.length < 5) { + return; + } + + for (var dataIndex = 0; dataIndex < data.count(); dataIndex++) { + var axisDimVal = data.get(cDim, dataIndex); + + var median = getPoint(axisDimVal, vDims[2], dataIndex); + var end1 = getPoint(axisDimVal, vDims[0], dataIndex); + var end2 = getPoint(axisDimVal, vDims[1], dataIndex); + var end4 = getPoint(axisDimVal, vDims[3], dataIndex); + var end5 = getPoint(axisDimVal, vDims[4], dataIndex); + + var ends = []; + addBodyEnd(ends, end2, 0); + addBodyEnd(ends, end4, 1); + + ends.push(end1, end2, end5, end4); + layEndLine(ends, end1); + layEndLine(ends, end5); + layEndLine(ends, median); + + data.setItemLayout(dataIndex, { + initBaseline: median[vDimIdx], + ends: ends + }); + } + + function getPoint(axisDimVal, dimIdx, dataIndex) { + var val = data.get(dimIdx, dataIndex); + var p = []; + p[cDimIdx] = axisDimVal; + p[vDimIdx] = val; + var point; + if (isNaN(axisDimVal) || isNaN(val)) { + point = [NaN, NaN]; + } + else { + point = coordSys.dataToPoint(p); + point[cDimIdx] += offset; + } + return point; + } + + function addBodyEnd(ends, point, start) { + var point1 = point.slice(); + var point2 = point.slice(); + point1[cDimIdx] += halfWidth; + point2[cDimIdx] -= halfWidth; + start + ? ends.push(point1, point2) + : ends.push(point2, point1); + } + + function layEndLine(ends, endCenter) { + var from = endCenter.slice(); + var to = endCenter.slice(); + from[cDimIdx] -= halfWidth; + to[cDimIdx] += halfWidth; + ends.push(from, to); + } +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +registerVisual(boxplotVisual); +registerLayout(boxplotLayout); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var CandlestickSeries = SeriesModel.extend({ + + type: 'series.candlestick', + + dependencies: ['xAxis', 'yAxis', 'grid'], + + /** + * @readOnly + */ + defaultValueDimensions: [ + {name: 'open', defaultTooltip: true}, + {name: 'close', defaultTooltip: true}, + {name: 'lowest', defaultTooltip: true}, + {name: 'highest', defaultTooltip: true} + ], + + /** + * @type {Array.} + * @readOnly + */ + dimensions: null, + + /** + * @override + */ + defaultOption: { + zlevel: 0, + z: 2, + coordinateSystem: 'cartesian2d', + legendHoverLink: true, + + hoverAnimation: true, + + // xAxisIndex: 0, + // yAxisIndex: 0, + + layout: null, // 'horizontal' or 'vertical' + + itemStyle: { + color: '#c23531', // 阳线 positive + color0: '#314656', // 阴线 negative '#c23531', '#314656' + borderWidth: 1, + // FIXME + // ec2中使用的是lineStyle.color 和 lineStyle.color0 + borderColor: '#c23531', + borderColor0: '#314656' + }, + + emphasis: { + itemStyle: { + borderWidth: 2 + } + }, + + barMaxWidth: null, + barMinWidth: null, + barWidth: null, + + large: true, + largeThreshold: 600, + + progressive: 3e3, + progressiveThreshold: 1e4, + progressiveChunkMode: 'mod', + + animationUpdate: false, + animationEasing: 'linear', + animationDuration: 300 + }, + + /** + * Get dimension for shadow in dataZoom + * @return {string} dimension name + */ + getShadowDim: function () { + return 'open'; + }, + + brushSelector: function (dataIndex, data, selectors) { + var itemLayout = data.getItemLayout(dataIndex); + return itemLayout && selectors.rect(itemLayout.brushRect); + } + +}); + +mixin(CandlestickSeries, seriesModelMixin, true); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var NORMAL_ITEM_STYLE_PATH$1 = ['itemStyle']; +var EMPHASIS_ITEM_STYLE_PATH$1 = ['emphasis', 'itemStyle']; +var SKIP_PROPS = ['color', 'color0', 'borderColor', 'borderColor0']; + + +var CandlestickView = Chart.extend({ + + type: 'candlestick', + + render: function (seriesModel, ecModel, api) { + this._updateDrawMode(seriesModel); + + this._isLargeDraw + ? this._renderLarge(seriesModel) + : this._renderNormal(seriesModel); + }, + + incrementalPrepareRender: function (seriesModel, ecModel, api) { + this._clear(); + this._updateDrawMode(seriesModel); + }, + + incrementalRender: function (params, seriesModel, ecModel, api) { + this._isLargeDraw + ? this._incrementalRenderLarge(params, seriesModel) + : this._incrementalRenderNormal(params, seriesModel); + }, + + _updateDrawMode: function (seriesModel) { + var isLargeDraw = seriesModel.pipelineContext.large; + if (this._isLargeDraw == null || isLargeDraw ^ this._isLargeDraw) { + this._isLargeDraw = isLargeDraw; + this._clear(); + } + }, + + _renderNormal: function (seriesModel) { + var data = seriesModel.getData(); + var oldData = this._data; + var group = this.group; + var isSimpleBox = data.getLayout('isSimpleBox'); + + // There is no old data only when first rendering or switching from + // stream mode to normal mode, where previous elements should be removed. + if (!this._data) { + group.removeAll(); + } + + data.diff(oldData) + .add(function (newIdx) { + if (data.hasValue(newIdx)) { + var el; + + var itemLayout = data.getItemLayout(newIdx); + el = createNormalBox$1(itemLayout, newIdx, true); + initProps(el, {shape: {points: itemLayout.ends}}, seriesModel, newIdx); + + setBoxCommon(el, data, newIdx, isSimpleBox); + + group.add(el); + data.setItemGraphicEl(newIdx, el); + } + }) + .update(function (newIdx, oldIdx) { + var el = oldData.getItemGraphicEl(oldIdx); + + // Empty data + if (!data.hasValue(newIdx)) { + group.remove(el); + return; + } + + var itemLayout = data.getItemLayout(newIdx); + if (!el) { + el = createNormalBox$1(itemLayout, newIdx); + } + else { + updateProps(el, {shape: {points: itemLayout.ends}}, seriesModel, newIdx); + } + + setBoxCommon(el, data, newIdx, isSimpleBox); + + group.add(el); + data.setItemGraphicEl(newIdx, el); + }) + .remove(function (oldIdx) { + var el = oldData.getItemGraphicEl(oldIdx); + el && group.remove(el); + }) + .execute(); + + this._data = data; + }, + + _renderLarge: function (seriesModel) { + this._clear(); + createLarge$1(seriesModel, this.group); + }, + + _incrementalRenderNormal: function (params, seriesModel) { + var data = seriesModel.getData(); + var isSimpleBox = data.getLayout('isSimpleBox'); + + var dataIndex; + while ((dataIndex = params.next()) != null) { + var el; + + var itemLayout = data.getItemLayout(dataIndex); + el = createNormalBox$1(itemLayout, dataIndex); + setBoxCommon(el, data, dataIndex, isSimpleBox); + + el.incremental = true; + this.group.add(el); + } + }, + + _incrementalRenderLarge: function (params, seriesModel) { + createLarge$1(seriesModel, this.group, true); + }, + + remove: function (ecModel) { + this._clear(); + }, + + _clear: function () { + this.group.removeAll(); + this._data = null; + }, + + dispose: noop + +}); + + +var NormalBoxPath = Path.extend({ + + type: 'normalCandlestickBox', + + shape: {}, + + buildPath: function (ctx, shape) { + var ends = shape.points; + + if (this.__simpleBox) { + ctx.moveTo(ends[4][0], ends[4][1]); + ctx.lineTo(ends[6][0], ends[6][1]); + } + else { + ctx.moveTo(ends[0][0], ends[0][1]); + ctx.lineTo(ends[1][0], ends[1][1]); + ctx.lineTo(ends[2][0], ends[2][1]); + ctx.lineTo(ends[3][0], ends[3][1]); + ctx.closePath(); + + ctx.moveTo(ends[4][0], ends[4][1]); + ctx.lineTo(ends[5][0], ends[5][1]); + ctx.moveTo(ends[6][0], ends[6][1]); + ctx.lineTo(ends[7][0], ends[7][1]); + } + } +}); + +function createNormalBox$1(itemLayout, dataIndex, isInit) { + var ends = itemLayout.ends; + return new NormalBoxPath({ + shape: { + points: isInit + ? transInit$1(ends, itemLayout) + : ends + }, + z2: 100 + }); +} + +function setBoxCommon(el, data, dataIndex, isSimpleBox) { + var itemModel = data.getItemModel(dataIndex); + var normalItemStyleModel = itemModel.getModel(NORMAL_ITEM_STYLE_PATH$1); + var color = data.getItemVisual(dataIndex, 'color'); + var borderColor = data.getItemVisual(dataIndex, 'borderColor') || color; + + // Color must be excluded. + // Because symbol provide setColor individually to set fill and stroke + var itemStyle = normalItemStyleModel.getItemStyle(SKIP_PROPS); + + el.useStyle(itemStyle); + el.style.strokeNoScale = true; + el.style.fill = color; + el.style.stroke = borderColor; + + el.__simpleBox = isSimpleBox; + + var hoverStyle = itemModel.getModel(EMPHASIS_ITEM_STYLE_PATH$1).getItemStyle(); + setHoverStyle(el, hoverStyle); +} + +function transInit$1(points, itemLayout) { + return map(points, function (point) { + point = point.slice(); + point[1] = itemLayout.initBaseline; + return point; + }); +} + + + +var LargeBoxPath = Path.extend({ + + type: 'largeCandlestickBox', + + shape: {}, + + buildPath: function (ctx, shape) { + // Drawing lines is more efficient than drawing + // a whole line or drawing rects. + var points = shape.points; + for (var i = 0; i < points.length;) { + if (this.__sign === points[i++]) { + var x = points[i++]; + ctx.moveTo(x, points[i++]); + ctx.lineTo(x, points[i++]); + } + else { + i += 3; + } + } + } +}); + +function createLarge$1(seriesModel, group, incremental) { + var data = seriesModel.getData(); + var largePoints = data.getLayout('largePoints'); + + var elP = new LargeBoxPath({ + shape: {points: largePoints}, + __sign: 1 + }); + group.add(elP); + var elN = new LargeBoxPath({ + shape: {points: largePoints}, + __sign: -1 + }); + group.add(elN); + + setLargeStyle$1(1, elP, seriesModel, data); + setLargeStyle$1(-1, elN, seriesModel, data); + + if (incremental) { + elP.incremental = true; + elN.incremental = true; + } +} + +function setLargeStyle$1(sign, el, seriesModel, data) { + var suffix = sign > 0 ? 'P' : 'N'; + var borderColor = data.getVisual('borderColor' + suffix) + || data.getVisual('color' + suffix); + + // Color must be excluded. + // Because symbol provide setColor individually to set fill and stroke + var itemStyle = seriesModel.getModel(NORMAL_ITEM_STYLE_PATH$1).getItemStyle(SKIP_PROPS); + + el.useStyle(itemStyle); + el.style.fill = null; + el.style.stroke = borderColor; + // No different + // el.style.lineWidth = .5; +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var preprocessor = function (option) { + if (!option || !isArray(option.series)) { + return; + } + + // Translate 'k' to 'candlestick'. + each$1(option.series, function (seriesItem) { + if (isObject$1(seriesItem) && seriesItem.type === 'k') { + seriesItem.type = 'candlestick'; + } + }); +}; + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var positiveBorderColorQuery = ['itemStyle', 'borderColor']; +var negativeBorderColorQuery = ['itemStyle', 'borderColor0']; +var positiveColorQuery = ['itemStyle', 'color']; +var negativeColorQuery = ['itemStyle', 'color0']; + +var candlestickVisual = { + + seriesType: 'candlestick', + + plan: createRenderPlanner(), + + // For legend. + performRawSeries: true, + + reset: function (seriesModel, ecModel) { + + var data = seriesModel.getData(); + var isLargeRender = seriesModel.pipelineContext.large; + + data.setVisual({ + legendSymbol: 'roundRect', + colorP: getColor(1, seriesModel), + colorN: getColor(-1, seriesModel), + borderColorP: getBorderColor(1, seriesModel), + borderColorN: getBorderColor(-1, seriesModel) + }); + + // Only visible series has each data be visual encoded + if (ecModel.isSeriesFiltered(seriesModel)) { + return; + } + + return !isLargeRender && {progress: progress}; + + + function progress(params, data) { + var dataIndex; + while ((dataIndex = params.next()) != null) { + var itemModel = data.getItemModel(dataIndex); + var sign = data.getItemLayout(dataIndex).sign; + + data.setItemVisual( + dataIndex, + { + color: getColor(sign, itemModel), + borderColor: getBorderColor(sign, itemModel) + } + ); + } + } + + function getColor(sign, model) { + return model.get( + sign > 0 ? positiveColorQuery : negativeColorQuery + ); + } + + function getBorderColor(sign, model) { + return model.get( + sign > 0 ? positiveBorderColorQuery : negativeBorderColorQuery + ); + } + + } + +}; + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/* global Float32Array */ + +var LargeArr$1 = typeof Float32Array !== 'undefined' ? Float32Array : Array; + +var candlestickLayout = { + + seriesType: 'candlestick', + + plan: createRenderPlanner(), + + reset: function (seriesModel) { + + var coordSys = seriesModel.coordinateSystem; + var data = seriesModel.getData(); + var candleWidth = calculateCandleWidth(seriesModel, data); + var cDimIdx = 0; + var vDimIdx = 1; + var coordDims = ['x', 'y']; + var cDim = data.mapDimension(coordDims[cDimIdx]); + var vDims = data.mapDimension(coordDims[vDimIdx], true); + var openDim = vDims[0]; + var closeDim = vDims[1]; + var lowestDim = vDims[2]; + var highestDim = vDims[3]; + + data.setLayout({ + candleWidth: candleWidth, + // The value is experimented visually. + isSimpleBox: candleWidth <= 1.3 + }); + + if (cDim == null || vDims.length < 4) { + return; + } + + return { + progress: seriesModel.pipelineContext.large + ? largeProgress : normalProgress + }; + + function normalProgress(params, data) { + var dataIndex; + while ((dataIndex = params.next()) != null) { + + var axisDimVal = data.get(cDim, dataIndex); + var openVal = data.get(openDim, dataIndex); + var closeVal = data.get(closeDim, dataIndex); + var lowestVal = data.get(lowestDim, dataIndex); + var highestVal = data.get(highestDim, dataIndex); + + var ocLow = Math.min(openVal, closeVal); + var ocHigh = Math.max(openVal, closeVal); + + var ocLowPoint = getPoint(ocLow, axisDimVal); + var ocHighPoint = getPoint(ocHigh, axisDimVal); + var lowestPoint = getPoint(lowestVal, axisDimVal); + var highestPoint = getPoint(highestVal, axisDimVal); + + var ends = []; + addBodyEnd(ends, ocHighPoint, 0); + addBodyEnd(ends, ocLowPoint, 1); + + ends.push( + subPixelOptimizePoint(highestPoint), + subPixelOptimizePoint(ocHighPoint), + subPixelOptimizePoint(lowestPoint), + subPixelOptimizePoint(ocLowPoint) + ); + + data.setItemLayout(dataIndex, { + sign: getSign(data, dataIndex, openVal, closeVal, closeDim), + initBaseline: openVal > closeVal + ? ocHighPoint[vDimIdx] : ocLowPoint[vDimIdx], // open point. + ends: ends, + brushRect: makeBrushRect(lowestVal, highestVal, axisDimVal) + }); + } + + function getPoint(val, axisDimVal) { + var p = []; + p[cDimIdx] = axisDimVal; + p[vDimIdx] = val; + return (isNaN(axisDimVal) || isNaN(val)) + ? [NaN, NaN] + : coordSys.dataToPoint(p); + } + + function addBodyEnd(ends, point, start) { + var point1 = point.slice(); + var point2 = point.slice(); + + point1[cDimIdx] = subPixelOptimize( + point1[cDimIdx] + candleWidth / 2, 1, false + ); + point2[cDimIdx] = subPixelOptimize( + point2[cDimIdx] - candleWidth / 2, 1, true + ); + + start + ? ends.push(point1, point2) + : ends.push(point2, point1); + } + + function makeBrushRect(lowestVal, highestVal, axisDimVal) { + var pmin = getPoint(lowestVal, axisDimVal); + var pmax = getPoint(highestVal, axisDimVal); + + pmin[cDimIdx] -= candleWidth / 2; + pmax[cDimIdx] -= candleWidth / 2; + + return { + x: pmin[0], + y: pmin[1], + width: vDimIdx ? candleWidth : pmax[0] - pmin[0], + height: vDimIdx ? pmax[1] - pmin[1] : candleWidth + }; + } + + function subPixelOptimizePoint(point) { + point[cDimIdx] = subPixelOptimize(point[cDimIdx], 1); + return point; + } + } + + function largeProgress(params, data) { + // Structure: [sign, x, yhigh, ylow, sign, x, yhigh, ylow, ...] + var points = new LargeArr$1(params.count * 5); + var offset = 0; + var point; + var tmpIn = []; + var tmpOut = []; + var dataIndex; + + while ((dataIndex = params.next()) != null) { + var axisDimVal = data.get(cDim, dataIndex); + var openVal = data.get(openDim, dataIndex); + var closeVal = data.get(closeDim, dataIndex); + var lowestVal = data.get(lowestDim, dataIndex); + var highestVal = data.get(highestDim, dataIndex); + + if (isNaN(axisDimVal) || isNaN(lowestVal) || isNaN(highestVal)) { + points[offset++] = NaN; + offset += 4; + continue; + } + + points[offset++] = getSign(data, dataIndex, openVal, closeVal, closeDim); + + tmpIn[cDimIdx] = axisDimVal; + + tmpIn[vDimIdx] = lowestVal; + point = coordSys.dataToPoint(tmpIn, null, tmpOut); + points[offset++] = point ? point[0] : NaN; + points[offset++] = point ? point[1] : NaN; + tmpIn[vDimIdx] = highestVal; + point = coordSys.dataToPoint(tmpIn, null, tmpOut); + points[offset++] = point ? point[1] : NaN; + } + + data.setLayout('largePoints', points); + } + } +}; + +function getSign(data, dataIndex, openVal, closeVal, closeDim) { + var sign; + if (openVal > closeVal) { + sign = -1; + } + else if (openVal < closeVal) { + sign = 1; + } + else { + sign = dataIndex > 0 + // If close === open, compare with close of last record + ? (data.get(closeDim, dataIndex - 1) <= closeVal ? 1 : -1) + // No record of previous, set to be positive + : 1; + } + + return sign; +} + +function calculateCandleWidth(seriesModel, data) { + var baseAxis = seriesModel.getBaseAxis(); + var extent; + + var bandWidth = baseAxis.type === 'category' + ? baseAxis.getBandWidth() + : ( + extent = baseAxis.getExtent(), + Math.abs(extent[1] - extent[0]) / data.count() + ); + + var barMaxWidth = parsePercent$1( + retrieve2(seriesModel.get('barMaxWidth'), bandWidth), + bandWidth + ); + var barMinWidth = parsePercent$1( + retrieve2(seriesModel.get('barMinWidth'), 1), + bandWidth + ); + var barWidth = seriesModel.get('barWidth'); + + return barWidth != null + ? parsePercent$1(barWidth, bandWidth) + // Put max outer to ensure bar visible in spite of overlap. + : Math.max(Math.min(bandWidth / 2, barMaxWidth), barMinWidth); +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +registerPreprocessor(preprocessor); +registerVisual(candlestickVisual); +registerLayout(candlestickLayout); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +SeriesModel.extend({ + + type: 'series.effectScatter', + + dependencies: ['grid', 'polar'], + + getInitialData: function (option, ecModel) { + return createListFromArray(this.getSource(), this); + }, + + brushSelector: 'point', + + defaultOption: { + coordinateSystem: 'cartesian2d', + zlevel: 0, + z: 2, + legendHoverLink: true, + + effectType: 'ripple', + + progressive: 0, + + // When to show the effect, option: 'render'|'emphasis' + showEffectOn: 'render', + + // Ripple effect config + rippleEffect: { + period: 4, + // Scale of ripple + scale: 2.5, + // Brush type can be fill or stroke + brushType: 'fill' + }, + + // Cartesian coordinate system + // xAxisIndex: 0, + // yAxisIndex: 0, + + // Polar coordinate system + // polarIndex: 0, + + // Geo coordinate system + // geoIndex: 0, + + // symbol: null, // 图形类型 + symbolSize: 10 // 图形大小,半宽(半径)参数,当图形为方向或菱形则总宽度为symbolSize * 2 + // symbolRotate: null, // 图形旋转控制 + + // large: false, + // Available when large is true + // largeThreshold: 2000, + + // itemStyle: { + // opacity: 1 + // } + } + +}); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/** + * Symbol with ripple effect + * @module echarts/chart/helper/EffectSymbol + */ + +var EFFECT_RIPPLE_NUMBER = 3; + +function normalizeSymbolSize$1(symbolSize) { + if (!isArray(symbolSize)) { + symbolSize = [+symbolSize, +symbolSize]; + } + return symbolSize; +} + +function updateRipplePath(rippleGroup, effectCfg) { + rippleGroup.eachChild(function (ripplePath) { + ripplePath.attr({ + z: effectCfg.z, + zlevel: effectCfg.zlevel, + style: { + stroke: effectCfg.brushType === 'stroke' ? effectCfg.color : null, + fill: effectCfg.brushType === 'fill' ? effectCfg.color : null + } + }); + }); +} +/** + * @constructor + * @param {module:echarts/data/List} data + * @param {number} idx + * @extends {module:zrender/graphic/Group} + */ +function EffectSymbol(data, idx) { + Group.call(this); + + var symbol = new SymbolClz$1(data, idx); + var rippleGroup = new Group(); + this.add(symbol); + this.add(rippleGroup); + + rippleGroup.beforeUpdate = function () { + this.attr(symbol.getScale()); + }; + this.updateData(data, idx); +} + +var effectSymbolProto = EffectSymbol.prototype; + +effectSymbolProto.stopEffectAnimation = function () { + this.childAt(1).removeAll(); +}; + +effectSymbolProto.startEffectAnimation = function (effectCfg) { + var symbolType = effectCfg.symbolType; + var color = effectCfg.color; + var rippleGroup = this.childAt(1); + + for (var i = 0; i < EFFECT_RIPPLE_NUMBER; i++) { + // var ripplePath = createSymbol( + // symbolType, -0.5, -0.5, 1, 1, color + // ); + // If width/height are set too small (e.g., set to 1) on ios10 + // and macOS Sierra, a circle stroke become a rect, no matter what + // the scale is set. So we set width/height as 2. See #4136. + var ripplePath = createSymbol( + symbolType, -1, -1, 2, 2, color + ); + ripplePath.attr({ + style: { + strokeNoScale: true + }, + z2: 99, + silent: true, + scale: [0.5, 0.5] + }); + + var delay = -i / EFFECT_RIPPLE_NUMBER * effectCfg.period + effectCfg.effectOffset; + // TODO Configurable effectCfg.period + ripplePath.animate('', true) + .when(effectCfg.period, { + scale: [effectCfg.rippleScale / 2, effectCfg.rippleScale / 2] + }) + .delay(delay) + .start(); + ripplePath.animateStyle(true) + .when(effectCfg.period, { + opacity: 0 + }) + .delay(delay) + .start(); + + rippleGroup.add(ripplePath); + } + + updateRipplePath(rippleGroup, effectCfg); +}; + +/** + * Update effect symbol + */ +effectSymbolProto.updateEffectAnimation = function (effectCfg) { + var oldEffectCfg = this._effectCfg; + var rippleGroup = this.childAt(1); + + // Must reinitialize effect if following configuration changed + var DIFFICULT_PROPS = ['symbolType', 'period', 'rippleScale']; + for (var i = 0; i < DIFFICULT_PROPS.length; i++) { + var propName = DIFFICULT_PROPS[i]; + if (oldEffectCfg[propName] !== effectCfg[propName]) { + this.stopEffectAnimation(); + this.startEffectAnimation(effectCfg); + return; + } + } + + updateRipplePath(rippleGroup, effectCfg); +}; + +/** + * Highlight symbol + */ +effectSymbolProto.highlight = function () { + this.trigger('emphasis'); +}; + +/** + * Downplay symbol + */ +effectSymbolProto.downplay = function () { + this.trigger('normal'); +}; + +/** + * Update symbol properties + * @param {module:echarts/data/List} data + * @param {number} idx + */ +effectSymbolProto.updateData = function (data, idx) { + var seriesModel = data.hostModel; + + this.childAt(0).updateData(data, idx); + + var rippleGroup = this.childAt(1); + var itemModel = data.getItemModel(idx); + var symbolType = data.getItemVisual(idx, 'symbol'); + var symbolSize = normalizeSymbolSize$1(data.getItemVisual(idx, 'symbolSize')); + var color = data.getItemVisual(idx, 'color'); + + rippleGroup.attr('scale', symbolSize); + + rippleGroup.traverse(function (ripplePath) { + ripplePath.attr({ + fill: color + }); + }); + + var symbolOffset = itemModel.getShallow('symbolOffset'); + if (symbolOffset) { + var pos = rippleGroup.position; + pos[0] = parsePercent$1(symbolOffset[0], symbolSize[0]); + pos[1] = parsePercent$1(symbolOffset[1], symbolSize[1]); + } + rippleGroup.rotation = (itemModel.getShallow('symbolRotate') || 0) * Math.PI / 180 || 0; + + var effectCfg = {}; + + effectCfg.showEffectOn = seriesModel.get('showEffectOn'); + effectCfg.rippleScale = itemModel.get('rippleEffect.scale'); + effectCfg.brushType = itemModel.get('rippleEffect.brushType'); + effectCfg.period = itemModel.get('rippleEffect.period') * 1000; + effectCfg.effectOffset = idx / data.count(); + effectCfg.z = itemModel.getShallow('z') || 0; + effectCfg.zlevel = itemModel.getShallow('zlevel') || 0; + effectCfg.symbolType = symbolType; + effectCfg.color = color; + + this.off('mouseover').off('mouseout').off('emphasis').off('normal'); + + if (effectCfg.showEffectOn === 'render') { + this._effectCfg + ? this.updateEffectAnimation(effectCfg) + : this.startEffectAnimation(effectCfg); + + this._effectCfg = effectCfg; + } + else { + // Not keep old effect config + this._effectCfg = null; + + this.stopEffectAnimation(); + var symbol = this.childAt(0); + var onEmphasis = function () { + symbol.highlight(); + if (effectCfg.showEffectOn !== 'render') { + this.startEffectAnimation(effectCfg); + } + }; + var onNormal = function () { + symbol.downplay(); + if (effectCfg.showEffectOn !== 'render') { + this.stopEffectAnimation(); + } + }; + this.on('mouseover', onEmphasis, this) + .on('mouseout', onNormal, this) + .on('emphasis', onEmphasis, this) + .on('normal', onNormal, this); + } + + this._effectCfg = effectCfg; +}; + +effectSymbolProto.fadeOut = function (cb) { + this.off('mouseover').off('mouseout').off('emphasis').off('normal'); + cb && cb(); +}; + +inherits(EffectSymbol, Group); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +extendChartView({ + + type: 'effectScatter', + + init: function () { + this._symbolDraw = new SymbolDraw(EffectSymbol); + }, + + render: function (seriesModel, ecModel, api) { + var data = seriesModel.getData(); + var effectSymbolDraw = this._symbolDraw; + effectSymbolDraw.updateData(data); + this.group.add(effectSymbolDraw.group); + }, + + updateTransform: function (seriesModel, ecModel, api) { + var data = seriesModel.getData(); + + this.group.dirty(); + + var res = pointsLayout().reset(seriesModel); + if (res.progress) { + res.progress({ start: 0, end: data.count() }, data); + } + + this._symbolDraw.updateLayout(data); + }, + + _updateGroupTransform: function (seriesModel) { + var coordSys = seriesModel.coordinateSystem; + if (coordSys && coordSys.getRoamTransform) { + this.group.transform = clone$2(coordSys.getRoamTransform()); + this.group.decomposeTransform(); + } + }, + + remove: function (ecModel, api) { + this._symbolDraw && this._symbolDraw.remove(api); + }, + + dispose: function () {} +}); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +registerVisual(visualSymbol('effectScatter', 'circle')); +registerLayout(pointsLayout('effectScatter')); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/* global Uint32Array, Float64Array, Float32Array */ + +var Uint32Arr = typeof Uint32Array === 'undefined' ? Array : Uint32Array; +var Float64Arr = typeof Float64Array === 'undefined' ? Array : Float64Array; + +function compatEc2(seriesOpt) { + var data = seriesOpt.data; + if (data && data[0] && data[0][0] && data[0][0].coord) { + if (__DEV__) { + console.warn('Lines data configuration has been changed to' + + ' { coords:[[1,2],[2,3]] }'); + } + seriesOpt.data = map(data, function (itemOpt) { + var coords = [ + itemOpt[0].coord, itemOpt[1].coord + ]; + var target = { + coords: coords + }; + if (itemOpt[0].name) { + target.fromName = itemOpt[0].name; + } + if (itemOpt[1].name) { + target.toName = itemOpt[1].name; + } + return mergeAll([target, itemOpt[0], itemOpt[1]]); + }); + } +} + +var LinesSeries = SeriesModel.extend({ + + type: 'series.lines', + + dependencies: ['grid', 'polar'], + + visualColorAccessPath: 'lineStyle.color', + + init: function (option) { + // The input data may be null/undefined. + option.data = option.data || []; + + // Not using preprocessor because mergeOption may not have series.type + compatEc2(option); + + var result = this._processFlatCoordsArray(option.data); + this._flatCoords = result.flatCoords; + this._flatCoordsOffset = result.flatCoordsOffset; + if (result.flatCoords) { + option.data = new Float32Array(result.count); + } + + LinesSeries.superApply(this, 'init', arguments); + }, + + mergeOption: function (option) { + // The input data may be null/undefined. + option.data = option.data || []; + + compatEc2(option); + + if (option.data) { + // Only update when have option data to merge. + var result = this._processFlatCoordsArray(option.data); + this._flatCoords = result.flatCoords; + this._flatCoordsOffset = result.flatCoordsOffset; + if (result.flatCoords) { + option.data = new Float32Array(result.count); + } + } + + LinesSeries.superApply(this, 'mergeOption', arguments); + }, + + appendData: function (params) { + var result = this._processFlatCoordsArray(params.data); + if (result.flatCoords) { + if (!this._flatCoords) { + this._flatCoords = result.flatCoords; + this._flatCoordsOffset = result.flatCoordsOffset; + } + else { + this._flatCoords = concatArray(this._flatCoords, result.flatCoords); + this._flatCoordsOffset = concatArray(this._flatCoordsOffset, result.flatCoordsOffset); + } + params.data = new Float32Array(result.count); + } + + this.getRawData().appendData(params.data); + }, + + _getCoordsFromItemModel: function (idx) { + var itemModel = this.getData().getItemModel(idx); + var coords = (itemModel.option instanceof Array) + ? itemModel.option : itemModel.getShallow('coords'); + + if (__DEV__) { + if (!(coords instanceof Array && coords.length > 0 && coords[0] instanceof Array)) { + throw new Error( + 'Invalid coords ' + JSON.stringify(coords) + '. Lines must have 2d coords array in data item.' + ); + } + } + return coords; + }, + + getLineCoordsCount: function (idx) { + if (this._flatCoordsOffset) { + return this._flatCoordsOffset[idx * 2 + 1]; + } + else { + return this._getCoordsFromItemModel(idx).length; + } + }, + + getLineCoords: function (idx, out) { + if (this._flatCoordsOffset) { + var offset = this._flatCoordsOffset[idx * 2]; + var len = this._flatCoordsOffset[idx * 2 + 1]; + for (var i = 0; i < len; i++) { + out[i] = out[i] || []; + out[i][0] = this._flatCoords[offset + i * 2]; + out[i][1] = this._flatCoords[offset + i * 2 + 1]; + } + return len; + } + else { + var coords = this._getCoordsFromItemModel(idx); + for (var i = 0; i < coords.length; i++) { + out[i] = out[i] || []; + out[i][0] = coords[i][0]; + out[i][1] = coords[i][1]; + } + return coords.length; + } + }, + + _processFlatCoordsArray: function (data) { + var startOffset = 0; + if (this._flatCoords) { + startOffset = this._flatCoords.length; + } + // Stored as a typed array. In format + // Points Count(2) | x | y | x | y | Points Count(3) | x | y | x | y | x | y | + if (typeof data[0] === 'number') { + var len = data.length; + // Store offset and len of each segment + var coordsOffsetAndLenStorage = new Uint32Arr(len); + var coordsStorage = new Float64Arr(len); + var coordsCursor = 0; + var offsetCursor = 0; + var dataCount = 0; + for (var i = 0; i < len;) { + dataCount++; + var count = data[i++]; + // Offset + coordsOffsetAndLenStorage[offsetCursor++] = coordsCursor + startOffset; + // Len + coordsOffsetAndLenStorage[offsetCursor++] = count; + for (var k = 0; k < count; k++) { + var x = data[i++]; + var y = data[i++]; + coordsStorage[coordsCursor++] = x; + coordsStorage[coordsCursor++] = y; + + if (i > len) { + if (__DEV__) { + throw new Error('Invalid data format.'); + } + } + } + } + + return { + flatCoordsOffset: new Uint32Array(coordsOffsetAndLenStorage.buffer, 0, offsetCursor), + flatCoords: coordsStorage, + count: dataCount + }; + } + + return { + flatCoordsOffset: null, + flatCoords: null, + count: data.length + }; + }, + + getInitialData: function (option, ecModel) { + if (__DEV__) { + var CoordSys = CoordinateSystemManager.get(option.coordinateSystem); + if (!CoordSys) { + throw new Error('Unkown coordinate system ' + option.coordinateSystem); + } + } + + var lineData = new List(['value'], this); + lineData.hasItemOption = false; + + lineData.initData(option.data, [], function (dataItem, dimName, dataIndex, dimIndex) { + // dataItem is simply coords + if (dataItem instanceof Array) { + return NaN; + } + else { + lineData.hasItemOption = true; + var value = dataItem.value; + if (value != null) { + return value instanceof Array ? value[dimIndex] : value; + } + } + }); + + return lineData; + }, + + formatTooltip: function (dataIndex) { + var data = this.getData(); + var itemModel = data.getItemModel(dataIndex); + var name = itemModel.get('name'); + if (name) { + return name; + } + var fromName = itemModel.get('fromName'); + var toName = itemModel.get('toName'); + var html = []; + fromName != null && html.push(fromName); + toName != null && html.push(toName); + + return encodeHTML(html.join(' > ')); + }, + + preventIncremental: function () { + return !!this.get('effect.show'); + }, + + getProgressive: function () { + var progressive = this.option.progressive; + if (progressive == null) { + return this.option.large ? 1e4 : this.get('progressive'); + } + return progressive; + }, + + getProgressiveThreshold: function () { + var progressiveThreshold = this.option.progressiveThreshold; + if (progressiveThreshold == null) { + return this.option.large ? 2e4 : this.get('progressiveThreshold'); + } + return progressiveThreshold; + }, + + defaultOption: { + coordinateSystem: 'geo', + zlevel: 0, + z: 2, + legendHoverLink: true, + + hoverAnimation: true, + // Cartesian coordinate system + xAxisIndex: 0, + yAxisIndex: 0, + + symbol: ['none', 'none'], + symbolSize: [10, 10], + // Geo coordinate system + geoIndex: 0, + + effect: { + show: false, + period: 4, + // Animation delay. support callback + // delay: 0, + // If move with constant speed px/sec + // period will be ignored if this property is > 0, + constantSpeed: 0, + symbol: 'circle', + symbolSize: 3, + loop: true, + // Length of trail, 0 - 1 + trailLength: 0.2 + // Same with lineStyle.color + // color + }, + + large: false, + // Available when large is true + largeThreshold: 2000, + + // If lines are polyline + // polyline not support curveness, label, animation + polyline: false, + + label: { + show: false, + position: 'end' + // distance: 5, + // formatter: 标签文本格式器,同Tooltip.formatter,不支持异步回调 + }, + + lineStyle: { + opacity: 0.5 + } + } +}); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/** + * Provide effect for line + * @module echarts/chart/helper/EffectLine + */ + +/** + * @constructor + * @extends {module:zrender/graphic/Group} + * @alias {module:echarts/chart/helper/Line} + */ +function EffectLine(lineData, idx, seriesScope) { + Group.call(this); + + this.add(this.createLine(lineData, idx, seriesScope)); + + this._updateEffectSymbol(lineData, idx); +} + +var effectLineProto = EffectLine.prototype; + +effectLineProto.createLine = function (lineData, idx, seriesScope) { + return new Line$1(lineData, idx, seriesScope); +}; + +effectLineProto._updateEffectSymbol = function (lineData, idx) { + var itemModel = lineData.getItemModel(idx); + var effectModel = itemModel.getModel('effect'); + var size = effectModel.get('symbolSize'); + var symbolType = effectModel.get('symbol'); + if (!isArray(size)) { + size = [size, size]; + } + var color = effectModel.get('color') || lineData.getItemVisual(idx, 'color'); + var symbol = this.childAt(1); + + if (this._symbolType !== symbolType) { + // Remove previous + this.remove(symbol); + + symbol = createSymbol( + symbolType, -0.5, -0.5, 1, 1, color + ); + symbol.z2 = 100; + symbol.culling = true; + + this.add(symbol); + } + + // Symbol may be removed if loop is false + if (!symbol) { + return; + } + + // Shadow color is same with color in default + symbol.setStyle('shadowColor', color); + symbol.setStyle(effectModel.getItemStyle(['color'])); + + symbol.attr('scale', size); + + symbol.setColor(color); + symbol.attr('scale', size); + + this._symbolType = symbolType; + + this._updateEffectAnimation(lineData, effectModel, idx); +}; + +effectLineProto._updateEffectAnimation = function (lineData, effectModel, idx) { + + var symbol = this.childAt(1); + if (!symbol) { + return; + } + + var self = this; + + var points = lineData.getItemLayout(idx); + + var period = effectModel.get('period') * 1000; + var loop = effectModel.get('loop'); + var constantSpeed = effectModel.get('constantSpeed'); + var delayExpr = retrieve(effectModel.get('delay'), function (idx) { + return idx / lineData.count() * period / 3; + }); + var isDelayFunc = typeof delayExpr === 'function'; + + // Ignore when updating + symbol.ignore = true; + + this.updateAnimationPoints(symbol, points); + + if (constantSpeed > 0) { + period = this.getLineLength(symbol) / constantSpeed * 1000; + } + + if (period !== this._period || loop !== this._loop) { + + symbol.stopAnimation(); + + var delay = delayExpr; + if (isDelayFunc) { + delay = delayExpr(idx); + } + if (symbol.__t > 0) { + delay = -period * symbol.__t; + } + symbol.__t = 0; + var animator = symbol.animate('', loop) + .when(period, { + __t: 1 + }) + .delay(delay) + .during(function () { + self.updateSymbolPosition(symbol); + }); + if (!loop) { + animator.done(function () { + self.remove(symbol); + }); + } + animator.start(); + } + + this._period = period; + this._loop = loop; +}; + +effectLineProto.getLineLength = function (symbol) { + // Not so accurate + return (dist(symbol.__p1, symbol.__cp1) + + dist(symbol.__cp1, symbol.__p2)); +}; + +effectLineProto.updateAnimationPoints = function (symbol, points) { + symbol.__p1 = points[0]; + symbol.__p2 = points[1]; + symbol.__cp1 = points[2] || [ + (points[0][0] + points[1][0]) / 2, + (points[0][1] + points[1][1]) / 2 + ]; +}; + +effectLineProto.updateData = function (lineData, idx, seriesScope) { + this.childAt(0).updateData(lineData, idx, seriesScope); + this._updateEffectSymbol(lineData, idx); +}; + +effectLineProto.updateSymbolPosition = function (symbol) { + var p1 = symbol.__p1; + var p2 = symbol.__p2; + var cp1 = symbol.__cp1; + var t = symbol.__t; + var pos = symbol.position; + var quadraticAt$$1 = quadraticAt; + var quadraticDerivativeAt$$1 = quadraticDerivativeAt; + pos[0] = quadraticAt$$1(p1[0], cp1[0], p2[0], t); + pos[1] = quadraticAt$$1(p1[1], cp1[1], p2[1], t); + + // Tangent + var tx = quadraticDerivativeAt$$1(p1[0], cp1[0], p2[0], t); + var ty = quadraticDerivativeAt$$1(p1[1], cp1[1], p2[1], t); + + symbol.rotation = -Math.atan2(ty, tx) - Math.PI / 2; + + symbol.ignore = false; +}; + + +effectLineProto.updateLayout = function (lineData, idx) { + this.childAt(0).updateLayout(lineData, idx); + + var effectModel = lineData.getItemModel(idx).getModel('effect'); + this._updateEffectAnimation(lineData, effectModel, idx); +}; + +inherits(EffectLine, Group); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/** + * @module echarts/chart/helper/Line + */ + +/** + * @constructor + * @extends {module:zrender/graphic/Group} + * @alias {module:echarts/chart/helper/Polyline} + */ +function Polyline$2(lineData, idx, seriesScope) { + Group.call(this); + + this._createPolyline(lineData, idx, seriesScope); +} + +var polylineProto = Polyline$2.prototype; + +polylineProto._createPolyline = function (lineData, idx, seriesScope) { + // var seriesModel = lineData.hostModel; + var points = lineData.getItemLayout(idx); + + var line = new Polyline({ + shape: { + points: points + } + }); + + this.add(line); + + this._updateCommonStl(lineData, idx, seriesScope); +}; + +polylineProto.updateData = function (lineData, idx, seriesScope) { + var seriesModel = lineData.hostModel; + + var line = this.childAt(0); + var target = { + shape: { + points: lineData.getItemLayout(idx) + } + }; + updateProps(line, target, seriesModel, idx); + + this._updateCommonStl(lineData, idx, seriesScope); +}; + +polylineProto._updateCommonStl = function (lineData, idx, seriesScope) { + var line = this.childAt(0); + var itemModel = lineData.getItemModel(idx); + + var visualColor = lineData.getItemVisual(idx, 'color'); + + var lineStyle = seriesScope && seriesScope.lineStyle; + var hoverLineStyle = seriesScope && seriesScope.hoverLineStyle; + + if (!seriesScope || lineData.hasItemOption) { + lineStyle = itemModel.getModel('lineStyle').getLineStyle(); + hoverLineStyle = itemModel.getModel('emphasis.lineStyle').getLineStyle(); + } + line.useStyle(defaults( + { + strokeNoScale: true, + fill: 'none', + stroke: visualColor + }, + lineStyle + )); + line.hoverStyle = hoverLineStyle; + + setHoverStyle(this); +}; + +polylineProto.updateLayout = function (lineData, idx) { + var polyline = this.childAt(0); + polyline.setShape('points', lineData.getItemLayout(idx)); +}; + +inherits(Polyline$2, Group); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/** + * Provide effect for line + * @module echarts/chart/helper/EffectLine + */ + +/** + * @constructor + * @extends {module:echarts/chart/helper/EffectLine} + * @alias {module:echarts/chart/helper/Polyline} + */ +function EffectPolyline(lineData, idx, seriesScope) { + EffectLine.call(this, lineData, idx, seriesScope); + this._lastFrame = 0; + this._lastFramePercent = 0; +} + +var effectPolylineProto = EffectPolyline.prototype; + +// Overwrite +effectPolylineProto.createLine = function (lineData, idx, seriesScope) { + return new Polyline$2(lineData, idx, seriesScope); +}; + +// Overwrite +effectPolylineProto.updateAnimationPoints = function (symbol, points) { + this._points = points; + var accLenArr = [0]; + var len$$1 = 0; + for (var i = 1; i < points.length; i++) { + var p1 = points[i - 1]; + var p2 = points[i]; + len$$1 += dist(p1, p2); + accLenArr.push(len$$1); + } + if (len$$1 === 0) { + return; + } + + for (var i = 0; i < accLenArr.length; i++) { + accLenArr[i] /= len$$1; + } + this._offsets = accLenArr; + this._length = len$$1; +}; + +// Overwrite +effectPolylineProto.getLineLength = function (symbol) { + return this._length; +}; + +// Overwrite +effectPolylineProto.updateSymbolPosition = function (symbol) { + var t = symbol.__t; + var points = this._points; + var offsets = this._offsets; + var len$$1 = points.length; + + if (!offsets) { + // Has length 0 + return; + } + + var lastFrame = this._lastFrame; + var frame; + + if (t < this._lastFramePercent) { + // Start from the next frame + // PENDING start from lastFrame ? + var start = Math.min(lastFrame + 1, len$$1 - 1); + for (frame = start; frame >= 0; frame--) { + if (offsets[frame] <= t) { + break; + } + } + // PENDING really need to do this ? + frame = Math.min(frame, len$$1 - 2); + } + else { + for (var frame = lastFrame; frame < len$$1; frame++) { + if (offsets[frame] > t) { + break; + } + } + frame = Math.min(frame - 1, len$$1 - 2); + } + + lerp( + symbol.position, points[frame], points[frame + 1], + (t - offsets[frame]) / (offsets[frame + 1] - offsets[frame]) + ); + + var tx = points[frame + 1][0] - points[frame][0]; + var ty = points[frame + 1][1] - points[frame][1]; + symbol.rotation = -Math.atan2(ty, tx) - Math.PI / 2; + + this._lastFrame = frame; + this._lastFramePercent = t; + + symbol.ignore = false; +}; + +inherits(EffectPolyline, EffectLine); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +// TODO Batch by color + +var LargeLineShape = extendShape({ + + shape: { + polyline: false, + curveness: 0, + segs: [] + }, + + buildPath: function (path, shape) { + var segs = shape.segs; + var curveness = shape.curveness; + + if (shape.polyline) { + for (var i = 0; i < segs.length;) { + var count = segs[i++]; + if (count > 0) { + path.moveTo(segs[i++], segs[i++]); + for (var k = 1; k < count; k++) { + path.lineTo(segs[i++], segs[i++]); + } + } + } + } + else { + for (var i = 0; i < segs.length;) { + var x0 = segs[i++]; + var y0 = segs[i++]; + var x1 = segs[i++]; + var y1 = segs[i++]; + path.moveTo(x0, y0); + if (curveness > 0) { + var x2 = (x0 + x1) / 2 - (y0 - y1) * curveness; + var y2 = (y0 + y1) / 2 - (x1 - x0) * curveness; + path.quadraticCurveTo(x2, y2, x1, y1); + } + else { + path.lineTo(x1, y1); + } + } + } + }, + + findDataIndex: function (x, y) { + + var shape = this.shape; + var segs = shape.segs; + var curveness = shape.curveness; + + if (shape.polyline) { + var dataIndex = 0; + for (var i = 0; i < segs.length;) { + var count = segs[i++]; + if (count > 0) { + var x0 = segs[i++]; + var y0 = segs[i++]; + for (var k = 1; k < count; k++) { + var x1 = segs[i++]; + var y1 = segs[i++]; + if (containStroke$1(x0, y0, x1, y1)) { + return dataIndex; + } + } + } + + dataIndex++; + } + } + else { + var dataIndex = 0; + for (var i = 0; i < segs.length;) { + var x0 = segs[i++]; + var y0 = segs[i++]; + var x1 = segs[i++]; + var y1 = segs[i++]; + if (curveness > 0) { + var x2 = (x0 + x1) / 2 - (y0 - y1) * curveness; + var y2 = (y0 + y1) / 2 - (x1 - x0) * curveness; + + if (containStroke$3(x0, y0, x2, y2, x1, y1)) { + return dataIndex; + } + } + else { + if (containStroke$1(x0, y0, x1, y1)) { + return dataIndex; + } + } + + dataIndex++; + } + } + + return -1; + } +}); + +function LargeLineDraw() { + this.group = new Group(); +} + +var largeLineProto = LargeLineDraw.prototype; + +largeLineProto.isPersistent = function () { + return !this._incremental; +}; + +/** + * Update symbols draw by new data + * @param {module:echarts/data/List} data + */ +largeLineProto.updateData = function (data) { + this.group.removeAll(); + + var lineEl = new LargeLineShape({ + rectHover: true, + cursor: 'default' + }); + lineEl.setShape({ + segs: data.getLayout('linesPoints') + }); + + this._setCommon(lineEl, data); + + // Add back + this.group.add(lineEl); + + this._incremental = null; +}; + +/** + * @override + */ +largeLineProto.incrementalPrepareUpdate = function (data) { + this.group.removeAll(); + + this._clearIncremental(); + + if (data.count() > 5e5) { + if (!this._incremental) { + this._incremental = new IncrementalDisplayble({ + silent: true + }); + } + this.group.add(this._incremental); + } + else { + this._incremental = null; + } +}; + +/** + * @override + */ +largeLineProto.incrementalUpdate = function (taskParams, data) { + var lineEl = new LargeLineShape(); + lineEl.setShape({ + segs: data.getLayout('linesPoints') + }); + + this._setCommon(lineEl, data, !!this._incremental); + + if (!this._incremental) { + lineEl.rectHover = true; + lineEl.cursor = 'default'; + lineEl.__startIndex = taskParams.start; + this.group.add(lineEl); + } + else { + this._incremental.addDisplayable(lineEl, true); + } +}; + +/** + * @override + */ +largeLineProto.remove = function () { + this._clearIncremental(); + this._incremental = null; + this.group.removeAll(); +}; + +largeLineProto._setCommon = function (lineEl, data, isIncremental) { + var hostModel = data.hostModel; + + lineEl.setShape({ + polyline: hostModel.get('polyline'), + curveness: hostModel.get('lineStyle.curveness') + }); + + lineEl.useStyle( + hostModel.getModel('lineStyle').getLineStyle() + ); + lineEl.style.strokeNoScale = true; + + var visualColor = data.getVisual('color'); + if (visualColor) { + lineEl.setStyle('stroke', visualColor); + } + lineEl.setStyle('fill'); + + if (!isIncremental) { + // Enable tooltip + // PENDING May have performance issue when path is extremely large + lineEl.seriesIndex = hostModel.seriesIndex; + lineEl.on('mousemove', function (e) { + lineEl.dataIndex = null; + var dataIndex = lineEl.findDataIndex(e.offsetX, e.offsetY); + if (dataIndex > 0) { + // Provide dataIndex for tooltip + lineEl.dataIndex = dataIndex + lineEl.__startIndex; + } + }); + } +}; + +largeLineProto._clearIncremental = function () { + var incremental = this._incremental; + if (incremental) { + incremental.clearDisplaybles(); + } +}; + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/* global Float32Array */ + +var linesLayout = { + seriesType: 'lines', + + plan: createRenderPlanner(), + + reset: function (seriesModel) { + var coordSys = seriesModel.coordinateSystem; + var isPolyline = seriesModel.get('polyline'); + var isLarge = seriesModel.pipelineContext.large; + + function progress(params, lineData) { + var lineCoords = []; + if (isLarge) { + var points; + var segCount = params.end - params.start; + if (isPolyline) { + var totalCoordsCount = 0; + for (var i = params.start; i < params.end; i++) { + totalCoordsCount += seriesModel.getLineCoordsCount(i); + } + points = new Float32Array(segCount + totalCoordsCount * 2); + } + else { + points = new Float32Array(segCount * 4); + } + + var offset = 0; + var pt = []; + for (var i = params.start; i < params.end; i++) { + var len = seriesModel.getLineCoords(i, lineCoords); + if (isPolyline) { + points[offset++] = len; + } + for (var k = 0; k < len; k++) { + pt = coordSys.dataToPoint(lineCoords[k], false, pt); + points[offset++] = pt[0]; + points[offset++] = pt[1]; + } + } + + lineData.setLayout('linesPoints', points); + } + else { + for (var i = params.start; i < params.end; i++) { + var itemModel = lineData.getItemModel(i); + var len = seriesModel.getLineCoords(i, lineCoords); + + var pts = []; + if (isPolyline) { + for (var j = 0; j < len; j++) { + pts.push(coordSys.dataToPoint(lineCoords[j])); + } + } + else { + pts[0] = coordSys.dataToPoint(lineCoords[0]); + pts[1] = coordSys.dataToPoint(lineCoords[1]); + + var curveness = itemModel.get('lineStyle.curveness'); + if (+curveness) { + pts[2] = [ + (pts[0][0] + pts[1][0]) / 2 - (pts[0][1] - pts[1][1]) * curveness, + (pts[0][1] + pts[1][1]) / 2 - (pts[1][0] - pts[0][0]) * curveness + ]; + } + } + lineData.setItemLayout(i, pts); + } + } + } + + return { progress: progress }; + } +}; + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +extendChartView({ + + type: 'lines', + + init: function () {}, + + render: function (seriesModel, ecModel, api) { + var data = seriesModel.getData(); + + var lineDraw = this._updateLineDraw(data, seriesModel); + + var zlevel = seriesModel.get('zlevel'); + var trailLength = seriesModel.get('effect.trailLength'); + + var zr = api.getZr(); + // Avoid the drag cause ghost shadow + // FIXME Better way ? + // SVG doesn't support + var isSvg = zr.painter.getType() === 'svg'; + if (!isSvg) { + zr.painter.getLayer(zlevel).clear(true); + } + // Config layer with motion blur + if (this._lastZlevel != null && !isSvg) { + zr.configLayer(this._lastZlevel, { + motionBlur: false + }); + } + if (this._showEffect(seriesModel) && trailLength) { + if (__DEV__) { + var notInIndividual = false; + ecModel.eachSeries(function (otherSeriesModel) { + if (otherSeriesModel !== seriesModel && otherSeriesModel.get('zlevel') === zlevel) { + notInIndividual = true; + } + }); + notInIndividual && console.warn('Lines with trail effect should have an individual zlevel'); + } + + if (!isSvg) { + zr.configLayer(zlevel, { + motionBlur: true, + lastFrameAlpha: Math.max(Math.min(trailLength / 10 + 0.9, 1), 0) + }); + } + } + + lineDraw.updateData(data); + + this._lastZlevel = zlevel; + + this._finished = true; + }, + + incrementalPrepareRender: function (seriesModel, ecModel, api) { + var data = seriesModel.getData(); + + var lineDraw = this._updateLineDraw(data, seriesModel); + + lineDraw.incrementalPrepareUpdate(data); + + this._clearLayer(api); + + this._finished = false; + }, + + incrementalRender: function (taskParams, seriesModel, ecModel) { + this._lineDraw.incrementalUpdate(taskParams, seriesModel.getData()); + + this._finished = taskParams.end === seriesModel.getData().count(); + }, + + updateTransform: function (seriesModel, ecModel, api) { + var data = seriesModel.getData(); + var pipelineContext = seriesModel.pipelineContext; + + if (!this._finished || pipelineContext.large || pipelineContext.progressiveRender) { + // TODO Don't have to do update in large mode. Only do it when there are millions of data. + return { + update: true + }; + } + else { + // TODO Use same logic with ScatterView. + // Manually update layout + var res = linesLayout.reset(seriesModel); + if (res.progress) { + res.progress({ start: 0, end: data.count() }, data); + } + this._lineDraw.updateLayout(); + this._clearLayer(api); + } + }, + + _updateLineDraw: function (data, seriesModel) { + var lineDraw = this._lineDraw; + var hasEffect = this._showEffect(seriesModel); + var isPolyline = !!seriesModel.get('polyline'); + var pipelineContext = seriesModel.pipelineContext; + var isLargeDraw = pipelineContext.large; + + if (__DEV__) { + if (hasEffect && isLargeDraw) { + console.warn('Large lines not support effect'); + } + } + if (!lineDraw + || hasEffect !== this._hasEffet + || isPolyline !== this._isPolyline + || isLargeDraw !== this._isLargeDraw + ) { + if (lineDraw) { + lineDraw.remove(); + } + lineDraw = this._lineDraw = isLargeDraw + ? new LargeLineDraw() + : new LineDraw( + isPolyline + ? (hasEffect ? EffectPolyline : Polyline$2) + : (hasEffect ? EffectLine : Line$1) + ); + this._hasEffet = hasEffect; + this._isPolyline = isPolyline; + this._isLargeDraw = isLargeDraw; + this.group.removeAll(); + } + + this.group.add(lineDraw.group); + + return lineDraw; + }, + + _showEffect: function (seriesModel) { + return !!seriesModel.get('effect.show'); + }, + + _clearLayer: function (api) { + // Not use motion when dragging or zooming + var zr = api.getZr(); + var isSvg = zr.painter.getType() === 'svg'; + if (!isSvg && this._lastZlevel != null) { + zr.painter.getLayer(this._lastZlevel).clear(true); + } + }, + + remove: function (ecModel, api) { + this._lineDraw && this._lineDraw.remove(); + this._lineDraw = null; + // Clear motion when lineDraw is removed + this._clearLayer(api); + }, + + dispose: function () {} +}); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + + +function normalize$2(a) { + if (!(a instanceof Array)) { + a = [a, a]; + } + return a; +} + +var opacityQuery = 'lineStyle.opacity'.split('.'); + +var linesVisual = { + seriesType: 'lines', + reset: function (seriesModel, ecModel, api) { + var symbolType = normalize$2(seriesModel.get('symbol')); + var symbolSize = normalize$2(seriesModel.get('symbolSize')); + var data = seriesModel.getData(); + + data.setVisual('fromSymbol', symbolType && symbolType[0]); + data.setVisual('toSymbol', symbolType && symbolType[1]); + data.setVisual('fromSymbolSize', symbolSize && symbolSize[0]); + data.setVisual('toSymbolSize', symbolSize && symbolSize[1]); + data.setVisual('opacity', seriesModel.get(opacityQuery)); + + function dataEach(data, idx) { + var itemModel = data.getItemModel(idx); + var symbolType = normalize$2(itemModel.getShallow('symbol', true)); + var symbolSize = normalize$2(itemModel.getShallow('symbolSize', true)); + var opacity = itemModel.get(opacityQuery); + + symbolType[0] && data.setItemVisual(idx, 'fromSymbol', symbolType[0]); + symbolType[1] && data.setItemVisual(idx, 'toSymbol', symbolType[1]); + symbolSize[0] && data.setItemVisual(idx, 'fromSymbolSize', symbolSize[0]); + symbolSize[1] && data.setItemVisual(idx, 'toSymbolSize', symbolSize[1]); + + data.setItemVisual(idx, 'opacity', opacity); + } + + return {dataEach: data.hasItemOption ? dataEach : null}; + } +}; + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +registerLayout(linesLayout); +registerVisual(linesVisual); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +SeriesModel.extend({ + type: 'series.heatmap', + + getInitialData: function (option, ecModel) { + return createListFromArray(this.getSource(), this, { + generateCoord: 'value' + }); + }, + + preventIncremental: function () { + var coordSysCreator = CoordinateSystemManager.get(this.get('coordinateSystem')); + if (coordSysCreator && coordSysCreator.dimensions) { + return coordSysCreator.dimensions[0] === 'lng' && coordSysCreator.dimensions[1] === 'lat'; + } + }, + + defaultOption: { + + // Cartesian2D or geo + coordinateSystem: 'cartesian2d', + + zlevel: 0, + + z: 2, + + // Cartesian coordinate system + // xAxisIndex: 0, + // yAxisIndex: 0, + + // Geo coordinate system + geoIndex: 0, + + blurSize: 30, + + pointSize: 20, + + maxOpacity: 1, + + minOpacity: 0 + } +}); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/* global Uint8ClampedArray */ + +/** + * @file defines echarts Heatmap Chart + * @author Ovilia (me@zhangwenli.com) + * Inspired by https://github.com/mourner/simpleheat + * + * @module + */ + +var GRADIENT_LEVELS = 256; + +/** + * Heatmap Chart + * + * @class + */ +function Heatmap() { + var canvas = createCanvas(); + this.canvas = canvas; + + this.blurSize = 30; + this.pointSize = 20; + + this.maxOpacity = 1; + this.minOpacity = 0; + + this._gradientPixels = {}; +} + +Heatmap.prototype = { + /** + * Renders Heatmap and returns the rendered canvas + * @param {Array} data array of data, each has x, y, value + * @param {number} width canvas width + * @param {number} height canvas height + */ + update: function (data, width, height, normalize, colorFunc, isInRange) { + var brush = this._getBrush(); + var gradientInRange = this._getGradient(data, colorFunc, 'inRange'); + var gradientOutOfRange = this._getGradient(data, colorFunc, 'outOfRange'); + var r = this.pointSize + this.blurSize; + + var canvas = this.canvas; + var ctx = canvas.getContext('2d'); + var len = data.length; + canvas.width = width; + canvas.height = height; + for (var i = 0; i < len; ++i) { + var p = data[i]; + var x = p[0]; + var y = p[1]; + var value = p[2]; + + // calculate alpha using value + var alpha = normalize(value); + + // draw with the circle brush with alpha + ctx.globalAlpha = alpha; + ctx.drawImage(brush, x - r, y - r); + } + + if (!canvas.width || !canvas.height) { + // Avoid "Uncaught DOMException: Failed to execute 'getImageData' on + // 'CanvasRenderingContext2D': The source height is 0." + return canvas; + } + + // colorize the canvas using alpha value and set with gradient + var imageData = ctx.getImageData(0, 0, canvas.width, canvas.height); + + var pixels = imageData.data; + var offset = 0; + var pixelLen = pixels.length; + var minOpacity = this.minOpacity; + var maxOpacity = this.maxOpacity; + var diffOpacity = maxOpacity - minOpacity; + + while (offset < pixelLen) { + var alpha = pixels[offset + 3] / 256; + var gradientOffset = Math.floor(alpha * (GRADIENT_LEVELS - 1)) * 4; + // Simple optimize to ignore the empty data + if (alpha > 0) { + var gradient = isInRange(alpha) ? gradientInRange : gradientOutOfRange; + // Any alpha > 0 will be mapped to [minOpacity, maxOpacity] + alpha > 0 && (alpha = alpha * diffOpacity + minOpacity); + pixels[offset++] = gradient[gradientOffset]; + pixels[offset++] = gradient[gradientOffset + 1]; + pixels[offset++] = gradient[gradientOffset + 2]; + pixels[offset++] = gradient[gradientOffset + 3] * alpha * 256; + } + else { + offset += 4; + } + } + ctx.putImageData(imageData, 0, 0); + + return canvas; + }, + + /** + * get canvas of a black circle brush used for canvas to draw later + * @private + * @returns {Object} circle brush canvas + */ + _getBrush: function () { + var brushCanvas = this._brushCanvas || (this._brushCanvas = createCanvas()); + // set brush size + var r = this.pointSize + this.blurSize; + var d = r * 2; + brushCanvas.width = d; + brushCanvas.height = d; + + var ctx = brushCanvas.getContext('2d'); + ctx.clearRect(0, 0, d, d); + + // in order to render shadow without the distinct circle, + // draw the distinct circle in an invisible place, + // and use shadowOffset to draw shadow in the center of the canvas + ctx.shadowOffsetX = d; + ctx.shadowBlur = this.blurSize; + // draw the shadow in black, and use alpha and shadow blur to generate + // color in color map + ctx.shadowColor = '#000'; + + // draw circle in the left to the canvas + ctx.beginPath(); + ctx.arc(-r, r, this.pointSize, 0, Math.PI * 2, true); + ctx.closePath(); + ctx.fill(); + return brushCanvas; + }, + + /** + * get gradient color map + * @private + */ + _getGradient: function (data, colorFunc, state) { + var gradientPixels = this._gradientPixels; + var pixelsSingleState = gradientPixels[state] || (gradientPixels[state] = new Uint8ClampedArray(256 * 4)); + var color = [0, 0, 0, 0]; + var off = 0; + for (var i = 0; i < 256; i++) { + colorFunc[state](i / 255, true, color); + pixelsSingleState[off++] = color[0]; + pixelsSingleState[off++] = color[1]; + pixelsSingleState[off++] = color[2]; + pixelsSingleState[off++] = color[3]; + } + return pixelsSingleState; + } +}; + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +function getIsInPiecewiseRange(dataExtent, pieceList, selected) { + var dataSpan = dataExtent[1] - dataExtent[0]; + pieceList = map(pieceList, function (piece) { + return { + interval: [ + (piece.interval[0] - dataExtent[0]) / dataSpan, + (piece.interval[1] - dataExtent[0]) / dataSpan + ] + }; + }); + var len = pieceList.length; + var lastIndex = 0; + + return function (val) { + // Try to find in the location of the last found + for (var i = lastIndex; i < len; i++) { + var interval = pieceList[i].interval; + if (interval[0] <= val && val <= interval[1]) { + lastIndex = i; + break; + } + } + if (i === len) { // Not found, back interation + for (var i = lastIndex - 1; i >= 0; i--) { + var interval = pieceList[i].interval; + if (interval[0] <= val && val <= interval[1]) { + lastIndex = i; + break; + } + } + } + return i >= 0 && i < len && selected[i]; + }; +} + +function getIsInContinuousRange(dataExtent, range) { + var dataSpan = dataExtent[1] - dataExtent[0]; + range = [ + (range[0] - dataExtent[0]) / dataSpan, + (range[1] - dataExtent[0]) / dataSpan + ]; + return function (val) { + return val >= range[0] && val <= range[1]; + }; +} + +function isGeoCoordSys(coordSys) { + var dimensions = coordSys.dimensions; + // Not use coorSys.type === 'geo' because coordSys maybe extended + return dimensions[0] === 'lng' && dimensions[1] === 'lat'; +} + +extendChartView({ + + type: 'heatmap', + + render: function (seriesModel, ecModel, api) { + var visualMapOfThisSeries; + ecModel.eachComponent('visualMap', function (visualMap) { + visualMap.eachTargetSeries(function (targetSeries) { + if (targetSeries === seriesModel) { + visualMapOfThisSeries = visualMap; + } + }); + }); + + if (__DEV__) { + if (!visualMapOfThisSeries) { + throw new Error('Heatmap must use with visualMap'); + } + } + + this.group.removeAll(); + + this._incrementalDisplayable = null; + + var coordSys = seriesModel.coordinateSystem; + if (coordSys.type === 'cartesian2d' || coordSys.type === 'calendar') { + this._renderOnCartesianAndCalendar(seriesModel, api, 0, seriesModel.getData().count()); + } + else if (isGeoCoordSys(coordSys)) { + this._renderOnGeo( + coordSys, seriesModel, visualMapOfThisSeries, api + ); + } + }, + + incrementalPrepareRender: function (seriesModel, ecModel, api) { + this.group.removeAll(); + }, + + incrementalRender: function (params, seriesModel, ecModel, api) { + var coordSys = seriesModel.coordinateSystem; + if (coordSys) { + this._renderOnCartesianAndCalendar(seriesModel, api, params.start, params.end, true); + } + }, + + _renderOnCartesianAndCalendar: function (seriesModel, api, start, end, incremental) { + + var coordSys = seriesModel.coordinateSystem; + var width; + var height; + + if (coordSys.type === 'cartesian2d') { + var xAxis = coordSys.getAxis('x'); + var yAxis = coordSys.getAxis('y'); + + if (__DEV__) { + if (!(xAxis.type === 'category' && yAxis.type === 'category')) { + throw new Error('Heatmap on cartesian must have two category axes'); + } + if (!(xAxis.onBand && yAxis.onBand)) { + throw new Error('Heatmap on cartesian must have two axes with boundaryGap true'); + } + } + + width = xAxis.getBandWidth(); + height = yAxis.getBandWidth(); + } + + var group = this.group; + var data = seriesModel.getData(); + + var itemStyleQuery = 'itemStyle'; + var hoverItemStyleQuery = 'emphasis.itemStyle'; + var labelQuery = 'label'; + var hoverLabelQuery = 'emphasis.label'; + var style = seriesModel.getModel(itemStyleQuery).getItemStyle(['color']); + var hoverStl = seriesModel.getModel(hoverItemStyleQuery).getItemStyle(); + var labelModel = seriesModel.getModel(labelQuery); + var hoverLabelModel = seriesModel.getModel(hoverLabelQuery); + var coordSysType = coordSys.type; + + + var dataDims = coordSysType === 'cartesian2d' + ? [ + data.mapDimension('x'), + data.mapDimension('y'), + data.mapDimension('value') + ] + : [ + data.mapDimension('time'), + data.mapDimension('value') + ]; + + for (var idx = start; idx < end; idx++) { + var rect; + + if (coordSysType === 'cartesian2d') { + // Ignore empty data + if (isNaN(data.get(dataDims[2], idx))) { + continue; + } + + var point = coordSys.dataToPoint([ + data.get(dataDims[0], idx), + data.get(dataDims[1], idx) + ]); + + rect = new Rect({ + shape: { + x: point[0] - width / 2, + y: point[1] - height / 2, + width: width, + height: height + }, + style: { + fill: data.getItemVisual(idx, 'color'), + opacity: data.getItemVisual(idx, 'opacity') + } + }); + } + else { + // Ignore empty data + if (isNaN(data.get(dataDims[1], idx))) { + continue; + } + + rect = new Rect({ + z2: 1, + shape: coordSys.dataToRect([data.get(dataDims[0], idx)]).contentShape, + style: { + fill: data.getItemVisual(idx, 'color'), + opacity: data.getItemVisual(idx, 'opacity') + } + }); + } + + var itemModel = data.getItemModel(idx); + + // Optimization for large datset + if (data.hasItemOption) { + style = itemModel.getModel(itemStyleQuery).getItemStyle(['color']); + hoverStl = itemModel.getModel(hoverItemStyleQuery).getItemStyle(); + labelModel = itemModel.getModel(labelQuery); + hoverLabelModel = itemModel.getModel(hoverLabelQuery); + } + + var rawValue = seriesModel.getRawValue(idx); + var defaultText = '-'; + if (rawValue && rawValue[2] != null) { + defaultText = rawValue[2]; + } + + setLabelStyle( + style, hoverStl, labelModel, hoverLabelModel, + { + labelFetcher: seriesModel, + labelDataIndex: idx, + defaultText: defaultText, + isRectText: true + } + ); + + rect.setStyle(style); + setHoverStyle(rect, data.hasItemOption ? hoverStl : extend({}, hoverStl)); + + rect.incremental = incremental; + // PENDING + if (incremental) { + // Rect must use hover layer if it's incremental. + rect.useHoverLayer = true; + } + + group.add(rect); + data.setItemGraphicEl(idx, rect); + } + }, + + _renderOnGeo: function (geo, seriesModel, visualMapModel, api) { + var inRangeVisuals = visualMapModel.targetVisuals.inRange; + var outOfRangeVisuals = visualMapModel.targetVisuals.outOfRange; + // if (!visualMapping) { + // throw new Error('Data range must have color visuals'); + // } + + var data = seriesModel.getData(); + var hmLayer = this._hmLayer || (this._hmLayer || new Heatmap()); + hmLayer.blurSize = seriesModel.get('blurSize'); + hmLayer.pointSize = seriesModel.get('pointSize'); + hmLayer.minOpacity = seriesModel.get('minOpacity'); + hmLayer.maxOpacity = seriesModel.get('maxOpacity'); + + var rect = geo.getViewRect().clone(); + var roamTransform = geo.getRoamTransform(); + rect.applyTransform(roamTransform); + + // Clamp on viewport + var x = Math.max(rect.x, 0); + var y = Math.max(rect.y, 0); + var x2 = Math.min(rect.width + rect.x, api.getWidth()); + var y2 = Math.min(rect.height + rect.y, api.getHeight()); + var width = x2 - x; + var height = y2 - y; + + var dims = [ + data.mapDimension('lng'), + data.mapDimension('lat'), + data.mapDimension('value') + ]; + + var points = data.mapArray(dims, function (lng, lat, value) { + var pt = geo.dataToPoint([lng, lat]); + pt[0] -= x; + pt[1] -= y; + pt.push(value); + return pt; + }); + + var dataExtent = visualMapModel.getExtent(); + var isInRange = visualMapModel.type === 'visualMap.continuous' + ? getIsInContinuousRange(dataExtent, visualMapModel.option.range) + : getIsInPiecewiseRange( + dataExtent, visualMapModel.getPieceList(), visualMapModel.option.selected + ); + + hmLayer.update( + points, width, height, + inRangeVisuals.color.getNormalizer(), + { + inRange: inRangeVisuals.color.getColorMapper(), + outOfRange: outOfRangeVisuals.color.getColorMapper() + }, + isInRange + ); + var img = new ZImage({ + style: { + width: width, + height: height, + x: x, + y: y, + image: hmLayer.canvas + }, + silent: true + }); + this.group.add(img); + }, + + dispose: function () {} +}); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var PictorialBarSeries = BaseBarSeries.extend({ + + type: 'series.pictorialBar', + + dependencies: ['grid'], + + defaultOption: { + symbol: 'circle', // Customized bar shape + symbolSize: null, // Can be ['100%', '100%'], null means auto. + symbolRotate: null, + + symbolPosition: null, // 'start' or 'end' or 'center', null means auto. + symbolOffset: null, + symbolMargin: null, // start margin and end margin. Can be a number or a percent string. + // Auto margin by defualt. + symbolRepeat: false, // false/null/undefined, means no repeat. + // Can be true, means auto calculate repeat times and cut by data. + // Can be a number, specifies repeat times, and do not cut by data. + // Can be 'fixed', means auto calculate repeat times but do not cut by data. + symbolRepeatDirection: 'end', // 'end' means from 'start' to 'end'. + + symbolClip: false, + symbolBoundingData: null, // Can be 60 or -40 or [-40, 60] + symbolPatternSize: 400, // 400 * 400 px + + barGap: '-100%', // In most case, overlap is needed. + + // z can be set in data item, which is z2 actually. + + // Disable progressive + progressive: 0, + hoverAnimation: false // Open only when needed. + }, + + getInitialData: function (option) { + // Disable stack. + option.stack = null; + return PictorialBarSeries.superApply(this, 'getInitialData', arguments); + } +}); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var BAR_BORDER_WIDTH_QUERY$1 = ['itemStyle', 'borderWidth']; + +// index: +isHorizontal +var LAYOUT_ATTRS = [ + {xy: 'x', wh: 'width', index: 0, posDesc: ['left', 'right']}, + {xy: 'y', wh: 'height', index: 1, posDesc: ['top', 'bottom']} +]; + +var pathForLineWidth = new Circle(); + +var BarView$1 = extendChartView({ + + type: 'pictorialBar', + + render: function (seriesModel, ecModel, api) { + var group = this.group; + var data = seriesModel.getData(); + var oldData = this._data; + + var cartesian = seriesModel.coordinateSystem; + var baseAxis = cartesian.getBaseAxis(); + var isHorizontal = !!baseAxis.isHorizontal(); + var coordSysRect = cartesian.grid.getRect(); + + var opt = { + ecSize: {width: api.getWidth(), height: api.getHeight()}, + seriesModel: seriesModel, + coordSys: cartesian, + coordSysExtent: [ + [coordSysRect.x, coordSysRect.x + coordSysRect.width], + [coordSysRect.y, coordSysRect.y + coordSysRect.height] + ], + isHorizontal: isHorizontal, + valueDim: LAYOUT_ATTRS[+isHorizontal], + categoryDim: LAYOUT_ATTRS[1 - isHorizontal] + }; + + data.diff(oldData) + .add(function (dataIndex) { + if (!data.hasValue(dataIndex)) { + return; + } + + var itemModel = getItemModel(data, dataIndex); + var symbolMeta = getSymbolMeta(data, dataIndex, itemModel, opt); + + var bar = createBar(data, opt, symbolMeta); + + data.setItemGraphicEl(dataIndex, bar); + group.add(bar); + + updateCommon$1(bar, opt, symbolMeta); + }) + .update(function (newIndex, oldIndex) { + var bar = oldData.getItemGraphicEl(oldIndex); + + if (!data.hasValue(newIndex)) { + group.remove(bar); + return; + } + + var itemModel = getItemModel(data, newIndex); + var symbolMeta = getSymbolMeta(data, newIndex, itemModel, opt); + + var pictorialShapeStr = getShapeStr(data, symbolMeta); + if (bar && pictorialShapeStr !== bar.__pictorialShapeStr) { + group.remove(bar); + data.setItemGraphicEl(newIndex, null); + bar = null; + } + + if (bar) { + updateBar(bar, opt, symbolMeta); + } + else { + bar = createBar(data, opt, symbolMeta, true); + } + + data.setItemGraphicEl(newIndex, bar); + bar.__pictorialSymbolMeta = symbolMeta; + // Add back + group.add(bar); + + updateCommon$1(bar, opt, symbolMeta); + }) + .remove(function (dataIndex) { + var bar = oldData.getItemGraphicEl(dataIndex); + bar && removeBar(oldData, dataIndex, bar.__pictorialSymbolMeta.animationModel, bar); + }) + .execute(); + + this._data = data; + + return this.group; + }, + + dispose: noop, + + remove: function (ecModel, api) { + var group = this.group; + var data = this._data; + if (ecModel.get('animation')) { + if (data) { + data.eachItemGraphicEl(function (bar) { + removeBar(data, bar.dataIndex, ecModel, bar); + }); + } + } + else { + group.removeAll(); + } + } +}); + + +// Set or calculate default value about symbol, and calculate layout info. +function getSymbolMeta(data, dataIndex, itemModel, opt) { + var layout = data.getItemLayout(dataIndex); + var symbolRepeat = itemModel.get('symbolRepeat'); + var symbolClip = itemModel.get('symbolClip'); + var symbolPosition = itemModel.get('symbolPosition') || 'start'; + var symbolRotate = itemModel.get('symbolRotate'); + var rotation = (symbolRotate || 0) * Math.PI / 180 || 0; + var symbolPatternSize = itemModel.get('symbolPatternSize') || 2; + var isAnimationEnabled = itemModel.isAnimationEnabled(); + + var symbolMeta = { + dataIndex: dataIndex, + layout: layout, + itemModel: itemModel, + symbolType: data.getItemVisual(dataIndex, 'symbol') || 'circle', + color: data.getItemVisual(dataIndex, 'color'), + symbolClip: symbolClip, + symbolRepeat: symbolRepeat, + symbolRepeatDirection: itemModel.get('symbolRepeatDirection'), + symbolPatternSize: symbolPatternSize, + rotation: rotation, + animationModel: isAnimationEnabled ? itemModel : null, + hoverAnimation: isAnimationEnabled && itemModel.get('hoverAnimation'), + z2: itemModel.getShallow('z', true) || 0 + }; + + prepareBarLength(itemModel, symbolRepeat, layout, opt, symbolMeta); + + prepareSymbolSize( + data, dataIndex, layout, symbolRepeat, symbolClip, symbolMeta.boundingLength, + symbolMeta.pxSign, symbolPatternSize, opt, symbolMeta + ); + + prepareLineWidth(itemModel, symbolMeta.symbolScale, rotation, opt, symbolMeta); + + var symbolSize = symbolMeta.symbolSize; + var symbolOffset = itemModel.get('symbolOffset'); + if (isArray(symbolOffset)) { + symbolOffset = [ + parsePercent$1(symbolOffset[0], symbolSize[0]), + parsePercent$1(symbolOffset[1], symbolSize[1]) + ]; + } + + prepareLayoutInfo( + itemModel, symbolSize, layout, symbolRepeat, symbolClip, symbolOffset, + symbolPosition, symbolMeta.valueLineWidth, symbolMeta.boundingLength, symbolMeta.repeatCutLength, + opt, symbolMeta + ); + + return symbolMeta; +} + +// bar length can be negative. +function prepareBarLength(itemModel, symbolRepeat, layout, opt, output) { + var valueDim = opt.valueDim; + var symbolBoundingData = itemModel.get('symbolBoundingData'); + var valueAxis = opt.coordSys.getOtherAxis(opt.coordSys.getBaseAxis()); + var zeroPx = valueAxis.toGlobalCoord(valueAxis.dataToCoord(0)); + var pxSignIdx = 1 - +(layout[valueDim.wh] <= 0); + var boundingLength; + + if (isArray(symbolBoundingData)) { + var symbolBoundingExtent = [ + convertToCoordOnAxis(valueAxis, symbolBoundingData[0]) - zeroPx, + convertToCoordOnAxis(valueAxis, symbolBoundingData[1]) - zeroPx + ]; + symbolBoundingExtent[1] < symbolBoundingExtent[0] && (symbolBoundingExtent.reverse()); + boundingLength = symbolBoundingExtent[pxSignIdx]; + } + else if (symbolBoundingData != null) { + boundingLength = convertToCoordOnAxis(valueAxis, symbolBoundingData) - zeroPx; + } + else if (symbolRepeat) { + boundingLength = opt.coordSysExtent[valueDim.index][pxSignIdx] - zeroPx; + } + else { + boundingLength = layout[valueDim.wh]; + } + + output.boundingLength = boundingLength; + + if (symbolRepeat) { + output.repeatCutLength = layout[valueDim.wh]; + } + + output.pxSign = boundingLength > 0 ? 1 : boundingLength < 0 ? -1 : 0; +} + +function convertToCoordOnAxis(axis, value) { + return axis.toGlobalCoord(axis.dataToCoord(axis.scale.parse(value))); +} + +// Support ['100%', '100%'] +function prepareSymbolSize( + data, dataIndex, layout, symbolRepeat, symbolClip, boundingLength, + pxSign, symbolPatternSize, opt, output +) { + var valueDim = opt.valueDim; + var categoryDim = opt.categoryDim; + var categorySize = Math.abs(layout[categoryDim.wh]); + + var symbolSize = data.getItemVisual(dataIndex, 'symbolSize'); + if (isArray(symbolSize)) { + symbolSize = symbolSize.slice(); + } + else { + if (symbolSize == null) { + symbolSize = '100%'; + } + symbolSize = [symbolSize, symbolSize]; + } + + // Note: percentage symbolSize (like '100%') do not consider lineWidth, because it is + // to complicated to calculate real percent value if considering scaled lineWidth. + // So the actual size will bigger than layout size if lineWidth is bigger than zero, + // which can be tolerated in pictorial chart. + + symbolSize[categoryDim.index] = parsePercent$1( + symbolSize[categoryDim.index], + categorySize + ); + symbolSize[valueDim.index] = parsePercent$1( + symbolSize[valueDim.index], + symbolRepeat ? categorySize : Math.abs(boundingLength) + ); + + output.symbolSize = symbolSize; + + // If x or y is less than zero, show reversed shape. + var symbolScale = output.symbolScale = [ + symbolSize[0] / symbolPatternSize, + symbolSize[1] / symbolPatternSize + ]; + // Follow convention, 'right' and 'top' is the normal scale. + symbolScale[valueDim.index] *= (opt.isHorizontal ? -1 : 1) * pxSign; +} + +function prepareLineWidth(itemModel, symbolScale, rotation, opt, output) { + // In symbols are drawn with scale, so do not need to care about the case that width + // or height are too small. But symbol use strokeNoScale, where acture lineWidth should + // be calculated. + var valueLineWidth = itemModel.get(BAR_BORDER_WIDTH_QUERY$1) || 0; + + if (valueLineWidth) { + pathForLineWidth.attr({ + scale: symbolScale.slice(), + rotation: rotation + }); + pathForLineWidth.updateTransform(); + valueLineWidth /= pathForLineWidth.getLineScale(); + valueLineWidth *= symbolScale[opt.valueDim.index]; + } + + output.valueLineWidth = valueLineWidth; +} + +function prepareLayoutInfo( + itemModel, symbolSize, layout, symbolRepeat, symbolClip, symbolOffset, + symbolPosition, valueLineWidth, boundingLength, repeatCutLength, opt, output +) { + var categoryDim = opt.categoryDim; + var valueDim = opt.valueDim; + var pxSign = output.pxSign; + + var unitLength = Math.max(symbolSize[valueDim.index] + valueLineWidth, 0); + var pathLen = unitLength; + + // Note: rotation will not effect the layout of symbols, because user may + // want symbols to rotate on its center, which should not be translated + // when rotating. + + if (symbolRepeat) { + var absBoundingLength = Math.abs(boundingLength); + + var symbolMargin = retrieve(itemModel.get('symbolMargin'), '15%') + ''; + var hasEndGap = false; + if (symbolMargin.lastIndexOf('!') === symbolMargin.length - 1) { + hasEndGap = true; + symbolMargin = symbolMargin.slice(0, symbolMargin.length - 1); + } + symbolMargin = parsePercent$1(symbolMargin, symbolSize[valueDim.index]); + + var uLenWithMargin = Math.max(unitLength + symbolMargin * 2, 0); + + // When symbol margin is less than 0, margin at both ends will be subtracted + // to ensure that all of the symbols will not be overflow the given area. + var endFix = hasEndGap ? 0 : symbolMargin * 2; + + // Both final repeatTimes and final symbolMargin area calculated based on + // boundingLength. + var repeatSpecified = isNumeric(symbolRepeat); + var repeatTimes = repeatSpecified + ? symbolRepeat + : toIntTimes((absBoundingLength + endFix) / uLenWithMargin); + + // Adjust calculate margin, to ensure each symbol is displayed + // entirely in the given layout area. + var mDiff = absBoundingLength - repeatTimes * unitLength; + symbolMargin = mDiff / 2 / (hasEndGap ? repeatTimes : repeatTimes - 1); + uLenWithMargin = unitLength + symbolMargin * 2; + endFix = hasEndGap ? 0 : symbolMargin * 2; + + // Update repeatTimes when not all symbol will be shown. + if (!repeatSpecified && symbolRepeat !== 'fixed') { + repeatTimes = repeatCutLength + ? toIntTimes((Math.abs(repeatCutLength) + endFix) / uLenWithMargin) + : 0; + } + + pathLen = repeatTimes * uLenWithMargin - endFix; + output.repeatTimes = repeatTimes; + output.symbolMargin = symbolMargin; + } + + var sizeFix = pxSign * (pathLen / 2); + var pathPosition = output.pathPosition = []; + pathPosition[categoryDim.index] = layout[categoryDim.wh] / 2; + pathPosition[valueDim.index] = symbolPosition === 'start' + ? sizeFix + : symbolPosition === 'end' + ? boundingLength - sizeFix + : boundingLength / 2; // 'center' + if (symbolOffset) { + pathPosition[0] += symbolOffset[0]; + pathPosition[1] += symbolOffset[1]; + } + + var bundlePosition = output.bundlePosition = []; + bundlePosition[categoryDim.index] = layout[categoryDim.xy]; + bundlePosition[valueDim.index] = layout[valueDim.xy]; + + var barRectShape = output.barRectShape = extend({}, layout); + barRectShape[valueDim.wh] = pxSign * Math.max( + Math.abs(layout[valueDim.wh]), Math.abs(pathPosition[valueDim.index] + sizeFix) + ); + barRectShape[categoryDim.wh] = layout[categoryDim.wh]; + + var clipShape = output.clipShape = {}; + // Consider that symbol may be overflow layout rect. + clipShape[categoryDim.xy] = -layout[categoryDim.xy]; + clipShape[categoryDim.wh] = opt.ecSize[categoryDim.wh]; + clipShape[valueDim.xy] = 0; + clipShape[valueDim.wh] = layout[valueDim.wh]; +} + +function createPath(symbolMeta) { + var symbolPatternSize = symbolMeta.symbolPatternSize; + var path = createSymbol( + // Consider texture img, make a big size. + symbolMeta.symbolType, + -symbolPatternSize / 2, + -symbolPatternSize / 2, + symbolPatternSize, + symbolPatternSize, + symbolMeta.color + ); + path.attr({ + culling: true + }); + path.type !== 'image' && path.setStyle({ + strokeNoScale: true + }); + + return path; +} + +function createOrUpdateRepeatSymbols(bar, opt, symbolMeta, isUpdate) { + var bundle = bar.__pictorialBundle; + var symbolSize = symbolMeta.symbolSize; + var valueLineWidth = symbolMeta.valueLineWidth; + var pathPosition = symbolMeta.pathPosition; + var valueDim = opt.valueDim; + var repeatTimes = symbolMeta.repeatTimes || 0; + + var index = 0; + var unit = symbolSize[opt.valueDim.index] + valueLineWidth + symbolMeta.symbolMargin * 2; + + eachPath(bar, function (path) { + path.__pictorialAnimationIndex = index; + path.__pictorialRepeatTimes = repeatTimes; + if (index < repeatTimes) { + updateAttr(path, null, makeTarget(index), symbolMeta, isUpdate); + } + else { + updateAttr(path, null, {scale: [0, 0]}, symbolMeta, isUpdate, function () { + bundle.remove(path); + }); + } + + updateHoverAnimation(path, symbolMeta); + + index++; + }); + + for (; index < repeatTimes; index++) { + var path = createPath(symbolMeta); + path.__pictorialAnimationIndex = index; + path.__pictorialRepeatTimes = repeatTimes; + bundle.add(path); + + var target = makeTarget(index); + + updateAttr( + path, + { + position: target.position, + scale: [0, 0] + }, + { + scale: target.scale, + rotation: target.rotation + }, + symbolMeta, + isUpdate + ); + + // FIXME + // If all emphasis/normal through action. + path + .on('mouseover', onMouseOver) + .on('mouseout', onMouseOut); + + updateHoverAnimation(path, symbolMeta); + } + + function makeTarget(index) { + var position = pathPosition.slice(); + // (start && pxSign > 0) || (end && pxSign < 0): i = repeatTimes - index + // Otherwise: i = index; + var pxSign = symbolMeta.pxSign; + var i = index; + if (symbolMeta.symbolRepeatDirection === 'start' ? pxSign > 0 : pxSign < 0) { + i = repeatTimes - 1 - index; + } + position[valueDim.index] = unit * (i - repeatTimes / 2 + 0.5) + pathPosition[valueDim.index]; + + return { + position: position, + scale: symbolMeta.symbolScale.slice(), + rotation: symbolMeta.rotation + }; + } + + function onMouseOver() { + eachPath(bar, function (path) { + path.trigger('emphasis'); + }); + } + + function onMouseOut() { + eachPath(bar, function (path) { + path.trigger('normal'); + }); + } +} + +function createOrUpdateSingleSymbol(bar, opt, symbolMeta, isUpdate) { + var bundle = bar.__pictorialBundle; + var mainPath = bar.__pictorialMainPath; + + if (!mainPath) { + mainPath = bar.__pictorialMainPath = createPath(symbolMeta); + bundle.add(mainPath); + + updateAttr( + mainPath, + { + position: symbolMeta.pathPosition.slice(), + scale: [0, 0], + rotation: symbolMeta.rotation + }, + { + scale: symbolMeta.symbolScale.slice() + }, + symbolMeta, + isUpdate + ); + + mainPath + .on('mouseover', onMouseOver) + .on('mouseout', onMouseOut); + } + else { + updateAttr( + mainPath, + null, + { + position: symbolMeta.pathPosition.slice(), + scale: symbolMeta.symbolScale.slice(), + rotation: symbolMeta.rotation + }, + symbolMeta, + isUpdate + ); + } + + updateHoverAnimation(mainPath, symbolMeta); + + function onMouseOver() { + this.trigger('emphasis'); + } + + function onMouseOut() { + this.trigger('normal'); + } +} + +// bar rect is used for label. +function createOrUpdateBarRect(bar, symbolMeta, isUpdate) { + var rectShape = extend({}, symbolMeta.barRectShape); + + var barRect = bar.__pictorialBarRect; + if (!barRect) { + barRect = bar.__pictorialBarRect = new Rect({ + z2: 2, + shape: rectShape, + silent: true, + style: { + stroke: 'transparent', + fill: 'transparent', + lineWidth: 0 + } + }); + + bar.add(barRect); + } + else { + updateAttr(barRect, null, {shape: rectShape}, symbolMeta, isUpdate); + } +} + +function createOrUpdateClip(bar, opt, symbolMeta, isUpdate) { + // If not clip, symbol will be remove and rebuilt. + if (symbolMeta.symbolClip) { + var clipPath = bar.__pictorialClipPath; + var clipShape = extend({}, symbolMeta.clipShape); + var valueDim = opt.valueDim; + var animationModel = symbolMeta.animationModel; + var dataIndex = symbolMeta.dataIndex; + + if (clipPath) { + updateProps( + clipPath, {shape: clipShape}, animationModel, dataIndex + ); + } + else { + clipShape[valueDim.wh] = 0; + clipPath = new Rect({shape: clipShape}); + bar.__pictorialBundle.setClipPath(clipPath); + bar.__pictorialClipPath = clipPath; + + var target = {}; + target[valueDim.wh] = symbolMeta.clipShape[valueDim.wh]; + + graphic[isUpdate ? 'updateProps' : 'initProps']( + clipPath, {shape: target}, animationModel, dataIndex + ); + } + } +} + +function getItemModel(data, dataIndex) { + var itemModel = data.getItemModel(dataIndex); + itemModel.getAnimationDelayParams = getAnimationDelayParams; + itemModel.isAnimationEnabled = isAnimationEnabled; + return itemModel; +} + +function getAnimationDelayParams(path) { + // The order is the same as the z-order, see `symbolRepeatDiretion`. + return { + index: path.__pictorialAnimationIndex, + count: path.__pictorialRepeatTimes + }; +} + +function isAnimationEnabled() { + // `animation` prop can be set on itemModel in pictorial bar chart. + return this.parentModel.isAnimationEnabled() && !!this.getShallow('animation'); +} + +function updateHoverAnimation(path, symbolMeta) { + path.off('emphasis').off('normal'); + + var scale = symbolMeta.symbolScale.slice(); + + symbolMeta.hoverAnimation && path + .on('emphasis', function () { + this.animateTo({ + scale: [scale[0] * 1.1, scale[1] * 1.1] + }, 400, 'elasticOut'); + }) + .on('normal', function () { + this.animateTo({ + scale: scale.slice() + }, 400, 'elasticOut'); + }); +} + +function createBar(data, opt, symbolMeta, isUpdate) { + // bar is the main element for each data. + var bar = new Group(); + // bundle is used for location and clip. + var bundle = new Group(); + bar.add(bundle); + bar.__pictorialBundle = bundle; + bundle.attr('position', symbolMeta.bundlePosition.slice()); + + if (symbolMeta.symbolRepeat) { + createOrUpdateRepeatSymbols(bar, opt, symbolMeta); + } + else { + createOrUpdateSingleSymbol(bar, opt, symbolMeta); + } + + createOrUpdateBarRect(bar, symbolMeta, isUpdate); + + createOrUpdateClip(bar, opt, symbolMeta, isUpdate); + + bar.__pictorialShapeStr = getShapeStr(data, symbolMeta); + bar.__pictorialSymbolMeta = symbolMeta; + + return bar; +} + +function updateBar(bar, opt, symbolMeta) { + var animationModel = symbolMeta.animationModel; + var dataIndex = symbolMeta.dataIndex; + var bundle = bar.__pictorialBundle; + + updateProps( + bundle, {position: symbolMeta.bundlePosition.slice()}, animationModel, dataIndex + ); + + if (symbolMeta.symbolRepeat) { + createOrUpdateRepeatSymbols(bar, opt, symbolMeta, true); + } + else { + createOrUpdateSingleSymbol(bar, opt, symbolMeta, true); + } + + createOrUpdateBarRect(bar, symbolMeta, true); + + createOrUpdateClip(bar, opt, symbolMeta, true); +} + +function removeBar(data, dataIndex, animationModel, bar) { + // Not show text when animating + var labelRect = bar.__pictorialBarRect; + labelRect && (labelRect.style.text = null); + + var pathes = []; + eachPath(bar, function (path) { + pathes.push(path); + }); + bar.__pictorialMainPath && pathes.push(bar.__pictorialMainPath); + + // I do not find proper remove animation for clip yet. + bar.__pictorialClipPath && (animationModel = null); + + each$1(pathes, function (path) { + updateProps( + path, {scale: [0, 0]}, animationModel, dataIndex, + function () { + bar.parent && bar.parent.remove(bar); + } + ); + }); + + data.setItemGraphicEl(dataIndex, null); +} + +function getShapeStr(data, symbolMeta) { + return [ + data.getItemVisual(symbolMeta.dataIndex, 'symbol') || 'none', + !!symbolMeta.symbolRepeat, + !!symbolMeta.symbolClip + ].join(':'); +} + +function eachPath(bar, cb, context) { + // Do not use Group#eachChild, because it do not support remove. + each$1(bar.__pictorialBundle.children(), function (el) { + el !== bar.__pictorialBarRect && cb.call(context, el); + }); +} + +function updateAttr(el, immediateAttrs, animationAttrs, symbolMeta, isUpdate, cb) { + immediateAttrs && el.attr(immediateAttrs); + // when symbolCip used, only clip path has init animation, otherwise it would be weird effect. + if (symbolMeta.symbolClip && !isUpdate) { + animationAttrs && el.attr(animationAttrs); + } + else { + animationAttrs && graphic[isUpdate ? 'updateProps' : 'initProps']( + el, animationAttrs, symbolMeta.animationModel, symbolMeta.dataIndex, cb + ); + } +} + +function updateCommon$1(bar, opt, symbolMeta) { + var color = symbolMeta.color; + var dataIndex = symbolMeta.dataIndex; + var itemModel = symbolMeta.itemModel; + // Color must be excluded. + // Because symbol provide setColor individually to set fill and stroke + var normalStyle = itemModel.getModel('itemStyle').getItemStyle(['color']); + var hoverStyle = itemModel.getModel('emphasis.itemStyle').getItemStyle(); + var cursorStyle = itemModel.getShallow('cursor'); + + eachPath(bar, function (path) { + // PENDING setColor should be before setStyle!!! + path.setColor(color); + path.setStyle(defaults( + { + fill: color, + opacity: symbolMeta.opacity + }, + normalStyle + )); + setHoverStyle(path, hoverStyle); + + cursorStyle && (path.cursor = cursorStyle); + path.z2 = symbolMeta.z2; + }); + + var barRectHoverStyle = {}; + var barPositionOutside = opt.valueDim.posDesc[+(symbolMeta.boundingLength > 0)]; + var barRect = bar.__pictorialBarRect; + + setLabel( + barRect.style, barRectHoverStyle, itemModel, + color, opt.seriesModel, dataIndex, barPositionOutside + ); + + setHoverStyle(barRect, barRectHoverStyle); +} + +function toIntTimes(times) { + var roundedTimes = Math.round(times); + // Escapse accurate error + return Math.abs(times - roundedTimes) < 1e-4 + ? roundedTimes + : Math.ceil(times); +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +// In case developer forget to include grid component +registerLayout(curry( + layout, 'pictorialBar' +)); +registerVisual(visualSymbol('pictorialBar', 'roundRect')); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/** + * @constructor module:echarts/coord/single/SingleAxis + * @extends {module:echarts/coord/Axis} + * @param {string} dim + * @param {*} scale + * @param {Array.} coordExtent + * @param {string} axisType + * @param {string} position + */ +var SingleAxis = function (dim, scale, coordExtent, axisType, position) { + + Axis.call(this, dim, scale, coordExtent); + + /** + * Axis type + * - 'category' + * - 'value' + * - 'time' + * - 'log' + * @type {string} + */ + this.type = axisType || 'value'; + + /** + * Axis position + * - 'top' + * - 'bottom' + * - 'left' + * - 'right' + * @type {string} + */ + this.position = position || 'bottom'; + + /** + * Axis orient + * - 'horizontal' + * - 'vertical' + * @type {[type]} + */ + this.orient = null; + +}; + +SingleAxis.prototype = { + + constructor: SingleAxis, + + /** + * Axis model + * @type {module:echarts/coord/single/AxisModel} + */ + model: null, + + /** + * Judge the orient of the axis. + * @return {boolean} + */ + isHorizontal: function () { + var position = this.position; + return position === 'top' || position === 'bottom'; + + }, + + /** + * @override + */ + pointToData: function (point, clamp) { + return this.coordinateSystem.pointToData(point, clamp)[0]; + }, + + /** + * Convert the local coord(processed by dataToCoord()) + * to global coord(concrete pixel coord). + * designated by module:echarts/coord/single/Single. + * @type {Function} + */ + toGlobalCoord: null, + + /** + * Convert the global coord to local coord. + * designated by module:echarts/coord/single/Single. + * @type {Function} + */ + toLocalCoord: null + +}; + +inherits(SingleAxis, Axis); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/** + * Single coordinates system. + */ + +/** + * Create a single coordinates system. + * + * @param {module:echarts/coord/single/AxisModel} axisModel + * @param {module:echarts/model/Global} ecModel + * @param {module:echarts/ExtensionAPI} api + */ +function Single(axisModel, ecModel, api) { + + /** + * @type {string} + * @readOnly + */ + this.dimension = 'single'; + + /** + * Add it just for draw tooltip. + * + * @type {Array.} + * @readOnly + */ + this.dimensions = ['single']; + + /** + * @private + * @type {module:echarts/coord/single/SingleAxis}. + */ + this._axis = null; + + /** + * @private + * @type {module:zrender/core/BoundingRect} + */ + this._rect; + + this._init(axisModel, ecModel, api); + + /** + * @type {module:echarts/coord/single/AxisModel} + */ + this.model = axisModel; +} + +Single.prototype = { + + type: 'singleAxis', + + axisPointerEnabled: true, + + constructor: Single, + + /** + * Initialize single coordinate system. + * + * @param {module:echarts/coord/single/AxisModel} axisModel + * @param {module:echarts/model/Global} ecModel + * @param {module:echarts/ExtensionAPI} api + * @private + */ + _init: function (axisModel, ecModel, api) { + + var dim = this.dimension; + + var axis = new SingleAxis( + dim, + createScaleByModel(axisModel), + [0, 0], + axisModel.get('type'), + axisModel.get('position') + ); + + var isCategory = axis.type === 'category'; + axis.onBand = isCategory && axisModel.get('boundaryGap'); + axis.inverse = axisModel.get('inverse'); + axis.orient = axisModel.get('orient'); + + axisModel.axis = axis; + axis.model = axisModel; + axis.coordinateSystem = this; + this._axis = axis; + }, + + /** + * Update axis scale after data processed + * @param {module:echarts/model/Global} ecModel + * @param {module:echarts/ExtensionAPI} api + */ + update: function (ecModel, api) { + ecModel.eachSeries(function (seriesModel) { + if (seriesModel.coordinateSystem === this) { + var data = seriesModel.getData(); + each$1(data.mapDimension(this.dimension, true), function (dim) { + this._axis.scale.unionExtentFromData(data, dim); + }, this); + niceScaleExtent(this._axis.scale, this._axis.model); + } + }, this); + }, + + /** + * Resize the single coordinate system. + * + * @param {module:echarts/coord/single/AxisModel} axisModel + * @param {module:echarts/ExtensionAPI} api + */ + resize: function (axisModel, api) { + this._rect = getLayoutRect( + { + left: axisModel.get('left'), + top: axisModel.get('top'), + right: axisModel.get('right'), + bottom: axisModel.get('bottom'), + width: axisModel.get('width'), + height: axisModel.get('height') + }, + { + width: api.getWidth(), + height: api.getHeight() + } + ); + + this._adjustAxis(); + }, + + /** + * @return {module:zrender/core/BoundingRect} + */ + getRect: function () { + return this._rect; + }, + + /** + * @private + */ + _adjustAxis: function () { + + var rect = this._rect; + var axis = this._axis; + + var isHorizontal = axis.isHorizontal(); + var extent = isHorizontal ? [0, rect.width] : [0, rect.height]; + var idx = axis.reverse ? 1 : 0; + + axis.setExtent(extent[idx], extent[1 - idx]); + + this._updateAxisTransform(axis, isHorizontal ? rect.x : rect.y); + + }, + + /** + * @param {module:echarts/coord/single/SingleAxis} axis + * @param {number} coordBase + */ + _updateAxisTransform: function (axis, coordBase) { + + var axisExtent = axis.getExtent(); + var extentSum = axisExtent[0] + axisExtent[1]; + var isHorizontal = axis.isHorizontal(); + + axis.toGlobalCoord = isHorizontal + ? function (coord) { + return coord + coordBase; + } + : function (coord) { + return extentSum - coord + coordBase; + }; + + axis.toLocalCoord = isHorizontal + ? function (coord) { + return coord - coordBase; + } + : function (coord) { + return extentSum - coord + coordBase; + }; + }, + + /** + * Get axis. + * + * @return {module:echarts/coord/single/SingleAxis} + */ + getAxis: function () { + return this._axis; + }, + + /** + * Get axis, add it just for draw tooltip. + * + * @return {[type]} [description] + */ + getBaseAxis: function () { + return this._axis; + }, + + /** + * @return {Array.} + */ + getAxes: function () { + return [this._axis]; + }, + + /** + * @return {Object} {baseAxes: [], otherAxes: []} + */ + getTooltipAxes: function () { + return {baseAxes: [this.getAxis()]}; + }, + + /** + * If contain point. + * + * @param {Array.} point + * @return {boolean} + */ + containPoint: function (point) { + var rect = this.getRect(); + var axis = this.getAxis(); + var orient = axis.orient; + if (orient === 'horizontal') { + return axis.contain(axis.toLocalCoord(point[0])) + && (point[1] >= rect.y && point[1] <= (rect.y + rect.height)); + } + else { + return axis.contain(axis.toLocalCoord(point[1])) + && (point[0] >= rect.y && point[0] <= (rect.y + rect.height)); + } + }, + + /** + * @param {Array.} point + * @return {Array.} + */ + pointToData: function (point) { + var axis = this.getAxis(); + return [axis.coordToData(axis.toLocalCoord( + point[axis.orient === 'horizontal' ? 0 : 1] + ))]; + }, + + /** + * Convert the series data to concrete point. + * + * @param {number|Array.} val + * @return {Array.} + */ + dataToPoint: function (val) { + var axis = this.getAxis(); + var rect = this.getRect(); + var pt = []; + var idx = axis.orient === 'horizontal' ? 0 : 1; + + if (val instanceof Array) { + val = val[0]; + } + + pt[idx] = axis.toGlobalCoord(axis.dataToCoord(+val)); + pt[1 - idx] = idx === 0 ? (rect.y + rect.height / 2) : (rect.x + rect.width / 2); + return pt; + } + +}; + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/** + * Single coordinate system creator. + */ + +/** + * Create single coordinate system and inject it into seriesModel. + * + * @param {module:echarts/model/Global} ecModel + * @param {module:echarts/ExtensionAPI} api + * @return {Array.} + */ +function create$3(ecModel, api) { + var singles = []; + + ecModel.eachComponent('singleAxis', function (axisModel, idx) { + + var single = new Single(axisModel, ecModel, api); + single.name = 'single_' + idx; + single.resize(axisModel, api); + axisModel.coordinateSystem = single; + singles.push(single); + + }); + + ecModel.eachSeries(function (seriesModel) { + if (seriesModel.get('coordinateSystem') === 'singleAxis') { + var singleAxisModel = ecModel.queryComponents({ + mainType: 'singleAxis', + index: seriesModel.get('singleAxisIndex'), + id: seriesModel.get('singleAxisId') + })[0]; + seriesModel.coordinateSystem = singleAxisModel && singleAxisModel.coordinateSystem; + } + }); + + return singles; +} + +CoordinateSystemManager.register('single', { + create: create$3, + dimensions: Single.prototype.dimensions +}); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/** + * @param {Object} opt {labelInside} + * @return {Object} { + * position, rotation, labelDirection, labelOffset, + * tickDirection, labelRotate, z2 + * } + */ +function layout$2(axisModel, opt) { + opt = opt || {}; + var single = axisModel.coordinateSystem; + var axis = axisModel.axis; + var layout = {}; + + var axisPosition = axis.position; + var orient = axis.orient; + + var rect = single.getRect(); + var rectBound = [rect.x, rect.x + rect.width, rect.y, rect.y + rect.height]; + + var positionMap = { + horizontal: {top: rectBound[2], bottom: rectBound[3]}, + vertical: {left: rectBound[0], right: rectBound[1]} + }; + + layout.position = [ + orient === 'vertical' + ? positionMap.vertical[axisPosition] + : rectBound[0], + orient === 'horizontal' + ? positionMap.horizontal[axisPosition] + : rectBound[3] + ]; + + var r = {horizontal: 0, vertical: 1}; + layout.rotation = Math.PI / 2 * r[orient]; + + var directionMap = {top: -1, bottom: 1, right: 1, left: -1}; + + layout.labelDirection = layout.tickDirection + = layout.nameDirection + = directionMap[axisPosition]; + + if (axisModel.get('axisTick.inside')) { + layout.tickDirection = -layout.tickDirection; + } + + if (retrieve(opt.labelInside, axisModel.get('axisLabel.inside'))) { + layout.labelDirection = -layout.labelDirection; + } + + var labelRotation = opt.rotate; + labelRotation == null && (labelRotation = axisModel.get('axisLabel.rotate')); + layout.labelRotation = axisPosition === 'top' ? -labelRotation : labelRotation; + + layout.z2 = 1; + + return layout; +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + + +var axisBuilderAttrs$2 = [ + 'axisLine', 'axisTickLabel', 'axisName' +]; + +var selfBuilderAttr = 'splitLine'; + +var SingleAxisView = AxisView.extend({ + + type: 'singleAxis', + + axisPointerClass: 'SingleAxisPointer', + + render: function (axisModel, ecModel, api, payload) { + + var group = this.group; + + group.removeAll(); + + var layout = layout$2(axisModel); + + var axisBuilder = new AxisBuilder(axisModel, layout); + + each$1(axisBuilderAttrs$2, axisBuilder.add, axisBuilder); + + group.add(axisBuilder.getGroup()); + + if (axisModel.get(selfBuilderAttr + '.show')) { + this['_' + selfBuilderAttr](axisModel); + } + + SingleAxisView.superCall(this, 'render', axisModel, ecModel, api, payload); + }, + + _splitLine: function (axisModel) { + var axis = axisModel.axis; + + if (axis.scale.isBlank()) { + return; + } + + var splitLineModel = axisModel.getModel('splitLine'); + var lineStyleModel = splitLineModel.getModel('lineStyle'); + var lineWidth = lineStyleModel.get('width'); + var lineColors = lineStyleModel.get('color'); + + lineColors = lineColors instanceof Array ? lineColors : [lineColors]; + + var gridRect = axisModel.coordinateSystem.getRect(); + var isHorizontal = axis.isHorizontal(); + + var splitLines = []; + var lineCount = 0; + + var ticksCoords = axis.getTicksCoords({ + tickModel: splitLineModel + }); + + var p1 = []; + var p2 = []; + + for (var i = 0; i < ticksCoords.length; ++i) { + var tickCoord = axis.toGlobalCoord(ticksCoords[i].coord); + if (isHorizontal) { + p1[0] = tickCoord; + p1[1] = gridRect.y; + p2[0] = tickCoord; + p2[1] = gridRect.y + gridRect.height; + } + else { + p1[0] = gridRect.x; + p1[1] = tickCoord; + p2[0] = gridRect.x + gridRect.width; + p2[1] = tickCoord; + } + var colorIndex = (lineCount++) % lineColors.length; + splitLines[colorIndex] = splitLines[colorIndex] || []; + splitLines[colorIndex].push(new Line( + subPixelOptimizeLine({ + shape: { + x1: p1[0], + y1: p1[1], + x2: p2[0], + y2: p2[1] + }, + style: { + lineWidth: lineWidth + }, + silent: true + }))); + } + + for (var i = 0; i < splitLines.length; ++i) { + this.group.add(mergePath(splitLines[i], { + style: { + stroke: lineColors[i % lineColors.length], + lineDash: lineStyleModel.getLineDash(lineWidth), + lineWidth: lineWidth + }, + silent: true + })); + } + } +}); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var AxisModel$4 = ComponentModel.extend({ + + type: 'singleAxis', + + layoutMode: 'box', + + /** + * @type {module:echarts/coord/single/SingleAxis} + */ + axis: null, + + /** + * @type {module:echarts/coord/single/Single} + */ + coordinateSystem: null, + + /** + * @override + */ + getCoordSysModel: function () { + return this; + } + +}); + +var defaultOption$2 = { + + left: '5%', + top: '5%', + right: '5%', + bottom: '5%', + + type: 'value', + + position: 'bottom', + + orient: 'horizontal', + + axisLine: { + show: true, + lineStyle: { + width: 2, + type: 'solid' + } + }, + + // Single coordinate system and single axis is the, + // which is used as the parent tooltip model. + // same model, so we set default tooltip show as true. + tooltip: { + show: true + }, + + axisTick: { + show: true, + length: 6, + lineStyle: { + width: 2 + } + }, + + axisLabel: { + show: true, + interval: 'auto' + }, + + splitLine: { + show: true, + lineStyle: { + type: 'dashed', + opacity: 0.2 + } + } +}; + +function getAxisType$2(axisName, option) { + return option.type || (option.data ? 'category' : 'value'); +} + +merge(AxisModel$4.prototype, axisModelCommonMixin); + +axisModelCreator('single', AxisModel$4, getAxisType$2, defaultOption$2); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/** + * @param {Object} finder contains {seriesIndex, dataIndex, dataIndexInside} + * @param {module:echarts/model/Global} ecModel + * @return {Object} {point: [x, y], el: ...} point Will not be null. + */ +var findPointFromSeries = function (finder, ecModel) { + var point = []; + var seriesIndex = finder.seriesIndex; + var seriesModel; + if (seriesIndex == null || !( + seriesModel = ecModel.getSeriesByIndex(seriesIndex) + )) { + return {point: []}; + } + + var data = seriesModel.getData(); + var dataIndex = queryDataIndex(data, finder); + if (dataIndex == null || dataIndex < 0 || isArray(dataIndex)) { + return {point: []}; + } + + var el = data.getItemGraphicEl(dataIndex); + var coordSys = seriesModel.coordinateSystem; + + if (seriesModel.getTooltipPosition) { + point = seriesModel.getTooltipPosition(dataIndex) || []; + } + else if (coordSys && coordSys.dataToPoint) { + point = coordSys.dataToPoint( + data.getValues( + map(coordSys.dimensions, function (dim) { + return data.mapDimension(dim); + }), dataIndex, true + ) + ) || []; + } + else if (el) { + // Use graphic bounding rect + var rect = el.getBoundingRect().clone(); + rect.applyTransform(el.transform); + point = [ + rect.x + rect.width / 2, + rect.y + rect.height / 2 + ]; + } + + return {point: point, el: el}; +}; + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var each$14 = each$1; +var curry$3 = curry; +var inner$9 = makeInner(); + +/** + * Basic logic: check all axis, if they do not demand show/highlight, + * then hide/downplay them. + * + * @param {Object} coordSysAxesInfo + * @param {Object} payload + * @param {string} [payload.currTrigger] 'click' | 'mousemove' | 'leave' + * @param {Array.} [payload.x] x and y, which are mandatory, specify a point to + * trigger axisPointer and tooltip. + * @param {Array.} [payload.y] x and y, which are mandatory, specify a point to + * trigger axisPointer and tooltip. + * @param {Object} [payload.seriesIndex] finder, optional, restrict target axes. + * @param {Object} [payload.dataIndex] finder, restrict target axes. + * @param {Object} [payload.axesInfo] finder, restrict target axes. + * [{ + * axisDim: 'x'|'y'|'angle'|..., + * axisIndex: ..., + * value: ... + * }, ...] + * @param {Function} [payload.dispatchAction] + * @param {Object} [payload.tooltipOption] + * @param {Object|Array.|Function} [payload.position] Tooltip position, + * which can be specified in dispatchAction + * @param {module:echarts/model/Global} ecModel + * @param {module:echarts/ExtensionAPI} api + * @return {Object} content of event obj for echarts.connect. + */ +var axisTrigger = function (payload, ecModel, api) { + var currTrigger = payload.currTrigger; + var point = [payload.x, payload.y]; + var finder = payload; + var dispatchAction = payload.dispatchAction || bind(api.dispatchAction, api); + var coordSysAxesInfo = ecModel.getComponent('axisPointer').coordSysAxesInfo; + + // Pending + // See #6121. But we are not able to reproduce it yet. + if (!coordSysAxesInfo) { + return; + } + + if (illegalPoint(point)) { + // Used in the default behavior of `connection`: use the sample seriesIndex + // and dataIndex. And also used in the tooltipView trigger. + point = findPointFromSeries({ + seriesIndex: finder.seriesIndex, + // Do not use dataIndexInside from other ec instance. + // FIXME: auto detect it? + dataIndex: finder.dataIndex + }, ecModel).point; + } + var isIllegalPoint = illegalPoint(point); + + // Axis and value can be specified when calling dispatchAction({type: 'updateAxisPointer'}). + // Notice: In this case, it is difficult to get the `point` (which is necessary to show + // tooltip, so if point is not given, we just use the point found by sample seriesIndex + // and dataIndex. + var inputAxesInfo = finder.axesInfo; + + var axesInfo = coordSysAxesInfo.axesInfo; + var shouldHide = currTrigger === 'leave' || illegalPoint(point); + var outputFinder = {}; + + var showValueMap = {}; + var dataByCoordSys = {list: [], map: {}}; + var updaters = { + showPointer: curry$3(showPointer, showValueMap), + showTooltip: curry$3(showTooltip, dataByCoordSys) + }; + + // Process for triggered axes. + each$14(coordSysAxesInfo.coordSysMap, function (coordSys, coordSysKey) { + // If a point given, it must be contained by the coordinate system. + var coordSysContainsPoint = isIllegalPoint || coordSys.containPoint(point); + + each$14(coordSysAxesInfo.coordSysAxesInfo[coordSysKey], function (axisInfo, key) { + var axis = axisInfo.axis; + var inputAxisInfo = findInputAxisInfo(inputAxesInfo, axisInfo); + // If no inputAxesInfo, no axis is restricted. + if (!shouldHide && coordSysContainsPoint && (!inputAxesInfo || inputAxisInfo)) { + var val = inputAxisInfo && inputAxisInfo.value; + if (val == null && !isIllegalPoint) { + val = axis.pointToData(point); + } + val != null && processOnAxis(axisInfo, val, updaters, false, outputFinder); + } + }); + }); + + // Process for linked axes. + var linkTriggers = {}; + each$14(axesInfo, function (tarAxisInfo, tarKey) { + var linkGroup = tarAxisInfo.linkGroup; + + // If axis has been triggered in the previous stage, it should not be triggered by link. + if (linkGroup && !showValueMap[tarKey]) { + each$14(linkGroup.axesInfo, function (srcAxisInfo, srcKey) { + var srcValItem = showValueMap[srcKey]; + // If srcValItem exist, source axis is triggered, so link to target axis. + if (srcAxisInfo !== tarAxisInfo && srcValItem) { + var val = srcValItem.value; + linkGroup.mapper && (val = tarAxisInfo.axis.scale.parse(linkGroup.mapper( + val, makeMapperParam(srcAxisInfo), makeMapperParam(tarAxisInfo) + ))); + linkTriggers[tarAxisInfo.key] = val; + } + }); + } + }); + each$14(linkTriggers, function (val, tarKey) { + processOnAxis(axesInfo[tarKey], val, updaters, true, outputFinder); + }); + + updateModelActually(showValueMap, axesInfo, outputFinder); + dispatchTooltipActually(dataByCoordSys, point, payload, dispatchAction); + dispatchHighDownActually(axesInfo, dispatchAction, api); + + return outputFinder; +}; + +function processOnAxis(axisInfo, newValue, updaters, dontSnap, outputFinder) { + var axis = axisInfo.axis; + + if (axis.scale.isBlank() || !axis.containData(newValue)) { + return; + } + + if (!axisInfo.involveSeries) { + updaters.showPointer(axisInfo, newValue); + return; + } + + // Heavy calculation. So put it after axis.containData checking. + var payloadInfo = buildPayloadsBySeries(newValue, axisInfo); + var payloadBatch = payloadInfo.payloadBatch; + var snapToValue = payloadInfo.snapToValue; + + // Fill content of event obj for echarts.connect. + // By defualt use the first involved series data as a sample to connect. + if (payloadBatch[0] && outputFinder.seriesIndex == null) { + extend(outputFinder, payloadBatch[0]); + } + + // If no linkSource input, this process is for collecting link + // target, where snap should not be accepted. + if (!dontSnap && axisInfo.snap) { + if (axis.containData(snapToValue) && snapToValue != null) { + newValue = snapToValue; + } + } + + updaters.showPointer(axisInfo, newValue, payloadBatch, outputFinder); + // Tooltip should always be snapToValue, otherwise there will be + // incorrect "axis value ~ series value" mapping displayed in tooltip. + updaters.showTooltip(axisInfo, payloadInfo, snapToValue); +} + +function buildPayloadsBySeries(value, axisInfo) { + var axis = axisInfo.axis; + var dim = axis.dim; + var snapToValue = value; + var payloadBatch = []; + var minDist = Number.MAX_VALUE; + var minDiff = -1; + + each$14(axisInfo.seriesModels, function (series, idx) { + var dataDim = series.getData().mapDimension(dim, true); + var seriesNestestValue; + var dataIndices; + + if (series.getAxisTooltipData) { + var result = series.getAxisTooltipData(dataDim, value, axis); + dataIndices = result.dataIndices; + seriesNestestValue = result.nestestValue; + } + else { + dataIndices = series.getData().indicesOfNearest( + dataDim[0], + value, + // Add a threshold to avoid find the wrong dataIndex + // when data length is not same. + // false, + axis.type === 'category' ? 0.5 : null + ); + if (!dataIndices.length) { + return; + } + seriesNestestValue = series.getData().get(dataDim[0], dataIndices[0]); + } + + if (seriesNestestValue == null || !isFinite(seriesNestestValue)) { + return; + } + + var diff = value - seriesNestestValue; + var dist = Math.abs(diff); + // Consider category case + if (dist <= minDist) { + if (dist < minDist || (diff >= 0 && minDiff < 0)) { + minDist = dist; + minDiff = diff; + snapToValue = seriesNestestValue; + payloadBatch.length = 0; + } + each$14(dataIndices, function (dataIndex) { + payloadBatch.push({ + seriesIndex: series.seriesIndex, + dataIndexInside: dataIndex, + dataIndex: series.getData().getRawIndex(dataIndex) + }); + }); + } + }); + + return { + payloadBatch: payloadBatch, + snapToValue: snapToValue + }; +} + +function showPointer(showValueMap, axisInfo, value, payloadBatch) { + showValueMap[axisInfo.key] = {value: value, payloadBatch: payloadBatch}; +} + +function showTooltip(dataByCoordSys, axisInfo, payloadInfo, value) { + var payloadBatch = payloadInfo.payloadBatch; + var axis = axisInfo.axis; + var axisModel = axis.model; + var axisPointerModel = axisInfo.axisPointerModel; + + // If no data, do not create anything in dataByCoordSys, + // whose length will be used to judge whether dispatch action. + if (!axisInfo.triggerTooltip || !payloadBatch.length) { + return; + } + + var coordSysModel = axisInfo.coordSys.model; + var coordSysKey = makeKey(coordSysModel); + var coordSysItem = dataByCoordSys.map[coordSysKey]; + if (!coordSysItem) { + coordSysItem = dataByCoordSys.map[coordSysKey] = { + coordSysId: coordSysModel.id, + coordSysIndex: coordSysModel.componentIndex, + coordSysType: coordSysModel.type, + coordSysMainType: coordSysModel.mainType, + dataByAxis: [] + }; + dataByCoordSys.list.push(coordSysItem); + } + + coordSysItem.dataByAxis.push({ + axisDim: axis.dim, + axisIndex: axisModel.componentIndex, + axisType: axisModel.type, + axisId: axisModel.id, + value: value, + // Caustion: viewHelper.getValueLabel is actually on "view stage", which + // depends that all models have been updated. So it should not be performed + // here. Considering axisPointerModel used here is volatile, which is hard + // to be retrieve in TooltipView, we prepare parameters here. + valueLabelOpt: { + precision: axisPointerModel.get('label.precision'), + formatter: axisPointerModel.get('label.formatter') + }, + seriesDataIndices: payloadBatch.slice() + }); +} + +function updateModelActually(showValueMap, axesInfo, outputFinder) { + var outputAxesInfo = outputFinder.axesInfo = []; + // Basic logic: If no 'show' required, 'hide' this axisPointer. + each$14(axesInfo, function (axisInfo, key) { + var option = axisInfo.axisPointerModel.option; + var valItem = showValueMap[key]; + + if (valItem) { + !axisInfo.useHandle && (option.status = 'show'); + option.value = valItem.value; + // For label formatter param and highlight. + option.seriesDataIndices = (valItem.payloadBatch || []).slice(); + } + // When always show (e.g., handle used), remain + // original value and status. + else { + // If hide, value still need to be set, consider + // click legend to toggle axis blank. + !axisInfo.useHandle && (option.status = 'hide'); + } + + // If status is 'hide', should be no info in payload. + option.status === 'show' && outputAxesInfo.push({ + axisDim: axisInfo.axis.dim, + axisIndex: axisInfo.axis.model.componentIndex, + value: option.value + }); + }); +} + +function dispatchTooltipActually(dataByCoordSys, point, payload, dispatchAction) { + // Basic logic: If no showTip required, hideTip will be dispatched. + if (illegalPoint(point) || !dataByCoordSys.list.length) { + dispatchAction({type: 'hideTip'}); + return; + } + + // In most case only one axis (or event one series is used). It is + // convinient to fetch payload.seriesIndex and payload.dataIndex + // dirtectly. So put the first seriesIndex and dataIndex of the first + // axis on the payload. + var sampleItem = ((dataByCoordSys.list[0].dataByAxis[0] || {}).seriesDataIndices || [])[0] || {}; + + dispatchAction({ + type: 'showTip', + escapeConnect: true, + x: point[0], + y: point[1], + tooltipOption: payload.tooltipOption, + position: payload.position, + dataIndexInside: sampleItem.dataIndexInside, + dataIndex: sampleItem.dataIndex, + seriesIndex: sampleItem.seriesIndex, + dataByCoordSys: dataByCoordSys.list + }); +} + +function dispatchHighDownActually(axesInfo, dispatchAction, api) { + // FIXME + // highlight status modification shoule be a stage of main process? + // (Consider confilct (e.g., legend and axisPointer) and setOption) + + var zr = api.getZr(); + var highDownKey = 'axisPointerLastHighlights'; + var lastHighlights = inner$9(zr)[highDownKey] || {}; + var newHighlights = inner$9(zr)[highDownKey] = {}; + + // Update highlight/downplay status according to axisPointer model. + // Build hash map and remove duplicate incidentally. + each$14(axesInfo, function (axisInfo, key) { + var option = axisInfo.axisPointerModel.option; + option.status === 'show' && each$14(option.seriesDataIndices, function (batchItem) { + var key = batchItem.seriesIndex + ' | ' + batchItem.dataIndex; + newHighlights[key] = batchItem; + }); + }); + + // Diff. + var toHighlight = []; + var toDownplay = []; + each$1(lastHighlights, function (batchItem, key) { + !newHighlights[key] && toDownplay.push(batchItem); + }); + each$1(newHighlights, function (batchItem, key) { + !lastHighlights[key] && toHighlight.push(batchItem); + }); + + toDownplay.length && api.dispatchAction({ + type: 'downplay', escapeConnect: true, batch: toDownplay + }); + toHighlight.length && api.dispatchAction({ + type: 'highlight', escapeConnect: true, batch: toHighlight + }); +} + +function findInputAxisInfo(inputAxesInfo, axisInfo) { + for (var i = 0; i < (inputAxesInfo || []).length; i++) { + var inputAxisInfo = inputAxesInfo[i]; + if (axisInfo.axis.dim === inputAxisInfo.axisDim + && axisInfo.axis.model.componentIndex === inputAxisInfo.axisIndex + ) { + return inputAxisInfo; + } + } +} + +function makeMapperParam(axisInfo) { + var axisModel = axisInfo.axis.model; + var item = {}; + var dim = item.axisDim = axisInfo.axis.dim; + item.axisIndex = item[dim + 'AxisIndex'] = axisModel.componentIndex; + item.axisName = item[dim + 'AxisName'] = axisModel.name; + item.axisId = item[dim + 'AxisId'] = axisModel.id; + return item; +} + +function illegalPoint(point) { + return !point || point[0] == null || isNaN(point[0]) || point[1] == null || isNaN(point[1]); +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var AxisPointerModel = extendComponentModel({ + + type: 'axisPointer', + + coordSysAxesInfo: null, + + defaultOption: { + // 'auto' means that show when triggered by tooltip or handle. + show: 'auto', + // 'click' | 'mousemove' | 'none' + triggerOn: null, // set default in AxisPonterView.js + + zlevel: 0, + z: 50, + + type: 'line', // 'line' 'shadow' 'cross' 'none'. + // axispointer triggered by tootip determine snap automatically, + // see `modelHelper`. + snap: false, + triggerTooltip: true, + + value: null, + status: null, // Init value depends on whether handle is used. + + // [group0, group1, ...] + // Each group can be: { + // mapper: function () {}, + // singleTooltip: 'multiple', // 'multiple' or 'single' + // xAxisId: ..., + // yAxisName: ..., + // angleAxisIndex: ... + // } + // mapper: can be ignored. + // input: {axisInfo, value} + // output: {axisInfo, value} + link: [], + + // Do not set 'auto' here, otherwise global animation: false + // will not effect at this axispointer. + animation: null, + animationDurationUpdate: 200, + + lineStyle: { + color: '#aaa', + width: 1, + type: 'solid' + }, + + shadowStyle: { + color: 'rgba(150,150,150,0.3)' + }, + + label: { + show: true, + formatter: null, // string | Function + precision: 'auto', // Or a number like 0, 1, 2 ... + margin: 3, + color: '#fff', + padding: [5, 7, 5, 7], + backgroundColor: 'auto', // default: axis line color + borderColor: null, + borderWidth: 0, + shadowBlur: 3, + shadowColor: '#aaa' + // Considering applicability, common style should + // better not have shadowOffset. + // shadowOffsetX: 0, + // shadowOffsetY: 2 + }, + + handle: { + show: false, + /* eslint-disable */ + icon: 'M10.7,11.9v-1.3H9.3v1.3c-4.9,0.3-8.8,4.4-8.8,9.4c0,5,3.9,9.1,8.8,9.4h1.3c4.9-0.3,8.8-4.4,8.8-9.4C19.5,16.3,15.6,12.2,10.7,11.9z M13.3,24.4H6.7v-1.2h6.6z M13.3,22H6.7v-1.2h6.6z M13.3,19.6H6.7v-1.2h6.6z', // jshint ignore:line + /* eslint-enable */ + size: 45, + // handle margin is from symbol center to axis, which is stable when circular move. + margin: 50, + // color: '#1b8bbd' + // color: '#2f4554' + color: '#333', + shadowBlur: 3, + shadowColor: '#aaa', + shadowOffsetX: 0, + shadowOffsetY: 2, + + // For mobile performance + throttle: 40 + } + } + +}); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var inner$10 = makeInner(); +var each$15 = each$1; + +/** + * @param {string} key + * @param {module:echarts/ExtensionAPI} api + * @param {Function} handler + * param: {string} currTrigger + * param: {Array.} point + */ +function register(key, api, handler) { + if (env$1.node) { + return; + } + + var zr = api.getZr(); + inner$10(zr).records || (inner$10(zr).records = {}); + + initGlobalListeners(zr, api); + + var record = inner$10(zr).records[key] || (inner$10(zr).records[key] = {}); + record.handler = handler; +} + +function initGlobalListeners(zr, api) { + if (inner$10(zr).initialized) { + return; + } + + inner$10(zr).initialized = true; + + useHandler('click', curry(doEnter, 'click')); + useHandler('mousemove', curry(doEnter, 'mousemove')); + // useHandler('mouseout', onLeave); + useHandler('globalout', onLeave); + + function useHandler(eventType, cb) { + zr.on(eventType, function (e) { + var dis = makeDispatchAction(api); + + each$15(inner$10(zr).records, function (record) { + record && cb(record, e, dis.dispatchAction); + }); + + dispatchTooltipFinally(dis.pendings, api); + }); + } +} + +function dispatchTooltipFinally(pendings, api) { + var showLen = pendings.showTip.length; + var hideLen = pendings.hideTip.length; + + var actuallyPayload; + if (showLen) { + actuallyPayload = pendings.showTip[showLen - 1]; + } + else if (hideLen) { + actuallyPayload = pendings.hideTip[hideLen - 1]; + } + if (actuallyPayload) { + actuallyPayload.dispatchAction = null; + api.dispatchAction(actuallyPayload); + } +} + +function onLeave(record, e, dispatchAction) { + record.handler('leave', null, dispatchAction); +} + +function doEnter(currTrigger, record, e, dispatchAction) { + record.handler(currTrigger, e, dispatchAction); +} + +function makeDispatchAction(api) { + var pendings = { + showTip: [], + hideTip: [] + }; + // FIXME + // better approach? + // 'showTip' and 'hideTip' can be triggered by axisPointer and tooltip, + // which may be conflict, (axisPointer call showTip but tooltip call hideTip); + // So we have to add "final stage" to merge those dispatched actions. + var dispatchAction = function (payload) { + var pendingList = pendings[payload.type]; + if (pendingList) { + pendingList.push(payload); + } + else { + payload.dispatchAction = dispatchAction; + api.dispatchAction(payload); + } + }; + + return { + dispatchAction: dispatchAction, + pendings: pendings + }; +} + +/** + * @param {string} key + * @param {module:echarts/ExtensionAPI} api + */ +function unregister(key, api) { + if (env$1.node) { + return; + } + var zr = api.getZr(); + var record = (inner$10(zr).records || {})[key]; + if (record) { + inner$10(zr).records[key] = null; + } +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var AxisPointerView = extendComponentView({ + + type: 'axisPointer', + + render: function (globalAxisPointerModel, ecModel, api) { + var globalTooltipModel = ecModel.getComponent('tooltip'); + var triggerOn = globalAxisPointerModel.get('triggerOn') + || (globalTooltipModel && globalTooltipModel.get('triggerOn') || 'mousemove|click'); + + // Register global listener in AxisPointerView to enable + // AxisPointerView to be independent to Tooltip. + register( + 'axisPointer', + api, + function (currTrigger, e, dispatchAction) { + // If 'none', it is not controlled by mouse totally. + if (triggerOn !== 'none' + && (currTrigger === 'leave' || triggerOn.indexOf(currTrigger) >= 0) + ) { + dispatchAction({ + type: 'updateAxisPointer', + currTrigger: currTrigger, + x: e && e.offsetX, + y: e && e.offsetY + }); + } + } + ); + }, + + /** + * @override + */ + remove: function (ecModel, api) { + unregister(api.getZr(), 'axisPointer'); + AxisPointerView.superApply(this._model, 'remove', arguments); + }, + + /** + * @override + */ + dispose: function (ecModel, api) { + unregister('axisPointer', api); + AxisPointerView.superApply(this._model, 'dispose', arguments); + } + +}); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var inner$11 = makeInner(); +var clone$4 = clone; +var bind$2 = bind; + +/** + * Base axis pointer class in 2D. + * Implemenents {module:echarts/component/axis/IAxisPointer}. + */ +function BaseAxisPointer() { +} + +BaseAxisPointer.prototype = { + + /** + * @private + */ + _group: null, + + /** + * @private + */ + _lastGraphicKey: null, + + /** + * @private + */ + _handle: null, + + /** + * @private + */ + _dragging: false, + + /** + * @private + */ + _lastValue: null, + + /** + * @private + */ + _lastStatus: null, + + /** + * @private + */ + _payloadInfo: null, + + /** + * In px, arbitrary value. Do not set too small, + * no animation is ok for most cases. + * @protected + */ + animationThreshold: 15, + + /** + * @implement + */ + render: function (axisModel, axisPointerModel, api, forceRender) { + var value = axisPointerModel.get('value'); + var status = axisPointerModel.get('status'); + + // Bind them to `this`, not in closure, otherwise they will not + // be replaced when user calling setOption in not merge mode. + this._axisModel = axisModel; + this._axisPointerModel = axisPointerModel; + this._api = api; + + // Optimize: `render` will be called repeatly during mouse move. + // So it is power consuming if performing `render` each time, + // especially on mobile device. + if (!forceRender + && this._lastValue === value + && this._lastStatus === status + ) { + return; + } + this._lastValue = value; + this._lastStatus = status; + + var group = this._group; + var handle = this._handle; + + if (!status || status === 'hide') { + // Do not clear here, for animation better. + group && group.hide(); + handle && handle.hide(); + return; + } + group && group.show(); + handle && handle.show(); + + // Otherwise status is 'show' + var elOption = {}; + this.makeElOption(elOption, value, axisModel, axisPointerModel, api); + + // Enable change axis pointer type. + var graphicKey = elOption.graphicKey; + if (graphicKey !== this._lastGraphicKey) { + this.clear(api); + } + this._lastGraphicKey = graphicKey; + + var moveAnimation = this._moveAnimation + = this.determineAnimation(axisModel, axisPointerModel); + + if (!group) { + group = this._group = new Group(); + this.createPointerEl(group, elOption, axisModel, axisPointerModel); + this.createLabelEl(group, elOption, axisModel, axisPointerModel); + api.getZr().add(group); + } + else { + var doUpdateProps = curry(updateProps$1, axisPointerModel, moveAnimation); + this.updatePointerEl(group, elOption, doUpdateProps, axisPointerModel); + this.updateLabelEl(group, elOption, doUpdateProps, axisPointerModel); + } + + updateMandatoryProps(group, axisPointerModel, true); + + this._renderHandle(value); + }, + + /** + * @implement + */ + remove: function (api) { + this.clear(api); + }, + + /** + * @implement + */ + dispose: function (api) { + this.clear(api); + }, + + /** + * @protected + */ + determineAnimation: function (axisModel, axisPointerModel) { + var animation = axisPointerModel.get('animation'); + var axis = axisModel.axis; + var isCategoryAxis = axis.type === 'category'; + var useSnap = axisPointerModel.get('snap'); + + // Value axis without snap always do not snap. + if (!useSnap && !isCategoryAxis) { + return false; + } + + if (animation === 'auto' || animation == null) { + var animationThreshold = this.animationThreshold; + if (isCategoryAxis && axis.getBandWidth() > animationThreshold) { + return true; + } + + // It is important to auto animation when snap used. Consider if there is + // a dataZoom, animation will be disabled when too many points exist, while + // it will be enabled for better visual effect when little points exist. + if (useSnap) { + var seriesDataCount = getAxisInfo(axisModel).seriesDataCount; + var axisExtent = axis.getExtent(); + // Approximate band width + return Math.abs(axisExtent[0] - axisExtent[1]) / seriesDataCount > animationThreshold; + } + + return false; + } + + return animation === true; + }, + + /** + * add {pointer, label, graphicKey} to elOption + * @protected + */ + makeElOption: function (elOption, value, axisModel, axisPointerModel, api) { + // Shoule be implemenented by sub-class. + }, + + /** + * @protected + */ + createPointerEl: function (group, elOption, axisModel, axisPointerModel) { + var pointerOption = elOption.pointer; + if (pointerOption) { + var pointerEl = inner$11(group).pointerEl = new graphic[pointerOption.type]( + clone$4(elOption.pointer) + ); + group.add(pointerEl); + } + }, + + /** + * @protected + */ + createLabelEl: function (group, elOption, axisModel, axisPointerModel) { + if (elOption.label) { + var labelEl = inner$11(group).labelEl = new Rect( + clone$4(elOption.label) + ); + + group.add(labelEl); + updateLabelShowHide(labelEl, axisPointerModel); + } + }, + + /** + * @protected + */ + updatePointerEl: function (group, elOption, updateProps$$1) { + var pointerEl = inner$11(group).pointerEl; + if (pointerEl) { + pointerEl.setStyle(elOption.pointer.style); + updateProps$$1(pointerEl, {shape: elOption.pointer.shape}); + } + }, + + /** + * @protected + */ + updateLabelEl: function (group, elOption, updateProps$$1, axisPointerModel) { + var labelEl = inner$11(group).labelEl; + if (labelEl) { + labelEl.setStyle(elOption.label.style); + updateProps$$1(labelEl, { + // Consider text length change in vertical axis, animation should + // be used on shape, otherwise the effect will be weird. + shape: elOption.label.shape, + position: elOption.label.position + }); + + updateLabelShowHide(labelEl, axisPointerModel); + } + }, + + /** + * @private + */ + _renderHandle: function (value) { + if (this._dragging || !this.updateHandleTransform) { + return; + } + + var axisPointerModel = this._axisPointerModel; + var zr = this._api.getZr(); + var handle = this._handle; + var handleModel = axisPointerModel.getModel('handle'); + + var status = axisPointerModel.get('status'); + if (!handleModel.get('show') || !status || status === 'hide') { + handle && zr.remove(handle); + this._handle = null; + return; + } + + var isInit; + if (!this._handle) { + isInit = true; + handle = this._handle = createIcon( + handleModel.get('icon'), + { + cursor: 'move', + draggable: true, + onmousemove: function (e) { + // Fot mobile devicem, prevent screen slider on the button. + stop(e.event); + }, + onmousedown: bind$2(this._onHandleDragMove, this, 0, 0), + drift: bind$2(this._onHandleDragMove, this), + ondragend: bind$2(this._onHandleDragEnd, this) + } + ); + zr.add(handle); + } + + updateMandatoryProps(handle, axisPointerModel, false); + + // update style + var includeStyles = [ + 'color', 'borderColor', 'borderWidth', 'opacity', + 'shadowColor', 'shadowBlur', 'shadowOffsetX', 'shadowOffsetY' + ]; + handle.setStyle(handleModel.getItemStyle(null, includeStyles)); + + // update position + var handleSize = handleModel.get('size'); + if (!isArray(handleSize)) { + handleSize = [handleSize, handleSize]; + } + handle.attr('scale', [handleSize[0] / 2, handleSize[1] / 2]); + + createOrUpdate( + this, + '_doDispatchAxisPointer', + handleModel.get('throttle') || 0, + 'fixRate' + ); + + this._moveHandleToValue(value, isInit); + }, + + /** + * @private + */ + _moveHandleToValue: function (value, isInit) { + updateProps$1( + this._axisPointerModel, + !isInit && this._moveAnimation, + this._handle, + getHandleTransProps(this.getHandleTransform( + value, this._axisModel, this._axisPointerModel + )) + ); + }, + + /** + * @private + */ + _onHandleDragMove: function (dx, dy) { + var handle = this._handle; + if (!handle) { + return; + } + + this._dragging = true; + + // Persistent for throttle. + var trans = this.updateHandleTransform( + getHandleTransProps(handle), + [dx, dy], + this._axisModel, + this._axisPointerModel + ); + this._payloadInfo = trans; + + handle.stopAnimation(); + handle.attr(getHandleTransProps(trans)); + inner$11(handle).lastProp = null; + + this._doDispatchAxisPointer(); + }, + + /** + * Throttled method. + * @private + */ + _doDispatchAxisPointer: function () { + var handle = this._handle; + if (!handle) { + return; + } + + var payloadInfo = this._payloadInfo; + var axisModel = this._axisModel; + this._api.dispatchAction({ + type: 'updateAxisPointer', + x: payloadInfo.cursorPoint[0], + y: payloadInfo.cursorPoint[1], + tooltipOption: payloadInfo.tooltipOption, + axesInfo: [{ + axisDim: axisModel.axis.dim, + axisIndex: axisModel.componentIndex + }] + }); + }, + + /** + * @private + */ + _onHandleDragEnd: function (moveAnimation) { + this._dragging = false; + var handle = this._handle; + if (!handle) { + return; + } + + var value = this._axisPointerModel.get('value'); + // Consider snap or categroy axis, handle may be not consistent with + // axisPointer. So move handle to align the exact value position when + // drag ended. + this._moveHandleToValue(value); + + // For the effect: tooltip will be shown when finger holding on handle + // button, and will be hidden after finger left handle button. + this._api.dispatchAction({ + type: 'hideTip' + }); + }, + + /** + * Should be implemenented by sub-class if support `handle`. + * @protected + * @param {number} value + * @param {module:echarts/model/Model} axisModel + * @param {module:echarts/model/Model} axisPointerModel + * @return {Object} {position: [x, y], rotation: 0} + */ + getHandleTransform: null, + + /** + * * Should be implemenented by sub-class if support `handle`. + * @protected + * @param {Object} transform {position, rotation} + * @param {Array.} delta [dx, dy] + * @param {module:echarts/model/Model} axisModel + * @param {module:echarts/model/Model} axisPointerModel + * @return {Object} {position: [x, y], rotation: 0, cursorPoint: [x, y]} + */ + updateHandleTransform: null, + + /** + * @private + */ + clear: function (api) { + this._lastValue = null; + this._lastStatus = null; + + var zr = api.getZr(); + var group = this._group; + var handle = this._handle; + if (zr && group) { + this._lastGraphicKey = null; + group && zr.remove(group); + handle && zr.remove(handle); + this._group = null; + this._handle = null; + this._payloadInfo = null; + } + }, + + /** + * @protected + */ + doClear: function () { + // Implemented by sub-class if necessary. + }, + + /** + * @protected + * @param {Array.} xy + * @param {Array.} wh + * @param {number} [xDimIndex=0] or 1 + */ + buildLabel: function (xy, wh, xDimIndex) { + xDimIndex = xDimIndex || 0; + return { + x: xy[xDimIndex], + y: xy[1 - xDimIndex], + width: wh[xDimIndex], + height: wh[1 - xDimIndex] + }; + } +}; + +BaseAxisPointer.prototype.constructor = BaseAxisPointer; + + +function updateProps$1(animationModel, moveAnimation, el, props) { + // Animation optimize. + if (!propsEqual(inner$11(el).lastProp, props)) { + inner$11(el).lastProp = props; + moveAnimation + ? updateProps(el, props, animationModel) + : (el.stopAnimation(), el.attr(props)); + } +} + +function propsEqual(lastProps, newProps) { + if (isObject$1(lastProps) && isObject$1(newProps)) { + var equals = true; + each$1(newProps, function (item, key) { + equals = equals && propsEqual(lastProps[key], item); + }); + return !!equals; + } + else { + return lastProps === newProps; + } +} + +function updateLabelShowHide(labelEl, axisPointerModel) { + labelEl[axisPointerModel.get('label.show') ? 'show' : 'hide'](); +} + +function getHandleTransProps(trans) { + return { + position: trans.position.slice(), + rotation: trans.rotation || 0 + }; +} + +function updateMandatoryProps(group, axisPointerModel, silent) { + var z = axisPointerModel.get('z'); + var zlevel = axisPointerModel.get('zlevel'); + + group && group.traverse(function (el) { + if (el.type !== 'group') { + z != null && (el.z = z); + zlevel != null && (el.zlevel = zlevel); + el.silent = silent; + } + }); +} + +enableClassExtend(BaseAxisPointer); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/** + * @param {module:echarts/model/Model} axisPointerModel + */ +function buildElStyle(axisPointerModel) { + var axisPointerType = axisPointerModel.get('type'); + var styleModel = axisPointerModel.getModel(axisPointerType + 'Style'); + var style; + if (axisPointerType === 'line') { + style = styleModel.getLineStyle(); + style.fill = null; + } + else if (axisPointerType === 'shadow') { + style = styleModel.getAreaStyle(); + style.stroke = null; + } + return style; +} + +/** + * @param {Function} labelPos {align, verticalAlign, position} + */ +function buildLabelElOption( + elOption, axisModel, axisPointerModel, api, labelPos +) { + var value = axisPointerModel.get('value'); + var text = getValueLabel( + value, axisModel.axis, axisModel.ecModel, + axisPointerModel.get('seriesDataIndices'), + { + precision: axisPointerModel.get('label.precision'), + formatter: axisPointerModel.get('label.formatter') + } + ); + var labelModel = axisPointerModel.getModel('label'); + var paddings = normalizeCssArray$1(labelModel.get('padding') || 0); + + var font = labelModel.getFont(); + var textRect = getBoundingRect(text, font); + + var position = labelPos.position; + var width = textRect.width + paddings[1] + paddings[3]; + var height = textRect.height + paddings[0] + paddings[2]; + + // Adjust by align. + var align = labelPos.align; + align === 'right' && (position[0] -= width); + align === 'center' && (position[0] -= width / 2); + var verticalAlign = labelPos.verticalAlign; + verticalAlign === 'bottom' && (position[1] -= height); + verticalAlign === 'middle' && (position[1] -= height / 2); + + // Not overflow ec container + confineInContainer(position, width, height, api); + + var bgColor = labelModel.get('backgroundColor'); + if (!bgColor || bgColor === 'auto') { + bgColor = axisModel.get('axisLine.lineStyle.color'); + } + + elOption.label = { + shape: {x: 0, y: 0, width: width, height: height, r: labelModel.get('borderRadius')}, + position: position.slice(), + // TODO: rich + style: { + text: text, + textFont: font, + textFill: labelModel.getTextColor(), + textPosition: 'inside', + fill: bgColor, + stroke: labelModel.get('borderColor') || 'transparent', + lineWidth: labelModel.get('borderWidth') || 0, + shadowBlur: labelModel.get('shadowBlur'), + shadowColor: labelModel.get('shadowColor'), + shadowOffsetX: labelModel.get('shadowOffsetX'), + shadowOffsetY: labelModel.get('shadowOffsetY') + }, + // Lable should be over axisPointer. + z2: 10 + }; +} + +// Do not overflow ec container +function confineInContainer(position, width, height, api) { + var viewWidth = api.getWidth(); + var viewHeight = api.getHeight(); + position[0] = Math.min(position[0] + width, viewWidth) - width; + position[1] = Math.min(position[1] + height, viewHeight) - height; + position[0] = Math.max(position[0], 0); + position[1] = Math.max(position[1], 0); +} + +/** + * @param {number} value + * @param {module:echarts/coord/Axis} axis + * @param {module:echarts/model/Global} ecModel + * @param {Object} opt + * @param {Array.} seriesDataIndices + * @param {number|string} opt.precision 'auto' or a number + * @param {string|Function} opt.formatter label formatter + */ +function getValueLabel(value, axis, ecModel, seriesDataIndices, opt) { + value = axis.scale.parse(value); + var text = axis.scale.getLabel( + // If `precision` is set, width can be fixed (like '12.00500'), which + // helps to debounce when when moving label. + value, {precision: opt.precision} + ); + var formatter = opt.formatter; + + if (formatter) { + var params = { + value: getAxisRawValue(axis, value), + seriesData: [] + }; + each$1(seriesDataIndices, function (idxItem) { + var series = ecModel.getSeriesByIndex(idxItem.seriesIndex); + var dataIndex = idxItem.dataIndexInside; + var dataParams = series && series.getDataParams(dataIndex); + dataParams && params.seriesData.push(dataParams); + }); + + if (isString(formatter)) { + text = formatter.replace('{value}', text); + } + else if (isFunction$1(formatter)) { + text = formatter(params); + } + } + + return text; +} + +/** + * @param {module:echarts/coord/Axis} axis + * @param {number} value + * @param {Object} layoutInfo { + * rotation, position, labelOffset, labelDirection, labelMargin + * } + */ +function getTransformedPosition(axis, value, layoutInfo) { + var transform = create$1(); + rotate(transform, transform, layoutInfo.rotation); + translate(transform, transform, layoutInfo.position); + + return applyTransform$1([ + axis.dataToCoord(value), + (layoutInfo.labelOffset || 0) + + (layoutInfo.labelDirection || 1) * (layoutInfo.labelMargin || 0) + ], transform); +} + +function buildCartesianSingleLabelElOption( + value, elOption, layoutInfo, axisModel, axisPointerModel, api +) { + var textLayout = AxisBuilder.innerTextLayout( + layoutInfo.rotation, 0, layoutInfo.labelDirection + ); + layoutInfo.labelMargin = axisPointerModel.get('label.margin'); + buildLabelElOption(elOption, axisModel, axisPointerModel, api, { + position: getTransformedPosition(axisModel.axis, value, layoutInfo), + align: textLayout.textAlign, + verticalAlign: textLayout.textVerticalAlign + }); +} + +/** + * @param {Array.} p1 + * @param {Array.} p2 + * @param {number} [xDimIndex=0] or 1 + */ +function makeLineShape(p1, p2, xDimIndex) { + xDimIndex = xDimIndex || 0; + return { + x1: p1[xDimIndex], + y1: p1[1 - xDimIndex], + x2: p2[xDimIndex], + y2: p2[1 - xDimIndex] + }; +} + +/** + * @param {Array.} xy + * @param {Array.} wh + * @param {number} [xDimIndex=0] or 1 + */ +function makeRectShape(xy, wh, xDimIndex) { + xDimIndex = xDimIndex || 0; + return { + x: xy[xDimIndex], + y: xy[1 - xDimIndex], + width: wh[xDimIndex], + height: wh[1 - xDimIndex] + }; +} + +function makeSectorShape(cx, cy, r0, r, startAngle, endAngle) { + return { + cx: cx, + cy: cy, + r0: r0, + r: r, + startAngle: startAngle, + endAngle: endAngle, + clockwise: true + }; +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var CartesianAxisPointer = BaseAxisPointer.extend({ + + /** + * @override + */ + makeElOption: function (elOption, value, axisModel, axisPointerModel, api) { + var axis = axisModel.axis; + var grid = axis.grid; + var axisPointerType = axisPointerModel.get('type'); + var otherExtent = getCartesian(grid, axis).getOtherAxis(axis).getGlobalExtent(); + var pixelValue = axis.toGlobalCoord(axis.dataToCoord(value, true)); + + if (axisPointerType && axisPointerType !== 'none') { + var elStyle = buildElStyle(axisPointerModel); + var pointerOption = pointerShapeBuilder[axisPointerType]( + axis, pixelValue, otherExtent, elStyle + ); + pointerOption.style = elStyle; + elOption.graphicKey = pointerOption.type; + elOption.pointer = pointerOption; + } + + var layoutInfo = layout$1(grid.model, axisModel); + buildCartesianSingleLabelElOption( + value, elOption, layoutInfo, axisModel, axisPointerModel, api + ); + }, + + /** + * @override + */ + getHandleTransform: function (value, axisModel, axisPointerModel) { + var layoutInfo = layout$1(axisModel.axis.grid.model, axisModel, { + labelInside: false + }); + layoutInfo.labelMargin = axisPointerModel.get('handle.margin'); + return { + position: getTransformedPosition(axisModel.axis, value, layoutInfo), + rotation: layoutInfo.rotation + (layoutInfo.labelDirection < 0 ? Math.PI : 0) + }; + }, + + /** + * @override + */ + updateHandleTransform: function (transform, delta, axisModel, axisPointerModel) { + var axis = axisModel.axis; + var grid = axis.grid; + var axisExtent = axis.getGlobalExtent(true); + var otherExtent = getCartesian(grid, axis).getOtherAxis(axis).getGlobalExtent(); + var dimIndex = axis.dim === 'x' ? 0 : 1; + + var currPosition = transform.position; + currPosition[dimIndex] += delta[dimIndex]; + currPosition[dimIndex] = Math.min(axisExtent[1], currPosition[dimIndex]); + currPosition[dimIndex] = Math.max(axisExtent[0], currPosition[dimIndex]); + + var cursorOtherValue = (otherExtent[1] + otherExtent[0]) / 2; + var cursorPoint = [cursorOtherValue, cursorOtherValue]; + cursorPoint[dimIndex] = currPosition[dimIndex]; + + // Make tooltip do not overlap axisPointer and in the middle of the grid. + var tooltipOptions = [{verticalAlign: 'middle'}, {align: 'center'}]; + + return { + position: currPosition, + rotation: transform.rotation, + cursorPoint: cursorPoint, + tooltipOption: tooltipOptions[dimIndex] + }; + } + +}); + +function getCartesian(grid, axis) { + var opt = {}; + opt[axis.dim + 'AxisIndex'] = axis.index; + return grid.getCartesian(opt); +} + +var pointerShapeBuilder = { + + line: function (axis, pixelValue, otherExtent, elStyle) { + var targetShape = makeLineShape( + [pixelValue, otherExtent[0]], + [pixelValue, otherExtent[1]], + getAxisDimIndex(axis) + ); + subPixelOptimizeLine({ + shape: targetShape, + style: elStyle + }); + return { + type: 'Line', + shape: targetShape + }; + }, + + shadow: function (axis, pixelValue, otherExtent, elStyle) { + var bandWidth = Math.max(1, axis.getBandWidth()); + var span = otherExtent[1] - otherExtent[0]; + return { + type: 'Rect', + shape: makeRectShape( + [pixelValue - bandWidth / 2, otherExtent[0]], + [bandWidth, span], + getAxisDimIndex(axis) + ) + }; + } +}; + +function getAxisDimIndex(axis) { + return axis.dim === 'x' ? 0 : 1; +} + +AxisView.registerAxisPointerClass('CartesianAxisPointer', CartesianAxisPointer); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +// CartesianAxisPointer is not supposed to be required here. But consider +// echarts.simple.js and online build tooltip, which only require gridSimple, +// CartesianAxisPointer should be able to required somewhere. +registerPreprocessor(function (option) { + // Always has a global axisPointerModel for default setting. + if (option) { + (!option.axisPointer || option.axisPointer.length === 0) + && (option.axisPointer = {}); + + var link = option.axisPointer.link; + // Normalize to array to avoid object mergin. But if link + // is not set, remain null/undefined, otherwise it will + // override existent link setting. + if (link && !isArray(link)) { + option.axisPointer.link = [link]; + } + } +}); + +// This process should proformed after coordinate systems created +// and series data processed. So put it on statistic processing stage. +registerProcessor(PRIORITY.PROCESSOR.STATISTIC, function (ecModel, api) { + // Build axisPointerModel, mergin tooltip.axisPointer model for each axis. + // allAxesInfo should be updated when setOption performed. + ecModel.getComponent('axisPointer').coordSysAxesInfo + = collect(ecModel, api); +}); + +// Broadcast to all views. +registerAction({ + type: 'updateAxisPointer', + event: 'updateAxisPointer', + update: ':updateAxisPointer' +}, axisTrigger); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var XY = ['x', 'y']; +var WH = ['width', 'height']; + +var SingleAxisPointer = BaseAxisPointer.extend({ + + /** + * @override + */ + makeElOption: function (elOption, value, axisModel, axisPointerModel, api) { + var axis = axisModel.axis; + var coordSys = axis.coordinateSystem; + var otherExtent = getGlobalExtent(coordSys, 1 - getPointDimIndex(axis)); + var pixelValue = coordSys.dataToPoint(value)[0]; + + var axisPointerType = axisPointerModel.get('type'); + if (axisPointerType && axisPointerType !== 'none') { + var elStyle = buildElStyle(axisPointerModel); + var pointerOption = pointerShapeBuilder$1[axisPointerType]( + axis, pixelValue, otherExtent, elStyle + ); + pointerOption.style = elStyle; + + elOption.graphicKey = pointerOption.type; + elOption.pointer = pointerOption; + } + + var layoutInfo = layout$2(axisModel); + buildCartesianSingleLabelElOption( + value, elOption, layoutInfo, axisModel, axisPointerModel, api + ); + }, + + /** + * @override + */ + getHandleTransform: function (value, axisModel, axisPointerModel) { + var layoutInfo = layout$2(axisModel, {labelInside: false}); + layoutInfo.labelMargin = axisPointerModel.get('handle.margin'); + return { + position: getTransformedPosition(axisModel.axis, value, layoutInfo), + rotation: layoutInfo.rotation + (layoutInfo.labelDirection < 0 ? Math.PI : 0) + }; + }, + + /** + * @override + */ + updateHandleTransform: function (transform, delta, axisModel, axisPointerModel) { + var axis = axisModel.axis; + var coordSys = axis.coordinateSystem; + var dimIndex = getPointDimIndex(axis); + var axisExtent = getGlobalExtent(coordSys, dimIndex); + var currPosition = transform.position; + currPosition[dimIndex] += delta[dimIndex]; + currPosition[dimIndex] = Math.min(axisExtent[1], currPosition[dimIndex]); + currPosition[dimIndex] = Math.max(axisExtent[0], currPosition[dimIndex]); + var otherExtent = getGlobalExtent(coordSys, 1 - dimIndex); + var cursorOtherValue = (otherExtent[1] + otherExtent[0]) / 2; + var cursorPoint = [cursorOtherValue, cursorOtherValue]; + cursorPoint[dimIndex] = currPosition[dimIndex]; + + return { + position: currPosition, + rotation: transform.rotation, + cursorPoint: cursorPoint, + tooltipOption: { + verticalAlign: 'middle' + } + }; + } +}); + +var pointerShapeBuilder$1 = { + + line: function (axis, pixelValue, otherExtent, elStyle) { + var targetShape = makeLineShape( + [pixelValue, otherExtent[0]], + [pixelValue, otherExtent[1]], + getPointDimIndex(axis) + ); + subPixelOptimizeLine({ + shape: targetShape, + style: elStyle + }); + return { + type: 'Line', + shape: targetShape + }; + }, + + shadow: function (axis, pixelValue, otherExtent, elStyle) { + var bandWidth = axis.getBandWidth(); + var span = otherExtent[1] - otherExtent[0]; + return { + type: 'Rect', + shape: makeRectShape( + [pixelValue - bandWidth / 2, otherExtent[0]], + [bandWidth, span], + getPointDimIndex(axis) + ) + }; + } +}; + +function getPointDimIndex(axis) { + return axis.isHorizontal() ? 0 : 1; +} + +function getGlobalExtent(coordSys, dimIndex) { + var rect = coordSys.getRect(); + return [rect[XY[dimIndex]], rect[XY[dimIndex]] + rect[WH[dimIndex]]]; +} + +AxisView.registerAxisPointerClass('SingleAxisPointer', SingleAxisPointer); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +extendComponentView({ + type: 'single' +}); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/** + * @file Define the themeRiver view's series model + * @author Deqing Li(annong035@gmail.com) + */ + +var DATA_NAME_INDEX = 2; + +var ThemeRiverSeries = SeriesModel.extend({ + + type: 'series.themeRiver', + + dependencies: ['singleAxis'], + + /** + * @readOnly + * @type {module:zrender/core/util#HashMap} + */ + nameMap: null, + + /** + * @override + */ + init: function (option) { + // eslint-disable-next-line + ThemeRiverSeries.superApply(this, 'init', arguments); + + // Put this function here is for the sake of consistency of code style. + // Enable legend selection for each data item + // Use a function instead of direct access because data reference may changed + this.legendDataProvider = function () { + return this.getRawData(); + }; + }, + + /** + * If there is no value of a certain point in the time for some event,set it value to 0. + * + * @param {Array} data initial data in the option + * @return {Array} + */ + fixData: function (data) { + var rawDataLength = data.length; + + // grouped data by name + var groupResult = groupData(data, function (item) { + return item[2]; + }); + var layData = []; + groupResult.buckets.each(function (items, key) { + layData.push({name: key, dataList: items}); + }); + + var layerNum = layData.length; + var largestLayer = -1; + var index = -1; + for (var i = 0; i < layerNum; ++i) { + var len = layData[i].dataList.length; + if (len > largestLayer) { + largestLayer = len; + index = i; + } + } + + for (var k = 0; k < layerNum; ++k) { + if (k === index) { + continue; + } + var name = layData[k].name; + for (var j = 0; j < largestLayer; ++j) { + var timeValue = layData[index].dataList[j][0]; + var length = layData[k].dataList.length; + var keyIndex = -1; + for (var l = 0; l < length; ++l) { + var value = layData[k].dataList[l][0]; + if (value === timeValue) { + keyIndex = l; + break; + } + } + if (keyIndex === -1) { + data[rawDataLength] = []; + data[rawDataLength][0] = timeValue; + data[rawDataLength][1] = 0; + data[rawDataLength][2] = name; + rawDataLength++; + + } + } + } + return data; + }, + + /** + * @override + * @param {Object} option the initial option that user gived + * @param {module:echarts/model/Model} ecModel the model object for themeRiver option + * @return {module:echarts/data/List} + */ + getInitialData: function (option, ecModel) { + + var singleAxisModel = ecModel.queryComponents({ + mainType: 'singleAxis', + index: this.get('singleAxisIndex'), + id: this.get('singleAxisId') + })[0]; + + var axisType = singleAxisModel.get('type'); + + // filter the data item with the value of label is undefined + var filterData = filter(option.data, function (dataItem) { + return dataItem[2] !== undefined; + }); + + // ??? TODO design a stage to transfer data for themeRiver and lines? + var data = this.fixData(filterData || []); + var nameList = []; + var nameMap = this.nameMap = createHashMap(); + var count = 0; + + for (var i = 0; i < data.length; ++i) { + nameList.push(data[i][DATA_NAME_INDEX]); + if (!nameMap.get(data[i][DATA_NAME_INDEX])) { + nameMap.set(data[i][DATA_NAME_INDEX], count); + count++; + } + } + + var dimensionsInfo = createDimensions(data, { + coordDimensions: ['single'], + dimensionsDefine: [ + { + name: 'time', + type: getDimensionTypeByAxis(axisType) + }, + { + name: 'value', + type: 'float' + }, + { + name: 'name', + type: 'ordinal' + } + ], + encodeDefine: { + single: 0, + value: 1, + itemName: 2 + } + }); + + var list = new List(dimensionsInfo, this); + list.initData(data); + + return list; + }, + + /** + * The raw data is divided into multiple layers and each layer + * has same name. + * + * @return {Array.>} + */ + getLayerSeries: function () { + var data = this.getData(); + var lenCount = data.count(); + var indexArr = []; + + for (var i = 0; i < lenCount; ++i) { + indexArr[i] = i; + } + + var timeDim = data.mapDimension('single'); + + // data group by name + var groupResult = groupData(indexArr, function (index) { + return data.get('name', index); + }); + var layerSeries = []; + groupResult.buckets.each(function (items, key) { + items.sort(function (index1, index2) { + return data.get(timeDim, index1) - data.get(timeDim, index2); + }); + layerSeries.push({name: key, indices: items}); + }); + + return layerSeries; + }, + + /** + * Get data indices for show tooltip content + * + * @param {Array.|string} dim single coordinate dimension + * @param {number} value axis value + * @param {module:echarts/coord/single/SingleAxis} baseAxis single Axis used + * the themeRiver. + * @return {Object} {dataIndices, nestestValue} + */ + getAxisTooltipData: function (dim, value, baseAxis) { + if (!isArray(dim)) { + dim = dim ? [dim] : []; + } + + var data = this.getData(); + var layerSeries = this.getLayerSeries(); + var indices = []; + var layerNum = layerSeries.length; + var nestestValue; + + for (var i = 0; i < layerNum; ++i) { + var minDist = Number.MAX_VALUE; + var nearestIdx = -1; + var pointNum = layerSeries[i].indices.length; + for (var j = 0; j < pointNum; ++j) { + var theValue = data.get(dim[0], layerSeries[i].indices[j]); + var dist = Math.abs(theValue - value); + if (dist <= minDist) { + nestestValue = theValue; + minDist = dist; + nearestIdx = layerSeries[i].indices[j]; + } + } + indices.push(nearestIdx); + } + + return {dataIndices: indices, nestestValue: nestestValue}; + }, + + /** + * @override + * @param {number} dataIndex index of data + */ + formatTooltip: function (dataIndex) { + var data = this.getData(); + var htmlName = data.getName(dataIndex); + var htmlValue = data.get(data.mapDimension('value'), dataIndex); + if (isNaN(htmlValue) || htmlValue == null) { + htmlValue = '-'; + } + return encodeHTML(htmlName + ' : ' + htmlValue); + }, + + defaultOption: { + zlevel: 0, + z: 2, + + coordinateSystem: 'singleAxis', + + // gap in axis's orthogonal orientation + boundaryGap: ['10%', '10%'], + + // legendHoverLink: true, + + singleAxisIndex: 0, + + animationEasing: 'linear', + + label: { + margin: 4, + show: true, + position: 'left', + color: '#000', + fontSize: 11 + }, + + emphasis: { + label: { + show: true + } + } + } +}); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/** + * @file The file used to draw themeRiver view + * @author Deqing Li(annong035@gmail.com) + */ + +extendChartView({ + + type: 'themeRiver', + + init: function () { + this._layers = []; + }, + + render: function (seriesModel, ecModel, api) { + var data = seriesModel.getData(); + + var group = this.group; + + var layerSeries = seriesModel.getLayerSeries(); + + var layoutInfo = data.getLayout('layoutInfo'); + var rect = layoutInfo.rect; + var boundaryGap = layoutInfo.boundaryGap; + + group.attr('position', [0, rect.y + boundaryGap[0]]); + + function keyGetter(item) { + return item.name; + } + var dataDiffer = new DataDiffer( + this._layersSeries || [], layerSeries, + keyGetter, keyGetter + ); + + var newLayersGroups = {}; + + dataDiffer + .add(bind(process, this, 'add')) + .update(bind(process, this, 'update')) + .remove(bind(process, this, 'remove')) + .execute(); + + function process(status, idx, oldIdx) { + var oldLayersGroups = this._layers; + if (status === 'remove') { + group.remove(oldLayersGroups[idx]); + return; + } + var points0 = []; + var points1 = []; + var color; + var indices = layerSeries[idx].indices; + for (var j = 0; j < indices.length; j++) { + var layout = data.getItemLayout(indices[j]); + var x = layout.x; + var y0 = layout.y0; + var y = layout.y; + + points0.push([x, y0]); + points1.push([x, y0 + y]); + + color = data.getItemVisual(indices[j], 'color'); + } + + var polygon; + var text; + var textLayout = data.getItemLayout(indices[0]); + var itemModel = data.getItemModel(indices[j - 1]); + var labelModel = itemModel.getModel('label'); + var margin = labelModel.get('margin'); + if (status === 'add') { + var layerGroup = newLayersGroups[idx] = new Group(); + polygon = new Polygon$1({ + shape: { + points: points0, + stackedOnPoints: points1, + smooth: 0.4, + stackedOnSmooth: 0.4, + smoothConstraint: false + }, + z2: 0 + }); + text = new Text({ + style: { + x: textLayout.x - margin, + y: textLayout.y0 + textLayout.y / 2 + } + }); + layerGroup.add(polygon); + layerGroup.add(text); + group.add(layerGroup); + + polygon.setClipPath(createGridClipShape$3(polygon.getBoundingRect(), seriesModel, function () { + polygon.removeClipPath(); + })); + } + else { + var layerGroup = oldLayersGroups[oldIdx]; + polygon = layerGroup.childAt(0); + text = layerGroup.childAt(1); + group.add(layerGroup); + + newLayersGroups[idx] = layerGroup; + + updateProps(polygon, { + shape: { + points: points0, + stackedOnPoints: points1 + } + }, seriesModel); + + updateProps(text, { + style: { + x: textLayout.x - margin, + y: textLayout.y0 + textLayout.y / 2 + } + }, seriesModel); + } + + var hoverItemStyleModel = itemModel.getModel('emphasis.itemStyle'); + var itemStyleModel = itemModel.getModel('itemStyle'); + + setTextStyle(text.style, labelModel, { + text: labelModel.get('show') + ? seriesModel.getFormattedLabel(indices[j - 1], 'normal') + || data.getName(indices[j - 1]) + : null, + textVerticalAlign: 'middle' + }); + + polygon.setStyle(extend({ + fill: color + }, itemStyleModel.getItemStyle(['color']))); + + setHoverStyle(polygon, hoverItemStyleModel.getItemStyle()); + } + + this._layersSeries = layerSeries; + this._layers = newLayersGroups; + }, + + dispose: function () {} +}); + +// add animation to the view +function createGridClipShape$3(rect, seriesModel, cb) { + var rectEl = new Rect({ + shape: { + x: rect.x - 10, + y: rect.y - 10, + width: 0, + height: rect.height + 20 + } + }); + initProps(rectEl, { + shape: { + width: rect.width + 20, + height: rect.height + 20 + } + }, seriesModel, cb); + + return rectEl; +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/** + * @file Using layout algorithm transform the raw data to layout information. + * @author Deqing Li(annong035@gmail.com) + */ + +var themeRiverLayout = function (ecModel, api) { + + ecModel.eachSeriesByType('themeRiver', function (seriesModel) { + + var data = seriesModel.getData(); + + var single = seriesModel.coordinateSystem; + + var layoutInfo = {}; + + // use the axis boundingRect for view + var rect = single.getRect(); + + layoutInfo.rect = rect; + + var boundaryGap = seriesModel.get('boundaryGap'); + + var axis = single.getAxis(); + + layoutInfo.boundaryGap = boundaryGap; + + if (axis.orient === 'horizontal') { + boundaryGap[0] = parsePercent$1(boundaryGap[0], rect.height); + boundaryGap[1] = parsePercent$1(boundaryGap[1], rect.height); + var height = rect.height - boundaryGap[0] - boundaryGap[1]; + themeRiverLayout$1(data, seriesModel, height); + } + else { + boundaryGap[0] = parsePercent$1(boundaryGap[0], rect.width); + boundaryGap[1] = parsePercent$1(boundaryGap[1], rect.width); + var width = rect.width - boundaryGap[0] - boundaryGap[1]; + themeRiverLayout$1(data, seriesModel, width); + } + + data.setLayout('layoutInfo', layoutInfo); + }); +}; + +/** + * The layout information about themeriver + * + * @param {module:echarts/data/List} data data in the series + * @param {module:echarts/model/Series} seriesModel the model object of themeRiver series + * @param {number} height value used to compute every series height + */ +function themeRiverLayout$1(data, seriesModel, height) { + if (!data.count()) { + return; + } + var coordSys = seriesModel.coordinateSystem; + // the data in each layer are organized into a series. + var layerSeries = seriesModel.getLayerSeries(); + + // the points in each layer. + var timeDim = data.mapDimension('single'); + var valueDim = data.mapDimension('value'); + var layerPoints = map(layerSeries, function (singleLayer) { + return map(singleLayer.indices, function (idx) { + var pt = coordSys.dataToPoint(data.get(timeDim, idx)); + pt[1] = data.get(valueDim, idx); + return pt; + }); + }); + + var base = computeBaseline(layerPoints); + var baseLine = base.y0; + var ky = height / base.max; + + // set layout information for each item. + var n = layerSeries.length; + var m = layerSeries[0].indices.length; + var baseY0; + for (var j = 0; j < m; ++j) { + baseY0 = baseLine[j] * ky; + data.setItemLayout(layerSeries[0].indices[j], { + layerIndex: 0, + x: layerPoints[0][j][0], + y0: baseY0, + y: layerPoints[0][j][1] * ky + }); + for (var i = 1; i < n; ++i) { + baseY0 += layerPoints[i - 1][j][1] * ky; + data.setItemLayout(layerSeries[i].indices[j], { + layerIndex: i, + x: layerPoints[i][j][0], + y0: baseY0, + y: layerPoints[i][j][1] * ky + }); + } + } +} + +/** + * Compute the baseLine of the rawdata + * Inspired by Lee Byron's paper Stacked Graphs - Geometry & Aesthetics + * + * @param {Array.} data the points in each layer + * @return {Object} + */ +function computeBaseline(data) { + var layerNum = data.length; + var pointNum = data[0].length; + var sums = []; + var y0 = []; + var max = 0; + var temp; + var base = {}; + + for (var i = 0; i < pointNum; ++i) { + for (var j = 0, temp = 0; j < layerNum; ++j) { + temp += data[j][i][1]; + } + if (temp > max) { + max = temp; + } + sums.push(temp); + } + + for (var k = 0; k < pointNum; ++k) { + y0[k] = (max - sums[k]) / 2; + } + max = 0; + + for (var l = 0; l < pointNum; ++l) { + var sum = sums[l] + y0[l]; + if (sum > max) { + max = sum; + } + } + base.y0 = y0; + base.max = max; + + return base; +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/** + * @file Visual encoding for themeRiver view + * @author Deqing Li(annong035@gmail.com) + */ + +var themeRiverVisual = function (ecModel) { + ecModel.eachSeriesByType('themeRiver', function (seriesModel) { + var data = seriesModel.getData(); + var rawData = seriesModel.getRawData(); + var colorList = seriesModel.get('color'); + var idxMap = createHashMap(); + + data.each(function (idx) { + idxMap.set(data.getRawIndex(idx), idx); + }); + + rawData.each(function (rawIndex) { + var name = rawData.getName(rawIndex); + var color = colorList[(seriesModel.nameMap.get(name) - 1) % colorList.length]; + + rawData.setItemVisual(rawIndex, 'color', color); + + var idx = idxMap.get(rawIndex); + + if (idx != null) { + data.setItemVisual(idx, 'color', color); + } + }); + }); +}; + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +registerLayout(themeRiverLayout); +registerVisual(themeRiverVisual); +registerProcessor(dataFilter('themeRiver')); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +SeriesModel.extend({ + + type: 'series.sunburst', + + /** + * @type {module:echarts/data/Tree~Node} + */ + _viewRoot: null, + + getInitialData: function (option, ecModel) { + // Create a virtual root. + var root = { name: option.name, children: option.data }; + + completeTreeValue$1(root); + + var levels = option.levels || []; + + // levels = option.levels = setDefault(levels, ecModel); + + var treeOption = {}; + + treeOption.levels = levels; + + // Make sure always a new tree is created when setOption, + // in TreemapView, we check whether oldTree === newTree + // to choose mappings approach among old shapes and new shapes. + return Tree.createTree(root, this, treeOption).data; + }, + + optionUpdated: function () { + this.resetViewRoot(); + }, + + /* + * @override + */ + getDataParams: function (dataIndex) { + var params = SeriesModel.prototype.getDataParams.apply(this, arguments); + + var node = this.getData().tree.getNodeByDataIndex(dataIndex); + params.treePathInfo = wrapTreePathInfo(node, this); + + return params; + }, + + defaultOption: { + zlevel: 0, + z: 2, + + // 默认全局居中 + center: ['50%', '50%'], + radius: [0, '75%'], + // 默认顺时针 + clockwise: true, + startAngle: 90, + // 最小角度改为0 + minAngle: 0, + + percentPrecision: 2, + + // If still show when all data zero. + stillShowZeroSum: true, + + // Policy of highlighting pieces when hover on one + // Valid values: 'none' (for not downplay others), 'descendant', + // 'ancestor', 'self' + highlightPolicy: 'descendant', + + // 'rootToNode', 'link', or false + nodeClick: 'rootToNode', + + renderLabelForZeroData: false, + + label: { + // could be: 'radial', 'tangential', or 'none' + rotate: 'radial', + show: true, + opacity: 1, + // 'left' is for inner side of inside, and 'right' is for outter + // side for inside + align: 'center', + position: 'inside', + distance: 5, + silent: true, + emphasis: {} + }, + itemStyle: { + borderWidth: 1, + borderColor: 'white', + borderType: 'solid', + shadowBlur: 0, + shadowColor: 'rgba(0, 0, 0, 0.2)', + shadowOffsetX: 0, + shadowOffsetY: 0, + opacity: 1, + emphasis: {}, + highlight: { + opacity: 1 + }, + downplay: { + opacity: 0.9 + } + }, + + // Animation type canbe expansion, scale + animationType: 'expansion', + animationDuration: 1000, + animationDurationUpdate: 500, + animationEasing: 'cubicOut', + + data: [], + + levels: [], + + /** + * Sort order. + * + * Valid values: 'desc', 'asc', null, or callback function. + * 'desc' and 'asc' for descend and ascendant order; + * null for not sorting; + * example of callback function: + * function(nodeA, nodeB) { + * return nodeA.getValue() - nodeB.getValue(); + * } + */ + sort: 'desc' + }, + + getViewRoot: function () { + return this._viewRoot; + }, + + /** + * @param {module:echarts/data/Tree~Node} [viewRoot] + */ + resetViewRoot: function (viewRoot) { + viewRoot + ? (this._viewRoot = viewRoot) + : (viewRoot = this._viewRoot); + + var root = this.getRawData().tree.root; + + if (!viewRoot + || (viewRoot !== root && !root.contains(viewRoot)) + ) { + this._viewRoot = root; + } + } +}); + + + +/** + * @param {Object} dataNode + */ +function completeTreeValue$1(dataNode) { + // Postorder travel tree. + // If value of none-leaf node is not set, + // calculate it by suming up the value of all children. + var sum = 0; + + each$1(dataNode.children, function (child) { + + completeTreeValue$1(child); + + var childValue = child.value; + isArray(childValue) && (childValue = childValue[0]); + + sum += childValue; + }); + + var thisValue = dataNode.value; + if (isArray(thisValue)) { + thisValue = thisValue[0]; + } + + if (thisValue == null || isNaN(thisValue)) { + thisValue = sum; + } + // Value should not less than 0. + if (thisValue < 0) { + thisValue = 0; + } + + isArray(dataNode.value) + ? (dataNode.value[0] = thisValue) + : (dataNode.value = thisValue); +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var NodeHighlightPolicy = { + NONE: 'none', // not downplay others + DESCENDANT: 'descendant', + ANCESTOR: 'ancestor', + SELF: 'self' +}; + +var DEFAULT_SECTOR_Z = 2; +var DEFAULT_TEXT_Z = 4; + +/** + * Sunburstce of Sunburst including Sector, Label, LabelLine + * @constructor + * @extends {module:zrender/graphic/Group} + */ +function SunburstPiece(node, seriesModel, ecModel) { + + Group.call(this); + + var sector = new Sector({ + z2: DEFAULT_SECTOR_Z + }); + sector.seriesIndex = seriesModel.seriesIndex; + + var text = new Text({ + z2: DEFAULT_TEXT_Z, + silent: node.getModel('label').get('silent') + }); + this.add(sector); + this.add(text); + + this.updateData(true, node, 'normal', seriesModel, ecModel); + + // Hover to change label and labelLine + function onEmphasis() { + text.ignore = text.hoverIgnore; + } + function onNormal() { + text.ignore = text.normalIgnore; + } + this.on('emphasis', onEmphasis) + .on('normal', onNormal) + .on('mouseover', onEmphasis) + .on('mouseout', onNormal); +} + +var SunburstPieceProto = SunburstPiece.prototype; + +SunburstPieceProto.updateData = function ( + firstCreate, + node, + state, + seriesModel, + ecModel +) { + this.node = node; + node.piece = this; + + seriesModel = seriesModel || this._seriesModel; + ecModel = ecModel || this._ecModel; + + var sector = this.childAt(0); + sector.dataIndex = node.dataIndex; + + var itemModel = node.getModel(); + var layout = node.getLayout(); + // if (!layout) { + // console.log(node.getLayout()); + // } + var sectorShape = extend({}, layout); + sectorShape.label = null; + + var visualColor = getNodeColor(node, seriesModel, ecModel); + + fillDefaultColor(node, seriesModel, visualColor); + + var normalStyle = itemModel.getModel('itemStyle').getItemStyle(); + var style; + if (state === 'normal') { + style = normalStyle; + } + else { + var stateStyle = itemModel.getModel(state + '.itemStyle') + .getItemStyle(); + style = merge(stateStyle, normalStyle); + } + style = defaults( + { + lineJoin: 'bevel', + fill: style.fill || visualColor + }, + style + ); + + if (firstCreate) { + sector.setShape(sectorShape); + sector.shape.r = layout.r0; + updateProps( + sector, + { + shape: { + r: layout.r + } + }, + seriesModel, + node.dataIndex + ); + sector.useStyle(style); + } + else if (typeof style.fill === 'object' && style.fill.type + || typeof sector.style.fill === 'object' && sector.style.fill.type + ) { + // Disable animation for gradient since no interpolation method + // is supported for gradient + updateProps(sector, { + shape: sectorShape + }, seriesModel); + sector.useStyle(style); + } + else { + updateProps(sector, { + shape: sectorShape, + style: style + }, seriesModel); + } + + this._updateLabel(seriesModel, visualColor, state); + + var cursorStyle = itemModel.getShallow('cursor'); + cursorStyle && sector.attr('cursor', cursorStyle); + + if (firstCreate) { + var highlightPolicy = seriesModel.getShallow('highlightPolicy'); + this._initEvents(sector, node, seriesModel, highlightPolicy); + } + + this._seriesModel = seriesModel || this._seriesModel; + this._ecModel = ecModel || this._ecModel; +}; + +SunburstPieceProto.onEmphasis = function (highlightPolicy) { + var that = this; + this.node.hostTree.root.eachNode(function (n) { + if (n.piece) { + if (that.node === n) { + n.piece.updateData(false, n, 'emphasis'); + } + else if (isNodeHighlighted(n, that.node, highlightPolicy)) { + n.piece.childAt(0).trigger('highlight'); + } + else if (highlightPolicy !== NodeHighlightPolicy.NONE) { + n.piece.childAt(0).trigger('downplay'); + } + } + }); +}; + +SunburstPieceProto.onNormal = function () { + this.node.hostTree.root.eachNode(function (n) { + if (n.piece) { + n.piece.updateData(false, n, 'normal'); + } + }); +}; + +SunburstPieceProto.onHighlight = function () { + this.updateData(false, this.node, 'highlight'); +}; + +SunburstPieceProto.onDownplay = function () { + this.updateData(false, this.node, 'downplay'); +}; + +SunburstPieceProto._updateLabel = function (seriesModel, visualColor, state) { + var itemModel = this.node.getModel(); + var normalModel = itemModel.getModel('label'); + var labelModel = state === 'normal' || state === 'emphasis' + ? normalModel + : itemModel.getModel(state + '.label'); + var labelHoverModel = itemModel.getModel('emphasis.label'); + + var text = retrieve( + seriesModel.getFormattedLabel( + this.node.dataIndex, 'normal', null, null, 'label' + ), + this.node.name + ); + if (getLabelAttr('show') === false) { + text = ''; + } + + var layout = this.node.getLayout(); + var labelMinAngle = labelModel.get('minAngle'); + if (labelMinAngle == null) { + labelMinAngle = normalModel.get('minAngle'); + } + labelMinAngle = labelMinAngle / 180 * Math.PI; + var angle = layout.endAngle - layout.startAngle; + if (labelMinAngle != null && Math.abs(angle) < labelMinAngle) { + // Not displaying text when angle is too small + text = ''; + } + + var label = this.childAt(1); + + setLabelStyle( + label.style, label.hoverStyle || {}, normalModel, labelHoverModel, + { + defaultText: labelModel.getShallow('show') ? text : null, + autoColor: visualColor, + useInsideStyle: true + } + ); + + var midAngle = (layout.startAngle + layout.endAngle) / 2; + var dx = Math.cos(midAngle); + var dy = Math.sin(midAngle); + + var r; + var labelPosition = getLabelAttr('position'); + var labelPadding = getLabelAttr('distance') || 0; + var textAlign = getLabelAttr('align'); + if (labelPosition === 'outside') { + r = layout.r + labelPadding; + textAlign = midAngle > Math.PI / 2 ? 'right' : 'left'; + } + else { + if (!textAlign || textAlign === 'center') { + r = (layout.r + layout.r0) / 2; + textAlign = 'center'; + } + else if (textAlign === 'left') { + r = layout.r0 + labelPadding; + if (midAngle > Math.PI / 2) { + textAlign = 'right'; + } + } + else if (textAlign === 'right') { + r = layout.r - labelPadding; + if (midAngle > Math.PI / 2) { + textAlign = 'left'; + } + } + } + + label.attr('style', { + text: text, + textAlign: textAlign, + textVerticalAlign: getLabelAttr('verticalAlign') || 'middle', + opacity: getLabelAttr('opacity') + }); + + var textX = r * dx + layout.cx; + var textY = r * dy + layout.cy; + label.attr('position', [textX, textY]); + + var rotateType = getLabelAttr('rotate'); + var rotate = 0; + if (rotateType === 'radial') { + rotate = -midAngle; + if (rotate < -Math.PI / 2) { + rotate += Math.PI; + } + } + else if (rotateType === 'tangential') { + rotate = Math.PI / 2 - midAngle; + if (rotate > Math.PI / 2) { + rotate -= Math.PI; + } + else if (rotate < -Math.PI / 2) { + rotate += Math.PI; + } + } else if (typeof rotateType === 'number') { + rotate = rotateType * Math.PI / 180; + } + label.attr('rotation', rotate); + + function getLabelAttr(name) { + var stateAttr = labelModel.get(name); + if (stateAttr == null) { + return normalModel.get(name); + } + else { + return stateAttr; + } + } +}; + +SunburstPieceProto._initEvents = function ( + sector, + node, + seriesModel, + highlightPolicy +) { + sector.off('mouseover').off('mouseout').off('emphasis').off('normal'); + + var that = this; + var onEmphasis = function () { + that.onEmphasis(highlightPolicy); + }; + var onNormal = function () { + that.onNormal(); + }; + var onDownplay = function () { + that.onDownplay(); + }; + var onHighlight = function () { + that.onHighlight(); + }; + + if (seriesModel.isAnimationEnabled()) { + sector + .on('mouseover', onEmphasis) + .on('mouseout', onNormal) + .on('emphasis', onEmphasis) + .on('normal', onNormal) + .on('downplay', onDownplay) + .on('highlight', onHighlight); + } +}; + +inherits(SunburstPiece, Group); + +/** + * Get node color + * + * @param {TreeNode} node the node to get color + * @param {module:echarts/model/Series} seriesModel series + * @param {module:echarts/model/Global} ecModel echarts defaults + */ +function getNodeColor(node, seriesModel, ecModel) { + // Color from visualMap + var visualColor = node.getVisual('color'); + var visualMetaList = node.getVisual('visualMeta'); + if (!visualMetaList || visualMetaList.length === 0) { + // Use first-generation color if has no visualMap + visualColor = null; + } + + // Self color or level color + var color = node.getModel('itemStyle').get('color'); + if (color) { + return color; + } + else if (visualColor) { + // Color mapping + return visualColor; + } + else if (node.depth === 0) { + // Virtual root node + return ecModel.option.color[0]; + } + else { + // First-generation color + var length = ecModel.option.color.length; + color = ecModel.option.color[getRootId(node) % length]; + } + return color; +} + +/** + * Get index of root in sorted order + * + * @param {TreeNode} node current node + * @return {number} index in root + */ +function getRootId(node) { + var ancestor = node; + while (ancestor.depth > 1) { + ancestor = ancestor.parentNode; + } + + var virtualRoot = node.getAncestors()[0]; + return indexOf(virtualRoot.children, ancestor); +} + +function isNodeHighlighted(node, activeNode, policy) { + if (policy === NodeHighlightPolicy.NONE) { + return false; + } + else if (policy === NodeHighlightPolicy.SELF) { + return node === activeNode; + } + else if (policy === NodeHighlightPolicy.ANCESTOR) { + return node === activeNode || node.isAncestorOf(activeNode); + } + else { + return node === activeNode || node.isDescendantOf(activeNode); + } +} + +// Fix tooltip callback function params.color incorrect when pick a default color +function fillDefaultColor(node, seriesModel, color) { + var data = seriesModel.getData(); + data.setItemVisual(node.dataIndex, 'color', color); +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var ROOT_TO_NODE_ACTION = 'sunburstRootToNode'; + +var SunburstView = Chart.extend({ + + type: 'sunburst', + + init: function () { + }, + + render: function (seriesModel, ecModel, api, payload) { + var that = this; + + this.seriesModel = seriesModel; + this.api = api; + this.ecModel = ecModel; + + var data = seriesModel.getData(); + var virtualRoot = data.tree.root; + + var newRoot = seriesModel.getViewRoot(); + + var group = this.group; + + var renderLabelForZeroData = seriesModel.get('renderLabelForZeroData'); + + var newChildren = []; + newRoot.eachNode(function (node) { + newChildren.push(node); + }); + var oldChildren = this._oldChildren || []; + + dualTravel(newChildren, oldChildren); + + renderRollUp(virtualRoot, newRoot); + + if (payload && payload.highlight && payload.highlight.piece) { + var highlightPolicy = seriesModel.getShallow('highlightPolicy'); + payload.highlight.piece.onEmphasis(highlightPolicy); + } + else if (payload && payload.unhighlight) { + var piece = this.virtualPiece; + if (!piece && virtualRoot.children.length) { + piece = virtualRoot.children[0].piece; + } + if (piece) { + piece.onNormal(); + } + } + + this._initEvents(); + + this._oldChildren = newChildren; + + function dualTravel(newChildren, oldChildren) { + if (newChildren.length === 0 && oldChildren.length === 0) { + return; + } + + new DataDiffer(oldChildren, newChildren, getKey, getKey) + .add(processNode) + .update(processNode) + .remove(curry(processNode, null)) + .execute(); + + function getKey(node) { + return node.getId(); + } + + function processNode(newId, oldId) { + var newNode = newId == null ? null : newChildren[newId]; + var oldNode = oldId == null ? null : oldChildren[oldId]; + + doRenderNode(newNode, oldNode); + } + } + + function doRenderNode(newNode, oldNode) { + if (!renderLabelForZeroData && newNode && !newNode.getValue()) { + // Not render data with value 0 + newNode = null; + } + + if (newNode !== virtualRoot && oldNode !== virtualRoot) { + if (oldNode && oldNode.piece) { + if (newNode) { + // Update + oldNode.piece.updateData( + false, newNode, 'normal', seriesModel, ecModel); + + // For tooltip + data.setItemGraphicEl(newNode.dataIndex, oldNode.piece); + } + else { + // Remove + removeNode(oldNode); + } + } + else if (newNode) { + // Add + var piece = new SunburstPiece( + newNode, + seriesModel, + ecModel + ); + group.add(piece); + + // For tooltip + data.setItemGraphicEl(newNode.dataIndex, piece); + } + } + } + + function removeNode(node) { + if (!node) { + return; + } + + if (node.piece) { + group.remove(node.piece); + node.piece = null; + } + } + + function renderRollUp(virtualRoot, viewRoot) { + if (viewRoot.depth > 0) { + // Render + if (that.virtualPiece) { + // Update + that.virtualPiece.updateData( + false, virtualRoot, 'normal', seriesModel, ecModel); + } + else { + // Add + that.virtualPiece = new SunburstPiece( + virtualRoot, + seriesModel, + ecModel + ); + group.add(that.virtualPiece); + } + + if (viewRoot.piece._onclickEvent) { + viewRoot.piece.off('click', viewRoot.piece._onclickEvent); + } + var event = function (e) { + that._rootToNode(viewRoot.parentNode); + }; + viewRoot.piece._onclickEvent = event; + that.virtualPiece.on('click', event); + } + else if (that.virtualPiece) { + // Remove + group.remove(that.virtualPiece); + that.virtualPiece = null; + } + } + }, + + dispose: function () { + }, + + /** + * @private + */ + _initEvents: function () { + var that = this; + + var event = function (e) { + var targetFound = false; + var viewRoot = that.seriesModel.getViewRoot(); + viewRoot.eachNode(function (node) { + if (!targetFound + && node.piece && node.piece.childAt(0) === e.target + ) { + var nodeClick = node.getModel().get('nodeClick'); + if (nodeClick === 'rootToNode') { + that._rootToNode(node); + } + else if (nodeClick === 'link') { + var itemModel = node.getModel(); + var link = itemModel.get('link'); + if (link) { + var linkTarget = itemModel.get('target', true) + || '_blank'; + window.open(link, linkTarget); + } + } + targetFound = true; + } + }); + }; + + if (this.group._onclickEvent) { + this.group.off('click', this.group._onclickEvent); + } + this.group.on('click', event); + this.group._onclickEvent = event; + }, + + /** + * @private + */ + _rootToNode: function (node) { + if (node !== this.seriesModel.getViewRoot()) { + this.api.dispatchAction({ + type: ROOT_TO_NODE_ACTION, + from: this.uid, + seriesId: this.seriesModel.id, + targetNode: node + }); + } + }, + + /** + * @implement + */ + containPoint: function (point, seriesModel) { + var treeRoot = seriesModel.getData(); + var itemLayout = treeRoot.getItemLayout(0); + if (itemLayout) { + var dx = point[0] - itemLayout.cx; + var dy = point[1] - itemLayout.cy; + var radius = Math.sqrt(dx * dx + dy * dy); + return radius <= itemLayout.r && radius >= itemLayout.r0; + } + } + +}); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/** + * @file Sunburst action + */ + +var ROOT_TO_NODE_ACTION$1 = 'sunburstRootToNode'; + +registerAction( + {type: ROOT_TO_NODE_ACTION$1, update: 'updateView'}, + function (payload, ecModel) { + + ecModel.eachComponent( + {mainType: 'series', subType: 'sunburst', query: payload}, + handleRootToNode + ); + + function handleRootToNode(model, index) { + var targetInfo = retrieveTargetInfo(payload, [ROOT_TO_NODE_ACTION$1], model); + + if (targetInfo) { + var originViewRoot = model.getViewRoot(); + if (originViewRoot) { + payload.direction = aboveViewRoot(originViewRoot, targetInfo.node) + ? 'rollUp' : 'drillDown'; + } + model.resetViewRoot(targetInfo.node); + } + } + } +); + + +var HIGHLIGHT_ACTION = 'sunburstHighlight'; + +registerAction( + {type: HIGHLIGHT_ACTION, update: 'updateView'}, + function (payload, ecModel) { + + ecModel.eachComponent( + {mainType: 'series', subType: 'sunburst', query: payload}, + handleHighlight + ); + + function handleHighlight(model, index) { + var targetInfo = retrieveTargetInfo(payload, [HIGHLIGHT_ACTION], model); + + if (targetInfo) { + payload.highlight = targetInfo.node; + } + } + } +); + + +var UNHIGHLIGHT_ACTION = 'sunburstUnhighlight'; + +registerAction( + {type: UNHIGHLIGHT_ACTION, update: 'updateView'}, + function (payload, ecModel) { + + ecModel.eachComponent( + {mainType: 'series', subType: 'sunburst', query: payload}, + handleUnhighlight + ); + + function handleUnhighlight(model, index) { + payload.unhighlight = true; + } + } +); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + + +var RADIAN$1 = Math.PI / 180; + +var sunburstLayout = function (seriesType, ecModel, api, payload) { + ecModel.eachSeriesByType(seriesType, function (seriesModel) { + var center = seriesModel.get('center'); + var radius = seriesModel.get('radius'); + + if (!isArray(radius)) { + radius = [0, radius]; + } + if (!isArray(center)) { + center = [center, center]; + } + + var width = api.getWidth(); + var height = api.getHeight(); + var size = Math.min(width, height); + var cx = parsePercent$1(center[0], width); + var cy = parsePercent$1(center[1], height); + var r0 = parsePercent$1(radius[0], size / 2); + var r = parsePercent$1(radius[1], size / 2); + + var startAngle = -seriesModel.get('startAngle') * RADIAN$1; + var minAngle = seriesModel.get('minAngle') * RADIAN$1; + + var virtualRoot = seriesModel.getData().tree.root; + var treeRoot = seriesModel.getViewRoot(); + var rootDepth = treeRoot.depth; + + var sort = seriesModel.get('sort'); + if (sort != null) { + initChildren$1(treeRoot, sort); + } + + var validDataCount = 0; + each$1(treeRoot.children, function (child) { + !isNaN(child.getValue()) && validDataCount++; + }); + + var sum = treeRoot.getValue(); + // Sum may be 0 + var unitRadian = Math.PI / (sum || validDataCount) * 2; + + var renderRollupNode = treeRoot.depth > 0; + var levels = treeRoot.height - (renderRollupNode ? -1 : 1); + var rPerLevel = (r - r0) / (levels || 1); + + var clockwise = seriesModel.get('clockwise'); + + var stillShowZeroSum = seriesModel.get('stillShowZeroSum'); + + // In the case some sector angle is smaller than minAngle + var dir = clockwise ? 1 : -1; + + /** + * Render a tree + * @return increased angle + */ + var renderNode = function (node, startAngle) { + if (!node) { + return; + } + + var endAngle = startAngle; + + // Render self + if (node !== virtualRoot) { + // Tree node is virtual, so it doesn't need to be drawn + var value = node.getValue(); + + var angle = (sum === 0 && stillShowZeroSum) + ? unitRadian : (value * unitRadian); + if (angle < minAngle) { + angle = minAngle; + + } + else { + + } + + endAngle = startAngle + dir * angle; + + var depth = node.depth - rootDepth + - (renderRollupNode ? -1 : 1); + var rStart = r0 + rPerLevel * depth; + var rEnd = r0 + rPerLevel * (depth + 1); + + var itemModel = node.getModel(); + if (itemModel.get('r0') != null) { + rStart = parsePercent$1(itemModel.get('r0'), size / 2); + } + if (itemModel.get('r') != null) { + rEnd = parsePercent$1(itemModel.get('r'), size / 2); + } + + node.setLayout({ + angle: angle, + startAngle: startAngle, + endAngle: endAngle, + clockwise: clockwise, + cx: cx, + cy: cy, + r0: rStart, + r: rEnd + }); + } + + // Render children + if (node.children && node.children.length) { + // currentAngle = startAngle; + var siblingAngle = 0; + each$1(node.children, function (node) { + siblingAngle += renderNode(node, startAngle + siblingAngle); + }); + } + + return endAngle - startAngle; + }; + + // Virtual root node for roll up + if (renderRollupNode) { + var rStart = r0; + var rEnd = r0 + rPerLevel; + + var angle = Math.PI * 2; + virtualRoot.setLayout({ + angle: angle, + startAngle: startAngle, + endAngle: startAngle + angle, + clockwise: clockwise, + cx: cx, + cy: cy, + r0: rStart, + r: rEnd + }); + } + + renderNode(treeRoot, startAngle); + }); +}; + +/** + * Init node children by order and update visual + * + * @param {TreeNode} node root node + * @param {boolean} isAsc if is in ascendant order + */ +function initChildren$1(node, isAsc) { + var children = node.children || []; + + node.children = sort$2(children, isAsc); + + // Init children recursively + if (children.length) { + each$1(node.children, function (child) { + initChildren$1(child, isAsc); + }); + } +} + +/** + * Sort children nodes + * + * @param {TreeNode[]} children children of node to be sorted + * @param {string | function | null} sort sort method + * See SunburstSeries.js for details. + */ +function sort$2(children, sortOrder) { + if (typeof sortOrder === 'function') { + return children.sort(sortOrder); + } + else { + var isAsc = sortOrder === 'asc'; + return children.sort(function (a, b) { + var diff = (a.getValue() - b.getValue()) * (isAsc ? 1 : -1); + return diff === 0 + ? (a.dataIndex - b.dataIndex) * (isAsc ? -1 : 1) + : diff; + }); + } +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +registerVisual(curry(dataColor, 'sunburst')); +registerLayout(curry(sunburstLayout, 'sunburst')); +registerProcessor(curry(dataFilter, 'sunburst')); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +function dataToCoordSize(dataSize, dataItem) { + // dataItem is necessary in log axis. + dataItem = dataItem || [0, 0]; + return map(['x', 'y'], function (dim, dimIdx) { + var axis = this.getAxis(dim); + var val = dataItem[dimIdx]; + var halfSize = dataSize[dimIdx] / 2; + return axis.type === 'category' + ? axis.getBandWidth() + : Math.abs(axis.dataToCoord(val - halfSize) - axis.dataToCoord(val + halfSize)); + }, this); +} + +var prepareCartesian2d = function (coordSys) { + var rect = coordSys.grid.getRect(); + return { + coordSys: { + // The name exposed to user is always 'cartesian2d' but not 'grid'. + type: 'cartesian2d', + x: rect.x, + y: rect.y, + width: rect.width, + height: rect.height + }, + api: { + coord: function (data) { + // do not provide "out" param + return coordSys.dataToPoint(data); + }, + size: bind(dataToCoordSize, coordSys) + } + }; +}; + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +function dataToCoordSize$1(dataSize, dataItem) { + dataItem = dataItem || [0, 0]; + return map([0, 1], function (dimIdx) { + var val = dataItem[dimIdx]; + var halfSize = dataSize[dimIdx] / 2; + var p1 = []; + var p2 = []; + p1[dimIdx] = val - halfSize; + p2[dimIdx] = val + halfSize; + p1[1 - dimIdx] = p2[1 - dimIdx] = dataItem[1 - dimIdx]; + return Math.abs(this.dataToPoint(p1)[dimIdx] - this.dataToPoint(p2)[dimIdx]); + }, this); +} + +var prepareGeo = function (coordSys) { + var rect = coordSys.getBoundingRect(); + return { + coordSys: { + type: 'geo', + x: rect.x, + y: rect.y, + width: rect.width, + height: rect.height, + zoom: coordSys.getZoom() + }, + api: { + coord: function (data) { + // do not provide "out" and noRoam param, + // Compatible with this usage: + // echarts.util.map(item.points, api.coord) + return coordSys.dataToPoint(data); + }, + size: bind(dataToCoordSize$1, coordSys) + } + }; +}; + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +function dataToCoordSize$2(dataSize, dataItem) { + // dataItem is necessary in log axis. + var axis = this.getAxis(); + var val = dataItem instanceof Array ? dataItem[0] : dataItem; + var halfSize = (dataSize instanceof Array ? dataSize[0] : dataSize) / 2; + return axis.type === 'category' + ? axis.getBandWidth() + : Math.abs(axis.dataToCoord(val - halfSize) - axis.dataToCoord(val + halfSize)); +} + +var prepareSingleAxis = function (coordSys) { + var rect = coordSys.getRect(); + + return { + coordSys: { + type: 'singleAxis', + x: rect.x, + y: rect.y, + width: rect.width, + height: rect.height + }, + api: { + coord: function (val) { + // do not provide "out" param + return coordSys.dataToPoint(val); + }, + size: bind(dataToCoordSize$2, coordSys) + } + }; +}; + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +function dataToCoordSize$3(dataSize, dataItem) { + // dataItem is necessary in log axis. + return map(['Radius', 'Angle'], function (dim, dimIdx) { + var axis = this['get' + dim + 'Axis'](); + var val = dataItem[dimIdx]; + var halfSize = dataSize[dimIdx] / 2; + var method = 'dataTo' + dim; + + var result = axis.type === 'category' + ? axis.getBandWidth() + : Math.abs(axis[method](val - halfSize) - axis[method](val + halfSize)); + + if (dim === 'Angle') { + result = result * Math.PI / 180; + } + + return result; + + }, this); +} + +var preparePolar = function (coordSys) { + var radiusAxis = coordSys.getRadiusAxis(); + var angleAxis = coordSys.getAngleAxis(); + var radius = radiusAxis.getExtent(); + radius[0] > radius[1] && radius.reverse(); + + return { + coordSys: { + type: 'polar', + cx: coordSys.cx, + cy: coordSys.cy, + r: radius[1], + r0: radius[0] + }, + api: { + coord: bind(function (data) { + var radius = radiusAxis.dataToRadius(data[0]); + var angle = angleAxis.dataToAngle(data[1]); + var coord = coordSys.coordToPoint([radius, angle]); + coord.push(radius, angle * Math.PI / 180); + return coord; + }), + size: bind(dataToCoordSize$3, coordSys) + } + }; +}; + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var prepareCalendar = function (coordSys) { + var rect = coordSys.getRect(); + var rangeInfo = coordSys.getRangeInfo(); + + return { + coordSys: { + type: 'calendar', + x: rect.x, + y: rect.y, + width: rect.width, + height: rect.height, + cellWidth: coordSys.getCellWidth(), + cellHeight: coordSys.getCellHeight(), + rangeInfo: { + start: rangeInfo.start, + end: rangeInfo.end, + weeks: rangeInfo.weeks, + dayCount: rangeInfo.allDay + } + }, + api: { + coord: function (data, clamp) { + return coordSys.dataToPoint(data, clamp); + } + } + }; +}; + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var ITEM_STYLE_NORMAL_PATH = ['itemStyle']; +var ITEM_STYLE_EMPHASIS_PATH = ['emphasis', 'itemStyle']; +var LABEL_NORMAL = ['label']; +var LABEL_EMPHASIS = ['emphasis', 'label']; +// Use prefix to avoid index to be the same as el.name, +// which will cause weird udpate animation. +var GROUP_DIFF_PREFIX = 'e\0\0'; + +/** + * To reduce total package size of each coordinate systems, the modules `prepareCustom` + * of each coordinate systems are not required by each coordinate systems directly, but + * required by the module `custom`. + * + * prepareInfoForCustomSeries {Function}: optional + * @return {Object} {coordSys: {...}, api: { + * coord: function (data, clamp) {}, // return point in global. + * size: function (dataSize, dataItem) {} // return size of each axis in coordSys. + * }} + */ +var prepareCustoms = { + cartesian2d: prepareCartesian2d, + geo: prepareGeo, + singleAxis: prepareSingleAxis, + polar: preparePolar, + calendar: prepareCalendar +}; + + +// ------ +// Model +// ------ + +SeriesModel.extend({ + + type: 'series.custom', + + dependencies: ['grid', 'polar', 'geo', 'singleAxis', 'calendar'], + + defaultOption: { + coordinateSystem: 'cartesian2d', // Can be set as 'none' + zlevel: 0, + z: 2, + legendHoverLink: true, + + useTransform: true + + // Cartesian coordinate system + // xAxisIndex: 0, + // yAxisIndex: 0, + + // Polar coordinate system + // polarIndex: 0, + + // Geo coordinate system + // geoIndex: 0, + + // label: {} + // itemStyle: {} + }, + + /** + * @override + */ + getInitialData: function (option, ecModel) { + return createListFromArray(this.getSource(), this); + }, + + /** + * @override + */ + getDataParams: function (dataIndex, dataType, el) { + var params = SeriesModel.prototype.getDataParams.apply(this, arguments); + el && (params.info = el.info); + return params; + } +}); + +// ----- +// View +// ----- + +Chart.extend({ + + type: 'custom', + + /** + * @private + * @type {module:echarts/data/List} + */ + _data: null, + + /** + * @override + */ + render: function (customSeries, ecModel, api, payload) { + var oldData = this._data; + var data = customSeries.getData(); + var group = this.group; + var renderItem = makeRenderItem(customSeries, data, ecModel, api); + + // By default, merge mode is applied. In most cases, custom series is + // used in the scenario that data amount is not large but graphic elements + // is complicated, where merge mode is probably necessary for optimization. + // For example, reuse graphic elements and only update the transform when + // roam or data zoom according to `actionType`. + data.diff(oldData) + .add(function (newIdx) { + createOrUpdate$1( + null, newIdx, renderItem(newIdx, payload), customSeries, group, data + ); + }) + .update(function (newIdx, oldIdx) { + var el = oldData.getItemGraphicEl(oldIdx); + createOrUpdate$1( + el, newIdx, renderItem(newIdx, payload), customSeries, group, data + ); + }) + .remove(function (oldIdx) { + var el = oldData.getItemGraphicEl(oldIdx); + el && group.remove(el); + }) + .execute(); + + this._data = data; + }, + + incrementalPrepareRender: function (customSeries, ecModel, api) { + this.group.removeAll(); + this._data = null; + }, + + incrementalRender: function (params, customSeries, ecModel, api, payload) { + var data = customSeries.getData(); + var renderItem = makeRenderItem(customSeries, data, ecModel, api); + function setIncrementalAndHoverLayer(el) { + if (!el.isGroup) { + el.incremental = true; + el.useHoverLayer = true; + } + } + for (var idx = params.start; idx < params.end; idx++) { + var el = createOrUpdate$1(null, idx, renderItem(idx, payload), customSeries, this.group, data); + el.traverse(setIncrementalAndHoverLayer); + } + }, + + /** + * @override + */ + dispose: noop, + + /** + * @override + */ + filterForExposedEvent: function (eventType, query, targetEl, packedEvent) { + var elementName = query.element; + if (elementName == null || targetEl.name === elementName) { + return true; + } + + // Enable to give a name on a group made by `renderItem`, and listen + // events that triggerd by its descendents. + while ((targetEl = targetEl.parent) && targetEl !== this.group) { + if (targetEl.name === elementName) { + return true; + } + } + + return false; + } +}); + + +function createEl(elOption) { + var graphicType = elOption.type; + var el; + + if (graphicType === 'path') { + var shape = elOption.shape; + // Using pathRect brings convenience to users sacle svg path. + var pathRect = (shape.width != null && shape.height != null) + ? { + x: shape.x || 0, + y: shape.y || 0, + width: shape.width, + height: shape.height + } + : null; + var pathData = getPathData(shape); + // Path is also used for icon, so layout 'center' by default. + el = makePath(pathData, null, pathRect, shape.layout || 'center'); + el.__customPathData = pathData; + } + else if (graphicType === 'image') { + el = new ZImage({}); + el.__customImagePath = elOption.style.image; + } + else if (graphicType === 'text') { + el = new Text({}); + el.__customText = elOption.style.text; + } + else { + var Clz = graphic[graphicType.charAt(0).toUpperCase() + graphicType.slice(1)]; + + if (__DEV__) { + assert$1(Clz, 'graphic type "' + graphicType + '" can not be found.'); + } + + el = new Clz(); + } + + el.__customGraphicType = graphicType; + el.name = elOption.name; + + return el; +} + +function updateEl(el, dataIndex, elOption, animatableModel, data, isInit, isRoot) { + var transitionProps = {}; + var elOptionStyle = elOption.style || {}; + + elOption.shape && (transitionProps.shape = clone(elOption.shape)); + elOption.position && (transitionProps.position = elOption.position.slice()); + elOption.scale && (transitionProps.scale = elOption.scale.slice()); + elOption.origin && (transitionProps.origin = elOption.origin.slice()); + elOption.rotation && (transitionProps.rotation = elOption.rotation); + + if (el.type === 'image' && elOption.style) { + var targetStyle = transitionProps.style = {}; + each$1(['x', 'y', 'width', 'height'], function (prop) { + prepareStyleTransition(prop, targetStyle, elOptionStyle, el.style, isInit); + }); + } + + if (el.type === 'text' && elOption.style) { + var targetStyle = transitionProps.style = {}; + each$1(['x', 'y'], function (prop) { + prepareStyleTransition(prop, targetStyle, elOptionStyle, el.style, isInit); + }); + // Compatible with previous: both support + // textFill and fill, textStroke and stroke in 'text' element. + !elOptionStyle.hasOwnProperty('textFill') && elOptionStyle.fill && ( + elOptionStyle.textFill = elOptionStyle.fill + ); + !elOptionStyle.hasOwnProperty('textStroke') && elOptionStyle.stroke && ( + elOptionStyle.textStroke = elOptionStyle.stroke + ); + } + + if (el.type !== 'group') { + el.useStyle(elOptionStyle); + + // Init animation. + if (isInit) { + el.style.opacity = 0; + var targetOpacity = elOptionStyle.opacity; + targetOpacity == null && (targetOpacity = 1); + initProps(el, {style: {opacity: targetOpacity}}, animatableModel, dataIndex); + } + } + + if (isInit) { + el.attr(transitionProps); + } + else { + updateProps(el, transitionProps, animatableModel, dataIndex); + } + + // Merge by default. + // z2 must not be null/undefined, otherwise sort error may occur. + elOption.hasOwnProperty('z2') && el.attr('z2', elOption.z2 || 0); + elOption.hasOwnProperty('silent') && el.attr('silent', elOption.silent); + elOption.hasOwnProperty('invisible') && el.attr('invisible', elOption.invisible); + elOption.hasOwnProperty('ignore') && el.attr('ignore', elOption.ignore); + // `elOption.info` enables user to mount some info on + // elements and use them in event handlers. + // Update them only when user specified, otherwise, remain. + elOption.hasOwnProperty('info') && el.attr('info', elOption.info); + + // If `elOption.styleEmphasis` is `false`, remove hover style. The + // logic is ensured by `graphicUtil.setElementHoverStyle`. + var styleEmphasis = elOption.styleEmphasis; + var disableStyleEmphasis = styleEmphasis === false; + if (!( + // Try to escapse setting hover style for performance. + (el.__cusHasEmphStl && styleEmphasis == null) + || (!el.__cusHasEmphStl && disableStyleEmphasis) + )) { + // Should not use graphicUtil.setHoverStyle, since the styleEmphasis + // should not be share by group and its descendants. + setElementHoverStyle(el, styleEmphasis); + el.__cusHasEmphStl = !disableStyleEmphasis; + } + isRoot && setAsHoverStyleTrigger(el, !disableStyleEmphasis); +} + +function prepareStyleTransition(prop, targetStyle, elOptionStyle, oldElStyle, isInit) { + if (elOptionStyle[prop] != null && !isInit) { + targetStyle[prop] = elOptionStyle[prop]; + elOptionStyle[prop] = oldElStyle[prop]; + } +} + +function makeRenderItem(customSeries, data, ecModel, api) { + var renderItem = customSeries.get('renderItem'); + var coordSys = customSeries.coordinateSystem; + var prepareResult = {}; + + if (coordSys) { + if (__DEV__) { + assert$1(renderItem, 'series.render is required.'); + assert$1( + coordSys.prepareCustoms || prepareCustoms[coordSys.type], + 'This coordSys does not support custom series.' + ); + } + + prepareResult = coordSys.prepareCustoms + ? coordSys.prepareCustoms() + : prepareCustoms[coordSys.type](coordSys); + } + + var userAPI = defaults({ + getWidth: api.getWidth, + getHeight: api.getHeight, + getZr: api.getZr, + getDevicePixelRatio: api.getDevicePixelRatio, + value: value, + style: style, + styleEmphasis: styleEmphasis, + visual: visual, + barLayout: barLayout, + currentSeriesIndices: currentSeriesIndices, + font: font + }, prepareResult.api || {}); + + var userParams = { + // The life cycle of context: current round of rendering. + // The global life cycle is probably not necessary, because + // user can store global status by themselves. + context: {}, + seriesId: customSeries.id, + seriesName: customSeries.name, + seriesIndex: customSeries.seriesIndex, + coordSys: prepareResult.coordSys, + dataInsideLength: data.count(), + encode: wrapEncodeDef(customSeries.getData()) + }; + + // Do not support call `api` asynchronously without dataIndexInside input. + var currDataIndexInside; + var currDirty = true; + var currItemModel; + var currLabelNormalModel; + var currLabelEmphasisModel; + var currVisualColor; + + return function (dataIndexInside, payload) { + currDataIndexInside = dataIndexInside; + currDirty = true; + + return renderItem && renderItem( + defaults({ + dataIndexInside: dataIndexInside, + dataIndex: data.getRawIndex(dataIndexInside), + // Can be used for optimization when zoom or roam. + actionType: payload ? payload.type : null + }, userParams), + userAPI + ); + }; + + // Do not update cache until api called. + function updateCache(dataIndexInside) { + dataIndexInside == null && (dataIndexInside = currDataIndexInside); + if (currDirty) { + currItemModel = data.getItemModel(dataIndexInside); + currLabelNormalModel = currItemModel.getModel(LABEL_NORMAL); + currLabelEmphasisModel = currItemModel.getModel(LABEL_EMPHASIS); + currVisualColor = data.getItemVisual(dataIndexInside, 'color'); + + currDirty = false; + } + } + + /** + * @public + * @param {number|string} dim + * @param {number} [dataIndexInside=currDataIndexInside] + * @return {number|string} value + */ + function value(dim, dataIndexInside) { + dataIndexInside == null && (dataIndexInside = currDataIndexInside); + return data.get(data.getDimension(dim || 0), dataIndexInside); + } + + /** + * By default, `visual` is applied to style (to support visualMap). + * `visual.color` is applied at `fill`. If user want apply visual.color on `stroke`, + * it can be implemented as: + * `api.style({stroke: api.visual('color'), fill: null})`; + * @public + * @param {Object} [extra] + * @param {number} [dataIndexInside=currDataIndexInside] + */ + function style(extra, dataIndexInside) { + dataIndexInside == null && (dataIndexInside = currDataIndexInside); + updateCache(dataIndexInside); + + var itemStyle = currItemModel.getModel(ITEM_STYLE_NORMAL_PATH).getItemStyle(); + + currVisualColor != null && (itemStyle.fill = currVisualColor); + var opacity = data.getItemVisual(dataIndexInside, 'opacity'); + opacity != null && (itemStyle.opacity = opacity); + + setTextStyle(itemStyle, currLabelNormalModel, null, { + autoColor: currVisualColor, + isRectText: true + }); + + itemStyle.text = currLabelNormalModel.getShallow('show') + ? retrieve2( + customSeries.getFormattedLabel(dataIndexInside, 'normal'), + getDefaultLabel(data, dataIndexInside) + ) + : null; + + extra && extend(itemStyle, extra); + return itemStyle; + } + + /** + * @public + * @param {Object} [extra] + * @param {number} [dataIndexInside=currDataIndexInside] + */ + function styleEmphasis(extra, dataIndexInside) { + dataIndexInside == null && (dataIndexInside = currDataIndexInside); + updateCache(dataIndexInside); + + var itemStyle = currItemModel.getModel(ITEM_STYLE_EMPHASIS_PATH).getItemStyle(); + + setTextStyle(itemStyle, currLabelEmphasisModel, null, { + isRectText: true + }, true); + + itemStyle.text = currLabelEmphasisModel.getShallow('show') + ? retrieve3( + customSeries.getFormattedLabel(dataIndexInside, 'emphasis'), + customSeries.getFormattedLabel(dataIndexInside, 'normal'), + getDefaultLabel(data, dataIndexInside) + ) + : null; + + extra && extend(itemStyle, extra); + return itemStyle; + } + + /** + * @public + * @param {string} visualType + * @param {number} [dataIndexInside=currDataIndexInside] + */ + function visual(visualType, dataIndexInside) { + dataIndexInside == null && (dataIndexInside = currDataIndexInside); + return data.getItemVisual(dataIndexInside, visualType); + } + + /** + * @public + * @param {number} opt.count Positive interger. + * @param {number} [opt.barWidth] + * @param {number} [opt.barMaxWidth] + * @param {number} [opt.barGap] + * @param {number} [opt.barCategoryGap] + * @return {Object} {width, offset, offsetCenter} is not support, return undefined. + */ + function barLayout(opt) { + if (coordSys.getBaseAxis) { + var baseAxis = coordSys.getBaseAxis(); + return getLayoutOnAxis(defaults({axis: baseAxis}, opt), api); + } + } + + /** + * @public + * @return {Array.} + */ + function currentSeriesIndices() { + return ecModel.getCurrentSeriesIndices(); + } + + /** + * @public + * @param {Object} opt + * @param {string} [opt.fontStyle] + * @param {number} [opt.fontWeight] + * @param {number} [opt.fontSize] + * @param {string} [opt.fontFamily] + * @return {string} font string + */ + function font(opt) { + return getFont(opt, ecModel); + } +} + +function wrapEncodeDef(data) { + var encodeDef = {}; + each$1(data.dimensions, function (dimName, dataDimIndex) { + var dimInfo = data.getDimensionInfo(dimName); + if (!dimInfo.isExtraCoord) { + var coordDim = dimInfo.coordDim; + var dataDims = encodeDef[coordDim] = encodeDef[coordDim] || []; + dataDims[dimInfo.coordDimIndex] = dataDimIndex; + } + }); + return encodeDef; +} + +function createOrUpdate$1(el, dataIndex, elOption, animatableModel, group, data) { + el = doCreateOrUpdate(el, dataIndex, elOption, animatableModel, group, data, true); + el && data.setItemGraphicEl(dataIndex, el); + + return el; +} + +function doCreateOrUpdate(el, dataIndex, elOption, animatableModel, group, data, isRoot) { + + // [Rule] + // By default, follow merge mode. + // (It probably brings benifit for performance in some cases of large data, where + // user program can be optimized to that only updated props needed to be re-calculated, + // or according to `actionType` some calculation can be skipped.) + // If `renderItem` returns `null`/`undefined`/`false`, remove the previous el if existing. + // (It seems that violate the "merge" principle, but most of users probably intuitively + // regard "return;" as "show nothing element whatever", so make a exception to meet the + // most cases.) + + var simplyRemove = !elOption; // `null`/`undefined`/`false` + elOption = elOption || {}; + var elOptionType = elOption.type; + var elOptionShape = elOption.shape; + var elOptionStyle = elOption.style; + + if (el && ( + simplyRemove + // || elOption.$merge === false + // If `elOptionType` is `null`, follow the merge principle. + || (elOptionType != null + && elOptionType !== el.__customGraphicType + ) + || (elOptionType === 'path' + && hasOwnPathData(elOptionShape) && getPathData(elOptionShape) !== el.__customPathData + ) + || (elOptionType === 'image' + && hasOwn(elOptionStyle, 'image') && elOptionStyle.image !== el.__customImagePath + ) + // FIXME test and remove this restriction? + || (elOptionType === 'text' + && hasOwn(elOptionShape, 'text') && elOptionStyle.text !== el.__customText + ) + )) { + group.remove(el); + el = null; + } + + // `elOption.type` is undefined when `renderItem` returns nothing. + if (simplyRemove) { + return; + } + + var isInit = !el; + !el && (el = createEl(elOption)); + updateEl(el, dataIndex, elOption, animatableModel, data, isInit, isRoot); + + if (elOptionType === 'group') { + mergeChildren(el, dataIndex, elOption, animatableModel, data); + } + + // Always add whatever already added to ensure sequence. + group.add(el); + + return el; +} + +// Usage: +// (1) By default, `elOption.$mergeChildren` is `'byIndex'`, which indicates that +// the existing children will not be removed, and enables the feature that +// update some of the props of some of the children simply by construct +// the returned children of `renderItem` like: +// `var children = group.children = []; children[3] = {opacity: 0.5};` +// (2) If `elOption.$mergeChildren` is `'byName'`, add/update/remove children +// by child.name. But that might be lower performance. +// (3) If `elOption.$mergeChildren` is `false`, the existing children will be +// replaced totally. +// (4) If `!elOption.children`, following the "merge" principle, nothing will happen. +// +// For implementation simpleness, do not provide a direct way to remove sinlge +// child (otherwise the total indicies of the children array have to be modified). +// User can remove a single child by set its `ignore` as `true` or replace +// it by another element, where its `$merge` can be set as `true` if necessary. +function mergeChildren(el, dataIndex, elOption, animatableModel, data) { + var newChildren = elOption.children; + var newLen = newChildren ? newChildren.length : 0; + var mergeChildren = elOption.$mergeChildren; + // `diffChildrenByName` has been deprecated. + var byName = mergeChildren === 'byName' || elOption.diffChildrenByName; + var notMerge = mergeChildren === false; + + // For better performance on roam update, only enter if necessary. + if (!newLen && !byName && !notMerge) { + return; + } + + if (byName) { + diffGroupChildren({ + oldChildren: el.children() || [], + newChildren: newChildren || [], + dataIndex: dataIndex, + animatableModel: animatableModel, + group: el, + data: data + }); + return; + } + + notMerge && el.removeAll(); + + // Mapping children of a group simply by index, which + // might be better performance. + var index = 0; + for (; index < newLen; index++) { + newChildren[index] && doCreateOrUpdate( + el.childAt(index), + dataIndex, + newChildren[index], + animatableModel, + el, + data + ); + } + if (__DEV__) { + assert$1( + !notMerge || el.childCount() === index, + 'MUST NOT contain empty item in children array when `group.$mergeChildren` is `false`.' + ); + } +} + +function diffGroupChildren(context) { + (new DataDiffer( + context.oldChildren, + context.newChildren, + getKey, + getKey, + context + )) + .add(processAddUpdate) + .update(processAddUpdate) + .remove(processRemove) + .execute(); +} + +function getKey(item, idx) { + var name = item && item.name; + return name != null ? name : GROUP_DIFF_PREFIX + idx; +} + +function processAddUpdate(newIndex, oldIndex) { + var context = this.context; + var childOption = newIndex != null ? context.newChildren[newIndex] : null; + var child = oldIndex != null ? context.oldChildren[oldIndex] : null; + + doCreateOrUpdate( + child, + context.dataIndex, + childOption, + context.animatableModel, + context.group, + context.data + ); +} + +function processRemove(oldIndex) { + var context = this.context; + var child = context.oldChildren[oldIndex]; + child && context.group.remove(child); +} + +function getPathData(shape) { + // "d" follows the SVG convention. + return shape && (shape.pathData || shape.d); +} + +function hasOwnPathData(shape) { + return shape && (shape.hasOwnProperty('pathData') || shape.hasOwnProperty('d')); +} + +function hasOwn(host, prop) { + return host && host.hasOwnProperty(prop); +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +// ------------- +// Preprocessor +// ------------- + +registerPreprocessor(function (option) { + var graphicOption = option.graphic; + + // Convert + // {graphic: [{left: 10, type: 'circle'}, ...]} + // or + // {graphic: {left: 10, type: 'circle'}} + // to + // {graphic: [{elements: [{left: 10, type: 'circle'}, ...]}]} + if (isArray(graphicOption)) { + if (!graphicOption[0] || !graphicOption[0].elements) { + option.graphic = [{elements: graphicOption}]; + } + else { + // Only one graphic instance can be instantiated. (We dont + // want that too many views are created in echarts._viewMap) + option.graphic = [option.graphic[0]]; + } + } + else if (graphicOption && !graphicOption.elements) { + option.graphic = [{elements: [graphicOption]}]; + } +}); + +// ------ +// Model +// ------ + +var GraphicModel = extendComponentModel({ + + type: 'graphic', + + defaultOption: { + + // Extra properties for each elements: + // + // left/right/top/bottom: (like 12, '22%', 'center', default undefined) + // If left/rigth is set, shape.x/shape.cx/position will not be used. + // If top/bottom is set, shape.y/shape.cy/position will not be used. + // This mechanism is useful when you want to position a group/element + // against the right side or the center of this container. + // + // width/height: (can only be pixel value, default 0) + // Only be used to specify contianer(group) size, if needed. And + // can not be percentage value (like '33%'). See the reason in the + // layout algorithm below. + // + // bounding: (enum: 'all' (default) | 'raw') + // Specify how to calculate boundingRect when locating. + // 'all': Get uioned and transformed boundingRect + // from both itself and its descendants. + // This mode simplies confining a group of elements in the bounding + // of their ancester container (e.g., using 'right: 0'). + // 'raw': Only use the boundingRect of itself and before transformed. + // This mode is similar to css behavior, which is useful when you + // want an element to be able to overflow its container. (Consider + // a rotated circle needs to be located in a corner.) + // info: custom info. enables user to mount some info on elements and use them + // in event handlers. Update them only when user specified, otherwise, remain. + + // Note: elements is always behind its ancestors in this elements array. + elements: [], + parentId: null + }, + + /** + * Save el options for the sake of the performance (only update modified graphics). + * The order is the same as those in option. (ancesters -> descendants) + * + * @private + * @type {Array.} + */ + _elOptionsToUpdate: null, + + /** + * @override + */ + mergeOption: function (option) { + // Prevent default merge to elements + var elements = this.option.elements; + this.option.elements = null; + + GraphicModel.superApply(this, 'mergeOption', arguments); + + this.option.elements = elements; + }, + + /** + * @override + */ + optionUpdated: function (newOption, isInit) { + var thisOption = this.option; + var newList = (isInit ? thisOption : newOption).elements; + var existList = thisOption.elements = isInit ? [] : thisOption.elements; + + var flattenedList = []; + this._flatten(newList, flattenedList); + + var mappingResult = mappingToExists(existList, flattenedList); + makeIdAndName(mappingResult); + + // Clear elOptionsToUpdate + var elOptionsToUpdate = this._elOptionsToUpdate = []; + + each$1(mappingResult, function (resultItem, index) { + var newElOption = resultItem.option; + + if (__DEV__) { + assert$1( + isObject$1(newElOption) || resultItem.exist, + 'Empty graphic option definition' + ); + } + + if (!newElOption) { + return; + } + + elOptionsToUpdate.push(newElOption); + + setKeyInfoToNewElOption(resultItem, newElOption); + + mergeNewElOptionToExist(existList, index, newElOption); + + setLayoutInfoToExist(existList[index], newElOption); + + }, this); + + // Clean + for (var i = existList.length - 1; i >= 0; i--) { + if (existList[i] == null) { + existList.splice(i, 1); + } + else { + // $action should be volatile, otherwise option gotten from + // `getOption` will contain unexpected $action. + delete existList[i].$action; + } + } + }, + + /** + * Convert + * [{ + * type: 'group', + * id: 'xx', + * children: [{type: 'circle'}, {type: 'polygon'}] + * }] + * to + * [ + * {type: 'group', id: 'xx'}, + * {type: 'circle', parentId: 'xx'}, + * {type: 'polygon', parentId: 'xx'} + * ] + * + * @private + * @param {Array.} optionList option list + * @param {Array.} result result of flatten + * @param {Object} parentOption parent option + */ + _flatten: function (optionList, result, parentOption) { + each$1(optionList, function (option) { + if (!option) { + return; + } + + if (parentOption) { + option.parentOption = parentOption; + } + + result.push(option); + + var children = option.children; + if (option.type === 'group' && children) { + this._flatten(children, result, option); + } + // Deleting for JSON output, and for not affecting group creation. + delete option.children; + }, this); + }, + + // FIXME + // Pass to view using payload? setOption has a payload? + useElOptionsToUpdate: function () { + var els = this._elOptionsToUpdate; + // Clear to avoid render duplicately when zooming. + this._elOptionsToUpdate = null; + return els; + } +}); + +// ----- +// View +// ----- + +extendComponentView({ + + type: 'graphic', + + /** + * @override + */ + init: function (ecModel, api) { + + /** + * @private + * @type {module:zrender/core/util.HashMap} + */ + this._elMap = createHashMap(); + + /** + * @private + * @type {module:echarts/graphic/GraphicModel} + */ + this._lastGraphicModel; + }, + + /** + * @override + */ + render: function (graphicModel, ecModel, api) { + + // Having leveraged between use cases and algorithm complexity, a very + // simple layout mechanism is used: + // The size(width/height) can be determined by itself or its parent (not + // implemented yet), but can not by its children. (Top-down travel) + // The location(x/y) can be determined by the bounding rect of itself + // (can including its descendants or not) and the size of its parent. + // (Bottom-up travel) + + // When `chart.clear()` or `chart.setOption({...}, true)` with the same id, + // view will be reused. + if (graphicModel !== this._lastGraphicModel) { + this._clear(); + } + this._lastGraphicModel = graphicModel; + + this._updateElements(graphicModel); + this._relocate(graphicModel, api); + }, + + /** + * Update graphic elements. + * + * @private + * @param {Object} graphicModel graphic model + */ + _updateElements: function (graphicModel) { + var elOptionsToUpdate = graphicModel.useElOptionsToUpdate(); + + if (!elOptionsToUpdate) { + return; + } + + var elMap = this._elMap; + var rootGroup = this.group; + + // Top-down tranverse to assign graphic settings to each elements. + each$1(elOptionsToUpdate, function (elOption) { + var $action = elOption.$action; + var id = elOption.id; + var existEl = elMap.get(id); + var parentId = elOption.parentId; + var targetElParent = parentId != null ? elMap.get(parentId) : rootGroup; + + var elOptionStyle = elOption.style; + if (elOption.type === 'text' && elOptionStyle) { + // In top/bottom mode, textVerticalAlign should not be used, which cause + // inaccurately locating. + if (elOption.hv && elOption.hv[1]) { + elOptionStyle.textVerticalAlign = elOptionStyle.textBaseline = null; + } + + // Compatible with previous setting: both support fill and textFill, + // stroke and textStroke. + !elOptionStyle.hasOwnProperty('textFill') && elOptionStyle.fill && ( + elOptionStyle.textFill = elOptionStyle.fill + ); + !elOptionStyle.hasOwnProperty('textStroke') && elOptionStyle.stroke && ( + elOptionStyle.textStroke = elOptionStyle.stroke + ); + } + + // Remove unnecessary props to avoid potential problems. + var elOptionCleaned = getCleanedElOption(elOption); + + // For simple, do not support parent change, otherwise reorder is needed. + if (__DEV__) { + existEl && assert$1( + targetElParent === existEl.parent, + 'Changing parent is not supported.' + ); + } + + if (!$action || $action === 'merge') { + existEl + ? existEl.attr(elOptionCleaned) + : createEl$1(id, targetElParent, elOptionCleaned, elMap); + } + else if ($action === 'replace') { + removeEl(existEl, elMap); + createEl$1(id, targetElParent, elOptionCleaned, elMap); + } + else if ($action === 'remove') { + removeEl(existEl, elMap); + } + + var el = elMap.get(id); + if (el) { + el.__ecGraphicWidth = elOption.width; + el.__ecGraphicHeight = elOption.height; + setEventData(el, graphicModel, elOption); + } + }); + }, + + /** + * Locate graphic elements. + * + * @private + * @param {Object} graphicModel graphic model + * @param {module:echarts/ExtensionAPI} api extension API + */ + _relocate: function (graphicModel, api) { + var elOptions = graphicModel.option.elements; + var rootGroup = this.group; + var elMap = this._elMap; + + // Bottom-up tranvese all elements (consider ec resize) to locate elements. + for (var i = elOptions.length - 1; i >= 0; i--) { + var elOption = elOptions[i]; + var el = elMap.get(elOption.id); + + if (!el) { + continue; + } + + var parentEl = el.parent; + var containerInfo = parentEl === rootGroup + ? { + width: api.getWidth(), + height: api.getHeight() + } + : { // Like 'position:absolut' in css, default 0. + width: parentEl.__ecGraphicWidth || 0, + height: parentEl.__ecGraphicHeight || 0 + }; + + positionElement( + el, elOption, containerInfo, null, + {hv: elOption.hv, boundingMode: elOption.bounding} + ); + } + }, + + /** + * Clear all elements. + * + * @private + */ + _clear: function () { + var elMap = this._elMap; + elMap.each(function (el) { + removeEl(el, elMap); + }); + this._elMap = createHashMap(); + }, + + /** + * @override + */ + dispose: function () { + this._clear(); + } +}); + +function createEl$1(id, targetElParent, elOption, elMap) { + var graphicType = elOption.type; + + if (__DEV__) { + assert$1(graphicType, 'graphic type MUST be set'); + } + + var Clz = graphic[graphicType.charAt(0).toUpperCase() + graphicType.slice(1)]; + + if (__DEV__) { + assert$1(Clz, 'graphic type can not be found'); + } + + var el = new Clz(elOption); + targetElParent.add(el); + elMap.set(id, el); + el.__ecGraphicId = id; +} + +function removeEl(existEl, elMap) { + var existElParent = existEl && existEl.parent; + if (existElParent) { + existEl.type === 'group' && existEl.traverse(function (el) { + removeEl(el, elMap); + }); + elMap.removeKey(existEl.__ecGraphicId); + existElParent.remove(existEl); + } +} + +// Remove unnecessary props to avoid potential problems. +function getCleanedElOption(elOption) { + elOption = extend({}, elOption); + each$1( + ['id', 'parentId', '$action', 'hv', 'bounding'].concat(LOCATION_PARAMS), + function (name) { + delete elOption[name]; + } + ); + return elOption; +} + +function isSetLoc(obj, props) { + var isSet; + each$1(props, function (prop) { + obj[prop] != null && obj[prop] !== 'auto' && (isSet = true); + }); + return isSet; +} + +function setKeyInfoToNewElOption(resultItem, newElOption) { + var existElOption = resultItem.exist; + + // Set id and type after id assigned. + newElOption.id = resultItem.keyInfo.id; + !newElOption.type && existElOption && (newElOption.type = existElOption.type); + + // Set parent id if not specified + if (newElOption.parentId == null) { + var newElParentOption = newElOption.parentOption; + if (newElParentOption) { + newElOption.parentId = newElParentOption.id; + } + else if (existElOption) { + newElOption.parentId = existElOption.parentId; + } + } + + // Clear + newElOption.parentOption = null; +} + +function mergeNewElOptionToExist(existList, index, newElOption) { + // Update existing options, for `getOption` feature. + var newElOptCopy = extend({}, newElOption); + var existElOption = existList[index]; + + var $action = newElOption.$action || 'merge'; + if ($action === 'merge') { + if (existElOption) { + + if (__DEV__) { + var newType = newElOption.type; + assert$1( + !newType || existElOption.type === newType, + 'Please set $action: "replace" to change `type`' + ); + } + + // We can ensure that newElOptCopy and existElOption are not + // the same object, so `merge` will not change newElOptCopy. + merge(existElOption, newElOptCopy, true); + // Rigid body, use ignoreSize. + mergeLayoutParam(existElOption, newElOptCopy, {ignoreSize: true}); + // Will be used in render. + copyLayoutParams(newElOption, existElOption); + } + else { + existList[index] = newElOptCopy; + } + } + else if ($action === 'replace') { + existList[index] = newElOptCopy; + } + else if ($action === 'remove') { + // null will be cleaned later. + existElOption && (existList[index] = null); + } +} + +function setLayoutInfoToExist(existItem, newElOption) { + if (!existItem) { + return; + } + existItem.hv = newElOption.hv = [ + // Rigid body, dont care `width`. + isSetLoc(newElOption, ['left', 'right']), + // Rigid body, dont care `height`. + isSetLoc(newElOption, ['top', 'bottom']) + ]; + // Give default group size. Otherwise layout error may occur. + if (existItem.type === 'group') { + existItem.width == null && (existItem.width = newElOption.width = 0); + existItem.height == null && (existItem.height = newElOption.height = 0); + } +} + +function setEventData(el, graphicModel, elOption) { + var eventData = el.eventData; + // Simple optimize for large amount of elements that no need event. + if (!el.silent && !el.ignore && !eventData) { + eventData = el.eventData = { + componentType: 'graphic', + componentIndex: graphicModel.componentIndex, + name: el.name + }; + } + + // `elOption.info` enables user to mount some info on + // elements and use them in event handlers. + if (eventData) { + eventData.info = el.info; + } +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var LegendModel = extendComponentModel({ + + type: 'legend.plain', + + dependencies: ['series'], + + layoutMode: { + type: 'box', + // legend.width/height are maxWidth/maxHeight actually, + // whereas realy width/height is calculated by its content. + // (Setting {left: 10, right: 10} does not make sense). + // So consider the case: + // `setOption({legend: {left: 10});` + // then `setOption({legend: {right: 10});` + // The previous `left` should be cleared by setting `ignoreSize`. + ignoreSize: true + }, + + init: function (option, parentModel, ecModel) { + this.mergeDefaultAndTheme(option, ecModel); + + option.selected = option.selected || {}; + }, + + mergeOption: function (option) { + LegendModel.superCall(this, 'mergeOption', option); + }, + + optionUpdated: function () { + this._updateData(this.ecModel); + + var legendData = this._data; + + // If selectedMode is single, try to select one + if (legendData[0] && this.get('selectedMode') === 'single') { + var hasSelected = false; + // If has any selected in option.selected + for (var i = 0; i < legendData.length; i++) { + var name = legendData[i].get('name'); + if (this.isSelected(name)) { + // Force to unselect others + this.select(name); + hasSelected = true; + break; + } + } + // Try select the first if selectedMode is single + !hasSelected && this.select(legendData[0].get('name')); + } + }, + + _updateData: function (ecModel) { + var potentialData = []; + var availableNames = []; + + ecModel.eachRawSeries(function (seriesModel) { + var seriesName = seriesModel.name; + availableNames.push(seriesName); + var isPotential; + + if (seriesModel.legendDataProvider) { + var data = seriesModel.legendDataProvider(); + var names = data.mapArray(data.getName); + + if (!ecModel.isSeriesFiltered(seriesModel)) { + availableNames = availableNames.concat(names); + } + + if (names.length) { + potentialData = potentialData.concat(names); + } + else { + isPotential = true; + } + } + else { + isPotential = true; + } + + if (isPotential && isNameSpecified(seriesModel)) { + potentialData.push(seriesModel.name); + } + }); + + /** + * @type {Array.} + * @private + */ + this._availableNames = availableNames; + + // If legend.data not specified in option, use availableNames as data, + // which is convinient for user preparing option. + var rawData = this.get('data') || potentialData; + + var legendData = map(rawData, function (dataItem) { + // Can be string or number + if (typeof dataItem === 'string' || typeof dataItem === 'number') { + dataItem = { + name: dataItem + }; + } + return new Model(dataItem, this, this.ecModel); + }, this); + + /** + * @type {Array.} + * @private + */ + this._data = legendData; + }, + + /** + * @return {Array.} + */ + getData: function () { + return this._data; + }, + + /** + * @param {string} name + */ + select: function (name) { + var selected = this.option.selected; + var selectedMode = this.get('selectedMode'); + if (selectedMode === 'single') { + var data = this._data; + each$1(data, function (dataItem) { + selected[dataItem.get('name')] = false; + }); + } + selected[name] = true; + }, + + /** + * @param {string} name + */ + unSelect: function (name) { + if (this.get('selectedMode') !== 'single') { + this.option.selected[name] = false; + } + }, + + /** + * @param {string} name + */ + toggleSelected: function (name) { + var selected = this.option.selected; + // Default is true + if (!selected.hasOwnProperty(name)) { + selected[name] = true; + } + this[selected[name] ? 'unSelect' : 'select'](name); + }, + + /** + * @param {string} name + */ + isSelected: function (name) { + var selected = this.option.selected; + return !(selected.hasOwnProperty(name) && !selected[name]) + && indexOf(this._availableNames, name) >= 0; + }, + + defaultOption: { + // 一级层叠 + zlevel: 0, + // 二级层叠 + z: 4, + show: true, + + // 布局方式,默认为水平布局,可选为: + // 'horizontal' | 'vertical' + orient: 'horizontal', + + left: 'center', + // right: 'center', + + top: 0, + // bottom: null, + + // 水平对齐 + // 'auto' | 'left' | 'right' + // 默认为 'auto', 根据 x 的位置判断是左对齐还是右对齐 + align: 'auto', + + backgroundColor: 'rgba(0,0,0,0)', + // 图例边框颜色 + borderColor: '#ccc', + borderRadius: 0, + // 图例边框线宽,单位px,默认为0(无边框) + borderWidth: 0, + // 图例内边距,单位px,默认各方向内边距为5, + // 接受数组分别设定上右下左边距,同css + padding: 5, + // 各个item之间的间隔,单位px,默认为10, + // 横向布局时为水平间隔,纵向布局时为纵向间隔 + itemGap: 10, + // 图例图形宽度 + itemWidth: 25, + // 图例图形高度 + itemHeight: 14, + + // 图例关闭时候的颜色 + inactiveColor: '#ccc', + + textStyle: { + // 图例文字颜色 + color: '#333' + }, + // formatter: '', + // 选择模式,默认开启图例开关 + selectedMode: true, + // 配置默认选中状态,可配合LEGEND.SELECTED事件做动态数据载入 + // selected: null, + // 图例内容(详见legend.data,数组中每一项代表一个item + // data: [], + + // Tooltip 相关配置 + tooltip: { + show: false + } + } +}); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +function legendSelectActionHandler(methodName, payload, ecModel) { + var selectedMap = {}; + var isToggleSelect = methodName === 'toggleSelected'; + var isSelected; + // Update all legend components + ecModel.eachComponent('legend', function (legendModel) { + if (isToggleSelect && isSelected != null) { + // Force other legend has same selected status + // Or the first is toggled to true and other are toggled to false + // In the case one legend has some item unSelected in option. And if other legend + // doesn't has the item, they will assume it is selected. + legendModel[isSelected ? 'select' : 'unSelect'](payload.name); + } + else { + legendModel[methodName](payload.name); + isSelected = legendModel.isSelected(payload.name); + } + var legendData = legendModel.getData(); + each$1(legendData, function (model) { + var name = model.get('name'); + // Wrap element + if (name === '\n' || name === '') { + return; + } + var isItemSelected = legendModel.isSelected(name); + if (selectedMap.hasOwnProperty(name)) { + // Unselected if any legend is unselected + selectedMap[name] = selectedMap[name] && isItemSelected; + } + else { + selectedMap[name] = isItemSelected; + } + }); + }); + // Return the event explicitly + return { + name: payload.name, + selected: selectedMap + }; +} +/** + * @event legendToggleSelect + * @type {Object} + * @property {string} type 'legendToggleSelect' + * @property {string} [from] + * @property {string} name Series name or data item name + */ +registerAction( + 'legendToggleSelect', 'legendselectchanged', + curry(legendSelectActionHandler, 'toggleSelected') +); + +/** + * @event legendSelect + * @type {Object} + * @property {string} type 'legendSelect' + * @property {string} name Series name or data item name + */ +registerAction( + 'legendSelect', 'legendselected', + curry(legendSelectActionHandler, 'select') +); + +/** + * @event legendUnSelect + * @type {Object} + * @property {string} type 'legendUnSelect' + * @property {string} name Series name or data item name + */ +registerAction( + 'legendUnSelect', 'legendunselected', + curry(legendSelectActionHandler, 'unSelect') +); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/** + * Layout list like component. + * It will box layout each items in group of component and then position the whole group in the viewport + * @param {module:zrender/group/Group} group + * @param {module:echarts/model/Component} componentModel + * @param {module:echarts/ExtensionAPI} + */ +function layout$3(group, componentModel, api) { + var boxLayoutParams = componentModel.getBoxLayoutParams(); + var padding = componentModel.get('padding'); + var viewportSize = {width: api.getWidth(), height: api.getHeight()}; + + var rect = getLayoutRect( + boxLayoutParams, + viewportSize, + padding + ); + + box( + componentModel.get('orient'), + group, + componentModel.get('itemGap'), + rect.width, + rect.height + ); + + positionElement( + group, + boxLayoutParams, + viewportSize, + padding + ); +} + +function makeBackground(rect, componentModel) { + var padding = normalizeCssArray$1( + componentModel.get('padding') + ); + var style = componentModel.getItemStyle(['color', 'opacity']); + style.fill = componentModel.get('backgroundColor'); + var rect = new Rect({ + shape: { + x: rect.x - padding[3], + y: rect.y - padding[0], + width: rect.width + padding[1] + padding[3], + height: rect.height + padding[0] + padding[2], + r: componentModel.get('borderRadius') + }, + style: style, + silent: true, + z2: -1 + }); + // FIXME + // `subPixelOptimizeRect` may bring some gap between edge of viewpart + // and background rect when setting like `left: 0`, `top: 0`. + // graphic.subPixelOptimizeRect(rect); + + return rect; +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var curry$4 = curry; +var each$16 = each$1; +var Group$3 = Group; + +var LegendView = extendComponentView({ + + type: 'legend.plain', + + newlineDisabled: false, + + /** + * @override + */ + init: function () { + + /** + * @private + * @type {module:zrender/container/Group} + */ + this.group.add(this._contentGroup = new Group$3()); + + /** + * @private + * @type {module:zrender/Element} + */ + this._backgroundEl; + + /** + * If first rendering, `contentGroup.position` is [0, 0], which + * does not make sense and may cause unexepcted animation if adopted. + * @private + * @type {boolean} + */ + this._isFirstRender = true; + }, + + /** + * @protected + */ + getContentGroup: function () { + return this._contentGroup; + }, + + /** + * @override + */ + render: function (legendModel, ecModel, api) { + var isFirstRender = this._isFirstRender; + this._isFirstRender = false; + + this.resetInner(); + + if (!legendModel.get('show', true)) { + return; + } + + var itemAlign = legendModel.get('align'); + if (!itemAlign || itemAlign === 'auto') { + itemAlign = ( + legendModel.get('left') === 'right' + && legendModel.get('orient') === 'vertical' + ) ? 'right' : 'left'; + } + + this.renderInner(itemAlign, legendModel, ecModel, api); + + // Perform layout. + var positionInfo = legendModel.getBoxLayoutParams(); + var viewportSize = {width: api.getWidth(), height: api.getHeight()}; + var padding = legendModel.get('padding'); + + var maxSize = getLayoutRect(positionInfo, viewportSize, padding); + + var mainRect = this.layoutInner(legendModel, itemAlign, maxSize, isFirstRender); + + // Place mainGroup, based on the calculated `mainRect`. + var layoutRect = getLayoutRect( + defaults({width: mainRect.width, height: mainRect.height}, positionInfo), + viewportSize, + padding + ); + this.group.attr('position', [layoutRect.x - mainRect.x, layoutRect.y - mainRect.y]); + + // Render background after group is layout. + this.group.add( + this._backgroundEl = makeBackground(mainRect, legendModel) + ); + }, + + /** + * @protected + */ + resetInner: function () { + this.getContentGroup().removeAll(); + this._backgroundEl && this.group.remove(this._backgroundEl); + }, + + /** + * @protected + */ + renderInner: function (itemAlign, legendModel, ecModel, api) { + var contentGroup = this.getContentGroup(); + var legendDrawnMap = createHashMap(); + var selectMode = legendModel.get('selectedMode'); + + var excludeSeriesId = []; + ecModel.eachRawSeries(function (seriesModel) { + !seriesModel.get('legendHoverLink') && excludeSeriesId.push(seriesModel.id); + }); + + each$16(legendModel.getData(), function (itemModel, dataIndex) { + var name = itemModel.get('name'); + + // Use empty string or \n as a newline string + if (!this.newlineDisabled && (name === '' || name === '\n')) { + contentGroup.add(new Group$3({ + newline: true + })); + return; + } + + // Representitive series. + var seriesModel = ecModel.getSeriesByName(name)[0]; + + if (legendDrawnMap.get(name)) { + // Have been drawed + return; + } + + // Series legend + if (seriesModel) { + var data = seriesModel.getData(); + var color = data.getVisual('color'); + + // If color is a callback function + if (typeof color === 'function') { + // Use the first data + color = color(seriesModel.getDataParams(0)); + } + + // Using rect symbol defaultly + var legendSymbolType = data.getVisual('legendSymbol') || 'roundRect'; + var symbolType = data.getVisual('symbol'); + + var itemGroup = this._createItem( + name, dataIndex, itemModel, legendModel, + legendSymbolType, symbolType, + itemAlign, color, + selectMode + ); + + itemGroup.on('click', curry$4(dispatchSelectAction, name, api)) + .on('mouseover', curry$4(dispatchHighlightAction, seriesModel.name, null, api, excludeSeriesId)) + .on('mouseout', curry$4(dispatchDownplayAction, seriesModel.name, null, api, excludeSeriesId)); + + legendDrawnMap.set(name, true); + } + else { + // Data legend of pie, funnel + ecModel.eachRawSeries(function (seriesModel) { + // In case multiple series has same data name + if (legendDrawnMap.get(name)) { + return; + } + + if (seriesModel.legendDataProvider) { + var data = seriesModel.legendDataProvider(); + var idx = data.indexOfName(name); + if (idx < 0) { + return; + } + + var color = data.getItemVisual(idx, 'color'); + + var legendSymbolType = 'roundRect'; + + var itemGroup = this._createItem( + name, dataIndex, itemModel, legendModel, + legendSymbolType, null, + itemAlign, color, + selectMode + ); + + // FIXME: consider different series has items with the same name. + itemGroup.on('click', curry$4(dispatchSelectAction, name, api)) + // Should not specify the series name, consider legend controls + // more than one pie series. + .on('mouseover', curry$4(dispatchHighlightAction, null, name, api, excludeSeriesId)) + .on('mouseout', curry$4(dispatchDownplayAction, null, name, api, excludeSeriesId)); + + legendDrawnMap.set(name, true); + } + + }, this); + } + + if (__DEV__) { + if (!legendDrawnMap.get(name)) { + console.warn( + name + ' series not exists. Legend data should be same with series name or data name.' + ); + } + } + }, this); + }, + + _createItem: function ( + name, dataIndex, itemModel, legendModel, + legendSymbolType, symbolType, + itemAlign, color, selectMode + ) { + var itemWidth = legendModel.get('itemWidth'); + var itemHeight = legendModel.get('itemHeight'); + var inactiveColor = legendModel.get('inactiveColor'); + var symbolKeepAspect = legendModel.get('symbolKeepAspect'); + + var isSelected = legendModel.isSelected(name); + var itemGroup = new Group$3(); + + var textStyleModel = itemModel.getModel('textStyle'); + + var itemIcon = itemModel.get('icon'); + + var tooltipModel = itemModel.getModel('tooltip'); + var legendGlobalTooltipModel = tooltipModel.parentModel; + + // Use user given icon first + legendSymbolType = itemIcon || legendSymbolType; + itemGroup.add(createSymbol( + legendSymbolType, + 0, + 0, + itemWidth, + itemHeight, + isSelected ? color : inactiveColor, + // symbolKeepAspect default true for legend + symbolKeepAspect == null ? true : symbolKeepAspect + )); + + // Compose symbols + // PENDING + if (!itemIcon && symbolType + // At least show one symbol, can't be all none + && ((symbolType !== legendSymbolType) || symbolType === 'none') + ) { + var size = itemHeight * 0.8; + if (symbolType === 'none') { + symbolType = 'circle'; + } + // Put symbol in the center + itemGroup.add(createSymbol( + symbolType, + (itemWidth - size) / 2, + (itemHeight - size) / 2, + size, + size, + isSelected ? color : inactiveColor, + // symbolKeepAspect default true for legend + symbolKeepAspect == null ? true : symbolKeepAspect + )); + } + + var textX = itemAlign === 'left' ? itemWidth + 5 : -5; + var textAlign = itemAlign; + + var formatter = legendModel.get('formatter'); + var content = name; + if (typeof formatter === 'string' && formatter) { + content = formatter.replace('{name}', name != null ? name : ''); + } + else if (typeof formatter === 'function') { + content = formatter(name); + } + + itemGroup.add(new Text({ + style: setTextStyle({}, textStyleModel, { + text: content, + x: textX, + y: itemHeight / 2, + textFill: isSelected ? textStyleModel.getTextColor() : inactiveColor, + textAlign: textAlign, + textVerticalAlign: 'middle' + }) + })); + + // Add a invisible rect to increase the area of mouse hover + var hitRect = new Rect({ + shape: itemGroup.getBoundingRect(), + invisible: true, + tooltip: tooltipModel.get('show') ? extend({ + content: name, + // Defaul formatter + formatter: legendGlobalTooltipModel.get('formatter', true) || function () { + return name; + }, + formatterParams: { + componentType: 'legend', + legendIndex: legendModel.componentIndex, + name: name, + $vars: ['name'] + } + }, tooltipModel.option) : null + }); + itemGroup.add(hitRect); + + itemGroup.eachChild(function (child) { + child.silent = true; + }); + + hitRect.silent = !selectMode; + + this.getContentGroup().add(itemGroup); + + setHoverStyle(itemGroup); + + itemGroup.__legendDataIndex = dataIndex; + + return itemGroup; + }, + + /** + * @protected + */ + layoutInner: function (legendModel, itemAlign, maxSize) { + var contentGroup = this.getContentGroup(); + + // Place items in contentGroup. + box( + legendModel.get('orient'), + contentGroup, + legendModel.get('itemGap'), + maxSize.width, + maxSize.height + ); + + var contentRect = contentGroup.getBoundingRect(); + contentGroup.attr('position', [-contentRect.x, -contentRect.y]); + + return this.group.getBoundingRect(); + }, + + /** + * @protected + */ + remove: function () { + this.getContentGroup().removeAll(); + this._isFirstRender = true; + } + +}); + +function dispatchSelectAction(name, api) { + api.dispatchAction({ + type: 'legendToggleSelect', + name: name + }); +} + +function dispatchHighlightAction(seriesName, dataName, api, excludeSeriesId) { + // If element hover will move to a hoverLayer. + var el = api.getZr().storage.getDisplayList()[0]; + if (!(el && el.useHoverLayer)) { + api.dispatchAction({ + type: 'highlight', + seriesName: seriesName, + name: dataName, + excludeSeriesId: excludeSeriesId + }); + } +} + +function dispatchDownplayAction(seriesName, dataName, api, excludeSeriesId) { + // If element hover will move to a hoverLayer. + var el = api.getZr().storage.getDisplayList()[0]; + if (!(el && el.useHoverLayer)) { + api.dispatchAction({ + type: 'downplay', + seriesName: seriesName, + name: dataName, + excludeSeriesId: excludeSeriesId + }); + } +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var legendFilter = function (ecModel) { + + var legendModels = ecModel.findComponents({ + mainType: 'legend' + }); + if (legendModels && legendModels.length) { + ecModel.filterSeries(function (series) { + // If in any legend component the status is not selected. + // Because in legend series is assumed selected when it is not in the legend data. + for (var i = 0; i < legendModels.length; i++) { + if (!legendModels[i].isSelected(series.name)) { + return false; + } + } + return true; + }); + } + +}; + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + + +// Do not contain scrollable legend, for sake of file size. + +// Series Filter +registerProcessor(legendFilter); + +ComponentModel.registerSubTypeDefaulter('legend', function () { + // Default 'plain' when no type specified. + return 'plain'; +}); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var ScrollableLegendModel = LegendModel.extend({ + + type: 'legend.scroll', + + /** + * @param {number} scrollDataIndex + */ + setScrollDataIndex: function (scrollDataIndex) { + this.option.scrollDataIndex = scrollDataIndex; + }, + + defaultOption: { + scrollDataIndex: 0, + pageButtonItemGap: 5, + pageButtonGap: null, + pageButtonPosition: 'end', // 'start' or 'end' + pageFormatter: '{current}/{total}', // If null/undefined, do not show page. + pageIcons: { + horizontal: ['M0,0L12,-10L12,10z', 'M0,0L-12,-10L-12,10z'], + vertical: ['M0,0L20,0L10,-20z', 'M0,0L20,0L10,20z'] + }, + pageIconColor: '#2f4554', + pageIconInactiveColor: '#aaa', + pageIconSize: 15, // Can be [10, 3], which represents [width, height] + pageTextStyle: { + color: '#333' + }, + + animationDurationUpdate: 800 + }, + + /** + * @override + */ + init: function (option, parentModel, ecModel, extraOpt) { + var inputPositionParams = getLayoutParams(option); + + ScrollableLegendModel.superCall(this, 'init', option, parentModel, ecModel, extraOpt); + + mergeAndNormalizeLayoutParams(this, option, inputPositionParams); + }, + + /** + * @override + */ + mergeOption: function (option, extraOpt) { + ScrollableLegendModel.superCall(this, 'mergeOption', option, extraOpt); + + mergeAndNormalizeLayoutParams(this, this.option, option); + }, + + getOrient: function () { + return this.get('orient') === 'vertical' + ? {index: 1, name: 'vertical'} + : {index: 0, name: 'horizontal'}; + } + +}); + +// Do not `ignoreSize` to enable setting {left: 10, right: 10}. +function mergeAndNormalizeLayoutParams(legendModel, target, raw) { + var orient = legendModel.getOrient(); + var ignoreSize = [1, 1]; + ignoreSize[orient.index] = 0; + mergeLayoutParam(target, raw, { + type: 'box', ignoreSize: ignoreSize + }); +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/** + * Separate legend and scrollable legend to reduce package size. + */ + +var Group$4 = Group; + +var WH$1 = ['width', 'height']; +var XY$1 = ['x', 'y']; + +var ScrollableLegendView = LegendView.extend({ + + type: 'legend.scroll', + + newlineDisabled: true, + + init: function () { + + ScrollableLegendView.superCall(this, 'init'); + + /** + * @private + * @type {number} For `scroll`. + */ + this._currentIndex = 0; + + /** + * @private + * @type {module:zrender/container/Group} + */ + this.group.add(this._containerGroup = new Group$4()); + this._containerGroup.add(this.getContentGroup()); + + /** + * @private + * @type {module:zrender/container/Group} + */ + this.group.add(this._controllerGroup = new Group$4()); + + /** + * + * @private + */ + this._showController; + }, + + /** + * @override + */ + resetInner: function () { + ScrollableLegendView.superCall(this, 'resetInner'); + + this._controllerGroup.removeAll(); + this._containerGroup.removeClipPath(); + this._containerGroup.__rectSize = null; + }, + + /** + * @override + */ + renderInner: function (itemAlign, legendModel, ecModel, api) { + var me = this; + + // Render content items. + ScrollableLegendView.superCall(this, 'renderInner', itemAlign, legendModel, ecModel, api); + + var controllerGroup = this._controllerGroup; + + // FIXME: support be 'auto' adapt to size number text length, + // e.g., '3/12345' should not overlap with the control arrow button. + var pageIconSize = legendModel.get('pageIconSize', true); + if (!isArray(pageIconSize)) { + pageIconSize = [pageIconSize, pageIconSize]; + } + + createPageButton('pagePrev', 0); + + var pageTextStyleModel = legendModel.getModel('pageTextStyle'); + controllerGroup.add(new Text({ + name: 'pageText', + style: { + textFill: pageTextStyleModel.getTextColor(), + font: pageTextStyleModel.getFont(), + textVerticalAlign: 'middle', + textAlign: 'center' + }, + silent: true + })); + + createPageButton('pageNext', 1); + + function createPageButton(name, iconIdx) { + var pageDataIndexName = name + 'DataIndex'; + var icon = createIcon( + legendModel.get('pageIcons', true)[legendModel.getOrient().name][iconIdx], + { + // Buttons will be created in each render, so we do not need + // to worry about avoiding using legendModel kept in scope. + onclick: bind( + me._pageGo, me, pageDataIndexName, legendModel, api + ) + }, + { + x: -pageIconSize[0] / 2, + y: -pageIconSize[1] / 2, + width: pageIconSize[0], + height: pageIconSize[1] + } + ); + icon.name = name; + controllerGroup.add(icon); + } + }, + + /** + * @override + */ + layoutInner: function (legendModel, itemAlign, maxSize, isFirstRender) { + var contentGroup = this.getContentGroup(); + var containerGroup = this._containerGroup; + var controllerGroup = this._controllerGroup; + + var orientIdx = legendModel.getOrient().index; + var wh = WH$1[orientIdx]; + var hw = WH$1[1 - orientIdx]; + var yx = XY$1[1 - orientIdx]; + + // Place items in contentGroup. + box( + legendModel.get('orient'), + contentGroup, + legendModel.get('itemGap'), + !orientIdx ? null : maxSize.width, + orientIdx ? null : maxSize.height + ); + + box( + // Buttons in controller are layout always horizontally. + 'horizontal', + controllerGroup, + legendModel.get('pageButtonItemGap', true) + ); + + var contentRect = contentGroup.getBoundingRect(); + var controllerRect = controllerGroup.getBoundingRect(); + var showController = this._showController = contentRect[wh] > maxSize[wh]; + + var contentPos = [-contentRect.x, -contentRect.y]; + // Remain contentPos when scroll animation perfroming. + // If first rendering, `contentGroup.position` is [0, 0], which + // does not make sense and may cause unexepcted animation if adopted. + if (!isFirstRender) { + contentPos[orientIdx] = contentGroup.position[orientIdx]; + } + + // Layout container group based on 0. + var containerPos = [0, 0]; + var controllerPos = [-controllerRect.x, -controllerRect.y]; + var pageButtonGap = retrieve2( + legendModel.get('pageButtonGap', true), legendModel.get('itemGap', true) + ); + + // Place containerGroup and controllerGroup and contentGroup. + if (showController) { + var pageButtonPosition = legendModel.get('pageButtonPosition', true); + // controller is on the right / bottom. + if (pageButtonPosition === 'end') { + controllerPos[orientIdx] += maxSize[wh] - controllerRect[wh]; + } + // controller is on the left / top. + else { + containerPos[orientIdx] += controllerRect[wh] + pageButtonGap; + } + } + + // Always align controller to content as 'middle'. + controllerPos[1 - orientIdx] += contentRect[hw] / 2 - controllerRect[hw] / 2; + + contentGroup.attr('position', contentPos); + containerGroup.attr('position', containerPos); + controllerGroup.attr('position', controllerPos); + + // Calculate `mainRect` and set `clipPath`. + // mainRect should not be calculated by `this.group.getBoundingRect()` + // for sake of the overflow. + var mainRect = this.group.getBoundingRect(); + var mainRect = {x: 0, y: 0}; + // Consider content may be overflow (should be clipped). + mainRect[wh] = showController ? maxSize[wh] : contentRect[wh]; + mainRect[hw] = Math.max(contentRect[hw], controllerRect[hw]); + // `containerRect[yx] + containerPos[1 - orientIdx]` is 0. + mainRect[yx] = Math.min(0, controllerRect[yx] + controllerPos[1 - orientIdx]); + + containerGroup.__rectSize = maxSize[wh]; + if (showController) { + var clipShape = {x: 0, y: 0}; + clipShape[wh] = Math.max(maxSize[wh] - controllerRect[wh] - pageButtonGap, 0); + clipShape[hw] = mainRect[hw]; + containerGroup.setClipPath(new Rect({shape: clipShape})); + // Consider content may be larger than container, container rect + // can not be obtained from `containerGroup.getBoundingRect()`. + containerGroup.__rectSize = clipShape[wh]; + } + else { + // Do not remove or ignore controller. Keep them set as place holders. + controllerGroup.eachChild(function (child) { + child.attr({invisible: true, silent: true}); + }); + } + + // Content translate animation. + var pageInfo = this._getPageInfo(legendModel); + pageInfo.pageIndex != null && updateProps( + contentGroup, + {position: pageInfo.contentPosition}, + // When switch from "show controller" to "not show controller", view should be + // updated immediately without animation, otherwise causes weird efffect. + showController ? legendModel : false + ); + + this._updatePageInfoView(legendModel, pageInfo); + + return mainRect; + }, + + _pageGo: function (to, legendModel, api) { + var scrollDataIndex = this._getPageInfo(legendModel)[to]; + + scrollDataIndex != null && api.dispatchAction({ + type: 'legendScroll', + scrollDataIndex: scrollDataIndex, + legendId: legendModel.id + }); + }, + + _updatePageInfoView: function (legendModel, pageInfo) { + var controllerGroup = this._controllerGroup; + + each$1(['pagePrev', 'pageNext'], function (name) { + var canJump = pageInfo[name + 'DataIndex'] != null; + var icon = controllerGroup.childOfName(name); + if (icon) { + icon.setStyle( + 'fill', + canJump + ? legendModel.get('pageIconColor', true) + : legendModel.get('pageIconInactiveColor', true) + ); + icon.cursor = canJump ? 'pointer' : 'default'; + } + }); + + var pageText = controllerGroup.childOfName('pageText'); + var pageFormatter = legendModel.get('pageFormatter'); + var pageIndex = pageInfo.pageIndex; + var current = pageIndex != null ? pageIndex + 1 : 0; + var total = pageInfo.pageCount; + + pageText && pageFormatter && pageText.setStyle( + 'text', + isString(pageFormatter) + ? pageFormatter.replace('{current}', current).replace('{total}', total) + : pageFormatter({current: current, total: total}) + ); + }, + + /** + * @param {module:echarts/model/Model} legendModel + * @return {Object} { + * contentPosition: Array., null when data item not found. + * pageIndex: number, null when data item not found. + * pageCount: number, always be a number, can be 0. + * pagePrevDataIndex: number, null when no next page. + * pageNextDataIndex: number, null when no previous page. + * } + */ + _getPageInfo: function (legendModel) { + var scrollDataIndex = legendModel.get('scrollDataIndex', true); + var contentGroup = this.getContentGroup(); + var containerRectSize = this._containerGroup.__rectSize; + var orientIdx = legendModel.getOrient().index; + var wh = WH$1[orientIdx]; + var xy = XY$1[orientIdx]; + var targetItemIndex = this._findTargetItemIndex(scrollDataIndex); + var children = contentGroup.children(); + var targetItem = children[targetItemIndex]; + var itemCount = children.length; + var pCount = !itemCount ? 0 : 1; + + var result = { + contentPosition: contentGroup.position.slice(), + pageCount: pCount, + pageIndex: pCount - 1, + pagePrevDataIndex: null, + pageNextDataIndex: null + }; + + if (!targetItem) { + return result; + } + + var targetItemInfo = getItemInfo(targetItem); + result.contentPosition[orientIdx] = -targetItemInfo.s; + + // Strategy: + // (1) Always align based on the left/top most item. + // (2) It is user-friendly that the last item shown in the + // current window is shown at the begining of next window. + // Otherwise if half of the last item is cut by the window, + // it will have no chance to display entirely. + // (3) Consider that item size probably be different, we + // have calculate pageIndex by size rather than item index, + // and we can not get page index directly by division. + // (4) The window is to narrow to contain more than + // one item, we should make sure that the page can be fliped. + + for (var i = targetItemIndex + 1, + winStartItemInfo = targetItemInfo, + winEndItemInfo = targetItemInfo, + currItemInfo = null; + i <= itemCount; + ++i + ) { + currItemInfo = getItemInfo(children[i]); + if ( + // Half of the last item is out of the window. + (!currItemInfo && winEndItemInfo.e > winStartItemInfo.s + containerRectSize) + // If the current item does not intersect with the window, the new page + // can be started at the current item or the last item. + || (currItemInfo && !intersect(currItemInfo, winStartItemInfo.s)) + ) { + if (winEndItemInfo.i > winStartItemInfo.i) { + winStartItemInfo = winEndItemInfo; + } + else { // e.g., when page size is smaller than item size. + winStartItemInfo = currItemInfo; + } + if (winStartItemInfo) { + if (result.pageNextDataIndex == null) { + result.pageNextDataIndex = winStartItemInfo.i; + } + ++result.pageCount; + } + } + winEndItemInfo = currItemInfo; + } + + for (var i = targetItemIndex - 1, + winStartItemInfo = targetItemInfo, + winEndItemInfo = targetItemInfo, + currItemInfo = null; + i >= -1; + --i + ) { + currItemInfo = getItemInfo(children[i]); + if ( + // If the the end item does not intersect with the window started + // from the current item, a page can be settled. + (!currItemInfo || !intersect(winEndItemInfo, currItemInfo.s)) + // e.g., when page size is smaller than item size. + && winStartItemInfo.i < winEndItemInfo.i + ) { + winEndItemInfo = winStartItemInfo; + if (result.pagePrevDataIndex == null) { + result.pagePrevDataIndex = winStartItemInfo.i; + } + ++result.pageCount; + ++result.pageIndex; + } + winStartItemInfo = currItemInfo; + } + + return result; + + function getItemInfo(el) { + if (el) { + var itemRect = el.getBoundingRect(); + var start = itemRect[xy] + el.position[orientIdx]; + return { + s: start, + e: start + itemRect[wh], + i: el.__legendDataIndex + }; + } + } + + function intersect(itemInfo, winStart) { + return itemInfo.e >= winStart && itemInfo.s <= winStart + containerRectSize; + } + }, + + _findTargetItemIndex: function (targetDataIndex) { + var index; + var contentGroup = this.getContentGroup(); + if (this._showController) { + contentGroup.eachChild(function (child, idx) { + if (child.__legendDataIndex === targetDataIndex) { + index = idx; + } + }); + } + else { + index = 0; + } + return index; + } + +}); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/** + * @event legendScroll + * @type {Object} + * @property {string} type 'legendScroll' + * @property {string} scrollDataIndex + */ +registerAction( + 'legendScroll', 'legendscroll', + function (payload, ecModel) { + var scrollDataIndex = payload.scrollDataIndex; + + scrollDataIndex != null && ecModel.eachComponent( + {mainType: 'legend', subType: 'scroll', query: payload}, + function (legendModel) { + legendModel.setScrollDataIndex(scrollDataIndex); + } + ); + } +); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/** + * Legend component entry file8 + */ + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +extendComponentModel({ + + type: 'tooltip', + + dependencies: ['axisPointer'], + + defaultOption: { + zlevel: 0, + + z: 60, + + show: true, + + // tooltip主体内容 + showContent: true, + + // 'trigger' only works on coordinate system. + // 'item' | 'axis' | 'none' + trigger: 'item', + + // 'click' | 'mousemove' | 'none' + triggerOn: 'mousemove|click', + + alwaysShowContent: false, + + displayMode: 'single', // 'single' | 'multipleByCoordSys' + + renderMode: 'auto', // 'auto' | 'html' | 'richText' + // 'auto': use html by default, and use non-html if `document` is not defined + // 'html': use html for tooltip + // 'richText': use canvas, svg, and etc. for tooltip + + // 位置 {Array} | {Function} + // position: null + // Consider triggered from axisPointer handle, verticalAlign should be 'middle' + // align: null, + // verticalAlign: null, + + // 是否约束 content 在 viewRect 中。默认 false 是为了兼容以前版本。 + confine: false, + + // 内容格式器:{string}(Template) ¦ {Function} + // formatter: null + + showDelay: 0, + + // 隐藏延迟,单位ms + hideDelay: 100, + + // 动画变换时间,单位s + transitionDuration: 0.4, + + enterable: false, + + // 提示背景颜色,默认为透明度为0.7的黑色 + backgroundColor: 'rgba(50,50,50,0.7)', + + // 提示边框颜色 + borderColor: '#333', + + // 提示边框圆角,单位px,默认为4 + borderRadius: 4, + + // 提示边框线宽,单位px,默认为0(无边框) + borderWidth: 0, + + // 提示内边距,单位px,默认各方向内边距为5, + // 接受数组分别设定上右下左边距,同css + padding: 5, + + // Extra css text + extraCssText: '', + + // 坐标轴指示器,坐标轴触发有效 + axisPointer: { + // 默认为直线 + // 可选为:'line' | 'shadow' | 'cross' + type: 'line', + + // type 为 line 的时候有效,指定 tooltip line 所在的轴,可选 + // 可选 'x' | 'y' | 'angle' | 'radius' | 'auto' + // 默认 'auto',会选择类型为 category 的轴,对于双数值轴,笛卡尔坐标系会默认选择 x 轴 + // 极坐标系会默认选择 angle 轴 + axis: 'auto', + + animation: 'auto', + animationDurationUpdate: 200, + animationEasingUpdate: 'exponentialOut', + + crossStyle: { + color: '#999', + width: 1, + type: 'dashed', + + // TODO formatter + textStyle: {} + } + + // lineStyle and shadowStyle should not be specified here, + // otherwise it will always override those styles on option.axisPointer. + }, + textStyle: { + color: '#fff', + fontSize: 14 + } + } +}); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var each$18 = each$1; +var toCamelCase$1 = toCamelCase; + +var vendors = ['', '-webkit-', '-moz-', '-o-']; + +var gCssText = 'position:absolute;display:block;border-style:solid;white-space:nowrap;z-index:9999999;'; + +/** + * @param {number} duration + * @return {string} + * @inner + */ +function assembleTransition(duration) { + var transitionCurve = 'cubic-bezier(0.23, 1, 0.32, 1)'; + var transitionText = 'left ' + duration + 's ' + transitionCurve + ',' + + 'top ' + duration + 's ' + transitionCurve; + return map(vendors, function (vendorPrefix) { + return vendorPrefix + 'transition:' + transitionText; + }).join(';'); +} + +/** + * @param {Object} textStyle + * @return {string} + * @inner + */ +function assembleFont(textStyleModel) { + var cssText = []; + + var fontSize = textStyleModel.get('fontSize'); + var color = textStyleModel.getTextColor(); + + color && cssText.push('color:' + color); + + cssText.push('font:' + textStyleModel.getFont()); + + fontSize + && cssText.push('line-height:' + Math.round(fontSize * 3 / 2) + 'px'); + + each$18(['decoration', 'align'], function (name) { + var val = textStyleModel.get(name); + val && cssText.push('text-' + name + ':' + val); + }); + + return cssText.join(';'); +} + +/** + * @param {Object} tooltipModel + * @return {string} + * @inner + */ +function assembleCssText(tooltipModel) { + + var cssText = []; + + var transitionDuration = tooltipModel.get('transitionDuration'); + var backgroundColor = tooltipModel.get('backgroundColor'); + var textStyleModel = tooltipModel.getModel('textStyle'); + var padding = tooltipModel.get('padding'); + + // Animation transition. Do not animate when transitionDuration is 0. + transitionDuration + && cssText.push(assembleTransition(transitionDuration)); + + if (backgroundColor) { + if (env$1.canvasSupported) { + cssText.push('background-Color:' + backgroundColor); + } + else { + // for ie + cssText.push( + 'background-Color:#' + toHex(backgroundColor) + ); + cssText.push('filter:alpha(opacity=70)'); + } + } + + // Border style + each$18(['width', 'color', 'radius'], function (name) { + var borderName = 'border-' + name; + var camelCase = toCamelCase$1(borderName); + var val = tooltipModel.get(camelCase); + val != null + && cssText.push(borderName + ':' + val + (name === 'color' ? '' : 'px')); + }); + + // Text style + cssText.push(assembleFont(textStyleModel)); + + // Padding + if (padding != null) { + cssText.push('padding:' + normalizeCssArray$1(padding).join('px ') + 'px'); + } + + return cssText.join(';') + ';'; +} + +/** + * @alias module:echarts/component/tooltip/TooltipContent + * @constructor + */ +function TooltipContent(container, api) { + if (env$1.wxa) { + return null; + } + + var el = document.createElement('div'); + var zr = this._zr = api.getZr(); + + this.el = el; + + this._x = api.getWidth() / 2; + this._y = api.getHeight() / 2; + + container.appendChild(el); + + this._container = container; + + this._show = false; + + /** + * @private + */ + this._hideTimeout; + + var self = this; + el.onmouseenter = function () { + // clear the timeout in hideLater and keep showing tooltip + if (self._enterable) { + clearTimeout(self._hideTimeout); + self._show = true; + } + self._inContent = true; + }; + el.onmousemove = function (e) { + e = e || window.event; + if (!self._enterable) { + // Try trigger zrender event to avoid mouse + // in and out shape too frequently + var handler = zr.handler; + normalizeEvent(container, e, true); + handler.dispatch('mousemove', e); + } + }; + el.onmouseleave = function () { + if (self._enterable) { + if (self._show) { + self.hideLater(self._hideDelay); + } + } + self._inContent = false; + }; +} + +TooltipContent.prototype = { + + constructor: TooltipContent, + + /** + * @private + * @type {boolean} + */ + _enterable: true, + + /** + * Update when tooltip is rendered + */ + update: function () { + // FIXME + // Move this logic to ec main? + var container = this._container; + var stl = container.currentStyle + || document.defaultView.getComputedStyle(container); + var domStyle = container.style; + if (domStyle.position !== 'absolute' && stl.position !== 'absolute') { + domStyle.position = 'relative'; + } + // Hide the tooltip + // PENDING + // this.hide(); + }, + + show: function (tooltipModel) { + clearTimeout(this._hideTimeout); + var el = this.el; + + el.style.cssText = gCssText + assembleCssText(tooltipModel) + // http://stackoverflow.com/questions/21125587/css3-transition-not-working-in-chrome-anymore + + ';left:' + this._x + 'px;top:' + this._y + 'px;' + + (tooltipModel.get('extraCssText') || ''); + + el.style.display = el.innerHTML ? 'block' : 'none'; + + // If mouse occsionally move over the tooltip, a mouseout event will be + // triggered by canvas, and cuase some unexpectable result like dragging + // stop, "unfocusAdjacency". Here `pointer-events: none` is used to solve + // it. Although it is not suppored by IE8~IE10, fortunately it is a rare + // scenario. + el.style.pointerEvents = this._enterable ? 'auto' : 'none'; + + this._show = true; + }, + + setContent: function (content) { + this.el.innerHTML = content == null ? '' : content; + }, + + setEnterable: function (enterable) { + this._enterable = enterable; + }, + + getSize: function () { + var el = this.el; + return [el.clientWidth, el.clientHeight]; + }, + + moveTo: function (x, y) { + // xy should be based on canvas root. But tooltipContent is + // the sibling of canvas root. So padding of ec container + // should be considered here. + var zr = this._zr; + var viewportRootOffset; + if (zr && zr.painter && (viewportRootOffset = zr.painter.getViewportRootOffset())) { + x += viewportRootOffset.offsetLeft; + y += viewportRootOffset.offsetTop; + } + + var style = this.el.style; + style.left = x + 'px'; + style.top = y + 'px'; + + this._x = x; + this._y = y; + }, + + hide: function () { + this.el.style.display = 'none'; + this._show = false; + }, + + hideLater: function (time) { + if (this._show && !(this._inContent && this._enterable)) { + if (time) { + this._hideDelay = time; + // Set show false to avoid invoke hideLater mutiple times + this._show = false; + this._hideTimeout = setTimeout(bind(this.hide, this), time); + } + else { + this.hide(); + } + } + }, + + isShow: function () { + return this._show; + }, + + getOuterSize: function () { + var width = this.el.clientWidth; + var height = this.el.clientHeight; + + // Consider browser compatibility. + // IE8 does not support getComputedStyle. + if (document.defaultView && document.defaultView.getComputedStyle) { + var stl = document.defaultView.getComputedStyle(this.el); + if (stl) { + width += parseInt(stl.paddingLeft, 10) + parseInt(stl.paddingRight, 10) + + parseInt(stl.borderLeftWidth, 10) + parseInt(stl.borderRightWidth, 10); + height += parseInt(stl.paddingTop, 10) + parseInt(stl.paddingBottom, 10) + + parseInt(stl.borderTopWidth, 10) + parseInt(stl.borderBottomWidth, 10); + } + } + + return {width: width, height: height}; + } +}; + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +// import Group from 'zrender/src/container/Group'; +/** + * @alias module:echarts/component/tooltip/TooltipRichContent + * @constructor + */ +function TooltipRichContent(api) { + + this._zr = api.getZr(); + + this._show = false; + + /** + * @private + */ + this._hideTimeout; +} + +TooltipRichContent.prototype = { + + constructor: TooltipRichContent, + + /** + * @private + * @type {boolean} + */ + _enterable: true, + + /** + * Update when tooltip is rendered + */ + update: function () { + // noop + }, + + show: function (tooltipModel) { + if (this._hideTimeout) { + clearTimeout(this._hideTimeout); + } + + this.el.attr('show', true); + this._show = true; + }, + + /** + * Set tooltip content + * + * @param {string} content rich text string of content + * @param {Object} markerRich rich text style + * @param {Object} tooltipModel tooltip model + */ + setContent: function (content, markerRich, tooltipModel) { + if (this.el) { + this._zr.remove(this.el); + } + + var markers = {}; + var text = content; + var prefix = '{marker'; + var suffix = '|}'; + var startId = text.indexOf(prefix); + while (startId >= 0) { + var endId = text.indexOf(suffix); + var name = text.substr(startId + prefix.length, endId - startId - prefix.length); + if (name.indexOf('sub') > -1) { + markers['marker' + name] = { + textWidth: 4, + textHeight: 4, + textBorderRadius: 2, + textBackgroundColor: markerRich[name], + // TODO: textOffset is not implemented for rich text + textOffset: [3, 0] + }; + } + else { + markers['marker' + name] = { + textWidth: 10, + textHeight: 10, + textBorderRadius: 5, + textBackgroundColor: markerRich[name] + }; + } + + text = text.substr(endId + 1); + startId = text.indexOf('{marker'); + } + + this.el = new Text({ + style: { + rich: markers, + text: content, + textLineHeight: 20, + textBackgroundColor: tooltipModel.get('backgroundColor'), + textBorderRadius: tooltipModel.get('borderRadius'), + textFill: tooltipModel.get('textStyle.color'), + textPadding: tooltipModel.get('padding') + }, + z: tooltipModel.get('z') + }); + this._zr.add(this.el); + + var self = this; + this.el.on('mouseover', function () { + // clear the timeout in hideLater and keep showing tooltip + if (self._enterable) { + clearTimeout(self._hideTimeout); + self._show = true; + } + self._inContent = true; + }); + this.el.on('mouseout', function () { + if (self._enterable) { + if (self._show) { + self.hideLater(self._hideDelay); + } + } + self._inContent = false; + }); + }, + + setEnterable: function (enterable) { + this._enterable = enterable; + }, + + getSize: function () { + var bounding = this.el.getBoundingRect(); + return [bounding.width, bounding.height]; + }, + + moveTo: function (x, y) { + if (this.el) { + this.el.attr('position', [x, y]); + } + }, + + hide: function () { + this.el.hide(); + this._show = false; + }, + + hideLater: function (time) { + if (this._show && !(this._inContent && this._enterable)) { + if (time) { + this._hideDelay = time; + // Set show false to avoid invoke hideLater mutiple times + this._show = false; + this._hideTimeout = setTimeout(bind(this.hide, this), time); + } + else { + this.hide(); + } + } + }, + + isShow: function () { + return this._show; + }, + + getOuterSize: function () { + return this.getSize(); + } +}; + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var bind$3 = bind; +var each$17 = each$1; +var parsePercent$2 = parsePercent$1; + +var proxyRect = new Rect({ + shape: {x: -1, y: -1, width: 2, height: 2} +}); + +extendComponentView({ + + type: 'tooltip', + + init: function (ecModel, api) { + if (env$1.node) { + return; + } + + var tooltipModel = ecModel.getComponent('tooltip'); + var renderMode = tooltipModel.get('renderMode'); + this._renderMode = getTooltipRenderMode(renderMode); + + var tooltipContent; + if (this._renderMode === 'html') { + tooltipContent = new TooltipContent(api.getDom(), api); + this._newLine = '
'; + } + else { + tooltipContent = new TooltipRichContent(api); + this._newLine = '\n'; + } + + this._tooltipContent = tooltipContent; + }, + + render: function (tooltipModel, ecModel, api) { + if (env$1.node) { + return; + } + + // Reset + this.group.removeAll(); + + /** + * @private + * @type {module:echarts/component/tooltip/TooltipModel} + */ + this._tooltipModel = tooltipModel; + + /** + * @private + * @type {module:echarts/model/Global} + */ + this._ecModel = ecModel; + + /** + * @private + * @type {module:echarts/ExtensionAPI} + */ + this._api = api; + + /** + * Should be cleaned when render. + * @private + * @type {Array.>} + */ + this._lastDataByCoordSys = null; + + /** + * @private + * @type {boolean} + */ + this._alwaysShowContent = tooltipModel.get('alwaysShowContent'); + + var tooltipContent = this._tooltipContent; + tooltipContent.update(); + tooltipContent.setEnterable(tooltipModel.get('enterable')); + + this._initGlobalListener(); + + this._keepShow(); + }, + + _initGlobalListener: function () { + var tooltipModel = this._tooltipModel; + var triggerOn = tooltipModel.get('triggerOn'); + + register( + 'itemTooltip', + this._api, + bind$3(function (currTrigger, e, dispatchAction) { + // If 'none', it is not controlled by mouse totally. + if (triggerOn !== 'none') { + if (triggerOn.indexOf(currTrigger) >= 0) { + this._tryShow(e, dispatchAction); + } + else if (currTrigger === 'leave') { + this._hide(dispatchAction); + } + } + }, this) + ); + }, + + _keepShow: function () { + var tooltipModel = this._tooltipModel; + var ecModel = this._ecModel; + var api = this._api; + + // Try to keep the tooltip show when refreshing + if (this._lastX != null + && this._lastY != null + // When user is willing to control tooltip totally using API, + // self.manuallyShowTip({x, y}) might cause tooltip hide, + // which is not expected. + && tooltipModel.get('triggerOn') !== 'none' + ) { + var self = this; + clearTimeout(this._refreshUpdateTimeout); + this._refreshUpdateTimeout = setTimeout(function () { + // Show tip next tick after other charts are rendered + // In case highlight action has wrong result + // FIXME + self.manuallyShowTip(tooltipModel, ecModel, api, { + x: self._lastX, + y: self._lastY + }); + }); + } + }, + + /** + * Show tip manually by + * dispatchAction({ + * type: 'showTip', + * x: 10, + * y: 10 + * }); + * Or + * dispatchAction({ + * type: 'showTip', + * seriesIndex: 0, + * dataIndex or dataIndexInside or name + * }); + * + * TODO Batch + */ + manuallyShowTip: function (tooltipModel, ecModel, api, payload) { + if (payload.from === this.uid || env$1.node) { + return; + } + + var dispatchAction = makeDispatchAction$1(payload, api); + + // Reset ticket + this._ticket = ''; + + // When triggered from axisPointer. + var dataByCoordSys = payload.dataByCoordSys; + + if (payload.tooltip && payload.x != null && payload.y != null) { + var el = proxyRect; + el.position = [payload.x, payload.y]; + el.update(); + el.tooltip = payload.tooltip; + // Manually show tooltip while view is not using zrender elements. + this._tryShow({ + offsetX: payload.x, + offsetY: payload.y, + target: el + }, dispatchAction); + } + else if (dataByCoordSys) { + this._tryShow({ + offsetX: payload.x, + offsetY: payload.y, + position: payload.position, + event: {}, + dataByCoordSys: payload.dataByCoordSys, + tooltipOption: payload.tooltipOption + }, dispatchAction); + } + else if (payload.seriesIndex != null) { + + if (this._manuallyAxisShowTip(tooltipModel, ecModel, api, payload)) { + return; + } + + var pointInfo = findPointFromSeries(payload, ecModel); + var cx = pointInfo.point[0]; + var cy = pointInfo.point[1]; + if (cx != null && cy != null) { + this._tryShow({ + offsetX: cx, + offsetY: cy, + position: payload.position, + target: pointInfo.el, + event: {} + }, dispatchAction); + } + } + else if (payload.x != null && payload.y != null) { + // FIXME + // should wrap dispatchAction like `axisPointer/globalListener` ? + api.dispatchAction({ + type: 'updateAxisPointer', + x: payload.x, + y: payload.y + }); + + this._tryShow({ + offsetX: payload.x, + offsetY: payload.y, + position: payload.position, + target: api.getZr().findHover(payload.x, payload.y).target, + event: {} + }, dispatchAction); + } + }, + + manuallyHideTip: function (tooltipModel, ecModel, api, payload) { + var tooltipContent = this._tooltipContent; + + if (!this._alwaysShowContent && this._tooltipModel) { + tooltipContent.hideLater(this._tooltipModel.get('hideDelay')); + } + + this._lastX = this._lastY = null; + + if (payload.from !== this.uid) { + this._hide(makeDispatchAction$1(payload, api)); + } + }, + + // Be compatible with previous design, that is, when tooltip.type is 'axis' and + // dispatchAction 'showTip' with seriesIndex and dataIndex will trigger axis pointer + // and tooltip. + _manuallyAxisShowTip: function (tooltipModel, ecModel, api, payload) { + var seriesIndex = payload.seriesIndex; + var dataIndex = payload.dataIndex; + var coordSysAxesInfo = ecModel.getComponent('axisPointer').coordSysAxesInfo; + + if (seriesIndex == null || dataIndex == null || coordSysAxesInfo == null) { + return; + } + + var seriesModel = ecModel.getSeriesByIndex(seriesIndex); + if (!seriesModel) { + return; + } + + var data = seriesModel.getData(); + var tooltipModel = buildTooltipModel([ + data.getItemModel(dataIndex), + seriesModel, + (seriesModel.coordinateSystem || {}).model, + tooltipModel + ]); + + if (tooltipModel.get('trigger') !== 'axis') { + return; + } + + api.dispatchAction({ + type: 'updateAxisPointer', + seriesIndex: seriesIndex, + dataIndex: dataIndex, + position: payload.position + }); + + return true; + }, + + _tryShow: function (e, dispatchAction) { + var el = e.target; + var tooltipModel = this._tooltipModel; + + if (!tooltipModel) { + return; + } + + // Save mouse x, mouse y. So we can try to keep showing the tip if chart is refreshed + this._lastX = e.offsetX; + this._lastY = e.offsetY; + + var dataByCoordSys = e.dataByCoordSys; + if (dataByCoordSys && dataByCoordSys.length) { + this._showAxisTooltip(dataByCoordSys, e); + } + // Always show item tooltip if mouse is on the element with dataIndex + else if (el && el.dataIndex != null) { + this._lastDataByCoordSys = null; + this._showSeriesItemTooltip(e, el, dispatchAction); + } + // Tooltip provided directly. Like legend. + else if (el && el.tooltip) { + this._lastDataByCoordSys = null; + this._showComponentItemTooltip(e, el, dispatchAction); + } + else { + this._lastDataByCoordSys = null; + this._hide(dispatchAction); + } + }, + + _showOrMove: function (tooltipModel, cb) { + // showDelay is used in this case: tooltip.enterable is set + // as true. User intent to move mouse into tooltip and click + // something. `showDelay` makes it easyer to enter the content + // but tooltip do not move immediately. + var delay = tooltipModel.get('showDelay'); + cb = bind(cb, this); + clearTimeout(this._showTimout); + delay > 0 + ? (this._showTimout = setTimeout(cb, delay)) + : cb(); + }, + + _showAxisTooltip: function (dataByCoordSys, e) { + var ecModel = this._ecModel; + var globalTooltipModel = this._tooltipModel; + var point = [e.offsetX, e.offsetY]; + var singleDefaultHTML = []; + var singleParamsList = []; + var singleTooltipModel = buildTooltipModel([ + e.tooltipOption, + globalTooltipModel + ]); + + var renderMode = this._renderMode; + var newLine = this._newLine; + + var markers = {}; + + each$17(dataByCoordSys, function (itemCoordSys) { + // var coordParamList = []; + // var coordDefaultHTML = []; + // var coordTooltipModel = buildTooltipModel([ + // e.tooltipOption, + // itemCoordSys.tooltipOption, + // ecModel.getComponent(itemCoordSys.coordSysMainType, itemCoordSys.coordSysIndex), + // globalTooltipModel + // ]); + // var displayMode = coordTooltipModel.get('displayMode'); + // var paramsList = displayMode === 'single' ? singleParamsList : []; + + each$17(itemCoordSys.dataByAxis, function (item) { + var axisModel = ecModel.getComponent(item.axisDim + 'Axis', item.axisIndex); + var axisValue = item.value; + var seriesDefaultHTML = []; + + if (!axisModel || axisValue == null) { + return; + } + + var valueLabel = getValueLabel( + axisValue, axisModel.axis, ecModel, + item.seriesDataIndices, + item.valueLabelOpt + ); + + each$1(item.seriesDataIndices, function (idxItem) { + var series = ecModel.getSeriesByIndex(idxItem.seriesIndex); + var dataIndex = idxItem.dataIndexInside; + var dataParams = series && series.getDataParams(dataIndex); + dataParams.axisDim = item.axisDim; + dataParams.axisIndex = item.axisIndex; + dataParams.axisType = item.axisType; + dataParams.axisId = item.axisId; + dataParams.axisValue = getAxisRawValue(axisModel.axis, axisValue); + dataParams.axisValueLabel = valueLabel; + + if (dataParams) { + singleParamsList.push(dataParams); + var seriesTooltip = series.formatTooltip(dataIndex, true, null, renderMode); + + var html; + if (isObject$1(seriesTooltip)) { + html = seriesTooltip.html; + var newMarkers = seriesTooltip.markers; + merge(markers, newMarkers); + } + else { + html = seriesTooltip; + } + seriesDefaultHTML.push(html); + } + }); + + // Default tooltip content + // FIXME + // (1) shold be the first data which has name? + // (2) themeRiver, firstDataIndex is array, and first line is unnecessary. + var firstLine = valueLabel; + if (renderMode !== 'html') { + singleDefaultHTML.push(seriesDefaultHTML.join(newLine)); + } + else { + singleDefaultHTML.push( + (firstLine ? encodeHTML(firstLine) + newLine : '') + + seriesDefaultHTML.join(newLine) + ); + } + }); + }, this); + + // In most case, the second axis is shown upper than the first one. + singleDefaultHTML.reverse(); + singleDefaultHTML = singleDefaultHTML.join(this._newLine + this._newLine); + + var positionExpr = e.position; + this._showOrMove(singleTooltipModel, function () { + if (this._updateContentNotChangedOnAxis(dataByCoordSys)) { + this._updatePosition( + singleTooltipModel, + positionExpr, + point[0], point[1], + this._tooltipContent, + singleParamsList + ); + } + else { + this._showTooltipContent( + singleTooltipModel, singleDefaultHTML, singleParamsList, Math.random(), + point[0], point[1], positionExpr, undefined, markers + ); + } + }); + + // Do not trigger events here, because this branch only be entered + // from dispatchAction. + }, + + _showSeriesItemTooltip: function (e, el, dispatchAction) { + var ecModel = this._ecModel; + // Use dataModel in element if possible + // Used when mouseover on a element like markPoint or edge + // In which case, the data is not main data in series. + var seriesIndex = el.seriesIndex; + var seriesModel = ecModel.getSeriesByIndex(seriesIndex); + + // For example, graph link. + var dataModel = el.dataModel || seriesModel; + var dataIndex = el.dataIndex; + var dataType = el.dataType; + var data = dataModel.getData(); + + var tooltipModel = buildTooltipModel([ + data.getItemModel(dataIndex), + dataModel, + seriesModel && (seriesModel.coordinateSystem || {}).model, + this._tooltipModel + ]); + + var tooltipTrigger = tooltipModel.get('trigger'); + if (tooltipTrigger != null && tooltipTrigger !== 'item') { + return; + } + + var params = dataModel.getDataParams(dataIndex, dataType); + var seriesTooltip = dataModel.formatTooltip(dataIndex, false, dataType, this._renderMode); + var defaultHtml; + var markers; + if (isObject$1(seriesTooltip)) { + defaultHtml = seriesTooltip.html; + markers = seriesTooltip.markers; + } + else { + defaultHtml = seriesTooltip; + markers = null; + } + + var asyncTicket = 'item_' + dataModel.name + '_' + dataIndex; + + this._showOrMove(tooltipModel, function () { + this._showTooltipContent( + tooltipModel, defaultHtml, params, asyncTicket, + e.offsetX, e.offsetY, e.position, e.target, markers + ); + }); + + // FIXME + // duplicated showtip if manuallyShowTip is called from dispatchAction. + dispatchAction({ + type: 'showTip', + dataIndexInside: dataIndex, + dataIndex: data.getRawIndex(dataIndex), + seriesIndex: seriesIndex, + from: this.uid + }); + }, + + _showComponentItemTooltip: function (e, el, dispatchAction) { + var tooltipOpt = el.tooltip; + if (typeof tooltipOpt === 'string') { + var content = tooltipOpt; + tooltipOpt = { + content: content, + // Fixed formatter + formatter: content + }; + } + var subTooltipModel = new Model(tooltipOpt, this._tooltipModel, this._ecModel); + var defaultHtml = subTooltipModel.get('content'); + var asyncTicket = Math.random(); + + // Do not check whether `trigger` is 'none' here, because `trigger` + // only works on cooridinate system. In fact, we have not found case + // that requires setting `trigger` nothing on component yet. + + this._showOrMove(subTooltipModel, function () { + this._showTooltipContent( + subTooltipModel, defaultHtml, subTooltipModel.get('formatterParams') || {}, + asyncTicket, e.offsetX, e.offsetY, e.position, el + ); + }); + + // If not dispatch showTip, tip may be hide triggered by axis. + dispatchAction({ + type: 'showTip', + from: this.uid + }); + }, + + _showTooltipContent: function ( + tooltipModel, defaultHtml, params, asyncTicket, x, y, positionExpr, el, markers + ) { + // Reset ticket + this._ticket = ''; + + if (!tooltipModel.get('showContent') || !tooltipModel.get('show')) { + return; + } + + var tooltipContent = this._tooltipContent; + + var formatter = tooltipModel.get('formatter'); + positionExpr = positionExpr || tooltipModel.get('position'); + var html = defaultHtml; + + if (formatter && typeof formatter === 'string') { + html = formatTpl(formatter, params, true); + } + else if (typeof formatter === 'function') { + var callback = bind$3(function (cbTicket, html) { + if (cbTicket === this._ticket) { + tooltipContent.setContent(html, markers, tooltipModel); + this._updatePosition( + tooltipModel, positionExpr, x, y, tooltipContent, params, el + ); + } + }, this); + this._ticket = asyncTicket; + html = formatter(params, asyncTicket, callback); + } + + tooltipContent.setContent(html, markers, tooltipModel); + tooltipContent.show(tooltipModel); + + this._updatePosition( + tooltipModel, positionExpr, x, y, tooltipContent, params, el + ); + }, + + /** + * @param {string|Function|Array.|Object} positionExpr + * @param {number} x Mouse x + * @param {number} y Mouse y + * @param {boolean} confine Whether confine tooltip content in view rect. + * @param {Object|} params + * @param {module:zrender/Element} el target element + * @param {module:echarts/ExtensionAPI} api + * @return {Array.} + */ + _updatePosition: function (tooltipModel, positionExpr, x, y, content, params, el) { + var viewWidth = this._api.getWidth(); + var viewHeight = this._api.getHeight(); + positionExpr = positionExpr || tooltipModel.get('position'); + + var contentSize = content.getSize(); + var align = tooltipModel.get('align'); + var vAlign = tooltipModel.get('verticalAlign'); + var rect = el && el.getBoundingRect().clone(); + el && rect.applyTransform(el.transform); + + if (typeof positionExpr === 'function') { + // Callback of position can be an array or a string specify the position + positionExpr = positionExpr([x, y], params, content.el, rect, { + viewSize: [viewWidth, viewHeight], + contentSize: contentSize.slice() + }); + } + + if (isArray(positionExpr)) { + x = parsePercent$2(positionExpr[0], viewWidth); + y = parsePercent$2(positionExpr[1], viewHeight); + } + else if (isObject$1(positionExpr)) { + positionExpr.width = contentSize[0]; + positionExpr.height = contentSize[1]; + var layoutRect = getLayoutRect( + positionExpr, {width: viewWidth, height: viewHeight} + ); + x = layoutRect.x; + y = layoutRect.y; + align = null; + // When positionExpr is left/top/right/bottom, + // align and verticalAlign will not work. + vAlign = null; + } + // Specify tooltip position by string 'top' 'bottom' 'left' 'right' around graphic element + else if (typeof positionExpr === 'string' && el) { + var pos = calcTooltipPosition( + positionExpr, rect, contentSize + ); + x = pos[0]; + y = pos[1]; + } + else { + var pos = refixTooltipPosition( + x, y, content, viewWidth, viewHeight, align ? null : 20, vAlign ? null : 20 + ); + x = pos[0]; + y = pos[1]; + } + + align && (x -= isCenterAlign(align) ? contentSize[0] / 2 : align === 'right' ? contentSize[0] : 0); + vAlign && (y -= isCenterAlign(vAlign) ? contentSize[1] / 2 : vAlign === 'bottom' ? contentSize[1] : 0); + + if (tooltipModel.get('confine')) { + var pos = confineTooltipPosition( + x, y, content, viewWidth, viewHeight + ); + x = pos[0]; + y = pos[1]; + } + + content.moveTo(x, y); + }, + + // FIXME + // Should we remove this but leave this to user? + _updateContentNotChangedOnAxis: function (dataByCoordSys) { + var lastCoordSys = this._lastDataByCoordSys; + var contentNotChanged = !!lastCoordSys + && lastCoordSys.length === dataByCoordSys.length; + + contentNotChanged && each$17(lastCoordSys, function (lastItemCoordSys, indexCoordSys) { + var lastDataByAxis = lastItemCoordSys.dataByAxis || {}; + var thisItemCoordSys = dataByCoordSys[indexCoordSys] || {}; + var thisDataByAxis = thisItemCoordSys.dataByAxis || []; + contentNotChanged &= lastDataByAxis.length === thisDataByAxis.length; + + contentNotChanged && each$17(lastDataByAxis, function (lastItem, indexAxis) { + var thisItem = thisDataByAxis[indexAxis] || {}; + var lastIndices = lastItem.seriesDataIndices || []; + var newIndices = thisItem.seriesDataIndices || []; + + contentNotChanged + &= lastItem.value === thisItem.value + && lastItem.axisType === thisItem.axisType + && lastItem.axisId === thisItem.axisId + && lastIndices.length === newIndices.length; + + contentNotChanged && each$17(lastIndices, function (lastIdxItem, j) { + var newIdxItem = newIndices[j]; + contentNotChanged + &= lastIdxItem.seriesIndex === newIdxItem.seriesIndex + && lastIdxItem.dataIndex === newIdxItem.dataIndex; + }); + }); + }); + + this._lastDataByCoordSys = dataByCoordSys; + + return !!contentNotChanged; + }, + + _hide: function (dispatchAction) { + // Do not directly hideLater here, because this behavior may be prevented + // in dispatchAction when showTip is dispatched. + + // FIXME + // duplicated hideTip if manuallyHideTip is called from dispatchAction. + this._lastDataByCoordSys = null; + dispatchAction({ + type: 'hideTip', + from: this.uid + }); + }, + + dispose: function (ecModel, api) { + if (env$1.node) { + return; + } + this._tooltipContent.hide(); + unregister('itemTooltip', api); + } +}); + + +/** + * @param {Array.} modelCascade + * From top to bottom. (the last one should be globalTooltipModel); + */ +function buildTooltipModel(modelCascade) { + var resultModel = modelCascade.pop(); + while (modelCascade.length) { + var tooltipOpt = modelCascade.pop(); + if (tooltipOpt) { + if (Model.isInstance(tooltipOpt)) { + tooltipOpt = tooltipOpt.get('tooltip', true); + } + // In each data item tooltip can be simply write: + // { + // value: 10, + // tooltip: 'Something you need to know' + // } + if (typeof tooltipOpt === 'string') { + tooltipOpt = {formatter: tooltipOpt}; + } + resultModel = new Model(tooltipOpt, resultModel, resultModel.ecModel); + } + } + return resultModel; +} + +function makeDispatchAction$1(payload, api) { + return payload.dispatchAction || bind(api.dispatchAction, api); +} + +function refixTooltipPosition(x, y, content, viewWidth, viewHeight, gapH, gapV) { + var size = content.getOuterSize(); + var width = size.width; + var height = size.height; + + if (gapH != null) { + if (x + width + gapH > viewWidth) { + x -= width + gapH; + } + else { + x += gapH; + } + } + if (gapV != null) { + if (y + height + gapV > viewHeight) { + y -= height + gapV; + } + else { + y += gapV; + } + } + return [x, y]; +} + +function confineTooltipPosition(x, y, content, viewWidth, viewHeight) { + var size = content.getOuterSize(); + var width = size.width; + var height = size.height; + + x = Math.min(x + width, viewWidth) - width; + y = Math.min(y + height, viewHeight) - height; + x = Math.max(x, 0); + y = Math.max(y, 0); + + return [x, y]; +} + +function calcTooltipPosition(position, rect, contentSize) { + var domWidth = contentSize[0]; + var domHeight = contentSize[1]; + var gap = 5; + var x = 0; + var y = 0; + var rectWidth = rect.width; + var rectHeight = rect.height; + switch (position) { + case 'inside': + x = rect.x + rectWidth / 2 - domWidth / 2; + y = rect.y + rectHeight / 2 - domHeight / 2; + break; + case 'top': + x = rect.x + rectWidth / 2 - domWidth / 2; + y = rect.y - domHeight - gap; + break; + case 'bottom': + x = rect.x + rectWidth / 2 - domWidth / 2; + y = rect.y + rectHeight + gap; + break; + case 'left': + x = rect.x - domWidth - gap; + y = rect.y + rectHeight / 2 - domHeight / 2; + break; + case 'right': + x = rect.x + rectWidth + gap; + y = rect.y + rectHeight / 2 - domHeight / 2; + } + return [x, y]; +} + +function isCenterAlign(align) { + return align === 'center' || align === 'middle'; +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +// FIXME Better way to pack data in graphic element + +/** + * @action + * @property {string} type + * @property {number} seriesIndex + * @property {number} dataIndex + * @property {number} [x] + * @property {number} [y] + */ +registerAction( + { + type: 'showTip', + event: 'showTip', + update: 'tooltip:manuallyShowTip' + }, + // noop + function () {} +); + +registerAction( + { + type: 'hideTip', + event: 'hideTip', + update: 'tooltip:manuallyHideTip' + }, + // noop + function () {} +); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +function getSeriesStackId$1(seriesModel) { + return seriesModel.get('stack') + || '__ec_stack_' + seriesModel.seriesIndex; +} + +function getAxisKey$1(axis) { + return axis.dim; +} + +/** + * @param {string} seriesType + * @param {module:echarts/model/Global} ecModel + * @param {module:echarts/ExtensionAPI} api + */ +function barLayoutPolar(seriesType, ecModel, api) { + + // FIXME + // Revert becuase it brings bar progressive bug. + // The complete fix will be added in the next version. + var width = api.getWidth(); + var height = api.getHeight(); + + var lastStackCoords = {}; + + var barWidthAndOffset = calRadialBar( + filter( + ecModel.getSeriesByType(seriesType), + function (seriesModel) { + return !ecModel.isSeriesFiltered(seriesModel) + && seriesModel.coordinateSystem + && seriesModel.coordinateSystem.type === 'polar'; + } + ) + ); + + ecModel.eachSeriesByType(seriesType, function (seriesModel) { + // Check series coordinate, do layout for polar only + if (seriesModel.coordinateSystem.type !== 'polar') { + return; + } + + var data = seriesModel.getData(); + var polar = seriesModel.coordinateSystem; + var baseAxis = polar.getBaseAxis(); + + var stackId = getSeriesStackId$1(seriesModel); + var columnLayoutInfo + = barWidthAndOffset[getAxisKey$1(baseAxis)][stackId]; + var columnOffset = columnLayoutInfo.offset; + var columnWidth = columnLayoutInfo.width; + var valueAxis = polar.getOtherAxis(baseAxis); + + var cx = seriesModel.coordinateSystem.cx; + var cy = seriesModel.coordinateSystem.cy; + + var barMinHeight = seriesModel.get('barMinHeight') || 0; + var barMinAngle = seriesModel.get('barMinAngle') || 0; + + lastStackCoords[stackId] = lastStackCoords[stackId] || []; + + var valueDim = data.mapDimension(valueAxis.dim); + var baseDim = data.mapDimension(baseAxis.dim); + var stacked = isDimensionStacked(data, valueDim /*, baseDim*/); + + var valueAxisStart = valueAxis.getExtent()[0]; + + for (var idx = 0, len = data.count(); idx < len; idx++) { + var value = data.get(valueDim, idx); + var baseValue = data.get(baseDim, idx); + + if (isNaN(value)) { + continue; + } + + var sign = value >= 0 ? 'p' : 'n'; + var baseCoord = valueAxisStart; + + // Because of the barMinHeight, we can not use the value in + // stackResultDimension directly. + // Only ordinal axis can be stacked. + if (stacked) { + if (!lastStackCoords[stackId][baseValue]) { + lastStackCoords[stackId][baseValue] = { + p: valueAxisStart, // Positive stack + n: valueAxisStart // Negative stack + }; + } + // Should also consider #4243 + baseCoord = lastStackCoords[stackId][baseValue][sign]; + } + + var r0; + var r; + var startAngle; + var endAngle; + + // radial sector + if (valueAxis.dim === 'radius') { + var radiusSpan = valueAxis.dataToRadius(value) - valueAxisStart; + var angle = baseAxis.dataToAngle(baseValue); + + if (Math.abs(radiusSpan) < barMinHeight) { + radiusSpan = (radiusSpan < 0 ? -1 : 1) * barMinHeight; + } + + r0 = baseCoord; + r = baseCoord + radiusSpan; + startAngle = angle - columnOffset; + endAngle = startAngle - columnWidth; + + stacked && (lastStackCoords[stackId][baseValue][sign] = r); + } + // tangential sector + else { + // angleAxis must be clamped. + var angleSpan = valueAxis.dataToAngle(value, true) - valueAxisStart; + var radius = baseAxis.dataToRadius(baseValue); + + if (Math.abs(angleSpan) < barMinAngle) { + angleSpan = (angleSpan < 0 ? -1 : 1) * barMinAngle; + } + + r0 = radius + columnOffset; + r = r0 + columnWidth; + startAngle = baseCoord; + endAngle = baseCoord + angleSpan; + + // if the previous stack is at the end of the ring, + // add a round to differentiate it from origin + // var extent = angleAxis.getExtent(); + // var stackCoord = angle; + // if (stackCoord === extent[0] && value > 0) { + // stackCoord = extent[1]; + // } + // else if (stackCoord === extent[1] && value < 0) { + // stackCoord = extent[0]; + // } + stacked && (lastStackCoords[stackId][baseValue][sign] = endAngle); + } + + data.setItemLayout(idx, { + cx: cx, + cy: cy, + r0: r0, + r: r, + // Consider that positive angle is anti-clockwise, + // while positive radian of sector is clockwise + startAngle: -startAngle * Math.PI / 180, + endAngle: -endAngle * Math.PI / 180 + }); + + } + + }, this); + +} + +/** + * Calculate bar width and offset for radial bar charts + */ +function calRadialBar(barSeries, api) { + // Columns info on each category axis. Key is polar name + var columnsMap = {}; + + each$1(barSeries, function (seriesModel, idx) { + var data = seriesModel.getData(); + var polar = seriesModel.coordinateSystem; + + var baseAxis = polar.getBaseAxis(); + + var axisExtent = baseAxis.getExtent(); + var bandWidth = baseAxis.type === 'category' + ? baseAxis.getBandWidth() + : (Math.abs(axisExtent[1] - axisExtent[0]) / data.count()); + + var columnsOnAxis = columnsMap[getAxisKey$1(baseAxis)] || { + bandWidth: bandWidth, + remainedWidth: bandWidth, + autoWidthCount: 0, + categoryGap: '20%', + gap: '30%', + stacks: {} + }; + var stacks = columnsOnAxis.stacks; + columnsMap[getAxisKey$1(baseAxis)] = columnsOnAxis; + + var stackId = getSeriesStackId$1(seriesModel); + + if (!stacks[stackId]) { + columnsOnAxis.autoWidthCount++; + } + stacks[stackId] = stacks[stackId] || { + width: 0, + maxWidth: 0 + }; + + var barWidth = parsePercent$1( + seriesModel.get('barWidth'), + bandWidth + ); + var barMaxWidth = parsePercent$1( + seriesModel.get('barMaxWidth'), + bandWidth + ); + var barGap = seriesModel.get('barGap'); + var barCategoryGap = seriesModel.get('barCategoryGap'); + + if (barWidth && !stacks[stackId].width) { + barWidth = Math.min(columnsOnAxis.remainedWidth, barWidth); + stacks[stackId].width = barWidth; + columnsOnAxis.remainedWidth -= barWidth; + } + + barMaxWidth && (stacks[stackId].maxWidth = barMaxWidth); + (barGap != null) && (columnsOnAxis.gap = barGap); + (barCategoryGap != null) && (columnsOnAxis.categoryGap = barCategoryGap); + }); + + + var result = {}; + + each$1(columnsMap, function (columnsOnAxis, coordSysName) { + + result[coordSysName] = {}; + + var stacks = columnsOnAxis.stacks; + var bandWidth = columnsOnAxis.bandWidth; + var categoryGap = parsePercent$1(columnsOnAxis.categoryGap, bandWidth); + var barGapPercent = parsePercent$1(columnsOnAxis.gap, 1); + + var remainedWidth = columnsOnAxis.remainedWidth; + var autoWidthCount = columnsOnAxis.autoWidthCount; + var autoWidth = (remainedWidth - categoryGap) + / (autoWidthCount + (autoWidthCount - 1) * barGapPercent); + autoWidth = Math.max(autoWidth, 0); + + // Find if any auto calculated bar exceeded maxBarWidth + each$1(stacks, function (column, stack) { + var maxWidth = column.maxWidth; + if (maxWidth && maxWidth < autoWidth) { + maxWidth = Math.min(maxWidth, remainedWidth); + if (column.width) { + maxWidth = Math.min(maxWidth, column.width); + } + remainedWidth -= maxWidth; + column.width = maxWidth; + autoWidthCount--; + } + }); + + // Recalculate width again + autoWidth = (remainedWidth - categoryGap) + / (autoWidthCount + (autoWidthCount - 1) * barGapPercent); + autoWidth = Math.max(autoWidth, 0); + + var widthSum = 0; + var lastColumn; + each$1(stacks, function (column, idx) { + if (!column.width) { + column.width = autoWidth; + } + lastColumn = column; + widthSum += column.width * (1 + barGapPercent); + }); + if (lastColumn) { + widthSum -= lastColumn.width * barGapPercent; + } + + var offset = -widthSum / 2; + each$1(stacks, function (column, stackId) { + result[coordSysName][stackId] = result[coordSysName][stackId] || { + offset: offset, + width: column.width + }; + + offset += column.width * (1 + barGapPercent); + }); + }); + + return result; +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +function RadiusAxis(scale, radiusExtent) { + + Axis.call(this, 'radius', scale, radiusExtent); + + /** + * Axis type + * - 'category' + * - 'value' + * - 'time' + * - 'log' + * @type {string} + */ + this.type = 'category'; +} + +RadiusAxis.prototype = { + + constructor: RadiusAxis, + + /** + * @override + */ + pointToData: function (point, clamp) { + return this.polar.pointToData(point, clamp)[this.dim === 'radius' ? 0 : 1]; + }, + + dataToRadius: Axis.prototype.dataToCoord, + + radiusToData: Axis.prototype.coordToData +}; + +inherits(RadiusAxis, Axis); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var inner$12 = makeInner(); + +function AngleAxis(scale, angleExtent) { + + angleExtent = angleExtent || [0, 360]; + + Axis.call(this, 'angle', scale, angleExtent); + + /** + * Axis type + * - 'category' + * - 'value' + * - 'time' + * - 'log' + * @type {string} + */ + this.type = 'category'; +} + +AngleAxis.prototype = { + + constructor: AngleAxis, + + /** + * @override + */ + pointToData: function (point, clamp) { + return this.polar.pointToData(point, clamp)[this.dim === 'radius' ? 0 : 1]; + }, + + dataToAngle: Axis.prototype.dataToCoord, + + angleToData: Axis.prototype.coordToData, + + /** + * Only be called in category axis. + * Angle axis uses text height to decide interval + * + * @override + * @return {number} Auto interval for cateogry axis tick and label + */ + calculateCategoryInterval: function () { + var axis = this; + var labelModel = axis.getLabelModel(); + + var ordinalScale = axis.scale; + var ordinalExtent = ordinalScale.getExtent(); + // Providing this method is for optimization: + // avoid generating a long array by `getTicks` + // in large category data case. + var tickCount = ordinalScale.count(); + + if (ordinalExtent[1] - ordinalExtent[0] < 1) { + return 0; + } + + var tickValue = ordinalExtent[0]; + var unitSpan = axis.dataToCoord(tickValue + 1) - axis.dataToCoord(tickValue); + var unitH = Math.abs(unitSpan); + + // Not precise, just use height as text width + // and each distance from axis line yet. + var rect = getBoundingRect( + tickValue, labelModel.getFont(), 'center', 'top' + ); + var maxH = Math.max(rect.height, 7); + + var dh = maxH / unitH; + // 0/0 is NaN, 1/0 is Infinity. + isNaN(dh) && (dh = Infinity); + var interval = Math.max(0, Math.floor(dh)); + + var cache = inner$12(axis.model); + var lastAutoInterval = cache.lastAutoInterval; + var lastTickCount = cache.lastTickCount; + + // Use cache to keep interval stable while moving zoom window, + // otherwise the calculated interval might jitter when the zoom + // window size is close to the interval-changing size. + if (lastAutoInterval != null + && lastTickCount != null + && Math.abs(lastAutoInterval - interval) <= 1 + && Math.abs(lastTickCount - tickCount) <= 1 + // Always choose the bigger one, otherwise the critical + // point is not the same when zooming in or zooming out. + && lastAutoInterval > interval + ) { + interval = lastAutoInterval; + } + // Only update cache if cache not used, otherwise the + // changing of interval is too insensitive. + else { + cache.lastTickCount = tickCount; + cache.lastAutoInterval = interval; + } + + return interval; + } +}; + +inherits(AngleAxis, Axis); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/** + * @module echarts/coord/polar/Polar + */ + +/** + * @alias {module:echarts/coord/polar/Polar} + * @constructor + * @param {string} name + */ +var Polar = function (name) { + + /** + * @type {string} + */ + this.name = name || ''; + + /** + * x of polar center + * @type {number} + */ + this.cx = 0; + + /** + * y of polar center + * @type {number} + */ + this.cy = 0; + + /** + * @type {module:echarts/coord/polar/RadiusAxis} + * @private + */ + this._radiusAxis = new RadiusAxis(); + + /** + * @type {module:echarts/coord/polar/AngleAxis} + * @private + */ + this._angleAxis = new AngleAxis(); + + this._radiusAxis.polar = this._angleAxis.polar = this; +}; + +Polar.prototype = { + + type: 'polar', + + axisPointerEnabled: true, + + constructor: Polar, + + /** + * @param {Array.} + * @readOnly + */ + dimensions: ['radius', 'angle'], + + /** + * @type {module:echarts/coord/PolarModel} + */ + model: null, + + /** + * If contain coord + * @param {Array.} point + * @return {boolean} + */ + containPoint: function (point) { + var coord = this.pointToCoord(point); + return this._radiusAxis.contain(coord[0]) + && this._angleAxis.contain(coord[1]); + }, + + /** + * If contain data + * @param {Array.} data + * @return {boolean} + */ + containData: function (data) { + return this._radiusAxis.containData(data[0]) + && this._angleAxis.containData(data[1]); + }, + + /** + * @param {string} dim + * @return {module:echarts/coord/polar/AngleAxis|module:echarts/coord/polar/RadiusAxis} + */ + getAxis: function (dim) { + return this['_' + dim + 'Axis']; + }, + + /** + * @return {Array.} + */ + getAxes: function () { + return [this._radiusAxis, this._angleAxis]; + }, + + /** + * Get axes by type of scale + * @param {string} scaleType + * @return {module:echarts/coord/polar/AngleAxis|module:echarts/coord/polar/RadiusAxis} + */ + getAxesByScale: function (scaleType) { + var axes = []; + var angleAxis = this._angleAxis; + var radiusAxis = this._radiusAxis; + angleAxis.scale.type === scaleType && axes.push(angleAxis); + radiusAxis.scale.type === scaleType && axes.push(radiusAxis); + + return axes; + }, + + /** + * @return {module:echarts/coord/polar/AngleAxis} + */ + getAngleAxis: function () { + return this._angleAxis; + }, + + /** + * @return {module:echarts/coord/polar/RadiusAxis} + */ + getRadiusAxis: function () { + return this._radiusAxis; + }, + + /** + * @param {module:echarts/coord/polar/Axis} + * @return {module:echarts/coord/polar/Axis} + */ + getOtherAxis: function (axis) { + var angleAxis = this._angleAxis; + return axis === angleAxis ? this._radiusAxis : angleAxis; + }, + + /** + * Base axis will be used on stacking. + * + * @return {module:echarts/coord/polar/Axis} + */ + getBaseAxis: function () { + return this.getAxesByScale('ordinal')[0] + || this.getAxesByScale('time')[0] + || this.getAngleAxis(); + }, + + /** + * @param {string} [dim] 'radius' or 'angle' or 'auto' or null/undefined + * @return {Object} {baseAxes: [], otherAxes: []} + */ + getTooltipAxes: function (dim) { + var baseAxis = (dim != null && dim !== 'auto') + ? this.getAxis(dim) : this.getBaseAxis(); + return { + baseAxes: [baseAxis], + otherAxes: [this.getOtherAxis(baseAxis)] + }; + }, + + /** + * Convert a single data item to (x, y) point. + * Parameter data is an array which the first element is radius and the second is angle + * @param {Array.} data + * @param {boolean} [clamp=false] + * @return {Array.} + */ + dataToPoint: function (data, clamp) { + return this.coordToPoint([ + this._radiusAxis.dataToRadius(data[0], clamp), + this._angleAxis.dataToAngle(data[1], clamp) + ]); + }, + + /** + * Convert a (x, y) point to data + * @param {Array.} point + * @param {boolean} [clamp=false] + * @return {Array.} + */ + pointToData: function (point, clamp) { + var coord = this.pointToCoord(point); + return [ + this._radiusAxis.radiusToData(coord[0], clamp), + this._angleAxis.angleToData(coord[1], clamp) + ]; + }, + + /** + * Convert a (x, y) point to (radius, angle) coord + * @param {Array.} point + * @return {Array.} + */ + pointToCoord: function (point) { + var dx = point[0] - this.cx; + var dy = point[1] - this.cy; + var angleAxis = this.getAngleAxis(); + var extent = angleAxis.getExtent(); + var minAngle = Math.min(extent[0], extent[1]); + var maxAngle = Math.max(extent[0], extent[1]); + // Fix fixed extent in polarCreator + // FIXME + angleAxis.inverse + ? (minAngle = maxAngle - 360) + : (maxAngle = minAngle + 360); + + var radius = Math.sqrt(dx * dx + dy * dy); + dx /= radius; + dy /= radius; + + var radian = Math.atan2(-dy, dx) / Math.PI * 180; + + // move to angleExtent + var dir = radian < minAngle ? 1 : -1; + while (radian < minAngle || radian > maxAngle) { + radian += dir * 360; + } + + return [radius, radian]; + }, + + /** + * Convert a (radius, angle) coord to (x, y) point + * @param {Array.} coord + * @return {Array.} + */ + coordToPoint: function (coord) { + var radius = coord[0]; + var radian = coord[1] / 180 * Math.PI; + var x = Math.cos(radian) * radius + this.cx; + // Inverse the y + var y = -Math.sin(radian) * radius + this.cy; + + return [x, y]; + } + +}; + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var PolarAxisModel = ComponentModel.extend({ + + type: 'polarAxis', + + /** + * @type {module:echarts/coord/polar/AngleAxis|module:echarts/coord/polar/RadiusAxis} + */ + axis: null, + + /** + * @override + */ + getCoordSysModel: function () { + return this.ecModel.queryComponents({ + mainType: 'polar', + index: this.option.polarIndex, + id: this.option.polarId + })[0]; + } + +}); + +merge(PolarAxisModel.prototype, axisModelCommonMixin); + +var polarAxisDefaultExtendedOption = { + angle: { + // polarIndex: 0, + // polarId: '', + + startAngle: 90, + + clockwise: true, + + splitNumber: 12, + + axisLabel: { + rotate: false + } + }, + radius: { + // polarIndex: 0, + // polarId: '', + + splitNumber: 5 + } +}; + +function getAxisType$3(axisDim, option) { + // Default axis with data is category axis + return option.type || (option.data ? 'category' : 'value'); +} + +axisModelCreator('angle', PolarAxisModel, getAxisType$3, polarAxisDefaultExtendedOption.angle); +axisModelCreator('radius', PolarAxisModel, getAxisType$3, polarAxisDefaultExtendedOption.radius); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +extendComponentModel({ + + type: 'polar', + + dependencies: ['polarAxis', 'angleAxis'], + + /** + * @type {module:echarts/coord/polar/Polar} + */ + coordinateSystem: null, + + /** + * @param {string} axisType + * @return {module:echarts/coord/polar/AxisModel} + */ + findAxisModel: function (axisType) { + var foundAxisModel; + var ecModel = this.ecModel; + + ecModel.eachComponent(axisType, function (axisModel) { + if (axisModel.getCoordSysModel() === this) { + foundAxisModel = axisModel; + } + }, this); + return foundAxisModel; + }, + + defaultOption: { + + zlevel: 0, + + z: 0, + + center: ['50%', '50%'], + + radius: '80%' + } +}); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +// TODO Axis scale + +/** + * Resize method bound to the polar + * @param {module:echarts/coord/polar/PolarModel} polarModel + * @param {module:echarts/ExtensionAPI} api + */ +function resizePolar(polar, polarModel, api) { + var center = polarModel.get('center'); + var width = api.getWidth(); + var height = api.getHeight(); + + polar.cx = parsePercent$1(center[0], width); + polar.cy = parsePercent$1(center[1], height); + + var radiusAxis = polar.getRadiusAxis(); + var size = Math.min(width, height) / 2; + var radius = parsePercent$1(polarModel.get('radius'), size); + radiusAxis.inverse + ? radiusAxis.setExtent(radius, 0) + : radiusAxis.setExtent(0, radius); +} + +/** + * Update polar + */ +function updatePolarScale(ecModel, api) { + var polar = this; + var angleAxis = polar.getAngleAxis(); + var radiusAxis = polar.getRadiusAxis(); + // Reset scale + angleAxis.scale.setExtent(Infinity, -Infinity); + radiusAxis.scale.setExtent(Infinity, -Infinity); + + ecModel.eachSeries(function (seriesModel) { + if (seriesModel.coordinateSystem === polar) { + var data = seriesModel.getData(); + each$1(data.mapDimension('radius', true), function (dim) { + radiusAxis.scale.unionExtentFromData( + data, getStackedDimension(data, dim) + ); + }); + each$1(data.mapDimension('angle', true), function (dim) { + angleAxis.scale.unionExtentFromData( + data, getStackedDimension(data, dim) + ); + }); + } + }); + + niceScaleExtent(angleAxis.scale, angleAxis.model); + niceScaleExtent(radiusAxis.scale, radiusAxis.model); + + // Fix extent of category angle axis + if (angleAxis.type === 'category' && !angleAxis.onBand) { + var extent = angleAxis.getExtent(); + var diff = 360 / angleAxis.scale.count(); + angleAxis.inverse ? (extent[1] += diff) : (extent[1] -= diff); + angleAxis.setExtent(extent[0], extent[1]); + } +} + +/** + * Set common axis properties + * @param {module:echarts/coord/polar/AngleAxis|module:echarts/coord/polar/RadiusAxis} + * @param {module:echarts/coord/polar/AxisModel} + * @inner + */ +function setAxis(axis, axisModel) { + axis.type = axisModel.get('type'); + axis.scale = createScaleByModel(axisModel); + axis.onBand = axisModel.get('boundaryGap') && axis.type === 'category'; + axis.inverse = axisModel.get('inverse'); + + if (axisModel.mainType === 'angleAxis') { + axis.inverse ^= axisModel.get('clockwise'); + var startAngle = axisModel.get('startAngle'); + axis.setExtent(startAngle, startAngle + (axis.inverse ? -360 : 360)); + } + + // Inject axis instance + axisModel.axis = axis; + axis.model = axisModel; +} + + +var polarCreator = { + + dimensions: Polar.prototype.dimensions, + + create: function (ecModel, api) { + var polarList = []; + ecModel.eachComponent('polar', function (polarModel, idx) { + var polar = new Polar(idx); + // Inject resize and update method + polar.update = updatePolarScale; + + var radiusAxis = polar.getRadiusAxis(); + var angleAxis = polar.getAngleAxis(); + + var radiusAxisModel = polarModel.findAxisModel('radiusAxis'); + var angleAxisModel = polarModel.findAxisModel('angleAxis'); + + setAxis(radiusAxis, radiusAxisModel); + setAxis(angleAxis, angleAxisModel); + + resizePolar(polar, polarModel, api); + + polarList.push(polar); + + polarModel.coordinateSystem = polar; + polar.model = polarModel; + }); + // Inject coordinateSystem to series + ecModel.eachSeries(function (seriesModel) { + if (seriesModel.get('coordinateSystem') === 'polar') { + var polarModel = ecModel.queryComponents({ + mainType: 'polar', + index: seriesModel.get('polarIndex'), + id: seriesModel.get('polarId') + })[0]; + + if (__DEV__) { + if (!polarModel) { + throw new Error( + 'Polar "' + retrieve( + seriesModel.get('polarIndex'), + seriesModel.get('polarId'), + 0 + ) + '" not found' + ); + } + } + seriesModel.coordinateSystem = polarModel.coordinateSystem; + } + }); + + return polarList; + } +}; + +CoordinateSystemManager.register('polar', polarCreator); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var elementList$1 = ['axisLine', 'axisLabel', 'axisTick', 'splitLine', 'splitArea']; + +function getAxisLineShape(polar, rExtent, angle) { + rExtent[1] > rExtent[0] && (rExtent = rExtent.slice().reverse()); + var start = polar.coordToPoint([rExtent[0], angle]); + var end = polar.coordToPoint([rExtent[1], angle]); + + return { + x1: start[0], + y1: start[1], + x2: end[0], + y2: end[1] + }; +} + +function getRadiusIdx(polar) { + var radiusAxis = polar.getRadiusAxis(); + return radiusAxis.inverse ? 0 : 1; +} + +// Remove the last tick which will overlap the first tick +function fixAngleOverlap(list) { + var firstItem = list[0]; + var lastItem = list[list.length - 1]; + if (firstItem + && lastItem + && Math.abs(Math.abs(firstItem.coord - lastItem.coord) - 360) < 1e-4 + ) { + list.pop(); + } +} + +AxisView.extend({ + + type: 'angleAxis', + + axisPointerClass: 'PolarAxisPointer', + + render: function (angleAxisModel, ecModel) { + this.group.removeAll(); + if (!angleAxisModel.get('show')) { + return; + } + + var angleAxis = angleAxisModel.axis; + var polar = angleAxis.polar; + var radiusExtent = polar.getRadiusAxis().getExtent(); + + var ticksAngles = angleAxis.getTicksCoords(); + var labels = map(angleAxis.getViewLabels(), function (labelItem) { + var labelItem = clone(labelItem); + labelItem.coord = angleAxis.dataToCoord(labelItem.tickValue); + return labelItem; + }); + + fixAngleOverlap(labels); + fixAngleOverlap(ticksAngles); + + each$1(elementList$1, function (name) { + if (angleAxisModel.get(name + '.show') + && (!angleAxis.scale.isBlank() || name === 'axisLine') + ) { + this['_' + name](angleAxisModel, polar, ticksAngles, radiusExtent, labels); + } + }, this); + }, + + /** + * @private + */ + _axisLine: function (angleAxisModel, polar, ticksAngles, radiusExtent) { + var lineStyleModel = angleAxisModel.getModel('axisLine.lineStyle'); + + var circle = new Circle({ + shape: { + cx: polar.cx, + cy: polar.cy, + r: radiusExtent[getRadiusIdx(polar)] + }, + style: lineStyleModel.getLineStyle(), + z2: 1, + silent: true + }); + circle.style.fill = null; + + this.group.add(circle); + }, + + /** + * @private + */ + _axisTick: function (angleAxisModel, polar, ticksAngles, radiusExtent) { + var tickModel = angleAxisModel.getModel('axisTick'); + + var tickLen = (tickModel.get('inside') ? -1 : 1) * tickModel.get('length'); + var radius = radiusExtent[getRadiusIdx(polar)]; + + var lines = map(ticksAngles, function (tickAngleItem) { + return new Line({ + shape: getAxisLineShape(polar, [radius, radius + tickLen], tickAngleItem.coord) + }); + }); + this.group.add(mergePath( + lines, { + style: defaults( + tickModel.getModel('lineStyle').getLineStyle(), + { + stroke: angleAxisModel.get('axisLine.lineStyle.color') + } + ) + } + )); + }, + + /** + * @private + */ + _axisLabel: function (angleAxisModel, polar, ticksAngles, radiusExtent, labels) { + var rawCategoryData = angleAxisModel.getCategories(true); + + var commonLabelModel = angleAxisModel.getModel('axisLabel'); + + var labelMargin = commonLabelModel.get('margin'); + + // Use length of ticksAngles because it may remove the last tick to avoid overlapping + each$1(labels, function (labelItem, idx) { + var labelModel = commonLabelModel; + var tickValue = labelItem.tickValue; + + var r = radiusExtent[getRadiusIdx(polar)]; + var p = polar.coordToPoint([r + labelMargin, labelItem.coord]); + var cx = polar.cx; + var cy = polar.cy; + + var labelTextAlign = Math.abs(p[0] - cx) / r < 0.3 + ? 'center' : (p[0] > cx ? 'left' : 'right'); + var labelTextVerticalAlign = Math.abs(p[1] - cy) / r < 0.3 + ? 'middle' : (p[1] > cy ? 'top' : 'bottom'); + + if (rawCategoryData && rawCategoryData[tickValue] && rawCategoryData[tickValue].textStyle) { + labelModel = new Model( + rawCategoryData[tickValue].textStyle, commonLabelModel, commonLabelModel.ecModel + ); + } + + var textEl = new Text({silent: true}); + this.group.add(textEl); + setTextStyle(textEl.style, labelModel, { + x: p[0], + y: p[1], + textFill: labelModel.getTextColor() || angleAxisModel.get('axisLine.lineStyle.color'), + text: labelItem.formattedLabel, + textAlign: labelTextAlign, + textVerticalAlign: labelTextVerticalAlign + }); + }, this); + }, + + /** + * @private + */ + _splitLine: function (angleAxisModel, polar, ticksAngles, radiusExtent) { + var splitLineModel = angleAxisModel.getModel('splitLine'); + var lineStyleModel = splitLineModel.getModel('lineStyle'); + var lineColors = lineStyleModel.get('color'); + var lineCount = 0; + + lineColors = lineColors instanceof Array ? lineColors : [lineColors]; + + var splitLines = []; + + for (var i = 0; i < ticksAngles.length; i++) { + var colorIndex = (lineCount++) % lineColors.length; + splitLines[colorIndex] = splitLines[colorIndex] || []; + splitLines[colorIndex].push(new Line({ + shape: getAxisLineShape(polar, radiusExtent, ticksAngles[i].coord) + })); + } + + // Simple optimization + // Batching the lines if color are the same + for (var i = 0; i < splitLines.length; i++) { + this.group.add(mergePath(splitLines[i], { + style: defaults({ + stroke: lineColors[i % lineColors.length] + }, lineStyleModel.getLineStyle()), + silent: true, + z: angleAxisModel.get('z') + })); + } + }, + + /** + * @private + */ + _splitArea: function (angleAxisModel, polar, ticksAngles, radiusExtent) { + if (!ticksAngles.length) { + return; + } + + var splitAreaModel = angleAxisModel.getModel('splitArea'); + var areaStyleModel = splitAreaModel.getModel('areaStyle'); + var areaColors = areaStyleModel.get('color'); + var lineCount = 0; + + areaColors = areaColors instanceof Array ? areaColors : [areaColors]; + + var splitAreas = []; + + var RADIAN = Math.PI / 180; + var prevAngle = -ticksAngles[0].coord * RADIAN; + var r0 = Math.min(radiusExtent[0], radiusExtent[1]); + var r1 = Math.max(radiusExtent[0], radiusExtent[1]); + + var clockwise = angleAxisModel.get('clockwise'); + + for (var i = 1; i < ticksAngles.length; i++) { + var colorIndex = (lineCount++) % areaColors.length; + splitAreas[colorIndex] = splitAreas[colorIndex] || []; + splitAreas[colorIndex].push(new Sector({ + shape: { + cx: polar.cx, + cy: polar.cy, + r0: r0, + r: r1, + startAngle: prevAngle, + endAngle: -ticksAngles[i].coord * RADIAN, + clockwise: clockwise + }, + silent: true + })); + prevAngle = -ticksAngles[i].coord * RADIAN; + } + + // Simple optimization + // Batching the lines if color are the same + for (var i = 0; i < splitAreas.length; i++) { + this.group.add(mergePath(splitAreas[i], { + style: defaults({ + fill: areaColors[i % areaColors.length] + }, areaStyleModel.getAreaStyle()), + silent: true + })); + } + } +}); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var axisBuilderAttrs$3 = [ + 'axisLine', 'axisTickLabel', 'axisName' +]; +var selfBuilderAttrs$1 = [ + 'splitLine', 'splitArea' +]; + +AxisView.extend({ + + type: 'radiusAxis', + + axisPointerClass: 'PolarAxisPointer', + + render: function (radiusAxisModel, ecModel) { + this.group.removeAll(); + if (!radiusAxisModel.get('show')) { + return; + } + var radiusAxis = radiusAxisModel.axis; + var polar = radiusAxis.polar; + var angleAxis = polar.getAngleAxis(); + var ticksCoords = radiusAxis.getTicksCoords(); + var axisAngle = angleAxis.getExtent()[0]; + var radiusExtent = radiusAxis.getExtent(); + + var layout = layoutAxis(polar, radiusAxisModel, axisAngle); + var axisBuilder = new AxisBuilder(radiusAxisModel, layout); + each$1(axisBuilderAttrs$3, axisBuilder.add, axisBuilder); + this.group.add(axisBuilder.getGroup()); + + each$1(selfBuilderAttrs$1, function (name) { + if (radiusAxisModel.get(name + '.show') && !radiusAxis.scale.isBlank()) { + this['_' + name](radiusAxisModel, polar, axisAngle, radiusExtent, ticksCoords); + } + }, this); + }, + + /** + * @private + */ + _splitLine: function (radiusAxisModel, polar, axisAngle, radiusExtent, ticksCoords) { + var splitLineModel = radiusAxisModel.getModel('splitLine'); + var lineStyleModel = splitLineModel.getModel('lineStyle'); + var lineColors = lineStyleModel.get('color'); + var lineCount = 0; + + lineColors = lineColors instanceof Array ? lineColors : [lineColors]; + + var splitLines = []; + + for (var i = 0; i < ticksCoords.length; i++) { + var colorIndex = (lineCount++) % lineColors.length; + splitLines[colorIndex] = splitLines[colorIndex] || []; + splitLines[colorIndex].push(new Circle({ + shape: { + cx: polar.cx, + cy: polar.cy, + r: ticksCoords[i].coord + }, + silent: true + })); + } + + // Simple optimization + // Batching the lines if color are the same + for (var i = 0; i < splitLines.length; i++) { + this.group.add(mergePath(splitLines[i], { + style: defaults({ + stroke: lineColors[i % lineColors.length], + fill: null + }, lineStyleModel.getLineStyle()), + silent: true + })); + } + }, + + /** + * @private + */ + _splitArea: function (radiusAxisModel, polar, axisAngle, radiusExtent, ticksCoords) { + if (!ticksCoords.length) { + return; + } + + var splitAreaModel = radiusAxisModel.getModel('splitArea'); + var areaStyleModel = splitAreaModel.getModel('areaStyle'); + var areaColors = areaStyleModel.get('color'); + var lineCount = 0; + + areaColors = areaColors instanceof Array ? areaColors : [areaColors]; + + var splitAreas = []; + + var prevRadius = ticksCoords[0].coord; + for (var i = 1; i < ticksCoords.length; i++) { + var colorIndex = (lineCount++) % areaColors.length; + splitAreas[colorIndex] = splitAreas[colorIndex] || []; + splitAreas[colorIndex].push(new Sector({ + shape: { + cx: polar.cx, + cy: polar.cy, + r0: prevRadius, + r: ticksCoords[i].coord, + startAngle: 0, + endAngle: Math.PI * 2 + }, + silent: true + })); + prevRadius = ticksCoords[i].coord; + } + + // Simple optimization + // Batching the lines if color are the same + for (var i = 0; i < splitAreas.length; i++) { + this.group.add(mergePath(splitAreas[i], { + style: defaults({ + fill: areaColors[i % areaColors.length] + }, areaStyleModel.getAreaStyle()), + silent: true + })); + } + } +}); + +/** + * @inner + */ +function layoutAxis(polar, radiusAxisModel, axisAngle) { + return { + position: [polar.cx, polar.cy], + rotation: axisAngle / 180 * Math.PI, + labelDirection: -1, + tickDirection: -1, + nameDirection: 1, + labelRotate: radiusAxisModel.getModel('axisLabel').get('rotate'), + // Over splitLine and splitArea + z2: 1 + }; +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var PolarAxisPointer = BaseAxisPointer.extend({ + + /** + * @override + */ + makeElOption: function (elOption, value, axisModel, axisPointerModel, api) { + var axis = axisModel.axis; + + if (axis.dim === 'angle') { + this.animationThreshold = Math.PI / 18; + } + + var polar = axis.polar; + var otherAxis = polar.getOtherAxis(axis); + var otherExtent = otherAxis.getExtent(); + + var coordValue; + coordValue = axis['dataTo' + capitalFirst(axis.dim)](value); + + var axisPointerType = axisPointerModel.get('type'); + if (axisPointerType && axisPointerType !== 'none') { + var elStyle = buildElStyle(axisPointerModel); + var pointerOption = pointerShapeBuilder$2[axisPointerType]( + axis, polar, coordValue, otherExtent, elStyle + ); + pointerOption.style = elStyle; + elOption.graphicKey = pointerOption.type; + elOption.pointer = pointerOption; + } + + var labelMargin = axisPointerModel.get('label.margin'); + var labelPos = getLabelPosition(value, axisModel, axisPointerModel, polar, labelMargin); + buildLabelElOption(elOption, axisModel, axisPointerModel, api, labelPos); + } + + // Do not support handle, utill any user requires it. + +}); + +function getLabelPosition(value, axisModel, axisPointerModel, polar, labelMargin) { + var axis = axisModel.axis; + var coord = axis.dataToCoord(value); + var axisAngle = polar.getAngleAxis().getExtent()[0]; + axisAngle = axisAngle / 180 * Math.PI; + var radiusExtent = polar.getRadiusAxis().getExtent(); + var position; + var align; + var verticalAlign; + + if (axis.dim === 'radius') { + var transform = create$1(); + rotate(transform, transform, axisAngle); + translate(transform, transform, [polar.cx, polar.cy]); + position = applyTransform$1([coord, -labelMargin], transform); + + var labelRotation = axisModel.getModel('axisLabel').get('rotate') || 0; + var labelLayout = AxisBuilder.innerTextLayout( + axisAngle, labelRotation * Math.PI / 180, -1 + ); + align = labelLayout.textAlign; + verticalAlign = labelLayout.textVerticalAlign; + } + else { // angle axis + var r = radiusExtent[1]; + position = polar.coordToPoint([r + labelMargin, coord]); + var cx = polar.cx; + var cy = polar.cy; + align = Math.abs(position[0] - cx) / r < 0.3 + ? 'center' : (position[0] > cx ? 'left' : 'right'); + verticalAlign = Math.abs(position[1] - cy) / r < 0.3 + ? 'middle' : (position[1] > cy ? 'top' : 'bottom'); + } + + return { + position: position, + align: align, + verticalAlign: verticalAlign + }; +} + + +var pointerShapeBuilder$2 = { + + line: function (axis, polar, coordValue, otherExtent, elStyle) { + return axis.dim === 'angle' + ? { + type: 'Line', + shape: makeLineShape( + polar.coordToPoint([otherExtent[0], coordValue]), + polar.coordToPoint([otherExtent[1], coordValue]) + ) + } + : { + type: 'Circle', + shape: { + cx: polar.cx, + cy: polar.cy, + r: coordValue + } + }; + }, + + shadow: function (axis, polar, coordValue, otherExtent, elStyle) { + var bandWidth = Math.max(1, axis.getBandWidth()); + var radian = Math.PI / 180; + + return axis.dim === 'angle' + ? { + type: 'Sector', + shape: makeSectorShape( + polar.cx, polar.cy, + otherExtent[0], otherExtent[1], + // In ECharts y is negative if angle is positive + (-coordValue - bandWidth / 2) * radian, + (-coordValue + bandWidth / 2) * radian + ) + } + : { + type: 'Sector', + shape: makeSectorShape( + polar.cx, polar.cy, + coordValue - bandWidth / 2, + coordValue + bandWidth / 2, + 0, Math.PI * 2 + ) + }; + } +}; + +AxisView.registerAxisPointerClass('PolarAxisPointer', PolarAxisPointer); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +// For reducing size of echarts.min, barLayoutPolar is required by polar. +registerLayout(curry(barLayoutPolar, 'bar')); + +// Polar view +extendComponentView({ + type: 'polar' +}); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var GeoModel = ComponentModel.extend({ + + type: 'geo', + + /** + * @type {module:echarts/coord/geo/Geo} + */ + coordinateSystem: null, + + layoutMode: 'box', + + init: function (option) { + ComponentModel.prototype.init.apply(this, arguments); + + // Default label emphasis `show` + defaultEmphasis(option, 'label', ['show']); + }, + + optionUpdated: function () { + var option = this.option; + var self = this; + + option.regions = geoCreator.getFilledRegions(option.regions, option.map, option.nameMap); + + this._optionModelMap = reduce(option.regions || [], function (optionModelMap, regionOpt) { + if (regionOpt.name) { + optionModelMap.set(regionOpt.name, new Model(regionOpt, self)); + } + return optionModelMap; + }, createHashMap()); + + this.updateSelectedMap(option.regions); + }, + + defaultOption: { + + zlevel: 0, + + z: 0, + + show: true, + + left: 'center', + + top: 'center', + + + // width:, + // height:, + // right + // bottom + + // Aspect is width / height. Inited to be geoJson bbox aspect + // This parameter is used for scale this aspect + // If svg used, aspectScale is 1 by default. + // aspectScale: 0.75, + aspectScale: null, + + ///// Layout with center and size + // If you wan't to put map in a fixed size box with right aspect ratio + // This two properties may more conveninet + // layoutCenter: [50%, 50%] + // layoutSize: 100 + + silent: false, + + // Map type + map: '', + + // Define left-top, right-bottom coords to control view + // For example, [ [180, 90], [-180, -90] ] + boundingCoords: null, + + // Default on center of map + center: null, + + zoom: 1, + + scaleLimit: null, + + // selectedMode: false + + label: { + show: false, + color: '#000' + }, + + itemStyle: { + // color: 各异, + borderWidth: 0.5, + borderColor: '#444', + color: '#eee' + }, + + emphasis: { + label: { + show: true, + color: 'rgb(100,0,0)' + }, + itemStyle: { + color: 'rgba(255,215,0,0.8)' + } + }, + + regions: [] + }, + + /** + * Get model of region + * @param {string} name + * @return {module:echarts/model/Model} + */ + getRegionModel: function (name) { + return this._optionModelMap.get(name) || new Model(null, this, this.ecModel); + }, + + /** + * Format label + * @param {string} name Region name + * @param {string} [status='normal'] 'normal' or 'emphasis' + * @return {string} + */ + getFormattedLabel: function (name, status) { + var regionModel = this.getRegionModel(name); + var formatter = regionModel.get('label.' + status + '.formatter'); + var params = { + name: name + }; + if (typeof formatter === 'function') { + params.status = status; + return formatter(params); + } + else if (typeof formatter === 'string') { + return formatter.replace('{a}', name != null ? name : ''); + } + }, + + setZoom: function (zoom) { + this.option.zoom = zoom; + }, + + setCenter: function (center) { + this.option.center = center; + } +}); + +mixin(GeoModel, selectableMixin); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +extendComponentView({ + + type: 'geo', + + init: function (ecModel, api) { + var mapDraw = new MapDraw(api, true); + this._mapDraw = mapDraw; + + this.group.add(mapDraw.group); + }, + + render: function (geoModel, ecModel, api, payload) { + // Not render if it is an toggleSelect action from self + if (payload && payload.type === 'geoToggleSelect' + && payload.from === this.uid + ) { + return; + } + + var mapDraw = this._mapDraw; + if (geoModel.get('show')) { + mapDraw.draw(geoModel, ecModel, api, this, payload); + } + else { + this._mapDraw.group.removeAll(); + } + + this.group.silent = geoModel.get('silent'); + }, + + dispose: function () { + this._mapDraw && this._mapDraw.remove(); + } + +}); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +function makeAction(method, actionInfo) { + actionInfo.update = 'updateView'; + registerAction(actionInfo, function (payload, ecModel) { + var selected = {}; + + ecModel.eachComponent( + { mainType: 'geo', query: payload}, + function (geoModel) { + geoModel[method](payload.name); + var geo = geoModel.coordinateSystem; + each$1(geo.regions, function (region) { + selected[region.name] = geoModel.isSelected(region.name) || false; + }); + } + ); + + return { + selected: selected, + name: payload.name + }; + }); +} + +makeAction('toggleSelected', { + type: 'geoToggleSelect', + event: 'geoselectchanged' +}); +makeAction('select', { + type: 'geoSelect', + event: 'geoselected' +}); +makeAction('unSelect', { + type: 'geoUnSelect', + event: 'geounselected' +}); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var DEFAULT_TOOLBOX_BTNS = ['rect', 'polygon', 'keep', 'clear']; + +var preprocessor$1 = function (option, isNew) { + var brushComponents = option && option.brush; + if (!isArray(brushComponents)) { + brushComponents = brushComponents ? [brushComponents] : []; + } + + if (!brushComponents.length) { + return; + } + + var brushComponentSpecifiedBtns = []; + + each$1(brushComponents, function (brushOpt) { + var tbs = brushOpt.hasOwnProperty('toolbox') + ? brushOpt.toolbox : []; + + if (tbs instanceof Array) { + brushComponentSpecifiedBtns = brushComponentSpecifiedBtns.concat(tbs); + } + }); + + var toolbox = option && option.toolbox; + + if (isArray(toolbox)) { + toolbox = toolbox[0]; + } + if (!toolbox) { + toolbox = {feature: {}}; + option.toolbox = [toolbox]; + } + + var toolboxFeature = (toolbox.feature || (toolbox.feature = {})); + var toolboxBrush = toolboxFeature.brush || (toolboxFeature.brush = {}); + var brushTypes = toolboxBrush.type || (toolboxBrush.type = []); + + brushTypes.push.apply(brushTypes, brushComponentSpecifiedBtns); + + removeDuplicate(brushTypes); + + if (isNew && !brushTypes.length) { + brushTypes.push.apply(brushTypes, DEFAULT_TOOLBOX_BTNS); + } +}; + +function removeDuplicate(arr) { + var map$$1 = {}; + each$1(arr, function (val) { + map$$1[val] = 1; + }); + arr.length = 0; + each$1(map$$1, function (flag, val) { + arr.push(val); + }); +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/** + * @file Visual solution, for consistent option specification. + */ + +var each$19 = each$1; + +function hasKeys(obj) { + if (obj) { + for (var name in obj) { + if (obj.hasOwnProperty(name)) { + return true; + } + } + } +} + +/** + * @param {Object} option + * @param {Array.} stateList + * @param {Function} [supplementVisualOption] + * @return {Object} visualMappings > + */ +function createVisualMappings(option, stateList, supplementVisualOption) { + var visualMappings = {}; + + each$19(stateList, function (state) { + var mappings = visualMappings[state] = createMappings(); + + each$19(option[state], function (visualData, visualType) { + if (!VisualMapping.isValidType(visualType)) { + return; + } + var mappingOption = { + type: visualType, + visual: visualData + }; + supplementVisualOption && supplementVisualOption(mappingOption, state); + mappings[visualType] = new VisualMapping(mappingOption); + + // Prepare a alpha for opacity, for some case that opacity + // is not supported, such as rendering using gradient color. + if (visualType === 'opacity') { + mappingOption = clone(mappingOption); + mappingOption.type = 'colorAlpha'; + mappings.__hidden.__alphaForOpacity = new VisualMapping(mappingOption); + } + }); + }); + + return visualMappings; + + function createMappings() { + var Creater = function () {}; + // Make sure hidden fields will not be visited by + // object iteration (with hasOwnProperty checking). + Creater.prototype.__hidden = Creater.prototype; + var obj = new Creater(); + return obj; + } +} + +/** + * @param {Object} thisOption + * @param {Object} newOption + * @param {Array.} keys + */ +function replaceVisualOption(thisOption, newOption, keys) { + // Visual attributes merge is not supported, otherwise it + // brings overcomplicated merge logic. See #2853. So if + // newOption has anyone of these keys, all of these keys + // will be reset. Otherwise, all keys remain. + var has; + each$1(keys, function (key) { + if (newOption.hasOwnProperty(key) && hasKeys(newOption[key])) { + has = true; + } + }); + has && each$1(keys, function (key) { + if (newOption.hasOwnProperty(key) && hasKeys(newOption[key])) { + thisOption[key] = clone(newOption[key]); + } + else { + delete thisOption[key]; + } + }); +} + +/** + * @param {Array.} stateList + * @param {Object} visualMappings > + * @param {module:echarts/data/List} list + * @param {Function} getValueState param: valueOrIndex, return: state. + * @param {object} [scope] Scope for getValueState + * @param {string} [dimension] Concrete dimension, if used. + */ +// ???! handle brush? +function applyVisual(stateList, visualMappings, data, getValueState, scope, dimension) { + var visualTypesMap = {}; + each$1(stateList, function (state) { + var visualTypes = VisualMapping.prepareVisualTypes(visualMappings[state]); + visualTypesMap[state] = visualTypes; + }); + + var dataIndex; + + function getVisual(key) { + return data.getItemVisual(dataIndex, key); + } + + function setVisual(key, value) { + data.setItemVisual(dataIndex, key, value); + } + + if (dimension == null) { + data.each(eachItem); + } + else { + data.each([dimension], eachItem); + } + + function eachItem(valueOrIndex, index) { + dataIndex = dimension == null ? valueOrIndex : index; + + var rawDataItem = data.getRawDataItem(dataIndex); + // Consider performance + if (rawDataItem && rawDataItem.visualMap === false) { + return; + } + + var valueState = getValueState.call(scope, valueOrIndex); + var mappings = visualMappings[valueState]; + var visualTypes = visualTypesMap[valueState]; + + for (var i = 0, len = visualTypes.length; i < len; i++) { + var type = visualTypes[i]; + mappings[type] && mappings[type].applyVisual( + valueOrIndex, getVisual, setVisual + ); + } + } +} + +/** + * @param {module:echarts/data/List} data + * @param {Array.} stateList + * @param {Object} visualMappings > + * @param {Function} getValueState param: valueOrIndex, return: state. + * @param {number} [dim] dimension or dimension index. + */ +function incrementalApplyVisual(stateList, visualMappings, getValueState, dim) { + var visualTypesMap = {}; + each$1(stateList, function (state) { + var visualTypes = VisualMapping.prepareVisualTypes(visualMappings[state]); + visualTypesMap[state] = visualTypes; + }); + + function progress(params, data) { + if (dim != null) { + dim = data.getDimension(dim); + } + + function getVisual(key) { + return data.getItemVisual(dataIndex, key); + } + + function setVisual(key, value) { + data.setItemVisual(dataIndex, key, value); + } + + var dataIndex; + while ((dataIndex = params.next()) != null) { + var rawDataItem = data.getRawDataItem(dataIndex); + + // Consider performance + if (rawDataItem && rawDataItem.visualMap === false) { + continue; + } + + var value = dim != null + ? data.get(dim, dataIndex, true) + : dataIndex; + + var valueState = getValueState(value); + var mappings = visualMappings[valueState]; + var visualTypes = visualTypesMap[valueState]; + + for (var i = 0, len = visualTypes.length; i < len; i++) { + var type = visualTypes[i]; + mappings[type] && mappings[type].applyVisual(value, getVisual, setVisual); + } + } + } + + return {progress: progress}; +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +// Key of the first level is brushType: `line`, `rect`, `polygon`. +// Key of the second level is chart element type: `point`, `rect`. +// See moudule:echarts/component/helper/BrushController +// function param: +// {Object} itemLayout fetch from data.getItemLayout(dataIndex) +// {Object} selectors {point: selector, rect: selector, ...} +// {Object} area {range: [[], [], ..], boudingRect} +// function return: +// {boolean} Whether in the given brush. +var selector = { + lineX: getLineSelectors(0), + lineY: getLineSelectors(1), + rect: { + point: function (itemLayout, selectors, area) { + return itemLayout && area.boundingRect.contain(itemLayout[0], itemLayout[1]); + }, + rect: function (itemLayout, selectors, area) { + return itemLayout && area.boundingRect.intersect(itemLayout); + } + }, + polygon: { + point: function (itemLayout, selectors, area) { + return itemLayout + && area.boundingRect.contain(itemLayout[0], itemLayout[1]) + && contain$1(area.range, itemLayout[0], itemLayout[1]); + }, + rect: function (itemLayout, selectors, area) { + var points = area.range; + + if (!itemLayout || points.length <= 1) { + return false; + } + + var x = itemLayout.x; + var y = itemLayout.y; + var width = itemLayout.width; + var height = itemLayout.height; + var p = points[0]; + + if (contain$1(points, x, y) + || contain$1(points, x + width, y) + || contain$1(points, x, y + height) + || contain$1(points, x + width, y + height) + || BoundingRect.create(itemLayout).contain(p[0], p[1]) + || lineIntersectPolygon(x, y, x + width, y, points) + || lineIntersectPolygon(x, y, x, y + height, points) + || lineIntersectPolygon(x + width, y, x + width, y + height, points) + || lineIntersectPolygon(x, y + height, x + width, y + height, points) + ) { + return true; + } + } + } +}; + +function getLineSelectors(xyIndex) { + var xy = ['x', 'y']; + var wh = ['width', 'height']; + + return { + point: function (itemLayout, selectors, area) { + if (itemLayout) { + var range = area.range; + var p = itemLayout[xyIndex]; + return inLineRange(p, range); + } + }, + rect: function (itemLayout, selectors, area) { + if (itemLayout) { + var range = area.range; + var layoutRange = [ + itemLayout[xy[xyIndex]], + itemLayout[xy[xyIndex]] + itemLayout[wh[xyIndex]] + ]; + layoutRange[1] < layoutRange[0] && layoutRange.reverse(); + return inLineRange(layoutRange[0], range) + || inLineRange(layoutRange[1], range) + || inLineRange(range[0], layoutRange) + || inLineRange(range[1], layoutRange); + } + } + }; +} + +function inLineRange(p, range) { + return range[0] <= p && p <= range[1]; +} + +function lineIntersectPolygon(lx, ly, l2x, l2y, points) { + for (var i = 0, p2 = points[points.length - 1]; i < points.length; i++) { + var p = points[i]; + if (lineIntersect(lx, ly, l2x, l2y, p[0], p[1], p2[0], p2[1])) { + return true; + } + p2 = p; + } +} + +// Code from with some fix. +// See +function lineIntersect(a1x, a1y, a2x, a2y, b1x, b1y, b2x, b2y) { + var delta = determinant(a2x - a1x, b1x - b2x, a2y - a1y, b1y - b2y); + if (nearZero(delta)) { // parallel + return false; + } + var namenda = determinant(b1x - a1x, b1x - b2x, b1y - a1y, b1y - b2y) / delta; + if (namenda < 0 || namenda > 1) { + return false; + } + var miu = determinant(a2x - a1x, b1x - a1x, a2y - a1y, b1y - a1y) / delta; + if (miu < 0 || miu > 1) { + return false; + } + return true; +} + +function nearZero(val) { + return val <= (1e-6) && val >= -(1e-6); +} + +function determinant(v1, v2, v3, v4) { + return v1 * v4 - v2 * v3; +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var each$20 = each$1; +var indexOf$1 = indexOf; +var curry$5 = curry; + +var COORD_CONVERTS = ['dataToPoint', 'pointToData']; + +// FIXME +// how to genarialize to more coordinate systems. +var INCLUDE_FINDER_MAIN_TYPES = [ + 'grid', 'xAxis', 'yAxis', 'geo', 'graph', + 'polar', 'radiusAxis', 'angleAxis', 'bmap' +]; + +/** + * [option in constructor]: + * { + * Index/Id/Name of geo, xAxis, yAxis, grid: See util/model#parseFinder. + * } + * + * + * [targetInfo]: + * + * There can be multiple axes in a single targetInfo. Consider the case + * of `grid` component, a targetInfo represents a grid which contains one or more + * cartesian and one or more axes. And consider the case of parallel system, + * which has multiple axes in a coordinate system. + * Can be { + * panelId: ..., + * coordSys: , + * coordSyses: all cartesians. + * gridModel: + * xAxes: correspond to coordSyses on index + * yAxes: correspond to coordSyses on index + * } + * or { + * panelId: ..., + * coordSys: + * coordSyses: [] + * geoModel: + * } + * + * + * [panelOpt]: + * + * Make from targetInfo. Input to BrushController. + * { + * panelId: ..., + * rect: ... + * } + * + * + * [area]: + * + * Generated by BrushController or user input. + * { + * panelId: Used to locate coordInfo directly. If user inpput, no panelId. + * brushType: determine how to convert to/from coord('rect' or 'polygon' or 'lineX/Y'). + * Index/Id/Name of geo, xAxis, yAxis, grid: See util/model#parseFinder. + * range: pixel range. + * coordRange: representitive coord range (the first one of coordRanges). + * coordRanges: coord ranges, used in multiple cartesian in one grid. + * } + */ + +/** + * @param {Object} option contains Index/Id/Name of xAxis/yAxis/geo/grid + * Each can be {number|Array.}. like: {xAxisIndex: [3, 4]} + * @param {module:echarts/model/Global} ecModel + * @param {Object} [opt] + * @param {Array.} [opt.include] include coordinate system types. + */ +function BrushTargetManager(option, ecModel, opt) { + /** + * @private + * @type {Array.} + */ + var targetInfoList = this._targetInfoList = []; + var info = {}; + var foundCpts = parseFinder$1(ecModel, option); + + each$20(targetInfoBuilders, function (builder, type) { + if (!opt || !opt.include || indexOf$1(opt.include, type) >= 0) { + builder(foundCpts, targetInfoList, info); + } + }); +} + +var proto$2 = BrushTargetManager.prototype; + +proto$2.setOutputRanges = function (areas, ecModel) { + this.matchOutputRanges(areas, ecModel, function (area, coordRange, coordSys) { + (area.coordRanges || (area.coordRanges = [])).push(coordRange); + // area.coordRange is the first of area.coordRanges + if (!area.coordRange) { + area.coordRange = coordRange; + // In 'category' axis, coord to pixel is not reversible, so we can not + // rebuild range by coordRange accrately, which may bring trouble when + // brushing only one item. So we use __rangeOffset to rebuilding range + // by coordRange. And this it only used in brush component so it is no + // need to be adapted to coordRanges. + var result = coordConvert[area.brushType](0, coordSys, coordRange); + area.__rangeOffset = { + offset: diffProcessor[area.brushType](result.values, area.range, [1, 1]), + xyMinMax: result.xyMinMax + }; + } + }); +}; + +proto$2.matchOutputRanges = function (areas, ecModel, cb) { + each$20(areas, function (area) { + var targetInfo = this.findTargetInfo(area, ecModel); + + if (targetInfo && targetInfo !== true) { + each$1( + targetInfo.coordSyses, + function (coordSys) { + var result = coordConvert[area.brushType](1, coordSys, area.range); + cb(area, result.values, coordSys, ecModel); + } + ); + } + }, this); +}; + +proto$2.setInputRanges = function (areas, ecModel) { + each$20(areas, function (area) { + var targetInfo = this.findTargetInfo(area, ecModel); + + if (__DEV__) { + assert$1( + !targetInfo || targetInfo === true || area.coordRange, + 'coordRange must be specified when coord index specified.' + ); + assert$1( + !targetInfo || targetInfo !== true || area.range, + 'range must be specified in global brush.' + ); + } + + area.range = area.range || []; + + // convert coordRange to global range and set panelId. + if (targetInfo && targetInfo !== true) { + area.panelId = targetInfo.panelId; + // (1) area.range shoule always be calculate from coordRange but does + // not keep its original value, for the sake of the dataZoom scenario, + // where area.coordRange remains unchanged but area.range may be changed. + // (2) Only support converting one coordRange to pixel range in brush + // component. So do not consider `coordRanges`. + // (3) About __rangeOffset, see comment above. + var result = coordConvert[area.brushType](0, targetInfo.coordSys, area.coordRange); + var rangeOffset = area.__rangeOffset; + area.range = rangeOffset + ? diffProcessor[area.brushType]( + result.values, + rangeOffset.offset, + getScales(result.xyMinMax, rangeOffset.xyMinMax) + ) + : result.values; + } + }, this); +}; + +proto$2.makePanelOpts = function (api, getDefaultBrushType) { + return map(this._targetInfoList, function (targetInfo) { + var rect = targetInfo.getPanelRect(); + return { + panelId: targetInfo.panelId, + defaultBrushType: getDefaultBrushType && getDefaultBrushType(targetInfo), + clipPath: makeRectPanelClipPath(rect), + isTargetByCursor: makeRectIsTargetByCursor( + rect, api, targetInfo.coordSysModel + ), + getLinearBrushOtherExtent: makeLinearBrushOtherExtent(rect) + }; + }); +}; + +proto$2.controlSeries = function (area, seriesModel, ecModel) { + // Check whether area is bound in coord, and series do not belong to that coord. + // If do not do this check, some brush (like lineX) will controll all axes. + var targetInfo = this.findTargetInfo(area, ecModel); + return targetInfo === true || ( + targetInfo && indexOf$1(targetInfo.coordSyses, seriesModel.coordinateSystem) >= 0 + ); +}; + +/** + * If return Object, a coord found. + * If reutrn true, global found. + * Otherwise nothing found. + * + * @param {Object} area + * @param {Array} targetInfoList + * @return {Object|boolean} + */ +proto$2.findTargetInfo = function (area, ecModel) { + var targetInfoList = this._targetInfoList; + var foundCpts = parseFinder$1(ecModel, area); + + for (var i = 0; i < targetInfoList.length; i++) { + var targetInfo = targetInfoList[i]; + var areaPanelId = area.panelId; + if (areaPanelId) { + if (targetInfo.panelId === areaPanelId) { + return targetInfo; + } + } + else { + for (var i = 0; i < targetInfoMatchers.length; i++) { + if (targetInfoMatchers[i](foundCpts, targetInfo)) { + return targetInfo; + } + } + } + } + + return true; +}; + +function formatMinMax(minMax) { + minMax[0] > minMax[1] && minMax.reverse(); + return minMax; +} + +function parseFinder$1(ecModel, option) { + return parseFinder( + ecModel, option, {includeMainTypes: INCLUDE_FINDER_MAIN_TYPES} + ); +} + +var targetInfoBuilders = { + + grid: function (foundCpts, targetInfoList) { + var xAxisModels = foundCpts.xAxisModels; + var yAxisModels = foundCpts.yAxisModels; + var gridModels = foundCpts.gridModels; + // Remove duplicated. + var gridModelMap = createHashMap(); + var xAxesHas = {}; + var yAxesHas = {}; + + if (!xAxisModels && !yAxisModels && !gridModels) { + return; + } + + each$20(xAxisModels, function (axisModel) { + var gridModel = axisModel.axis.grid.model; + gridModelMap.set(gridModel.id, gridModel); + xAxesHas[gridModel.id] = true; + }); + each$20(yAxisModels, function (axisModel) { + var gridModel = axisModel.axis.grid.model; + gridModelMap.set(gridModel.id, gridModel); + yAxesHas[gridModel.id] = true; + }); + each$20(gridModels, function (gridModel) { + gridModelMap.set(gridModel.id, gridModel); + xAxesHas[gridModel.id] = true; + yAxesHas[gridModel.id] = true; + }); + + gridModelMap.each(function (gridModel) { + var grid = gridModel.coordinateSystem; + var cartesians = []; + + each$20(grid.getCartesians(), function (cartesian, index) { + if (indexOf$1(xAxisModels, cartesian.getAxis('x').model) >= 0 + || indexOf$1(yAxisModels, cartesian.getAxis('y').model) >= 0 + ) { + cartesians.push(cartesian); + } + }); + targetInfoList.push({ + panelId: 'grid--' + gridModel.id, + gridModel: gridModel, + coordSysModel: gridModel, + // Use the first one as the representitive coordSys. + coordSys: cartesians[0], + coordSyses: cartesians, + getPanelRect: panelRectBuilder.grid, + xAxisDeclared: xAxesHas[gridModel.id], + yAxisDeclared: yAxesHas[gridModel.id] + }); + }); + }, + + geo: function (foundCpts, targetInfoList) { + each$20(foundCpts.geoModels, function (geoModel) { + var coordSys = geoModel.coordinateSystem; + targetInfoList.push({ + panelId: 'geo--' + geoModel.id, + geoModel: geoModel, + coordSysModel: geoModel, + coordSys: coordSys, + coordSyses: [coordSys], + getPanelRect: panelRectBuilder.geo + }); + }); + } +}; + +var targetInfoMatchers = [ + + // grid + function (foundCpts, targetInfo) { + var xAxisModel = foundCpts.xAxisModel; + var yAxisModel = foundCpts.yAxisModel; + var gridModel = foundCpts.gridModel; + + !gridModel && xAxisModel && (gridModel = xAxisModel.axis.grid.model); + !gridModel && yAxisModel && (gridModel = yAxisModel.axis.grid.model); + + return gridModel && gridModel === targetInfo.gridModel; + }, + + // geo + function (foundCpts, targetInfo) { + var geoModel = foundCpts.geoModel; + return geoModel && geoModel === targetInfo.geoModel; + } +]; + +var panelRectBuilder = { + + grid: function () { + // grid is not Transformable. + return this.coordSys.grid.getRect().clone(); + }, + + geo: function () { + var coordSys = this.coordSys; + var rect = coordSys.getBoundingRect().clone(); + // geo roam and zoom transform + rect.applyTransform(getTransform(coordSys)); + return rect; + } +}; + +var coordConvert = { + + lineX: curry$5(axisConvert, 0), + + lineY: curry$5(axisConvert, 1), + + rect: function (to, coordSys, rangeOrCoordRange) { + var xminymin = coordSys[COORD_CONVERTS[to]]([rangeOrCoordRange[0][0], rangeOrCoordRange[1][0]]); + var xmaxymax = coordSys[COORD_CONVERTS[to]]([rangeOrCoordRange[0][1], rangeOrCoordRange[1][1]]); + var values = [ + formatMinMax([xminymin[0], xmaxymax[0]]), + formatMinMax([xminymin[1], xmaxymax[1]]) + ]; + return {values: values, xyMinMax: values}; + }, + + polygon: function (to, coordSys, rangeOrCoordRange) { + var xyMinMax = [[Infinity, -Infinity], [Infinity, -Infinity]]; + var values = map(rangeOrCoordRange, function (item) { + var p = coordSys[COORD_CONVERTS[to]](item); + xyMinMax[0][0] = Math.min(xyMinMax[0][0], p[0]); + xyMinMax[1][0] = Math.min(xyMinMax[1][0], p[1]); + xyMinMax[0][1] = Math.max(xyMinMax[0][1], p[0]); + xyMinMax[1][1] = Math.max(xyMinMax[1][1], p[1]); + return p; + }); + return {values: values, xyMinMax: xyMinMax}; + } +}; + +function axisConvert(axisNameIndex, to, coordSys, rangeOrCoordRange) { + if (__DEV__) { + assert$1( + coordSys.type === 'cartesian2d', + 'lineX/lineY brush is available only in cartesian2d.' + ); + } + + var axis = coordSys.getAxis(['x', 'y'][axisNameIndex]); + var values = formatMinMax(map([0, 1], function (i) { + return to + ? axis.coordToData(axis.toLocalCoord(rangeOrCoordRange[i])) + : axis.toGlobalCoord(axis.dataToCoord(rangeOrCoordRange[i])); + })); + var xyMinMax = []; + xyMinMax[axisNameIndex] = values; + xyMinMax[1 - axisNameIndex] = [NaN, NaN]; + + return {values: values, xyMinMax: xyMinMax}; +} + +var diffProcessor = { + lineX: curry$5(axisDiffProcessor, 0), + + lineY: curry$5(axisDiffProcessor, 1), + + rect: function (values, refer, scales) { + return [ + [values[0][0] - scales[0] * refer[0][0], values[0][1] - scales[0] * refer[0][1]], + [values[1][0] - scales[1] * refer[1][0], values[1][1] - scales[1] * refer[1][1]] + ]; + }, + + polygon: function (values, refer, scales) { + return map(values, function (item, idx) { + return [item[0] - scales[0] * refer[idx][0], item[1] - scales[1] * refer[idx][1]]; + }); + } +}; + +function axisDiffProcessor(axisNameIndex, values, refer, scales) { + return [ + values[0] - scales[axisNameIndex] * refer[0], + values[1] - scales[axisNameIndex] * refer[1] + ]; +} + +// We have to process scale caused by dataZoom manually, +// although it might be not accurate. +function getScales(xyMinMaxCurr, xyMinMaxOrigin) { + var sizeCurr = getSize(xyMinMaxCurr); + var sizeOrigin = getSize(xyMinMaxOrigin); + var scales = [sizeCurr[0] / sizeOrigin[0], sizeCurr[1] / sizeOrigin[1]]; + isNaN(scales[0]) && (scales[0] = 1); + isNaN(scales[1]) && (scales[1] = 1); + return scales; +} + +function getSize(xyMinMax) { + return xyMinMax + ? [xyMinMax[0][1] - xyMinMax[0][0], xyMinMax[1][1] - xyMinMax[1][0]] + : [NaN, NaN]; +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var STATE_LIST = ['inBrush', 'outOfBrush']; +var DISPATCH_METHOD = '__ecBrushSelect'; +var DISPATCH_FLAG = '__ecInBrushSelectEvent'; +var PRIORITY_BRUSH = PRIORITY.VISUAL.BRUSH; + +/** + * Layout for visual, the priority higher than other layout, and before brush visual. + */ +registerLayout(PRIORITY_BRUSH, function (ecModel, api, payload) { + ecModel.eachComponent({mainType: 'brush'}, function (brushModel) { + + payload && payload.type === 'takeGlobalCursor' && brushModel.setBrushOption( + payload.key === 'brush' ? payload.brushOption : {brushType: false} + ); + + var brushTargetManager = brushModel.brushTargetManager = new BrushTargetManager(brushModel.option, ecModel); + + brushTargetManager.setInputRanges(brushModel.areas, ecModel); + }); +}); + +/** + * Register the visual encoding if this modules required. + */ +registerVisual(PRIORITY_BRUSH, function (ecModel, api, payload) { + + var brushSelected = []; + var throttleType; + var throttleDelay; + + ecModel.eachComponent({mainType: 'brush'}, function (brushModel, brushIndex) { + + var thisBrushSelected = { + brushId: brushModel.id, + brushIndex: brushIndex, + brushName: brushModel.name, + areas: clone(brushModel.areas), + selected: [] + }; + // Every brush component exists in event params, convenient + // for user to find by index. + brushSelected.push(thisBrushSelected); + + var brushOption = brushModel.option; + var brushLink = brushOption.brushLink; + var linkedSeriesMap = []; + var selectedDataIndexForLink = []; + var rangeInfoBySeries = []; + var hasBrushExists = 0; + + if (!brushIndex) { // Only the first throttle setting works. + throttleType = brushOption.throttleType; + throttleDelay = brushOption.throttleDelay; + } + + // Add boundingRect and selectors to range. + var areas = map(brushModel.areas, function (area) { + return bindSelector( + defaults( + {boundingRect: boundingRectBuilders[area.brushType](area)}, + area + ) + ); + }); + + var visualMappings = createVisualMappings( + brushModel.option, STATE_LIST, function (mappingOption) { + mappingOption.mappingMethod = 'fixed'; + } + ); + + isArray(brushLink) && each$1(brushLink, function (seriesIndex) { + linkedSeriesMap[seriesIndex] = 1; + }); + + function linkOthers(seriesIndex) { + return brushLink === 'all' || linkedSeriesMap[seriesIndex]; + } + + // If no supported brush or no brush on the series, + // all visuals should be in original state. + function brushed(rangeInfoList) { + return !!rangeInfoList.length; + } + + /** + * Logic for each series: (If the logic has to be modified one day, do it carefully!) + * + * ( brushed ┬ && ┬hasBrushExist ┬ && linkOthers ) => StepA: ┬record, ┬ StepB: ┬visualByRecord. + * !brushed┘ ├hasBrushExist ┤ └nothing,┘ ├visualByRecord. + * └!hasBrushExist┘ └nothing. + * ( !brushed && ┬hasBrushExist ┬ && linkOthers ) => StepA: nothing, StepB: ┬visualByRecord. + * └!hasBrushExist┘ └nothing. + * ( brushed ┬ && !linkOthers ) => StepA: nothing, StepB: ┬visualByCheck. + * !brushed┘ └nothing. + * ( !brushed && !linkOthers ) => StepA: nothing, StepB: nothing. + */ + + // Step A + ecModel.eachSeries(function (seriesModel, seriesIndex) { + var rangeInfoList = rangeInfoBySeries[seriesIndex] = []; + + seriesModel.subType === 'parallel' + ? stepAParallel(seriesModel, seriesIndex, rangeInfoList) + : stepAOthers(seriesModel, seriesIndex, rangeInfoList); + }); + + function stepAParallel(seriesModel, seriesIndex) { + var coordSys = seriesModel.coordinateSystem; + hasBrushExists |= coordSys.hasAxisBrushed(); + + linkOthers(seriesIndex) && coordSys.eachActiveState( + seriesModel.getData(), + function (activeState, dataIndex) { + activeState === 'active' && (selectedDataIndexForLink[dataIndex] = 1); + } + ); + } + + function stepAOthers(seriesModel, seriesIndex, rangeInfoList) { + var selectorsByBrushType = getSelectorsByBrushType(seriesModel); + if (!selectorsByBrushType || brushModelNotControll(brushModel, seriesIndex)) { + return; + } + + each$1(areas, function (area) { + selectorsByBrushType[area.brushType] + && brushModel.brushTargetManager.controlSeries(area, seriesModel, ecModel) + && rangeInfoList.push(area); + hasBrushExists |= brushed(rangeInfoList); + }); + + if (linkOthers(seriesIndex) && brushed(rangeInfoList)) { + var data = seriesModel.getData(); + data.each(function (dataIndex) { + if (checkInRange(selectorsByBrushType, rangeInfoList, data, dataIndex)) { + selectedDataIndexForLink[dataIndex] = 1; + } + }); + } + } + + // Step B + ecModel.eachSeries(function (seriesModel, seriesIndex) { + var seriesBrushSelected = { + seriesId: seriesModel.id, + seriesIndex: seriesIndex, + seriesName: seriesModel.name, + dataIndex: [] + }; + // Every series exists in event params, convenient + // for user to find series by seriesIndex. + thisBrushSelected.selected.push(seriesBrushSelected); + + var selectorsByBrushType = getSelectorsByBrushType(seriesModel); + var rangeInfoList = rangeInfoBySeries[seriesIndex]; + + var data = seriesModel.getData(); + var getValueState = linkOthers(seriesIndex) + ? function (dataIndex) { + return selectedDataIndexForLink[dataIndex] + ? (seriesBrushSelected.dataIndex.push(data.getRawIndex(dataIndex)), 'inBrush') + : 'outOfBrush'; + } + : function (dataIndex) { + return checkInRange(selectorsByBrushType, rangeInfoList, data, dataIndex) + ? (seriesBrushSelected.dataIndex.push(data.getRawIndex(dataIndex)), 'inBrush') + : 'outOfBrush'; + }; + + // If no supported brush or no brush, all visuals are in original state. + (linkOthers(seriesIndex) ? hasBrushExists : brushed(rangeInfoList)) + && applyVisual( + STATE_LIST, visualMappings, data, getValueState + ); + }); + + }); + + dispatchAction(api, throttleType, throttleDelay, brushSelected, payload); +}); + +function dispatchAction(api, throttleType, throttleDelay, brushSelected, payload) { + // This event will not be triggered when `setOpion`, otherwise dead lock may + // triggered when do `setOption` in event listener, which we do not find + // satisfactory way to solve yet. Some considered resolutions: + // (a) Diff with prevoius selected data ant only trigger event when changed. + // But store previous data and diff precisely (i.e., not only by dataIndex, but + // also detect value changes in selected data) might bring complexity or fragility. + // (b) Use spectial param like `silent` to suppress event triggering. + // But such kind of volatile param may be weird in `setOption`. + if (!payload) { + return; + } + + var zr = api.getZr(); + if (zr[DISPATCH_FLAG]) { + return; + } + + if (!zr[DISPATCH_METHOD]) { + zr[DISPATCH_METHOD] = doDispatch; + } + + var fn = createOrUpdate(zr, DISPATCH_METHOD, throttleDelay, throttleType); + + fn(api, brushSelected); +} + +function doDispatch(api, brushSelected) { + if (!api.isDisposed()) { + var zr = api.getZr(); + zr[DISPATCH_FLAG] = true; + api.dispatchAction({ + type: 'brushSelect', + batch: brushSelected + }); + zr[DISPATCH_FLAG] = false; + } +} + +function checkInRange(selectorsByBrushType, rangeInfoList, data, dataIndex) { + for (var i = 0, len = rangeInfoList.length; i < len; i++) { + var area = rangeInfoList[i]; + if (selectorsByBrushType[area.brushType]( + dataIndex, data, area.selectors, area + )) { + return true; + } + } +} + +function getSelectorsByBrushType(seriesModel) { + var brushSelector = seriesModel.brushSelector; + if (isString(brushSelector)) { + var sels = []; + each$1(selector, function (selectorsByElementType, brushType) { + sels[brushType] = function (dataIndex, data, selectors, area) { + var itemLayout = data.getItemLayout(dataIndex); + return selectorsByElementType[brushSelector](itemLayout, selectors, area); + }; + }); + return sels; + } + else if (isFunction$1(brushSelector)) { + var bSelector = {}; + each$1(selector, function (sel, brushType) { + bSelector[brushType] = brushSelector; + }); + return bSelector; + } + return brushSelector; +} + +function brushModelNotControll(brushModel, seriesIndex) { + var seriesIndices = brushModel.option.seriesIndex; + return seriesIndices != null + && seriesIndices !== 'all' + && ( + isArray(seriesIndices) + ? indexOf(seriesIndices, seriesIndex) < 0 + : seriesIndex !== seriesIndices + ); +} + +function bindSelector(area) { + var selectors = area.selectors = {}; + each$1(selector[area.brushType], function (selFn, elType) { + // Do not use function binding or curry for performance. + selectors[elType] = function (itemLayout) { + return selFn(itemLayout, selectors, area); + }; + }); + return area; +} + +var boundingRectBuilders = { + + lineX: noop, + + lineY: noop, + + rect: function (area) { + return getBoundingRectFromMinMax(area.range); + }, + + polygon: function (area) { + var minMax; + var range = area.range; + + for (var i = 0, len = range.length; i < len; i++) { + minMax = minMax || [[Infinity, -Infinity], [Infinity, -Infinity]]; + var rg = range[i]; + rg[0] < minMax[0][0] && (minMax[0][0] = rg[0]); + rg[0] > minMax[0][1] && (minMax[0][1] = rg[0]); + rg[1] < minMax[1][0] && (minMax[1][0] = rg[1]); + rg[1] > minMax[1][1] && (minMax[1][1] = rg[1]); + } + + return minMax && getBoundingRectFromMinMax(minMax); + } +}; + +function getBoundingRectFromMinMax(minMax) { + return new BoundingRect( + minMax[0][0], + minMax[1][0], + minMax[0][1] - minMax[0][0], + minMax[1][1] - minMax[1][0] + ); +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var DEFAULT_OUT_OF_BRUSH_COLOR = ['#ddd']; + +var BrushModel = extendComponentModel({ + + type: 'brush', + + dependencies: ['geo', 'grid', 'xAxis', 'yAxis', 'parallel', 'series'], + + /** + * @protected + */ + defaultOption: { + // inBrush: null, + // outOfBrush: null, + toolbox: null, // Default value see preprocessor. + brushLink: null, // Series indices array, broadcast using dataIndex. + // or 'all', which means all series. 'none' or null means no series. + seriesIndex: 'all', // seriesIndex array, specify series controlled by this brush component. + geoIndex: null, // + xAxisIndex: null, + yAxisIndex: null, + + brushType: 'rect', // Default brushType, see BrushController. + brushMode: 'single', // Default brushMode, 'single' or 'multiple' + transformable: true, // Default transformable. + brushStyle: { // Default brushStyle + borderWidth: 1, + color: 'rgba(120,140,180,0.3)', + borderColor: 'rgba(120,140,180,0.8)' + }, + + throttleType: 'fixRate', // Throttle in brushSelected event. 'fixRate' or 'debounce'. + // If null, no throttle. Valid only in the first brush component + throttleDelay: 0, // Unit: ms, 0 means every event will be triggered. + + // FIXME + // 试验效果 + removeOnClick: true, + + z: 10000 + }, + + /** + * @readOnly + * @type {Array.} + */ + areas: [], + + /** + * Current activated brush type. + * If null, brush is inactived. + * see module:echarts/component/helper/BrushController + * @readOnly + * @type {string} + */ + brushType: null, + + /** + * Current brush opt. + * see module:echarts/component/helper/BrushController + * @readOnly + * @type {Object} + */ + brushOption: {}, + + /** + * @readOnly + * @type {Array.} + */ + coordInfoList: [], + + optionUpdated: function (newOption, isInit) { + var thisOption = this.option; + + !isInit && replaceVisualOption( + thisOption, newOption, ['inBrush', 'outOfBrush'] + ); + + var inBrush = thisOption.inBrush = thisOption.inBrush || {}; + // Always give default visual, consider setOption at the second time. + thisOption.outOfBrush = thisOption.outOfBrush || {color: DEFAULT_OUT_OF_BRUSH_COLOR}; + + if (!inBrush.hasOwnProperty('liftZ')) { + // Bigger than the highlight z lift, otherwise it will + // be effected by the highlight z when brush. + inBrush.liftZ = 5; + } + }, + + /** + * If ranges is null/undefined, range state remain. + * + * @param {Array.} [ranges] + */ + setAreas: function (areas) { + if (__DEV__) { + assert$1(isArray(areas)); + each$1(areas, function (area) { + assert$1(area.brushType, 'Illegal areas'); + }); + } + + // If ranges is null/undefined, range state remain. + // This helps user to dispatchAction({type: 'brush'}) with no areas + // set but just want to get the current brush select info from a `brush` event. + if (!areas) { + return; + } + + this.areas = map(areas, function (area) { + return generateBrushOption(this.option, area); + }, this); + }, + + /** + * see module:echarts/component/helper/BrushController + * @param {Object} brushOption + */ + setBrushOption: function (brushOption) { + this.brushOption = generateBrushOption(this.option, brushOption); + this.brushType = this.brushOption.brushType; + } + +}); + +function generateBrushOption(option, brushOption) { + return merge( + { + brushType: option.brushType, + brushMode: option.brushMode, + transformable: option.transformable, + brushStyle: new Model(option.brushStyle).getItemStyle(), + removeOnClick: option.removeOnClick, + z: option.z + }, + brushOption, + true + ); +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +extendComponentView({ + + type: 'brush', + + init: function (ecModel, api) { + + /** + * @readOnly + * @type {module:echarts/model/Global} + */ + this.ecModel = ecModel; + + /** + * @readOnly + * @type {module:echarts/ExtensionAPI} + */ + this.api = api; + + /** + * @readOnly + * @type {module:echarts/component/brush/BrushModel} + */ + this.model; + + /** + * @private + * @type {module:echarts/component/helper/BrushController} + */ + (this._brushController = new BrushController(api.getZr())) + .on('brush', bind(this._onBrush, this)) + .mount(); + }, + + /** + * @override + */ + render: function (brushModel) { + this.model = brushModel; + return updateController.apply(this, arguments); + }, + + /** + * @override + */ + updateTransform: updateController, + + /** + * @override + */ + updateView: updateController, + + // /** + // * @override + // */ + // updateLayout: updateController, + + // /** + // * @override + // */ + // updateVisual: updateController, + + /** + * @override + */ + dispose: function () { + this._brushController.dispose(); + }, + + /** + * @private + */ + _onBrush: function (areas, opt) { + var modelId = this.model.id; + + this.model.brushTargetManager.setOutputRanges(areas, this.ecModel); + + // Action is not dispatched on drag end, because the drag end + // emits the same params with the last drag move event, and + // may have some delay when using touch pad, which makes + // animation not smooth (when using debounce). + (!opt.isEnd || opt.removeOnClick) && this.api.dispatchAction({ + type: 'brush', + brushId: modelId, + areas: clone(areas), + $from: modelId + }); + } + +}); + +function updateController(brushModel, ecModel, api, payload) { + // Do not update controller when drawing. + (!payload || payload.$from !== brushModel.id) && this._brushController + .setPanels(brushModel.brushTargetManager.makePanelOpts(api)) + .enableBrush(brushModel.brushOption) + .updateCovers(brushModel.areas.slice()); +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/** + * payload: { + * brushIndex: number, or, + * brushId: string, or, + * brushName: string, + * globalRanges: Array + * } + */ +registerAction( + {type: 'brush', event: 'brush' /*, update: 'updateView' */}, + function (payload, ecModel) { + ecModel.eachComponent({mainType: 'brush', query: payload}, function (brushModel) { + brushModel.setAreas(payload.areas); + }); + } +); + +/** + * payload: { + * brushComponents: [ + * { + * brushId, + * brushIndex, + * brushName, + * series: [ + * { + * seriesId, + * seriesIndex, + * seriesName, + * rawIndices: [21, 34, ...] + * }, + * ... + * ] + * }, + * ... + * ] + * } + */ +registerAction( + {type: 'brushSelect', event: 'brushSelected', update: 'none'}, + function () {} +); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + + +var features = {}; + +function register$1(name, ctor) { + features[name] = ctor; +} + +function get$1(name) { + return features[name]; +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var brushLang = lang.toolbox.brush; + +function Brush(model, ecModel, api) { + this.model = model; + this.ecModel = ecModel; + this.api = api; + + /** + * @private + * @type {string} + */ + this._brushType; + + /** + * @private + * @type {string} + */ + this._brushMode; +} + +Brush.defaultOption = { + show: true, + type: ['rect', 'polygon', 'lineX', 'lineY', 'keep', 'clear'], + icon: { + /* eslint-disable */ + rect: 'M7.3,34.7 M0.4,10V-0.2h9.8 M89.6,10V-0.2h-9.8 M0.4,60v10.2h9.8 M89.6,60v10.2h-9.8 M12.3,22.4V10.5h13.1 M33.6,10.5h7.8 M49.1,10.5h7.8 M77.5,22.4V10.5h-13 M12.3,31.1v8.2 M77.7,31.1v8.2 M12.3,47.6v11.9h13.1 M33.6,59.5h7.6 M49.1,59.5 h7.7 M77.5,47.6v11.9h-13', // jshint ignore:line + polygon: 'M55.2,34.9c1.7,0,3.1,1.4,3.1,3.1s-1.4,3.1-3.1,3.1 s-3.1-1.4-3.1-3.1S53.5,34.9,55.2,34.9z M50.4,51c1.7,0,3.1,1.4,3.1,3.1c0,1.7-1.4,3.1-3.1,3.1c-1.7,0-3.1-1.4-3.1-3.1 C47.3,52.4,48.7,51,50.4,51z M55.6,37.1l1.5-7.8 M60.1,13.5l1.6-8.7l-7.8,4 M59,19l-1,5.3 M24,16.1l6.4,4.9l6.4-3.3 M48.5,11.6 l-5.9,3.1 M19.1,12.8L9.7,5.1l1.1,7.7 M13.4,29.8l1,7.3l6.6,1.6 M11.6,18.4l1,6.1 M32.8,41.9 M26.6,40.4 M27.3,40.2l6.1,1.6 M49.9,52.1l-5.6-7.6l-4.9-1.2', // jshint ignore:line + lineX: 'M15.2,30 M19.7,15.6V1.9H29 M34.8,1.9H40.4 M55.3,15.6V1.9H45.9 M19.7,44.4V58.1H29 M34.8,58.1H40.4 M55.3,44.4 V58.1H45.9 M12.5,20.3l-9.4,9.6l9.6,9.8 M3.1,29.9h16.5 M62.5,20.3l9.4,9.6L62.3,39.7 M71.9,29.9H55.4', // jshint ignore:line + lineY: 'M38.8,7.7 M52.7,12h13.2v9 M65.9,26.6V32 M52.7,46.3h13.2v-9 M24.9,12H11.8v9 M11.8,26.6V32 M24.9,46.3H11.8v-9 M48.2,5.1l-9.3-9l-9.4,9.2 M38.9-3.9V12 M48.2,53.3l-9.3,9l-9.4-9.2 M38.9,62.3V46.4', // jshint ignore:line + keep: 'M4,10.5V1h10.3 M20.7,1h6.1 M33,1h6.1 M55.4,10.5V1H45.2 M4,17.3v6.6 M55.6,17.3v6.6 M4,30.5V40h10.3 M20.7,40 h6.1 M33,40h6.1 M55.4,30.5V40H45.2 M21,18.9h62.9v48.6H21V18.9z', // jshint ignore:line + clear: 'M22,14.7l30.9,31 M52.9,14.7L22,45.7 M4.7,16.8V4.2h13.1 M26,4.2h7.8 M41.6,4.2h7.8 M70.3,16.8V4.2H57.2 M4.7,25.9v8.6 M70.3,25.9v8.6 M4.7,43.2v12.6h13.1 M26,55.8h7.8 M41.6,55.8h7.8 M70.3,43.2v12.6H57.2' // jshint ignore:line + /* eslint-enable */ + }, + // `rect`, `polygon`, `lineX`, `lineY`, `keep`, `clear` + title: clone(brushLang.title) +}; + +var proto$3 = Brush.prototype; + +// proto.updateLayout = function (featureModel, ecModel, api) { +/* eslint-disable */ +proto$3.render = +/* eslint-enable */ +proto$3.updateView = function (featureModel, ecModel, api) { + var brushType; + var brushMode; + var isBrushed; + + ecModel.eachComponent({mainType: 'brush'}, function (brushModel) { + brushType = brushModel.brushType; + brushMode = brushModel.brushOption.brushMode || 'single'; + isBrushed |= brushModel.areas.length; + }); + this._brushType = brushType; + this._brushMode = brushMode; + + each$1(featureModel.get('type', true), function (type) { + featureModel.setIconStatus( + type, + ( + type === 'keep' + ? brushMode === 'multiple' + : type === 'clear' + ? isBrushed + : type === brushType + ) ? 'emphasis' : 'normal' + ); + }); +}; + +proto$3.getIcons = function () { + var model = this.model; + var availableIcons = model.get('icon', true); + var icons = {}; + each$1(model.get('type', true), function (type) { + if (availableIcons[type]) { + icons[type] = availableIcons[type]; + } + }); + return icons; +}; + +proto$3.onclick = function (ecModel, api, type) { + var brushType = this._brushType; + var brushMode = this._brushMode; + + if (type === 'clear') { + // Trigger parallel action firstly + api.dispatchAction({ + type: 'axisAreaSelect', + intervals: [] + }); + + api.dispatchAction({ + type: 'brush', + command: 'clear', + // Clear all areas of all brush components. + areas: [] + }); + } + else { + api.dispatchAction({ + type: 'takeGlobalCursor', + key: 'brush', + brushOption: { + brushType: type === 'keep' + ? brushType + : (brushType === type ? false : type), + brushMode: type === 'keep' + ? (brushMode === 'multiple' ? 'single' : 'multiple') + : brushMode + } + }); + } +}; + +register$1('brush', Brush); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/** + * Brush component entry + */ + +registerPreprocessor(preprocessor$1); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +// (24*60*60*1000) +var PROXIMATE_ONE_DAY = 86400000; + +/** + * Calendar + * + * @constructor + * + * @param {Object} calendarModel calendarModel + * @param {Object} ecModel ecModel + * @param {Object} api api + */ +function Calendar(calendarModel, ecModel, api) { + this._model = calendarModel; +} + +Calendar.prototype = { + + constructor: Calendar, + + type: 'calendar', + + dimensions: ['time', 'value'], + + // Required in createListFromData + getDimensionsInfo: function () { + return [{name: 'time', type: 'time'}, 'value']; + }, + + getRangeInfo: function () { + return this._rangeInfo; + }, + + getModel: function () { + return this._model; + }, + + getRect: function () { + return this._rect; + }, + + getCellWidth: function () { + return this._sw; + }, + + getCellHeight: function () { + return this._sh; + }, + + getOrient: function () { + return this._orient; + }, + + /** + * getFirstDayOfWeek + * + * @example + * 0 : start at Sunday + * 1 : start at Monday + * + * @return {number} + */ + getFirstDayOfWeek: function () { + return this._firstDayOfWeek; + }, + + /** + * get date info + * + * @param {string|number} date date + * @return {Object} + * { + * y: string, local full year, eg., '1940', + * m: string, local month, from '01' ot '12', + * d: string, local date, from '01' to '31' (if exists), + * day: It is not date.getDay(). It is the location of the cell in a week, from 0 to 6, + * time: timestamp, + * formatedDate: string, yyyy-MM-dd, + * date: original date object. + * } + */ + getDateInfo: function (date) { + + date = parseDate(date); + + var y = date.getFullYear(); + + var m = date.getMonth() + 1; + m = m < 10 ? '0' + m : m; + + var d = date.getDate(); + d = d < 10 ? '0' + d : d; + + var day = date.getDay(); + + day = Math.abs((day + 7 - this.getFirstDayOfWeek()) % 7); + + return { + y: y, + m: m, + d: d, + day: day, + time: date.getTime(), + formatedDate: y + '-' + m + '-' + d, + date: date + }; + }, + + getNextNDay: function (date, n) { + n = n || 0; + if (n === 0) { + return this.getDateInfo(date); + } + + date = new Date(this.getDateInfo(date).time); + date.setDate(date.getDate() + n); + + return this.getDateInfo(date); + }, + + update: function (ecModel, api) { + + this._firstDayOfWeek = +this._model.getModel('dayLabel').get('firstDay'); + this._orient = this._model.get('orient'); + this._lineWidth = this._model.getModel('itemStyle').getItemStyle().lineWidth || 0; + + + this._rangeInfo = this._getRangeInfo(this._initRangeOption()); + var weeks = this._rangeInfo.weeks || 1; + var whNames = ['width', 'height']; + var cellSize = this._model.get('cellSize').slice(); + var layoutParams = this._model.getBoxLayoutParams(); + var cellNumbers = this._orient === 'horizontal' ? [weeks, 7] : [7, weeks]; + + each$1([0, 1], function (idx) { + if (cellSizeSpecified(cellSize, idx)) { + layoutParams[whNames[idx]] = cellSize[idx] * cellNumbers[idx]; + } + }); + + var whGlobal = { + width: api.getWidth(), + height: api.getHeight() + }; + var calendarRect = this._rect = getLayoutRect(layoutParams, whGlobal); + + each$1([0, 1], function (idx) { + if (!cellSizeSpecified(cellSize, idx)) { + cellSize[idx] = calendarRect[whNames[idx]] / cellNumbers[idx]; + } + }); + + function cellSizeSpecified(cellSize, idx) { + return cellSize[idx] != null && cellSize[idx] !== 'auto'; + } + + this._sw = cellSize[0]; + this._sh = cellSize[1]; + }, + + + /** + * Convert a time data(time, value) item to (x, y) point. + * + * @override + * @param {Array|number} data data + * @param {boolean} [clamp=true] out of range + * @return {Array} point + */ + dataToPoint: function (data, clamp) { + isArray(data) && (data = data[0]); + clamp == null && (clamp = true); + + var dayInfo = this.getDateInfo(data); + var range = this._rangeInfo; + var date = dayInfo.formatedDate; + + // if not in range return [NaN, NaN] + if (clamp && !( + dayInfo.time >= range.start.time + && dayInfo.time < range.end.time + PROXIMATE_ONE_DAY + )) { + return [NaN, NaN]; + } + + var week = dayInfo.day; + var nthWeek = this._getRangeInfo([range.start.time, date]).nthWeek; + + if (this._orient === 'vertical') { + return [ + this._rect.x + week * this._sw + this._sw / 2, + this._rect.y + nthWeek * this._sh + this._sh / 2 + ]; + + } + + return [ + this._rect.x + nthWeek * this._sw + this._sw / 2, + this._rect.y + week * this._sh + this._sh / 2 + ]; + + }, + + /** + * Convert a (x, y) point to time data + * + * @override + * @param {string} point point + * @return {string} data + */ + pointToData: function (point) { + + var date = this.pointToDate(point); + + return date && date.time; + }, + + /** + * Convert a time date item to (x, y) four point. + * + * @param {Array} data date[0] is date + * @param {boolean} [clamp=true] out of range + * @return {Object} point + */ + dataToRect: function (data, clamp) { + var point = this.dataToPoint(data, clamp); + + return { + contentShape: { + x: point[0] - (this._sw - this._lineWidth) / 2, + y: point[1] - (this._sh - this._lineWidth) / 2, + width: this._sw - this._lineWidth, + height: this._sh - this._lineWidth + }, + + center: point, + + tl: [ + point[0] - this._sw / 2, + point[1] - this._sh / 2 + ], + + tr: [ + point[0] + this._sw / 2, + point[1] - this._sh / 2 + ], + + br: [ + point[0] + this._sw / 2, + point[1] + this._sh / 2 + ], + + bl: [ + point[0] - this._sw / 2, + point[1] + this._sh / 2 + ] + + }; + }, + + /** + * Convert a (x, y) point to time date + * + * @param {Array} point point + * @return {Object} date + */ + pointToDate: function (point) { + var nthX = Math.floor((point[0] - this._rect.x) / this._sw) + 1; + var nthY = Math.floor((point[1] - this._rect.y) / this._sh) + 1; + var range = this._rangeInfo.range; + + if (this._orient === 'vertical') { + return this._getDateByWeeksAndDay(nthY, nthX - 1, range); + } + + return this._getDateByWeeksAndDay(nthX, nthY - 1, range); + }, + + /** + * @inheritDoc + */ + convertToPixel: curry(doConvert$2, 'dataToPoint'), + + /** + * @inheritDoc + */ + convertFromPixel: curry(doConvert$2, 'pointToData'), + + /** + * initRange + * + * @private + * @return {Array} [start, end] + */ + _initRangeOption: function () { + var range = this._model.get('range'); + + var rg = range; + + if (isArray(rg) && rg.length === 1) { + rg = rg[0]; + } + + if (/^\d{4}$/.test(rg)) { + range = [rg + '-01-01', rg + '-12-31']; + } + + if (/^\d{4}[\/|-]\d{1,2}$/.test(rg)) { + + var start = this.getDateInfo(rg); + var firstDay = start.date; + firstDay.setMonth(firstDay.getMonth() + 1); + + var end = this.getNextNDay(firstDay, -1); + range = [start.formatedDate, end.formatedDate]; + } + + if (/^\d{4}[\/|-]\d{1,2}[\/|-]\d{1,2}$/.test(rg)) { + range = [rg, rg]; + } + + var tmp = this._getRangeInfo(range); + + if (tmp.start.time > tmp.end.time) { + range.reverse(); + } + + return range; + }, + + /** + * range info + * + * @private + * @param {Array} range range ['2017-01-01', '2017-07-08'] + * If range[0] > range[1], they will not be reversed. + * @return {Object} obj + */ + _getRangeInfo: function (range) { + range = [ + this.getDateInfo(range[0]), + this.getDateInfo(range[1]) + ]; + + var reversed; + if (range[0].time > range[1].time) { + reversed = true; + range.reverse(); + } + + var allDay = Math.floor(range[1].time / PROXIMATE_ONE_DAY) + - Math.floor(range[0].time / PROXIMATE_ONE_DAY) + 1; + + // Consider case: + // Firstly set system timezone as "Time Zone: America/Toronto", + // ``` + // var first = new Date(1478412000000 - 3600 * 1000 * 2.5); + // var second = new Date(1478412000000); + // var allDays = Math.floor(second / ONE_DAY) - Math.floor(first / ONE_DAY) + 1; + // ``` + // will get wrong result because of DST. So we should fix it. + var date = new Date(range[0].time); + var startDateNum = date.getDate(); + var endDateNum = range[1].date.getDate(); + date.setDate(startDateNum + allDay - 1); + // The bias can not over a month, so just compare date. + if (date.getDate() !== endDateNum) { + var sign = date.getTime() - range[1].time > 0 ? 1 : -1; + while (date.getDate() !== endDateNum && (date.getTime() - range[1].time) * sign > 0) { + allDay -= sign; + date.setDate(startDateNum + allDay - 1); + } + } + + var weeks = Math.floor((allDay + range[0].day + 6) / 7); + var nthWeek = reversed ? -weeks + 1 : weeks - 1; + + reversed && range.reverse(); + + return { + range: [range[0].formatedDate, range[1].formatedDate], + start: range[0], + end: range[1], + allDay: allDay, + weeks: weeks, + // From 0. + nthWeek: nthWeek, + fweek: range[0].day, + lweek: range[1].day + }; + }, + + /** + * get date by nthWeeks and week day in range + * + * @private + * @param {number} nthWeek the week + * @param {number} day the week day + * @param {Array} range [d1, d2] + * @return {Object} + */ + _getDateByWeeksAndDay: function (nthWeek, day, range) { + var rangeInfo = this._getRangeInfo(range); + + if (nthWeek > rangeInfo.weeks + || (nthWeek === 0 && day < rangeInfo.fweek) + || (nthWeek === rangeInfo.weeks && day > rangeInfo.lweek) + ) { + return false; + } + + var nthDay = (nthWeek - 1) * 7 - rangeInfo.fweek + day; + var date = new Date(rangeInfo.start.time); + date.setDate(rangeInfo.start.d + nthDay); + + return this.getDateInfo(date); + } +}; + +Calendar.dimensions = Calendar.prototype.dimensions; + +Calendar.getDimensionsInfo = Calendar.prototype.getDimensionsInfo; + +Calendar.create = function (ecModel, api) { + var calendarList = []; + + ecModel.eachComponent('calendar', function (calendarModel) { + var calendar = new Calendar(calendarModel, ecModel, api); + calendarList.push(calendar); + calendarModel.coordinateSystem = calendar; + }); + + ecModel.eachSeries(function (calendarSeries) { + if (calendarSeries.get('coordinateSystem') === 'calendar') { + // Inject coordinate system + calendarSeries.coordinateSystem = calendarList[calendarSeries.get('calendarIndex') || 0]; + } + }); + return calendarList; +}; + +function doConvert$2(methodName, ecModel, finder, value) { + var calendarModel = finder.calendarModel; + var seriesModel = finder.seriesModel; + + var coordSys = calendarModel + ? calendarModel.coordinateSystem + : seriesModel + ? seriesModel.coordinateSystem + : null; + + return coordSys === this ? coordSys[methodName](value) : null; +} + +CoordinateSystemManager.register('calendar', Calendar); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var CalendarModel = ComponentModel.extend({ + + type: 'calendar', + + /** + * @type {module:echarts/coord/calendar/Calendar} + */ + coordinateSystem: null, + + defaultOption: { + zlevel: 0, + z: 2, + left: 80, + top: 60, + + cellSize: 20, + + // horizontal vertical + orient: 'horizontal', + + // month separate line style + splitLine: { + show: true, + lineStyle: { + color: '#000', + width: 1, + type: 'solid' + } + }, + + // rect style temporarily unused emphasis + itemStyle: { + color: '#fff', + borderWidth: 1, + borderColor: '#ccc' + }, + + // week text style + dayLabel: { + show: true, + + // a week first day + firstDay: 0, + + // start end + position: 'start', + margin: '50%', // 50% of cellSize + nameMap: 'en', + color: '#000' + }, + + // month text style + monthLabel: { + show: true, + + // start end + position: 'start', + margin: 5, + + // center or left + align: 'center', + + // cn en [] + nameMap: 'en', + formatter: null, + color: '#000' + }, + + // year text style + yearLabel: { + show: true, + + // top bottom left right + position: null, + margin: 30, + formatter: null, + color: '#ccc', + fontFamily: 'sans-serif', + fontWeight: 'bolder', + fontSize: 20 + } + }, + + /** + * @override + */ + init: function (option, parentModel, ecModel, extraOpt) { + var inputPositionParams = getLayoutParams(option); + + CalendarModel.superApply(this, 'init', arguments); + + mergeAndNormalizeLayoutParams$1(option, inputPositionParams); + }, + + /** + * @override + */ + mergeOption: function (option, extraOpt) { + CalendarModel.superApply(this, 'mergeOption', arguments); + + mergeAndNormalizeLayoutParams$1(this.option, option); + } +}); + +function mergeAndNormalizeLayoutParams$1(target, raw) { + // Normalize cellSize + var cellSize = target.cellSize; + + if (!isArray(cellSize)) { + cellSize = target.cellSize = [cellSize, cellSize]; + } + else if (cellSize.length === 1) { + cellSize[1] = cellSize[0]; + } + + var ignoreSize = map([0, 1], function (hvIdx) { + // If user have set `width` or both `left` and `right`, cellSize + // will be automatically set to 'auto', otherwise the default + // setting of cellSize will make `width` setting not work. + if (sizeCalculable(raw, hvIdx)) { + cellSize[hvIdx] = 'auto'; + } + return cellSize[hvIdx] != null && cellSize[hvIdx] !== 'auto'; + }); + + mergeLayoutParam(target, raw, { + type: 'box', ignoreSize: ignoreSize + }); +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var MONTH_TEXT = { + EN: [ + 'Jan', 'Feb', 'Mar', + 'Apr', 'May', 'Jun', + 'Jul', 'Aug', 'Sep', + 'Oct', 'Nov', 'Dec' + ], + CN: [ + '一月', '二月', '三月', + '四月', '五月', '六月', + '七月', '八月', '九月', + '十月', '十一月', '十二月' + ] +}; + +var WEEK_TEXT = { + EN: ['S', 'M', 'T', 'W', 'T', 'F', 'S'], + CN: ['日', '一', '二', '三', '四', '五', '六'] +}; + +extendComponentView({ + + type: 'calendar', + + /** + * top/left line points + * @private + */ + _tlpoints: null, + + /** + * bottom/right line points + * @private + */ + _blpoints: null, + + /** + * first day of month + * @private + */ + _firstDayOfMonth: null, + + /** + * first day point of month + * @private + */ + _firstDayPoints: null, + + render: function (calendarModel, ecModel, api) { + + var group = this.group; + + group.removeAll(); + + var coordSys = calendarModel.coordinateSystem; + + // range info + var rangeData = coordSys.getRangeInfo(); + var orient = coordSys.getOrient(); + + this._renderDayRect(calendarModel, rangeData, group); + + // _renderLines must be called prior to following function + this._renderLines(calendarModel, rangeData, orient, group); + + this._renderYearText(calendarModel, rangeData, orient, group); + + this._renderMonthText(calendarModel, orient, group); + + this._renderWeekText(calendarModel, rangeData, orient, group); + }, + + // render day rect + _renderDayRect: function (calendarModel, rangeData, group) { + var coordSys = calendarModel.coordinateSystem; + var itemRectStyleModel = calendarModel.getModel('itemStyle').getItemStyle(); + var sw = coordSys.getCellWidth(); + var sh = coordSys.getCellHeight(); + + for (var i = rangeData.start.time; + i <= rangeData.end.time; + i = coordSys.getNextNDay(i, 1).time + ) { + + var point = coordSys.dataToRect([i], false).tl; + + // every rect + var rect = new Rect({ + shape: { + x: point[0], + y: point[1], + width: sw, + height: sh + }, + cursor: 'default', + style: itemRectStyleModel + }); + + group.add(rect); + } + + }, + + // render separate line + _renderLines: function (calendarModel, rangeData, orient, group) { + + var self = this; + + var coordSys = calendarModel.coordinateSystem; + + var lineStyleModel = calendarModel.getModel('splitLine.lineStyle').getLineStyle(); + var show = calendarModel.get('splitLine.show'); + + var lineWidth = lineStyleModel.lineWidth; + + this._tlpoints = []; + this._blpoints = []; + this._firstDayOfMonth = []; + this._firstDayPoints = []; + + + var firstDay = rangeData.start; + + for (var i = 0; firstDay.time <= rangeData.end.time; i++) { + addPoints(firstDay.formatedDate); + + if (i === 0) { + firstDay = coordSys.getDateInfo(rangeData.start.y + '-' + rangeData.start.m); + } + + var date = firstDay.date; + date.setMonth(date.getMonth() + 1); + firstDay = coordSys.getDateInfo(date); + } + + addPoints(coordSys.getNextNDay(rangeData.end.time, 1).formatedDate); + + function addPoints(date) { + + self._firstDayOfMonth.push(coordSys.getDateInfo(date)); + self._firstDayPoints.push(coordSys.dataToRect([date], false).tl); + + var points = self._getLinePointsOfOneWeek(calendarModel, date, orient); + + self._tlpoints.push(points[0]); + self._blpoints.push(points[points.length - 1]); + + show && self._drawSplitline(points, lineStyleModel, group); + } + + + // render top/left line + show && this._drawSplitline(self._getEdgesPoints(self._tlpoints, lineWidth, orient), lineStyleModel, group); + + // render bottom/right line + show && this._drawSplitline(self._getEdgesPoints(self._blpoints, lineWidth, orient), lineStyleModel, group); + + }, + + // get points at both ends + _getEdgesPoints: function (points, lineWidth, orient) { + var rs = [points[0].slice(), points[points.length - 1].slice()]; + var idx = orient === 'horizontal' ? 0 : 1; + + // both ends of the line are extend half lineWidth + rs[0][idx] = rs[0][idx] - lineWidth / 2; + rs[1][idx] = rs[1][idx] + lineWidth / 2; + + return rs; + }, + + // render split line + _drawSplitline: function (points, lineStyleModel, group) { + + var poyline = new Polyline({ + z2: 20, + shape: { + points: points + }, + style: lineStyleModel + }); + + group.add(poyline); + }, + + // render month line of one week points + _getLinePointsOfOneWeek: function (calendarModel, date, orient) { + + var coordSys = calendarModel.coordinateSystem; + date = coordSys.getDateInfo(date); + + var points = []; + + for (var i = 0; i < 7; i++) { + + var tmpD = coordSys.getNextNDay(date.time, i); + var point = coordSys.dataToRect([tmpD.time], false); + + points[2 * tmpD.day] = point.tl; + points[2 * tmpD.day + 1] = point[orient === 'horizontal' ? 'bl' : 'tr']; + } + + return points; + + }, + + _formatterLabel: function (formatter, params) { + + if (typeof formatter === 'string' && formatter) { + return formatTplSimple(formatter, params); + } + + if (typeof formatter === 'function') { + return formatter(params); + } + + return params.nameMap; + + }, + + _yearTextPositionControl: function (textEl, point, orient, position, margin) { + + point = point.slice(); + var aligns = ['center', 'bottom']; + + if (position === 'bottom') { + point[1] += margin; + aligns = ['center', 'top']; + } + else if (position === 'left') { + point[0] -= margin; + } + else if (position === 'right') { + point[0] += margin; + aligns = ['center', 'top']; + } + else { // top + point[1] -= margin; + } + + var rotate = 0; + if (position === 'left' || position === 'right') { + rotate = Math.PI / 2; + } + + return { + rotation: rotate, + position: point, + style: { + textAlign: aligns[0], + textVerticalAlign: aligns[1] + } + }; + }, + + // render year + _renderYearText: function (calendarModel, rangeData, orient, group) { + var yearLabel = calendarModel.getModel('yearLabel'); + + if (!yearLabel.get('show')) { + return; + } + + var margin = yearLabel.get('margin'); + var pos = yearLabel.get('position'); + + if (!pos) { + pos = orient !== 'horizontal' ? 'top' : 'left'; + } + + var points = [this._tlpoints[this._tlpoints.length - 1], this._blpoints[0]]; + var xc = (points[0][0] + points[1][0]) / 2; + var yc = (points[0][1] + points[1][1]) / 2; + + var idx = orient === 'horizontal' ? 0 : 1; + + var posPoints = { + top: [xc, points[idx][1]], + bottom: [xc, points[1 - idx][1]], + left: [points[1 - idx][0], yc], + right: [points[idx][0], yc] + }; + + var name = rangeData.start.y; + + if (+rangeData.end.y > +rangeData.start.y) { + name = name + '-' + rangeData.end.y; + } + + var formatter = yearLabel.get('formatter'); + + var params = { + start: rangeData.start.y, + end: rangeData.end.y, + nameMap: name + }; + + var content = this._formatterLabel(formatter, params); + + var yearText = new Text({z2: 30}); + setTextStyle(yearText.style, yearLabel, {text: content}), + yearText.attr(this._yearTextPositionControl(yearText, posPoints[pos], orient, pos, margin)); + + group.add(yearText); + }, + + _monthTextPositionControl: function (point, isCenter, orient, position, margin) { + var align = 'left'; + var vAlign = 'top'; + var x = point[0]; + var y = point[1]; + + if (orient === 'horizontal') { + y = y + margin; + + if (isCenter) { + align = 'center'; + } + + if (position === 'start') { + vAlign = 'bottom'; + } + } + else { + x = x + margin; + + if (isCenter) { + vAlign = 'middle'; + } + + if (position === 'start') { + align = 'right'; + } + } + + return { + x: x, + y: y, + textAlign: align, + textVerticalAlign: vAlign + }; + }, + + // render month and year text + _renderMonthText: function (calendarModel, orient, group) { + var monthLabel = calendarModel.getModel('monthLabel'); + + if (!monthLabel.get('show')) { + return; + } + + var nameMap = monthLabel.get('nameMap'); + var margin = monthLabel.get('margin'); + var pos = monthLabel.get('position'); + var align = monthLabel.get('align'); + + var termPoints = [this._tlpoints, this._blpoints]; + + if (isString(nameMap)) { + nameMap = MONTH_TEXT[nameMap.toUpperCase()] || []; + } + + var idx = pos === 'start' ? 0 : 1; + var axis = orient === 'horizontal' ? 0 : 1; + margin = pos === 'start' ? -margin : margin; + var isCenter = (align === 'center'); + + for (var i = 0; i < termPoints[idx].length - 1; i++) { + + var tmp = termPoints[idx][i].slice(); + var firstDay = this._firstDayOfMonth[i]; + + if (isCenter) { + var firstDayPoints = this._firstDayPoints[i]; + tmp[axis] = (firstDayPoints[axis] + termPoints[0][i + 1][axis]) / 2; + } + + var formatter = monthLabel.get('formatter'); + var name = nameMap[+firstDay.m - 1]; + var params = { + yyyy: firstDay.y, + yy: (firstDay.y + '').slice(2), + MM: firstDay.m, + M: +firstDay.m, + nameMap: name + }; + + var content = this._formatterLabel(formatter, params); + + var monthText = new Text({z2: 30}); + extend( + setTextStyle(monthText.style, monthLabel, {text: content}), + this._monthTextPositionControl(tmp, isCenter, orient, pos, margin) + ); + + group.add(monthText); + } + }, + + _weekTextPositionControl: function (point, orient, position, margin, cellSize) { + var align = 'center'; + var vAlign = 'middle'; + var x = point[0]; + var y = point[1]; + var isStart = position === 'start'; + + if (orient === 'horizontal') { + x = x + margin + (isStart ? 1 : -1) * cellSize[0] / 2; + align = isStart ? 'right' : 'left'; + } + else { + y = y + margin + (isStart ? 1 : -1) * cellSize[1] / 2; + vAlign = isStart ? 'bottom' : 'top'; + } + + return { + x: x, + y: y, + textAlign: align, + textVerticalAlign: vAlign + }; + }, + + // render weeks + _renderWeekText: function (calendarModel, rangeData, orient, group) { + var dayLabel = calendarModel.getModel('dayLabel'); + + if (!dayLabel.get('show')) { + return; + } + + var coordSys = calendarModel.coordinateSystem; + var pos = dayLabel.get('position'); + var nameMap = dayLabel.get('nameMap'); + var margin = dayLabel.get('margin'); + var firstDayOfWeek = coordSys.getFirstDayOfWeek(); + + if (isString(nameMap)) { + nameMap = WEEK_TEXT[nameMap.toUpperCase()] || []; + } + + var start = coordSys.getNextNDay( + rangeData.end.time, (7 - rangeData.lweek) + ).time; + + var cellSize = [coordSys.getCellWidth(), coordSys.getCellHeight()]; + margin = parsePercent$1(margin, cellSize[orient === 'horizontal' ? 0 : 1]); + + if (pos === 'start') { + start = coordSys.getNextNDay( + rangeData.start.time, -(7 + rangeData.fweek) + ).time; + margin = -margin; + } + + for (var i = 0; i < 7; i++) { + + var tmpD = coordSys.getNextNDay(start, i); + var point = coordSys.dataToRect([tmpD.time], false).center; + var day = i; + day = Math.abs((i + firstDayOfWeek) % 7); + var weekText = new Text({z2: 30}); + + extend( + setTextStyle(weekText.style, dayLabel, {text: nameMap[day]}), + this._weekTextPositionControl(point, orient, pos, margin, cellSize) + ); + group.add(weekText); + } + } +}); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/** + * @file calendar.js + * @author dxh + */ + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +// Model +extendComponentModel({ + + type: 'title', + + layoutMode: {type: 'box', ignoreSize: true}, + + defaultOption: { + // 一级层叠 + zlevel: 0, + // 二级层叠 + z: 6, + show: true, + + text: '', + // 超链接跳转 + // link: null, + // 仅支持self | blank + target: 'blank', + subtext: '', + + // 超链接跳转 + // sublink: null, + // 仅支持self | blank + subtarget: 'blank', + + // 'center' ¦ 'left' ¦ 'right' + // ¦ {number}(x坐标,单位px) + left: 0, + // 'top' ¦ 'bottom' ¦ 'center' + // ¦ {number}(y坐标,单位px) + top: 0, + + // 水平对齐 + // 'auto' | 'left' | 'right' | 'center' + // 默认根据 left 的位置判断是左对齐还是右对齐 + // textAlign: null + // + // 垂直对齐 + // 'auto' | 'top' | 'bottom' | 'middle' + // 默认根据 top 位置判断是上对齐还是下对齐 + // textBaseline: null + + backgroundColor: 'rgba(0,0,0,0)', + + // 标题边框颜色 + borderColor: '#ccc', + + // 标题边框线宽,单位px,默认为0(无边框) + borderWidth: 0, + + // 标题内边距,单位px,默认各方向内边距为5, + // 接受数组分别设定上右下左边距,同css + padding: 5, + + // 主副标题纵向间隔,单位px,默认为10, + itemGap: 10, + textStyle: { + fontSize: 18, + fontWeight: 'bolder', + color: '#333' + }, + subtextStyle: { + color: '#aaa' + } + } +}); + +// View +extendComponentView({ + + type: 'title', + + render: function (titleModel, ecModel, api) { + this.group.removeAll(); + + if (!titleModel.get('show')) { + return; + } + + var group = this.group; + + var textStyleModel = titleModel.getModel('textStyle'); + var subtextStyleModel = titleModel.getModel('subtextStyle'); + + var textAlign = titleModel.get('textAlign'); + var textBaseline = titleModel.get('textBaseline'); + + var textEl = new Text({ + style: setTextStyle({}, textStyleModel, { + text: titleModel.get('text'), + textFill: textStyleModel.getTextColor() + }, {disableBox: true}), + z2: 10 + }); + + var textRect = textEl.getBoundingRect(); + + var subText = titleModel.get('subtext'); + var subTextEl = new Text({ + style: setTextStyle({}, subtextStyleModel, { + text: subText, + textFill: subtextStyleModel.getTextColor(), + y: textRect.height + titleModel.get('itemGap'), + textVerticalAlign: 'top' + }, {disableBox: true}), + z2: 10 + }); + + var link = titleModel.get('link'); + var sublink = titleModel.get('sublink'); + var triggerEvent = titleModel.get('triggerEvent', true); + + textEl.silent = !link && !triggerEvent; + subTextEl.silent = !sublink && !triggerEvent; + + if (link) { + textEl.on('click', function () { + window.open(link, '_' + titleModel.get('target')); + }); + } + if (sublink) { + subTextEl.on('click', function () { + window.open(sublink, '_' + titleModel.get('subtarget')); + }); + } + + textEl.eventData = subTextEl.eventData = triggerEvent + ? { + componentType: 'title', + componentIndex: titleModel.componentIndex + } + : null; + + group.add(textEl); + subText && group.add(subTextEl); + // If no subText, but add subTextEl, there will be an empty line. + + var groupRect = group.getBoundingRect(); + var layoutOption = titleModel.getBoxLayoutParams(); + layoutOption.width = groupRect.width; + layoutOption.height = groupRect.height; + var layoutRect = getLayoutRect( + layoutOption, { + width: api.getWidth(), + height: api.getHeight() + }, titleModel.get('padding') + ); + // Adjust text align based on position + if (!textAlign) { + // Align left if title is on the left. center and right is same + textAlign = titleModel.get('left') || titleModel.get('right'); + if (textAlign === 'middle') { + textAlign = 'center'; + } + // Adjust layout by text align + if (textAlign === 'right') { + layoutRect.x += layoutRect.width; + } + else if (textAlign === 'center') { + layoutRect.x += layoutRect.width / 2; + } + } + if (!textBaseline) { + textBaseline = titleModel.get('top') || titleModel.get('bottom'); + if (textBaseline === 'center') { + textBaseline = 'middle'; + } + if (textBaseline === 'bottom') { + layoutRect.y += layoutRect.height; + } + else if (textBaseline === 'middle') { + layoutRect.y += layoutRect.height / 2; + } + + textBaseline = textBaseline || 'top'; + } + + group.attr('position', [layoutRect.x, layoutRect.y]); + var alignStyle = { + textAlign: textAlign, + textVerticalAlign: textBaseline + }; + textEl.setStyle(alignStyle); + subTextEl.setStyle(alignStyle); + + // Render background + // Get groupRect again because textAlign has been changed + groupRect = group.getBoundingRect(); + var padding = layoutRect.margin; + var style = titleModel.getItemStyle(['color', 'opacity']); + style.fill = titleModel.get('backgroundColor'); + var rect = new Rect({ + shape: { + x: groupRect.x - padding[3], + y: groupRect.y - padding[0], + width: groupRect.width + padding[1] + padding[3], + height: groupRect.height + padding[0] + padding[2], + r: titleModel.get('borderRadius') + }, + style: style, + silent: true + }); + subPixelOptimizeRect(rect); + + group.add(rect); + } +}); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +ComponentModel.registerSubTypeDefaulter('dataZoom', function () { + // Default 'slider' when no type specified. + return 'slider'; +}); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var AXIS_DIMS = ['x', 'y', 'z', 'radius', 'angle', 'single']; +// Supported coords. +var COORDS = ['cartesian2d', 'polar', 'singleAxis']; + +/** + * @param {string} coordType + * @return {boolean} + */ +function isCoordSupported(coordType) { + return indexOf(COORDS, coordType) >= 0; +} + +/** + * Create "each" method to iterate names. + * + * @pubilc + * @param {Array.} names + * @param {Array.=} attrs + * @return {Function} + */ +function createNameEach(names, attrs) { + names = names.slice(); + var capitalNames = map(names, capitalFirst); + attrs = (attrs || []).slice(); + var capitalAttrs = map(attrs, capitalFirst); + + return function (callback, context) { + each$1(names, function (name, index) { + var nameObj = {name: name, capital: capitalNames[index]}; + + for (var j = 0; j < attrs.length; j++) { + nameObj[attrs[j]] = name + capitalAttrs[j]; + } + + callback.call(context, nameObj); + }); + }; +} + +/** + * Iterate each dimension name. + * + * @public + * @param {Function} callback The parameter is like: + * { + * name: 'angle', + * capital: 'Angle', + * axis: 'angleAxis', + * axisIndex: 'angleAixs', + * index: 'angleIndex' + * } + * @param {Object} context + */ +var eachAxisDim$1 = createNameEach(AXIS_DIMS, ['axisIndex', 'axis', 'index', 'id']); + +/** + * If tow dataZoomModels has the same axis controlled, we say that they are 'linked'. + * dataZoomModels and 'links' make up one or more graphics. + * This function finds the graphic where the source dataZoomModel is in. + * + * @public + * @param {Function} forEachNode Node iterator. + * @param {Function} forEachEdgeType edgeType iterator + * @param {Function} edgeIdGetter Giving node and edgeType, return an array of edge id. + * @return {Function} Input: sourceNode, Output: Like {nodes: [], dims: {}} + */ +function createLinkedNodesFinder(forEachNode, forEachEdgeType, edgeIdGetter) { + + return function (sourceNode) { + var result = { + nodes: [], + records: {} // key: edgeType.name, value: Object (key: edge id, value: boolean). + }; + + forEachEdgeType(function (edgeType) { + result.records[edgeType.name] = {}; + }); + + if (!sourceNode) { + return result; + } + + absorb(sourceNode, result); + + var existsLink; + do { + existsLink = false; + forEachNode(processSingleNode); + } + while (existsLink); + + function processSingleNode(node) { + if (!isNodeAbsorded(node, result) && isLinked(node, result)) { + absorb(node, result); + existsLink = true; + } + } + + return result; + }; + + function isNodeAbsorded(node, result) { + return indexOf(result.nodes, node) >= 0; + } + + function isLinked(node, result) { + var hasLink = false; + forEachEdgeType(function (edgeType) { + each$1(edgeIdGetter(node, edgeType) || [], function (edgeId) { + result.records[edgeType.name][edgeId] && (hasLink = true); + }); + }); + return hasLink; + } + + function absorb(node, result) { + result.nodes.push(node); + forEachEdgeType(function (edgeType) { + each$1(edgeIdGetter(node, edgeType) || [], function (edgeId) { + result.records[edgeType.name][edgeId] = true; + }); + }); + } +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var each$22 = each$1; +var asc$1 = asc; + +/** + * Operate single axis. + * One axis can only operated by one axis operator. + * Different dataZoomModels may be defined to operate the same axis. + * (i.e. 'inside' data zoom and 'slider' data zoom components) + * So dataZoomModels share one axisProxy in that case. + * + * @class + */ +var AxisProxy = function (dimName, axisIndex, dataZoomModel, ecModel) { + + /** + * @private + * @type {string} + */ + this._dimName = dimName; + + /** + * @private + */ + this._axisIndex = axisIndex; + + /** + * @private + * @type {Array.} + */ + this._valueWindow; + + /** + * @private + * @type {Array.} + */ + this._percentWindow; + + /** + * @private + * @type {Array.} + */ + this._dataExtent; + + /** + * {minSpan, maxSpan, minValueSpan, maxValueSpan} + * @private + * @type {Object} + */ + this._minMaxSpan; + + /** + * @readOnly + * @type {module: echarts/model/Global} + */ + this.ecModel = ecModel; + + /** + * @private + * @type {module: echarts/component/dataZoom/DataZoomModel} + */ + this._dataZoomModel = dataZoomModel; + + // /** + // * @readOnly + // * @private + // */ + // this.hasSeriesStacked; +}; + +AxisProxy.prototype = { + + constructor: AxisProxy, + + /** + * Whether the axisProxy is hosted by dataZoomModel. + * + * @public + * @param {module: echarts/component/dataZoom/DataZoomModel} dataZoomModel + * @return {boolean} + */ + hostedBy: function (dataZoomModel) { + return this._dataZoomModel === dataZoomModel; + }, + + /** + * @return {Array.} Value can only be NaN or finite value. + */ + getDataValueWindow: function () { + return this._valueWindow.slice(); + }, + + /** + * @return {Array.} + */ + getDataPercentWindow: function () { + return this._percentWindow.slice(); + }, + + /** + * @public + * @param {number} axisIndex + * @return {Array} seriesModels + */ + getTargetSeriesModels: function () { + var seriesModels = []; + var ecModel = this.ecModel; + + ecModel.eachSeries(function (seriesModel) { + if (isCoordSupported(seriesModel.get('coordinateSystem'))) { + var dimName = this._dimName; + var axisModel = ecModel.queryComponents({ + mainType: dimName + 'Axis', + index: seriesModel.get(dimName + 'AxisIndex'), + id: seriesModel.get(dimName + 'AxisId') + })[0]; + if (this._axisIndex === (axisModel && axisModel.componentIndex)) { + seriesModels.push(seriesModel); + } + } + }, this); + + return seriesModels; + }, + + getAxisModel: function () { + return this.ecModel.getComponent(this._dimName + 'Axis', this._axisIndex); + }, + + getOtherAxisModel: function () { + var axisDim = this._dimName; + var ecModel = this.ecModel; + var axisModel = this.getAxisModel(); + var isCartesian = axisDim === 'x' || axisDim === 'y'; + var otherAxisDim; + var coordSysIndexName; + if (isCartesian) { + coordSysIndexName = 'gridIndex'; + otherAxisDim = axisDim === 'x' ? 'y' : 'x'; + } + else { + coordSysIndexName = 'polarIndex'; + otherAxisDim = axisDim === 'angle' ? 'radius' : 'angle'; + } + var foundOtherAxisModel; + ecModel.eachComponent(otherAxisDim + 'Axis', function (otherAxisModel) { + if ((otherAxisModel.get(coordSysIndexName) || 0) + === (axisModel.get(coordSysIndexName) || 0) + ) { + foundOtherAxisModel = otherAxisModel; + } + }); + return foundOtherAxisModel; + }, + + getMinMaxSpan: function () { + return clone(this._minMaxSpan); + }, + + /** + * Only calculate by given range and this._dataExtent, do not change anything. + * + * @param {Object} opt + * @param {number} [opt.start] + * @param {number} [opt.end] + * @param {number} [opt.startValue] + * @param {number} [opt.endValue] + */ + calculateDataWindow: function (opt) { + var dataExtent = this._dataExtent; + var axisModel = this.getAxisModel(); + var scale = axisModel.axis.scale; + var rangePropMode = this._dataZoomModel.getRangePropMode(); + var percentExtent = [0, 100]; + var percentWindow = [ + opt.start, + opt.end + ]; + var valueWindow = []; + + each$22(['startValue', 'endValue'], function (prop) { + valueWindow.push(opt[prop] != null ? scale.parse(opt[prop]) : null); + }); + + // Normalize bound. + each$22([0, 1], function (idx) { + var boundValue = valueWindow[idx]; + var boundPercent = percentWindow[idx]; + + // Notice: dataZoom is based either on `percentProp` ('start', 'end') or + // on `valueProp` ('startValue', 'endValue'). The former one is suitable + // for cases that a dataZoom component controls multiple axes with different + // unit or extent, and the latter one is suitable for accurate zoom by pixel + // (e.g., in dataZoomSelect). `valueProp` can be calculated from `percentProp`, + // but it is awkward that `percentProp` can not be obtained from `valueProp` + // accurately (because all of values that are overflow the `dataExtent` will + // be calculated to percent '100%'). So we have to use + // `dataZoom.getRangePropMode()` to mark which prop is used. + // `rangePropMode` is updated only when setOption or dispatchAction, otherwise + // it remains its original value. + + if (rangePropMode[idx] === 'percent') { + if (boundPercent == null) { + boundPercent = percentExtent[idx]; + } + // Use scale.parse to math round for category or time axis. + boundValue = scale.parse(linearMap( + boundPercent, percentExtent, dataExtent, true + )); + } + else { + // Calculating `percent` from `value` may be not accurate, because + // This calculation can not be inversed, because all of values that + // are overflow the `dataExtent` will be calculated to percent '100%' + boundPercent = linearMap( + boundValue, dataExtent, percentExtent, true + ); + } + + // valueWindow[idx] = round(boundValue); + // percentWindow[idx] = round(boundPercent); + valueWindow[idx] = boundValue; + percentWindow[idx] = boundPercent; + }); + + return { + valueWindow: asc$1(valueWindow), + percentWindow: asc$1(percentWindow) + }; + }, + + /** + * Notice: reset should not be called before series.restoreData() called, + * so it is recommanded to be called in "process stage" but not "model init + * stage". + * + * @param {module: echarts/component/dataZoom/DataZoomModel} dataZoomModel + */ + reset: function (dataZoomModel) { + if (dataZoomModel !== this._dataZoomModel) { + return; + } + + var targetSeries = this.getTargetSeriesModels(); + // Culculate data window and data extent, and record them. + this._dataExtent = calculateDataExtent(this, this._dimName, targetSeries); + + // this.hasSeriesStacked = false; + // each(targetSeries, function (series) { + // var data = series.getData(); + // var dataDim = data.mapDimension(this._dimName); + // var stackedDimension = data.getCalculationInfo('stackedDimension'); + // if (stackedDimension && stackedDimension === dataDim) { + // this.hasSeriesStacked = true; + // } + // }, this); + + var dataWindow = this.calculateDataWindow(dataZoomModel.option); + + this._valueWindow = dataWindow.valueWindow; + this._percentWindow = dataWindow.percentWindow; + + setMinMaxSpan(this); + + // Update axis setting then. + setAxisModel(this); + }, + + /** + * @param {module: echarts/component/dataZoom/DataZoomModel} dataZoomModel + */ + restore: function (dataZoomModel) { + if (dataZoomModel !== this._dataZoomModel) { + return; + } + + this._valueWindow = this._percentWindow = null; + setAxisModel(this, true); + }, + + /** + * @param {module: echarts/component/dataZoom/DataZoomModel} dataZoomModel + */ + filterData: function (dataZoomModel, api) { + if (dataZoomModel !== this._dataZoomModel) { + return; + } + + var axisDim = this._dimName; + var seriesModels = this.getTargetSeriesModels(); + var filterMode = dataZoomModel.get('filterMode'); + var valueWindow = this._valueWindow; + + if (filterMode === 'none') { + return; + } + + // FIXME + // Toolbox may has dataZoom injected. And if there are stacked bar chart + // with NaN data, NaN will be filtered and stack will be wrong. + // So we need to force the mode to be set empty. + // In fect, it is not a big deal that do not support filterMode-'filter' + // when using toolbox#dataZoom, utill tooltip#dataZoom support "single axis + // selection" some day, which might need "adapt to data extent on the + // otherAxis", which is disabled by filterMode-'empty'. + // But currently, stack has been fixed to based on value but not index, + // so this is not an issue any more. + // var otherAxisModel = this.getOtherAxisModel(); + // if (dataZoomModel.get('$fromToolbox') + // && otherAxisModel + // && otherAxisModel.hasSeriesStacked + // ) { + // filterMode = 'empty'; + // } + + // TODO + // filterMode 'weakFilter' and 'empty' is not optimized for huge data yet. + + each$22(seriesModels, function (seriesModel) { + var seriesData = seriesModel.getData(); + var dataDims = seriesData.mapDimension(axisDim, true); + + if (!dataDims.length) { + return; + } + + if (filterMode === 'weakFilter') { + seriesData.filterSelf(function (dataIndex) { + var leftOut; + var rightOut; + var hasValue; + for (var i = 0; i < dataDims.length; i++) { + var value = seriesData.get(dataDims[i], dataIndex); + var thisHasValue = !isNaN(value); + var thisLeftOut = value < valueWindow[0]; + var thisRightOut = value > valueWindow[1]; + if (thisHasValue && !thisLeftOut && !thisRightOut) { + return true; + } + thisHasValue && (hasValue = true); + thisLeftOut && (leftOut = true); + thisRightOut && (rightOut = true); + } + // If both left out and right out, do not filter. + return hasValue && leftOut && rightOut; + }); + } + else { + each$22(dataDims, function (dim) { + if (filterMode === 'empty') { + seriesModel.setData( + seriesData.map(dim, function (value) { + return !isInWindow(value) ? NaN : value; + }) + ); + } + else { + var range = {}; + range[dim] = valueWindow; + + // console.time('select'); + seriesData.selectRange(range); + // console.timeEnd('select'); + } + }); + } + + each$22(dataDims, function (dim) { + seriesData.setApproximateExtent(valueWindow, dim); + }); + }); + + function isInWindow(value) { + return value >= valueWindow[0] && value <= valueWindow[1]; + } + } +}; + +function calculateDataExtent(axisProxy, axisDim, seriesModels) { + var dataExtent = [Infinity, -Infinity]; + + each$22(seriesModels, function (seriesModel) { + var seriesData = seriesModel.getData(); + if (seriesData) { + each$22(seriesData.mapDimension(axisDim, true), function (dim) { + var seriesExtent = seriesData.getApproximateExtent(dim); + seriesExtent[0] < dataExtent[0] && (dataExtent[0] = seriesExtent[0]); + seriesExtent[1] > dataExtent[1] && (dataExtent[1] = seriesExtent[1]); + }); + } + }); + + if (dataExtent[1] < dataExtent[0]) { + dataExtent = [NaN, NaN]; + } + + // It is important to get "consistent" extent when more then one axes is + // controlled by a `dataZoom`, otherwise those axes will not be synchronized + // when zooming. But it is difficult to know what is "consistent", considering + // axes have different type or even different meanings (For example, two + // time axes are used to compare data of the same date in different years). + // So basically dataZoom just obtains extent by series.data (in category axis + // extent can be obtained from axis.data). + // Nevertheless, user can set min/max/scale on axes to make extent of axes + // consistent. + fixExtentByAxis(axisProxy, dataExtent); + + return dataExtent; +} + +function fixExtentByAxis(axisProxy, dataExtent) { + var axisModel = axisProxy.getAxisModel(); + var min = axisModel.getMin(true); + + // For category axis, if min/max/scale are not set, extent is determined + // by axis.data by default. + var isCategoryAxis = axisModel.get('type') === 'category'; + var axisDataLen = isCategoryAxis && axisModel.getCategories().length; + + if (min != null && min !== 'dataMin' && typeof min !== 'function') { + dataExtent[0] = min; + } + else if (isCategoryAxis) { + dataExtent[0] = axisDataLen > 0 ? 0 : NaN; + } + + var max = axisModel.getMax(true); + if (max != null && max !== 'dataMax' && typeof max !== 'function') { + dataExtent[1] = max; + } + else if (isCategoryAxis) { + dataExtent[1] = axisDataLen > 0 ? axisDataLen - 1 : NaN; + } + + if (!axisModel.get('scale', true)) { + dataExtent[0] > 0 && (dataExtent[0] = 0); + dataExtent[1] < 0 && (dataExtent[1] = 0); + } + + // For value axis, if min/max/scale are not set, we just use the extent obtained + // by series data, which may be a little different from the extent calculated by + // `axisHelper.getScaleExtent`. But the different just affects the experience a + // little when zooming. So it will not be fixed until some users require it strongly. + + return dataExtent; +} + +function setAxisModel(axisProxy, isRestore) { + var axisModel = axisProxy.getAxisModel(); + + var percentWindow = axisProxy._percentWindow; + var valueWindow = axisProxy._valueWindow; + + if (!percentWindow) { + return; + } + + // [0, 500]: arbitrary value, guess axis extent. + var precision = getPixelPrecision(valueWindow, [0, 500]); + precision = Math.min(precision, 20); + // isRestore or isFull + var useOrigin = isRestore || (percentWindow[0] === 0 && percentWindow[1] === 100); + + axisModel.setRange( + useOrigin ? null : +valueWindow[0].toFixed(precision), + useOrigin ? null : +valueWindow[1].toFixed(precision) + ); +} + +function setMinMaxSpan(axisProxy) { + var minMaxSpan = axisProxy._minMaxSpan = {}; + var dataZoomModel = axisProxy._dataZoomModel; + + each$22(['min', 'max'], function (minMax) { + minMaxSpan[minMax + 'Span'] = dataZoomModel.get(minMax + 'Span'); + + // minValueSpan and maxValueSpan has higher priority than minSpan and maxSpan + var valueSpan = dataZoomModel.get(minMax + 'ValueSpan'); + + if (valueSpan != null) { + minMaxSpan[minMax + 'ValueSpan'] = valueSpan; + valueSpan = axisProxy.getAxisModel().axis.scale.parse(valueSpan); + + if (valueSpan != null) { + var dataExtent = axisProxy._dataExtent; + minMaxSpan[minMax + 'Span'] = linearMap( + dataExtent[0] + valueSpan, dataExtent, [0, 100], true + ); + } + } + }); +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var each$21 = each$1; +var eachAxisDim = eachAxisDim$1; + +var DataZoomModel = extendComponentModel({ + + type: 'dataZoom', + + dependencies: [ + 'xAxis', 'yAxis', 'zAxis', 'radiusAxis', 'angleAxis', 'singleAxis', 'series' + ], + + /** + * @protected + */ + defaultOption: { + zlevel: 0, + z: 4, // Higher than normal component (z: 2). + orient: null, // Default auto by axisIndex. Possible value: 'horizontal', 'vertical'. + xAxisIndex: null, // Default the first horizontal category axis. + yAxisIndex: null, // Default the first vertical category axis. + + filterMode: 'filter', // Possible values: 'filter' or 'empty' or 'weakFilter'. + // 'filter': data items which are out of window will be removed. This option is + // applicable when filtering outliers. For each data item, it will be + // filtered if one of the relevant dimensions is out of the window. + // 'weakFilter': data items which are out of window will be removed. This option + // is applicable when filtering outliers. For each data item, it will be + // filtered only if all of the relevant dimensions are out of the same + // side of the window. + // 'empty': data items which are out of window will be set to empty. + // This option is applicable when user should not neglect + // that there are some data items out of window. + // 'none': Do not filter. + // Taking line chart as an example, line will be broken in + // the filtered points when filterModel is set to 'empty', but + // be connected when set to 'filter'. + + throttle: null, // Dispatch action by the fixed rate, avoid frequency. + // default 100. Do not throttle when use null/undefined. + // If animation === true and animationDurationUpdate > 0, + // default value is 100, otherwise 20. + start: 0, // Start percent. 0 ~ 100 + end: 100, // End percent. 0 ~ 100 + startValue: null, // Start value. If startValue specified, start is ignored. + endValue: null, // End value. If endValue specified, end is ignored. + minSpan: null, // 0 ~ 100 + maxSpan: null, // 0 ~ 100 + minValueSpan: null, // The range of dataZoom can not be smaller than that. + maxValueSpan: null, // The range of dataZoom can not be larger than that. + rangeMode: null // Array, can be 'value' or 'percent'. + }, + + /** + * @override + */ + init: function (option, parentModel, ecModel) { + + /** + * key like x_0, y_1 + * @private + * @type {Object} + */ + this._dataIntervalByAxis = {}; + + /** + * @private + */ + this._dataInfo = {}; + + /** + * key like x_0, y_1 + * @private + */ + this._axisProxies = {}; + + /** + * @readOnly + */ + this.textStyleModel; + + /** + * @private + */ + this._autoThrottle = true; + + /** + * 'percent' or 'value' + * @private + */ + this._rangePropMode = ['percent', 'percent']; + + var rawOption = retrieveRaw(option); + + this.mergeDefaultAndTheme(option, ecModel); + + this.doInit(rawOption); + }, + + /** + * @override + */ + mergeOption: function (newOption) { + var rawOption = retrieveRaw(newOption); + + //FIX #2591 + merge(this.option, newOption, true); + + this.doInit(rawOption); + }, + + /** + * @protected + */ + doInit: function (rawOption) { + var thisOption = this.option; + + // Disable realtime view update if canvas is not supported. + if (!env$1.canvasSupported) { + thisOption.realtime = false; + } + + this._setDefaultThrottle(rawOption); + + updateRangeUse(this, rawOption); + + each$21([['start', 'startValue'], ['end', 'endValue']], function (names, index) { + // start/end has higher priority over startValue/endValue if they + // both set, but we should make chart.setOption({endValue: 1000}) + // effective, rather than chart.setOption({endValue: 1000, end: null}). + if (this._rangePropMode[index] === 'value') { + thisOption[names[0]] = null; + } + // Otherwise do nothing and use the merge result. + }, this); + + this.textStyleModel = this.getModel('textStyle'); + + this._resetTarget(); + + this._giveAxisProxies(); + }, + + /** + * @private + */ + _giveAxisProxies: function () { + var axisProxies = this._axisProxies; + + this.eachTargetAxis(function (dimNames, axisIndex, dataZoomModel, ecModel) { + var axisModel = this.dependentModels[dimNames.axis][axisIndex]; + + // If exists, share axisProxy with other dataZoomModels. + var axisProxy = axisModel.__dzAxisProxy || ( + // Use the first dataZoomModel as the main model of axisProxy. + axisModel.__dzAxisProxy = new AxisProxy( + dimNames.name, axisIndex, this, ecModel + ) + ); + // FIXME + // dispose __dzAxisProxy + + axisProxies[dimNames.name + '_' + axisIndex] = axisProxy; + }, this); + }, + + /** + * @private + */ + _resetTarget: function () { + var thisOption = this.option; + + var autoMode = this._judgeAutoMode(); + + eachAxisDim(function (dimNames) { + var axisIndexName = dimNames.axisIndex; + thisOption[axisIndexName] = normalizeToArray( + thisOption[axisIndexName] + ); + }, this); + + if (autoMode === 'axisIndex') { + this._autoSetAxisIndex(); + } + else if (autoMode === 'orient') { + this._autoSetOrient(); + } + }, + + /** + * @private + */ + _judgeAutoMode: function () { + // Auto set only works for setOption at the first time. + // The following is user's reponsibility. So using merged + // option is OK. + var thisOption = this.option; + + var hasIndexSpecified = false; + eachAxisDim(function (dimNames) { + // When user set axisIndex as a empty array, we think that user specify axisIndex + // but do not want use auto mode. Because empty array may be encountered when + // some error occured. + if (thisOption[dimNames.axisIndex] != null) { + hasIndexSpecified = true; + } + }, this); + + var orient = thisOption.orient; + + if (orient == null && hasIndexSpecified) { + return 'orient'; + } + else if (!hasIndexSpecified) { + if (orient == null) { + thisOption.orient = 'horizontal'; + } + return 'axisIndex'; + } + }, + + /** + * @private + */ + _autoSetAxisIndex: function () { + var autoAxisIndex = true; + var orient = this.get('orient', true); + var thisOption = this.option; + var dependentModels = this.dependentModels; + + if (autoAxisIndex) { + // Find axis that parallel to dataZoom as default. + var dimName = orient === 'vertical' ? 'y' : 'x'; + + if (dependentModels[dimName + 'Axis'].length) { + thisOption[dimName + 'AxisIndex'] = [0]; + autoAxisIndex = false; + } + else { + each$21(dependentModels.singleAxis, function (singleAxisModel) { + if (autoAxisIndex && singleAxisModel.get('orient', true) === orient) { + thisOption.singleAxisIndex = [singleAxisModel.componentIndex]; + autoAxisIndex = false; + } + }); + } + } + + if (autoAxisIndex) { + // Find the first category axis as default. (consider polar) + eachAxisDim(function (dimNames) { + if (!autoAxisIndex) { + return; + } + var axisIndices = []; + var axisModels = this.dependentModels[dimNames.axis]; + if (axisModels.length && !axisIndices.length) { + for (var i = 0, len = axisModels.length; i < len; i++) { + if (axisModels[i].get('type') === 'category') { + axisIndices.push(i); + } + } + } + thisOption[dimNames.axisIndex] = axisIndices; + if (axisIndices.length) { + autoAxisIndex = false; + } + }, this); + } + + if (autoAxisIndex) { + // FIXME + // 这里是兼容ec2的写法(没指定xAxisIndex和yAxisIndex时把scatter和双数值轴折柱纳入dataZoom控制), + // 但是实际是否需要Grid.js#getScaleByOption来判断(考虑time,log等axis type)? + + // If both dataZoom.xAxisIndex and dataZoom.yAxisIndex is not specified, + // dataZoom component auto adopts series that reference to + // both xAxis and yAxis which type is 'value'. + this.ecModel.eachSeries(function (seriesModel) { + if (this._isSeriesHasAllAxesTypeOf(seriesModel, 'value')) { + eachAxisDim(function (dimNames) { + var axisIndices = thisOption[dimNames.axisIndex]; + + var axisIndex = seriesModel.get(dimNames.axisIndex); + var axisId = seriesModel.get(dimNames.axisId); + + var axisModel = seriesModel.ecModel.queryComponents({ + mainType: dimNames.axis, + index: axisIndex, + id: axisId + })[0]; + + if (__DEV__) { + if (!axisModel) { + throw new Error( + dimNames.axis + ' "' + retrieve( + axisIndex, + axisId, + 0 + ) + '" not found' + ); + } + } + axisIndex = axisModel.componentIndex; + + if (indexOf(axisIndices, axisIndex) < 0) { + axisIndices.push(axisIndex); + } + }); + } + }, this); + } + }, + + /** + * @private + */ + _autoSetOrient: function () { + var dim; + + // Find the first axis + this.eachTargetAxis(function (dimNames) { + !dim && (dim = dimNames.name); + }, this); + + this.option.orient = dim === 'y' ? 'vertical' : 'horizontal'; + }, + + /** + * @private + */ + _isSeriesHasAllAxesTypeOf: function (seriesModel, axisType) { + // FIXME + // 需要series的xAxisIndex和yAxisIndex都首先自动设置上。 + // 例如series.type === scatter时。 + + var is = true; + eachAxisDim(function (dimNames) { + var seriesAxisIndex = seriesModel.get(dimNames.axisIndex); + var axisModel = this.dependentModels[dimNames.axis][seriesAxisIndex]; + + if (!axisModel || axisModel.get('type') !== axisType) { + is = false; + } + }, this); + return is; + }, + + /** + * @private + */ + _setDefaultThrottle: function (rawOption) { + // When first time user set throttle, auto throttle ends. + if (rawOption.hasOwnProperty('throttle')) { + this._autoThrottle = false; + } + if (this._autoThrottle) { + var globalOption = this.ecModel.option; + this.option.throttle + = (globalOption.animation && globalOption.animationDurationUpdate > 0) + ? 100 : 20; + } + }, + + /** + * @public + */ + getFirstTargetAxisModel: function () { + var firstAxisModel; + eachAxisDim(function (dimNames) { + if (firstAxisModel == null) { + var indices = this.get(dimNames.axisIndex); + if (indices.length) { + firstAxisModel = this.dependentModels[dimNames.axis][indices[0]]; + } + } + }, this); + + return firstAxisModel; + }, + + /** + * @public + * @param {Function} callback param: axisModel, dimNames, axisIndex, dataZoomModel, ecModel + */ + eachTargetAxis: function (callback, context) { + var ecModel = this.ecModel; + eachAxisDim(function (dimNames) { + each$21( + this.get(dimNames.axisIndex), + function (axisIndex) { + callback.call(context, dimNames, axisIndex, this, ecModel); + }, + this + ); + }, this); + }, + + /** + * @param {string} dimName + * @param {number} axisIndex + * @return {module:echarts/component/dataZoom/AxisProxy} If not found, return null/undefined. + */ + getAxisProxy: function (dimName, axisIndex) { + return this._axisProxies[dimName + '_' + axisIndex]; + }, + + /** + * @param {string} dimName + * @param {number} axisIndex + * @return {module:echarts/model/Model} If not found, return null/undefined. + */ + getAxisModel: function (dimName, axisIndex) { + var axisProxy = this.getAxisProxy(dimName, axisIndex); + return axisProxy && axisProxy.getAxisModel(); + }, + + /** + * If not specified, set to undefined. + * + * @public + * @param {Object} opt + * @param {number} [opt.start] + * @param {number} [opt.end] + * @param {number} [opt.startValue] + * @param {number} [opt.endValue] + * @param {boolean} [ignoreUpdateRangeUsg=false] + */ + setRawRange: function (opt, ignoreUpdateRangeUsg) { + var option = this.option; + each$21([['start', 'startValue'], ['end', 'endValue']], function (names) { + // If only one of 'start' and 'startValue' is not null/undefined, the other + // should be cleared, which enable clear the option. + // If both of them are not set, keep option with the original value, which + // enable use only set start but not set end when calling `dispatchAction`. + // The same as 'end' and 'endValue'. + if (opt[names[0]] != null || opt[names[1]] != null) { + option[names[0]] = opt[names[0]]; + option[names[1]] = opt[names[1]]; + } + }, this); + + !ignoreUpdateRangeUsg && updateRangeUse(this, opt); + }, + + /** + * @public + * @return {Array.} [startPercent, endPercent] + */ + getPercentRange: function () { + var axisProxy = this.findRepresentativeAxisProxy(); + if (axisProxy) { + return axisProxy.getDataPercentWindow(); + } + }, + + /** + * @public + * For example, chart.getModel().getComponent('dataZoom').getValueRange('y', 0); + * + * @param {string} [axisDimName] + * @param {number} [axisIndex] + * @return {Array.} [startValue, endValue] value can only be '-' or finite number. + */ + getValueRange: function (axisDimName, axisIndex) { + if (axisDimName == null && axisIndex == null) { + var axisProxy = this.findRepresentativeAxisProxy(); + if (axisProxy) { + return axisProxy.getDataValueWindow(); + } + } + else { + return this.getAxisProxy(axisDimName, axisIndex).getDataValueWindow(); + } + }, + + /** + * @public + * @param {module:echarts/model/Model} [axisModel] If axisModel given, find axisProxy + * corresponding to the axisModel + * @return {module:echarts/component/dataZoom/AxisProxy} + */ + findRepresentativeAxisProxy: function (axisModel) { + if (axisModel) { + return axisModel.__dzAxisProxy; + } + + // Find the first hosted axisProxy + var axisProxies = this._axisProxies; + for (var key in axisProxies) { + if (axisProxies.hasOwnProperty(key) && axisProxies[key].hostedBy(this)) { + return axisProxies[key]; + } + } + + // If no hosted axis find not hosted axisProxy. + // Consider this case: dataZoomModel1 and dataZoomModel2 control the same axis, + // and the option.start or option.end settings are different. The percentRange + // should follow axisProxy. + // (We encounter this problem in toolbox data zoom.) + for (var key in axisProxies) { + if (axisProxies.hasOwnProperty(key) && !axisProxies[key].hostedBy(this)) { + return axisProxies[key]; + } + } + }, + + /** + * @return {Array.} + */ + getRangePropMode: function () { + return this._rangePropMode.slice(); + } + +}); + +function retrieveRaw(option) { + var ret = {}; + each$21( + ['start', 'end', 'startValue', 'endValue', 'throttle'], + function (name) { + option.hasOwnProperty(name) && (ret[name] = option[name]); + } + ); + return ret; +} + +function updateRangeUse(dataZoomModel, rawOption) { + var rangePropMode = dataZoomModel._rangePropMode; + var rangeModeInOption = dataZoomModel.get('rangeMode'); + + each$21([['start', 'startValue'], ['end', 'endValue']], function (names, index) { + var percentSpecified = rawOption[names[0]] != null; + var valueSpecified = rawOption[names[1]] != null; + if (percentSpecified && !valueSpecified) { + rangePropMode[index] = 'percent'; + } + else if (!percentSpecified && valueSpecified) { + rangePropMode[index] = 'value'; + } + else if (rangeModeInOption) { + rangePropMode[index] = rangeModeInOption[index]; + } + else if (percentSpecified) { // percentSpecified && valueSpecified + rangePropMode[index] = 'percent'; + } + // else remain its original setting. + }); +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var DataZoomView = Component.extend({ + + type: 'dataZoom', + + render: function (dataZoomModel, ecModel, api, payload) { + this.dataZoomModel = dataZoomModel; + this.ecModel = ecModel; + this.api = api; + }, + + /** + * Find the first target coordinate system. + * + * @protected + * @return {Object} { + * grid: [ + * {model: coord0, axisModels: [axis1, axis3], coordIndex: 1}, + * {model: coord1, axisModels: [axis0, axis2], coordIndex: 0}, + * ... + * ], // cartesians must not be null/undefined. + * polar: [ + * {model: coord0, axisModels: [axis4], coordIndex: 0}, + * ... + * ], // polars must not be null/undefined. + * singleAxis: [ + * {model: coord0, axisModels: [], coordIndex: 0} + * ] + */ + getTargetCoordInfo: function () { + var dataZoomModel = this.dataZoomModel; + var ecModel = this.ecModel; + var coordSysLists = {}; + + dataZoomModel.eachTargetAxis(function (dimNames, axisIndex) { + var axisModel = ecModel.getComponent(dimNames.axis, axisIndex); + if (axisModel) { + var coordModel = axisModel.getCoordSysModel(); + coordModel && save( + coordModel, + axisModel, + coordSysLists[coordModel.mainType] || (coordSysLists[coordModel.mainType] = []), + coordModel.componentIndex + ); + } + }, this); + + function save(coordModel, axisModel, store, coordIndex) { + var item; + for (var i = 0; i < store.length; i++) { + if (store[i].model === coordModel) { + item = store[i]; + break; + } + } + if (!item) { + store.push(item = { + model: coordModel, axisModels: [], coordIndex: coordIndex + }); + } + item.axisModels.push(axisModel); + } + + return coordSysLists; + } + +}); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var SliderZoomModel = DataZoomModel.extend({ + + type: 'dataZoom.slider', + + layoutMode: 'box', + + /** + * @protected + */ + defaultOption: { + show: true, + + // ph => placeholder. Using placehoder here because + // deault value can only be drived in view stage. + right: 'ph', // Default align to grid rect. + top: 'ph', // Default align to grid rect. + width: 'ph', // Default align to grid rect. + height: 'ph', // Default align to grid rect. + left: null, // Default align to grid rect. + bottom: null, // Default align to grid rect. + + backgroundColor: 'rgba(47,69,84,0)', // Background of slider zoom component. + // dataBackgroundColor: '#ddd', // Background coor of data shadow and border of box, + // highest priority, remain for compatibility of + // previous version, but not recommended any more. + dataBackground: { + lineStyle: { + color: '#2f4554', + width: 0.5, + opacity: 0.3 + }, + areaStyle: { + color: 'rgba(47,69,84,0.3)', + opacity: 0.3 + } + }, + borderColor: '#ddd', // border color of the box. For compatibility, + // if dataBackgroundColor is set, borderColor + // is ignored. + + fillerColor: 'rgba(167,183,204,0.4)', // Color of selected area. + // handleColor: 'rgba(89,170,216,0.95)', // Color of handle. + // handleIcon: 'path://M4.9,17.8c0-1.4,4.5-10.5,5.5-12.4c0-0.1,0.6-1.1,0.9-1.1c0.4,0,0.9,1,0.9,1.1c1.1,2.2,5.4,11,5.4,12.4v17.8c0,1.5-0.6,2.1-1.3,2.1H6.1c-0.7,0-1.3-0.6-1.3-2.1V17.8z', + /* eslint-disable */ + handleIcon: 'M8.2,13.6V3.9H6.3v9.7H3.1v14.9h3.3v9.7h1.8v-9.7h3.3V13.6H8.2z M9.7,24.4H4.8v-1.4h4.9V24.4z M9.7,19.1H4.8v-1.4h4.9V19.1z', + /* eslint-enable */ + // Percent of the slider height + handleSize: '100%', + + handleStyle: { + color: '#a7b7cc' + }, + + labelPrecision: null, + labelFormatter: null, + showDetail: true, + showDataShadow: 'auto', // Default auto decision. + realtime: true, + zoomLock: false, // Whether disable zoom. + textStyle: { + color: '#333' + } + } + +}); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var Rect$2 = Rect; +var linearMap$1 = linearMap; +var asc$2 = asc; +var bind$4 = bind; +var each$23 = each$1; + +// Constants +var DEFAULT_LOCATION_EDGE_GAP = 7; +var DEFAULT_FRAME_BORDER_WIDTH = 1; +var DEFAULT_FILLER_SIZE = 30; +var HORIZONTAL = 'horizontal'; +var VERTICAL = 'vertical'; +var LABEL_GAP = 5; +var SHOW_DATA_SHADOW_SERIES_TYPE = ['line', 'bar', 'candlestick', 'scatter']; + +var SliderZoomView = DataZoomView.extend({ + + type: 'dataZoom.slider', + + init: function (ecModel, api) { + + /** + * @private + * @type {Object} + */ + this._displayables = {}; + + /** + * @private + * @type {string} + */ + this._orient; + + /** + * [0, 100] + * @private + */ + this._range; + + /** + * [coord of the first handle, coord of the second handle] + * @private + */ + this._handleEnds; + + /** + * [length, thick] + * @private + * @type {Array.} + */ + this._size; + + /** + * @private + * @type {number} + */ + this._handleWidth; + + /** + * @private + * @type {number} + */ + this._handleHeight; + + /** + * @private + */ + this._location; + + /** + * @private + */ + this._dragging; + + /** + * @private + */ + this._dataShadowInfo; + + this.api = api; + }, + + /** + * @override + */ + render: function (dataZoomModel, ecModel, api, payload) { + SliderZoomView.superApply(this, 'render', arguments); + + createOrUpdate( + this, + '_dispatchZoomAction', + this.dataZoomModel.get('throttle'), + 'fixRate' + ); + + this._orient = dataZoomModel.get('orient'); + + if (this.dataZoomModel.get('show') === false) { + this.group.removeAll(); + return; + } + + // Notice: this._resetInterval() should not be executed when payload.type + // is 'dataZoom', origin this._range should be maintained, otherwise 'pan' + // or 'zoom' info will be missed because of 'throttle' of this.dispatchAction, + if (!payload || payload.type !== 'dataZoom' || payload.from !== this.uid) { + this._buildView(); + } + + this._updateView(); + }, + + /** + * @override + */ + remove: function () { + SliderZoomView.superApply(this, 'remove', arguments); + clear(this, '_dispatchZoomAction'); + }, + + /** + * @override + */ + dispose: function () { + SliderZoomView.superApply(this, 'dispose', arguments); + clear(this, '_dispatchZoomAction'); + }, + + _buildView: function () { + var thisGroup = this.group; + + thisGroup.removeAll(); + + this._resetLocation(); + this._resetInterval(); + + var barGroup = this._displayables.barGroup = new Group(); + + this._renderBackground(); + + this._renderHandle(); + + this._renderDataShadow(); + + thisGroup.add(barGroup); + + this._positionGroup(); + }, + + /** + * @private + */ + _resetLocation: function () { + var dataZoomModel = this.dataZoomModel; + var api = this.api; + + // If some of x/y/width/height are not specified, + // auto-adapt according to target grid. + var coordRect = this._findCoordRect(); + var ecSize = {width: api.getWidth(), height: api.getHeight()}; + // Default align by coordinate system rect. + var positionInfo = this._orient === HORIZONTAL + ? { + // Why using 'right', because right should be used in vertical, + // and it is better to be consistent for dealing with position param merge. + right: ecSize.width - coordRect.x - coordRect.width, + top: (ecSize.height - DEFAULT_FILLER_SIZE - DEFAULT_LOCATION_EDGE_GAP), + width: coordRect.width, + height: DEFAULT_FILLER_SIZE + } + : { // vertical + right: DEFAULT_LOCATION_EDGE_GAP, + top: coordRect.y, + width: DEFAULT_FILLER_SIZE, + height: coordRect.height + }; + + // Do not write back to option and replace value 'ph', because + // the 'ph' value should be recalculated when resize. + var layoutParams = getLayoutParams(dataZoomModel.option); + + // Replace the placeholder value. + each$1(['right', 'top', 'width', 'height'], function (name) { + if (layoutParams[name] === 'ph') { + layoutParams[name] = positionInfo[name]; + } + }); + + var layoutRect = getLayoutRect( + layoutParams, + ecSize, + dataZoomModel.padding + ); + + this._location = {x: layoutRect.x, y: layoutRect.y}; + this._size = [layoutRect.width, layoutRect.height]; + this._orient === VERTICAL && this._size.reverse(); + }, + + /** + * @private + */ + _positionGroup: function () { + var thisGroup = this.group; + var location = this._location; + var orient = this._orient; + + // Just use the first axis to determine mapping. + var targetAxisModel = this.dataZoomModel.getFirstTargetAxisModel(); + var inverse = targetAxisModel && targetAxisModel.get('inverse'); + + var barGroup = this._displayables.barGroup; + var otherAxisInverse = (this._dataShadowInfo || {}).otherAxisInverse; + + // Transform barGroup. + barGroup.attr( + (orient === HORIZONTAL && !inverse) + ? {scale: otherAxisInverse ? [1, 1] : [1, -1]} + : (orient === HORIZONTAL && inverse) + ? {scale: otherAxisInverse ? [-1, 1] : [-1, -1]} + : (orient === VERTICAL && !inverse) + ? {scale: otherAxisInverse ? [1, -1] : [1, 1], rotation: Math.PI / 2} + // Dont use Math.PI, considering shadow direction. + : {scale: otherAxisInverse ? [-1, -1] : [-1, 1], rotation: Math.PI / 2} + ); + + // Position barGroup + var rect = thisGroup.getBoundingRect([barGroup]); + thisGroup.attr('position', [location.x - rect.x, location.y - rect.y]); + }, + + /** + * @private + */ + _getViewExtent: function () { + return [0, this._size[0]]; + }, + + _renderBackground: function () { + var dataZoomModel = this.dataZoomModel; + var size = this._size; + var barGroup = this._displayables.barGroup; + + barGroup.add(new Rect$2({ + silent: true, + shape: { + x: 0, y: 0, width: size[0], height: size[1] + }, + style: { + fill: dataZoomModel.get('backgroundColor') + }, + z2: -40 + })); + + // Click panel, over shadow, below handles. + barGroup.add(new Rect$2({ + shape: { + x: 0, y: 0, width: size[0], height: size[1] + }, + style: { + fill: 'transparent' + }, + z2: 0, + onclick: bind(this._onClickPanelClick, this) + })); + }, + + _renderDataShadow: function () { + var info = this._dataShadowInfo = this._prepareDataShadowInfo(); + + if (!info) { + return; + } + + var size = this._size; + var seriesModel = info.series; + var data = seriesModel.getRawData(); + + var otherDim = seriesModel.getShadowDim + ? seriesModel.getShadowDim() // @see candlestick + : info.otherDim; + + if (otherDim == null) { + return; + } + + var otherDataExtent = data.getDataExtent(otherDim); + // Nice extent. + var otherOffset = (otherDataExtent[1] - otherDataExtent[0]) * 0.3; + otherDataExtent = [ + otherDataExtent[0] - otherOffset, + otherDataExtent[1] + otherOffset + ]; + var otherShadowExtent = [0, size[1]]; + + var thisShadowExtent = [0, size[0]]; + + var areaPoints = [[size[0], 0], [0, 0]]; + var linePoints = []; + var step = thisShadowExtent[1] / (data.count() - 1); + var thisCoord = 0; + + // Optimize for large data shadow + var stride = Math.round(data.count() / size[0]); + var lastIsEmpty; + data.each([otherDim], function (value, index) { + if (stride > 0 && (index % stride)) { + thisCoord += step; + return; + } + + // FIXME + // Should consider axis.min/axis.max when drawing dataShadow. + + // FIXME + // 应该使用统一的空判断?还是在list里进行空判断? + var isEmpty = value == null || isNaN(value) || value === ''; + // See #4235. + var otherCoord = isEmpty + ? 0 : linearMap$1(value, otherDataExtent, otherShadowExtent, true); + + // Attempt to draw data shadow precisely when there are empty value. + if (isEmpty && !lastIsEmpty && index) { + areaPoints.push([areaPoints[areaPoints.length - 1][0], 0]); + linePoints.push([linePoints[linePoints.length - 1][0], 0]); + } + else if (!isEmpty && lastIsEmpty) { + areaPoints.push([thisCoord, 0]); + linePoints.push([thisCoord, 0]); + } + + areaPoints.push([thisCoord, otherCoord]); + linePoints.push([thisCoord, otherCoord]); + + thisCoord += step; + lastIsEmpty = isEmpty; + }); + + var dataZoomModel = this.dataZoomModel; + // var dataBackgroundModel = dataZoomModel.getModel('dataBackground'); + this._displayables.barGroup.add(new Polygon({ + shape: {points: areaPoints}, + style: defaults( + {fill: dataZoomModel.get('dataBackgroundColor')}, + dataZoomModel.getModel('dataBackground.areaStyle').getAreaStyle() + ), + silent: true, + z2: -20 + })); + this._displayables.barGroup.add(new Polyline({ + shape: {points: linePoints}, + style: dataZoomModel.getModel('dataBackground.lineStyle').getLineStyle(), + silent: true, + z2: -19 + })); + }, + + _prepareDataShadowInfo: function () { + var dataZoomModel = this.dataZoomModel; + var showDataShadow = dataZoomModel.get('showDataShadow'); + + if (showDataShadow === false) { + return; + } + + // Find a representative series. + var result; + var ecModel = this.ecModel; + + dataZoomModel.eachTargetAxis(function (dimNames, axisIndex) { + var seriesModels = dataZoomModel + .getAxisProxy(dimNames.name, axisIndex) + .getTargetSeriesModels(); + + each$1(seriesModels, function (seriesModel) { + if (result) { + return; + } + + if (showDataShadow !== true && indexOf( + SHOW_DATA_SHADOW_SERIES_TYPE, seriesModel.get('type') + ) < 0 + ) { + return; + } + + var thisAxis = ecModel.getComponent(dimNames.axis, axisIndex).axis; + var otherDim = getOtherDim(dimNames.name); + var otherAxisInverse; + var coordSys = seriesModel.coordinateSystem; + + if (otherDim != null && coordSys.getOtherAxis) { + otherAxisInverse = coordSys.getOtherAxis(thisAxis).inverse; + } + + otherDim = seriesModel.getData().mapDimension(otherDim); + + result = { + thisAxis: thisAxis, + series: seriesModel, + thisDim: dimNames.name, + otherDim: otherDim, + otherAxisInverse: otherAxisInverse + }; + + }, this); + + }, this); + + return result; + }, + + _renderHandle: function () { + var displaybles = this._displayables; + var handles = displaybles.handles = []; + var handleLabels = displaybles.handleLabels = []; + var barGroup = this._displayables.barGroup; + var size = this._size; + var dataZoomModel = this.dataZoomModel; + + barGroup.add(displaybles.filler = new Rect$2({ + draggable: true, + cursor: getCursor(this._orient), + drift: bind$4(this._onDragMove, this, 'all'), + onmousemove: function (e) { + // Fot mobile devicem, prevent screen slider on the button. + stop(e.event); + }, + ondragstart: bind$4(this._showDataInfo, this, true), + ondragend: bind$4(this._onDragEnd, this), + onmouseover: bind$4(this._showDataInfo, this, true), + onmouseout: bind$4(this._showDataInfo, this, false), + style: { + fill: dataZoomModel.get('fillerColor'), + textPosition: 'inside' + } + })); + + // Frame border. + barGroup.add(new Rect$2(subPixelOptimizeRect({ + silent: true, + shape: { + x: 0, + y: 0, + width: size[0], + height: size[1] + }, + style: { + stroke: dataZoomModel.get('dataBackgroundColor') + || dataZoomModel.get('borderColor'), + lineWidth: DEFAULT_FRAME_BORDER_WIDTH, + fill: 'rgba(0,0,0,0)' + } + }))); + + each$23([0, 1], function (handleIndex) { + var path = createIcon( + dataZoomModel.get('handleIcon'), + { + cursor: getCursor(this._orient), + draggable: true, + drift: bind$4(this._onDragMove, this, handleIndex), + onmousemove: function (e) { + // Fot mobile devicem, prevent screen slider on the button. + stop(e.event); + }, + ondragend: bind$4(this._onDragEnd, this), + onmouseover: bind$4(this._showDataInfo, this, true), + onmouseout: bind$4(this._showDataInfo, this, false) + }, + {x: -1, y: 0, width: 2, height: 2} + ); + + var bRect = path.getBoundingRect(); + this._handleHeight = parsePercent$1(dataZoomModel.get('handleSize'), this._size[1]); + this._handleWidth = bRect.width / bRect.height * this._handleHeight; + + path.setStyle(dataZoomModel.getModel('handleStyle').getItemStyle()); + var handleColor = dataZoomModel.get('handleColor'); + // Compatitable with previous version + if (handleColor != null) { + path.style.fill = handleColor; + } + + barGroup.add(handles[handleIndex] = path); + + var textStyleModel = dataZoomModel.textStyleModel; + + this.group.add( + handleLabels[handleIndex] = new Text({ + silent: true, + invisible: true, + style: { + x: 0, y: 0, text: '', + textVerticalAlign: 'middle', + textAlign: 'center', + textFill: textStyleModel.getTextColor(), + textFont: textStyleModel.getFont() + }, + z2: 10 + })); + + }, this); + }, + + /** + * @private + */ + _resetInterval: function () { + var range = this._range = this.dataZoomModel.getPercentRange(); + var viewExtent = this._getViewExtent(); + + this._handleEnds = [ + linearMap$1(range[0], [0, 100], viewExtent, true), + linearMap$1(range[1], [0, 100], viewExtent, true) + ]; + }, + + /** + * @private + * @param {(number|string)} handleIndex 0 or 1 or 'all' + * @param {number} delta + * @return {boolean} changed + */ + _updateInterval: function (handleIndex, delta) { + var dataZoomModel = this.dataZoomModel; + var handleEnds = this._handleEnds; + var viewExtend = this._getViewExtent(); + var minMaxSpan = dataZoomModel.findRepresentativeAxisProxy().getMinMaxSpan(); + var percentExtent = [0, 100]; + + sliderMove( + delta, + handleEnds, + viewExtend, + dataZoomModel.get('zoomLock') ? 'all' : handleIndex, + minMaxSpan.minSpan != null + ? linearMap$1(minMaxSpan.minSpan, percentExtent, viewExtend, true) : null, + minMaxSpan.maxSpan != null + ? linearMap$1(minMaxSpan.maxSpan, percentExtent, viewExtend, true) : null + ); + + var lastRange = this._range; + var range = this._range = asc$2([ + linearMap$1(handleEnds[0], viewExtend, percentExtent, true), + linearMap$1(handleEnds[1], viewExtend, percentExtent, true) + ]); + + return !lastRange || lastRange[0] !== range[0] || lastRange[1] !== range[1]; + }, + + /** + * @private + */ + _updateView: function (nonRealtime) { + var displaybles = this._displayables; + var handleEnds = this._handleEnds; + var handleInterval = asc$2(handleEnds.slice()); + var size = this._size; + + each$23([0, 1], function (handleIndex) { + // Handles + var handle = displaybles.handles[handleIndex]; + var handleHeight = this._handleHeight; + handle.attr({ + scale: [handleHeight / 2, handleHeight / 2], + position: [handleEnds[handleIndex], size[1] / 2 - handleHeight / 2] + }); + }, this); + + // Filler + displaybles.filler.setShape({ + x: handleInterval[0], + y: 0, + width: handleInterval[1] - handleInterval[0], + height: size[1] + }); + + this._updateDataInfo(nonRealtime); + }, + + /** + * @private + */ + _updateDataInfo: function (nonRealtime) { + var dataZoomModel = this.dataZoomModel; + var displaybles = this._displayables; + var handleLabels = displaybles.handleLabels; + var orient = this._orient; + var labelTexts = ['', '']; + + // FIXME + // date型,支持formatter,autoformatter(ec2 date.getAutoFormatter) + if (dataZoomModel.get('showDetail')) { + var axisProxy = dataZoomModel.findRepresentativeAxisProxy(); + + if (axisProxy) { + var axis = axisProxy.getAxisModel().axis; + var range = this._range; + + var dataInterval = nonRealtime + // See #4434, data and axis are not processed and reset yet in non-realtime mode. + ? axisProxy.calculateDataWindow({ + start: range[0], end: range[1] + }).valueWindow + : axisProxy.getDataValueWindow(); + + labelTexts = [ + this._formatLabel(dataInterval[0], axis), + this._formatLabel(dataInterval[1], axis) + ]; + } + } + + var orderedHandleEnds = asc$2(this._handleEnds.slice()); + + setLabel.call(this, 0); + setLabel.call(this, 1); + + function setLabel(handleIndex) { + // Label + // Text should not transform by barGroup. + // Ignore handlers transform + var barTransform = getTransform( + displaybles.handles[handleIndex].parent, this.group + ); + var direction = transformDirection( + handleIndex === 0 ? 'right' : 'left', barTransform + ); + var offset = this._handleWidth / 2 + LABEL_GAP; + var textPoint = applyTransform$1( + [ + orderedHandleEnds[handleIndex] + (handleIndex === 0 ? -offset : offset), + this._size[1] / 2 + ], + barTransform + ); + handleLabels[handleIndex].setStyle({ + x: textPoint[0], + y: textPoint[1], + textVerticalAlign: orient === HORIZONTAL ? 'middle' : direction, + textAlign: orient === HORIZONTAL ? direction : 'center', + text: labelTexts[handleIndex] + }); + } + }, + + /** + * @private + */ + _formatLabel: function (value, axis) { + var dataZoomModel = this.dataZoomModel; + var labelFormatter = dataZoomModel.get('labelFormatter'); + + var labelPrecision = dataZoomModel.get('labelPrecision'); + if (labelPrecision == null || labelPrecision === 'auto') { + labelPrecision = axis.getPixelPrecision(); + } + + var valueStr = (value == null || isNaN(value)) + ? '' + // FIXME Glue code + : (axis.type === 'category' || axis.type === 'time') + ? axis.scale.getLabel(Math.round(value)) + // param of toFixed should less then 20. + : value.toFixed(Math.min(labelPrecision, 20)); + + return isFunction$1(labelFormatter) + ? labelFormatter(value, valueStr) + : isString(labelFormatter) + ? labelFormatter.replace('{value}', valueStr) + : valueStr; + }, + + /** + * @private + * @param {boolean} showOrHide true: show, false: hide + */ + _showDataInfo: function (showOrHide) { + // Always show when drgging. + showOrHide = this._dragging || showOrHide; + + var handleLabels = this._displayables.handleLabels; + handleLabels[0].attr('invisible', !showOrHide); + handleLabels[1].attr('invisible', !showOrHide); + }, + + _onDragMove: function (handleIndex, dx, dy) { + this._dragging = true; + + // Transform dx, dy to bar coordination. + var barTransform = this._displayables.barGroup.getLocalTransform(); + var vertex = applyTransform$1([dx, dy], barTransform, true); + + var changed = this._updateInterval(handleIndex, vertex[0]); + + var realtime = this.dataZoomModel.get('realtime'); + + this._updateView(!realtime); + + // Avoid dispatch dataZoom repeatly but range not changed, + // which cause bad visual effect when progressive enabled. + changed && realtime && this._dispatchZoomAction(); + }, + + _onDragEnd: function () { + this._dragging = false; + this._showDataInfo(false); + + // While in realtime mode and stream mode, dispatch action when + // drag end will cause the whole view rerender, which is unnecessary. + var realtime = this.dataZoomModel.get('realtime'); + !realtime && this._dispatchZoomAction(); + }, + + _onClickPanelClick: function (e) { + var size = this._size; + var localPoint = this._displayables.barGroup.transformCoordToLocal(e.offsetX, e.offsetY); + + if (localPoint[0] < 0 || localPoint[0] > size[0] + || localPoint[1] < 0 || localPoint[1] > size[1] + ) { + return; + } + + var handleEnds = this._handleEnds; + var center = (handleEnds[0] + handleEnds[1]) / 2; + + var changed = this._updateInterval('all', localPoint[0] - center); + this._updateView(); + changed && this._dispatchZoomAction(); + }, + + /** + * This action will be throttled. + * @private + */ + _dispatchZoomAction: function () { + var range = this._range; + + this.api.dispatchAction({ + type: 'dataZoom', + from: this.uid, + dataZoomId: this.dataZoomModel.id, + start: range[0], + end: range[1] + }); + }, + + /** + * @private + */ + _findCoordRect: function () { + // Find the grid coresponding to the first axis referred by dataZoom. + var rect; + each$23(this.getTargetCoordInfo(), function (coordInfoList) { + if (!rect && coordInfoList.length) { + var coordSys = coordInfoList[0].model.coordinateSystem; + rect = coordSys.getRect && coordSys.getRect(); + } + }); + if (!rect) { + var width = this.api.getWidth(); + var height = this.api.getHeight(); + rect = { + x: width * 0.2, + y: height * 0.2, + width: width * 0.6, + height: height * 0.6 + }; + } + + return rect; + } + +}); + +function getOtherDim(thisDim) { + // FIXME + // 这个逻辑和getOtherAxis里一致,但是写在这里是否不好 + var map$$1 = {x: 'y', y: 'x', radius: 'angle', angle: 'radius'}; + return map$$1[thisDim]; +} + +function getCursor(orient) { + return orient === 'vertical' ? 'ns-resize' : 'ew-resize'; +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +DataZoomModel.extend({ + + type: 'dataZoom.inside', + + /** + * @protected + */ + defaultOption: { + disabled: false, // Whether disable this inside zoom. + zoomLock: false, // Whether disable zoom but only pan. + zoomOnMouseWheel: true, // Can be: true / false / 'shift' / 'ctrl' / 'alt'. + moveOnMouseMove: true, // Can be: true / false / 'shift' / 'ctrl' / 'alt'. + moveOnMouseWheel: false, // Can be: true / false / 'shift' / 'ctrl' / 'alt'. + preventDefaultMouseMove: true + } +}); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +// Only create one roam controller for each coordinate system. +// one roam controller might be refered by two inside data zoom +// components (for example, one for x and one for y). When user +// pan or zoom, only dispatch one action for those data zoom +// components. + +var ATTR$1 = '\0_ec_dataZoom_roams'; + + +/** + * @public + * @param {module:echarts/ExtensionAPI} api + * @param {Object} dataZoomInfo + * @param {string} dataZoomInfo.coordId + * @param {Function} dataZoomInfo.containsPoint + * @param {Array.} dataZoomInfo.allCoordIds + * @param {string} dataZoomInfo.dataZoomId + * @param {Object} dataZoomInfo.getRange + * @param {Function} dataZoomInfo.getRange.pan + * @param {Function} dataZoomInfo.getRange.zoom + * @param {Function} dataZoomInfo.getRange.scrollMove + * @param {boolean} dataZoomInfo.dataZoomModel + */ +function register$2(api, dataZoomInfo) { + var store = giveStore(api); + var theDataZoomId = dataZoomInfo.dataZoomId; + var theCoordId = dataZoomInfo.coordId; + + // Do clean when a dataZoom changes its target coordnate system. + // Avoid memory leak, dispose all not-used-registered. + each$1(store, function (record, coordId) { + var dataZoomInfos = record.dataZoomInfos; + if (dataZoomInfos[theDataZoomId] + && indexOf(dataZoomInfo.allCoordIds, theCoordId) < 0 + ) { + delete dataZoomInfos[theDataZoomId]; + record.count--; + } + }); + + cleanStore(store); + + var record = store[theCoordId]; + // Create if needed. + if (!record) { + record = store[theCoordId] = { + coordId: theCoordId, + dataZoomInfos: {}, + count: 0 + }; + record.controller = createController(api, record); + record.dispatchAction = curry(dispatchAction$1, api); + } + + // Update reference of dataZoom. + !(record.dataZoomInfos[theDataZoomId]) && record.count++; + record.dataZoomInfos[theDataZoomId] = dataZoomInfo; + + var controllerParams = mergeControllerParams(record.dataZoomInfos); + record.controller.enable(controllerParams.controlType, controllerParams.opt); + + // Consider resize, area should be always updated. + record.controller.setPointerChecker(dataZoomInfo.containsPoint); + + // Update throttle. + createOrUpdate( + record, + 'dispatchAction', + dataZoomInfo.dataZoomModel.get('throttle', true), + 'fixRate' + ); +} + +/** + * @public + * @param {module:echarts/ExtensionAPI} api + * @param {string} dataZoomId + */ +function unregister$1(api, dataZoomId) { + var store = giveStore(api); + + each$1(store, function (record) { + record.controller.dispose(); + var dataZoomInfos = record.dataZoomInfos; + if (dataZoomInfos[dataZoomId]) { + delete dataZoomInfos[dataZoomId]; + record.count--; + } + }); + + cleanStore(store); +} + +/** + * @public + */ +function generateCoordId(coordModel) { + return coordModel.type + '\0_' + coordModel.id; +} + +/** + * Key: coordId, value: {dataZoomInfos: [], count, controller} + * @type {Array.} + */ +function giveStore(api) { + // Mount store on zrender instance, so that we do not + // need to worry about dispose. + var zr = api.getZr(); + return zr[ATTR$1] || (zr[ATTR$1] = {}); +} + +function createController(api, newRecord) { + var controller = new RoamController(api.getZr()); + + each$1(['pan', 'zoom', 'scrollMove'], function (eventName) { + controller.on(eventName, function (event) { + var batch = []; + + each$1(newRecord.dataZoomInfos, function (info) { + // Check whether the behaviors (zoomOnMouseWheel, moveOnMouseMove, + // moveOnMouseWheel, ...) enabled. + if (!event.isAvailableBehavior(info.dataZoomModel.option)) { + return; + } + + var method = (info.getRange || {})[eventName]; + var range = method && method(newRecord.controller, event); + + !info.dataZoomModel.get('disabled', true) && range && batch.push({ + dataZoomId: info.dataZoomId, + start: range[0], + end: range[1] + }); + }); + + batch.length && newRecord.dispatchAction(batch); + }); + }); + + return controller; +} + +function cleanStore(store) { + each$1(store, function (record, coordId) { + if (!record.count) { + record.controller.dispose(); + delete store[coordId]; + } + }); +} + +/** + * This action will be throttled. + */ +function dispatchAction$1(api, batch) { + api.dispatchAction({ + type: 'dataZoom', + batch: batch + }); +} + +/** + * Merge roamController settings when multiple dataZooms share one roamController. + */ +function mergeControllerParams(dataZoomInfos) { + var controlType; + // DO NOT use reserved word (true, false, undefined) as key literally. Even if encapsulated + // as string, it is probably revert to reserved word by compress tool. See #7411. + var prefix = 'type_'; + var typePriority = { + 'type_true': 2, + 'type_move': 1, + 'type_false': 0, + 'type_undefined': -1 + }; + var preventDefaultMouseMove = true; + + each$1(dataZoomInfos, function (dataZoomInfo) { + var dataZoomModel = dataZoomInfo.dataZoomModel; + var oneType = dataZoomModel.get('disabled', true) + ? false + : dataZoomModel.get('zoomLock', true) + ? 'move' + : true; + if (typePriority[prefix + oneType] > typePriority[prefix + controlType]) { + controlType = oneType; + } + + // Prevent default move event by default. If one false, do not prevent. Otherwise + // users may be confused why it does not work when multiple insideZooms exist. + preventDefaultMouseMove &= dataZoomModel.get('preventDefaultMouseMove', true); + }); + + return { + controlType: controlType, + opt: { + // RoamController will enable all of these functionalities, + // and the final behavior is determined by its event listener + // provided by each inside zoom. + zoomOnMouseWheel: true, + moveOnMouseMove: true, + moveOnMouseWheel: true, + preventDefaultMouseMove: !!preventDefaultMouseMove + } + }; +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var bind$5 = bind; + +var InsideZoomView = DataZoomView.extend({ + + type: 'dataZoom.inside', + + /** + * @override + */ + init: function (ecModel, api) { + /** + * 'throttle' is used in this.dispatchAction, so we save range + * to avoid missing some 'pan' info. + * @private + * @type {Array.} + */ + this._range; + }, + + /** + * @override + */ + render: function (dataZoomModel, ecModel, api, payload) { + InsideZoomView.superApply(this, 'render', arguments); + + // Hance the `throttle` util ensures to preserve command order, + // here simply updating range all the time will not cause missing + // any of the the roam change. + this._range = dataZoomModel.getPercentRange(); + + // Reset controllers. + each$1(this.getTargetCoordInfo(), function (coordInfoList, coordSysName) { + + var allCoordIds = map(coordInfoList, function (coordInfo) { + return generateCoordId(coordInfo.model); + }); + + each$1(coordInfoList, function (coordInfo) { + var coordModel = coordInfo.model; + + var getRange = {}; + each$1(['pan', 'zoom', 'scrollMove'], function (eventName) { + getRange[eventName] = bind$5(roamHandlers[eventName], this, coordInfo, coordSysName); + }, this); + + register$2( + api, + { + coordId: generateCoordId(coordModel), + allCoordIds: allCoordIds, + containsPoint: function (e, x, y) { + return coordModel.coordinateSystem.containPoint([x, y]); + }, + dataZoomId: dataZoomModel.id, + dataZoomModel: dataZoomModel, + getRange: getRange + } + ); + }, this); + + }, this); + }, + + /** + * @override + */ + dispose: function () { + unregister$1(this.api, this.dataZoomModel.id); + InsideZoomView.superApply(this, 'dispose', arguments); + this._range = null; + } + +}); + +var roamHandlers = { + + /** + * @this {module:echarts/component/dataZoom/InsideZoomView} + */ + zoom: function (coordInfo, coordSysName, controller, e) { + var lastRange = this._range; + var range = lastRange.slice(); + + // Calculate transform by the first axis. + var axisModel = coordInfo.axisModels[0]; + if (!axisModel) { + return; + } + + var directionInfo = getDirectionInfo[coordSysName]( + null, [e.originX, e.originY], axisModel, controller, coordInfo + ); + var percentPoint = ( + directionInfo.signal > 0 + ? (directionInfo.pixelStart + directionInfo.pixelLength - directionInfo.pixel) + : (directionInfo.pixel - directionInfo.pixelStart) + ) / directionInfo.pixelLength * (range[1] - range[0]) + range[0]; + + var scale = Math.max(1 / e.scale, 0); + range[0] = (range[0] - percentPoint) * scale + percentPoint; + range[1] = (range[1] - percentPoint) * scale + percentPoint; + + // Restrict range. + var minMaxSpan = this.dataZoomModel.findRepresentativeAxisProxy().getMinMaxSpan(); + + sliderMove(0, range, [0, 100], 0, minMaxSpan.minSpan, minMaxSpan.maxSpan); + + this._range = range; + + if (lastRange[0] !== range[0] || lastRange[1] !== range[1]) { + return range; + } + }, + + /** + * @this {module:echarts/component/dataZoom/InsideZoomView} + */ + pan: makeMover(function (range, axisModel, coordInfo, coordSysName, controller, e) { + var directionInfo = getDirectionInfo[coordSysName]( + [e.oldX, e.oldY], [e.newX, e.newY], axisModel, controller, coordInfo + ); + + return directionInfo.signal + * (range[1] - range[0]) + * directionInfo.pixel / directionInfo.pixelLength; + }), + + /** + * @this {module:echarts/component/dataZoom/InsideZoomView} + */ + scrollMove: makeMover(function (range, axisModel, coordInfo, coordSysName, controller, e) { + var directionInfo = getDirectionInfo[coordSysName]( + [0, 0], [e.scrollDelta, e.scrollDelta], axisModel, controller, coordInfo + ); + return directionInfo.signal * (range[1] - range[0]) * e.scrollDelta; + }) +}; + +function makeMover(getPercentDelta) { + return function (coordInfo, coordSysName, controller, e) { + var lastRange = this._range; + var range = lastRange.slice(); + + // Calculate transform by the first axis. + var axisModel = coordInfo.axisModels[0]; + if (!axisModel) { + return; + } + + var percentDelta = getPercentDelta( + range, axisModel, coordInfo, coordSysName, controller, e + ); + + sliderMove(percentDelta, range, [0, 100], 'all'); + + this._range = range; + + if (lastRange[0] !== range[0] || lastRange[1] !== range[1]) { + return range; + } + }; +} + +var getDirectionInfo = { + + grid: function (oldPoint, newPoint, axisModel, controller, coordInfo) { + var axis = axisModel.axis; + var ret = {}; + var rect = coordInfo.model.coordinateSystem.getRect(); + oldPoint = oldPoint || [0, 0]; + + if (axis.dim === 'x') { + ret.pixel = newPoint[0] - oldPoint[0]; + ret.pixelLength = rect.width; + ret.pixelStart = rect.x; + ret.signal = axis.inverse ? 1 : -1; + } + else { // axis.dim === 'y' + ret.pixel = newPoint[1] - oldPoint[1]; + ret.pixelLength = rect.height; + ret.pixelStart = rect.y; + ret.signal = axis.inverse ? -1 : 1; + } + + return ret; + }, + + polar: function (oldPoint, newPoint, axisModel, controller, coordInfo) { + var axis = axisModel.axis; + var ret = {}; + var polar = coordInfo.model.coordinateSystem; + var radiusExtent = polar.getRadiusAxis().getExtent(); + var angleExtent = polar.getAngleAxis().getExtent(); + + oldPoint = oldPoint ? polar.pointToCoord(oldPoint) : [0, 0]; + newPoint = polar.pointToCoord(newPoint); + + if (axisModel.mainType === 'radiusAxis') { + ret.pixel = newPoint[0] - oldPoint[0]; + // ret.pixelLength = Math.abs(radiusExtent[1] - radiusExtent[0]); + // ret.pixelStart = Math.min(radiusExtent[0], radiusExtent[1]); + ret.pixelLength = radiusExtent[1] - radiusExtent[0]; + ret.pixelStart = radiusExtent[0]; + ret.signal = axis.inverse ? 1 : -1; + } + else { // 'angleAxis' + ret.pixel = newPoint[1] - oldPoint[1]; + // ret.pixelLength = Math.abs(angleExtent[1] - angleExtent[0]); + // ret.pixelStart = Math.min(angleExtent[0], angleExtent[1]); + ret.pixelLength = angleExtent[1] - angleExtent[0]; + ret.pixelStart = angleExtent[0]; + ret.signal = axis.inverse ? -1 : 1; + } + + return ret; + }, + + singleAxis: function (oldPoint, newPoint, axisModel, controller, coordInfo) { + var axis = axisModel.axis; + var rect = coordInfo.model.coordinateSystem.getRect(); + var ret = {}; + + oldPoint = oldPoint || [0, 0]; + + if (axis.orient === 'horizontal') { + ret.pixel = newPoint[0] - oldPoint[0]; + ret.pixelLength = rect.width; + ret.pixelStart = rect.x; + ret.signal = axis.inverse ? 1 : -1; + } + else { // 'vertical' + ret.pixel = newPoint[1] - oldPoint[1]; + ret.pixelLength = rect.height; + ret.pixelStart = rect.y; + ret.signal = axis.inverse ? -1 : 1; + } + + return ret; + } +}; + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +registerProcessor({ + + // `dataZoomProcessor` will only be performed in needed series. Consider if + // there is a line series and a pie series, it is better not to update the + // line series if only pie series is needed to be updated. + getTargetSeries: function (ecModel) { + var seriesModelMap = createHashMap(); + + ecModel.eachComponent('dataZoom', function (dataZoomModel) { + dataZoomModel.eachTargetAxis(function (dimNames, axisIndex, dataZoomModel) { + var axisProxy = dataZoomModel.getAxisProxy(dimNames.name, axisIndex); + each$1(axisProxy.getTargetSeriesModels(), function (seriesModel) { + seriesModelMap.set(seriesModel.uid, seriesModel); + }); + }); + }); + + return seriesModelMap; + }, + + modifyOutputEnd: true, + + // Consider appendData, where filter should be performed. Because data process is + // in block mode currently, it is not need to worry about that the overallProgress + // execute every frame. + overallReset: function (ecModel, api) { + + ecModel.eachComponent('dataZoom', function (dataZoomModel) { + // We calculate window and reset axis here but not in model + // init stage and not after action dispatch handler, because + // reset should be called after seriesData.restoreData. + dataZoomModel.eachTargetAxis(function (dimNames, axisIndex, dataZoomModel) { + dataZoomModel.getAxisProxy(dimNames.name, axisIndex).reset(dataZoomModel, api); + }); + + // Caution: data zoom filtering is order sensitive when using + // percent range and no min/max/scale set on axis. + // For example, we have dataZoom definition: + // [ + // {xAxisIndex: 0, start: 30, end: 70}, + // {yAxisIndex: 0, start: 20, end: 80} + // ] + // In this case, [20, 80] of y-dataZoom should be based on data + // that have filtered by x-dataZoom using range of [30, 70], + // but should not be based on full raw data. Thus sliding + // x-dataZoom will change both ranges of xAxis and yAxis, + // while sliding y-dataZoom will only change the range of yAxis. + // So we should filter x-axis after reset x-axis immediately, + // and then reset y-axis and filter y-axis. + dataZoomModel.eachTargetAxis(function (dimNames, axisIndex, dataZoomModel) { + dataZoomModel.getAxisProxy(dimNames.name, axisIndex).filterData(dataZoomModel, api); + }); + }); + + ecModel.eachComponent('dataZoom', function (dataZoomModel) { + // Fullfill all of the range props so that user + // is able to get them from chart.getOption(). + var axisProxy = dataZoomModel.findRepresentativeAxisProxy(); + var percentRange = axisProxy.getDataPercentWindow(); + var valueRange = axisProxy.getDataValueWindow(); + + dataZoomModel.setRawRange({ + start: percentRange[0], + end: percentRange[1], + startValue: valueRange[0], + endValue: valueRange[1] + }, true); + }); + } +}); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +registerAction('dataZoom', function (payload, ecModel) { + + var linkedNodesFinder = createLinkedNodesFinder( + bind(ecModel.eachComponent, ecModel, 'dataZoom'), + eachAxisDim$1, + function (model, dimNames) { + return model.get(dimNames.axisIndex); + } + ); + + var effectedModels = []; + + ecModel.eachComponent( + {mainType: 'dataZoom', query: payload}, + function (model, index) { + effectedModels.push.apply( + effectedModels, linkedNodesFinder(model).nodes + ); + } + ); + + each$1(effectedModels, function (dataZoomModel, index) { + dataZoomModel.setRawRange({ + start: payload.start, + end: payload.end, + startValue: payload.startValue, + endValue: payload.endValue + }); + }); + +}); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/** + * DataZoom component entry + */ + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var each$24 = each$1; + +var preprocessor$2 = function (option) { + var visualMap = option && option.visualMap; + + if (!isArray(visualMap)) { + visualMap = visualMap ? [visualMap] : []; + } + + each$24(visualMap, function (opt) { + if (!opt) { + return; + } + + // rename splitList to pieces + if (has$1(opt, 'splitList') && !has$1(opt, 'pieces')) { + opt.pieces = opt.splitList; + delete opt.splitList; + } + + var pieces = opt.pieces; + if (pieces && isArray(pieces)) { + each$24(pieces, function (piece) { + if (isObject$1(piece)) { + if (has$1(piece, 'start') && !has$1(piece, 'min')) { + piece.min = piece.start; + } + if (has$1(piece, 'end') && !has$1(piece, 'max')) { + piece.max = piece.end; + } + } + }); + } + }); +}; + +function has$1(obj, name) { + return obj && obj.hasOwnProperty && obj.hasOwnProperty(name); +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +ComponentModel.registerSubTypeDefaulter('visualMap', function (option) { + // Compatible with ec2, when splitNumber === 0, continuous visualMap will be used. + return ( + !option.categories + && ( + !( + option.pieces + ? option.pieces.length > 0 + : option.splitNumber > 0 + ) + || option.calculable + ) + ) + ? 'continuous' : 'piecewise'; +}); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var VISUAL_PRIORITY = PRIORITY.VISUAL.COMPONENT; + +registerVisual(VISUAL_PRIORITY, { + createOnAllSeries: true, + reset: function (seriesModel, ecModel) { + var resetDefines = []; + ecModel.eachComponent('visualMap', function (visualMapModel) { + var pipelineContext = seriesModel.pipelineContext; + if (!visualMapModel.isTargetSeries(seriesModel) + || (pipelineContext && pipelineContext.large) + ) { + return; + } + + resetDefines.push(incrementalApplyVisual( + visualMapModel.stateList, + visualMapModel.targetVisuals, + bind(visualMapModel.getValueState, visualMapModel), + visualMapModel.getDataDimension(seriesModel.getData()) + )); + }); + + return resetDefines; + } +}); + +// Only support color. +registerVisual(VISUAL_PRIORITY, { + createOnAllSeries: true, + reset: function (seriesModel, ecModel) { + var data = seriesModel.getData(); + var visualMetaList = []; + + ecModel.eachComponent('visualMap', function (visualMapModel) { + if (visualMapModel.isTargetSeries(seriesModel)) { + var visualMeta = visualMapModel.getVisualMeta( + bind(getColorVisual, null, seriesModel, visualMapModel) + ) || {stops: [], outerColors: []}; + + var concreteDim = visualMapModel.getDataDimension(data); + var dimInfo = data.getDimensionInfo(concreteDim); + if (dimInfo != null) { + // visualMeta.dimension should be dimension index, but not concrete dimension. + visualMeta.dimension = dimInfo.index; + visualMetaList.push(visualMeta); + } + } + }); + + // console.log(JSON.stringify(visualMetaList.map(a => a.stops))); + seriesModel.getData().setVisual('visualMeta', visualMetaList); + } +}); + +// FIXME +// performance and export for heatmap? +// value can be Infinity or -Infinity +function getColorVisual(seriesModel, visualMapModel, value, valueState) { + var mappings = visualMapModel.targetVisuals[valueState]; + var visualTypes = VisualMapping.prepareVisualTypes(mappings); + var resultVisual = { + color: seriesModel.getData().getVisual('color') // default color. + }; + + for (var i = 0, len = visualTypes.length; i < len; i++) { + var type = visualTypes[i]; + var mapping = mappings[ + type === 'opacity' ? '__alphaForOpacity' : type + ]; + mapping && mapping.applyVisual(value, getVisual, setVisual); + } + + return resultVisual.color; + + function getVisual(key) { + return resultVisual[key]; + } + + function setVisual(key, value) { + resultVisual[key] = value; + } +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/** + * @file Visual mapping. + */ + +var visualDefault = { + + /** + * @public + */ + get: function (visualType, key, isCategory) { + var value = clone( + (defaultOption$3[visualType] || {})[key] + ); + + return isCategory + ? (isArray(value) ? value[value.length - 1] : value) + : value; + } + +}; + +var defaultOption$3 = { + + color: { + active: ['#006edd', '#e0ffff'], + inactive: ['rgba(0,0,0,0)'] + }, + + colorHue: { + active: [0, 360], + inactive: [0, 0] + }, + + colorSaturation: { + active: [0.3, 1], + inactive: [0, 0] + }, + + colorLightness: { + active: [0.9, 0.5], + inactive: [0, 0] + }, + + colorAlpha: { + active: [0.3, 1], + inactive: [0, 0] + }, + + opacity: { + active: [0.3, 1], + inactive: [0, 0] + }, + + symbol: { + active: ['circle', 'roundRect', 'diamond'], + inactive: ['none'] + }, + + symbolSize: { + active: [10, 50], + inactive: [0, 0] + } +}; + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var mapVisual$2 = VisualMapping.mapVisual; +var eachVisual = VisualMapping.eachVisual; +var isArray$3 = isArray; +var each$25 = each$1; +var asc$3 = asc; +var linearMap$2 = linearMap; +var noop$2 = noop; + +var VisualMapModel = extendComponentModel({ + + type: 'visualMap', + + dependencies: ['series'], + + /** + * @readOnly + * @type {Array.} + */ + stateList: ['inRange', 'outOfRange'], + + /** + * @readOnly + * @type {Array.} + */ + replacableOptionKeys: [ + 'inRange', 'outOfRange', 'target', 'controller', 'color' + ], + + /** + * [lowerBound, upperBound] + * + * @readOnly + * @type {Array.} + */ + dataBound: [-Infinity, Infinity], + + /** + * @readOnly + * @type {string|Object} + */ + layoutMode: {type: 'box', ignoreSize: true}, + + /** + * @protected + */ + defaultOption: { + show: true, + + zlevel: 0, + z: 4, + + seriesIndex: 'all', // 'all' or null/undefined: all series. + // A number or an array of number: the specified series. + + // set min: 0, max: 200, only for campatible with ec2. + // In fact min max should not have default value. + min: 0, // min value, must specified if pieces is not specified. + max: 200, // max value, must specified if pieces is not specified. + + dimension: null, + inRange: null, // 'color', 'colorHue', 'colorSaturation', 'colorLightness', 'colorAlpha', + // 'symbol', 'symbolSize' + outOfRange: null, // 'color', 'colorHue', 'colorSaturation', + // 'colorLightness', 'colorAlpha', + // 'symbol', 'symbolSize' + + left: 0, // 'center' ¦ 'left' ¦ 'right' ¦ {number} (px) + right: null, // The same as left. + top: null, // 'top' ¦ 'bottom' ¦ 'center' ¦ {number} (px) + bottom: 0, // The same as top. + + itemWidth: null, + itemHeight: null, + inverse: false, + orient: 'vertical', // 'horizontal' ¦ 'vertical' + + backgroundColor: 'rgba(0,0,0,0)', + borderColor: '#ccc', // 值域边框颜色 + contentColor: '#5793f3', + inactiveColor: '#aaa', + borderWidth: 0, // 值域边框线宽,单位px,默认为0(无边框) + padding: 5, // 值域内边距,单位px,默认各方向内边距为5, + // 接受数组分别设定上右下左边距,同css + textGap: 10, // + precision: 0, // 小数精度,默认为0,无小数点 + color: null, //颜色(deprecated,兼容ec2,顺序同pieces,不同于inRange/outOfRange) + + formatter: null, + text: null, // 文本,如['高', '低'],兼容ec2,text[0]对应高值,text[1]对应低值 + textStyle: { + color: '#333' // 值域文字颜色 + } + }, + + /** + * @protected + */ + init: function (option, parentModel, ecModel) { + + /** + * @private + * @type {Array.} + */ + this._dataExtent; + + /** + * @readOnly + */ + this.targetVisuals = {}; + + /** + * @readOnly + */ + this.controllerVisuals = {}; + + /** + * @readOnly + */ + this.textStyleModel; + + /** + * [width, height] + * @readOnly + * @type {Array.} + */ + this.itemSize; + + this.mergeDefaultAndTheme(option, ecModel); + }, + + /** + * @protected + */ + optionUpdated: function (newOption, isInit) { + var thisOption = this.option; + + // FIXME + // necessary? + // Disable realtime view update if canvas is not supported. + if (!env$1.canvasSupported) { + thisOption.realtime = false; + } + + !isInit && replaceVisualOption( + thisOption, newOption, this.replacableOptionKeys + ); + + this.textStyleModel = this.getModel('textStyle'); + + this.resetItemSize(); + + this.completeVisualOption(); + }, + + /** + * @protected + */ + resetVisual: function (supplementVisualOption) { + var stateList = this.stateList; + supplementVisualOption = bind(supplementVisualOption, this); + + this.controllerVisuals = createVisualMappings( + this.option.controller, stateList, supplementVisualOption + ); + this.targetVisuals = createVisualMappings( + this.option.target, stateList, supplementVisualOption + ); + }, + + /** + * @protected + * @return {Array.} An array of series indices. + */ + getTargetSeriesIndices: function () { + var optionSeriesIndex = this.option.seriesIndex; + var seriesIndices = []; + + if (optionSeriesIndex == null || optionSeriesIndex === 'all') { + this.ecModel.eachSeries(function (seriesModel, index) { + seriesIndices.push(index); + }); + } + else { + seriesIndices = normalizeToArray(optionSeriesIndex); + } + + return seriesIndices; + }, + + /** + * @public + */ + eachTargetSeries: function (callback, context) { + each$1(this.getTargetSeriesIndices(), function (seriesIndex) { + callback.call(context, this.ecModel.getSeriesByIndex(seriesIndex)); + }, this); + }, + + /** + * @pubilc + */ + isTargetSeries: function (seriesModel) { + var is = false; + this.eachTargetSeries(function (model) { + model === seriesModel && (is = true); + }); + return is; + }, + + /** + * @example + * this.formatValueText(someVal); // format single numeric value to text. + * this.formatValueText(someVal, true); // format single category value to text. + * this.formatValueText([min, max]); // format numeric min-max to text. + * this.formatValueText([this.dataBound[0], max]); // using data lower bound. + * this.formatValueText([min, this.dataBound[1]]); // using data upper bound. + * + * @param {number|Array.} value Real value, or this.dataBound[0 or 1]. + * @param {boolean} [isCategory=false] Only available when value is number. + * @param {Array.} edgeSymbols Open-close symbol when value is interval. + * @return {string} + * @protected + */ + formatValueText: function (value, isCategory, edgeSymbols) { + var option = this.option; + var precision = option.precision; + var dataBound = this.dataBound; + var formatter = option.formatter; + var isMinMax; + var textValue; + edgeSymbols = edgeSymbols || ['<', '>']; + + if (isArray(value)) { + value = value.slice(); + isMinMax = true; + } + + textValue = isCategory + ? value + : (isMinMax + ? [toFixed(value[0]), toFixed(value[1])] + : toFixed(value) + ); + + if (isString(formatter)) { + return formatter + .replace('{value}', isMinMax ? textValue[0] : textValue) + .replace('{value2}', isMinMax ? textValue[1] : textValue); + } + else if (isFunction$1(formatter)) { + return isMinMax + ? formatter(value[0], value[1]) + : formatter(value); + } + + if (isMinMax) { + if (value[0] === dataBound[0]) { + return edgeSymbols[0] + ' ' + textValue[1]; + } + else if (value[1] === dataBound[1]) { + return edgeSymbols[1] + ' ' + textValue[0]; + } + else { + return textValue[0] + ' - ' + textValue[1]; + } + } + else { // Format single value (includes category case). + return textValue; + } + + function toFixed(val) { + return val === dataBound[0] + ? 'min' + : val === dataBound[1] + ? 'max' + : (+val).toFixed(Math.min(precision, 20)); + } + }, + + /** + * @protected + */ + resetExtent: function () { + var thisOption = this.option; + + // Can not calculate data extent by data here. + // Because series and data may be modified in processing stage. + // So we do not support the feature "auto min/max". + + var extent = asc$3([thisOption.min, thisOption.max]); + + this._dataExtent = extent; + }, + + /** + * @public + * @param {module:echarts/data/List} list + * @return {string} Concrete dimention. If return null/undefined, + * no dimension used. + */ + getDataDimension: function (list) { + var optDim = this.option.dimension; + var listDimensions = list.dimensions; + if (optDim == null && !listDimensions.length) { + return; + } + + if (optDim != null) { + return list.getDimension(optDim); + } + + var dimNames = list.dimensions; + for (var i = dimNames.length - 1; i >= 0; i--) { + var dimName = dimNames[i]; + var dimInfo = list.getDimensionInfo(dimName); + if (!dimInfo.isCalculationCoord) { + return dimName; + } + } + }, + + /** + * @public + * @override + */ + getExtent: function () { + return this._dataExtent.slice(); + }, + + /** + * @protected + */ + completeVisualOption: function () { + var ecModel = this.ecModel; + var thisOption = this.option; + var base = {inRange: thisOption.inRange, outOfRange: thisOption.outOfRange}; + + var target = thisOption.target || (thisOption.target = {}); + var controller = thisOption.controller || (thisOption.controller = {}); + + merge(target, base); // Do not override + merge(controller, base); // Do not override + + var isCategory = this.isCategory(); + + completeSingle.call(this, target); + completeSingle.call(this, controller); + completeInactive.call(this, target, 'inRange', 'outOfRange'); + // completeInactive.call(this, target, 'outOfRange', 'inRange'); + completeController.call(this, controller); + + function completeSingle(base) { + // Compatible with ec2 dataRange.color. + // The mapping order of dataRange.color is: [high value, ..., low value] + // whereas inRange.color and outOfRange.color is [low value, ..., high value] + // Notice: ec2 has no inverse. + if (isArray$3(thisOption.color) + // If there has been inRange: {symbol: ...}, adding color is a mistake. + // So adding color only when no inRange defined. + && !base.inRange + ) { + base.inRange = {color: thisOption.color.slice().reverse()}; + } + + // Compatible with previous logic, always give a defautl color, otherwise + // simple config with no inRange and outOfRange will not work. + // Originally we use visualMap.color as the default color, but setOption at + // the second time the default color will be erased. So we change to use + // constant DEFAULT_COLOR. + // If user do not want the defualt color, set inRange: {color: null}. + base.inRange = base.inRange || {color: ecModel.get('gradientColor')}; + + // If using shortcut like: {inRange: 'symbol'}, complete default value. + each$25(this.stateList, function (state) { + var visualType = base[state]; + + if (isString(visualType)) { + var defa = visualDefault.get(visualType, 'active', isCategory); + if (defa) { + base[state] = {}; + base[state][visualType] = defa; + } + else { + // Mark as not specified. + delete base[state]; + } + } + }, this); + } + + function completeInactive(base, stateExist, stateAbsent) { + var optExist = base[stateExist]; + var optAbsent = base[stateAbsent]; + + if (optExist && !optAbsent) { + optAbsent = base[stateAbsent] = {}; + each$25(optExist, function (visualData, visualType) { + if (!VisualMapping.isValidType(visualType)) { + return; + } + + var defa = visualDefault.get(visualType, 'inactive', isCategory); + + if (defa != null) { + optAbsent[visualType] = defa; + + // Compatibable with ec2: + // Only inactive color to rgba(0,0,0,0) can not + // make label transparent, so use opacity also. + if (visualType === 'color' + && !optAbsent.hasOwnProperty('opacity') + && !optAbsent.hasOwnProperty('colorAlpha') + ) { + optAbsent.opacity = [0, 0]; + } + } + }); + } + } + + function completeController(controller) { + var symbolExists = (controller.inRange || {}).symbol + || (controller.outOfRange || {}).symbol; + var symbolSizeExists = (controller.inRange || {}).symbolSize + || (controller.outOfRange || {}).symbolSize; + var inactiveColor = this.get('inactiveColor'); + + each$25(this.stateList, function (state) { + + var itemSize = this.itemSize; + var visuals = controller[state]; + + // Set inactive color for controller if no other color + // attr (like colorAlpha) specified. + if (!visuals) { + visuals = controller[state] = { + color: isCategory ? inactiveColor : [inactiveColor] + }; + } + + // Consistent symbol and symbolSize if not specified. + if (visuals.symbol == null) { + visuals.symbol = symbolExists + && clone(symbolExists) + || (isCategory ? 'roundRect' : ['roundRect']); + } + if (visuals.symbolSize == null) { + visuals.symbolSize = symbolSizeExists + && clone(symbolSizeExists) + || (isCategory ? itemSize[0] : [itemSize[0], itemSize[0]]); + } + + // Filter square and none. + visuals.symbol = mapVisual$2(visuals.symbol, function (symbol) { + return (symbol === 'none' || symbol === 'square') ? 'roundRect' : symbol; + }); + + // Normalize symbolSize + var symbolSize = visuals.symbolSize; + + if (symbolSize != null) { + var max = -Infinity; + // symbolSize can be object when categories defined. + eachVisual(symbolSize, function (value) { + value > max && (max = value); + }); + visuals.symbolSize = mapVisual$2(symbolSize, function (value) { + return linearMap$2(value, [0, max], [0, itemSize[0]], true); + }); + } + + }, this); + } + }, + + /** + * @protected + */ + resetItemSize: function () { + this.itemSize = [ + parseFloat(this.get('itemWidth')), + parseFloat(this.get('itemHeight')) + ]; + }, + + /** + * @public + */ + isCategory: function () { + return !!this.option.categories; + }, + + /** + * @public + * @abstract + */ + setSelected: noop$2, + + /** + * @public + * @abstract + * @param {*|module:echarts/data/List} valueOrData + * @param {number} dataIndex + * @return {string} state See this.stateList + */ + getValueState: noop$2, + + /** + * FIXME + * Do not publish to thirt-part-dev temporarily + * util the interface is stable. (Should it return + * a function but not visual meta?) + * + * @pubilc + * @abstract + * @param {Function} getColorVisual + * params: value, valueState + * return: color + * @return {Object} visualMeta + * should includes {stops, outerColors} + * outerColor means [colorBeyondMinValue, colorBeyondMaxValue] + */ + getVisualMeta: noop$2 + +}); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +// Constant +var DEFAULT_BAR_BOUND = [20, 140]; + +var ContinuousModel = VisualMapModel.extend({ + + type: 'visualMap.continuous', + + /** + * @protected + */ + defaultOption: { + align: 'auto', // 'auto', 'left', 'right', 'top', 'bottom' + calculable: false, // This prop effect default component type determine, + // See echarts/component/visualMap/typeDefaulter. + range: null, // selected range. In default case `range` is [min, max] + // and can auto change along with modification of min max, + // util use specifid a range. + realtime: true, // Whether realtime update. + itemHeight: null, // The length of the range control edge. + itemWidth: null, // The length of the other side. + hoverLink: true, // Enable hover highlight. + hoverLinkDataSize: null, // The size of hovered data. + hoverLinkOnHandle: null // Whether trigger hoverLink when hover handle. + // If not specified, follow the value of `realtime`. + }, + + /** + * @override + */ + optionUpdated: function (newOption, isInit) { + ContinuousModel.superApply(this, 'optionUpdated', arguments); + + this.resetExtent(); + + this.resetVisual(function (mappingOption) { + mappingOption.mappingMethod = 'linear'; + mappingOption.dataExtent = this.getExtent(); + }); + + this._resetRange(); + }, + + /** + * @protected + * @override + */ + resetItemSize: function () { + ContinuousModel.superApply(this, 'resetItemSize', arguments); + + var itemSize = this.itemSize; + + this._orient === 'horizontal' && itemSize.reverse(); + + (itemSize[0] == null || isNaN(itemSize[0])) && (itemSize[0] = DEFAULT_BAR_BOUND[0]); + (itemSize[1] == null || isNaN(itemSize[1])) && (itemSize[1] = DEFAULT_BAR_BOUND[1]); + }, + + /** + * @private + */ + _resetRange: function () { + var dataExtent = this.getExtent(); + var range = this.option.range; + + if (!range || range.auto) { + // `range` should always be array (so we dont use other + // value like 'auto') for user-friend. (consider getOption). + dataExtent.auto = 1; + this.option.range = dataExtent; + } + else if (isArray(range)) { + if (range[0] > range[1]) { + range.reverse(); + } + range[0] = Math.max(range[0], dataExtent[0]); + range[1] = Math.min(range[1], dataExtent[1]); + } + }, + + /** + * @protected + * @override + */ + completeVisualOption: function () { + VisualMapModel.prototype.completeVisualOption.apply(this, arguments); + + each$1(this.stateList, function (state) { + var symbolSize = this.option.controller[state].symbolSize; + if (symbolSize && symbolSize[0] !== symbolSize[1]) { + symbolSize[0] = 0; // For good looking. + } + }, this); + }, + + /** + * @override + */ + setSelected: function (selected) { + this.option.range = selected.slice(); + this._resetRange(); + }, + + /** + * @public + */ + getSelected: function () { + var dataExtent = this.getExtent(); + + var dataInterval = asc( + (this.get('range') || []).slice() + ); + + // Clamp + dataInterval[0] > dataExtent[1] && (dataInterval[0] = dataExtent[1]); + dataInterval[1] > dataExtent[1] && (dataInterval[1] = dataExtent[1]); + dataInterval[0] < dataExtent[0] && (dataInterval[0] = dataExtent[0]); + dataInterval[1] < dataExtent[0] && (dataInterval[1] = dataExtent[0]); + + return dataInterval; + }, + + /** + * @override + */ + getValueState: function (value) { + var range = this.option.range; + var dataExtent = this.getExtent(); + + // When range[0] === dataExtent[0], any value larger than dataExtent[0] maps to 'inRange'. + // range[1] is processed likewise. + return ( + (range[0] <= dataExtent[0] || range[0] <= value) + && (range[1] >= dataExtent[1] || value <= range[1]) + ) ? 'inRange' : 'outOfRange'; + }, + + /** + * @params {Array.} range target value: range[0] <= value && value <= range[1] + * @return {Array.} [{seriesId, dataIndices: >}, ...] + */ + findTargetDataIndices: function (range) { + var result = []; + + this.eachTargetSeries(function (seriesModel) { + var dataIndices = []; + var data = seriesModel.getData(); + + data.each(this.getDataDimension(data), function (value, dataIndex) { + range[0] <= value && value <= range[1] && dataIndices.push(dataIndex); + }, this); + + result.push({seriesId: seriesModel.id, dataIndex: dataIndices}); + }, this); + + return result; + }, + + /** + * @implement + */ + getVisualMeta: function (getColorVisual) { + var oVals = getColorStopValues(this, 'outOfRange', this.getExtent()); + var iVals = getColorStopValues(this, 'inRange', this.option.range.slice()); + var stops = []; + + function setStop(value, valueState) { + stops.push({ + value: value, + color: getColorVisual(value, valueState) + }); + } + + // Format to: outOfRange -- inRange -- outOfRange. + var iIdx = 0; + var oIdx = 0; + var iLen = iVals.length; + var oLen = oVals.length; + + for (; oIdx < oLen && (!iVals.length || oVals[oIdx] <= iVals[0]); oIdx++) { + // If oVal[oIdx] === iVals[iIdx], oVal[oIdx] should be ignored. + if (oVals[oIdx] < iVals[iIdx]) { + setStop(oVals[oIdx], 'outOfRange'); + } + } + for (var first = 1; iIdx < iLen; iIdx++, first = 0) { + // If range is full, value beyond min, max will be clamped. + // make a singularity + first && stops.length && setStop(iVals[iIdx], 'outOfRange'); + setStop(iVals[iIdx], 'inRange'); + } + for (var first = 1; oIdx < oLen; oIdx++) { + if (!iVals.length || iVals[iVals.length - 1] < oVals[oIdx]) { + // make a singularity + if (first) { + stops.length && setStop(stops[stops.length - 1].value, 'outOfRange'); + first = 0; + } + setStop(oVals[oIdx], 'outOfRange'); + } + } + + var stopsLen = stops.length; + + return { + stops: stops, + outerColors: [ + stopsLen ? stops[0].color : 'transparent', + stopsLen ? stops[stopsLen - 1].color : 'transparent' + ] + }; + } + +}); + +function getColorStopValues(visualMapModel, valueState, dataExtent) { + if (dataExtent[0] === dataExtent[1]) { + return dataExtent.slice(); + } + + // When using colorHue mapping, it is not linear color any more. + // Moreover, canvas gradient seems not to be accurate linear. + // FIXME + // Should be arbitrary value 100? or based on pixel size? + var count = 200; + var step = (dataExtent[1] - dataExtent[0]) / count; + + var value = dataExtent[0]; + var stopValues = []; + for (var i = 0; i <= count && value < dataExtent[1]; i++) { + stopValues.push(value); + value += step; + } + stopValues.push(dataExtent[1]); + + return stopValues; +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var VisualMapView = extendComponentView({ + + type: 'visualMap', + + /** + * @readOnly + * @type {Object} + */ + autoPositionValues: {left: 1, right: 1, top: 1, bottom: 1}, + + init: function (ecModel, api) { + /** + * @readOnly + * @type {module:echarts/model/Global} + */ + this.ecModel = ecModel; + + /** + * @readOnly + * @type {module:echarts/ExtensionAPI} + */ + this.api = api; + + /** + * @readOnly + * @type {module:echarts/component/visualMap/visualMapModel} + */ + this.visualMapModel; + }, + + /** + * @protected + */ + render: function (visualMapModel, ecModel, api, payload) { + this.visualMapModel = visualMapModel; + + if (visualMapModel.get('show') === false) { + this.group.removeAll(); + return; + } + + this.doRender.apply(this, arguments); + }, + + /** + * @protected + */ + renderBackground: function (group) { + var visualMapModel = this.visualMapModel; + var padding = normalizeCssArray$1(visualMapModel.get('padding') || 0); + var rect = group.getBoundingRect(); + + group.add(new Rect({ + z2: -1, // Lay background rect on the lowest layer. + silent: true, + shape: { + x: rect.x - padding[3], + y: rect.y - padding[0], + width: rect.width + padding[3] + padding[1], + height: rect.height + padding[0] + padding[2] + }, + style: { + fill: visualMapModel.get('backgroundColor'), + stroke: visualMapModel.get('borderColor'), + lineWidth: visualMapModel.get('borderWidth') + } + })); + }, + + /** + * @protected + * @param {number} targetValue can be Infinity or -Infinity + * @param {string=} visualCluster Only can be 'color' 'opacity' 'symbol' 'symbolSize' + * @param {Object} [opts] + * @param {string=} [opts.forceState] Specify state, instead of using getValueState method. + * @param {string=} [opts.convertOpacityToAlpha=false] For color gradient in controller widget. + * @return {*} Visual value. + */ + getControllerVisual: function (targetValue, visualCluster, opts) { + opts = opts || {}; + + var forceState = opts.forceState; + var visualMapModel = this.visualMapModel; + var visualObj = {}; + + // Default values. + if (visualCluster === 'symbol') { + visualObj.symbol = visualMapModel.get('itemSymbol'); + } + if (visualCluster === 'color') { + var defaultColor = visualMapModel.get('contentColor'); + visualObj.color = defaultColor; + } + + function getter(key) { + return visualObj[key]; + } + + function setter(key, value) { + visualObj[key] = value; + } + + var mappings = visualMapModel.controllerVisuals[ + forceState || visualMapModel.getValueState(targetValue) + ]; + var visualTypes = VisualMapping.prepareVisualTypes(mappings); + + each$1(visualTypes, function (type) { + var visualMapping = mappings[type]; + if (opts.convertOpacityToAlpha && type === 'opacity') { + type = 'colorAlpha'; + visualMapping = mappings.__alphaForOpacity; + } + if (VisualMapping.dependsOn(type, visualCluster)) { + visualMapping && visualMapping.applyVisual( + targetValue, getter, setter + ); + } + }); + + return visualObj[visualCluster]; + }, + + /** + * @protected + */ + positionGroup: function (group) { + var model = this.visualMapModel; + var api = this.api; + + positionElement( + group, + model.getBoxLayoutParams(), + {width: api.getWidth(), height: api.getHeight()} + ); + }, + + /** + * @protected + * @abstract + */ + doRender: noop + +}); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/** + * @param {module:echarts/component/visualMap/VisualMapModel} visualMapModel\ + * @param {module:echarts/ExtensionAPI} api + * @param {Array.} itemSize always [short, long] + * @return {string} 'left' or 'right' or 'top' or 'bottom' + */ +function getItemAlign(visualMapModel, api, itemSize) { + var modelOption = visualMapModel.option; + var itemAlign = modelOption.align; + + if (itemAlign != null && itemAlign !== 'auto') { + return itemAlign; + } + + // Auto decision align. + var ecSize = {width: api.getWidth(), height: api.getHeight()}; + var realIndex = modelOption.orient === 'horizontal' ? 1 : 0; + + var paramsSet = [ + ['left', 'right', 'width'], + ['top', 'bottom', 'height'] + ]; + var reals = paramsSet[realIndex]; + var fakeValue = [0, null, 10]; + + var layoutInput = {}; + for (var i = 0; i < 3; i++) { + layoutInput[paramsSet[1 - realIndex][i]] = fakeValue[i]; + layoutInput[reals[i]] = i === 2 ? itemSize[0] : modelOption[reals[i]]; + } + + var rParam = [['x', 'width', 3], ['y', 'height', 0]][realIndex]; + var rect = getLayoutRect(layoutInput, ecSize, modelOption.padding); + + return reals[ + (rect.margin[rParam[2]] || 0) + rect[rParam[0]] + rect[rParam[1]] * 0.5 + < ecSize[rParam[1]] * 0.5 ? 0 : 1 + ]; +} + +/** + * Prepare dataIndex for outside usage, where dataIndex means rawIndex, and + * dataIndexInside means filtered index. + */ +function convertDataIndex(batch) { + each$1(batch || [], function (batchItem) { + if (batch.dataIndex != null) { + batch.dataIndexInside = batch.dataIndex; + batch.dataIndex = null; + } + }); + return batch; +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var linearMap$3 = linearMap; +var each$26 = each$1; +var mathMin$7 = Math.min; +var mathMax$7 = Math.max; + +// Arbitrary value +var HOVER_LINK_SIZE = 12; +var HOVER_LINK_OUT = 6; + +// Notice: +// Any "interval" should be by the order of [low, high]. +// "handle0" (handleIndex === 0) maps to +// low data value: this._dataInterval[0] and has low coord. +// "handle1" (handleIndex === 1) maps to +// high data value: this._dataInterval[1] and has high coord. +// The logic of transform is implemented in this._createBarGroup. + +var ContinuousView = VisualMapView.extend({ + + type: 'visualMap.continuous', + + /** + * @override + */ + init: function () { + + ContinuousView.superApply(this, 'init', arguments); + + /** + * @private + */ + this._shapes = {}; + + /** + * @private + */ + this._dataInterval = []; + + /** + * @private + */ + this._handleEnds = []; + + /** + * @private + */ + this._orient; + + /** + * @private + */ + this._useHandle; + + /** + * @private + */ + this._hoverLinkDataIndices = []; + + /** + * @private + */ + this._dragging; + + /** + * @private + */ + this._hovering; + }, + + /** + * @protected + * @override + */ + doRender: function (visualMapModel, ecModel, api, payload) { + if (!payload || payload.type !== 'selectDataRange' || payload.from !== this.uid) { + this._buildView(); + } + }, + + /** + * @private + */ + _buildView: function () { + this.group.removeAll(); + + var visualMapModel = this.visualMapModel; + var thisGroup = this.group; + + this._orient = visualMapModel.get('orient'); + this._useHandle = visualMapModel.get('calculable'); + + this._resetInterval(); + + this._renderBar(thisGroup); + + var dataRangeText = visualMapModel.get('text'); + this._renderEndsText(thisGroup, dataRangeText, 0); + this._renderEndsText(thisGroup, dataRangeText, 1); + + // Do this for background size calculation. + this._updateView(true); + + // After updating view, inner shapes is built completely, + // and then background can be rendered. + this.renderBackground(thisGroup); + + // Real update view + this._updateView(); + + this._enableHoverLinkToSeries(); + this._enableHoverLinkFromSeries(); + + this.positionGroup(thisGroup); + }, + + /** + * @private + */ + _renderEndsText: function (group, dataRangeText, endsIndex) { + if (!dataRangeText) { + return; + } + + // Compatible with ec2, text[0] map to high value, text[1] map low value. + var text = dataRangeText[1 - endsIndex]; + text = text != null ? text + '' : ''; + + var visualMapModel = this.visualMapModel; + var textGap = visualMapModel.get('textGap'); + var itemSize = visualMapModel.itemSize; + + var barGroup = this._shapes.barGroup; + var position = this._applyTransform( + [ + itemSize[0] / 2, + endsIndex === 0 ? -textGap : itemSize[1] + textGap + ], + barGroup + ); + var align = this._applyTransform( + endsIndex === 0 ? 'bottom' : 'top', + barGroup + ); + var orient = this._orient; + var textStyleModel = this.visualMapModel.textStyleModel; + + this.group.add(new Text({ + style: { + x: position[0], + y: position[1], + textVerticalAlign: orient === 'horizontal' ? 'middle' : align, + textAlign: orient === 'horizontal' ? align : 'center', + text: text, + textFont: textStyleModel.getFont(), + textFill: textStyleModel.getTextColor() + } + })); + }, + + /** + * @private + */ + _renderBar: function (targetGroup) { + var visualMapModel = this.visualMapModel; + var shapes = this._shapes; + var itemSize = visualMapModel.itemSize; + var orient = this._orient; + var useHandle = this._useHandle; + var itemAlign = getItemAlign(visualMapModel, this.api, itemSize); + var barGroup = shapes.barGroup = this._createBarGroup(itemAlign); + + // Bar + barGroup.add(shapes.outOfRange = createPolygon()); + barGroup.add(shapes.inRange = createPolygon( + null, + useHandle ? getCursor$1(this._orient) : null, + bind(this._dragHandle, this, 'all', false), + bind(this._dragHandle, this, 'all', true) + )); + + var textRect = visualMapModel.textStyleModel.getTextRect('国'); + var textSize = mathMax$7(textRect.width, textRect.height); + + // Handle + if (useHandle) { + shapes.handleThumbs = []; + shapes.handleLabels = []; + shapes.handleLabelPoints = []; + + this._createHandle(barGroup, 0, itemSize, textSize, orient, itemAlign); + this._createHandle(barGroup, 1, itemSize, textSize, orient, itemAlign); + } + + this._createIndicator(barGroup, itemSize, textSize, orient); + + targetGroup.add(barGroup); + }, + + /** + * @private + */ + _createHandle: function (barGroup, handleIndex, itemSize, textSize, orient) { + var onDrift = bind(this._dragHandle, this, handleIndex, false); + var onDragEnd = bind(this._dragHandle, this, handleIndex, true); + var handleThumb = createPolygon( + createHandlePoints(handleIndex, textSize), + getCursor$1(this._orient), + onDrift, + onDragEnd + ); + handleThumb.position[0] = itemSize[0]; + barGroup.add(handleThumb); + + // Text is always horizontal layout but should not be effected by + // transform (orient/inverse). So label is built separately but not + // use zrender/graphic/helper/RectText, and is located based on view + // group (according to handleLabelPoint) but not barGroup. + var textStyleModel = this.visualMapModel.textStyleModel; + var handleLabel = new Text({ + draggable: true, + drift: onDrift, + onmousemove: function (e) { + // Fot mobile devicem, prevent screen slider on the button. + stop(e.event); + }, + ondragend: onDragEnd, + style: { + x: 0, y: 0, text: '', + textFont: textStyleModel.getFont(), + textFill: textStyleModel.getTextColor() + } + }); + this.group.add(handleLabel); + + var handleLabelPoint = [ + orient === 'horizontal' + ? textSize / 2 + : textSize * 1.5, + orient === 'horizontal' + ? (handleIndex === 0 ? -(textSize * 1.5) : (textSize * 1.5)) + : (handleIndex === 0 ? -textSize / 2 : textSize / 2) + ]; + + var shapes = this._shapes; + shapes.handleThumbs[handleIndex] = handleThumb; + shapes.handleLabelPoints[handleIndex] = handleLabelPoint; + shapes.handleLabels[handleIndex] = handleLabel; + }, + + /** + * @private + */ + _createIndicator: function (barGroup, itemSize, textSize, orient) { + var indicator = createPolygon([[0, 0]], 'move'); + indicator.position[0] = itemSize[0]; + indicator.attr({invisible: true, silent: true}); + barGroup.add(indicator); + + var textStyleModel = this.visualMapModel.textStyleModel; + var indicatorLabel = new Text({ + silent: true, + invisible: true, + style: { + x: 0, y: 0, text: '', + textFont: textStyleModel.getFont(), + textFill: textStyleModel.getTextColor() + } + }); + this.group.add(indicatorLabel); + + var indicatorLabelPoint = [ + orient === 'horizontal' ? textSize / 2 : HOVER_LINK_OUT + 3, + 0 + ]; + + var shapes = this._shapes; + shapes.indicator = indicator; + shapes.indicatorLabel = indicatorLabel; + shapes.indicatorLabelPoint = indicatorLabelPoint; + }, + + /** + * @private + */ + _dragHandle: function (handleIndex, isEnd, dx, dy) { + if (!this._useHandle) { + return; + } + + this._dragging = !isEnd; + + if (!isEnd) { + // Transform dx, dy to bar coordination. + var vertex = this._applyTransform([dx, dy], this._shapes.barGroup, true); + this._updateInterval(handleIndex, vertex[1]); + + // Considering realtime, update view should be executed + // before dispatch action. + this._updateView(); + } + + // dragEnd do not dispatch action when realtime. + if (isEnd === !this.visualMapModel.get('realtime')) { // jshint ignore:line + this.api.dispatchAction({ + type: 'selectDataRange', + from: this.uid, + visualMapId: this.visualMapModel.id, + selected: this._dataInterval.slice() + }); + } + + if (isEnd) { + !this._hovering && this._clearHoverLinkToSeries(); + } + else if (useHoverLinkOnHandle(this.visualMapModel)) { + this._doHoverLinkToSeries(this._handleEnds[handleIndex], false); + } + }, + + /** + * @private + */ + _resetInterval: function () { + var visualMapModel = this.visualMapModel; + + var dataInterval = this._dataInterval = visualMapModel.getSelected(); + var dataExtent = visualMapModel.getExtent(); + var sizeExtent = [0, visualMapModel.itemSize[1]]; + + this._handleEnds = [ + linearMap$3(dataInterval[0], dataExtent, sizeExtent, true), + linearMap$3(dataInterval[1], dataExtent, sizeExtent, true) + ]; + }, + + /** + * @private + * @param {(number|string)} handleIndex 0 or 1 or 'all' + * @param {number} dx + * @param {number} dy + */ + _updateInterval: function (handleIndex, delta) { + delta = delta || 0; + var visualMapModel = this.visualMapModel; + var handleEnds = this._handleEnds; + var sizeExtent = [0, visualMapModel.itemSize[1]]; + + sliderMove( + delta, + handleEnds, + sizeExtent, + handleIndex, + // cross is forbiden + 0 + ); + + var dataExtent = visualMapModel.getExtent(); + // Update data interval. + this._dataInterval = [ + linearMap$3(handleEnds[0], sizeExtent, dataExtent, true), + linearMap$3(handleEnds[1], sizeExtent, dataExtent, true) + ]; + }, + + /** + * @private + */ + _updateView: function (forSketch) { + var visualMapModel = this.visualMapModel; + var dataExtent = visualMapModel.getExtent(); + var shapes = this._shapes; + + var outOfRangeHandleEnds = [0, visualMapModel.itemSize[1]]; + var inRangeHandleEnds = forSketch ? outOfRangeHandleEnds : this._handleEnds; + + var visualInRange = this._createBarVisual( + this._dataInterval, dataExtent, inRangeHandleEnds, 'inRange' + ); + var visualOutOfRange = this._createBarVisual( + dataExtent, dataExtent, outOfRangeHandleEnds, 'outOfRange' + ); + + shapes.inRange + .setStyle({ + fill: visualInRange.barColor, + opacity: visualInRange.opacity + }) + .setShape('points', visualInRange.barPoints); + shapes.outOfRange + .setStyle({ + fill: visualOutOfRange.barColor, + opacity: visualOutOfRange.opacity + }) + .setShape('points', visualOutOfRange.barPoints); + + this._updateHandle(inRangeHandleEnds, visualInRange); + }, + + /** + * @private + */ + _createBarVisual: function (dataInterval, dataExtent, handleEnds, forceState) { + var opts = { + forceState: forceState, + convertOpacityToAlpha: true + }; + var colorStops = this._makeColorGradient(dataInterval, opts); + + var symbolSizes = [ + this.getControllerVisual(dataInterval[0], 'symbolSize', opts), + this.getControllerVisual(dataInterval[1], 'symbolSize', opts) + ]; + var barPoints = this._createBarPoints(handleEnds, symbolSizes); + + return { + barColor: new LinearGradient(0, 0, 0, 1, colorStops), + barPoints: barPoints, + handlesColor: [ + colorStops[0].color, + colorStops[colorStops.length - 1].color + ] + }; + }, + + /** + * @private + */ + _makeColorGradient: function (dataInterval, opts) { + // Considering colorHue, which is not linear, so we have to sample + // to calculate gradient color stops, but not only caculate head + // and tail. + var sampleNumber = 100; // Arbitrary value. + var colorStops = []; + var step = (dataInterval[1] - dataInterval[0]) / sampleNumber; + + colorStops.push({ + color: this.getControllerVisual(dataInterval[0], 'color', opts), + offset: 0 + }); + + for (var i = 1; i < sampleNumber; i++) { + var currValue = dataInterval[0] + step * i; + if (currValue > dataInterval[1]) { + break; + } + colorStops.push({ + color: this.getControllerVisual(currValue, 'color', opts), + offset: i / sampleNumber + }); + } + + colorStops.push({ + color: this.getControllerVisual(dataInterval[1], 'color', opts), + offset: 1 + }); + + return colorStops; + }, + + /** + * @private + */ + _createBarPoints: function (handleEnds, symbolSizes) { + var itemSize = this.visualMapModel.itemSize; + + return [ + [itemSize[0] - symbolSizes[0], handleEnds[0]], + [itemSize[0], handleEnds[0]], + [itemSize[0], handleEnds[1]], + [itemSize[0] - symbolSizes[1], handleEnds[1]] + ]; + }, + + /** + * @private + */ + _createBarGroup: function (itemAlign) { + var orient = this._orient; + var inverse = this.visualMapModel.get('inverse'); + + return new Group( + (orient === 'horizontal' && !inverse) + ? {scale: itemAlign === 'bottom' ? [1, 1] : [-1, 1], rotation: Math.PI / 2} + : (orient === 'horizontal' && inverse) + ? {scale: itemAlign === 'bottom' ? [-1, 1] : [1, 1], rotation: -Math.PI / 2} + : (orient === 'vertical' && !inverse) + ? {scale: itemAlign === 'left' ? [1, -1] : [-1, -1]} + : {scale: itemAlign === 'left' ? [1, 1] : [-1, 1]} + ); + }, + + /** + * @private + */ + _updateHandle: function (handleEnds, visualInRange) { + if (!this._useHandle) { + return; + } + + var shapes = this._shapes; + var visualMapModel = this.visualMapModel; + var handleThumbs = shapes.handleThumbs; + var handleLabels = shapes.handleLabels; + + each$26([0, 1], function (handleIndex) { + var handleThumb = handleThumbs[handleIndex]; + handleThumb.setStyle('fill', visualInRange.handlesColor[handleIndex]); + handleThumb.position[1] = handleEnds[handleIndex]; + + // Update handle label position. + var textPoint = applyTransform$1( + shapes.handleLabelPoints[handleIndex], + getTransform(handleThumb, this.group) + ); + handleLabels[handleIndex].setStyle({ + x: textPoint[0], + y: textPoint[1], + text: visualMapModel.formatValueText(this._dataInterval[handleIndex]), + textVerticalAlign: 'middle', + textAlign: this._applyTransform( + this._orient === 'horizontal' + ? (handleIndex === 0 ? 'bottom' : 'top') + : 'left', + shapes.barGroup + ) + }); + }, this); + }, + + /** + * @private + * @param {number} cursorValue + * @param {number} textValue + * @param {string} [rangeSymbol] + * @param {number} [halfHoverLinkSize] + */ + _showIndicator: function (cursorValue, textValue, rangeSymbol, halfHoverLinkSize) { + var visualMapModel = this.visualMapModel; + var dataExtent = visualMapModel.getExtent(); + var itemSize = visualMapModel.itemSize; + var sizeExtent = [0, itemSize[1]]; + var pos = linearMap$3(cursorValue, dataExtent, sizeExtent, true); + + var shapes = this._shapes; + var indicator = shapes.indicator; + if (!indicator) { + return; + } + + indicator.position[1] = pos; + indicator.attr('invisible', false); + indicator.setShape('points', createIndicatorPoints( + !!rangeSymbol, halfHoverLinkSize, pos, itemSize[1] + )); + + var opts = {convertOpacityToAlpha: true}; + var color = this.getControllerVisual(cursorValue, 'color', opts); + indicator.setStyle('fill', color); + + // Update handle label position. + var textPoint = applyTransform$1( + shapes.indicatorLabelPoint, + getTransform(indicator, this.group) + ); + + var indicatorLabel = shapes.indicatorLabel; + indicatorLabel.attr('invisible', false); + var align = this._applyTransform('left', shapes.barGroup); + var orient = this._orient; + indicatorLabel.setStyle({ + text: (rangeSymbol ? rangeSymbol : '') + visualMapModel.formatValueText(textValue), + textVerticalAlign: orient === 'horizontal' ? align : 'middle', + textAlign: orient === 'horizontal' ? 'center' : align, + x: textPoint[0], + y: textPoint[1] + }); + }, + + /** + * @private + */ + _enableHoverLinkToSeries: function () { + var self = this; + this._shapes.barGroup + + .on('mousemove', function (e) { + self._hovering = true; + + if (!self._dragging) { + var itemSize = self.visualMapModel.itemSize; + var pos = self._applyTransform( + [e.offsetX, e.offsetY], self._shapes.barGroup, true, true + ); + // For hover link show when hover handle, which might be + // below or upper than sizeExtent. + pos[1] = mathMin$7(mathMax$7(0, pos[1]), itemSize[1]); + self._doHoverLinkToSeries( + pos[1], + 0 <= pos[0] && pos[0] <= itemSize[0] + ); + } + }) + + .on('mouseout', function () { + // When mouse is out of handle, hoverLink still need + // to be displayed when realtime is set as false. + self._hovering = false; + !self._dragging && self._clearHoverLinkToSeries(); + }); + }, + + /** + * @private + */ + _enableHoverLinkFromSeries: function () { + var zr = this.api.getZr(); + + if (this.visualMapModel.option.hoverLink) { + zr.on('mouseover', this._hoverLinkFromSeriesMouseOver, this); + zr.on('mouseout', this._hideIndicator, this); + } + else { + this._clearHoverLinkFromSeries(); + } + }, + + /** + * @private + */ + _doHoverLinkToSeries: function (cursorPos, hoverOnBar) { + var visualMapModel = this.visualMapModel; + var itemSize = visualMapModel.itemSize; + + if (!visualMapModel.option.hoverLink) { + return; + } + + var sizeExtent = [0, itemSize[1]]; + var dataExtent = visualMapModel.getExtent(); + + // For hover link show when hover handle, which might be below or upper than sizeExtent. + cursorPos = mathMin$7(mathMax$7(sizeExtent[0], cursorPos), sizeExtent[1]); + + var halfHoverLinkSize = getHalfHoverLinkSize(visualMapModel, dataExtent, sizeExtent); + var hoverRange = [cursorPos - halfHoverLinkSize, cursorPos + halfHoverLinkSize]; + var cursorValue = linearMap$3(cursorPos, sizeExtent, dataExtent, true); + var valueRange = [ + linearMap$3(hoverRange[0], sizeExtent, dataExtent, true), + linearMap$3(hoverRange[1], sizeExtent, dataExtent, true) + ]; + // Consider data range is out of visualMap range, see test/visualMap-continuous.html, + // where china and india has very large population. + hoverRange[0] < sizeExtent[0] && (valueRange[0] = -Infinity); + hoverRange[1] > sizeExtent[1] && (valueRange[1] = Infinity); + + // Do not show indicator when mouse is over handle, + // otherwise labels overlap, especially when dragging. + if (hoverOnBar) { + if (valueRange[0] === -Infinity) { + this._showIndicator(cursorValue, valueRange[1], '< ', halfHoverLinkSize); + } + else if (valueRange[1] === Infinity) { + this._showIndicator(cursorValue, valueRange[0], '> ', halfHoverLinkSize); + } + else { + this._showIndicator(cursorValue, cursorValue, '≈ ', halfHoverLinkSize); + } + } + + // When realtime is set as false, handles, which are in barGroup, + // also trigger hoverLink, which help user to realize where they + // focus on when dragging. (see test/heatmap-large.html) + // When realtime is set as true, highlight will not show when hover + // handle, because the label on handle, which displays a exact value + // but not range, might mislead users. + var oldBatch = this._hoverLinkDataIndices; + var newBatch = []; + if (hoverOnBar || useHoverLinkOnHandle(visualMapModel)) { + newBatch = this._hoverLinkDataIndices = visualMapModel.findTargetDataIndices(valueRange); + } + + var resultBatches = compressBatches(oldBatch, newBatch); + + this._dispatchHighDown('downplay', convertDataIndex(resultBatches[0])); + this._dispatchHighDown('highlight', convertDataIndex(resultBatches[1])); + }, + + /** + * @private + */ + _hoverLinkFromSeriesMouseOver: function (e) { + var el = e.target; + var visualMapModel = this.visualMapModel; + + if (!el || el.dataIndex == null) { + return; + } + + var dataModel = this.ecModel.getSeriesByIndex(el.seriesIndex); + + if (!visualMapModel.isTargetSeries(dataModel)) { + return; + } + + var data = dataModel.getData(el.dataType); + var value = data.get(visualMapModel.getDataDimension(data), el.dataIndex, true); + + if (!isNaN(value)) { + this._showIndicator(value, value); + } + }, + + /** + * @private + */ + _hideIndicator: function () { + var shapes = this._shapes; + shapes.indicator && shapes.indicator.attr('invisible', true); + shapes.indicatorLabel && shapes.indicatorLabel.attr('invisible', true); + }, + + /** + * @private + */ + _clearHoverLinkToSeries: function () { + this._hideIndicator(); + + var indices = this._hoverLinkDataIndices; + this._dispatchHighDown('downplay', convertDataIndex(indices)); + + indices.length = 0; + }, + + /** + * @private + */ + _clearHoverLinkFromSeries: function () { + this._hideIndicator(); + + var zr = this.api.getZr(); + zr.off('mouseover', this._hoverLinkFromSeriesMouseOver); + zr.off('mouseout', this._hideIndicator); + }, + + /** + * @private + */ + _applyTransform: function (vertex, element, inverse, global) { + var transform = getTransform(element, global ? null : this.group); + + return graphic[ + isArray(vertex) ? 'applyTransform' : 'transformDirection' + ](vertex, transform, inverse); + }, + + /** + * @private + */ + _dispatchHighDown: function (type, batch) { + batch && batch.length && this.api.dispatchAction({ + type: type, + batch: batch + }); + }, + + /** + * @override + */ + dispose: function () { + this._clearHoverLinkFromSeries(); + this._clearHoverLinkToSeries(); + }, + + /** + * @override + */ + remove: function () { + this._clearHoverLinkFromSeries(); + this._clearHoverLinkToSeries(); + } + +}); + +function createPolygon(points, cursor, onDrift, onDragEnd) { + return new Polygon({ + shape: {points: points}, + draggable: !!onDrift, + cursor: cursor, + drift: onDrift, + onmousemove: function (e) { + // Fot mobile devicem, prevent screen slider on the button. + stop(e.event); + }, + ondragend: onDragEnd + }); +} + +function createHandlePoints(handleIndex, textSize) { + return handleIndex === 0 + ? [[0, 0], [textSize, 0], [textSize, -textSize]] + : [[0, 0], [textSize, 0], [textSize, textSize]]; +} + +function createIndicatorPoints(isRange, halfHoverLinkSize, pos, extentMax) { + return isRange + ? [ // indicate range + [0, -mathMin$7(halfHoverLinkSize, mathMax$7(pos, 0))], + [HOVER_LINK_OUT, 0], + [0, mathMin$7(halfHoverLinkSize, mathMax$7(extentMax - pos, 0))] + ] + : [ // indicate single value + [0, 0], [5, -5], [5, 5] + ]; +} + +function getHalfHoverLinkSize(visualMapModel, dataExtent, sizeExtent) { + var halfHoverLinkSize = HOVER_LINK_SIZE / 2; + var hoverLinkDataSize = visualMapModel.get('hoverLinkDataSize'); + if (hoverLinkDataSize) { + halfHoverLinkSize = linearMap$3(hoverLinkDataSize, dataExtent, sizeExtent, true) / 2; + } + return halfHoverLinkSize; +} + +function useHoverLinkOnHandle(visualMapModel) { + var hoverLinkOnHandle = visualMapModel.get('hoverLinkOnHandle'); + return !!(hoverLinkOnHandle == null ? visualMapModel.get('realtime') : hoverLinkOnHandle); +} + +function getCursor$1(orient) { + return orient === 'vertical' ? 'ns-resize' : 'ew-resize'; +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var actionInfo$2 = { + type: 'selectDataRange', + event: 'dataRangeSelected', + // FIXME use updateView appears wrong + update: 'update' +}; + +registerAction(actionInfo$2, function (payload, ecModel) { + + ecModel.eachComponent({mainType: 'visualMap', query: payload}, function (model) { + model.setSelected(payload.selected); + }); + +}); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/** + * DataZoom component entry + */ + +registerPreprocessor(preprocessor$2); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var PiecewiseModel = VisualMapModel.extend({ + + type: 'visualMap.piecewise', + + /** + * Order Rule: + * + * option.categories / option.pieces / option.text / option.selected: + * If !option.inverse, + * Order when vertical: ['top', ..., 'bottom']. + * Order when horizontal: ['left', ..., 'right']. + * If option.inverse, the meaning of + * the order should be reversed. + * + * this._pieceList: + * The order is always [low, ..., high]. + * + * Mapping from location to low-high: + * If !option.inverse + * When vertical, top is high. + * When horizontal, right is high. + * If option.inverse, reverse. + */ + + /** + * @protected + */ + defaultOption: { + selected: null, // Object. If not specified, means selected. + // When pieces and splitNumber: {'0': true, '5': true} + // When categories: {'cate1': false, 'cate3': true} + // When selected === false, means all unselected. + + minOpen: false, // Whether include values that smaller than `min`. + maxOpen: false, // Whether include values that bigger than `max`. + + align: 'auto', // 'auto', 'left', 'right' + itemWidth: 20, // When put the controller vertically, it is the length of + // horizontal side of each item. Otherwise, vertical side. + itemHeight: 14, // When put the controller vertically, it is the length of + // vertical side of each item. Otherwise, horizontal side. + itemSymbol: 'roundRect', + pieceList: null, // Each item is Object, with some of those attrs: + // {min, max, lt, gt, lte, gte, value, + // color, colorSaturation, colorAlpha, opacity, + // symbol, symbolSize}, which customize the range or visual + // coding of the certain piece. Besides, see "Order Rule". + categories: null, // category names, like: ['some1', 'some2', 'some3']. + // Attr min/max are ignored when categories set. See "Order Rule" + splitNumber: 5, // If set to 5, auto split five pieces equally. + // If set to 0 and component type not set, component type will be + // determined as "continuous". (It is less reasonable but for ec2 + // compatibility, see echarts/component/visualMap/typeDefaulter) + selectedMode: 'multiple', // Can be 'multiple' or 'single'. + itemGap: 10, // The gap between two items, in px. + hoverLink: true, // Enable hover highlight. + + showLabel: null // By default, when text is used, label will hide (the logic + // is remained for compatibility reason) + }, + + /** + * @override + */ + optionUpdated: function (newOption, isInit) { + PiecewiseModel.superApply(this, 'optionUpdated', arguments); + + /** + * The order is always [low, ..., high]. + * [{text: string, interval: Array.}, ...] + * @private + * @type {Array.} + */ + this._pieceList = []; + + this.resetExtent(); + + /** + * 'pieces', 'categories', 'splitNumber' + * @type {string} + */ + var mode = this._mode = this._determineMode(); + + resetMethods[this._mode].call(this); + + this._resetSelected(newOption, isInit); + + var categories = this.option.categories; + + this.resetVisual(function (mappingOption, state) { + if (mode === 'categories') { + mappingOption.mappingMethod = 'category'; + mappingOption.categories = clone(categories); + } + else { + mappingOption.dataExtent = this.getExtent(); + mappingOption.mappingMethod = 'piecewise'; + mappingOption.pieceList = map(this._pieceList, function (piece) { + var piece = clone(piece); + if (state !== 'inRange') { + // FIXME + // outOfRange do not support special visual in pieces. + piece.visual = null; + } + return piece; + }); + } + }); + }, + + /** + * @protected + * @override + */ + completeVisualOption: function () { + // Consider this case: + // visualMap: { + // pieces: [{symbol: 'circle', lt: 0}, {symbol: 'rect', gte: 0}] + // } + // where no inRange/outOfRange set but only pieces. So we should make + // default inRange/outOfRange for this case, otherwise visuals that only + // appear in `pieces` will not be taken into account in visual encoding. + + var option = this.option; + var visualTypesInPieces = {}; + var visualTypes = VisualMapping.listVisualTypes(); + var isCategory = this.isCategory(); + + each$1(option.pieces, function (piece) { + each$1(visualTypes, function (visualType) { + if (piece.hasOwnProperty(visualType)) { + visualTypesInPieces[visualType] = 1; + } + }); + }); + + each$1(visualTypesInPieces, function (v, visualType) { + var exists = 0; + each$1(this.stateList, function (state) { + exists |= has(option, state, visualType) + || has(option.target, state, visualType); + }, this); + + !exists && each$1(this.stateList, function (state) { + (option[state] || (option[state] = {}))[visualType] = visualDefault.get( + visualType, state === 'inRange' ? 'active' : 'inactive', isCategory + ); + }); + }, this); + + function has(obj, state, visualType) { + return obj && obj[state] && ( + isObject$1(obj[state]) + ? obj[state].hasOwnProperty(visualType) + : obj[state] === visualType // e.g., inRange: 'symbol' + ); + } + + VisualMapModel.prototype.completeVisualOption.apply(this, arguments); + }, + + _resetSelected: function (newOption, isInit) { + var thisOption = this.option; + var pieceList = this._pieceList; + + // Selected do not merge but all override. + var selected = (isInit ? thisOption : newOption).selected || {}; + thisOption.selected = selected; + + // Consider 'not specified' means true. + each$1(pieceList, function (piece, index) { + var key = this.getSelectedMapKey(piece); + if (!selected.hasOwnProperty(key)) { + selected[key] = true; + } + }, this); + + if (thisOption.selectedMode === 'single') { + // Ensure there is only one selected. + var hasSel = false; + + each$1(pieceList, function (piece, index) { + var key = this.getSelectedMapKey(piece); + if (selected[key]) { + hasSel + ? (selected[key] = false) + : (hasSel = true); + } + }, this); + } + // thisOption.selectedMode === 'multiple', default: all selected. + }, + + /** + * @public + */ + getSelectedMapKey: function (piece) { + return this._mode === 'categories' + ? piece.value + '' : piece.index + ''; + }, + + /** + * @public + */ + getPieceList: function () { + return this._pieceList; + }, + + /** + * @private + * @return {string} + */ + _determineMode: function () { + var option = this.option; + + return option.pieces && option.pieces.length > 0 + ? 'pieces' + : this.option.categories + ? 'categories' + : 'splitNumber'; + }, + + /** + * @public + * @override + */ + setSelected: function (selected) { + this.option.selected = clone(selected); + }, + + /** + * @public + * @override + */ + getValueState: function (value) { + var index = VisualMapping.findPieceIndex(value, this._pieceList); + + return index != null + ? (this.option.selected[this.getSelectedMapKey(this._pieceList[index])] + ? 'inRange' : 'outOfRange' + ) + : 'outOfRange'; + }, + + /** + * @public + * @params {number} pieceIndex piece index in visualMapModel.getPieceList() + * @return {Array.} [{seriesId, dataIndices: >}, ...] + */ + findTargetDataIndices: function (pieceIndex) { + var result = []; + + this.eachTargetSeries(function (seriesModel) { + var dataIndices = []; + var data = seriesModel.getData(); + + data.each(this.getDataDimension(data), function (value, dataIndex) { + // Should always base on model pieceList, because it is order sensitive. + var pIdx = VisualMapping.findPieceIndex(value, this._pieceList); + pIdx === pieceIndex && dataIndices.push(dataIndex); + }, this); + + result.push({seriesId: seriesModel.id, dataIndex: dataIndices}); + }, this); + + return result; + }, + + /** + * @private + * @param {Object} piece piece.value or piece.interval is required. + * @return {number} Can be Infinity or -Infinity + */ + getRepresentValue: function (piece) { + var representValue; + if (this.isCategory()) { + representValue = piece.value; + } + else { + if (piece.value != null) { + representValue = piece.value; + } + else { + var pieceInterval = piece.interval || []; + representValue = (pieceInterval[0] === -Infinity && pieceInterval[1] === Infinity) + ? 0 + : (pieceInterval[0] + pieceInterval[1]) / 2; + } + } + return representValue; + }, + + getVisualMeta: function (getColorVisual) { + // Do not support category. (category axis is ordinal, numerical) + if (this.isCategory()) { + return; + } + + var stops = []; + var outerColors = []; + var visualMapModel = this; + + function setStop(interval, valueState) { + var representValue = visualMapModel.getRepresentValue({interval: interval}); + if (!valueState) { + valueState = visualMapModel.getValueState(representValue); + } + var color = getColorVisual(representValue, valueState); + if (interval[0] === -Infinity) { + outerColors[0] = color; + } + else if (interval[1] === Infinity) { + outerColors[1] = color; + } + else { + stops.push( + {value: interval[0], color: color}, + {value: interval[1], color: color} + ); + } + } + + // Suplement + var pieceList = this._pieceList.slice(); + if (!pieceList.length) { + pieceList.push({interval: [-Infinity, Infinity]}); + } + else { + var edge = pieceList[0].interval[0]; + edge !== -Infinity && pieceList.unshift({interval: [-Infinity, edge]}); + edge = pieceList[pieceList.length - 1].interval[1]; + edge !== Infinity && pieceList.push({interval: [edge, Infinity]}); + } + + var curr = -Infinity; + each$1(pieceList, function (piece) { + var interval = piece.interval; + if (interval) { + // Fulfill gap. + interval[0] > curr && setStop([curr, interval[0]], 'outOfRange'); + setStop(interval.slice()); + curr = interval[1]; + } + }, this); + + return {stops: stops, outerColors: outerColors}; + } + +}); + +/** + * Key is this._mode + * @type {Object} + * @this {module:echarts/component/viusalMap/PiecewiseMode} + */ +var resetMethods = { + + splitNumber: function () { + var thisOption = this.option; + var pieceList = this._pieceList; + var precision = Math.min(thisOption.precision, 20); + var dataExtent = this.getExtent(); + var splitNumber = thisOption.splitNumber; + splitNumber = Math.max(parseInt(splitNumber, 10), 1); + thisOption.splitNumber = splitNumber; + + var splitStep = (dataExtent[1] - dataExtent[0]) / splitNumber; + // Precision auto-adaption + while (+splitStep.toFixed(precision) !== splitStep && precision < 5) { + precision++; + } + thisOption.precision = precision; + splitStep = +splitStep.toFixed(precision); + + var index = 0; + + if (thisOption.minOpen) { + pieceList.push({ + index: index++, + interval: [-Infinity, dataExtent[0]], + close: [0, 0] + }); + } + + for ( + var curr = dataExtent[0], len = index + splitNumber; + index < len; + curr += splitStep + ) { + var max = index === splitNumber - 1 ? dataExtent[1] : (curr + splitStep); + + pieceList.push({ + index: index++, + interval: [curr, max], + close: [1, 1] + }); + } + + if (thisOption.maxOpen) { + pieceList.push({ + index: index++, + interval: [dataExtent[1], Infinity], + close: [0, 0] + }); + } + + reformIntervals(pieceList); + + each$1(pieceList, function (piece) { + piece.text = this.formatValueText(piece.interval); + }, this); + }, + + categories: function () { + var thisOption = this.option; + each$1(thisOption.categories, function (cate) { + // FIXME category模式也使用pieceList,但在visualMapping中不是使用pieceList。 + // 是否改一致。 + this._pieceList.push({ + text: this.formatValueText(cate, true), + value: cate + }); + }, this); + + // See "Order Rule". + normalizeReverse(thisOption, this._pieceList); + }, + + pieces: function () { + var thisOption = this.option; + var pieceList = this._pieceList; + + each$1(thisOption.pieces, function (pieceListItem, index) { + + if (!isObject$1(pieceListItem)) { + pieceListItem = {value: pieceListItem}; + } + + var item = {text: '', index: index}; + + if (pieceListItem.label != null) { + item.text = pieceListItem.label; + } + + if (pieceListItem.hasOwnProperty('value')) { + var value = item.value = pieceListItem.value; + item.interval = [value, value]; + item.close = [1, 1]; + } + else { + // `min` `max` is legacy option. + // `lt` `gt` `lte` `gte` is recommanded. + var interval = item.interval = []; + var close = item.close = [0, 0]; + + var closeList = [1, 0, 1]; + var infinityList = [-Infinity, Infinity]; + + var useMinMax = []; + for (var lg = 0; lg < 2; lg++) { + var names = [['gte', 'gt', 'min'], ['lte', 'lt', 'max']][lg]; + for (var i = 0; i < 3 && interval[lg] == null; i++) { + interval[lg] = pieceListItem[names[i]]; + close[lg] = closeList[i]; + useMinMax[lg] = i === 2; + } + interval[lg] == null && (interval[lg] = infinityList[lg]); + } + useMinMax[0] && interval[1] === Infinity && (close[0] = 0); + useMinMax[1] && interval[0] === -Infinity && (close[1] = 0); + + if (__DEV__) { + if (interval[0] > interval[1]) { + console.warn( + 'Piece ' + index + 'is illegal: ' + interval + + ' lower bound should not greater then uppper bound.' + ); + } + } + + if (interval[0] === interval[1] && close[0] && close[1]) { + // Consider: [{min: 5, max: 5, visual: {...}}, {min: 0, max: 5}], + // we use value to lift the priority when min === max + item.value = interval[0]; + } + } + + item.visual = VisualMapping.retrieveVisuals(pieceListItem); + + pieceList.push(item); + + }, this); + + // See "Order Rule". + normalizeReverse(thisOption, pieceList); + // Only pieces + reformIntervals(pieceList); + + each$1(pieceList, function (piece) { + var close = piece.close; + var edgeSymbols = [['<', '≤'][close[1]], ['>', '≥'][close[0]]]; + piece.text = piece.text || this.formatValueText( + piece.value != null ? piece.value : piece.interval, + false, + edgeSymbols + ); + }, this); + } +}; + +function normalizeReverse(thisOption, pieceList) { + var inverse = thisOption.inverse; + if (thisOption.orient === 'vertical' ? !inverse : inverse) { + pieceList.reverse(); + } +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var PiecewiseVisualMapView = VisualMapView.extend({ + + type: 'visualMap.piecewise', + + /** + * @protected + * @override + */ + doRender: function () { + var thisGroup = this.group; + + thisGroup.removeAll(); + + var visualMapModel = this.visualMapModel; + var textGap = visualMapModel.get('textGap'); + var textStyleModel = visualMapModel.textStyleModel; + var textFont = textStyleModel.getFont(); + var textFill = textStyleModel.getTextColor(); + var itemAlign = this._getItemAlign(); + var itemSize = visualMapModel.itemSize; + var viewData = this._getViewData(); + var endsText = viewData.endsText; + var showLabel = retrieve(visualMapModel.get('showLabel', true), !endsText); + + endsText && this._renderEndsText( + thisGroup, endsText[0], itemSize, showLabel, itemAlign + ); + + each$1(viewData.viewPieceList, renderItem, this); + + endsText && this._renderEndsText( + thisGroup, endsText[1], itemSize, showLabel, itemAlign + ); + + box( + visualMapModel.get('orient'), thisGroup, visualMapModel.get('itemGap') + ); + + this.renderBackground(thisGroup); + + this.positionGroup(thisGroup); + + function renderItem(item) { + var piece = item.piece; + + var itemGroup = new Group(); + itemGroup.onclick = bind(this._onItemClick, this, piece); + + this._enableHoverLink(itemGroup, item.indexInModelPieceList); + + var representValue = visualMapModel.getRepresentValue(piece); + + this._createItemSymbol( + itemGroup, representValue, [0, 0, itemSize[0], itemSize[1]] + ); + + if (showLabel) { + var visualState = this.visualMapModel.getValueState(representValue); + + itemGroup.add(new Text({ + style: { + x: itemAlign === 'right' ? -textGap : itemSize[0] + textGap, + y: itemSize[1] / 2, + text: piece.text, + textVerticalAlign: 'middle', + textAlign: itemAlign, + textFont: textFont, + textFill: textFill, + opacity: visualState === 'outOfRange' ? 0.5 : 1 + } + })); + } + + thisGroup.add(itemGroup); + } + }, + + /** + * @private + */ + _enableHoverLink: function (itemGroup, pieceIndex) { + itemGroup + .on('mouseover', bind(onHoverLink, this, 'highlight')) + .on('mouseout', bind(onHoverLink, this, 'downplay')); + + function onHoverLink(method) { + var visualMapModel = this.visualMapModel; + + visualMapModel.option.hoverLink && this.api.dispatchAction({ + type: method, + batch: convertDataIndex( + visualMapModel.findTargetDataIndices(pieceIndex) + ) + }); + } + }, + + /** + * @private + */ + _getItemAlign: function () { + var visualMapModel = this.visualMapModel; + var modelOption = visualMapModel.option; + + if (modelOption.orient === 'vertical') { + return getItemAlign( + visualMapModel, this.api, visualMapModel.itemSize + ); + } + else { // horizontal, most case left unless specifying right. + var align = modelOption.align; + if (!align || align === 'auto') { + align = 'left'; + } + return align; + } + }, + + /** + * @private + */ + _renderEndsText: function (group, text, itemSize, showLabel, itemAlign) { + if (!text) { + return; + } + + var itemGroup = new Group(); + var textStyleModel = this.visualMapModel.textStyleModel; + + itemGroup.add(new Text({ + style: { + x: showLabel ? (itemAlign === 'right' ? itemSize[0] : 0) : itemSize[0] / 2, + y: itemSize[1] / 2, + textVerticalAlign: 'middle', + textAlign: showLabel ? itemAlign : 'center', + text: text, + textFont: textStyleModel.getFont(), + textFill: textStyleModel.getTextColor() + } + })); + + group.add(itemGroup); + }, + + /** + * @private + * @return {Object} {peiceList, endsText} The order is the same as screen pixel order. + */ + _getViewData: function () { + var visualMapModel = this.visualMapModel; + + var viewPieceList = map(visualMapModel.getPieceList(), function (piece, index) { + return {piece: piece, indexInModelPieceList: index}; + }); + var endsText = visualMapModel.get('text'); + + // Consider orient and inverse. + var orient = visualMapModel.get('orient'); + var inverse = visualMapModel.get('inverse'); + + // Order of model pieceList is always [low, ..., high] + if (orient === 'horizontal' ? inverse : !inverse) { + viewPieceList.reverse(); + } + // Origin order of endsText is [high, low] + else if (endsText) { + endsText = endsText.slice().reverse(); + } + + return {viewPieceList: viewPieceList, endsText: endsText}; + }, + + /** + * @private + */ + _createItemSymbol: function (group, representValue, shapeParam) { + group.add(createSymbol( + this.getControllerVisual(representValue, 'symbol'), + shapeParam[0], shapeParam[1], shapeParam[2], shapeParam[3], + this.getControllerVisual(representValue, 'color') + )); + }, + + /** + * @private + */ + _onItemClick: function (piece) { + var visualMapModel = this.visualMapModel; + var option = visualMapModel.option; + var selected = clone(option.selected); + var newKey = visualMapModel.getSelectedMapKey(piece); + + if (option.selectedMode === 'single') { + selected[newKey] = true; + each$1(selected, function (o, key) { + selected[key] = key === newKey; + }); + } + else { + selected[newKey] = !selected[newKey]; + } + + this.api.dispatchAction({ + type: 'selectDataRange', + from: this.uid, + visualMapId: this.visualMapModel.id, + selected: selected + }); + } +}); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/** + * DataZoom component entry + */ + +registerPreprocessor(preprocessor$2); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/** + * visualMap component entry + */ + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var addCommas$1 = addCommas; +var encodeHTML$1 = encodeHTML; + +function fillLabel(opt) { + defaultEmphasis(opt, 'label', ['show']); +} +var MarkerModel = extendComponentModel({ + + type: 'marker', + + dependencies: ['series', 'grid', 'polar', 'geo'], + + /** + * @overrite + */ + init: function (option, parentModel, ecModel, extraOpt) { + + if (__DEV__) { + if (this.type === 'marker') { + throw new Error('Marker component is abstract component. Use markLine, markPoint, markArea instead.'); + } + } + this.mergeDefaultAndTheme(option, ecModel); + this.mergeOption(option, ecModel, extraOpt.createdBySelf, true); + }, + + /** + * @return {boolean} + */ + isAnimationEnabled: function () { + if (env$1.node) { + return false; + } + + var hostSeries = this.__hostSeries; + return this.getShallow('animation') && hostSeries && hostSeries.isAnimationEnabled(); + }, + + mergeOption: function (newOpt, ecModel, createdBySelf, isInit) { + var MarkerModel = this.constructor; + var modelPropName = this.mainType + 'Model'; + if (!createdBySelf) { + ecModel.eachSeries(function (seriesModel) { + + var markerOpt = seriesModel.get(this.mainType, true); + + var markerModel = seriesModel[modelPropName]; + if (!markerOpt || !markerOpt.data) { + seriesModel[modelPropName] = null; + return; + } + if (!markerModel) { + if (isInit) { + // Default label emphasis `position` and `show` + fillLabel(markerOpt); + } + each$1(markerOpt.data, function (item) { + // FIXME Overwrite fillLabel method ? + if (item instanceof Array) { + fillLabel(item[0]); + fillLabel(item[1]); + } + else { + fillLabel(item); + } + }); + + markerModel = new MarkerModel( + markerOpt, this, ecModel + ); + + extend(markerModel, { + mainType: this.mainType, + // Use the same series index and name + seriesIndex: seriesModel.seriesIndex, + name: seriesModel.name, + createdBySelf: true + }); + + markerModel.__hostSeries = seriesModel; + } + else { + markerModel.mergeOption(markerOpt, ecModel, true); + } + seriesModel[modelPropName] = markerModel; + }, this); + } + }, + + formatTooltip: function (dataIndex) { + var data = this.getData(); + var value = this.getRawValue(dataIndex); + var formattedValue = isArray(value) + ? map(value, addCommas$1).join(', ') : addCommas$1(value); + var name = data.getName(dataIndex); + var html = encodeHTML$1(this.name); + if (value != null || name) { + html += '
'; + } + if (name) { + html += encodeHTML$1(name); + if (value != null) { + html += ' : '; + } + } + if (value != null) { + html += encodeHTML$1(formattedValue); + } + return html; + }, + + getData: function () { + return this._data; + }, + + setData: function (data) { + this._data = data; + } +}); + +mixin(MarkerModel, dataFormatMixin); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +MarkerModel.extend({ + + type: 'markPoint', + + defaultOption: { + zlevel: 0, + z: 5, + symbol: 'pin', + symbolSize: 50, + //symbolRotate: 0, + //symbolOffset: [0, 0] + tooltip: { + trigger: 'item' + }, + label: { + show: true, + position: 'inside' + }, + itemStyle: { + borderWidth: 2 + }, + emphasis: { + label: { + show: true + } + } + } +}); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var indexOf$2 = indexOf; + +function hasXOrY(item) { + return !(isNaN(parseFloat(item.x)) && isNaN(parseFloat(item.y))); +} + +function hasXAndY(item) { + return !isNaN(parseFloat(item.x)) && !isNaN(parseFloat(item.y)); +} + +// Make it simple, do not visit all stacked value to count precision. +// function getPrecision(data, valueAxisDim, dataIndex) { +// var precision = -1; +// var stackedDim = data.mapDimension(valueAxisDim); +// do { +// precision = Math.max( +// numberUtil.getPrecision(data.get(stackedDim, dataIndex)), +// precision +// ); +// var stackedOnSeries = data.getCalculationInfo('stackedOnSeries'); +// if (stackedOnSeries) { +// var byValue = data.get(data.getCalculationInfo('stackedByDimension'), dataIndex); +// data = stackedOnSeries.getData(); +// dataIndex = data.indexOf(data.getCalculationInfo('stackedByDimension'), byValue); +// stackedDim = data.getCalculationInfo('stackedDimension'); +// } +// else { +// data = null; +// } +// } while (data); + +// return precision; +// } + +function markerTypeCalculatorWithExtent( + mlType, data, otherDataDim, targetDataDim, otherCoordIndex, targetCoordIndex +) { + var coordArr = []; + + var stacked = isDimensionStacked(data, targetDataDim /*, otherDataDim*/); + var calcDataDim = stacked + ? data.getCalculationInfo('stackResultDimension') + : targetDataDim; + + var value = numCalculate(data, calcDataDim, mlType); + + var dataIndex = data.indicesOfNearest(calcDataDim, value)[0]; + coordArr[otherCoordIndex] = data.get(otherDataDim, dataIndex); + coordArr[targetCoordIndex] = data.get(targetDataDim, dataIndex); + + // Make it simple, do not visit all stacked value to count precision. + var precision = getPrecision(data.get(targetDataDim, dataIndex)); + precision = Math.min(precision, 20); + if (precision >= 0) { + coordArr[targetCoordIndex] = +coordArr[targetCoordIndex].toFixed(precision); + } + + return coordArr; +} + +var curry$6 = curry; +// TODO Specified percent +var markerTypeCalculator = { + /** + * @method + * @param {module:echarts/data/List} data + * @param {string} baseAxisDim + * @param {string} valueAxisDim + */ + min: curry$6(markerTypeCalculatorWithExtent, 'min'), + /** + * @method + * @param {module:echarts/data/List} data + * @param {string} baseAxisDim + * @param {string} valueAxisDim + */ + max: curry$6(markerTypeCalculatorWithExtent, 'max'), + + /** + * @method + * @param {module:echarts/data/List} data + * @param {string} baseAxisDim + * @param {string} valueAxisDim + */ + average: curry$6(markerTypeCalculatorWithExtent, 'average') +}; + +/** + * Transform markPoint data item to format used in List by do the following + * 1. Calculate statistic like `max`, `min`, `average` + * 2. Convert `item.xAxis`, `item.yAxis` to `item.coord` array + * @param {module:echarts/model/Series} seriesModel + * @param {module:echarts/coord/*} [coordSys] + * @param {Object} item + * @return {Object} + */ +function dataTransform(seriesModel, item) { + var data = seriesModel.getData(); + var coordSys = seriesModel.coordinateSystem; + + // 1. If not specify the position with pixel directly + // 2. If `coord` is not a data array. Which uses `xAxis`, + // `yAxis` to specify the coord on each dimension + + // parseFloat first because item.x and item.y can be percent string like '20%' + if (item && !hasXAndY(item) && !isArray(item.coord) && coordSys) { + var dims = coordSys.dimensions; + var axisInfo = getAxisInfo$1(item, data, coordSys, seriesModel); + + // Clone the option + // Transform the properties xAxis, yAxis, radiusAxis, angleAxis, geoCoord to value + item = clone(item); + + if (item.type + && markerTypeCalculator[item.type] + && axisInfo.baseAxis && axisInfo.valueAxis + ) { + var otherCoordIndex = indexOf$2(dims, axisInfo.baseAxis.dim); + var targetCoordIndex = indexOf$2(dims, axisInfo.valueAxis.dim); + + item.coord = markerTypeCalculator[item.type]( + data, axisInfo.baseDataDim, axisInfo.valueDataDim, + otherCoordIndex, targetCoordIndex + ); + // Force to use the value of calculated value. + item.value = item.coord[targetCoordIndex]; + } + else { + // FIXME Only has one of xAxis and yAxis. + var coord = [ + item.xAxis != null ? item.xAxis : item.radiusAxis, + item.yAxis != null ? item.yAxis : item.angleAxis + ]; + // Each coord support max, min, average + for (var i = 0; i < 2; i++) { + if (markerTypeCalculator[coord[i]]) { + coord[i] = numCalculate(data, data.mapDimension(dims[i]), coord[i]); + } + } + item.coord = coord; + } + } + return item; +} + +function getAxisInfo$1(item, data, coordSys, seriesModel) { + var ret = {}; + + if (item.valueIndex != null || item.valueDim != null) { + ret.valueDataDim = item.valueIndex != null + ? data.getDimension(item.valueIndex) : item.valueDim; + ret.valueAxis = coordSys.getAxis(dataDimToCoordDim(seriesModel, ret.valueDataDim)); + ret.baseAxis = coordSys.getOtherAxis(ret.valueAxis); + ret.baseDataDim = data.mapDimension(ret.baseAxis.dim); + } + else { + ret.baseAxis = seriesModel.getBaseAxis(); + ret.valueAxis = coordSys.getOtherAxis(ret.baseAxis); + ret.baseDataDim = data.mapDimension(ret.baseAxis.dim); + ret.valueDataDim = data.mapDimension(ret.valueAxis.dim); + } + + return ret; +} + +function dataDimToCoordDim(seriesModel, dataDim) { + var data = seriesModel.getData(); + var dimensions = data.dimensions; + dataDim = data.getDimension(dataDim); + for (var i = 0; i < dimensions.length; i++) { + var dimItem = data.getDimensionInfo(dimensions[i]); + if (dimItem.name === dataDim) { + return dimItem.coordDim; + } + } +} + +/** + * Filter data which is out of coordinateSystem range + * [dataFilter description] + * @param {module:echarts/coord/*} [coordSys] + * @param {Object} item + * @return {boolean} + */ +function dataFilter$1(coordSys, item) { + // Alwalys return true if there is no coordSys + return (coordSys && coordSys.containData && item.coord && !hasXOrY(item)) + ? coordSys.containData(item.coord) : true; +} + +function dimValueGetter(item, dimName, dataIndex, dimIndex) { + // x, y, radius, angle + if (dimIndex < 2) { + return item.coord && item.coord[dimIndex]; + } + return item.value; +} + +function numCalculate(data, valueDataDim, type) { + if (type === 'average') { + var sum = 0; + var count = 0; + data.each(valueDataDim, function (val, idx) { + if (!isNaN(val)) { + sum += val; + count++; + } + }); + return sum / count; + } + else if (type === 'median') { + return data.getMedian(valueDataDim); + } + else { + // max & min + return data.getDataExtent(valueDataDim, true)[type === 'max' ? 1 : 0]; + } +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var MarkerView = extendComponentView({ + + type: 'marker', + + init: function () { + /** + * Markline grouped by series + * @private + * @type {module:zrender/core/util.HashMap} + */ + this.markerGroupMap = createHashMap(); + }, + + render: function (markerModel, ecModel, api) { + var markerGroupMap = this.markerGroupMap; + markerGroupMap.each(function (item) { + item.__keep = false; + }); + + var markerModelKey = this.type + 'Model'; + ecModel.eachSeries(function (seriesModel) { + var markerModel = seriesModel[markerModelKey]; + markerModel && this.renderSeries(seriesModel, markerModel, ecModel, api); + }, this); + + markerGroupMap.each(function (item) { + !item.__keep && this.group.remove(item.group); + }, this); + }, + + renderSeries: function () {} +}); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +function updateMarkerLayout(mpData, seriesModel, api) { + var coordSys = seriesModel.coordinateSystem; + mpData.each(function (idx) { + var itemModel = mpData.getItemModel(idx); + var point; + var xPx = parsePercent$1(itemModel.get('x'), api.getWidth()); + var yPx = parsePercent$1(itemModel.get('y'), api.getHeight()); + if (!isNaN(xPx) && !isNaN(yPx)) { + point = [xPx, yPx]; + } + // Chart like bar may have there own marker positioning logic + else if (seriesModel.getMarkerPosition) { + // Use the getMarkerPoisition + point = seriesModel.getMarkerPosition( + mpData.getValues(mpData.dimensions, idx) + ); + } + else if (coordSys) { + var x = mpData.get(coordSys.dimensions[0], idx); + var y = mpData.get(coordSys.dimensions[1], idx); + point = coordSys.dataToPoint([x, y]); + + } + + // Use x, y if has any + if (!isNaN(xPx)) { + point[0] = xPx; + } + if (!isNaN(yPx)) { + point[1] = yPx; + } + + mpData.setItemLayout(idx, point); + }); +} + +MarkerView.extend({ + + type: 'markPoint', + + // updateLayout: function (markPointModel, ecModel, api) { + // ecModel.eachSeries(function (seriesModel) { + // var mpModel = seriesModel.markPointModel; + // if (mpModel) { + // updateMarkerLayout(mpModel.getData(), seriesModel, api); + // this.markerGroupMap.get(seriesModel.id).updateLayout(mpModel); + // } + // }, this); + // }, + + updateTransform: function (markPointModel, ecModel, api) { + ecModel.eachSeries(function (seriesModel) { + var mpModel = seriesModel.markPointModel; + if (mpModel) { + updateMarkerLayout(mpModel.getData(), seriesModel, api); + this.markerGroupMap.get(seriesModel.id).updateLayout(mpModel); + } + }, this); + }, + + renderSeries: function (seriesModel, mpModel, ecModel, api) { + var coordSys = seriesModel.coordinateSystem; + var seriesId = seriesModel.id; + var seriesData = seriesModel.getData(); + + var symbolDrawMap = this.markerGroupMap; + var symbolDraw = symbolDrawMap.get(seriesId) + || symbolDrawMap.set(seriesId, new SymbolDraw()); + + var mpData = createList$1(coordSys, seriesModel, mpModel); + + // FIXME + mpModel.setData(mpData); + + updateMarkerLayout(mpModel.getData(), seriesModel, api); + + mpData.each(function (idx) { + var itemModel = mpData.getItemModel(idx); + var symbolSize = itemModel.getShallow('symbolSize'); + if (typeof symbolSize === 'function') { + // FIXME 这里不兼容 ECharts 2.x,2.x 貌似参数是整个数据? + symbolSize = symbolSize( + mpModel.getRawValue(idx), mpModel.getDataParams(idx) + ); + } + mpData.setItemVisual(idx, { + symbolSize: symbolSize, + color: itemModel.get('itemStyle.color') + || seriesData.getVisual('color'), + symbol: itemModel.getShallow('symbol') + }); + }); + + // TODO Text are wrong + symbolDraw.updateData(mpData); + this.group.add(symbolDraw.group); + + // Set host model for tooltip + // FIXME + mpData.eachItemGraphicEl(function (el) { + el.traverse(function (child) { + child.dataModel = mpModel; + }); + }); + + symbolDraw.__keep = true; + + symbolDraw.group.silent = mpModel.get('silent') || seriesModel.get('silent'); + } +}); + +/** + * @inner + * @param {module:echarts/coord/*} [coordSys] + * @param {module:echarts/model/Series} seriesModel + * @param {module:echarts/model/Model} mpModel + */ +function createList$1(coordSys, seriesModel, mpModel) { + var coordDimsInfos; + if (coordSys) { + coordDimsInfos = map(coordSys && coordSys.dimensions, function (coordDim) { + var info = seriesModel.getData().getDimensionInfo( + seriesModel.getData().mapDimension(coordDim) + ) || {}; + // In map series data don't have lng and lat dimension. Fallback to same with coordSys + return defaults({name: coordDim}, info); + }); + } + else { + coordDimsInfos = [{ + name: 'value', + type: 'float' + }]; + } + + var mpData = new List(coordDimsInfos, mpModel); + var dataOpt = map(mpModel.get('data'), curry( + dataTransform, seriesModel + )); + if (coordSys) { + dataOpt = filter( + dataOpt, curry(dataFilter$1, coordSys) + ); + } + + mpData.initData(dataOpt, null, + coordSys ? dimValueGetter : function (item) { + return item.value; + } + ); + + return mpData; +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +// HINT Markpoint can't be used too much +registerPreprocessor(function (opt) { + // Make sure markPoint component is enabled + opt.markPoint = opt.markPoint || {}; +}); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +MarkerModel.extend({ + + type: 'markLine', + + defaultOption: { + zlevel: 0, + z: 5, + + symbol: ['circle', 'arrow'], + symbolSize: [8, 16], + + //symbolRotate: 0, + + precision: 2, + tooltip: { + trigger: 'item' + }, + label: { + show: true, + position: 'end' + }, + lineStyle: { + type: 'dashed' + }, + emphasis: { + label: { + show: true + }, + lineStyle: { + width: 3 + } + }, + animationEasing: 'linear' + } +}); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var markLineTransform = function (seriesModel, coordSys, mlModel, item) { + var data = seriesModel.getData(); + // Special type markLine like 'min', 'max', 'average', 'median' + var mlType = item.type; + + if (!isArray(item) + && ( + mlType === 'min' || mlType === 'max' || mlType === 'average' || mlType === 'median' + // In case + // data: [{ + // yAxis: 10 + // }] + || (item.xAxis != null || item.yAxis != null) + ) + ) { + var valueAxis; + var valueDataDim; + var value; + + if (item.yAxis != null || item.xAxis != null) { + valueDataDim = item.yAxis != null ? 'y' : 'x'; + valueAxis = coordSys.getAxis(valueDataDim); + + value = retrieve(item.yAxis, item.xAxis); + } + else { + var axisInfo = getAxisInfo$1(item, data, coordSys, seriesModel); + valueDataDim = axisInfo.valueDataDim; + valueAxis = axisInfo.valueAxis; + value = numCalculate(data, valueDataDim, mlType); + } + var valueIndex = valueDataDim === 'x' ? 0 : 1; + var baseIndex = 1 - valueIndex; + + var mlFrom = clone(item); + var mlTo = {}; + + mlFrom.type = null; + + mlFrom.coord = []; + mlTo.coord = []; + mlFrom.coord[baseIndex] = -Infinity; + mlTo.coord[baseIndex] = Infinity; + + var precision = mlModel.get('precision'); + if (precision >= 0 && typeof value === 'number') { + value = +value.toFixed(Math.min(precision, 20)); + } + + mlFrom.coord[valueIndex] = mlTo.coord[valueIndex] = value; + + item = [mlFrom, mlTo, { // Extra option for tooltip and label + type: mlType, + valueIndex: item.valueIndex, + // Force to use the value of calculated value. + value: value + }]; + } + + item = [ + dataTransform(seriesModel, item[0]), + dataTransform(seriesModel, item[1]), + extend({}, item[2]) + ]; + + // Avoid line data type is extended by from(to) data type + item[2].type = item[2].type || ''; + + // Merge from option and to option into line option + merge(item[2], item[0]); + merge(item[2], item[1]); + + return item; +}; + +function isInifinity(val) { + return !isNaN(val) && !isFinite(val); +} + +// If a markLine has one dim +function ifMarkLineHasOnlyDim(dimIndex, fromCoord, toCoord, coordSys) { + var otherDimIndex = 1 - dimIndex; + var dimName = coordSys.dimensions[dimIndex]; + return isInifinity(fromCoord[otherDimIndex]) && isInifinity(toCoord[otherDimIndex]) + && fromCoord[dimIndex] === toCoord[dimIndex] && coordSys.getAxis(dimName).containData(fromCoord[dimIndex]); +} + +function markLineFilter(coordSys, item) { + if (coordSys.type === 'cartesian2d') { + var fromCoord = item[0].coord; + var toCoord = item[1].coord; + // In case + // { + // markLine: { + // data: [{ yAxis: 2 }] + // } + // } + if ( + fromCoord && toCoord + && (ifMarkLineHasOnlyDim(1, fromCoord, toCoord, coordSys) + || ifMarkLineHasOnlyDim(0, fromCoord, toCoord, coordSys)) + ) { + return true; + } + } + return dataFilter$1(coordSys, item[0]) + && dataFilter$1(coordSys, item[1]); +} + +function updateSingleMarkerEndLayout( + data, idx, isFrom, seriesModel, api +) { + var coordSys = seriesModel.coordinateSystem; + var itemModel = data.getItemModel(idx); + + var point; + var xPx = parsePercent$1(itemModel.get('x'), api.getWidth()); + var yPx = parsePercent$1(itemModel.get('y'), api.getHeight()); + if (!isNaN(xPx) && !isNaN(yPx)) { + point = [xPx, yPx]; + } + else { + // Chart like bar may have there own marker positioning logic + if (seriesModel.getMarkerPosition) { + // Use the getMarkerPoisition + point = seriesModel.getMarkerPosition( + data.getValues(data.dimensions, idx) + ); + } + else { + var dims = coordSys.dimensions; + var x = data.get(dims[0], idx); + var y = data.get(dims[1], idx); + point = coordSys.dataToPoint([x, y]); + } + // Expand line to the edge of grid if value on one axis is Inifnity + // In case + // markLine: { + // data: [{ + // yAxis: 2 + // // or + // type: 'average' + // }] + // } + if (coordSys.type === 'cartesian2d') { + var xAxis = coordSys.getAxis('x'); + var yAxis = coordSys.getAxis('y'); + var dims = coordSys.dimensions; + if (isInifinity(data.get(dims[0], idx))) { + point[0] = xAxis.toGlobalCoord(xAxis.getExtent()[isFrom ? 0 : 1]); + } + else if (isInifinity(data.get(dims[1], idx))) { + point[1] = yAxis.toGlobalCoord(yAxis.getExtent()[isFrom ? 0 : 1]); + } + } + + // Use x, y if has any + if (!isNaN(xPx)) { + point[0] = xPx; + } + if (!isNaN(yPx)) { + point[1] = yPx; + } + } + + data.setItemLayout(idx, point); +} + +MarkerView.extend({ + + type: 'markLine', + + // updateLayout: function (markLineModel, ecModel, api) { + // ecModel.eachSeries(function (seriesModel) { + // var mlModel = seriesModel.markLineModel; + // if (mlModel) { + // var mlData = mlModel.getData(); + // var fromData = mlModel.__from; + // var toData = mlModel.__to; + // // Update visual and layout of from symbol and to symbol + // fromData.each(function (idx) { + // updateSingleMarkerEndLayout(fromData, idx, true, seriesModel, api); + // updateSingleMarkerEndLayout(toData, idx, false, seriesModel, api); + // }); + // // Update layout of line + // mlData.each(function (idx) { + // mlData.setItemLayout(idx, [ + // fromData.getItemLayout(idx), + // toData.getItemLayout(idx) + // ]); + // }); + + // this.markerGroupMap.get(seriesModel.id).updateLayout(); + + // } + // }, this); + // }, + + updateTransform: function (markLineModel, ecModel, api) { + ecModel.eachSeries(function (seriesModel) { + var mlModel = seriesModel.markLineModel; + if (mlModel) { + var mlData = mlModel.getData(); + var fromData = mlModel.__from; + var toData = mlModel.__to; + // Update visual and layout of from symbol and to symbol + fromData.each(function (idx) { + updateSingleMarkerEndLayout(fromData, idx, true, seriesModel, api); + updateSingleMarkerEndLayout(toData, idx, false, seriesModel, api); + }); + // Update layout of line + mlData.each(function (idx) { + mlData.setItemLayout(idx, [ + fromData.getItemLayout(idx), + toData.getItemLayout(idx) + ]); + }); + + this.markerGroupMap.get(seriesModel.id).updateLayout(); + + } + }, this); + }, + + renderSeries: function (seriesModel, mlModel, ecModel, api) { + var coordSys = seriesModel.coordinateSystem; + var seriesId = seriesModel.id; + var seriesData = seriesModel.getData(); + + var lineDrawMap = this.markerGroupMap; + var lineDraw = lineDrawMap.get(seriesId) + || lineDrawMap.set(seriesId, new LineDraw()); + this.group.add(lineDraw.group); + + var mlData = createList$2(coordSys, seriesModel, mlModel); + + var fromData = mlData.from; + var toData = mlData.to; + var lineData = mlData.line; + + mlModel.__from = fromData; + mlModel.__to = toData; + // Line data for tooltip and formatter + mlModel.setData(lineData); + + var symbolType = mlModel.get('symbol'); + var symbolSize = mlModel.get('symbolSize'); + if (!isArray(symbolType)) { + symbolType = [symbolType, symbolType]; + } + if (typeof symbolSize === 'number') { + symbolSize = [symbolSize, symbolSize]; + } + + // Update visual and layout of from symbol and to symbol + mlData.from.each(function (idx) { + updateDataVisualAndLayout(fromData, idx, true); + updateDataVisualAndLayout(toData, idx, false); + }); + + // Update visual and layout of line + lineData.each(function (idx) { + var lineColor = lineData.getItemModel(idx).get('lineStyle.color'); + lineData.setItemVisual(idx, { + color: lineColor || fromData.getItemVisual(idx, 'color') + }); + lineData.setItemLayout(idx, [ + fromData.getItemLayout(idx), + toData.getItemLayout(idx) + ]); + + lineData.setItemVisual(idx, { + 'fromSymbolSize': fromData.getItemVisual(idx, 'symbolSize'), + 'fromSymbol': fromData.getItemVisual(idx, 'symbol'), + 'toSymbolSize': toData.getItemVisual(idx, 'symbolSize'), + 'toSymbol': toData.getItemVisual(idx, 'symbol') + }); + }); + + lineDraw.updateData(lineData); + + // Set host model for tooltip + // FIXME + mlData.line.eachItemGraphicEl(function (el, idx) { + el.traverse(function (child) { + child.dataModel = mlModel; + }); + }); + + function updateDataVisualAndLayout(data, idx, isFrom) { + var itemModel = data.getItemModel(idx); + + updateSingleMarkerEndLayout( + data, idx, isFrom, seriesModel, api + ); + + data.setItemVisual(idx, { + symbolSize: itemModel.get('symbolSize') || symbolSize[isFrom ? 0 : 1], + symbol: itemModel.get('symbol', true) || symbolType[isFrom ? 0 : 1], + color: itemModel.get('itemStyle.color') || seriesData.getVisual('color') + }); + } + + lineDraw.__keep = true; + + lineDraw.group.silent = mlModel.get('silent') || seriesModel.get('silent'); + } +}); + +/** + * @inner + * @param {module:echarts/coord/*} coordSys + * @param {module:echarts/model/Series} seriesModel + * @param {module:echarts/model/Model} mpModel + */ +function createList$2(coordSys, seriesModel, mlModel) { + + var coordDimsInfos; + if (coordSys) { + coordDimsInfos = map(coordSys && coordSys.dimensions, function (coordDim) { + var info = seriesModel.getData().getDimensionInfo( + seriesModel.getData().mapDimension(coordDim) + ) || {}; + // In map series data don't have lng and lat dimension. Fallback to same with coordSys + return defaults({name: coordDim}, info); + }); + } + else { + coordDimsInfos = [{ + name: 'value', + type: 'float' + }]; + } + + var fromData = new List(coordDimsInfos, mlModel); + var toData = new List(coordDimsInfos, mlModel); + // No dimensions + var lineData = new List([], mlModel); + + var optData = map(mlModel.get('data'), curry( + markLineTransform, seriesModel, coordSys, mlModel + )); + if (coordSys) { + optData = filter( + optData, curry(markLineFilter, coordSys) + ); + } + var dimValueGetter$$1 = coordSys ? dimValueGetter : function (item) { + return item.value; + }; + fromData.initData( + map(optData, function (item) { + return item[0]; + }), + null, + dimValueGetter$$1 + ); + toData.initData( + map(optData, function (item) { + return item[1]; + }), + null, + dimValueGetter$$1 + ); + lineData.initData( + map(optData, function (item) { + return item[2]; + }) + ); + lineData.hasItemOption = true; + + return { + from: fromData, + to: toData, + line: lineData + }; +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +registerPreprocessor(function (opt) { + // Make sure markLine component is enabled + opt.markLine = opt.markLine || {}; +}); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +MarkerModel.extend({ + + type: 'markArea', + + defaultOption: { + zlevel: 0, + // PENDING + z: 1, + tooltip: { + trigger: 'item' + }, + // markArea should fixed on the coordinate system + animation: false, + label: { + show: true, + position: 'top' + }, + itemStyle: { + // color and borderColor default to use color from series + // color: 'auto' + // borderColor: 'auto' + borderWidth: 0 + }, + + emphasis: { + label: { + show: true, + position: 'top' + } + } + } +}); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +// TODO Better on polar + +var markAreaTransform = function (seriesModel, coordSys, maModel, item) { + var lt = dataTransform(seriesModel, item[0]); + var rb = dataTransform(seriesModel, item[1]); + var retrieve$$1 = retrieve; + + // FIXME make sure lt is less than rb + var ltCoord = lt.coord; + var rbCoord = rb.coord; + ltCoord[0] = retrieve$$1(ltCoord[0], -Infinity); + ltCoord[1] = retrieve$$1(ltCoord[1], -Infinity); + + rbCoord[0] = retrieve$$1(rbCoord[0], Infinity); + rbCoord[1] = retrieve$$1(rbCoord[1], Infinity); + + // Merge option into one + var result = mergeAll([{}, lt, rb]); + + result.coord = [ + lt.coord, rb.coord + ]; + result.x0 = lt.x; + result.y0 = lt.y; + result.x1 = rb.x; + result.y1 = rb.y; + return result; +}; + +function isInifinity$1(val) { + return !isNaN(val) && !isFinite(val); +} + +// If a markArea has one dim +function ifMarkLineHasOnlyDim$1(dimIndex, fromCoord, toCoord, coordSys) { + var otherDimIndex = 1 - dimIndex; + return isInifinity$1(fromCoord[otherDimIndex]) && isInifinity$1(toCoord[otherDimIndex]); +} + +function markAreaFilter(coordSys, item) { + var fromCoord = item.coord[0]; + var toCoord = item.coord[1]; + if (coordSys.type === 'cartesian2d') { + // In case + // { + // markArea: { + // data: [{ yAxis: 2 }] + // } + // } + if ( + fromCoord && toCoord + && (ifMarkLineHasOnlyDim$1(1, fromCoord, toCoord, coordSys) + || ifMarkLineHasOnlyDim$1(0, fromCoord, toCoord, coordSys)) + ) { + return true; + } + } + return dataFilter$1(coordSys, { + coord: fromCoord, + x: item.x0, + y: item.y0 + }) + || dataFilter$1(coordSys, { + coord: toCoord, + x: item.x1, + y: item.y1 + }); +} + +// dims can be ['x0', 'y0'], ['x1', 'y1'], ['x0', 'y1'], ['x1', 'y0'] +function getSingleMarkerEndPoint(data, idx, dims, seriesModel, api) { + var coordSys = seriesModel.coordinateSystem; + var itemModel = data.getItemModel(idx); + + var point; + var xPx = parsePercent$1(itemModel.get(dims[0]), api.getWidth()); + var yPx = parsePercent$1(itemModel.get(dims[1]), api.getHeight()); + if (!isNaN(xPx) && !isNaN(yPx)) { + point = [xPx, yPx]; + } + else { + // Chart like bar may have there own marker positioning logic + if (seriesModel.getMarkerPosition) { + // Use the getMarkerPoisition + point = seriesModel.getMarkerPosition( + data.getValues(dims, idx) + ); + } + else { + var x = data.get(dims[0], idx); + var y = data.get(dims[1], idx); + var pt = [x, y]; + coordSys.clampData && coordSys.clampData(pt, pt); + point = coordSys.dataToPoint(pt, true); + } + if (coordSys.type === 'cartesian2d') { + var xAxis = coordSys.getAxis('x'); + var yAxis = coordSys.getAxis('y'); + var x = data.get(dims[0], idx); + var y = data.get(dims[1], idx); + if (isInifinity$1(x)) { + point[0] = xAxis.toGlobalCoord(xAxis.getExtent()[dims[0] === 'x0' ? 0 : 1]); + } + else if (isInifinity$1(y)) { + point[1] = yAxis.toGlobalCoord(yAxis.getExtent()[dims[1] === 'y0' ? 0 : 1]); + } + } + + // Use x, y if has any + if (!isNaN(xPx)) { + point[0] = xPx; + } + if (!isNaN(yPx)) { + point[1] = yPx; + } + } + + return point; +} + +var dimPermutations = [['x0', 'y0'], ['x1', 'y0'], ['x1', 'y1'], ['x0', 'y1']]; + +MarkerView.extend({ + + type: 'markArea', + + // updateLayout: function (markAreaModel, ecModel, api) { + // ecModel.eachSeries(function (seriesModel) { + // var maModel = seriesModel.markAreaModel; + // if (maModel) { + // var areaData = maModel.getData(); + // areaData.each(function (idx) { + // var points = zrUtil.map(dimPermutations, function (dim) { + // return getSingleMarkerEndPoint(areaData, idx, dim, seriesModel, api); + // }); + // // Layout + // areaData.setItemLayout(idx, points); + // var el = areaData.getItemGraphicEl(idx); + // el.setShape('points', points); + // }); + // } + // }, this); + // }, + + updateTransform: function (markAreaModel, ecModel, api) { + ecModel.eachSeries(function (seriesModel) { + var maModel = seriesModel.markAreaModel; + if (maModel) { + var areaData = maModel.getData(); + areaData.each(function (idx) { + var points = map(dimPermutations, function (dim) { + return getSingleMarkerEndPoint(areaData, idx, dim, seriesModel, api); + }); + // Layout + areaData.setItemLayout(idx, points); + var el = areaData.getItemGraphicEl(idx); + el.setShape('points', points); + }); + } + }, this); + }, + + renderSeries: function (seriesModel, maModel, ecModel, api) { + var coordSys = seriesModel.coordinateSystem; + var seriesId = seriesModel.id; + var seriesData = seriesModel.getData(); + + var areaGroupMap = this.markerGroupMap; + var polygonGroup = areaGroupMap.get(seriesId) + || areaGroupMap.set(seriesId, {group: new Group()}); + + this.group.add(polygonGroup.group); + polygonGroup.__keep = true; + + var areaData = createList$3(coordSys, seriesModel, maModel); + + // Line data for tooltip and formatter + maModel.setData(areaData); + + // Update visual and layout of line + areaData.each(function (idx) { + // Layout + areaData.setItemLayout(idx, map(dimPermutations, function (dim) { + return getSingleMarkerEndPoint(areaData, idx, dim, seriesModel, api); + })); + + // Visual + areaData.setItemVisual(idx, { + color: seriesData.getVisual('color') + }); + }); + + + areaData.diff(polygonGroup.__data) + .add(function (idx) { + var polygon = new Polygon({ + shape: { + points: areaData.getItemLayout(idx) + } + }); + areaData.setItemGraphicEl(idx, polygon); + polygonGroup.group.add(polygon); + }) + .update(function (newIdx, oldIdx) { + var polygon = polygonGroup.__data.getItemGraphicEl(oldIdx); + updateProps(polygon, { + shape: { + points: areaData.getItemLayout(newIdx) + } + }, maModel, newIdx); + polygonGroup.group.add(polygon); + areaData.setItemGraphicEl(newIdx, polygon); + }) + .remove(function (idx) { + var polygon = polygonGroup.__data.getItemGraphicEl(idx); + polygonGroup.group.remove(polygon); + }) + .execute(); + + areaData.eachItemGraphicEl(function (polygon, idx) { + var itemModel = areaData.getItemModel(idx); + var labelModel = itemModel.getModel('label'); + var labelHoverModel = itemModel.getModel('emphasis.label'); + var color = areaData.getItemVisual(idx, 'color'); + polygon.useStyle( + defaults( + itemModel.getModel('itemStyle').getItemStyle(), + { + fill: modifyAlpha(color, 0.4), + stroke: color + } + ) + ); + + polygon.hoverStyle = itemModel.getModel('emphasis.itemStyle').getItemStyle(); + + setLabelStyle( + polygon.style, polygon.hoverStyle, labelModel, labelHoverModel, + { + labelFetcher: maModel, + labelDataIndex: idx, + defaultText: areaData.getName(idx) || '', + isRectText: true, + autoColor: color + } + ); + + setHoverStyle(polygon, {}); + + polygon.dataModel = maModel; + }); + + polygonGroup.__data = areaData; + + polygonGroup.group.silent = maModel.get('silent') || seriesModel.get('silent'); + } +}); + +/** + * @inner + * @param {module:echarts/coord/*} coordSys + * @param {module:echarts/model/Series} seriesModel + * @param {module:echarts/model/Model} mpModel + */ +function createList$3(coordSys, seriesModel, maModel) { + + var coordDimsInfos; + var areaData; + var dims = ['x0', 'y0', 'x1', 'y1']; + if (coordSys) { + coordDimsInfos = map(coordSys && coordSys.dimensions, function (coordDim) { + var data = seriesModel.getData(); + var info = data.getDimensionInfo( + data.mapDimension(coordDim) + ) || {}; + // In map series data don't have lng and lat dimension. Fallback to same with coordSys + return defaults({name: coordDim}, info); + }); + areaData = new List(map(dims, function (dim, idx) { + return { + name: dim, + type: coordDimsInfos[idx % 2].type + }; + }), maModel); + } + else { + coordDimsInfos = [{ + name: 'value', + type: 'float' + }]; + areaData = new List(coordDimsInfos, maModel); + } + + var optData = map(maModel.get('data'), curry( + markAreaTransform, seriesModel, coordSys, maModel + )); + if (coordSys) { + optData = filter( + optData, curry(markAreaFilter, coordSys) + ); + } + + var dimValueGetter$$1 = coordSys ? function (item, dimName, dataIndex, dimIndex) { + return item.coord[Math.floor(dimIndex / 2)][dimIndex % 2]; + } : function (item) { + return item.value; + }; + areaData.initData(optData, null, dimValueGetter$$1); + areaData.hasItemOption = true; + return areaData; +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +registerPreprocessor(function (opt) { + // Make sure markArea component is enabled + opt.markArea = opt.markArea || {}; +}); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var preprocessor$3 = function (option) { + var timelineOpt = option && option.timeline; + + if (!isArray(timelineOpt)) { + timelineOpt = timelineOpt ? [timelineOpt] : []; + } + + each$1(timelineOpt, function (opt) { + if (!opt) { + return; + } + + compatibleEC2(opt); + }); +}; + +function compatibleEC2(opt) { + var type = opt.type; + + var ec2Types = {'number': 'value', 'time': 'time'}; + + // Compatible with ec2 + if (ec2Types[type]) { + opt.axisType = ec2Types[type]; + delete opt.type; + } + + transferItem(opt); + + if (has$2(opt, 'controlPosition')) { + var controlStyle = opt.controlStyle || (opt.controlStyle = {}); + if (!has$2(controlStyle, 'position')) { + controlStyle.position = opt.controlPosition; + } + if (controlStyle.position === 'none' && !has$2(controlStyle, 'show')) { + controlStyle.show = false; + delete controlStyle.position; + } + delete opt.controlPosition; + } + + each$1(opt.data || [], function (dataItem) { + if (isObject$1(dataItem) && !isArray(dataItem)) { + if (!has$2(dataItem, 'value') && has$2(dataItem, 'name')) { + // In ec2, using name as value. + dataItem.value = dataItem.name; + } + transferItem(dataItem); + } + }); +} + +function transferItem(opt) { + var itemStyle = opt.itemStyle || (opt.itemStyle = {}); + + var itemStyleEmphasis = itemStyle.emphasis || (itemStyle.emphasis = {}); + + // Transfer label out + var label = opt.label || (opt.label || {}); + var labelNormal = label.normal || (label.normal = {}); + var excludeLabelAttr = {normal: 1, emphasis: 1}; + + each$1(label, function (value, name) { + if (!excludeLabelAttr[name] && !has$2(labelNormal, name)) { + labelNormal[name] = value; + } + }); + + if (itemStyleEmphasis.label && !has$2(label, 'emphasis')) { + label.emphasis = itemStyleEmphasis.label; + delete itemStyleEmphasis.label; + } +} + +function has$2(obj, attr) { + return obj.hasOwnProperty(attr); +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +ComponentModel.registerSubTypeDefaulter('timeline', function () { + // Only slider now. + return 'slider'; +}); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +registerAction( + + {type: 'timelineChange', event: 'timelineChanged', update: 'prepareAndUpdate'}, + + function (payload, ecModel) { + + var timelineModel = ecModel.getComponent('timeline'); + if (timelineModel && payload.currentIndex != null) { + timelineModel.setCurrentIndex(payload.currentIndex); + + if (!timelineModel.get('loop', true) && timelineModel.isIndexMax()) { + timelineModel.setPlayState(false); + } + } + + // Set normalized currentIndex to payload. + ecModel.resetOption('timeline'); + + return defaults({ + currentIndex: timelineModel.option.currentIndex + }, payload); + } +); + +registerAction( + + {type: 'timelinePlayChange', event: 'timelinePlayChanged', update: 'update'}, + + function (payload, ecModel) { + var timelineModel = ecModel.getComponent('timeline'); + if (timelineModel && payload.playState != null) { + timelineModel.setPlayState(payload.playState); + } + } +); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var TimelineModel = ComponentModel.extend({ + + type: 'timeline', + + layoutMode: 'box', + + /** + * @protected + */ + defaultOption: { + + zlevel: 0, // 一级层叠 + z: 4, // 二级层叠 + show: true, + + axisType: 'time', // 模式是时间类型,支持 value, category + + realtime: true, + + left: '20%', + top: null, + right: '20%', + bottom: 0, + width: null, + height: 40, + padding: 5, + + controlPosition: 'left', // 'left' 'right' 'top' 'bottom' 'none' + autoPlay: false, + rewind: false, // 反向播放 + loop: true, + playInterval: 2000, // 播放时间间隔,单位ms + + currentIndex: 0, + + itemStyle: {}, + label: { + color: '#000' + }, + + data: [] + }, + + /** + * @override + */ + init: function (option, parentModel, ecModel) { + + /** + * @private + * @type {module:echarts/data/List} + */ + this._data; + + /** + * @private + * @type {Array.} + */ + this._names; + + this.mergeDefaultAndTheme(option, ecModel); + this._initData(); + }, + + /** + * @override + */ + mergeOption: function (option) { + TimelineModel.superApply(this, 'mergeOption', arguments); + this._initData(); + }, + + /** + * @param {number} [currentIndex] + */ + setCurrentIndex: function (currentIndex) { + if (currentIndex == null) { + currentIndex = this.option.currentIndex; + } + var count = this._data.count(); + + if (this.option.loop) { + currentIndex = (currentIndex % count + count) % count; + } + else { + currentIndex >= count && (currentIndex = count - 1); + currentIndex < 0 && (currentIndex = 0); + } + + this.option.currentIndex = currentIndex; + }, + + /** + * @return {number} currentIndex + */ + getCurrentIndex: function () { + return this.option.currentIndex; + }, + + /** + * @return {boolean} + */ + isIndexMax: function () { + return this.getCurrentIndex() >= this._data.count() - 1; + }, + + /** + * @param {boolean} state true: play, false: stop + */ + setPlayState: function (state) { + this.option.autoPlay = !!state; + }, + + /** + * @return {boolean} true: play, false: stop + */ + getPlayState: function () { + return !!this.option.autoPlay; + }, + + /** + * @private + */ + _initData: function () { + var thisOption = this.option; + var dataArr = thisOption.data || []; + var axisType = thisOption.axisType; + var names = this._names = []; + + if (axisType === 'category') { + var idxArr = []; + each$1(dataArr, function (item, index) { + var value = getDataItemValue(item); + var newItem; + + if (isObject$1(item)) { + newItem = clone(item); + newItem.value = index; + } + else { + newItem = index; + } + + idxArr.push(newItem); + + if (!isString(value) && (value == null || isNaN(value))) { + value = ''; + } + + names.push(value + ''); + }); + dataArr = idxArr; + } + + var dimType = ({category: 'ordinal', time: 'time'})[axisType] || 'number'; + + var data = this._data = new List([{name: 'value', type: dimType}], this); + + data.initData(dataArr, names); + }, + + getData: function () { + return this._data; + }, + + /** + * @public + * @return {Array.} categoreis + */ + getCategories: function () { + if (this.get('axisType') === 'category') { + return this._names.slice(); + } + } + +}); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var SliderTimelineModel = TimelineModel.extend({ + + type: 'timeline.slider', + + /** + * @protected + */ + defaultOption: { + + backgroundColor: 'rgba(0,0,0,0)', // 时间轴背景颜色 + borderColor: '#ccc', // 时间轴边框颜色 + borderWidth: 0, // 时间轴边框线宽,单位px,默认为0(无边框) + + orient: 'horizontal', // 'vertical' + inverse: false, + + tooltip: { // boolean or Object + trigger: 'item' // data item may also have tootip attr. + }, + + symbol: 'emptyCircle', + symbolSize: 10, + + lineStyle: { + show: true, + width: 2, + color: '#304654' + }, + label: { // 文本标签 + position: 'auto', // auto left right top bottom + // When using number, label position is not + // restricted by viewRect. + // positive: right/bottom, negative: left/top + show: true, + interval: 'auto', + rotate: 0, + // formatter: null, + // 其余属性默认使用全局文本样式,详见TEXTSTYLE + color: '#304654' + }, + itemStyle: { + color: '#304654', + borderWidth: 1 + }, + + checkpointStyle: { + symbol: 'circle', + symbolSize: 13, + color: '#c23531', + borderWidth: 5, + borderColor: 'rgba(194,53,49, 0.5)', + animation: true, + animationDuration: 300, + animationEasing: 'quinticInOut' + }, + + controlStyle: { + show: true, + showPlayBtn: true, + showPrevBtn: true, + showNextBtn: true, + itemSize: 22, + itemGap: 12, + position: 'left', // 'left' 'right' 'top' 'bottom' + playIcon: 'path://M31.6,53C17.5,53,6,41.5,6,27.4S17.5,1.8,31.6,1.8C45.7,1.8,57.2,13.3,57.2,27.4S45.7,53,31.6,53z M31.6,3.3 C18.4,3.3,7.5,14.1,7.5,27.4c0,13.3,10.8,24.1,24.1,24.1C44.9,51.5,55.7,40.7,55.7,27.4C55.7,14.1,44.9,3.3,31.6,3.3z M24.9,21.3 c0-2.2,1.6-3.1,3.5-2l10.5,6.1c1.899,1.1,1.899,2.9,0,4l-10.5,6.1c-1.9,1.1-3.5,0.2-3.5-2V21.3z', // jshint ignore:line + stopIcon: 'path://M30.9,53.2C16.8,53.2,5.3,41.7,5.3,27.6S16.8,2,30.9,2C45,2,56.4,13.5,56.4,27.6S45,53.2,30.9,53.2z M30.9,3.5C17.6,3.5,6.8,14.4,6.8,27.6c0,13.3,10.8,24.1,24.101,24.1C44.2,51.7,55,40.9,55,27.6C54.9,14.4,44.1,3.5,30.9,3.5z M36.9,35.8c0,0.601-0.4,1-0.9,1h-1.3c-0.5,0-0.9-0.399-0.9-1V19.5c0-0.6,0.4-1,0.9-1H36c0.5,0,0.9,0.4,0.9,1V35.8z M27.8,35.8 c0,0.601-0.4,1-0.9,1h-1.3c-0.5,0-0.9-0.399-0.9-1V19.5c0-0.6,0.4-1,0.9-1H27c0.5,0,0.9,0.4,0.9,1L27.8,35.8L27.8,35.8z', // jshint ignore:line + nextIcon: 'path://M18.6,50.8l22.5-22.5c0.2-0.2,0.3-0.4,0.3-0.7c0-0.3-0.1-0.5-0.3-0.7L18.7,4.4c-0.1-0.1-0.2-0.3-0.2-0.5 c0-0.4,0.3-0.8,0.8-0.8c0.2,0,0.5,0.1,0.6,0.3l23.5,23.5l0,0c0.2,0.2,0.3,0.4,0.3,0.7c0,0.3-0.1,0.5-0.3,0.7l-0.1,0.1L19.7,52 c-0.1,0.1-0.3,0.2-0.5,0.2c-0.4,0-0.8-0.3-0.8-0.8C18.4,51.2,18.5,51,18.6,50.8z', // jshint ignore:line + prevIcon: 'path://M43,52.8L20.4,30.3c-0.2-0.2-0.3-0.4-0.3-0.7c0-0.3,0.1-0.5,0.3-0.7L42.9,6.4c0.1-0.1,0.2-0.3,0.2-0.5 c0-0.4-0.3-0.8-0.8-0.8c-0.2,0-0.5,0.1-0.6,0.3L18.3,28.8l0,0c-0.2,0.2-0.3,0.4-0.3,0.7c0,0.3,0.1,0.5,0.3,0.7l0.1,0.1L41.9,54 c0.1,0.1,0.3,0.2,0.5,0.2c0.4,0,0.8-0.3,0.8-0.8C43.2,53.2,43.1,53,43,52.8z', // jshint ignore:line + + color: '#304654', + borderColor: '#304654', + borderWidth: 1 + }, + + emphasis: { + label: { + show: true, + // 其余属性默认使用全局文本样式,详见TEXTSTYLE + color: '#c23531' + }, + + itemStyle: { + color: '#c23531' + }, + + controlStyle: { + color: '#c23531', + borderColor: '#c23531', + borderWidth: 2 + } + }, + data: [] + } + +}); + +mixin(SliderTimelineModel, dataFormatMixin); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var TimelineView = Component.extend({ + type: 'timeline' +}); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/** + * Extend axis 2d + * @constructor module:echarts/coord/cartesian/Axis2D + * @extends {module:echarts/coord/cartesian/Axis} + * @param {string} dim + * @param {*} scale + * @param {Array.} coordExtent + * @param {string} axisType + * @param {string} position + */ +var TimelineAxis = function (dim, scale, coordExtent, axisType) { + + Axis.call(this, dim, scale, coordExtent); + + /** + * Axis type + * - 'category' + * - 'value' + * - 'time' + * - 'log' + * @type {string} + */ + this.type = axisType || 'value'; + + /** + * Axis model + * @param {module:echarts/component/TimelineModel} + */ + this.model = null; +}; + +TimelineAxis.prototype = { + + constructor: TimelineAxis, + + /** + * @override + */ + getLabelModel: function () { + return this.model.getModel('label'); + }, + + /** + * @override + */ + isHorizontal: function () { + return this.model.get('orient') === 'horizontal'; + } + +}; + +inherits(TimelineAxis, Axis); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var bind$6 = bind; +var each$27 = each$1; + +var PI$4 = Math.PI; + +TimelineView.extend({ + + type: 'timeline.slider', + + init: function (ecModel, api) { + + this.api = api; + + /** + * @private + * @type {module:echarts/component/timeline/TimelineAxis} + */ + this._axis; + + /** + * @private + * @type {module:zrender/core/BoundingRect} + */ + this._viewRect; + + /** + * @type {number} + */ + this._timer; + + /** + * @type {module:zrender/Element} + */ + this._currentPointer; + + /** + * @type {module:zrender/container/Group} + */ + this._mainGroup; + + /** + * @type {module:zrender/container/Group} + */ + this._labelGroup; + }, + + /** + * @override + */ + render: function (timelineModel, ecModel, api, payload) { + this.model = timelineModel; + this.api = api; + this.ecModel = ecModel; + + this.group.removeAll(); + + if (timelineModel.get('show', true)) { + + var layoutInfo = this._layout(timelineModel, api); + var mainGroup = this._createGroup('mainGroup'); + var labelGroup = this._createGroup('labelGroup'); + + /** + * @private + * @type {module:echarts/component/timeline/TimelineAxis} + */ + var axis = this._axis = this._createAxis(layoutInfo, timelineModel); + + timelineModel.formatTooltip = function (dataIndex) { + return encodeHTML(axis.scale.getLabel(dataIndex)); + }; + + each$27( + ['AxisLine', 'AxisTick', 'Control', 'CurrentPointer'], + function (name) { + this['_render' + name](layoutInfo, mainGroup, axis, timelineModel); + }, + this + ); + + this._renderAxisLabel(layoutInfo, labelGroup, axis, timelineModel); + this._position(layoutInfo, timelineModel); + } + + this._doPlayStop(); + }, + + /** + * @override + */ + remove: function () { + this._clearTimer(); + this.group.removeAll(); + }, + + /** + * @override + */ + dispose: function () { + this._clearTimer(); + }, + + _layout: function (timelineModel, api) { + var labelPosOpt = timelineModel.get('label.position'); + var orient = timelineModel.get('orient'); + var viewRect = getViewRect$4(timelineModel, api); + // Auto label offset. + if (labelPosOpt == null || labelPosOpt === 'auto') { + labelPosOpt = orient === 'horizontal' + ? ((viewRect.y + viewRect.height / 2) < api.getHeight() / 2 ? '-' : '+') + : ((viewRect.x + viewRect.width / 2) < api.getWidth() / 2 ? '+' : '-'); + } + else if (isNaN(labelPosOpt)) { + labelPosOpt = ({ + horizontal: {top: '-', bottom: '+'}, + vertical: {left: '-', right: '+'} + })[orient][labelPosOpt]; + } + + var labelAlignMap = { + horizontal: 'center', + vertical: (labelPosOpt >= 0 || labelPosOpt === '+') ? 'left' : 'right' + }; + + var labelBaselineMap = { + horizontal: (labelPosOpt >= 0 || labelPosOpt === '+') ? 'top' : 'bottom', + vertical: 'middle' + }; + var rotationMap = { + horizontal: 0, + vertical: PI$4 / 2 + }; + + // Position + var mainLength = orient === 'vertical' ? viewRect.height : viewRect.width; + + var controlModel = timelineModel.getModel('controlStyle'); + var showControl = controlModel.get('show', true); + var controlSize = showControl ? controlModel.get('itemSize') : 0; + var controlGap = showControl ? controlModel.get('itemGap') : 0; + var sizePlusGap = controlSize + controlGap; + + // Special label rotate. + var labelRotation = timelineModel.get('label.rotate') || 0; + labelRotation = labelRotation * PI$4 / 180; // To radian. + + var playPosition; + var prevBtnPosition; + var nextBtnPosition; + var axisExtent; + var controlPosition = controlModel.get('position', true); + var showPlayBtn = showControl && controlModel.get('showPlayBtn', true); + var showPrevBtn = showControl && controlModel.get('showPrevBtn', true); + var showNextBtn = showControl && controlModel.get('showNextBtn', true); + var xLeft = 0; + var xRight = mainLength; + + // position[0] means left, position[1] means middle. + if (controlPosition === 'left' || controlPosition === 'bottom') { + showPlayBtn && (playPosition = [0, 0], xLeft += sizePlusGap); + showPrevBtn && (prevBtnPosition = [xLeft, 0], xLeft += sizePlusGap); + showNextBtn && (nextBtnPosition = [xRight - controlSize, 0], xRight -= sizePlusGap); + } + else { // 'top' 'right' + showPlayBtn && (playPosition = [xRight - controlSize, 0], xRight -= sizePlusGap); + showPrevBtn && (prevBtnPosition = [0, 0], xLeft += sizePlusGap); + showNextBtn && (nextBtnPosition = [xRight - controlSize, 0], xRight -= sizePlusGap); + } + axisExtent = [xLeft, xRight]; + + if (timelineModel.get('inverse')) { + axisExtent.reverse(); + } + + return { + viewRect: viewRect, + mainLength: mainLength, + orient: orient, + + rotation: rotationMap[orient], + labelRotation: labelRotation, + labelPosOpt: labelPosOpt, + labelAlign: timelineModel.get('label.align') || labelAlignMap[orient], + labelBaseline: timelineModel.get('label.verticalAlign') + || timelineModel.get('label.baseline') + || labelBaselineMap[orient], + + // Based on mainGroup. + playPosition: playPosition, + prevBtnPosition: prevBtnPosition, + nextBtnPosition: nextBtnPosition, + axisExtent: axisExtent, + + controlSize: controlSize, + controlGap: controlGap + }; + }, + + _position: function (layoutInfo, timelineModel) { + // Position is be called finally, because bounding rect is needed for + // adapt content to fill viewRect (auto adapt offset). + + // Timeline may be not all in the viewRect when 'offset' is specified + // as a number, because it is more appropriate that label aligns at + // 'offset' but not the other edge defined by viewRect. + + var mainGroup = this._mainGroup; + var labelGroup = this._labelGroup; + + var viewRect = layoutInfo.viewRect; + if (layoutInfo.orient === 'vertical') { + // transform to horizontal, inverse rotate by left-top point. + var m = create$1(); + var rotateOriginX = viewRect.x; + var rotateOriginY = viewRect.y + viewRect.height; + translate(m, m, [-rotateOriginX, -rotateOriginY]); + rotate(m, m, -PI$4 / 2); + translate(m, m, [rotateOriginX, rotateOriginY]); + viewRect = viewRect.clone(); + viewRect.applyTransform(m); + } + + var viewBound = getBound(viewRect); + var mainBound = getBound(mainGroup.getBoundingRect()); + var labelBound = getBound(labelGroup.getBoundingRect()); + + var mainPosition = mainGroup.position; + var labelsPosition = labelGroup.position; + + labelsPosition[0] = mainPosition[0] = viewBound[0][0]; + + var labelPosOpt = layoutInfo.labelPosOpt; + + if (isNaN(labelPosOpt)) { // '+' or '-' + var mainBoundIdx = labelPosOpt === '+' ? 0 : 1; + toBound(mainPosition, mainBound, viewBound, 1, mainBoundIdx); + toBound(labelsPosition, labelBound, viewBound, 1, 1 - mainBoundIdx); + } + else { + var mainBoundIdx = labelPosOpt >= 0 ? 0 : 1; + toBound(mainPosition, mainBound, viewBound, 1, mainBoundIdx); + labelsPosition[1] = mainPosition[1] + labelPosOpt; + } + + mainGroup.attr('position', mainPosition); + labelGroup.attr('position', labelsPosition); + mainGroup.rotation = labelGroup.rotation = layoutInfo.rotation; + + setOrigin(mainGroup); + setOrigin(labelGroup); + + function setOrigin(targetGroup) { + var pos = targetGroup.position; + targetGroup.origin = [ + viewBound[0][0] - pos[0], + viewBound[1][0] - pos[1] + ]; + } + + function getBound(rect) { + // [[xmin, xmax], [ymin, ymax]] + return [ + [rect.x, rect.x + rect.width], + [rect.y, rect.y + rect.height] + ]; + } + + function toBound(fromPos, from, to, dimIdx, boundIdx) { + fromPos[dimIdx] += to[dimIdx][boundIdx] - from[dimIdx][boundIdx]; + } + }, + + _createAxis: function (layoutInfo, timelineModel) { + var data = timelineModel.getData(); + var axisType = timelineModel.get('axisType'); + + var scale = createScaleByModel(timelineModel, axisType); + + // Customize scale. The `tickValue` is `dataIndex`. + scale.getTicks = function () { + return data.mapArray(['value'], function (value) { + return value; + }); + }; + + var dataExtent = data.getDataExtent('value'); + scale.setExtent(dataExtent[0], dataExtent[1]); + scale.niceTicks(); + + var axis = new TimelineAxis('value', scale, layoutInfo.axisExtent, axisType); + axis.model = timelineModel; + + return axis; + }, + + _createGroup: function (name) { + var newGroup = this['_' + name] = new Group(); + this.group.add(newGroup); + return newGroup; + }, + + _renderAxisLine: function (layoutInfo, group, axis, timelineModel) { + var axisExtent = axis.getExtent(); + + if (!timelineModel.get('lineStyle.show')) { + return; + } + + group.add(new Line({ + shape: { + x1: axisExtent[0], y1: 0, + x2: axisExtent[1], y2: 0 + }, + style: extend( + {lineCap: 'round'}, + timelineModel.getModel('lineStyle').getLineStyle() + ), + silent: true, + z2: 1 + })); + }, + + /** + * @private + */ + _renderAxisTick: function (layoutInfo, group, axis, timelineModel) { + var data = timelineModel.getData(); + // Show all ticks, despite ignoring strategy. + var ticks = axis.scale.getTicks(); + + // The value is dataIndex, see the costomized scale. + each$27(ticks, function (value) { + var tickCoord = axis.dataToCoord(value); + var itemModel = data.getItemModel(value); + var itemStyleModel = itemModel.getModel('itemStyle'); + var hoverStyleModel = itemModel.getModel('emphasis.itemStyle'); + var symbolOpt = { + position: [tickCoord, 0], + onclick: bind$6(this._changeTimeline, this, value) + }; + var el = giveSymbol(itemModel, itemStyleModel, group, symbolOpt); + setHoverStyle(el, hoverStyleModel.getItemStyle()); + + if (itemModel.get('tooltip')) { + el.dataIndex = value; + el.dataModel = timelineModel; + } + else { + el.dataIndex = el.dataModel = null; + } + + }, this); + }, + + /** + * @private + */ + _renderAxisLabel: function (layoutInfo, group, axis, timelineModel) { + var labelModel = axis.getLabelModel(); + + if (!labelModel.get('show')) { + return; + } + + var data = timelineModel.getData(); + var labels = axis.getViewLabels(); + + each$27(labels, function (labelItem) { + // The tickValue is dataIndex, see the costomized scale. + var dataIndex = labelItem.tickValue; + + var itemModel = data.getItemModel(dataIndex); + var normalLabelModel = itemModel.getModel('label'); + var hoverLabelModel = itemModel.getModel('emphasis.label'); + var tickCoord = axis.dataToCoord(labelItem.tickValue); + var textEl = new Text({ + position: [tickCoord, 0], + rotation: layoutInfo.labelRotation - layoutInfo.rotation, + onclick: bind$6(this._changeTimeline, this, dataIndex), + silent: false + }); + setTextStyle(textEl.style, normalLabelModel, { + text: labelItem.formattedLabel, + textAlign: layoutInfo.labelAlign, + textVerticalAlign: layoutInfo.labelBaseline + }); + + group.add(textEl); + setHoverStyle( + textEl, setTextStyle({}, hoverLabelModel) + ); + + }, this); + }, + + /** + * @private + */ + _renderControl: function (layoutInfo, group, axis, timelineModel) { + var controlSize = layoutInfo.controlSize; + var rotation = layoutInfo.rotation; + + var itemStyle = timelineModel.getModel('controlStyle').getItemStyle(); + var hoverStyle = timelineModel.getModel('emphasis.controlStyle').getItemStyle(); + var rect = [0, -controlSize / 2, controlSize, controlSize]; + var playState = timelineModel.getPlayState(); + var inverse = timelineModel.get('inverse', true); + + makeBtn( + layoutInfo.nextBtnPosition, + 'controlStyle.nextIcon', + bind$6(this._changeTimeline, this, inverse ? '-' : '+') + ); + makeBtn( + layoutInfo.prevBtnPosition, + 'controlStyle.prevIcon', + bind$6(this._changeTimeline, this, inverse ? '+' : '-') + ); + makeBtn( + layoutInfo.playPosition, + 'controlStyle.' + (playState ? 'stopIcon' : 'playIcon'), + bind$6(this._handlePlayClick, this, !playState), + true + ); + + function makeBtn(position, iconPath, onclick, willRotate) { + if (!position) { + return; + } + var opt = { + position: position, + origin: [controlSize / 2, 0], + rotation: willRotate ? -rotation : 0, + rectHover: true, + style: itemStyle, + onclick: onclick + }; + var btn = makeIcon(timelineModel, iconPath, rect, opt); + group.add(btn); + setHoverStyle(btn, hoverStyle); + } + }, + + _renderCurrentPointer: function (layoutInfo, group, axis, timelineModel) { + var data = timelineModel.getData(); + var currentIndex = timelineModel.getCurrentIndex(); + var pointerModel = data.getItemModel(currentIndex).getModel('checkpointStyle'); + var me = this; + + var callback = { + onCreate: function (pointer) { + pointer.draggable = true; + pointer.drift = bind$6(me._handlePointerDrag, me); + pointer.ondragend = bind$6(me._handlePointerDragend, me); + pointerMoveTo(pointer, currentIndex, axis, timelineModel, true); + }, + onUpdate: function (pointer) { + pointerMoveTo(pointer, currentIndex, axis, timelineModel); + } + }; + + // Reuse when exists, for animation and drag. + this._currentPointer = giveSymbol( + pointerModel, pointerModel, this._mainGroup, {}, this._currentPointer, callback + ); + }, + + _handlePlayClick: function (nextState) { + this._clearTimer(); + this.api.dispatchAction({ + type: 'timelinePlayChange', + playState: nextState, + from: this.uid + }); + }, + + _handlePointerDrag: function (dx, dy, e) { + this._clearTimer(); + this._pointerChangeTimeline([e.offsetX, e.offsetY]); + }, + + _handlePointerDragend: function (e) { + this._pointerChangeTimeline([e.offsetX, e.offsetY], true); + }, + + _pointerChangeTimeline: function (mousePos, trigger) { + var toCoord = this._toAxisCoord(mousePos)[0]; + + var axis = this._axis; + var axisExtent = asc(axis.getExtent().slice()); + + toCoord > axisExtent[1] && (toCoord = axisExtent[1]); + toCoord < axisExtent[0] && (toCoord = axisExtent[0]); + + this._currentPointer.position[0] = toCoord; + this._currentPointer.dirty(); + + var targetDataIndex = this._findNearestTick(toCoord); + var timelineModel = this.model; + + if (trigger || ( + targetDataIndex !== timelineModel.getCurrentIndex() + && timelineModel.get('realtime') + )) { + this._changeTimeline(targetDataIndex); + } + }, + + _doPlayStop: function () { + this._clearTimer(); + + if (this.model.getPlayState()) { + this._timer = setTimeout( + bind$6(handleFrame, this), + this.model.get('playInterval') + ); + } + + function handleFrame() { + // Do not cache + var timelineModel = this.model; + this._changeTimeline( + timelineModel.getCurrentIndex() + + (timelineModel.get('rewind', true) ? -1 : 1) + ); + } + }, + + _toAxisCoord: function (vertex) { + var trans = this._mainGroup.getLocalTransform(); + return applyTransform$1(vertex, trans, true); + }, + + _findNearestTick: function (axisCoord) { + var data = this.model.getData(); + var dist = Infinity; + var targetDataIndex; + var axis = this._axis; + + data.each(['value'], function (value, dataIndex) { + var coord = axis.dataToCoord(value); + var d = Math.abs(coord - axisCoord); + if (d < dist) { + dist = d; + targetDataIndex = dataIndex; + } + }); + + return targetDataIndex; + }, + + _clearTimer: function () { + if (this._timer) { + clearTimeout(this._timer); + this._timer = null; + } + }, + + _changeTimeline: function (nextIndex) { + var currentIndex = this.model.getCurrentIndex(); + + if (nextIndex === '+') { + nextIndex = currentIndex + 1; + } + else if (nextIndex === '-') { + nextIndex = currentIndex - 1; + } + + this.api.dispatchAction({ + type: 'timelineChange', + currentIndex: nextIndex, + from: this.uid + }); + } + +}); + +function getViewRect$4(model, api) { + return getLayoutRect( + model.getBoxLayoutParams(), + { + width: api.getWidth(), + height: api.getHeight() + }, + model.get('padding') + ); +} + +function makeIcon(timelineModel, objPath, rect, opts) { + var icon = makePath( + timelineModel.get(objPath).replace(/^path:\/\//, ''), + clone(opts || {}), + new BoundingRect(rect[0], rect[1], rect[2], rect[3]), + 'center' + ); + + return icon; +} + +/** + * Create symbol or update symbol + * opt: basic position and event handlers + */ +function giveSymbol(hostModel, itemStyleModel, group, opt, symbol, callback) { + var color = itemStyleModel.get('color'); + + if (!symbol) { + var symbolType = hostModel.get('symbol'); + symbol = createSymbol(symbolType, -1, -1, 2, 2, color); + symbol.setStyle('strokeNoScale', true); + group.add(symbol); + callback && callback.onCreate(symbol); + } + else { + symbol.setColor(color); + group.add(symbol); // Group may be new, also need to add. + callback && callback.onUpdate(symbol); + } + + // Style + var itemStyle = itemStyleModel.getItemStyle(['color', 'symbol', 'symbolSize']); + symbol.setStyle(itemStyle); + + // Transform and events. + opt = merge({ + rectHover: true, + z2: 100 + }, opt, true); + + var symbolSize = hostModel.get('symbolSize'); + symbolSize = symbolSize instanceof Array + ? symbolSize.slice() + : [+symbolSize, +symbolSize]; + symbolSize[0] /= 2; + symbolSize[1] /= 2; + opt.scale = symbolSize; + + var symbolOffset = hostModel.get('symbolOffset'); + if (symbolOffset) { + var pos = opt.position = opt.position || [0, 0]; + pos[0] += parsePercent$1(symbolOffset[0], symbolSize[0]); + pos[1] += parsePercent$1(symbolOffset[1], symbolSize[1]); + } + + var symbolRotate = hostModel.get('symbolRotate'); + opt.rotation = (symbolRotate || 0) * Math.PI / 180 || 0; + + symbol.attr(opt); + + // FIXME + // (1) When symbol.style.strokeNoScale is true and updateTransform is not performed, + // getBoundingRect will return wrong result. + // (This is supposed to be resolved in zrender, but it is a little difficult to + // leverage performance and auto updateTransform) + // (2) All of ancesters of symbol do not scale, so we can just updateTransform symbol. + symbol.updateTransform(); + + return symbol; +} + +function pointerMoveTo(pointer, dataIndex, axis, timelineModel, noAnimation) { + if (pointer.dragging) { + return; + } + + var pointerModel = timelineModel.getModel('checkpointStyle'); + var toCoord = axis.dataToCoord(timelineModel.getData().get(['value'], dataIndex)); + + if (noAnimation || !pointerModel.get('animation', true)) { + pointer.attr({position: [toCoord, 0]}); + } + else { + pointer.stopAnimation(true); + pointer.animateTo( + {position: [toCoord, 0]}, + pointerModel.get('animationDuration', true), + pointerModel.get('animationEasing', true) + ); + } +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/** + * DataZoom component entry + */ + +registerPreprocessor(preprocessor$3); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var ToolboxModel = extendComponentModel({ + + type: 'toolbox', + + layoutMode: { + type: 'box', + ignoreSize: true + }, + + optionUpdated: function () { + ToolboxModel.superApply(this, 'optionUpdated', arguments); + + each$1(this.option.feature, function (featureOpt, featureName) { + var Feature = get$1(featureName); + Feature && merge(featureOpt, Feature.defaultOption); + }); + }, + + defaultOption: { + + show: true, + + z: 6, + + zlevel: 0, + + orient: 'horizontal', + + left: 'right', + + top: 'top', + + // right + // bottom + + backgroundColor: 'transparent', + + borderColor: '#ccc', + + borderRadius: 0, + + borderWidth: 0, + + padding: 5, + + itemSize: 15, + + itemGap: 8, + + showTitle: true, + + iconStyle: { + borderColor: '#666', + color: 'none' + }, + emphasis: { + iconStyle: { + borderColor: '#3E98C5' + } + } + // textStyle: {}, + + // feature + } +}); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +extendComponentView({ + + type: 'toolbox', + + render: function (toolboxModel, ecModel, api, payload) { + var group = this.group; + group.removeAll(); + + if (!toolboxModel.get('show')) { + return; + } + + var itemSize = +toolboxModel.get('itemSize'); + var featureOpts = toolboxModel.get('feature') || {}; + var features = this._features || (this._features = {}); + + var featureNames = []; + each$1(featureOpts, function (opt, name) { + featureNames.push(name); + }); + + (new DataDiffer(this._featureNames || [], featureNames)) + .add(processFeature) + .update(processFeature) + .remove(curry(processFeature, null)) + .execute(); + + // Keep for diff. + this._featureNames = featureNames; + + function processFeature(newIndex, oldIndex) { + var featureName = featureNames[newIndex]; + var oldName = featureNames[oldIndex]; + var featureOpt = featureOpts[featureName]; + var featureModel = new Model(featureOpt, toolboxModel, toolboxModel.ecModel); + var feature; + + if (featureName && !oldName) { // Create + if (isUserFeatureName(featureName)) { + feature = { + model: featureModel, + onclick: featureModel.option.onclick, + featureName: featureName + }; + } + else { + var Feature = get$1(featureName); + if (!Feature) { + return; + } + feature = new Feature(featureModel, ecModel, api); + } + features[featureName] = feature; + } + else { + feature = features[oldName]; + // If feature does not exsit. + if (!feature) { + return; + } + feature.model = featureModel; + feature.ecModel = ecModel; + feature.api = api; + } + + if (!featureName && oldName) { + feature.dispose && feature.dispose(ecModel, api); + return; + } + + if (!featureModel.get('show') || feature.unusable) { + feature.remove && feature.remove(ecModel, api); + return; + } + + createIconPaths(featureModel, feature, featureName); + + featureModel.setIconStatus = function (iconName, status) { + var option = this.option; + var iconPaths = this.iconPaths; + option.iconStatus = option.iconStatus || {}; + option.iconStatus[iconName] = status; + // FIXME + iconPaths[iconName] && iconPaths[iconName].trigger(status); + }; + + if (feature.render) { + feature.render(featureModel, ecModel, api, payload); + } + } + + function createIconPaths(featureModel, feature, featureName) { + var iconStyleModel = featureModel.getModel('iconStyle'); + var iconStyleEmphasisModel = featureModel.getModel('emphasis.iconStyle'); + + // If one feature has mutiple icon. they are orginaized as + // { + // icon: { + // foo: '', + // bar: '' + // }, + // title: { + // foo: '', + // bar: '' + // } + // } + var icons = feature.getIcons ? feature.getIcons() : featureModel.get('icon'); + var titles = featureModel.get('title') || {}; + if (typeof icons === 'string') { + var icon = icons; + var title = titles; + icons = {}; + titles = {}; + icons[featureName] = icon; + titles[featureName] = title; + } + var iconPaths = featureModel.iconPaths = {}; + each$1(icons, function (iconStr, iconName) { + var path = createIcon( + iconStr, + {}, + { + x: -itemSize / 2, + y: -itemSize / 2, + width: itemSize, + height: itemSize + } + ); + path.setStyle(iconStyleModel.getItemStyle()); + path.hoverStyle = iconStyleEmphasisModel.getItemStyle(); + + setHoverStyle(path); + + if (toolboxModel.get('showTitle')) { + path.__title = titles[iconName]; + path.on('mouseover', function () { + // Should not reuse above hoverStyle, which might be modified. + var hoverStyle = iconStyleEmphasisModel.getItemStyle(); + path.setStyle({ + text: titles[iconName], + textPosition: hoverStyle.textPosition || 'bottom', + textFill: hoverStyle.fill || hoverStyle.stroke || '#000', + textAlign: hoverStyle.textAlign || 'center' + }); + }) + .on('mouseout', function () { + path.setStyle({ + textFill: null + }); + }); + } + path.trigger(featureModel.get('iconStatus.' + iconName) || 'normal'); + + group.add(path); + path.on('click', bind( + feature.onclick, feature, ecModel, api, iconName + )); + + iconPaths[iconName] = path; + }); + } + + layout$3(group, toolboxModel, api); + // Render background after group is layout + // FIXME + group.add(makeBackground(group.getBoundingRect(), toolboxModel)); + + // Adjust icon title positions to avoid them out of screen + group.eachChild(function (icon) { + var titleText = icon.__title; + var hoverStyle = icon.hoverStyle; + // May be background element + if (hoverStyle && titleText) { + var rect = getBoundingRect( + titleText, makeFont(hoverStyle) + ); + var offsetX = icon.position[0] + group.position[0]; + var offsetY = icon.position[1] + group.position[1] + itemSize; + + var needPutOnTop = false; + if (offsetY + rect.height > api.getHeight()) { + hoverStyle.textPosition = 'top'; + needPutOnTop = true; + } + var topOffset = needPutOnTop ? (-5 - rect.height) : (itemSize + 8); + if (offsetX + rect.width / 2 > api.getWidth()) { + hoverStyle.textPosition = ['100%', topOffset]; + hoverStyle.textAlign = 'right'; + } + else if (offsetX - rect.width / 2 < 0) { + hoverStyle.textPosition = [0, topOffset]; + hoverStyle.textAlign = 'left'; + } + } + }); + }, + + updateView: function (toolboxModel, ecModel, api, payload) { + each$1(this._features, function (feature) { + feature.updateView && feature.updateView(feature.model, ecModel, api, payload); + }); + }, + + // updateLayout: function (toolboxModel, ecModel, api, payload) { + // zrUtil.each(this._features, function (feature) { + // feature.updateLayout && feature.updateLayout(feature.model, ecModel, api, payload); + // }); + // }, + + remove: function (ecModel, api) { + each$1(this._features, function (feature) { + feature.remove && feature.remove(ecModel, api); + }); + this.group.removeAll(); + }, + + dispose: function (ecModel, api) { + each$1(this._features, function (feature) { + feature.dispose && feature.dispose(ecModel, api); + }); + } +}); + +function isUserFeatureName(featureName) { + return featureName.indexOf('my') === 0; +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/* global Uint8Array */ + +var saveAsImageLang = lang.toolbox.saveAsImage; + +function SaveAsImage(model) { + this.model = model; +} + +SaveAsImage.defaultOption = { + show: true, + icon: 'M4.7,22.9L29.3,45.5L54.7,23.4M4.6,43.6L4.6,58L53.8,58L53.8,43.6M29.2,45.1L29.2,0', + title: saveAsImageLang.title, + type: 'png', + // Default use option.backgroundColor + // backgroundColor: '#fff', + name: '', + excludeComponents: ['toolbox'], + pixelRatio: 1, + lang: saveAsImageLang.lang.slice() +}; + +SaveAsImage.prototype.unusable = !env$1.canvasSupported; + +var proto$4 = SaveAsImage.prototype; + +proto$4.onclick = function (ecModel, api) { + var model = this.model; + var title = model.get('name') || ecModel.get('title.0.text') || 'echarts'; + var $a = document.createElement('a'); + var type = model.get('type', true) || 'png'; + $a.download = title + '.' + type; + $a.target = '_blank'; + var url = api.getConnectedDataURL({ + type: type, + backgroundColor: model.get('backgroundColor', true) + || ecModel.get('backgroundColor') || '#fff', + excludeComponents: model.get('excludeComponents'), + pixelRatio: model.get('pixelRatio') + }); + $a.href = url; + // Chrome and Firefox + if (typeof MouseEvent === 'function' && !env$1.browser.ie && !env$1.browser.edge) { + var evt = new MouseEvent('click', { + view: window, + bubbles: true, + cancelable: false + }); + $a.dispatchEvent(evt); + } + // IE + else { + if (window.navigator.msSaveOrOpenBlob) { + var bstr = atob(url.split(',')[1]); + var n = bstr.length; + var u8arr = new Uint8Array(n); + while (n--) { + u8arr[n] = bstr.charCodeAt(n); + } + var blob = new Blob([u8arr]); + window.navigator.msSaveOrOpenBlob(blob, title + '.' + type); + } + else { + var lang$$1 = model.get('lang'); + var html = '' + + '' + + '' + + ''; + var tab = window.open(); + tab.document.write(html); + } + } +}; + +register$1( + 'saveAsImage', SaveAsImage +); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var magicTypeLang = lang.toolbox.magicType; + +function MagicType(model) { + this.model = model; +} + +MagicType.defaultOption = { + show: true, + type: [], + // Icon group + icon: { + /* eslint-disable */ + line: 'M4.1,28.9h7.1l9.3-22l7.4,38l9.7-19.7l3,12.8h14.9M4.1,58h51.4', + bar: 'M6.7,22.9h10V48h-10V22.9zM24.9,13h10v35h-10V13zM43.2,2h10v46h-10V2zM3.1,58h53.7', + stack: 'M8.2,38.4l-8.4,4.1l30.6,15.3L60,42.5l-8.1-4.1l-21.5,11L8.2,38.4z M51.9,30l-8.1,4.2l-13.4,6.9l-13.9-6.9L8.2,30l-8.4,4.2l8.4,4.2l22.2,11l21.5-11l8.1-4.2L51.9,30z M51.9,21.7l-8.1,4.2L35.7,30l-5.3,2.8L24.9,30l-8.4-4.1l-8.3-4.2l-8.4,4.2L8.2,30l8.3,4.2l13.9,6.9l13.4-6.9l8.1-4.2l8.1-4.1L51.9,21.7zM30.4,2.2L-0.2,17.5l8.4,4.1l8.3,4.2l8.4,4.2l5.5,2.7l5.3-2.7l8.1-4.2l8.1-4.2l8.1-4.1L30.4,2.2z', // jshint ignore:line + tiled: 'M2.3,2.2h22.8V25H2.3V2.2z M35,2.2h22.8V25H35V2.2zM2.3,35h22.8v22.8H2.3V35z M35,35h22.8v22.8H35V35z' + /* eslint-enable */ + }, + // `line`, `bar`, `stack`, `tiled` + title: clone(magicTypeLang.title), + option: {}, + seriesIndex: {} +}; + +var proto$5 = MagicType.prototype; + +proto$5.getIcons = function () { + var model = this.model; + var availableIcons = model.get('icon'); + var icons = {}; + each$1(model.get('type'), function (type) { + if (availableIcons[type]) { + icons[type] = availableIcons[type]; + } + }); + return icons; +}; + +var seriesOptGenreator = { + 'line': function (seriesType, seriesId, seriesModel, model) { + if (seriesType === 'bar') { + return merge({ + id: seriesId, + type: 'line', + // Preserve data related option + data: seriesModel.get('data'), + stack: seriesModel.get('stack'), + markPoint: seriesModel.get('markPoint'), + markLine: seriesModel.get('markLine') + }, model.get('option.line') || {}, true); + } + }, + 'bar': function (seriesType, seriesId, seriesModel, model) { + if (seriesType === 'line') { + return merge({ + id: seriesId, + type: 'bar', + // Preserve data related option + data: seriesModel.get('data'), + stack: seriesModel.get('stack'), + markPoint: seriesModel.get('markPoint'), + markLine: seriesModel.get('markLine') + }, model.get('option.bar') || {}, true); + } + }, + 'stack': function (seriesType, seriesId, seriesModel, model) { + if (seriesType === 'line' || seriesType === 'bar') { + return merge({ + id: seriesId, + stack: '__ec_magicType_stack__' + }, model.get('option.stack') || {}, true); + } + }, + 'tiled': function (seriesType, seriesId, seriesModel, model) { + if (seriesType === 'line' || seriesType === 'bar') { + return merge({ + id: seriesId, + stack: '' + }, model.get('option.tiled') || {}, true); + } + } +}; + +var radioTypes = [ + ['line', 'bar'], + ['stack', 'tiled'] +]; + +proto$5.onclick = function (ecModel, api, type) { + var model = this.model; + var seriesIndex = model.get('seriesIndex.' + type); + // Not supported magicType + if (!seriesOptGenreator[type]) { + return; + } + var newOption = { + series: [] + }; + var generateNewSeriesTypes = function (seriesModel) { + var seriesType = seriesModel.subType; + var seriesId = seriesModel.id; + var newSeriesOpt = seriesOptGenreator[type]( + seriesType, seriesId, seriesModel, model + ); + if (newSeriesOpt) { + // PENDING If merge original option? + defaults(newSeriesOpt, seriesModel.option); + newOption.series.push(newSeriesOpt); + } + // Modify boundaryGap + var coordSys = seriesModel.coordinateSystem; + if (coordSys && coordSys.type === 'cartesian2d' && (type === 'line' || type === 'bar')) { + var categoryAxis = coordSys.getAxesByScale('ordinal')[0]; + if (categoryAxis) { + var axisDim = categoryAxis.dim; + var axisType = axisDim + 'Axis'; + var axisModel = ecModel.queryComponents({ + mainType: axisType, + index: seriesModel.get(name + 'Index'), + id: seriesModel.get(name + 'Id') + })[0]; + var axisIndex = axisModel.componentIndex; + + newOption[axisType] = newOption[axisType] || []; + for (var i = 0; i <= axisIndex; i++) { + newOption[axisType][axisIndex] = newOption[axisType][axisIndex] || {}; + } + newOption[axisType][axisIndex].boundaryGap = type === 'bar'; + } + } + }; + + each$1(radioTypes, function (radio) { + if (indexOf(radio, type) >= 0) { + each$1(radio, function (item) { + model.setIconStatus(item, 'normal'); + }); + } + }); + + model.setIconStatus(type, 'emphasis'); + + ecModel.eachComponent( + { + mainType: 'series', + query: seriesIndex == null ? null : { + seriesIndex: seriesIndex + } + }, generateNewSeriesTypes + ); + api.dispatchAction({ + type: 'changeMagicType', + currentType: type, + newOption: newOption + }); +}; + +registerAction({ + type: 'changeMagicType', + event: 'magicTypeChanged', + update: 'prepareAndUpdate' +}, function (payload, ecModel) { + ecModel.mergeOption(payload.newOption); +}); + +register$1('magicType', MagicType); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var dataViewLang = lang.toolbox.dataView; + +var BLOCK_SPLITER = new Array(60).join('-'); +var ITEM_SPLITER = '\t'; +/** + * Group series into two types + * 1. on category axis, like line, bar + * 2. others, like scatter, pie + * @param {module:echarts/model/Global} ecModel + * @return {Object} + * @inner + */ +function groupSeries(ecModel) { + var seriesGroupByCategoryAxis = {}; + var otherSeries = []; + var meta = []; + ecModel.eachRawSeries(function (seriesModel) { + var coordSys = seriesModel.coordinateSystem; + + if (coordSys && (coordSys.type === 'cartesian2d' || coordSys.type === 'polar')) { + var baseAxis = coordSys.getBaseAxis(); + if (baseAxis.type === 'category') { + var key = baseAxis.dim + '_' + baseAxis.index; + if (!seriesGroupByCategoryAxis[key]) { + seriesGroupByCategoryAxis[key] = { + categoryAxis: baseAxis, + valueAxis: coordSys.getOtherAxis(baseAxis), + series: [] + }; + meta.push({ + axisDim: baseAxis.dim, + axisIndex: baseAxis.index + }); + } + seriesGroupByCategoryAxis[key].series.push(seriesModel); + } + else { + otherSeries.push(seriesModel); + } + } + else { + otherSeries.push(seriesModel); + } + }); + + return { + seriesGroupByCategoryAxis: seriesGroupByCategoryAxis, + other: otherSeries, + meta: meta + }; +} + +/** + * Assemble content of series on cateogory axis + * @param {Array.} series + * @return {string} + * @inner + */ +function assembleSeriesWithCategoryAxis(series) { + var tables = []; + each$1(series, function (group, key) { + var categoryAxis = group.categoryAxis; + var valueAxis = group.valueAxis; + var valueAxisDim = valueAxis.dim; + + var headers = [' '].concat(map(group.series, function (series) { + return series.name; + })); + var columns = [categoryAxis.model.getCategories()]; + each$1(group.series, function (series) { + columns.push(series.getRawData().mapArray(valueAxisDim, function (val) { + return val; + })); + }); + // Assemble table content + var lines = [headers.join(ITEM_SPLITER)]; + for (var i = 0; i < columns[0].length; i++) { + var items = []; + for (var j = 0; j < columns.length; j++) { + items.push(columns[j][i]); + } + lines.push(items.join(ITEM_SPLITER)); + } + tables.push(lines.join('\n')); + }); + return tables.join('\n\n' + BLOCK_SPLITER + '\n\n'); +} + +/** + * Assemble content of other series + * @param {Array.} series + * @return {string} + * @inner + */ +function assembleOtherSeries(series) { + return map(series, function (series) { + var data = series.getRawData(); + var lines = [series.name]; + var vals = []; + data.each(data.dimensions, function () { + var argLen = arguments.length; + var dataIndex = arguments[argLen - 1]; + var name = data.getName(dataIndex); + for (var i = 0; i < argLen - 1; i++) { + vals[i] = arguments[i]; + } + lines.push((name ? (name + ITEM_SPLITER) : '') + vals.join(ITEM_SPLITER)); + }); + return lines.join('\n'); + }).join('\n\n' + BLOCK_SPLITER + '\n\n'); +} + +/** + * @param {module:echarts/model/Global} + * @return {Object} + * @inner + */ +function getContentFromModel(ecModel) { + + var result = groupSeries(ecModel); + + return { + value: filter([ + assembleSeriesWithCategoryAxis(result.seriesGroupByCategoryAxis), + assembleOtherSeries(result.other) + ], function (str) { + return str.replace(/[\n\t\s]/g, ''); + }).join('\n\n' + BLOCK_SPLITER + '\n\n'), + + meta: result.meta + }; +} + + +function trim$1(str) { + return str.replace(/^\s\s*/, '').replace(/\s\s*$/, ''); +} +/** + * If a block is tsv format + */ +function isTSVFormat(block) { + // Simple method to find out if a block is tsv format + var firstLine = block.slice(0, block.indexOf('\n')); + if (firstLine.indexOf(ITEM_SPLITER) >= 0) { + return true; + } +} + +var itemSplitRegex = new RegExp('[' + ITEM_SPLITER + ']+', 'g'); +/** + * @param {string} tsv + * @return {Object} + */ +function parseTSVContents(tsv) { + var tsvLines = tsv.split(/\n+/g); + var headers = trim$1(tsvLines.shift()).split(itemSplitRegex); + + var categories = []; + var series = map(headers, function (header) { + return { + name: header, + data: [] + }; + }); + for (var i = 0; i < tsvLines.length; i++) { + var items = trim$1(tsvLines[i]).split(itemSplitRegex); + categories.push(items.shift()); + for (var j = 0; j < items.length; j++) { + series[j] && (series[j].data[i] = items[j]); + } + } + return { + series: series, + categories: categories + }; +} + +/** + * @param {string} str + * @return {Array.} + * @inner + */ +function parseListContents(str) { + var lines = str.split(/\n+/g); + var seriesName = trim$1(lines.shift()); + + var data = []; + for (var i = 0; i < lines.length; i++) { + var items = trim$1(lines[i]).split(itemSplitRegex); + var name = ''; + var value; + var hasName = false; + if (isNaN(items[0])) { // First item is name + hasName = true; + name = items[0]; + items = items.slice(1); + data[i] = { + name: name, + value: [] + }; + value = data[i].value; + } + else { + value = data[i] = []; + } + for (var j = 0; j < items.length; j++) { + value.push(+items[j]); + } + if (value.length === 1) { + hasName ? (data[i].value = value[0]) : (data[i] = value[0]); + } + } + + return { + name: seriesName, + data: data + }; +} + +/** + * @param {string} str + * @param {Array.} blockMetaList + * @return {Object} + * @inner + */ +function parseContents(str, blockMetaList) { + var blocks = str.split(new RegExp('\n*' + BLOCK_SPLITER + '\n*', 'g')); + var newOption = { + series: [] + }; + each$1(blocks, function (block, idx) { + if (isTSVFormat(block)) { + var result = parseTSVContents(block); + var blockMeta = blockMetaList[idx]; + var axisKey = blockMeta.axisDim + 'Axis'; + + if (blockMeta) { + newOption[axisKey] = newOption[axisKey] || []; + newOption[axisKey][blockMeta.axisIndex] = { + data: result.categories + }; + newOption.series = newOption.series.concat(result.series); + } + } + else { + var result = parseListContents(block); + newOption.series.push(result); + } + }); + return newOption; +} + +/** + * @alias {module:echarts/component/toolbox/feature/DataView} + * @constructor + * @param {module:echarts/model/Model} model + */ +function DataView(model) { + + this._dom = null; + + this.model = model; +} + +DataView.defaultOption = { + show: true, + readOnly: false, + optionToContent: null, + contentToOption: null, + + icon: 'M17.5,17.3H33 M17.5,17.3H33 M45.4,29.5h-28 M11.5,2v56H51V14.8L38.4,2H11.5z M38.4,2.2v12.7H51 M45.4,41.7h-28', + title: clone(dataViewLang.title), + lang: clone(dataViewLang.lang), + backgroundColor: '#fff', + textColor: '#000', + textareaColor: '#fff', + textareaBorderColor: '#333', + buttonColor: '#c23531', + buttonTextColor: '#fff' +}; + +DataView.prototype.onclick = function (ecModel, api) { + var container = api.getDom(); + var model = this.model; + if (this._dom) { + container.removeChild(this._dom); + } + var root = document.createElement('div'); + root.style.cssText = 'position:absolute;left:5px;top:5px;bottom:5px;right:5px;'; + root.style.backgroundColor = model.get('backgroundColor') || '#fff'; + + // Create elements + var header = document.createElement('h4'); + var lang$$1 = model.get('lang') || []; + header.innerHTML = lang$$1[0] || model.get('title'); + header.style.cssText = 'margin: 10px 20px;'; + header.style.color = model.get('textColor'); + + var viewMain = document.createElement('div'); + var textarea = document.createElement('textarea'); + viewMain.style.cssText = 'display:block;width:100%;overflow:auto;'; + + var optionToContent = model.get('optionToContent'); + var contentToOption = model.get('contentToOption'); + var result = getContentFromModel(ecModel); + if (typeof optionToContent === 'function') { + var htmlOrDom = optionToContent(api.getOption()); + if (typeof htmlOrDom === 'string') { + viewMain.innerHTML = htmlOrDom; + } + else if (isDom(htmlOrDom)) { + viewMain.appendChild(htmlOrDom); + } + } + else { + // Use default textarea + viewMain.appendChild(textarea); + textarea.readOnly = model.get('readOnly'); + textarea.style.cssText = 'width:100%;height:100%;font-family:monospace;font-size:14px;line-height:1.6rem;'; + textarea.style.color = model.get('textColor'); + textarea.style.borderColor = model.get('textareaBorderColor'); + textarea.style.backgroundColor = model.get('textareaColor'); + textarea.value = result.value; + } + + var blockMetaList = result.meta; + + var buttonContainer = document.createElement('div'); + buttonContainer.style.cssText = 'position:absolute;bottom:0;left:0;right:0;'; + + var buttonStyle = 'float:right;margin-right:20px;border:none;' + + 'cursor:pointer;padding:2px 5px;font-size:12px;border-radius:3px'; + var closeButton = document.createElement('div'); + var refreshButton = document.createElement('div'); + + buttonStyle += ';background-color:' + model.get('buttonColor'); + buttonStyle += ';color:' + model.get('buttonTextColor'); + + var self = this; + + function close() { + container.removeChild(root); + self._dom = null; + } + addEventListener(closeButton, 'click', close); + + addEventListener(refreshButton, 'click', function () { + var newOption; + try { + if (typeof contentToOption === 'function') { + newOption = contentToOption(viewMain, api.getOption()); + } + else { + newOption = parseContents(textarea.value, blockMetaList); + } + } + catch (e) { + close(); + throw new Error('Data view format error ' + e); + } + if (newOption) { + api.dispatchAction({ + type: 'changeDataView', + newOption: newOption + }); + } + + close(); + }); + + closeButton.innerHTML = lang$$1[1]; + refreshButton.innerHTML = lang$$1[2]; + refreshButton.style.cssText = buttonStyle; + closeButton.style.cssText = buttonStyle; + + !model.get('readOnly') && buttonContainer.appendChild(refreshButton); + buttonContainer.appendChild(closeButton); + + // http://stackoverflow.com/questions/6637341/use-tab-to-indent-in-textarea + addEventListener(textarea, 'keydown', function (e) { + if ((e.keyCode || e.which) === 9) { + // get caret position/selection + var val = this.value; + var start = this.selectionStart; + var end = this.selectionEnd; + + // set textarea value to: text before caret + tab + text after caret + this.value = val.substring(0, start) + ITEM_SPLITER + val.substring(end); + + // put caret at right position again + this.selectionStart = this.selectionEnd = start + 1; + + // prevent the focus lose + stop(e); + } + }); + + root.appendChild(header); + root.appendChild(viewMain); + root.appendChild(buttonContainer); + + viewMain.style.height = (container.clientHeight - 80) + 'px'; + + container.appendChild(root); + this._dom = root; +}; + +DataView.prototype.remove = function (ecModel, api) { + this._dom && api.getDom().removeChild(this._dom); +}; + +DataView.prototype.dispose = function (ecModel, api) { + this.remove(ecModel, api); +}; + +/** + * @inner + */ +function tryMergeDataOption(newData, originalData) { + return map(newData, function (newVal, idx) { + var original = originalData && originalData[idx]; + if (isObject$1(original) && !isArray(original)) { + if (isObject$1(newVal) && !isArray(newVal)) { + newVal = newVal.value; + } + // Original data has option + return defaults({ + value: newVal + }, original); + } + else { + return newVal; + } + }); +} + +register$1('dataView', DataView); + +registerAction({ + type: 'changeDataView', + event: 'dataViewChanged', + update: 'prepareAndUpdate' +}, function (payload, ecModel) { + var newSeriesOptList = []; + each$1(payload.newOption.series, function (seriesOpt) { + var seriesModel = ecModel.getSeriesByName(seriesOpt.name)[0]; + if (!seriesModel) { + // New created series + // Geuss the series type + newSeriesOptList.push(extend({ + // Default is scatter + type: 'scatter' + }, seriesOpt)); + } + else { + var originalData = seriesModel.get('data'); + newSeriesOptList.push({ + name: seriesOpt.name, + data: tryMergeDataOption(seriesOpt.data, originalData) + }); + } + }); + + ecModel.mergeOption(defaults({ + series: newSeriesOptList + }, payload.newOption)); +}); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var each$29 = each$1; + +var ATTR$2 = '\0_ec_hist_store'; + +/** + * @param {module:echarts/model/Global} ecModel + * @param {Object} newSnapshot {dataZoomId, batch: [payloadInfo, ...]} + */ +function push(ecModel, newSnapshot) { + var store = giveStore$1(ecModel); + + // If previous dataZoom can not be found, + // complete an range with current range. + each$29(newSnapshot, function (batchItem, dataZoomId) { + var i = store.length - 1; + for (; i >= 0; i--) { + var snapshot = store[i]; + if (snapshot[dataZoomId]) { + break; + } + } + if (i < 0) { + // No origin range set, create one by current range. + var dataZoomModel = ecModel.queryComponents( + {mainType: 'dataZoom', subType: 'select', id: dataZoomId} + )[0]; + if (dataZoomModel) { + var percentRange = dataZoomModel.getPercentRange(); + store[0][dataZoomId] = { + dataZoomId: dataZoomId, + start: percentRange[0], + end: percentRange[1] + }; + } + } + }); + + store.push(newSnapshot); +} + +/** + * @param {module:echarts/model/Global} ecModel + * @return {Object} snapshot + */ +function pop(ecModel) { + var store = giveStore$1(ecModel); + var head = store[store.length - 1]; + store.length > 1 && store.pop(); + + // Find top for all dataZoom. + var snapshot = {}; + each$29(head, function (batchItem, dataZoomId) { + for (var i = store.length - 1; i >= 0; i--) { + var batchItem = store[i][dataZoomId]; + if (batchItem) { + snapshot[dataZoomId] = batchItem; + break; + } + } + }); + + return snapshot; +} + +/** + * @param {module:echarts/model/Global} ecModel + */ +function clear$1(ecModel) { + ecModel[ATTR$2] = null; +} + +/** + * @param {module:echarts/model/Global} ecModel + * @return {number} records. always >= 1. + */ +function count(ecModel) { + return giveStore$1(ecModel).length; +} + +/** + * [{key: dataZoomId, value: {dataZoomId, range}}, ...] + * History length of each dataZoom may be different. + * this._history[0] is used to store origin range. + * @type {Array.} + */ +function giveStore$1(ecModel) { + var store = ecModel[ATTR$2]; + if (!store) { + store = ecModel[ATTR$2] = [{}]; + } + return store; +} + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +DataZoomModel.extend({ + type: 'dataZoom.select' +}); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +DataZoomView.extend({ + type: 'dataZoom.select' +}); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +/** + * DataZoom component entry + */ + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +// Use dataZoomSelect +var dataZoomLang = lang.toolbox.dataZoom; +var each$28 = each$1; + +// Spectial component id start with \0ec\0, see echarts/model/Global.js~hasInnerId +var DATA_ZOOM_ID_BASE = '\0_ec_\0toolbox-dataZoom_'; + +function DataZoom(model, ecModel, api) { + + /** + * @private + * @type {module:echarts/component/helper/BrushController} + */ + (this._brushController = new BrushController(api.getZr())) + .on('brush', bind(this._onBrush, this)) + .mount(); + + /** + * @private + * @type {boolean} + */ + this._isZoomActive; +} + +DataZoom.defaultOption = { + show: true, + // Icon group + icon: { + zoom: 'M0,13.5h26.9 M13.5,26.9V0 M32.1,13.5H58V58H13.5 V32.1', + back: 'M22,1.4L9.9,13.5l12.3,12.3 M10.3,13.5H54.9v44.6 H10.3v-26' + }, + // `zoom`, `back` + title: clone(dataZoomLang.title) +}; + +var proto$6 = DataZoom.prototype; + +proto$6.render = function (featureModel, ecModel, api, payload) { + this.model = featureModel; + this.ecModel = ecModel; + this.api = api; + + updateZoomBtnStatus(featureModel, ecModel, this, payload, api); + updateBackBtnStatus(featureModel, ecModel); +}; + +proto$6.onclick = function (ecModel, api, type) { + handlers$1[type].call(this); +}; + +proto$6.remove = function (ecModel, api) { + this._brushController.unmount(); +}; + +proto$6.dispose = function (ecModel, api) { + this._brushController.dispose(); +}; + +/** + * @private + */ +var handlers$1 = { + + zoom: function () { + var nextActive = !this._isZoomActive; + + this.api.dispatchAction({ + type: 'takeGlobalCursor', + key: 'dataZoomSelect', + dataZoomSelectActive: nextActive + }); + }, + + back: function () { + this._dispatchZoomAction(pop(this.ecModel)); + } +}; + +/** + * @private + */ +proto$6._onBrush = function (areas, opt) { + if (!opt.isEnd || !areas.length) { + return; + } + var snapshot = {}; + var ecModel = this.ecModel; + + this._brushController.updateCovers([]); // remove cover + + var brushTargetManager = new BrushTargetManager( + retrieveAxisSetting(this.model.option), ecModel, {include: ['grid']} + ); + brushTargetManager.matchOutputRanges(areas, ecModel, function (area, coordRange, coordSys) { + if (coordSys.type !== 'cartesian2d') { + return; + } + + var brushType = area.brushType; + if (brushType === 'rect') { + setBatch('x', coordSys, coordRange[0]); + setBatch('y', coordSys, coordRange[1]); + } + else { + setBatch(({lineX: 'x', lineY: 'y'})[brushType], coordSys, coordRange); + } + }); + + push(ecModel, snapshot); + + this._dispatchZoomAction(snapshot); + + function setBatch(dimName, coordSys, minMax) { + var axis = coordSys.getAxis(dimName); + var axisModel = axis.model; + var dataZoomModel = findDataZoom(dimName, axisModel, ecModel); + + // Restrict range. + var minMaxSpan = dataZoomModel.findRepresentativeAxisProxy(axisModel).getMinMaxSpan(); + if (minMaxSpan.minValueSpan != null || minMaxSpan.maxValueSpan != null) { + minMax = sliderMove( + 0, minMax.slice(), axis.scale.getExtent(), 0, + minMaxSpan.minValueSpan, minMaxSpan.maxValueSpan + ); + } + + dataZoomModel && (snapshot[dataZoomModel.id] = { + dataZoomId: dataZoomModel.id, + startValue: minMax[0], + endValue: minMax[1] + }); + } + + function findDataZoom(dimName, axisModel, ecModel) { + var found; + ecModel.eachComponent({mainType: 'dataZoom', subType: 'select'}, function (dzModel) { + var has = dzModel.getAxisModel(dimName, axisModel.componentIndex); + has && (found = dzModel); + }); + return found; + } +}; + +/** + * @private + */ +proto$6._dispatchZoomAction = function (snapshot) { + var batch = []; + + // Convert from hash map to array. + each$28(snapshot, function (batchItem, dataZoomId) { + batch.push(clone(batchItem)); + }); + + batch.length && this.api.dispatchAction({ + type: 'dataZoom', + from: this.uid, + batch: batch + }); +}; + +function retrieveAxisSetting(option) { + var setting = {}; + // Compatible with previous setting: null => all axis, false => no axis. + each$1(['xAxisIndex', 'yAxisIndex'], function (name) { + setting[name] = option[name]; + setting[name] == null && (setting[name] = 'all'); + (setting[name] === false || setting[name] === 'none') && (setting[name] = []); + }); + return setting; +} + +function updateBackBtnStatus(featureModel, ecModel) { + featureModel.setIconStatus( + 'back', + count(ecModel) > 1 ? 'emphasis' : 'normal' + ); +} + +function updateZoomBtnStatus(featureModel, ecModel, view, payload, api) { + var zoomActive = view._isZoomActive; + + if (payload && payload.type === 'takeGlobalCursor') { + zoomActive = payload.key === 'dataZoomSelect' + ? payload.dataZoomSelectActive : false; + } + + view._isZoomActive = zoomActive; + + featureModel.setIconStatus('zoom', zoomActive ? 'emphasis' : 'normal'); + + var brushTargetManager = new BrushTargetManager( + retrieveAxisSetting(featureModel.option), ecModel, {include: ['grid']} + ); + + view._brushController + .setPanels(brushTargetManager.makePanelOpts(api, function (targetInfo) { + return (targetInfo.xAxisDeclared && !targetInfo.yAxisDeclared) + ? 'lineX' + : (!targetInfo.xAxisDeclared && targetInfo.yAxisDeclared) + ? 'lineY' + : 'rect'; + })) + .enableBrush( + zoomActive + ? { + brushType: 'auto', + brushStyle: { + // FIXME user customized? + lineWidth: 0, + fill: 'rgba(0,0,0,0.2)' + } + } + : false + ); +} + + +register$1('dataZoom', DataZoom); + + +// Create special dataZoom option for select +// FIXME consider the case of merge option, where axes options are not exists. +registerPreprocessor(function (option) { + if (!option) { + return; + } + + var dataZoomOpts = option.dataZoom || (option.dataZoom = []); + if (!isArray(dataZoomOpts)) { + option.dataZoom = dataZoomOpts = [dataZoomOpts]; + } + + var toolboxOpt = option.toolbox; + if (toolboxOpt) { + // Assume there is only one toolbox + if (isArray(toolboxOpt)) { + toolboxOpt = toolboxOpt[0]; + } + + if (toolboxOpt && toolboxOpt.feature) { + var dataZoomOpt = toolboxOpt.feature.dataZoom; + // FIXME: If add dataZoom when setOption in merge mode, + // no axis info to be added. See `test/dataZoom-extreme.html` + addForAxis('xAxis', dataZoomOpt); + addForAxis('yAxis', dataZoomOpt); + } + } + + function addForAxis(axisName, dataZoomOpt) { + if (!dataZoomOpt) { + return; + } + + // Try not to modify model, because it is not merged yet. + var axisIndicesName = axisName + 'Index'; + var givenAxisIndices = dataZoomOpt[axisIndicesName]; + if (givenAxisIndices != null + && givenAxisIndices !== 'all' + && !isArray(givenAxisIndices) + ) { + givenAxisIndices = (givenAxisIndices === false || givenAxisIndices === 'none') ? [] : [givenAxisIndices]; + } + + forEachComponent(axisName, function (axisOpt, axisIndex) { + if (givenAxisIndices != null + && givenAxisIndices !== 'all' + && indexOf(givenAxisIndices, axisIndex) === -1 + ) { + return; + } + var newOpt = { + type: 'select', + $fromToolbox: true, + // Id for merge mapping. + id: DATA_ZOOM_ID_BASE + axisName + axisIndex + }; + // FIXME + // Only support one axis now. + newOpt[axisIndicesName] = axisIndex; + dataZoomOpts.push(newOpt); + }); + } + + function forEachComponent(mainType, cb) { + var opts = option[mainType]; + if (!isArray(opts)) { + opts = opts ? [opts] : []; + } + each$28(opts, cb); + } +}); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var restoreLang = lang.toolbox.restore; + +function Restore(model) { + this.model = model; +} + +Restore.defaultOption = { + show: true, + /* eslint-disable */ + icon: 'M3.8,33.4 M47,18.9h9.8V8.7 M56.3,20.1 C52.1,9,40.5,0.6,26.8,2.1C12.6,3.7,1.6,16.2,2.1,30.6 M13,41.1H3.1v10.2 M3.7,39.9c4.2,11.1,15.8,19.5,29.5,18 c14.2-1.6,25.2-14.1,24.7-28.5', + /* eslint-enable */ + title: restoreLang.title +}; + +var proto$7 = Restore.prototype; + +proto$7.onclick = function (ecModel, api, type) { + clear$1(ecModel); + + api.dispatchAction({ + type: 'restore', + from: this.uid + }); +}; + +register$1('restore', Restore); + +registerAction( + {type: 'restore', event: 'restore', update: 'prepareAndUpdate'}, + function (payload, ecModel) { + ecModel.resetOption('recreate'); + } +); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +var urn = 'urn:schemas-microsoft-com:vml'; +var win = typeof window === 'undefined' ? null : window; + +var vmlInited = false; + +var doc = win && win.document; + +function createNode(tagName) { + return doCreateNode(tagName); +} + +// Avoid assign to an exported variable, for transforming to cjs. +var doCreateNode; + +if (doc && !env$1.canvasSupported) { + try { + !doc.namespaces.zrvml && doc.namespaces.add('zrvml', urn); + doCreateNode = function (tagName) { + return doc.createElement(''); + }; + } + catch (e) { + doCreateNode = function (tagName) { + return doc.createElement('<' + tagName + ' xmlns="' + urn + '" class="zrvml">'); + }; + } +} + +// From raphael +function initVML() { + if (vmlInited || !doc) { + return; + } + vmlInited = true; + + var styleSheets = doc.styleSheets; + if (styleSheets.length < 31) { + doc.createStyleSheet().addRule('.zrvml', 'behavior:url(#default#VML)'); + } + else { + // http://msdn.microsoft.com/en-us/library/ms531194%28VS.85%29.aspx + styleSheets[0].addRule('.zrvml', 'behavior:url(#default#VML)'); + } +} + +// http://www.w3.org/TR/NOTE-VML +// TODO Use proxy like svg instead of overwrite brush methods + +var CMD$3 = PathProxy.CMD; +var round$4 = Math.round; +var sqrt = Math.sqrt; +var abs$1 = Math.abs; +var cos = Math.cos; +var sin = Math.sin; +var mathMax$8 = Math.max; + +if (!env$1.canvasSupported) { + + var comma = ','; + var imageTransformPrefix = 'progid:DXImageTransform.Microsoft'; + + var Z = 21600; + var Z2 = Z / 2; + + var ZLEVEL_BASE = 100000; + var Z_BASE$1 = 1000; + + var initRootElStyle = function (el) { + el.style.cssText = 'position:absolute;left:0;top:0;width:1px;height:1px;'; + el.coordsize = Z + ',' + Z; + el.coordorigin = '0,0'; + }; + + var encodeHtmlAttribute = function (s) { + return String(s).replace(/&/g, '&').replace(/"/g, '"'); + }; + + var rgb2Str = function (r, g, b) { + return 'rgb(' + [r, g, b].join(',') + ')'; + }; + + var append = function (parent, child) { + if (child && parent && child.parentNode !== parent) { + parent.appendChild(child); + } + }; + + var remove = function (parent, child) { + if (child && parent && child.parentNode === parent) { + parent.removeChild(child); + } + }; + + var getZIndex = function (zlevel, z, z2) { + // z 的取值范围为 [0, 1000] + return (parseFloat(zlevel) || 0) * ZLEVEL_BASE + (parseFloat(z) || 0) * Z_BASE$1 + z2; + }; + + var parsePercent$3 = function (value, maxValue) { + if (typeof value === 'string') { + if (value.lastIndexOf('%') >= 0) { + return parseFloat(value) / 100 * maxValue; + } + return parseFloat(value); + } + return value; + }; + + /*************************************************** + * PATH + **************************************************/ + + var setColorAndOpacity = function (el, color, opacity) { + var colorArr = parse(color); + opacity = +opacity; + if (isNaN(opacity)) { + opacity = 1; + } + if (colorArr) { + el.color = rgb2Str(colorArr[0], colorArr[1], colorArr[2]); + el.opacity = opacity * colorArr[3]; + } + }; + + var getColorAndAlpha = function (color) { + var colorArr = parse(color); + return [ + rgb2Str(colorArr[0], colorArr[1], colorArr[2]), + colorArr[3] + ]; + }; + + var updateFillNode = function (el, style, zrEl) { + // TODO pattern + var fill = style.fill; + if (fill != null) { + // Modified from excanvas + if (fill instanceof Gradient) { + var gradientType; + var angle = 0; + var focus = [0, 0]; + // additional offset + var shift = 0; + // scale factor for offset + var expansion = 1; + var rect = zrEl.getBoundingRect(); + var rectWidth = rect.width; + var rectHeight = rect.height; + if (fill.type === 'linear') { + gradientType = 'gradient'; + var transform = zrEl.transform; + var p0 = [fill.x * rectWidth, fill.y * rectHeight]; + var p1 = [fill.x2 * rectWidth, fill.y2 * rectHeight]; + if (transform) { + applyTransform(p0, p0, transform); + applyTransform(p1, p1, transform); + } + var dx = p1[0] - p0[0]; + var dy = p1[1] - p0[1]; + angle = Math.atan2(dx, dy) * 180 / Math.PI; + // The angle should be a non-negative number. + if (angle < 0) { + angle += 360; + } + + // Very small angles produce an unexpected result because they are + // converted to a scientific notation string. + if (angle < 1e-6) { + angle = 0; + } + } + else { + gradientType = 'gradientradial'; + var p0 = [fill.x * rectWidth, fill.y * rectHeight]; + var transform = zrEl.transform; + var scale$$1 = zrEl.scale; + var width = rectWidth; + var height = rectHeight; + focus = [ + // Percent in bounding rect + (p0[0] - rect.x) / width, + (p0[1] - rect.y) / height + ]; + if (transform) { + applyTransform(p0, p0, transform); + } + + width /= scale$$1[0] * Z; + height /= scale$$1[1] * Z; + var dimension = mathMax$8(width, height); + shift = 2 * 0 / dimension; + expansion = 2 * fill.r / dimension - shift; + } + + // We need to sort the color stops in ascending order by offset, + // otherwise IE won't interpret it correctly. + var stops = fill.colorStops.slice(); + stops.sort(function (cs1, cs2) { + return cs1.offset - cs2.offset; + }); + + var length$$1 = stops.length; + // Color and alpha list of first and last stop + var colorAndAlphaList = []; + var colors = []; + for (var i = 0; i < length$$1; i++) { + var stop = stops[i]; + var colorAndAlpha = getColorAndAlpha(stop.color); + colors.push(stop.offset * expansion + shift + ' ' + colorAndAlpha[0]); + if (i === 0 || i === length$$1 - 1) { + colorAndAlphaList.push(colorAndAlpha); + } + } + + if (length$$1 >= 2) { + var color1 = colorAndAlphaList[0][0]; + var color2 = colorAndAlphaList[1][0]; + var opacity1 = colorAndAlphaList[0][1] * style.opacity; + var opacity2 = colorAndAlphaList[1][1] * style.opacity; + + el.type = gradientType; + el.method = 'none'; + el.focus = '100%'; + el.angle = angle; + el.color = color1; + el.color2 = color2; + el.colors = colors.join(','); + // When colors attribute is used, the meanings of opacity and o:opacity2 + // are reversed. + el.opacity = opacity2; + // FIXME g_o_:opacity ? + el.opacity2 = opacity1; + } + if (gradientType === 'radial') { + el.focusposition = focus.join(','); + } + } + else { + // FIXME Change from Gradient fill to color fill + setColorAndOpacity(el, fill, style.opacity); + } + } + }; + + var updateStrokeNode = function (el, style) { + // if (style.lineJoin != null) { + // el.joinstyle = style.lineJoin; + // } + // if (style.miterLimit != null) { + // el.miterlimit = style.miterLimit * Z; + // } + // if (style.lineCap != null) { + // el.endcap = style.lineCap; + // } + if (style.lineDash != null) { + el.dashstyle = style.lineDash.join(' '); + } + if (style.stroke != null && !(style.stroke instanceof Gradient)) { + setColorAndOpacity(el, style.stroke, style.opacity); + } + }; + + var updateFillAndStroke = function (vmlEl, type, style, zrEl) { + var isFill = type === 'fill'; + var el = vmlEl.getElementsByTagName(type)[0]; + // Stroke must have lineWidth + if (style[type] != null && style[type] !== 'none' && (isFill || (!isFill && style.lineWidth))) { + vmlEl[isFill ? 'filled' : 'stroked'] = 'true'; + // FIXME Remove before updating, or set `colors` will throw error + if (style[type] instanceof Gradient) { + remove(vmlEl, el); + } + if (!el) { + el = createNode(type); + } + + isFill ? updateFillNode(el, style, zrEl) : updateStrokeNode(el, style); + append(vmlEl, el); + } + else { + vmlEl[isFill ? 'filled' : 'stroked'] = 'false'; + remove(vmlEl, el); + } + }; + + var points$3 = [[], [], []]; + var pathDataToString = function (path, m) { + var M = CMD$3.M; + var C = CMD$3.C; + var L = CMD$3.L; + var A = CMD$3.A; + var Q = CMD$3.Q; + + var str = []; + var nPoint; + var cmdStr; + var cmd; + var i; + var xi; + var yi; + var data = path.data; + var dataLength = path.len(); + for (i = 0; i < dataLength;) { + cmd = data[i++]; + cmdStr = ''; + nPoint = 0; + switch (cmd) { + case M: + cmdStr = ' m '; + nPoint = 1; + xi = data[i++]; + yi = data[i++]; + points$3[0][0] = xi; + points$3[0][1] = yi; + break; + case L: + cmdStr = ' l '; + nPoint = 1; + xi = data[i++]; + yi = data[i++]; + points$3[0][0] = xi; + points$3[0][1] = yi; + break; + case Q: + case C: + cmdStr = ' c '; + nPoint = 3; + var x1 = data[i++]; + var y1 = data[i++]; + var x2 = data[i++]; + var y2 = data[i++]; + var x3; + var y3; + if (cmd === Q) { + // Convert quadratic to cubic using degree elevation + x3 = x2; + y3 = y2; + x2 = (x2 + 2 * x1) / 3; + y2 = (y2 + 2 * y1) / 3; + x1 = (xi + 2 * x1) / 3; + y1 = (yi + 2 * y1) / 3; + } + else { + x3 = data[i++]; + y3 = data[i++]; + } + points$3[0][0] = x1; + points$3[0][1] = y1; + points$3[1][0] = x2; + points$3[1][1] = y2; + points$3[2][0] = x3; + points$3[2][1] = y3; + + xi = x3; + yi = y3; + break; + case A: + var x = 0; + var y = 0; + var sx = 1; + var sy = 1; + var angle = 0; + if (m) { + // Extract SRT from matrix + x = m[4]; + y = m[5]; + sx = sqrt(m[0] * m[0] + m[1] * m[1]); + sy = sqrt(m[2] * m[2] + m[3] * m[3]); + angle = Math.atan2(-m[1] / sy, m[0] / sx); + } + + var cx = data[i++]; + var cy = data[i++]; + var rx = data[i++]; + var ry = data[i++]; + var startAngle = data[i++] + angle; + var endAngle = data[i++] + startAngle + angle; + // FIXME + // var psi = data[i++]; + i++; + var clockwise = data[i++]; + + var x0 = cx + cos(startAngle) * rx; + var y0 = cy + sin(startAngle) * ry; + + var x1 = cx + cos(endAngle) * rx; + var y1 = cy + sin(endAngle) * ry; + + var type = clockwise ? ' wa ' : ' at '; + if (Math.abs(x0 - x1) < 1e-4) { + // IE won't render arches drawn counter clockwise if x0 == x1. + if (Math.abs(endAngle - startAngle) > 1e-2) { + // Offset x0 by 1/80 of a pixel. Use something + // that can be represented in binary + if (clockwise) { + x0 += 270 / Z; + } + } + else { + // Avoid case draw full circle + if (Math.abs(y0 - cy) < 1e-4) { + if ((clockwise && x0 < cx) || (!clockwise && x0 > cx)) { + y1 -= 270 / Z; + } + else { + y1 += 270 / Z; + } + } + else if ((clockwise && y0 < cy) || (!clockwise && y0 > cy)) { + x1 += 270 / Z; + } + else { + x1 -= 270 / Z; + } + } + } + str.push( + type, + round$4(((cx - rx) * sx + x) * Z - Z2), comma, + round$4(((cy - ry) * sy + y) * Z - Z2), comma, + round$4(((cx + rx) * sx + x) * Z - Z2), comma, + round$4(((cy + ry) * sy + y) * Z - Z2), comma, + round$4((x0 * sx + x) * Z - Z2), comma, + round$4((y0 * sy + y) * Z - Z2), comma, + round$4((x1 * sx + x) * Z - Z2), comma, + round$4((y1 * sy + y) * Z - Z2) + ); + + xi = x1; + yi = y1; + break; + case CMD$3.R: + var p0 = points$3[0]; + var p1 = points$3[1]; + // x0, y0 + p0[0] = data[i++]; + p0[1] = data[i++]; + // x1, y1 + p1[0] = p0[0] + data[i++]; + p1[1] = p0[1] + data[i++]; + + if (m) { + applyTransform(p0, p0, m); + applyTransform(p1, p1, m); + } + + p0[0] = round$4(p0[0] * Z - Z2); + p1[0] = round$4(p1[0] * Z - Z2); + p0[1] = round$4(p0[1] * Z - Z2); + p1[1] = round$4(p1[1] * Z - Z2); + str.push( + // x0, y0 + ' m ', p0[0], comma, p0[1], + // x1, y0 + ' l ', p1[0], comma, p0[1], + // x1, y1 + ' l ', p1[0], comma, p1[1], + // x0, y1 + ' l ', p0[0], comma, p1[1] + ); + break; + case CMD$3.Z: + // FIXME Update xi, yi + str.push(' x '); + } + + if (nPoint > 0) { + str.push(cmdStr); + for (var k = 0; k < nPoint; k++) { + var p = points$3[k]; + + m && applyTransform(p, p, m); + // 不 round 会非常慢 + str.push( + round$4(p[0] * Z - Z2), comma, round$4(p[1] * Z - Z2), + k < nPoint - 1 ? comma : '' + ); + } + } + } + + return str.join(''); + }; + + // Rewrite the original path method + Path.prototype.brushVML = function (vmlRoot) { + var style = this.style; + + var vmlEl = this._vmlEl; + if (!vmlEl) { + vmlEl = createNode('shape'); + initRootElStyle(vmlEl); + + this._vmlEl = vmlEl; + } + + updateFillAndStroke(vmlEl, 'fill', style, this); + updateFillAndStroke(vmlEl, 'stroke', style, this); + + var m = this.transform; + var needTransform = m != null; + var strokeEl = vmlEl.getElementsByTagName('stroke')[0]; + if (strokeEl) { + var lineWidth = style.lineWidth; + // Get the line scale. + // Determinant of this.m_ means how much the area is enlarged by the + // transformation. So its square root can be used as a scale factor + // for width. + if (needTransform && !style.strokeNoScale) { + var det = m[0] * m[3] - m[1] * m[2]; + lineWidth *= sqrt(abs$1(det)); + } + strokeEl.weight = lineWidth + 'px'; + } + + var path = this.path || (this.path = new PathProxy()); + if (this.__dirtyPath) { + path.beginPath(); + path.subPixelOptimize = false; + this.buildPath(path, this.shape); + path.toStatic(); + this.__dirtyPath = false; + } + + vmlEl.path = pathDataToString(path, this.transform); + + vmlEl.style.zIndex = getZIndex(this.zlevel, this.z, this.z2); + + // Append to root + append(vmlRoot, vmlEl); + + // Text + if (style.text != null) { + this.drawRectText(vmlRoot, this.getBoundingRect()); + } + else { + this.removeRectText(vmlRoot); + } + }; + + Path.prototype.onRemove = function (vmlRoot) { + remove(vmlRoot, this._vmlEl); + this.removeRectText(vmlRoot); + }; + + Path.prototype.onAdd = function (vmlRoot) { + append(vmlRoot, this._vmlEl); + this.appendRectText(vmlRoot); + }; + + /*************************************************** + * IMAGE + **************************************************/ + var isImage = function (img) { + // FIXME img instanceof Image 如果 img 是一个字符串的时候,IE8 下会报错 + return (typeof img === 'object') && img.tagName && img.tagName.toUpperCase() === 'IMG'; + // return img instanceof Image; + }; + + // Rewrite the original path method + ZImage.prototype.brushVML = function (vmlRoot) { + var style = this.style; + var image = style.image; + + // Image original width, height + var ow; + var oh; + + if (isImage(image)) { + var src = image.src; + if (src === this._imageSrc) { + ow = this._imageWidth; + oh = this._imageHeight; + } + else { + var imageRuntimeStyle = image.runtimeStyle; + var oldRuntimeWidth = imageRuntimeStyle.width; + var oldRuntimeHeight = imageRuntimeStyle.height; + imageRuntimeStyle.width = 'auto'; + imageRuntimeStyle.height = 'auto'; + + // get the original size + ow = image.width; + oh = image.height; + + // and remove overides + imageRuntimeStyle.width = oldRuntimeWidth; + imageRuntimeStyle.height = oldRuntimeHeight; + + // Caching image original width, height and src + this._imageSrc = src; + this._imageWidth = ow; + this._imageHeight = oh; + } + image = src; + } + else { + if (image === this._imageSrc) { + ow = this._imageWidth; + oh = this._imageHeight; + } + } + if (!image) { + return; + } + + var x = style.x || 0; + var y = style.y || 0; + + var dw = style.width; + var dh = style.height; + + var sw = style.sWidth; + var sh = style.sHeight; + var sx = style.sx || 0; + var sy = style.sy || 0; + + var hasCrop = sw && sh; + + var vmlEl = this._vmlEl; + if (!vmlEl) { + // FIXME 使用 group 在 left, top 都不是 0 的时候就无法显示了。 + // vmlEl = vmlCore.createNode('group'); + vmlEl = doc.createElement('div'); + initRootElStyle(vmlEl); + + this._vmlEl = vmlEl; + } + + var vmlElStyle = vmlEl.style; + var hasRotation = false; + var m; + var scaleX = 1; + var scaleY = 1; + if (this.transform) { + m = this.transform; + scaleX = sqrt(m[0] * m[0] + m[1] * m[1]); + scaleY = sqrt(m[2] * m[2] + m[3] * m[3]); + + hasRotation = m[1] || m[2]; + } + if (hasRotation) { + // If filters are necessary (rotation exists), create them + // filters are bog-slow, so only create them if abbsolutely necessary + // The following check doesn't account for skews (which don't exist + // in the canvas spec (yet) anyway. + // From excanvas + var p0 = [x, y]; + var p1 = [x + dw, y]; + var p2 = [x, y + dh]; + var p3 = [x + dw, y + dh]; + applyTransform(p0, p0, m); + applyTransform(p1, p1, m); + applyTransform(p2, p2, m); + applyTransform(p3, p3, m); + + var maxX = mathMax$8(p0[0], p1[0], p2[0], p3[0]); + var maxY = mathMax$8(p0[1], p1[1], p2[1], p3[1]); + + var transformFilter = []; + transformFilter.push('M11=', m[0] / scaleX, comma, + 'M12=', m[2] / scaleY, comma, + 'M21=', m[1] / scaleX, comma, + 'M22=', m[3] / scaleY, comma, + 'Dx=', round$4(x * scaleX + m[4]), comma, + 'Dy=', round$4(y * scaleY + m[5])); + + vmlElStyle.padding = '0 ' + round$4(maxX) + 'px ' + round$4(maxY) + 'px 0'; + // FIXME DXImageTransform 在 IE11 的兼容模式下不起作用 + vmlElStyle.filter = imageTransformPrefix + '.Matrix(' + + transformFilter.join('') + ', SizingMethod=clip)'; + + } + else { + if (m) { + x = x * scaleX + m[4]; + y = y * scaleY + m[5]; + } + vmlElStyle.filter = ''; + vmlElStyle.left = round$4(x) + 'px'; + vmlElStyle.top = round$4(y) + 'px'; + } + + var imageEl = this._imageEl; + var cropEl = this._cropEl; + + if (!imageEl) { + imageEl = doc.createElement('div'); + this._imageEl = imageEl; + } + var imageELStyle = imageEl.style; + if (hasCrop) { + // Needs know image original width and height + if (!(ow && oh)) { + var tmpImage = new Image(); + var self = this; + tmpImage.onload = function () { + tmpImage.onload = null; + ow = tmpImage.width; + oh = tmpImage.height; + // Adjust image width and height to fit the ratio destinationSize / sourceSize + imageELStyle.width = round$4(scaleX * ow * dw / sw) + 'px'; + imageELStyle.height = round$4(scaleY * oh * dh / sh) + 'px'; + + // Caching image original width, height and src + self._imageWidth = ow; + self._imageHeight = oh; + self._imageSrc = image; + }; + tmpImage.src = image; + } + else { + imageELStyle.width = round$4(scaleX * ow * dw / sw) + 'px'; + imageELStyle.height = round$4(scaleY * oh * dh / sh) + 'px'; + } + + if (!cropEl) { + cropEl = doc.createElement('div'); + cropEl.style.overflow = 'hidden'; + this._cropEl = cropEl; + } + var cropElStyle = cropEl.style; + cropElStyle.width = round$4((dw + sx * dw / sw) * scaleX); + cropElStyle.height = round$4((dh + sy * dh / sh) * scaleY); + cropElStyle.filter = imageTransformPrefix + '.Matrix(Dx=' + + (-sx * dw / sw * scaleX) + ',Dy=' + (-sy * dh / sh * scaleY) + ')'; + + if (!cropEl.parentNode) { + vmlEl.appendChild(cropEl); + } + if (imageEl.parentNode !== cropEl) { + cropEl.appendChild(imageEl); + } + } + else { + imageELStyle.width = round$4(scaleX * dw) + 'px'; + imageELStyle.height = round$4(scaleY * dh) + 'px'; + + vmlEl.appendChild(imageEl); + + if (cropEl && cropEl.parentNode) { + vmlEl.removeChild(cropEl); + this._cropEl = null; + } + } + + var filterStr = ''; + var alpha = style.opacity; + if (alpha < 1) { + filterStr += '.Alpha(opacity=' + round$4(alpha * 100) + ') '; + } + filterStr += imageTransformPrefix + '.AlphaImageLoader(src=' + image + ', SizingMethod=scale)'; + + imageELStyle.filter = filterStr; + + vmlEl.style.zIndex = getZIndex(this.zlevel, this.z, this.z2); + + // Append to root + append(vmlRoot, vmlEl); + + // Text + if (style.text != null) { + this.drawRectText(vmlRoot, this.getBoundingRect()); + } + }; + + ZImage.prototype.onRemove = function (vmlRoot) { + remove(vmlRoot, this._vmlEl); + + this._vmlEl = null; + this._cropEl = null; + this._imageEl = null; + + this.removeRectText(vmlRoot); + }; + + ZImage.prototype.onAdd = function (vmlRoot) { + append(vmlRoot, this._vmlEl); + this.appendRectText(vmlRoot); + }; + + + /*************************************************** + * TEXT + **************************************************/ + + var DEFAULT_STYLE_NORMAL = 'normal'; + + var fontStyleCache = {}; + var fontStyleCacheCount = 0; + var MAX_FONT_CACHE_SIZE = 100; + var fontEl = document.createElement('div'); + + var getFontStyle = function (fontString) { + var fontStyle = fontStyleCache[fontString]; + if (!fontStyle) { + // Clear cache + if (fontStyleCacheCount > MAX_FONT_CACHE_SIZE) { + fontStyleCacheCount = 0; + fontStyleCache = {}; + } + + var style = fontEl.style; + var fontFamily; + try { + style.font = fontString; + fontFamily = style.fontFamily.split(',')[0]; + } + catch (e) { + } + + fontStyle = { + style: style.fontStyle || DEFAULT_STYLE_NORMAL, + variant: style.fontVariant || DEFAULT_STYLE_NORMAL, + weight: style.fontWeight || DEFAULT_STYLE_NORMAL, + size: parseFloat(style.fontSize || 12) | 0, + family: fontFamily || 'Microsoft YaHei' + }; + + fontStyleCache[fontString] = fontStyle; + fontStyleCacheCount++; + } + return fontStyle; + }; + + var textMeasureEl; + // Overwrite measure text method + $override$1('measureText', function (text, textFont) { + var doc$$1 = doc; + if (!textMeasureEl) { + textMeasureEl = doc$$1.createElement('div'); + textMeasureEl.style.cssText = 'position:absolute;top:-20000px;left:0;' + + 'padding:0;margin:0;border:none;white-space:pre;'; + doc.body.appendChild(textMeasureEl); + } + + try { + textMeasureEl.style.font = textFont; + } + catch (ex) { + // Ignore failures to set to invalid font. + } + textMeasureEl.innerHTML = ''; + // Don't use innerHTML or innerText because they allow markup/whitespace. + textMeasureEl.appendChild(doc$$1.createTextNode(text)); + return { + width: textMeasureEl.offsetWidth + }; + }); + + var tmpRect$2 = new BoundingRect(); + + var drawRectText = function (vmlRoot, rect, textRect, fromTextEl) { + + var style = this.style; + + // Optimize, avoid normalize every time. + this.__dirty && normalizeTextStyle(style, true); + + var text = style.text; + // Convert to string + text != null && (text += ''); + if (!text) { + return; + } + + // Convert rich text to plain text. Rich text is not supported in + // IE8-, but tags in rich text template will be removed. + if (style.rich) { + var contentBlock = parseRichText(text, style); + text = []; + for (var i = 0; i < contentBlock.lines.length; i++) { + var tokens = contentBlock.lines[i].tokens; + var textLine = []; + for (var j = 0; j < tokens.length; j++) { + textLine.push(tokens[j].text); + } + text.push(textLine.join('')); + } + text = text.join('\n'); + } + + var x; + var y; + var align = style.textAlign; + var verticalAlign = style.textVerticalAlign; + + var fontStyle = getFontStyle(style.font); + // FIXME encodeHtmlAttribute ? + var font = fontStyle.style + ' ' + fontStyle.variant + ' ' + fontStyle.weight + ' ' + + fontStyle.size + 'px "' + fontStyle.family + '"'; + + textRect = textRect || getBoundingRect( + text, font, align, verticalAlign, style.textPadding, style.textLineHeight + ); + + // Transform rect to view space + var m = this.transform; + // Ignore transform for text in other element + if (m && !fromTextEl) { + tmpRect$2.copy(rect); + tmpRect$2.applyTransform(m); + rect = tmpRect$2; + } + + if (!fromTextEl) { + var textPosition = style.textPosition; + var distance$$1 = style.textDistance; + // Text position represented by coord + if (textPosition instanceof Array) { + x = rect.x + parsePercent$3(textPosition[0], rect.width); + y = rect.y + parsePercent$3(textPosition[1], rect.height); + + align = align || 'left'; + } + else { + var res = adjustTextPositionOnRect( + textPosition, rect, distance$$1 + ); + x = res.x; + y = res.y; + + // Default align and baseline when has textPosition + align = align || res.textAlign; + verticalAlign = verticalAlign || res.textVerticalAlign; + } + } + else { + x = rect.x; + y = rect.y; + } + + x = adjustTextX(x, textRect.width, align); + y = adjustTextY(y, textRect.height, verticalAlign); + + // Force baseline 'middle' + y += textRect.height / 2; + + // var fontSize = fontStyle.size; + // 1.75 is an arbitrary number, as there is no info about the text baseline + // switch (baseline) { + // case 'hanging': + // case 'top': + // y += fontSize / 1.75; + // break; + // case 'middle': + // break; + // default: + // // case null: + // // case 'alphabetic': + // // case 'ideographic': + // // case 'bottom': + // y -= fontSize / 2.25; + // break; + // } + + // switch (align) { + // case 'left': + // break; + // case 'center': + // x -= textRect.width / 2; + // break; + // case 'right': + // x -= textRect.width; + // break; + // case 'end': + // align = elementStyle.direction == 'ltr' ? 'right' : 'left'; + // break; + // case 'start': + // align = elementStyle.direction == 'rtl' ? 'right' : 'left'; + // break; + // default: + // align = 'left'; + // } + + var createNode$$1 = createNode; + + var textVmlEl = this._textVmlEl; + var pathEl; + var textPathEl; + var skewEl; + if (!textVmlEl) { + textVmlEl = createNode$$1('line'); + pathEl = createNode$$1('path'); + textPathEl = createNode$$1('textpath'); + skewEl = createNode$$1('skew'); + + // FIXME Why here is not cammel case + // Align 'center' seems wrong + textPathEl.style['v-text-align'] = 'left'; + + initRootElStyle(textVmlEl); + + pathEl.textpathok = true; + textPathEl.on = true; + + textVmlEl.from = '0 0'; + textVmlEl.to = '1000 0.05'; + + append(textVmlEl, skewEl); + append(textVmlEl, pathEl); + append(textVmlEl, textPathEl); + + this._textVmlEl = textVmlEl; + } + else { + // 这里是在前面 appendChild 保证顺序的前提下 + skewEl = textVmlEl.firstChild; + pathEl = skewEl.nextSibling; + textPathEl = pathEl.nextSibling; + } + + var coords = [x, y]; + var textVmlElStyle = textVmlEl.style; + // Ignore transform for text in other element + if (m && fromTextEl) { + applyTransform(coords, coords, m); + + skewEl.on = true; + + skewEl.matrix = m[0].toFixed(3) + comma + m[2].toFixed(3) + comma + + m[1].toFixed(3) + comma + m[3].toFixed(3) + ',0,0'; + + // Text position + skewEl.offset = (round$4(coords[0]) || 0) + ',' + (round$4(coords[1]) || 0); + // Left top point as origin + skewEl.origin = '0 0'; + + textVmlElStyle.left = '0px'; + textVmlElStyle.top = '0px'; + } + else { + skewEl.on = false; + textVmlElStyle.left = round$4(x) + 'px'; + textVmlElStyle.top = round$4(y) + 'px'; + } + + textPathEl.string = encodeHtmlAttribute(text); + // TODO + try { + textPathEl.style.font = font; + } + // Error font format + catch (e) {} + + updateFillAndStroke(textVmlEl, 'fill', { + fill: style.textFill, + opacity: style.opacity + }, this); + updateFillAndStroke(textVmlEl, 'stroke', { + stroke: style.textStroke, + opacity: style.opacity, + lineDash: style.lineDash + }, this); + + textVmlEl.style.zIndex = getZIndex(this.zlevel, this.z, this.z2); + + // Attached to root + append(vmlRoot, textVmlEl); + }; + + var removeRectText = function (vmlRoot) { + remove(vmlRoot, this._textVmlEl); + this._textVmlEl = null; + }; + + var appendRectText = function (vmlRoot) { + append(vmlRoot, this._textVmlEl); + }; + + var list = [RectText, Displayable, ZImage, Path, Text]; + + // In case Displayable has been mixed in RectText + for (var i$3 = 0; i$3 < list.length; i$3++) { + var proto$8 = list[i$3].prototype; + proto$8.drawRectText = drawRectText; + proto$8.removeRectText = removeRectText; + proto$8.appendRectText = appendRectText; + } + + Text.prototype.brushVML = function (vmlRoot) { + var style = this.style; + if (style.text != null) { + this.drawRectText(vmlRoot, { + x: style.x || 0, y: style.y || 0, + width: 0, height: 0 + }, this.getBoundingRect(), true); + } + else { + this.removeRectText(vmlRoot); + } + }; + + Text.prototype.onRemove = function (vmlRoot) { + this.removeRectText(vmlRoot); + }; + + Text.prototype.onAdd = function (vmlRoot) { + this.appendRectText(vmlRoot); + }; +} + +/** + * VML Painter. + * + * @module zrender/vml/Painter + */ + +function parseInt10$1(val) { + return parseInt(val, 10); +} + +/** + * @alias module:zrender/vml/Painter + */ +function VMLPainter(root, storage) { + + initVML(); + + this.root = root; + + this.storage = storage; + + var vmlViewport = document.createElement('div'); + + var vmlRoot = document.createElement('div'); + + vmlViewport.style.cssText = 'display:inline-block;overflow:hidden;position:relative;width:300px;height:150px;'; + + vmlRoot.style.cssText = 'position:absolute;left:0;top:0;'; + + root.appendChild(vmlViewport); + + this._vmlRoot = vmlRoot; + this._vmlViewport = vmlViewport; + + this.resize(); + + // Modify storage + var oldDelFromStorage = storage.delFromStorage; + var oldAddToStorage = storage.addToStorage; + storage.delFromStorage = function (el) { + oldDelFromStorage.call(storage, el); + + if (el) { + el.onRemove && el.onRemove(vmlRoot); + } + }; + + storage.addToStorage = function (el) { + // Displayable already has a vml node + el.onAdd && el.onAdd(vmlRoot); + + oldAddToStorage.call(storage, el); + }; + + this._firstPaint = true; +} + +VMLPainter.prototype = { + + constructor: VMLPainter, + + getType: function () { + return 'vml'; + }, + + /** + * @return {HTMLDivElement} + */ + getViewportRoot: function () { + return this._vmlViewport; + }, + + getViewportRootOffset: function () { + var viewportRoot = this.getViewportRoot(); + if (viewportRoot) { + return { + offsetLeft: viewportRoot.offsetLeft || 0, + offsetTop: viewportRoot.offsetTop || 0 + }; + } + }, + + /** + * 刷新 + */ + refresh: function () { + + var list = this.storage.getDisplayList(true, true); + + this._paintList(list); + }, + + _paintList: function (list) { + var vmlRoot = this._vmlRoot; + for (var i = 0; i < list.length; i++) { + var el = list[i]; + if (el.invisible || el.ignore) { + if (!el.__alreadyNotVisible) { + el.onRemove(vmlRoot); + } + // Set as already invisible + el.__alreadyNotVisible = true; + } + else { + if (el.__alreadyNotVisible) { + el.onAdd(vmlRoot); + } + el.__alreadyNotVisible = false; + if (el.__dirty) { + el.beforeBrush && el.beforeBrush(); + (el.brushVML || el.brush).call(el, vmlRoot); + el.afterBrush && el.afterBrush(); + } + } + el.__dirty = false; + } + + if (this._firstPaint) { + // Detached from document at first time + // to avoid page refreshing too many times + + // FIXME 如果每次都先 removeChild 可能会导致一些填充和描边的效果改变 + this._vmlViewport.appendChild(vmlRoot); + this._firstPaint = false; + } + }, + + resize: function (width, height) { + var width = width == null ? this._getWidth() : width; + var height = height == null ? this._getHeight() : height; + + if (this._width !== width || this._height !== height) { + this._width = width; + this._height = height; + + var vmlViewportStyle = this._vmlViewport.style; + vmlViewportStyle.width = width + 'px'; + vmlViewportStyle.height = height + 'px'; + } + }, + + dispose: function () { + this.root.innerHTML = ''; + + this._vmlRoot = + this._vmlViewport = + this.storage = null; + }, + + getWidth: function () { + return this._width; + }, + + getHeight: function () { + return this._height; + }, + + clear: function () { + if (this._vmlViewport) { + this.root.removeChild(this._vmlViewport); + } + }, + + _getWidth: function () { + var root = this.root; + var stl = root.currentStyle; + + return ((root.clientWidth || parseInt10$1(stl.width)) + - parseInt10$1(stl.paddingLeft) + - parseInt10$1(stl.paddingRight)) | 0; + }, + + _getHeight: function () { + var root = this.root; + var stl = root.currentStyle; + + return ((root.clientHeight || parseInt10$1(stl.height)) + - parseInt10$1(stl.paddingTop) + - parseInt10$1(stl.paddingBottom)) | 0; + } +}; + +// Not supported methods +function createMethodNotSupport(method) { + return function () { + zrLog('In IE8.0 VML mode painter not support method "' + method + '"'); + }; +} + +// Unsupported methods +each$1([ + 'getLayer', 'insertLayer', 'eachLayer', 'eachBuiltinLayer', 'eachOtherLayer', 'getLayers', + 'modLayer', 'delLayer', 'clearLayer', 'toDataURL', 'pathToImage' +], function (name) { + VMLPainter.prototype[name] = createMethodNotSupport(name); +}); + +registerPainter('vml', VMLPainter); + +var svgURI = 'http://www.w3.org/2000/svg'; + +function createElement(name) { + return document.createElementNS(svgURI, name); +} + +// TODO +// 1. shadow +// 2. Image: sx, sy, sw, sh + +var CMD$4 = PathProxy.CMD; +var arrayJoin = Array.prototype.join; + +var NONE = 'none'; +var mathRound = Math.round; +var mathSin$3 = Math.sin; +var mathCos$3 = Math.cos; +var PI$5 = Math.PI; +var PI2$7 = Math.PI * 2; +var degree = 180 / PI$5; + +var EPSILON$4 = 1e-4; + +function round4(val) { + return mathRound(val * 1e4) / 1e4; +} + +function isAroundZero$1(val) { + return val < EPSILON$4 && val > -EPSILON$4; +} + +function pathHasFill(style, isText) { + var fill = isText ? style.textFill : style.fill; + return fill != null && fill !== NONE; +} + +function pathHasStroke(style, isText) { + var stroke = isText ? style.textStroke : style.stroke; + return stroke != null && stroke !== NONE; +} + +function setTransform(svgEl, m) { + if (m) { + attr(svgEl, 'transform', 'matrix(' + arrayJoin.call(m, ',') + ')'); + } +} + +function attr(el, key, val) { + if (!val || val.type !== 'linear' && val.type !== 'radial') { + // Don't set attribute for gradient, since it need new dom nodes + el.setAttribute(key, val); + } +} + +function attrXLink(el, key, val) { + el.setAttributeNS('http://www.w3.org/1999/xlink', key, val); +} + +function bindStyle(svgEl, style, isText, el) { + if (pathHasFill(style, isText)) { + var fill = isText ? style.textFill : style.fill; + fill = fill === 'transparent' ? NONE : fill; + + /** + * FIXME: + * This is a temporary fix for Chrome's clipping bug + * that happens when a clip-path is referring another one. + * This fix should be used before Chrome's bug is fixed. + * For an element that has clip-path, and fill is none, + * set it to be "rgba(0, 0, 0, 0.002)" will hide the element. + * Otherwise, it will show black fill color. + * 0.002 is used because this won't work for alpha values smaller + * than 0.002. + * + * See + * https://bugs.chromium.org/p/chromium/issues/detail?id=659790 + * for more information. + */ + if (svgEl.getAttribute('clip-path') !== 'none' && fill === NONE) { + fill = 'rgba(0, 0, 0, 0.002)'; + } + + attr(svgEl, 'fill', fill); + attr(svgEl, 'fill-opacity', style.fillOpacity != null ? style.fillOpacity * style.opacity : style.opacity); + } + else { + attr(svgEl, 'fill', NONE); + } + + if (pathHasStroke(style, isText)) { + var stroke = isText ? style.textStroke : style.stroke; + stroke = stroke === 'transparent' ? NONE : stroke; + attr(svgEl, 'stroke', stroke); + var strokeWidth = isText + ? style.textStrokeWidth + : style.lineWidth; + var strokeScale = !isText && style.strokeNoScale + ? el.getLineScale() + : 1; + attr(svgEl, 'stroke-width', strokeWidth / strokeScale); + // stroke then fill for text; fill then stroke for others + attr(svgEl, 'paint-order', isText ? 'stroke' : 'fill'); + attr(svgEl, 'stroke-opacity', style.strokeOpacity != null ? style.strokeOpacity : style.opacity); + var lineDash = style.lineDash; + if (lineDash) { + attr(svgEl, 'stroke-dasharray', style.lineDash.join(',')); + attr(svgEl, 'stroke-dashoffset', mathRound(style.lineDashOffset || 0)); + } + else { + attr(svgEl, 'stroke-dasharray', ''); + } + + // PENDING + style.lineCap && attr(svgEl, 'stroke-linecap', style.lineCap); + style.lineJoin && attr(svgEl, 'stroke-linejoin', style.lineJoin); + style.miterLimit && attr(svgEl, 'stroke-miterlimit', style.miterLimit); + } + else { + attr(svgEl, 'stroke', NONE); + } +} + +/*************************************************** + * PATH + **************************************************/ +function pathDataToString$1(path) { + var str = []; + var data = path.data; + var dataLength = path.len(); + for (var i = 0; i < dataLength;) { + var cmd = data[i++]; + var cmdStr = ''; + var nData = 0; + switch (cmd) { + case CMD$4.M: + cmdStr = 'M'; + nData = 2; + break; + case CMD$4.L: + cmdStr = 'L'; + nData = 2; + break; + case CMD$4.Q: + cmdStr = 'Q'; + nData = 4; + break; + case CMD$4.C: + cmdStr = 'C'; + nData = 6; + break; + case CMD$4.A: + var cx = data[i++]; + var cy = data[i++]; + var rx = data[i++]; + var ry = data[i++]; + var theta = data[i++]; + var dTheta = data[i++]; + var psi = data[i++]; + var clockwise = data[i++]; + + var dThetaPositive = Math.abs(dTheta); + var isCircle = isAroundZero$1(dThetaPositive - PI2$7) + && !isAroundZero$1(dThetaPositive); + + var large = false; + if (dThetaPositive >= PI2$7) { + large = true; + } + else if (isAroundZero$1(dThetaPositive)) { + large = false; + } + else { + large = (dTheta > -PI$5 && dTheta < 0 || dTheta > PI$5) + === !!clockwise; + } + + var x0 = round4(cx + rx * mathCos$3(theta)); + var y0 = round4(cy + ry * mathSin$3(theta)); + + // It will not draw if start point and end point are exactly the same + // We need to shift the end point with a small value + // FIXME A better way to draw circle ? + if (isCircle) { + if (clockwise) { + dTheta = PI2$7 - 1e-4; + } + else { + dTheta = -PI2$7 + 1e-4; + } + + large = true; + + if (i === 9) { + // Move to (x0, y0) only when CMD.A comes at the + // first position of a shape. + // For instance, when drawing a ring, CMD.A comes + // after CMD.M, so it's unnecessary to move to + // (x0, y0). + str.push('M', x0, y0); + } + } + + var x = round4(cx + rx * mathCos$3(theta + dTheta)); + var y = round4(cy + ry * mathSin$3(theta + dTheta)); + + // FIXME Ellipse + str.push('A', round4(rx), round4(ry), + mathRound(psi * degree), +large, +clockwise, x, y); + break; + case CMD$4.Z: + cmdStr = 'Z'; + break; + case CMD$4.R: + var x = round4(data[i++]); + var y = round4(data[i++]); + var w = round4(data[i++]); + var h = round4(data[i++]); + str.push( + 'M', x, y, + 'L', x + w, y, + 'L', x + w, y + h, + 'L', x, y + h, + 'L', x, y + ); + break; + } + cmdStr && str.push(cmdStr); + for (var j = 0; j < nData; j++) { + // PENDING With scale + str.push(round4(data[i++])); + } + } + return str.join(' '); +} + +var svgPath = {}; +svgPath.brush = function (el) { + var style = el.style; + + var svgEl = el.__svgEl; + if (!svgEl) { + svgEl = createElement('path'); + el.__svgEl = svgEl; + } + + if (!el.path) { + el.createPathProxy(); + } + var path = el.path; + + if (el.__dirtyPath) { + path.beginPath(); + path.subPixelOptimize = false; + el.buildPath(path, el.shape); + el.__dirtyPath = false; + + var pathStr = pathDataToString$1(path); + if (pathStr.indexOf('NaN') < 0) { + // Ignore illegal path, which may happen such in out-of-range + // data in Calendar series. + attr(svgEl, 'd', pathStr); + } + } + + bindStyle(svgEl, style, false, el); + setTransform(svgEl, el.transform); + + if (style.text != null) { + svgTextDrawRectText(el, el.getBoundingRect()); + } +}; + +/*************************************************** + * IMAGE + **************************************************/ +var svgImage = {}; +svgImage.brush = function (el) { + var style = el.style; + var image = style.image; + + if (image instanceof HTMLImageElement) { + var src = image.src; + image = src; + } + if (!image) { + return; + } + + var x = style.x || 0; + var y = style.y || 0; + + var dw = style.width; + var dh = style.height; + + var svgEl = el.__svgEl; + if (!svgEl) { + svgEl = createElement('image'); + el.__svgEl = svgEl; + } + + if (image !== el.__imageSrc) { + attrXLink(svgEl, 'href', image); + // Caching image src + el.__imageSrc = image; + } + + attr(svgEl, 'width', dw); + attr(svgEl, 'height', dh); + + attr(svgEl, 'x', x); + attr(svgEl, 'y', y); + + setTransform(svgEl, el.transform); + + if (style.text != null) { + svgTextDrawRectText(el, el.getBoundingRect()); + } +}; + +/*************************************************** + * TEXT + **************************************************/ +var svgText = {}; +var tmpRect$3 = new BoundingRect(); + +var svgTextDrawRectText = function (el, rect, textRect) { + var style = el.style; + + el.__dirty && normalizeTextStyle(style, true); + + var text = style.text; + // Convert to string + if (text == null) { + // Draw no text only when text is set to null, but not '' + return; + } + else { + text += ''; + } + + var textSvgEl = el.__textSvgEl; + if (!textSvgEl) { + textSvgEl = createElement('text'); + el.__textSvgEl = textSvgEl; + } + + var x; + var y; + var textPosition = style.textPosition; + var distance = style.textDistance; + var align = style.textAlign || 'left'; + + if (typeof style.fontSize === 'number') { + style.fontSize += 'px'; + } + var font = style.font + || [ + style.fontStyle || '', + style.fontWeight || '', + style.fontSize || '', + style.fontFamily || '' + ].join(' ') + || DEFAULT_FONT$1; + + var verticalAlign = getVerticalAlignForSvg(style.textVerticalAlign); + + textRect = getBoundingRect( + text, font, align, + verticalAlign, style.textPadding, style.textLineHeight + ); + + var lineHeight = textRect.lineHeight; + // Text position represented by coord + if (textPosition instanceof Array) { + x = rect.x + textPosition[0]; + y = rect.y + textPosition[1]; + } + else { + var newPos = adjustTextPositionOnRect( + textPosition, rect, distance + ); + x = newPos.x; + y = newPos.y; + verticalAlign = getVerticalAlignForSvg(newPos.textVerticalAlign); + align = newPos.textAlign; + } + + attr(textSvgEl, 'alignment-baseline', verticalAlign); + + if (font) { + textSvgEl.style.font = font; + } + + var textPadding = style.textPadding; + + // Make baseline top + attr(textSvgEl, 'x', x); + attr(textSvgEl, 'y', y); + + bindStyle(textSvgEl, style, true, el); + if (el instanceof Text || el.style.transformText) { + // Transform text with element + setTransform(textSvgEl, el.transform); + } + else { + if (el.transform) { + tmpRect$3.copy(rect); + tmpRect$3.applyTransform(el.transform); + rect = tmpRect$3; + } + else { + var pos = el.transformCoordToGlobal(rect.x, rect.y); + rect.x = pos[0]; + rect.y = pos[1]; + el.transform = identity(create$1()); + } + + // Text rotation, but no element transform + var origin = style.textOrigin; + if (origin === 'center') { + x = textRect.width / 2 + x; + y = textRect.height / 2 + y; + } + else if (origin) { + x = origin[0] + x; + y = origin[1] + y; + } + var rotate$$1 = -style.textRotation || 0; + var transform = create$1(); + // Apply textRotate to element matrix + rotate(transform, transform, rotate$$1); + + var pos = [el.transform[4], el.transform[5]]; + translate(transform, transform, pos); + setTransform(textSvgEl, transform); + } + + var textLines = text.split('\n'); + var nTextLines = textLines.length; + var textAnchor = align; + // PENDING + if (textAnchor === 'left') { + textAnchor = 'start'; + textPadding && (x += textPadding[3]); + } + else if (textAnchor === 'right') { + textAnchor = 'end'; + textPadding && (x -= textPadding[1]); + } + else if (textAnchor === 'center') { + textAnchor = 'middle'; + textPadding && (x += (textPadding[3] - textPadding[1]) / 2); + } + + var dy = 0; + if (verticalAlign === 'after-edge') { + dy = -textRect.height + lineHeight; + textPadding && (dy -= textPadding[2]); + } + else if (verticalAlign === 'middle') { + dy = (-textRect.height + lineHeight) / 2; + textPadding && (y += (textPadding[0] - textPadding[2]) / 2); + } + else { + textPadding && (dy += textPadding[0]); + } + + // Font may affect position of each tspan elements + if (el.__text !== text || el.__textFont !== font) { + var tspanList = el.__tspanList || []; + el.__tspanList = tspanList; + for (var i = 0; i < nTextLines; i++) { + // Using cached tspan elements + var tspan = tspanList[i]; + if (!tspan) { + tspan = tspanList[i] = createElement('tspan'); + textSvgEl.appendChild(tspan); + attr(tspan, 'alignment-baseline', verticalAlign); + attr(tspan, 'text-anchor', textAnchor); + } + else { + tspan.innerHTML = ''; + } + attr(tspan, 'x', x); + attr(tspan, 'y', y + i * lineHeight + dy); + tspan.appendChild(document.createTextNode(textLines[i])); + } + // Remove unsed tspan elements + for (; i < tspanList.length; i++) { + textSvgEl.removeChild(tspanList[i]); + } + tspanList.length = nTextLines; + + el.__text = text; + el.__textFont = font; + } + else if (el.__tspanList.length) { + // Update span x and y + var len = el.__tspanList.length; + for (var i = 0; i < len; ++i) { + var tspan = el.__tspanList[i]; + if (tspan) { + attr(tspan, 'x', x); + attr(tspan, 'y', y + i * lineHeight + dy); + } + } + } +}; + +function getVerticalAlignForSvg(verticalAlign) { + if (verticalAlign === 'middle') { + return 'middle'; + } + else if (verticalAlign === 'bottom') { + return 'after-edge'; + } + else { + return 'hanging'; + } +} + +svgText.drawRectText = svgTextDrawRectText; + +svgText.brush = function (el) { + var style = el.style; + if (style.text != null) { + // 强制设置 textPosition + style.textPosition = [0, 0]; + svgTextDrawRectText(el, { + x: style.x || 0, y: style.y || 0, + width: 0, height: 0 + }, el.getBoundingRect()); + } +}; + +// Myers' Diff Algorithm +// Modified from https://github.com/kpdecker/jsdiff/blob/master/src/diff/base.js + +function Diff() {} + +Diff.prototype = { + diff: function (oldArr, newArr, equals) { + if (!equals) { + equals = function (a, b) { + return a === b; + }; + } + this.equals = equals; + + var self = this; + + oldArr = oldArr.slice(); + newArr = newArr.slice(); + // Allow subclasses to massage the input prior to running + var newLen = newArr.length; + var oldLen = oldArr.length; + var editLength = 1; + var maxEditLength = newLen + oldLen; + var bestPath = [{ newPos: -1, components: [] }]; + + // Seed editLength = 0, i.e. the content starts with the same values + var oldPos = this.extractCommon(bestPath[0], newArr, oldArr, 0); + if (bestPath[0].newPos + 1 >= newLen && oldPos + 1 >= oldLen) { + var indices = []; + for (var i = 0; i < newArr.length; i++) { + indices.push(i); + } + // Identity per the equality and tokenizer + return [{ + indices: indices, count: newArr.length + }]; + } + + // Main worker method. checks all permutations of a given edit length for acceptance. + function execEditLength() { + for (var diagonalPath = -1 * editLength; diagonalPath <= editLength; diagonalPath += 2) { + var basePath; + var addPath = bestPath[diagonalPath - 1]; + var removePath = bestPath[diagonalPath + 1]; + var oldPos = (removePath ? removePath.newPos : 0) - diagonalPath; + if (addPath) { + // No one else is going to attempt to use this value, clear it + bestPath[diagonalPath - 1] = undefined; + } + + var canAdd = addPath && addPath.newPos + 1 < newLen; + var canRemove = removePath && 0 <= oldPos && oldPos < oldLen; + if (!canAdd && !canRemove) { + // If this path is a terminal then prune + bestPath[diagonalPath] = undefined; + continue; + } + + // Select the diagonal that we want to branch from. We select the prior + // path whose position in the new string is the farthest from the origin + // and does not pass the bounds of the diff graph + if (!canAdd || (canRemove && addPath.newPos < removePath.newPos)) { + basePath = clonePath(removePath); + self.pushComponent(basePath.components, undefined, true); + } + else { + basePath = addPath; // No need to clone, we've pulled it from the list + basePath.newPos++; + self.pushComponent(basePath.components, true, undefined); + } + + oldPos = self.extractCommon(basePath, newArr, oldArr, diagonalPath); + + // If we have hit the end of both strings, then we are done + if (basePath.newPos + 1 >= newLen && oldPos + 1 >= oldLen) { + return buildValues(self, basePath.components, newArr, oldArr); + } + else { + // Otherwise track this path as a potential candidate and continue. + bestPath[diagonalPath] = basePath; + } + } + + editLength++; + } + + while (editLength <= maxEditLength) { + var ret = execEditLength(); + if (ret) { + return ret; + } + } + }, + + pushComponent: function (components, added, removed) { + var last = components[components.length - 1]; + if (last && last.added === added && last.removed === removed) { + // We need to clone here as the component clone operation is just + // as shallow array clone + components[components.length - 1] = {count: last.count + 1, added: added, removed: removed }; + } + else { + components.push({count: 1, added: added, removed: removed }); + } + }, + extractCommon: function (basePath, newArr, oldArr, diagonalPath) { + var newLen = newArr.length; + var oldLen = oldArr.length; + var newPos = basePath.newPos; + var oldPos = newPos - diagonalPath; + var commonCount = 0; + + while (newPos + 1 < newLen && oldPos + 1 < oldLen && this.equals(newArr[newPos + 1], oldArr[oldPos + 1])) { + newPos++; + oldPos++; + commonCount++; + } + + if (commonCount) { + basePath.components.push({count: commonCount}); + } + + basePath.newPos = newPos; + return oldPos; + }, + tokenize: function (value) { + return value.slice(); + }, + join: function (value) { + return value.slice(); + } +}; + +function buildValues(diff, components, newArr, oldArr) { + var componentPos = 0; + var componentLen = components.length; + var newPos = 0; + var oldPos = 0; + + for (; componentPos < componentLen; componentPos++) { + var component = components[componentPos]; + if (!component.removed) { + var indices = []; + for (var i = newPos; i < newPos + component.count; i++) { + indices.push(i); + } + component.indices = indices; + newPos += component.count; + // Common case + if (!component.added) { + oldPos += component.count; + } + } + else { + var indices = []; + for (var i = oldPos; i < oldPos + component.count; i++) { + indices.push(i); + } + component.indices = indices; + oldPos += component.count; + } + } + + return components; +} + +function clonePath(path) { + return { newPos: path.newPos, components: path.components.slice(0) }; +} + +var arrayDiff = new Diff(); + +var arrayDiff$1 = function (oldArr, newArr, callback) { + return arrayDiff.diff(oldArr, newArr, callback); +}; + +/** + * @file Manages elements that can be defined in in SVG, + * e.g., gradients, clip path, etc. + * @author Zhang Wenli + */ + +var MARK_UNUSED = '0'; +var MARK_USED = '1'; + +/** + * Manages elements that can be defined in in SVG, + * e.g., gradients, clip path, etc. + * + * @class + * @param {number} zrId zrender instance id + * @param {SVGElement} svgRoot root of SVG document + * @param {string|string[]} tagNames possible tag names + * @param {string} markLabel label name to make if the element + * is used + */ +function Definable( + zrId, + svgRoot, + tagNames, + markLabel, + domName +) { + this._zrId = zrId; + this._svgRoot = svgRoot; + this._tagNames = typeof tagNames === 'string' ? [tagNames] : tagNames; + this._markLabel = markLabel; + this._domName = domName || '_dom'; + + this.nextId = 0; +} + + +Definable.prototype.createElement = createElement; + + +/** + * Get the tag for svgRoot; optionally creates one if not exists. + * + * @param {boolean} isForceCreating if need to create when not exists + * @return {SVGDefsElement} SVG element, null if it doesn't + * exist and isForceCreating is false + */ +Definable.prototype.getDefs = function (isForceCreating) { + var svgRoot = this._svgRoot; + var defs = this._svgRoot.getElementsByTagName('defs'); + if (defs.length === 0) { + // Not exist + if (isForceCreating) { + defs = svgRoot.insertBefore( + this.createElement('defs'), // Create new tag + svgRoot.firstChild // Insert in the front of svg + ); + if (!defs.contains) { + // IE doesn't support contains method + defs.contains = function (el) { + var children = defs.children; + if (!children) { + return false; + } + for (var i = children.length - 1; i >= 0; --i) { + if (children[i] === el) { + return true; + } + } + return false; + }; + } + return defs; + } + else { + return null; + } + } + else { + return defs[0]; + } +}; + + +/** + * Update DOM element if necessary. + * + * @param {Object|string} element style element. e.g., for gradient, + * it may be '#ccc' or {type: 'linear', ...} + * @param {Function|undefined} onUpdate update callback + */ +Definable.prototype.update = function (element, onUpdate) { + if (!element) { + return; + } + + var defs = this.getDefs(false); + if (element[this._domName] && defs.contains(element[this._domName])) { + // Update DOM + if (typeof onUpdate === 'function') { + onUpdate(element); + } + } + else { + // No previous dom, create new + var dom = this.add(element); + if (dom) { + element[this._domName] = dom; + } + } +}; + + +/** + * Add gradient dom to defs + * + * @param {SVGElement} dom DOM to be added to + */ +Definable.prototype.addDom = function (dom) { + var defs = this.getDefs(true); + defs.appendChild(dom); +}; + + +/** + * Remove DOM of a given element. + * + * @param {SVGElement} element element to remove dom + */ +Definable.prototype.removeDom = function (element) { + var defs = this.getDefs(false); + if (defs && element[this._domName]) { + defs.removeChild(element[this._domName]); + element[this._domName] = null; + } +}; + + +/** + * Get DOMs of this element. + * + * @return {HTMLDomElement} doms of this defineable elements in + */ +Definable.prototype.getDoms = function () { + var defs = this.getDefs(false); + if (!defs) { + // No dom when defs is not defined + return []; + } + + var doms = []; + each$1(this._tagNames, function (tagName) { + var tags = defs.getElementsByTagName(tagName); + // Note that tags is HTMLCollection, which is array-like + // rather than real array. + // So `doms.concat(tags)` add tags as one object. + doms = doms.concat([].slice.call(tags)); + }); + + return doms; +}; + + +/** + * Mark DOMs to be unused before painting, and clear unused ones at the end + * of the painting. + */ +Definable.prototype.markAllUnused = function () { + var doms = this.getDoms(); + var that = this; + each$1(doms, function (dom) { + dom[that._markLabel] = MARK_UNUSED; + }); +}; + + +/** + * Mark a single DOM to be used. + * + * @param {SVGElement} dom DOM to mark + */ +Definable.prototype.markUsed = function (dom) { + if (dom) { + dom[this._markLabel] = MARK_USED; + } +}; + + +/** + * Remove unused DOMs defined in + */ +Definable.prototype.removeUnused = function () { + var defs = this.getDefs(false); + if (!defs) { + // Nothing to remove + return; + } + + var doms = this.getDoms(); + var that = this; + each$1(doms, function (dom) { + if (dom[that._markLabel] !== MARK_USED) { + // Remove gradient + defs.removeChild(dom); + } + }); +}; + + +/** + * Get SVG proxy. + * + * @param {Displayable} displayable displayable element + * @return {Path|Image|Text} svg proxy of given element + */ +Definable.prototype.getSvgProxy = function (displayable) { + if (displayable instanceof Path) { + return svgPath; + } + else if (displayable instanceof ZImage) { + return svgImage; + } + else if (displayable instanceof Text) { + return svgText; + } + else { + return svgPath; + } +}; + + +/** + * Get text SVG element. + * + * @param {Displayable} displayable displayable element + * @return {SVGElement} SVG element of text + */ +Definable.prototype.getTextSvgElement = function (displayable) { + return displayable.__textSvgEl; +}; + + +/** + * Get SVG element. + * + * @param {Displayable} displayable displayable element + * @return {SVGElement} SVG element + */ +Definable.prototype.getSvgElement = function (displayable) { + return displayable.__svgEl; +}; + +/** + * @file Manages SVG gradient elements. + * @author Zhang Wenli + */ + +/** + * Manages SVG gradient elements. + * + * @class + * @extends Definable + * @param {number} zrId zrender instance id + * @param {SVGElement} svgRoot root of SVG document + */ +function GradientManager(zrId, svgRoot) { + Definable.call( + this, + zrId, + svgRoot, + ['linearGradient', 'radialGradient'], + '__gradient_in_use__' + ); +} + + +inherits(GradientManager, Definable); + + +/** + * Create new gradient DOM for fill or stroke if not exist, + * but will not update gradient if exists. + * + * @param {SvgElement} svgElement SVG element to paint + * @param {Displayable} displayable zrender displayable element + */ +GradientManager.prototype.addWithoutUpdate = function ( + svgElement, + displayable +) { + if (displayable && displayable.style) { + var that = this; + each$1(['fill', 'stroke'], function (fillOrStroke) { + if (displayable.style[fillOrStroke] + && (displayable.style[fillOrStroke].type === 'linear' + || displayable.style[fillOrStroke].type === 'radial') + ) { + var gradient = displayable.style[fillOrStroke]; + var defs = that.getDefs(true); + + // Create dom in if not exists + var dom; + if (gradient._dom) { + // Gradient exists + dom = gradient._dom; + if (!defs.contains(gradient._dom)) { + // _dom is no longer in defs, recreate + that.addDom(dom); + } + } + else { + // New dom + dom = that.add(gradient); + } + + that.markUsed(displayable); + + var id = dom.getAttribute('id'); + svgElement.setAttribute(fillOrStroke, 'url(#' + id + ')'); + } + }); + } +}; + + +/** + * Add a new gradient tag in + * + * @param {Gradient} gradient zr gradient instance + * @return {SVGLinearGradientElement | SVGRadialGradientElement} + * created DOM + */ +GradientManager.prototype.add = function (gradient) { + var dom; + if (gradient.type === 'linear') { + dom = this.createElement('linearGradient'); + } + else if (gradient.type === 'radial') { + dom = this.createElement('radialGradient'); + } + else { + zrLog('Illegal gradient type.'); + return null; + } + + // Set dom id with gradient id, since each gradient instance + // will have no more than one dom element. + // id may exists before for those dirty elements, in which case + // id should remain the same, and other attributes should be + // updated. + gradient.id = gradient.id || this.nextId++; + dom.setAttribute('id', 'zr' + this._zrId + + '-gradient-' + gradient.id); + + this.updateDom(gradient, dom); + this.addDom(dom); + + return dom; +}; + + +/** + * Update gradient. + * + * @param {Gradient} gradient zr gradient instance + */ +GradientManager.prototype.update = function (gradient) { + var that = this; + Definable.prototype.update.call(this, gradient, function () { + var type = gradient.type; + var tagName = gradient._dom.tagName; + if (type === 'linear' && tagName === 'linearGradient' + || type === 'radial' && tagName === 'radialGradient' + ) { + // Gradient type is not changed, update gradient + that.updateDom(gradient, gradient._dom); + } + else { + // Remove and re-create if type is changed + that.removeDom(gradient); + that.add(gradient); + } + }); +}; + + +/** + * Update gradient dom + * + * @param {Gradient} gradient zr gradient instance + * @param {SVGLinearGradientElement | SVGRadialGradientElement} dom + * DOM to update + */ +GradientManager.prototype.updateDom = function (gradient, dom) { + if (gradient.type === 'linear') { + dom.setAttribute('x1', gradient.x); + dom.setAttribute('y1', gradient.y); + dom.setAttribute('x2', gradient.x2); + dom.setAttribute('y2', gradient.y2); + } + else if (gradient.type === 'radial') { + dom.setAttribute('cx', gradient.x); + dom.setAttribute('cy', gradient.y); + dom.setAttribute('r', gradient.r); + } + else { + zrLog('Illegal gradient type.'); + return; + } + + if (gradient.global) { + // x1, x2, y1, y2 in range of 0 to canvas width or height + dom.setAttribute('gradientUnits', 'userSpaceOnUse'); + } + else { + // x1, x2, y1, y2 in range of 0 to 1 + dom.setAttribute('gradientUnits', 'objectBoundingBox'); + } + + // Remove color stops if exists + dom.innerHTML = ''; + + // Add color stops + var colors = gradient.colorStops; + for (var i = 0, len = colors.length; i < len; ++i) { + var stop = this.createElement('stop'); + stop.setAttribute('offset', colors[i].offset * 100 + '%'); + + var color = colors[i].color; + if (color.indexOf('rgba' > -1)) { + // Fix Safari bug that stop-color not recognizing alpha #9014 + var opacity = parse(color)[3]; + var hex = toHex(color); + + // stop-color cannot be color, since: + // The opacity value used for the gradient calculation is the + // *product* of the value of stop-opacity and the opacity of the + // value of stop-color. + // See https://www.w3.org/TR/SVG2/pservers.html#StopOpacityProperty + stop.setAttribute('stop-color', '#' + hex); + stop.setAttribute('stop-opacity', opacity); + } + else { + stop.setAttribute('stop-color', colors[i].color); + } + + dom.appendChild(stop); + } + + // Store dom element in gradient, to avoid creating multiple + // dom instances for the same gradient element + gradient._dom = dom; +}; + +/** + * Mark a single gradient to be used + * + * @param {Displayable} displayable displayable element + */ +GradientManager.prototype.markUsed = function (displayable) { + if (displayable.style) { + var gradient = displayable.style.fill; + if (gradient && gradient._dom) { + Definable.prototype.markUsed.call(this, gradient._dom); + } + + gradient = displayable.style.stroke; + if (gradient && gradient._dom) { + Definable.prototype.markUsed.call(this, gradient._dom); + } + } +}; + +/** + * @file Manages SVG clipPath elements. + * @author Zhang Wenli + */ + +/** + * Manages SVG clipPath elements. + * + * @class + * @extends Definable + * @param {number} zrId zrender instance id + * @param {SVGElement} svgRoot root of SVG document + */ +function ClippathManager(zrId, svgRoot) { + Definable.call(this, zrId, svgRoot, 'clipPath', '__clippath_in_use__'); +} + + +inherits(ClippathManager, Definable); + + +/** + * Update clipPath. + * + * @param {Displayable} displayable displayable element + */ +ClippathManager.prototype.update = function (displayable) { + var svgEl = this.getSvgElement(displayable); + if (svgEl) { + this.updateDom(svgEl, displayable.__clipPaths, false); + } + + var textEl = this.getTextSvgElement(displayable); + if (textEl) { + // Make another clipPath for text, since it's transform + // matrix is not the same with svgElement + this.updateDom(textEl, displayable.__clipPaths, true); + } + + this.markUsed(displayable); +}; + + +/** + * Create an SVGElement of displayable and create a of its + * clipPath + * + * @param {Displayable} parentEl parent element + * @param {ClipPath[]} clipPaths clipPaths of parent element + * @param {boolean} isText if parent element is Text + */ +ClippathManager.prototype.updateDom = function ( + parentEl, + clipPaths, + isText +) { + if (clipPaths && clipPaths.length > 0) { + // Has clipPath, create with the first clipPath + var defs = this.getDefs(true); + var clipPath = clipPaths[0]; + var clipPathEl; + var id; + + var dom = isText ? '_textDom' : '_dom'; + + if (clipPath[dom]) { + // Use a dom that is already in + id = clipPath[dom].getAttribute('id'); + clipPathEl = clipPath[dom]; + + // Use a dom that is already in + if (!defs.contains(clipPathEl)) { + // This happens when set old clipPath that has + // been previously removed + defs.appendChild(clipPathEl); + } + } + else { + // New + id = 'zr' + this._zrId + '-clip-' + this.nextId; + ++this.nextId; + clipPathEl = this.createElement('clipPath'); + clipPathEl.setAttribute('id', id); + defs.appendChild(clipPathEl); + + clipPath[dom] = clipPathEl; + } + + // Build path and add to + var svgProxy = this.getSvgProxy(clipPath); + if (clipPath.transform + && clipPath.parent.invTransform + && !isText + ) { + /** + * If a clipPath has a parent with transform, the transform + * of parent should not be considered when setting transform + * of clipPath. So we need to transform back from parent's + * transform, which is done by multiplying parent's inverse + * transform. + */ + // Store old transform + var transform = Array.prototype.slice.call( + clipPath.transform + ); + + // Transform back from parent, and brush path + mul$1( + clipPath.transform, + clipPath.parent.invTransform, + clipPath.transform + ); + svgProxy.brush(clipPath); + + // Set back transform of clipPath + clipPath.transform = transform; + } + else { + svgProxy.brush(clipPath); + } + + var pathEl = this.getSvgElement(clipPath); + + clipPathEl.innerHTML = ''; + /** + * Use `cloneNode()` here to appendChild to multiple parents, + * which may happend when Text and other shapes are using the same + * clipPath. Since Text will create an extra clipPath DOM due to + * different transform rules. + */ + clipPathEl.appendChild(pathEl.cloneNode()); + + parentEl.setAttribute('clip-path', 'url(#' + id + ')'); + + if (clipPaths.length > 1) { + // Make the other clipPaths recursively + this.updateDom(clipPathEl, clipPaths.slice(1), isText); + } + } + else { + // No clipPath + if (parentEl) { + parentEl.setAttribute('clip-path', 'none'); + } + } +}; + +/** + * Mark a single clipPath to be used + * + * @param {Displayable} displayable displayable element + */ +ClippathManager.prototype.markUsed = function (displayable) { + var that = this; + if (displayable.__clipPaths && displayable.__clipPaths.length > 0) { + each$1(displayable.__clipPaths, function (clipPath) { + if (clipPath._dom) { + Definable.prototype.markUsed.call(that, clipPath._dom); + } + if (clipPath._textDom) { + Definable.prototype.markUsed.call(that, clipPath._textDom); + } + }); + } +}; + +/** + * @file Manages SVG shadow elements. + * @author Zhang Wenli + */ + +/** + * Manages SVG shadow elements. + * + * @class + * @extends Definable + * @param {number} zrId zrender instance id + * @param {SVGElement} svgRoot root of SVG document + */ +function ShadowManager(zrId, svgRoot) { + Definable.call( + this, + zrId, + svgRoot, + ['filter'], + '__filter_in_use__', + '_shadowDom' + ); +} + + +inherits(ShadowManager, Definable); + + +/** + * Create new shadow DOM for fill or stroke if not exist, + * but will not update shadow if exists. + * + * @param {SvgElement} svgElement SVG element to paint + * @param {Displayable} displayable zrender displayable element + */ +ShadowManager.prototype.addWithoutUpdate = function ( + svgElement, + displayable +) { + if (displayable && hasShadow(displayable.style)) { + var style = displayable.style; + + // Create dom in if not exists + var dom; + if (style._shadowDom) { + // Gradient exists + dom = style._shadowDom; + + var defs = this.getDefs(true); + if (!defs.contains(style._shadowDom)) { + // _shadowDom is no longer in defs, recreate + this.addDom(dom); + } + } + else { + // New dom + dom = this.add(displayable); + } + + this.markUsed(displayable); + + var id = dom.getAttribute('id'); + svgElement.style.filter = 'url(#' + id + ')'; + } +}; + + +/** + * Add a new shadow tag in + * + * @param {Displayable} displayable zrender displayable element + * @return {SVGFilterElement} created DOM + */ +ShadowManager.prototype.add = function (displayable) { + var dom = this.createElement('filter'); + var style = displayable.style; + + // Set dom id with shadow id, since each shadow instance + // will have no more than one dom element. + // id may exists before for those dirty elements, in which case + // id should remain the same, and other attributes should be + // updated. + style._shadowDomId = style._shadowDomId || this.nextId++; + dom.setAttribute('id', 'zr' + this._zrId + + '-shadow-' + style._shadowDomId); + + this.updateDom(displayable, dom); + this.addDom(dom); + + return dom; +}; + + +/** + * Update shadow. + * + * @param {Displayable} displayable zrender displayable element + */ +ShadowManager.prototype.update = function (svgElement, displayable) { + var style = displayable.style; + if (hasShadow(style)) { + var that = this; + Definable.prototype.update.call(this, displayable, function (style) { + that.updateDom(displayable, style._shadowDom); + }); + } + else { + // Remove shadow + this.remove(svgElement, style); + } +}; + + +/** + * Remove DOM and clear parent filter + */ +ShadowManager.prototype.remove = function (svgElement, style) { + if (style._shadowDomId != null) { + this.removeDom(style); + svgElement.style.filter = ''; + } +}; + + +/** + * Update shadow dom + * + * @param {Displayable} displayable zrender displayable element + * @param {SVGFilterElement} dom DOM to update + */ +ShadowManager.prototype.updateDom = function (displayable, dom) { + var domChild = dom.getElementsByTagName('feDropShadow'); + if (domChild.length === 0) { + domChild = this.createElement('feDropShadow'); + } + else { + domChild = domChild[0]; + } + + var style = displayable.style; + var scaleX = displayable.scale ? (displayable.scale[0] || 1) : 1; + var scaleY = displayable.scale ? (displayable.scale[1] || 1) : 1; + + // TODO: textBoxShadowBlur is not supported yet + var offsetX, offsetY, blur, color; + if (style.shadowBlur || style.shadowOffsetX || style.shadowOffsetY) { + offsetX = style.shadowOffsetX || 0; + offsetY = style.shadowOffsetY || 0; + blur = style.shadowBlur; + color = style.shadowColor; + } + else if (style.textShadowBlur) { + offsetX = style.textShadowOffsetX || 0; + offsetY = style.textShadowOffsetY || 0; + blur = style.textShadowBlur; + color = style.textShadowColor; + } + else { + // Remove shadow + this.removeDom(dom, style); + return; + } + + domChild.setAttribute('dx', offsetX / scaleX); + domChild.setAttribute('dy', offsetY / scaleY); + domChild.setAttribute('flood-color', color); + + // Divide by two here so that it looks the same as in canvas + // See: https://html.spec.whatwg.org/multipage/canvas.html#dom-context-2d-shadowblur + var stdDx = blur / 2 / scaleX; + var stdDy = blur / 2 / scaleY; + var stdDeviation = stdDx + ' ' + stdDy; + domChild.setAttribute('stdDeviation', stdDeviation); + + // Fix filter clipping problem + dom.setAttribute('x', '-100%'); + dom.setAttribute('y', '-100%'); + dom.setAttribute('width', Math.ceil(blur / 2 * 200) + '%'); + dom.setAttribute('height', Math.ceil(blur / 2 * 200) + '%'); + + dom.appendChild(domChild); + + // Store dom element in shadow, to avoid creating multiple + // dom instances for the same shadow element + style._shadowDom = dom; +}; + +/** + * Mark a single shadow to be used + * + * @param {Displayable} displayable displayable element + */ +ShadowManager.prototype.markUsed = function (displayable) { + var style = displayable.style; + if (style && style._shadowDom) { + Definable.prototype.markUsed.call(this, style._shadowDom); + } +}; + +function hasShadow(style) { + // TODO: textBoxShadowBlur is not supported yet + return style + && (style.shadowBlur || style.shadowOffsetX || style.shadowOffsetY + || style.textShadowBlur || style.textShadowOffsetX + || style.textShadowOffsetY); +} + +/** + * SVG Painter + * @module zrender/svg/Painter + */ + +function parseInt10$2(val) { + return parseInt(val, 10); +} + +function getSvgProxy(el) { + if (el instanceof Path) { + return svgPath; + } + else if (el instanceof ZImage) { + return svgImage; + } + else if (el instanceof Text) { + return svgText; + } + else { + return svgPath; + } +} + +function checkParentAvailable(parent, child) { + return child && parent && child.parentNode !== parent; +} + +function insertAfter(parent, child, prevSibling) { + if (checkParentAvailable(parent, child) && prevSibling) { + var nextSibling = prevSibling.nextSibling; + nextSibling ? parent.insertBefore(child, nextSibling) + : parent.appendChild(child); + } +} + +function prepend(parent, child) { + if (checkParentAvailable(parent, child)) { + var firstChild = parent.firstChild; + firstChild ? parent.insertBefore(child, firstChild) + : parent.appendChild(child); + } +} + +function remove$1(parent, child) { + if (child && parent && child.parentNode === parent) { + parent.removeChild(child); + } +} + +function getTextSvgElement(displayable) { + return displayable.__textSvgEl; +} + +function getSvgElement(displayable) { + return displayable.__svgEl; +} + +/** + * @alias module:zrender/svg/Painter + * @constructor + * @param {HTMLElement} root 绘图容器 + * @param {module:zrender/Storage} storage + * @param {Object} opts + */ +var SVGPainter = function (root, storage, opts, zrId) { + + this.root = root; + this.storage = storage; + this._opts = opts = extend({}, opts || {}); + + var svgRoot = createElement('svg'); + svgRoot.setAttribute('xmlns', 'http://www.w3.org/2000/svg'); + svgRoot.setAttribute('version', '1.1'); + svgRoot.setAttribute('baseProfile', 'full'); + svgRoot.style.cssText = 'user-select:none;position:absolute;left:0;top:0;'; + + this.gradientManager = new GradientManager(zrId, svgRoot); + this.clipPathManager = new ClippathManager(zrId, svgRoot); + this.shadowManager = new ShadowManager(zrId, svgRoot); + + var viewport = document.createElement('div'); + viewport.style.cssText = 'overflow:hidden;position:relative'; + + this._svgRoot = svgRoot; + this._viewport = viewport; + + root.appendChild(viewport); + viewport.appendChild(svgRoot); + + this.resize(opts.width, opts.height); + + this._visibleList = []; +}; + +SVGPainter.prototype = { + + constructor: SVGPainter, + + getType: function () { + return 'svg'; + }, + + getViewportRoot: function () { + return this._viewport; + }, + + getViewportRootOffset: function () { + var viewportRoot = this.getViewportRoot(); + if (viewportRoot) { + return { + offsetLeft: viewportRoot.offsetLeft || 0, + offsetTop: viewportRoot.offsetTop || 0 + }; + } + }, + + refresh: function () { + + var list = this.storage.getDisplayList(true); + + this._paintList(list); + }, + + setBackgroundColor: function (backgroundColor) { + // TODO gradient + this._viewport.style.background = backgroundColor; + }, + + _paintList: function (list) { + this.gradientManager.markAllUnused(); + this.clipPathManager.markAllUnused(); + this.shadowManager.markAllUnused(); + + var svgRoot = this._svgRoot; + var visibleList = this._visibleList; + var listLen = list.length; + + var newVisibleList = []; + var i; + for (i = 0; i < listLen; i++) { + var displayable = list[i]; + var svgProxy = getSvgProxy(displayable); + var svgElement = getSvgElement(displayable) + || getTextSvgElement(displayable); + if (!displayable.invisible) { + if (displayable.__dirty) { + svgProxy && svgProxy.brush(displayable); + + // Update clipPath + this.clipPathManager.update(displayable); + + // Update gradient and shadow + if (displayable.style) { + this.gradientManager + .update(displayable.style.fill); + this.gradientManager + .update(displayable.style.stroke); + + this.shadowManager + .update(svgElement, displayable); + } + + displayable.__dirty = false; + } + newVisibleList.push(displayable); + } + } + + var diff = arrayDiff$1(visibleList, newVisibleList); + var prevSvgElement; + + // First do remove, in case element moved to the head and do remove + // after add + for (i = 0; i < diff.length; i++) { + var item = diff[i]; + if (item.removed) { + for (var k = 0; k < item.count; k++) { + var displayable = visibleList[item.indices[k]]; + var svgElement = getSvgElement(displayable); + var textSvgElement = getTextSvgElement(displayable); + remove$1(svgRoot, svgElement); + remove$1(svgRoot, textSvgElement); + } + } + } + for (i = 0; i < diff.length; i++) { + var item = diff[i]; + if (item.added) { + for (var k = 0; k < item.count; k++) { + var displayable = newVisibleList[item.indices[k]]; + var svgElement = getSvgElement(displayable); + var textSvgElement = getTextSvgElement(displayable); + prevSvgElement + ? insertAfter(svgRoot, svgElement, prevSvgElement) + : prepend(svgRoot, svgElement); + if (svgElement) { + insertAfter(svgRoot, textSvgElement, svgElement); + } + else if (prevSvgElement) { + insertAfter( + svgRoot, textSvgElement, prevSvgElement + ); + } + else { + prepend(svgRoot, textSvgElement); + } + // Insert text + insertAfter(svgRoot, textSvgElement, svgElement); + prevSvgElement = textSvgElement || svgElement + || prevSvgElement; + + this.gradientManager + .addWithoutUpdate(svgElement, displayable); + this.shadowManager + .addWithoutUpdate(prevSvgElement, displayable); + this.clipPathManager.markUsed(displayable); + } + } + else if (!item.removed) { + for (var k = 0; k < item.count; k++) { + var displayable = newVisibleList[item.indices[k]]; + prevSvgElement = + svgElement = + getTextSvgElement(displayable) + || getSvgElement(displayable) + || prevSvgElement; + + this.gradientManager.markUsed(displayable); + this.gradientManager + .addWithoutUpdate(svgElement, displayable); + + this.shadowManager.markUsed(displayable); + this.shadowManager + .addWithoutUpdate(svgElement, displayable); + + this.clipPathManager.markUsed(displayable); + } + } + } + + this.gradientManager.removeUnused(); + this.clipPathManager.removeUnused(); + this.shadowManager.removeUnused(); + + this._visibleList = newVisibleList; + }, + + _getDefs: function (isForceCreating) { + var svgRoot = this._svgRoot; + var defs = this._svgRoot.getElementsByTagName('defs'); + if (defs.length === 0) { + // Not exist + if (isForceCreating) { + var defs = svgRoot.insertBefore( + createElement('defs'), // Create new tag + svgRoot.firstChild // Insert in the front of svg + ); + if (!defs.contains) { + // IE doesn't support contains method + defs.contains = function (el) { + var children = defs.children; + if (!children) { + return false; + } + for (var i = children.length - 1; i >= 0; --i) { + if (children[i] === el) { + return true; + } + } + return false; + }; + } + return defs; + } + else { + return null; + } + } + else { + return defs[0]; + } + }, + + resize: function (width, height) { + var viewport = this._viewport; + // FIXME Why ? + viewport.style.display = 'none'; + + // Save input w/h + var opts = this._opts; + width != null && (opts.width = width); + height != null && (opts.height = height); + + width = this._getSize(0); + height = this._getSize(1); + + viewport.style.display = ''; + + if (this._width !== width || this._height !== height) { + this._width = width; + this._height = height; + + var viewportStyle = viewport.style; + viewportStyle.width = width + 'px'; + viewportStyle.height = height + 'px'; + + var svgRoot = this._svgRoot; + // Set width by 'svgRoot.width = width' is invalid + svgRoot.setAttribute('width', width); + svgRoot.setAttribute('height', height); + } + }, + + /** + * 获取绘图区域宽度 + */ + getWidth: function () { + return this._width; + }, + + /** + * 获取绘图区域高度 + */ + getHeight: function () { + return this._height; + }, + + _getSize: function (whIdx) { + var opts = this._opts; + var wh = ['width', 'height'][whIdx]; + var cwh = ['clientWidth', 'clientHeight'][whIdx]; + var plt = ['paddingLeft', 'paddingTop'][whIdx]; + var prb = ['paddingRight', 'paddingBottom'][whIdx]; + + if (opts[wh] != null && opts[wh] !== 'auto') { + return parseFloat(opts[wh]); + } + + var root = this.root; + // IE8 does not support getComputedStyle, but it use VML. + var stl = document.defaultView.getComputedStyle(root); + + return ( + (root[cwh] || parseInt10$2(stl[wh]) || parseInt10$2(root.style[wh])) + - (parseInt10$2(stl[plt]) || 0) + - (parseInt10$2(stl[prb]) || 0) + ) | 0; + }, + + dispose: function () { + this.root.innerHTML = ''; + + this._svgRoot = + this._viewport = + this.storage = + null; + }, + + clear: function () { + if (this._viewport) { + this.root.removeChild(this._viewport); + } + }, + + pathToDataUrl: function () { + this.refresh(); + var html = this._svgRoot.outerHTML; + return 'data:image/svg+xml;charset=UTF-8,' + html; + } +}; + +// Not supported methods +function createMethodNotSupport$1(method) { + return function () { + zrLog('In SVG mode painter not support method "' + method + '"'); + }; +} + +// Unsuppoted methods +each$1([ + 'getLayer', 'insertLayer', 'eachLayer', 'eachBuiltinLayer', + 'eachOtherLayer', 'getLayers', 'modLayer', 'delLayer', 'clearLayer', + 'toDataURL', 'pathToImage' +], function (name) { + SVGPainter.prototype[name] = createMethodNotSupport$1(name); +}); + +registerPainter('svg', SVGPainter); + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +// Import all charts and components + +exports.version = version; +exports.dependencies = dependencies; +exports.PRIORITY = PRIORITY; +exports.init = init; +exports.connect = connect; +exports.disConnect = disConnect; +exports.disconnect = disconnect; +exports.dispose = dispose; +exports.getInstanceByDom = getInstanceByDom; +exports.getInstanceById = getInstanceById; +exports.registerTheme = registerTheme; +exports.registerPreprocessor = registerPreprocessor; +exports.registerProcessor = registerProcessor; +exports.registerPostUpdate = registerPostUpdate; +exports.registerAction = registerAction; +exports.registerCoordinateSystem = registerCoordinateSystem; +exports.getCoordinateSystemDimensions = getCoordinateSystemDimensions; +exports.registerLayout = registerLayout; +exports.registerVisual = registerVisual; +exports.registerLoading = registerLoading; +exports.extendComponentModel = extendComponentModel; +exports.extendComponentView = extendComponentView; +exports.extendSeriesModel = extendSeriesModel; +exports.extendChartView = extendChartView; +exports.setCanvasCreator = setCanvasCreator; +exports.registerMap = registerMap; +exports.getMap = getMap; +exports.dataTool = dataTool; +exports.zrender = zrender; +exports.number = number; +exports.format = format; +exports.throttle = throttle; +exports.helper = helper; +exports.matrix = matrix; +exports.vector = vector; +exports.color = color; +exports.parseGeoJSON = parseGeoJson$1; +exports.parseGeoJson = parseGeoJson; +exports.util = ecUtil; +exports.graphic = graphic$1; +exports.List = List; +exports.Model = Model; +exports.Axis = Axis; +exports.env = env$1; + +}))); +//# sourceMappingURL=echarts.js.map diff --git "a/web/114 HELLO\345\205\261\344\272\253\345\215\225\350\275\246\350\277\220\350\220\245\347\256\241\347\220\206\345\271\263\345\217\260/js/jquery.js" "b/web/114 HELLO\345\205\261\344\272\253\345\215\225\350\275\246\350\277\220\350\220\245\347\256\241\347\220\206\345\271\263\345\217\260/js/jquery.js" new file mode 100644 index 00000000..fad9ab12 --- /dev/null +++ "b/web/114 HELLO\345\205\261\344\272\253\345\215\225\350\275\246\350\277\220\350\220\245\347\256\241\347\220\206\345\271\263\345\217\260/js/jquery.js" @@ -0,0 +1,5 @@ +/*! jQuery v2.1.4 | (c) 2005, 2015 jQuery Foundation, Inc. | jquery.org/license */ +!function(a,b){"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){var c=[],d=c.slice,e=c.concat,f=c.push,g=c.indexOf,h={},i=h.toString,j=h.hasOwnProperty,k={},l=a.document,m="2.1.4",n=function(a,b){return new n.fn.init(a,b)},o=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,p=/^-ms-/,q=/-([\da-z])/gi,r=function(a,b){return b.toUpperCase()};n.fn=n.prototype={jquery:m,constructor:n,selector:"",length:0,toArray:function(){return d.call(this)},get:function(a){return null!=a?0>a?this[a+this.length]:this[a]:d.call(this)},pushStack:function(a){var b=n.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a,b){return n.each(this,a,b)},map:function(a){return this.pushStack(n.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(d.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor(null)},push:f,sort:c.sort,splice:c.splice},n.extend=n.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||n.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(a=arguments[h]))for(b in a)c=g[b],d=a[b],g!==d&&(j&&d&&(n.isPlainObject(d)||(e=n.isArray(d)))?(e?(e=!1,f=c&&n.isArray(c)?c:[]):f=c&&n.isPlainObject(c)?c:{},g[b]=n.extend(j,f,d)):void 0!==d&&(g[b]=d));return g},n.extend({expando:"jQuery"+(m+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===n.type(a)},isArray:Array.isArray,isWindow:function(a){return null!=a&&a===a.window},isNumeric:function(a){return!n.isArray(a)&&a-parseFloat(a)+1>=0},isPlainObject:function(a){return"object"!==n.type(a)||a.nodeType||n.isWindow(a)?!1:a.constructor&&!j.call(a.constructor.prototype,"isPrototypeOf")?!1:!0},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?h[i.call(a)]||"object":typeof a},globalEval:function(a){var b,c=eval;a=n.trim(a),a&&(1===a.indexOf("use strict")?(b=l.createElement("script"),b.text=a,l.head.appendChild(b).parentNode.removeChild(b)):c(a))},camelCase:function(a){return a.replace(p,"ms-").replace(q,r)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b,c){var d,e=0,f=a.length,g=s(a);if(c){if(g){for(;f>e;e++)if(d=b.apply(a[e],c),d===!1)break}else for(e in a)if(d=b.apply(a[e],c),d===!1)break}else if(g){for(;f>e;e++)if(d=b.call(a[e],e,a[e]),d===!1)break}else for(e in a)if(d=b.call(a[e],e,a[e]),d===!1)break;return a},trim:function(a){return null==a?"":(a+"").replace(o,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(s(Object(a))?n.merge(c,"string"==typeof a?[a]:a):f.call(c,a)),c},inArray:function(a,b,c){return null==b?-1:g.call(b,a,c)},merge:function(a,b){for(var c=+b.length,d=0,e=a.length;c>d;d++)a[e++]=b[d];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,f=0,g=a.length,h=s(a),i=[];if(h)for(;g>f;f++)d=b(a[f],f,c),null!=d&&i.push(d);else for(f in a)d=b(a[f],f,c),null!=d&&i.push(d);return e.apply([],i)},guid:1,proxy:function(a,b){var c,e,f;return"string"==typeof b&&(c=a[b],b=a,a=c),n.isFunction(a)?(e=d.call(arguments,2),f=function(){return a.apply(b||this,e.concat(d.call(arguments)))},f.guid=a.guid=a.guid||n.guid++,f):void 0},now:Date.now,support:k}),n.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(a,b){h["[object "+b+"]"]=b.toLowerCase()});function s(a){var b="length"in a&&a.length,c=n.type(a);return"function"===c||n.isWindow(a)?!1:1===a.nodeType&&b?!0:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var t=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+1*new Date,v=a.document,w=0,x=0,y=ha(),z=ha(),A=ha(),B=function(a,b){return a===b&&(l=!0),0},C=1<<31,D={}.hasOwnProperty,E=[],F=E.pop,G=E.push,H=E.push,I=E.slice,J=function(a,b){for(var c=0,d=a.length;d>c;c++)if(a[c]===b)return c;return-1},K="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",L="[\\x20\\t\\r\\n\\f]",M="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",N=M.replace("w","w#"),O="\\["+L+"*("+M+")(?:"+L+"*([*^$|!~]?=)"+L+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+N+"))|)"+L+"*\\]",P=":("+M+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+O+")*)|.*)\\)|)",Q=new RegExp(L+"+","g"),R=new RegExp("^"+L+"+|((?:^|[^\\\\])(?:\\\\.)*)"+L+"+$","g"),S=new RegExp("^"+L+"*,"+L+"*"),T=new RegExp("^"+L+"*([>+~]|"+L+")"+L+"*"),U=new RegExp("="+L+"*([^\\]'\"]*?)"+L+"*\\]","g"),V=new RegExp(P),W=new RegExp("^"+N+"$"),X={ID:new RegExp("^#("+M+")"),CLASS:new RegExp("^\\.("+M+")"),TAG:new RegExp("^("+M.replace("w","w*")+")"),ATTR:new RegExp("^"+O),PSEUDO:new RegExp("^"+P),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+L+"*(even|odd|(([+-]|)(\\d*)n|)"+L+"*(?:([+-]|)"+L+"*(\\d+)|))"+L+"*\\)|)","i"),bool:new RegExp("^(?:"+K+")$","i"),needsContext:new RegExp("^"+L+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+L+"*((?:-\\d)?\\d*)"+L+"*\\)|)(?=[^-]|$)","i")},Y=/^(?:input|select|textarea|button)$/i,Z=/^h\d$/i,$=/^[^{]+\{\s*\[native \w/,_=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,aa=/[+~]/,ba=/'|\\/g,ca=new RegExp("\\\\([\\da-f]{1,6}"+L+"?|("+L+")|.)","ig"),da=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:0>d?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)},ea=function(){m()};try{H.apply(E=I.call(v.childNodes),v.childNodes),E[v.childNodes.length].nodeType}catch(fa){H={apply:E.length?function(a,b){G.apply(a,I.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function ga(a,b,d,e){var f,h,j,k,l,o,r,s,w,x;if((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,d=d||[],k=b.nodeType,"string"!=typeof a||!a||1!==k&&9!==k&&11!==k)return d;if(!e&&p){if(11!==k&&(f=_.exec(a)))if(j=f[1]){if(9===k){if(h=b.getElementById(j),!h||!h.parentNode)return d;if(h.id===j)return d.push(h),d}else if(b.ownerDocument&&(h=b.ownerDocument.getElementById(j))&&t(b,h)&&h.id===j)return d.push(h),d}else{if(f[2])return H.apply(d,b.getElementsByTagName(a)),d;if((j=f[3])&&c.getElementsByClassName)return H.apply(d,b.getElementsByClassName(j)),d}if(c.qsa&&(!q||!q.test(a))){if(s=r=u,w=b,x=1!==k&&a,1===k&&"object"!==b.nodeName.toLowerCase()){o=g(a),(r=b.getAttribute("id"))?s=r.replace(ba,"\\$&"):b.setAttribute("id",s),s="[id='"+s+"'] ",l=o.length;while(l--)o[l]=s+ra(o[l]);w=aa.test(a)&&pa(b.parentNode)||b,x=o.join(",")}if(x)try{return H.apply(d,w.querySelectorAll(x)),d}catch(y){}finally{r||b.removeAttribute("id")}}}return i(a.replace(R,"$1"),b,d,e)}function ha(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function ia(a){return a[u]=!0,a}function ja(a){var b=n.createElement("div");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function ka(a,b){var c=a.split("|"),e=a.length;while(e--)d.attrHandle[c[e]]=b}function la(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&(~b.sourceIndex||C)-(~a.sourceIndex||C);if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function ma(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function na(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function oa(a){return ia(function(b){return b=+b,ia(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function pa(a){return a&&"undefined"!=typeof a.getElementsByTagName&&a}c=ga.support={},f=ga.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?"HTML"!==b.nodeName:!1},m=ga.setDocument=function(a){var b,e,g=a?a.ownerDocument||a:v;return g!==n&&9===g.nodeType&&g.documentElement?(n=g,o=g.documentElement,e=g.defaultView,e&&e!==e.top&&(e.addEventListener?e.addEventListener("unload",ea,!1):e.attachEvent&&e.attachEvent("onunload",ea)),p=!f(g),c.attributes=ja(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=ja(function(a){return a.appendChild(g.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=$.test(g.getElementsByClassName),c.getById=ja(function(a){return o.appendChild(a).id=u,!g.getElementsByName||!g.getElementsByName(u).length}),c.getById?(d.find.ID=function(a,b){if("undefined"!=typeof b.getElementById&&p){var c=b.getElementById(a);return c&&c.parentNode?[c]:[]}},d.filter.ID=function(a){var b=a.replace(ca,da);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(ca,da);return function(a){var c="undefined"!=typeof a.getAttributeNode&&a.getAttributeNode("id");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return"undefined"!=typeof b.getElementsByTagName?b.getElementsByTagName(a):c.qsa?b.querySelectorAll(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){return p?b.getElementsByClassName(a):void 0},r=[],q=[],(c.qsa=$.test(g.querySelectorAll))&&(ja(function(a){o.appendChild(a).innerHTML="",a.querySelectorAll("[msallowcapture^='']").length&&q.push("[*^$]="+L+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+L+"*(?:value|"+K+")"),a.querySelectorAll("[id~="+u+"-]").length||q.push("~="),a.querySelectorAll(":checked").length||q.push(":checked"),a.querySelectorAll("a#"+u+"+*").length||q.push(".#.+[+~]")}),ja(function(a){var b=g.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+L+"*[*^$|!~]?="),a.querySelectorAll(":enabled").length||q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=$.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&ja(function(a){c.disconnectedMatch=s.call(a,"div"),s.call(a,"[s!='']:x"),r.push("!=",P)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=$.test(o.compareDocumentPosition),t=b||$.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===g||a.ownerDocument===v&&t(v,a)?-1:b===g||b.ownerDocument===v&&t(v,b)?1:k?J(k,a)-J(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,e=a.parentNode,f=b.parentNode,h=[a],i=[b];if(!e||!f)return a===g?-1:b===g?1:e?-1:f?1:k?J(k,a)-J(k,b):0;if(e===f)return la(a,b);c=a;while(c=c.parentNode)h.unshift(c);c=b;while(c=c.parentNode)i.unshift(c);while(h[d]===i[d])d++;return d?la(h[d],i[d]):h[d]===v?-1:i[d]===v?1:0},g):n},ga.matches=function(a,b){return ga(a,null,null,b)},ga.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(U,"='$1']"),!(!c.matchesSelector||!p||r&&r.test(b)||q&&q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return ga(b,n,null,[a]).length>0},ga.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},ga.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&D.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},ga.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},ga.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=ga.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=ga.selectors={cacheLength:50,createPseudo:ia,match:X,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(ca,da),a[3]=(a[3]||a[4]||a[5]||"").replace(ca,da),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||ga.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&ga.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return X.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&V.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(ca,da).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+L+")"+a+"("+L+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||"undefined"!=typeof a.getAttribute&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=ga.attr(d,a);return null==e?"!="===b:b?(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e.replace(Q," ")+" ").indexOf(c)>-1:"|="===b?e===c||e.slice(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h;if(q){if(f){while(p){l=b;while(l=l[p])if(h?l.nodeName.toLowerCase()===r:1===l.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){k=q[u]||(q[u]={}),j=k[a]||[],n=j[0]===w&&j[1],m=j[0]===w&&j[2],l=n&&q.childNodes[n];while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if(1===l.nodeType&&++m&&l===b){k[a]=[w,n,m];break}}else if(s&&(j=(b[u]||(b[u]={}))[a])&&j[0]===w)m=j[1];else while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if((h?l.nodeName.toLowerCase()===r:1===l.nodeType)&&++m&&(s&&((l[u]||(l[u]={}))[a]=[w,m]),l===b))break;return m-=e,m===d||m%d===0&&m/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||ga.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?ia(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=J(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:ia(function(a){var b=[],c=[],d=h(a.replace(R,"$1"));return d[u]?ia(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),b[0]=null,!c.pop()}}),has:ia(function(a){return function(b){return ga(a,b).length>0}}),contains:ia(function(a){return a=a.replace(ca,da),function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:ia(function(a){return W.test(a||"")||ga.error("unsupported lang: "+a),a=a.replace(ca,da).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return Z.test(a.nodeName)},input:function(a){return Y.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:oa(function(){return[0]}),last:oa(function(a,b){return[b-1]}),eq:oa(function(a,b,c){return[0>c?c+b:c]}),even:oa(function(a,b){for(var c=0;b>c;c+=2)a.push(c);return a}),odd:oa(function(a,b){for(var c=1;b>c;c+=2)a.push(c);return a}),lt:oa(function(a,b,c){for(var d=0>c?c+b:c;--d>=0;)a.push(d);return a}),gt:oa(function(a,b,c){for(var d=0>c?c+b:c;++db;b++)d+=a[b].value;return d}function sa(a,b,c){var d=b.dir,e=c&&"parentNode"===d,f=x++;return b.first?function(b,c,f){while(b=b[d])if(1===b.nodeType||e)return a(b,c,f)}:function(b,c,g){var h,i,j=[w,f];if(g){while(b=b[d])if((1===b.nodeType||e)&&a(b,c,g))return!0}else while(b=b[d])if(1===b.nodeType||e){if(i=b[u]||(b[u]={}),(h=i[d])&&h[0]===w&&h[1]===f)return j[2]=h[2];if(i[d]=j,j[2]=a(b,c,g))return!0}}}function ta(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function ua(a,b,c){for(var d=0,e=b.length;e>d;d++)ga(a,b[d],c);return c}function va(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;i>h;h++)(f=a[h])&&(!c||c(f,d,e))&&(g.push(f),j&&b.push(h));return g}function wa(a,b,c,d,e,f){return d&&!d[u]&&(d=wa(d)),e&&!e[u]&&(e=wa(e,f)),ia(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||ua(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:va(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=va(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?J(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=va(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):H.apply(g,r)})}function xa(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=sa(function(a){return a===b},h,!0),l=sa(function(a){return J(b,a)>-1},h,!0),m=[function(a,c,d){var e=!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d));return b=null,e}];f>i;i++)if(c=d.relative[a[i].type])m=[sa(ta(m),c)];else{if(c=d.filter[a[i].type].apply(null,a[i].matches),c[u]){for(e=++i;f>e;e++)if(d.relative[a[e].type])break;return wa(i>1&&ta(m),i>1&&ra(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(R,"$1"),c,e>i&&xa(a.slice(i,e)),f>e&&xa(a=a.slice(e)),f>e&&ra(a))}m.push(c)}return ta(m)}function ya(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,h,i,k){var l,m,o,p=0,q="0",r=f&&[],s=[],t=j,u=f||e&&d.find.TAG("*",k),v=w+=null==t?1:Math.random()||.1,x=u.length;for(k&&(j=g!==n&&g);q!==x&&null!=(l=u[q]);q++){if(e&&l){m=0;while(o=a[m++])if(o(l,g,h)){i.push(l);break}k&&(w=v)}c&&((l=!o&&l)&&p--,f&&r.push(l))}if(p+=q,c&&q!==p){m=0;while(o=b[m++])o(r,s,g,h);if(f){if(p>0)while(q--)r[q]||s[q]||(s[q]=F.call(i));s=va(s)}H.apply(i,s),k&&!f&&s.length>0&&p+b.length>1&&ga.uniqueSort(i)}return k&&(w=v,j=t),r};return c?ia(f):f}return h=ga.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=xa(b[c]),f[u]?d.push(f):e.push(f);f=A(a,ya(e,d)),f.selector=a}return f},i=ga.select=function(a,b,e,f){var i,j,k,l,m,n="function"==typeof a&&a,o=!f&&g(a=n.selector||a);if(e=e||[],1===o.length){if(j=o[0]=o[0].slice(0),j.length>2&&"ID"===(k=j[0]).type&&c.getById&&9===b.nodeType&&p&&d.relative[j[1].type]){if(b=(d.find.ID(k.matches[0].replace(ca,da),b)||[])[0],!b)return e;n&&(b=b.parentNode),a=a.slice(j.shift().value.length)}i=X.needsContext.test(a)?0:j.length;while(i--){if(k=j[i],d.relative[l=k.type])break;if((m=d.find[l])&&(f=m(k.matches[0].replace(ca,da),aa.test(j[0].type)&&pa(b.parentNode)||b))){if(j.splice(i,1),a=f.length&&ra(j),!a)return H.apply(e,f),e;break}}}return(n||h(a,o))(f,b,!p,e,aa.test(a)&&pa(b.parentNode)||b),e},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=ja(function(a){return 1&a.compareDocumentPosition(n.createElement("div"))}),ja(function(a){return a.innerHTML="","#"===a.firstChild.getAttribute("href")})||ka("type|href|height|width",function(a,b,c){return c?void 0:a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&ja(function(a){return a.innerHTML="",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||ka("value",function(a,b,c){return c||"input"!==a.nodeName.toLowerCase()?void 0:a.defaultValue}),ja(function(a){return null==a.getAttribute("disabled")})||ka(K,function(a,b,c){var d;return c?void 0:a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),ga}(a);n.find=t,n.expr=t.selectors,n.expr[":"]=n.expr.pseudos,n.unique=t.uniqueSort,n.text=t.getText,n.isXMLDoc=t.isXML,n.contains=t.contains;var u=n.expr.match.needsContext,v=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,w=/^.[^:#\[\.,]*$/;function x(a,b,c){if(n.isFunction(b))return n.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return n.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(w.test(b))return n.filter(b,a,c);b=n.filter(b,a)}return n.grep(a,function(a){return g.call(b,a)>=0!==c})}n.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?n.find.matchesSelector(d,a)?[d]:[]:n.find.matches(a,n.grep(b,function(a){return 1===a.nodeType}))},n.fn.extend({find:function(a){var b,c=this.length,d=[],e=this;if("string"!=typeof a)return this.pushStack(n(a).filter(function(){for(b=0;c>b;b++)if(n.contains(e[b],this))return!0}));for(b=0;c>b;b++)n.find(a,e[b],d);return d=this.pushStack(c>1?n.unique(d):d),d.selector=this.selector?this.selector+" "+a:a,d},filter:function(a){return this.pushStack(x(this,a||[],!1))},not:function(a){return this.pushStack(x(this,a||[],!0))},is:function(a){return!!x(this,"string"==typeof a&&u.test(a)?n(a):a||[],!1).length}});var y,z=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,A=n.fn.init=function(a,b){var c,d;if(!a)return this;if("string"==typeof a){if(c="<"===a[0]&&">"===a[a.length-1]&&a.length>=3?[null,a,null]:z.exec(a),!c||!c[1]&&b)return!b||b.jquery?(b||y).find(a):this.constructor(b).find(a);if(c[1]){if(b=b instanceof n?b[0]:b,n.merge(this,n.parseHTML(c[1],b&&b.nodeType?b.ownerDocument||b:l,!0)),v.test(c[1])&&n.isPlainObject(b))for(c in b)n.isFunction(this[c])?this[c](b[c]):this.attr(c,b[c]);return this}return d=l.getElementById(c[2]),d&&d.parentNode&&(this.length=1,this[0]=d),this.context=l,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):n.isFunction(a)?"undefined"!=typeof y.ready?y.ready(a):a(n):(void 0!==a.selector&&(this.selector=a.selector,this.context=a.context),n.makeArray(a,this))};A.prototype=n.fn,y=n(l);var B=/^(?:parents|prev(?:Until|All))/,C={children:!0,contents:!0,next:!0,prev:!0};n.extend({dir:function(a,b,c){var d=[],e=void 0!==c;while((a=a[b])&&9!==a.nodeType)if(1===a.nodeType){if(e&&n(a).is(c))break;d.push(a)}return d},sibling:function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c}}),n.fn.extend({has:function(a){var b=n(a,this),c=b.length;return this.filter(function(){for(var a=0;c>a;a++)if(n.contains(this,b[a]))return!0})},closest:function(a,b){for(var c,d=0,e=this.length,f=[],g=u.test(a)||"string"!=typeof a?n(a,b||this.context):0;e>d;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&n.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?n.unique(f):f)},index:function(a){return a?"string"==typeof a?g.call(n(a),this[0]):g.call(this,a.jquery?a[0]:a):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(n.unique(n.merge(this.get(),n(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function D(a,b){while((a=a[b])&&1!==a.nodeType);return a}n.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return n.dir(a,"parentNode")},parentsUntil:function(a,b,c){return n.dir(a,"parentNode",c)},next:function(a){return D(a,"nextSibling")},prev:function(a){return D(a,"previousSibling")},nextAll:function(a){return n.dir(a,"nextSibling")},prevAll:function(a){return n.dir(a,"previousSibling")},nextUntil:function(a,b,c){return n.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return n.dir(a,"previousSibling",c)},siblings:function(a){return n.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return n.sibling(a.firstChild)},contents:function(a){return a.contentDocument||n.merge([],a.childNodes)}},function(a,b){n.fn[a]=function(c,d){var e=n.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=n.filter(d,e)),this.length>1&&(C[a]||n.unique(e),B.test(a)&&e.reverse()),this.pushStack(e)}});var E=/\S+/g,F={};function G(a){var b=F[a]={};return n.each(a.match(E)||[],function(a,c){b[c]=!0}),b}n.Callbacks=function(a){a="string"==typeof a?F[a]||G(a):n.extend({},a);var b,c,d,e,f,g,h=[],i=!a.once&&[],j=function(l){for(b=a.memory&&l,c=!0,g=e||0,e=0,f=h.length,d=!0;h&&f>g;g++)if(h[g].apply(l[0],l[1])===!1&&a.stopOnFalse){b=!1;break}d=!1,h&&(i?i.length&&j(i.shift()):b?h=[]:k.disable())},k={add:function(){if(h){var c=h.length;!function g(b){n.each(b,function(b,c){var d=n.type(c);"function"===d?a.unique&&k.has(c)||h.push(c):c&&c.length&&"string"!==d&&g(c)})}(arguments),d?f=h.length:b&&(e=c,j(b))}return this},remove:function(){return h&&n.each(arguments,function(a,b){var c;while((c=n.inArray(b,h,c))>-1)h.splice(c,1),d&&(f>=c&&f--,g>=c&&g--)}),this},has:function(a){return a?n.inArray(a,h)>-1:!(!h||!h.length)},empty:function(){return h=[],f=0,this},disable:function(){return h=i=b=void 0,this},disabled:function(){return!h},lock:function(){return i=void 0,b||k.disable(),this},locked:function(){return!i},fireWith:function(a,b){return!h||c&&!i||(b=b||[],b=[a,b.slice?b.slice():b],d?i.push(b):j(b)),this},fire:function(){return k.fireWith(this,arguments),this},fired:function(){return!!c}};return k},n.extend({Deferred:function(a){var b=[["resolve","done",n.Callbacks("once memory"),"resolved"],["reject","fail",n.Callbacks("once memory"),"rejected"],["notify","progress",n.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return n.Deferred(function(c){n.each(b,function(b,f){var g=n.isFunction(a[b])&&a[b];e[f[1]](function(){var a=g&&g.apply(this,arguments);a&&n.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f[0]+"With"](this===d?c.promise():this,g?[a]:arguments)})}),a=null}).promise()},promise:function(a){return null!=a?n.extend(a,d):d}},e={};return d.pipe=d.then,n.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[1^a][2].disable,b[2][2].lock),e[f[0]]=function(){return e[f[0]+"With"](this===e?d:this,arguments),this},e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=d.call(arguments),e=c.length,f=1!==e||a&&n.isFunction(a.promise)?e:0,g=1===f?a:n.Deferred(),h=function(a,b,c){return function(e){b[a]=this,c[a]=arguments.length>1?d.call(arguments):e,c===i?g.notifyWith(b,c):--f||g.resolveWith(b,c)}},i,j,k;if(e>1)for(i=new Array(e),j=new Array(e),k=new Array(e);e>b;b++)c[b]&&n.isFunction(c[b].promise)?c[b].promise().done(h(b,k,c)).fail(g.reject).progress(h(b,j,i)):--f;return f||g.resolveWith(k,c),g.promise()}});var H;n.fn.ready=function(a){return n.ready.promise().done(a),this},n.extend({isReady:!1,readyWait:1,holdReady:function(a){a?n.readyWait++:n.ready(!0)},ready:function(a){(a===!0?--n.readyWait:n.isReady)||(n.isReady=!0,a!==!0&&--n.readyWait>0||(H.resolveWith(l,[n]),n.fn.triggerHandler&&(n(l).triggerHandler("ready"),n(l).off("ready"))))}});function I(){l.removeEventListener("DOMContentLoaded",I,!1),a.removeEventListener("load",I,!1),n.ready()}n.ready.promise=function(b){return H||(H=n.Deferred(),"complete"===l.readyState?setTimeout(n.ready):(l.addEventListener("DOMContentLoaded",I,!1),a.addEventListener("load",I,!1))),H.promise(b)},n.ready.promise();var J=n.access=function(a,b,c,d,e,f,g){var h=0,i=a.length,j=null==c;if("object"===n.type(c)){e=!0;for(h in c)n.access(a,b,h,c[h],!0,f,g)}else if(void 0!==d&&(e=!0,n.isFunction(d)||(g=!0),j&&(g?(b.call(a,d),b=null):(j=b,b=function(a,b,c){return j.call(n(a),c)})),b))for(;i>h;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f};n.acceptData=function(a){return 1===a.nodeType||9===a.nodeType||!+a.nodeType};function K(){Object.defineProperty(this.cache={},0,{get:function(){return{}}}),this.expando=n.expando+K.uid++}K.uid=1,K.accepts=n.acceptData,K.prototype={key:function(a){if(!K.accepts(a))return 0;var b={},c=a[this.expando];if(!c){c=K.uid++;try{b[this.expando]={value:c},Object.defineProperties(a,b)}catch(d){b[this.expando]=c,n.extend(a,b)}}return this.cache[c]||(this.cache[c]={}),c},set:function(a,b,c){var d,e=this.key(a),f=this.cache[e];if("string"==typeof b)f[b]=c;else if(n.isEmptyObject(f))n.extend(this.cache[e],b);else for(d in b)f[d]=b[d];return f},get:function(a,b){var c=this.cache[this.key(a)];return void 0===b?c:c[b]},access:function(a,b,c){var d;return void 0===b||b&&"string"==typeof b&&void 0===c?(d=this.get(a,b),void 0!==d?d:this.get(a,n.camelCase(b))):(this.set(a,b,c),void 0!==c?c:b)},remove:function(a,b){var c,d,e,f=this.key(a),g=this.cache[f];if(void 0===b)this.cache[f]={};else{n.isArray(b)?d=b.concat(b.map(n.camelCase)):(e=n.camelCase(b),b in g?d=[b,e]:(d=e,d=d in g?[d]:d.match(E)||[])),c=d.length;while(c--)delete g[d[c]]}},hasData:function(a){return!n.isEmptyObject(this.cache[a[this.expando]]||{})},discard:function(a){a[this.expando]&&delete this.cache[a[this.expando]]}};var L=new K,M=new K,N=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,O=/([A-Z])/g;function P(a,b,c){var d;if(void 0===c&&1===a.nodeType)if(d="data-"+b.replace(O,"-$1").toLowerCase(),c=a.getAttribute(d),"string"==typeof c){try{c="true"===c?!0:"false"===c?!1:"null"===c?null:+c+""===c?+c:N.test(c)?n.parseJSON(c):c}catch(e){}M.set(a,b,c)}else c=void 0;return c}n.extend({hasData:function(a){return M.hasData(a)||L.hasData(a)},data:function(a,b,c){ +return M.access(a,b,c)},removeData:function(a,b){M.remove(a,b)},_data:function(a,b,c){return L.access(a,b,c)},_removeData:function(a,b){L.remove(a,b)}}),n.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=M.get(f),1===f.nodeType&&!L.get(f,"hasDataAttrs"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.indexOf("data-")&&(d=n.camelCase(d.slice(5)),P(f,d,e[d])));L.set(f,"hasDataAttrs",!0)}return e}return"object"==typeof a?this.each(function(){M.set(this,a)}):J(this,function(b){var c,d=n.camelCase(a);if(f&&void 0===b){if(c=M.get(f,a),void 0!==c)return c;if(c=M.get(f,d),void 0!==c)return c;if(c=P(f,d,void 0),void 0!==c)return c}else this.each(function(){var c=M.get(this,d);M.set(this,d,b),-1!==a.indexOf("-")&&void 0!==c&&M.set(this,a,b)})},null,b,arguments.length>1,null,!0)},removeData:function(a){return this.each(function(){M.remove(this,a)})}}),n.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=L.get(a,b),c&&(!d||n.isArray(c)?d=L.access(a,b,n.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=n.queue(a,b),d=c.length,e=c.shift(),f=n._queueHooks(a,b),g=function(){n.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return L.get(a,c)||L.access(a,c,{empty:n.Callbacks("once memory").add(function(){L.remove(a,[b+"queue",c])})})}}),n.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.lengthx",k.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue}();var U="undefined";k.focusinBubbles="onfocusin"in a;var V=/^key/,W=/^(?:mouse|pointer|contextmenu)|click/,X=/^(?:focusinfocus|focusoutblur)$/,Y=/^([^.]*)(?:\.(.+)|)$/;function Z(){return!0}function $(){return!1}function _(){try{return l.activeElement}catch(a){}}n.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=L.get(a);if(r){c.handler&&(f=c,c=f.handler,e=f.selector),c.guid||(c.guid=n.guid++),(i=r.events)||(i=r.events={}),(g=r.handle)||(g=r.handle=function(b){return typeof n!==U&&n.event.triggered!==b.type?n.event.dispatch.apply(a,arguments):void 0}),b=(b||"").match(E)||[""],j=b.length;while(j--)h=Y.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o&&(l=n.event.special[o]||{},o=(e?l.delegateType:l.bindType)||o,l=n.event.special[o]||{},k=n.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&n.expr.match.needsContext.test(e),namespace:p.join(".")},f),(m=i[o])||(m=i[o]=[],m.delegateCount=0,l.setup&&l.setup.call(a,d,p,g)!==!1||a.addEventListener&&a.addEventListener(o,g,!1)),l.add&&(l.add.call(a,k),k.handler.guid||(k.handler.guid=c.guid)),e?m.splice(m.delegateCount++,0,k):m.push(k),n.event.global[o]=!0)}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=L.hasData(a)&&L.get(a);if(r&&(i=r.events)){b=(b||"").match(E)||[""],j=b.length;while(j--)if(h=Y.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o){l=n.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,m=i[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),g=f=m.length;while(f--)k=m[f],!e&&q!==k.origType||c&&c.guid!==k.guid||h&&!h.test(k.namespace)||d&&d!==k.selector&&("**"!==d||!k.selector)||(m.splice(f,1),k.selector&&m.delegateCount--,l.remove&&l.remove.call(a,k));g&&!m.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||n.removeEvent(a,o,r.handle),delete i[o])}else for(o in i)n.event.remove(a,o+b[j],c,d,!0);n.isEmptyObject(i)&&(delete r.handle,L.remove(a,"events"))}},trigger:function(b,c,d,e){var f,g,h,i,k,m,o,p=[d||l],q=j.call(b,"type")?b.type:b,r=j.call(b,"namespace")?b.namespace.split("."):[];if(g=h=d=d||l,3!==d.nodeType&&8!==d.nodeType&&!X.test(q+n.event.triggered)&&(q.indexOf(".")>=0&&(r=q.split("."),q=r.shift(),r.sort()),k=q.indexOf(":")<0&&"on"+q,b=b[n.expando]?b:new n.Event(q,"object"==typeof b&&b),b.isTrigger=e?2:3,b.namespace=r.join("."),b.namespace_re=b.namespace?new RegExp("(^|\\.)"+r.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=d),c=null==c?[b]:n.makeArray(c,[b]),o=n.event.special[q]||{},e||!o.trigger||o.trigger.apply(d,c)!==!1)){if(!e&&!o.noBubble&&!n.isWindow(d)){for(i=o.delegateType||q,X.test(i+q)||(g=g.parentNode);g;g=g.parentNode)p.push(g),h=g;h===(d.ownerDocument||l)&&p.push(h.defaultView||h.parentWindow||a)}f=0;while((g=p[f++])&&!b.isPropagationStopped())b.type=f>1?i:o.bindType||q,m=(L.get(g,"events")||{})[b.type]&&L.get(g,"handle"),m&&m.apply(g,c),m=k&&g[k],m&&m.apply&&n.acceptData(g)&&(b.result=m.apply(g,c),b.result===!1&&b.preventDefault());return b.type=q,e||b.isDefaultPrevented()||o._default&&o._default.apply(p.pop(),c)!==!1||!n.acceptData(d)||k&&n.isFunction(d[q])&&!n.isWindow(d)&&(h=d[k],h&&(d[k]=null),n.event.triggered=q,d[q](),n.event.triggered=void 0,h&&(d[k]=h)),b.result}},dispatch:function(a){a=n.event.fix(a);var b,c,e,f,g,h=[],i=d.call(arguments),j=(L.get(this,"events")||{})[a.type]||[],k=n.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=n.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,c=0;while((g=f.handlers[c++])&&!a.isImmediatePropagationStopped())(!a.namespace_re||a.namespace_re.test(g.namespace))&&(a.handleObj=g,a.data=g.data,e=((n.event.special[g.origType]||{}).handle||g.handler).apply(f.elem,i),void 0!==e&&(a.result=e)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&(!a.button||"click"!==a.type))for(;i!==this;i=i.parentNode||this)if(i.disabled!==!0||"click"!==a.type){for(d=[],c=0;h>c;c++)f=b[c],e=f.selector+" ",void 0===d[e]&&(d[e]=f.needsContext?n(e,this).index(i)>=0:n.find(e,this,null,[i]).length),d[e]&&d.push(f);d.length&&g.push({elem:i,handlers:d})}return h]*)\/>/gi,ba=/<([\w:]+)/,ca=/<|&#?\w+;/,da=/<(?:script|style|link)/i,ea=/checked\s*(?:[^=]|=\s*.checked.)/i,fa=/^$|\/(?:java|ecma)script/i,ga=/^true\/(.*)/,ha=/^\s*\s*$/g,ia={option:[1,""],thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};ia.optgroup=ia.option,ia.tbody=ia.tfoot=ia.colgroup=ia.caption=ia.thead,ia.th=ia.td;function ja(a,b){return n.nodeName(a,"table")&&n.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function ka(a){return a.type=(null!==a.getAttribute("type"))+"/"+a.type,a}function la(a){var b=ga.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function ma(a,b){for(var c=0,d=a.length;d>c;c++)L.set(a[c],"globalEval",!b||L.get(b[c],"globalEval"))}function na(a,b){var c,d,e,f,g,h,i,j;if(1===b.nodeType){if(L.hasData(a)&&(f=L.access(a),g=L.set(b,f),j=f.events)){delete g.handle,g.events={};for(e in j)for(c=0,d=j[e].length;d>c;c++)n.event.add(b,e,j[e][c])}M.hasData(a)&&(h=M.access(a),i=n.extend({},h),M.set(b,i))}}function oa(a,b){var c=a.getElementsByTagName?a.getElementsByTagName(b||"*"):a.querySelectorAll?a.querySelectorAll(b||"*"):[];return void 0===b||b&&n.nodeName(a,b)?n.merge([a],c):c}function pa(a,b){var c=b.nodeName.toLowerCase();"input"===c&&T.test(a.type)?b.checked=a.checked:("input"===c||"textarea"===c)&&(b.defaultValue=a.defaultValue)}n.extend({clone:function(a,b,c){var d,e,f,g,h=a.cloneNode(!0),i=n.contains(a.ownerDocument,a);if(!(k.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||n.isXMLDoc(a)))for(g=oa(h),f=oa(a),d=0,e=f.length;e>d;d++)pa(f[d],g[d]);if(b)if(c)for(f=f||oa(a),g=g||oa(h),d=0,e=f.length;e>d;d++)na(f[d],g[d]);else na(a,h);return g=oa(h,"script"),g.length>0&&ma(g,!i&&oa(a,"script")),h},buildFragment:function(a,b,c,d){for(var e,f,g,h,i,j,k=b.createDocumentFragment(),l=[],m=0,o=a.length;o>m;m++)if(e=a[m],e||0===e)if("object"===n.type(e))n.merge(l,e.nodeType?[e]:e);else if(ca.test(e)){f=f||k.appendChild(b.createElement("div")),g=(ba.exec(e)||["",""])[1].toLowerCase(),h=ia[g]||ia._default,f.innerHTML=h[1]+e.replace(aa,"<$1>")+h[2],j=h[0];while(j--)f=f.lastChild;n.merge(l,f.childNodes),f=k.firstChild,f.textContent=""}else l.push(b.createTextNode(e));k.textContent="",m=0;while(e=l[m++])if((!d||-1===n.inArray(e,d))&&(i=n.contains(e.ownerDocument,e),f=oa(k.appendChild(e),"script"),i&&ma(f),c)){j=0;while(e=f[j++])fa.test(e.type||"")&&c.push(e)}return k},cleanData:function(a){for(var b,c,d,e,f=n.event.special,g=0;void 0!==(c=a[g]);g++){if(n.acceptData(c)&&(e=c[L.expando],e&&(b=L.cache[e]))){if(b.events)for(d in b.events)f[d]?n.event.remove(c,d):n.removeEvent(c,d,b.handle);L.cache[e]&&delete L.cache[e]}delete M.cache[c[M.expando]]}}}),n.fn.extend({text:function(a){return J(this,function(a){return void 0===a?n.text(this):this.empty().each(function(){(1===this.nodeType||11===this.nodeType||9===this.nodeType)&&(this.textContent=a)})},null,a,arguments.length)},append:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=ja(this,a);b.appendChild(a)}})},prepend:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=ja(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},remove:function(a,b){for(var c,d=a?n.filter(a,this):this,e=0;null!=(c=d[e]);e++)b||1!==c.nodeType||n.cleanData(oa(c)),c.parentNode&&(b&&n.contains(c.ownerDocument,c)&&ma(oa(c,"script")),c.parentNode.removeChild(c));return this},empty:function(){for(var a,b=0;null!=(a=this[b]);b++)1===a.nodeType&&(n.cleanData(oa(a,!1)),a.textContent="");return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return n.clone(this,a,b)})},html:function(a){return J(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a&&1===b.nodeType)return b.innerHTML;if("string"==typeof a&&!da.test(a)&&!ia[(ba.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(aa,"<$1>");try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(n.cleanData(oa(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=arguments[0];return this.domManip(arguments,function(b){a=this.parentNode,n.cleanData(oa(this)),a&&a.replaceChild(b,this)}),a&&(a.length||a.nodeType)?this:this.remove()},detach:function(a){return this.remove(a,!0)},domManip:function(a,b){a=e.apply([],a);var c,d,f,g,h,i,j=0,l=this.length,m=this,o=l-1,p=a[0],q=n.isFunction(p);if(q||l>1&&"string"==typeof p&&!k.checkClone&&ea.test(p))return this.each(function(c){var d=m.eq(c);q&&(a[0]=p.call(this,c,d.html())),d.domManip(a,b)});if(l&&(c=n.buildFragment(a,this[0].ownerDocument,!1,this),d=c.firstChild,1===c.childNodes.length&&(c=d),d)){for(f=n.map(oa(c,"script"),ka),g=f.length;l>j;j++)h=c,j!==o&&(h=n.clone(h,!0,!0),g&&n.merge(f,oa(h,"script"))),b.call(this[j],h,j);if(g)for(i=f[f.length-1].ownerDocument,n.map(f,la),j=0;g>j;j++)h=f[j],fa.test(h.type||"")&&!L.access(h,"globalEval")&&n.contains(i,h)&&(h.src?n._evalUrl&&n._evalUrl(h.src):n.globalEval(h.textContent.replace(ha,"")))}return this}}),n.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){n.fn[a]=function(a){for(var c,d=[],e=n(a),g=e.length-1,h=0;g>=h;h++)c=h===g?this:this.clone(!0),n(e[h])[b](c),f.apply(d,c.get());return this.pushStack(d)}});var qa,ra={};function sa(b,c){var d,e=n(c.createElement(b)).appendTo(c.body),f=a.getDefaultComputedStyle&&(d=a.getDefaultComputedStyle(e[0]))?d.display:n.css(e[0],"display");return e.detach(),f}function ta(a){var b=l,c=ra[a];return c||(c=sa(a,b),"none"!==c&&c||(qa=(qa||n(" + +
+
+

馆藏图书

+

3367220

+
+
+

新增图书

+

76921

+
+
+

读者总数

+

271599

+
+
+

新增读者

+

19206

+
+
+

借阅总量

+

17741348

+
+
+

最近借阅

+

1066937

+
+
+ +
+ +
+ +
+
+

新增馆藏/新增读者分析

+
+ +
+
+
+
+
+ +
+
+

到馆人次/借阅册次分析

+ +
+ +
+
+
+
+
+ + +
+
+
+ +
+ +
+
+

实时客流分析

+
+
+
+
+
+

今日入馆

+
+
235
+
+
+
+
+
+
+

当前在馆

+
+
95
+
+
+
+
+
7小时内读者滞馆情况
+ +
+
+
+
+
+
+ +
+ +
+
+

最近24小时分管借阅情况

+
+
+
+
借阅位置
+
册次
+
最后借阅时间
+
+
+
+
上海图书馆综合借阅室
+
121
+
2024-08-25 17:00:00
+
+
+
上海图书馆璜土分管
+
105
+
2024-08-25 17:00:00
+
+
+
上海图书馆少儿馆
+
95
+
2024-08-25 17:00:00
+
+
+
上海图书馆嘉定分馆
+
84
+
2024-08-25 17:00:00
+
+
+
上海图书馆世纪广场
+
76
+
2024-08-25 17:00:00
+
+
+
上海图书馆长宁分馆
+
59
+
2024-08-25 17:00:00
+
+
+
上海图书馆少儿馆
+
49
+
2024-08-25 17:00:00
+
+
+
上海图书馆综合借阅室
+
44
+
2024-08-25 17:00:00
+
+
+
+
+ +
+
+

读者构成情况分析

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git "a/web/117 \344\270\212\346\265\267\345\270\202\345\233\276\344\271\246\351\246\206\345\244\247\345\261\217\347\234\213\346\235\277/static/citySelectData.js" "b/web/117 \344\270\212\346\265\267\345\270\202\345\233\276\344\271\246\351\246\206\345\244\247\345\261\217\347\234\213\346\235\277/static/citySelectData.js" new file mode 100644 index 00000000..399a568f --- /dev/null +++ "b/web/117 \344\270\212\346\265\267\345\270\202\345\233\276\344\271\246\351\246\206\345\244\247\345\261\217\347\234\213\346\235\277/static/citySelectData.js" @@ -0,0 +1,71 @@ +var prov=new Array(); +prov[12] = '12-B 北京-12'; +prov[37] = '37-T 天津-37'; +prov[34] = '34-S 上海-34'; +prov[43] = '43-C 重庆-43'; +prov[39] = '39-X 香港-39'; +prov[11] = '11-A 澳门-11'; +prov[36] = '36-T 台湾-36'; +prov[10]='58321-H 合肥-58321|58424-A 安庆-58424|58102-B 亳州-58102|58221-B 蚌埠-58221|58236-C 滁州-58236|58427-C 池州-58427|58203-F 阜阳-58203|58116-H 淮北-58116|58224-H 淮南-58224|70931-H 黄山-70931|58311-L 六安-58311|58336-M 马鞍山-58336|58122-S 宿州-58122|58429-T 铜陵-58429|58334-W 芜湖-58334|58433-X 宣城-58433' +prov[13]='58847-F 福州-58847|71415-D 钓鱼岛-71415|58927-L 龙岩-58927|58834-N 南平-58834|58846-N 宁德-58846|58946-P 莆田-58946|59131-Q 泉州-59131|58828-S 三明-58828|59134-X 厦门-59134|59126-Z 漳州-59126' +prov[14]='52889-L 兰州-52889|56080-G 甘南-56080|60472-L 陇南-60472|52896-B 白银-52896|52995-D 定西-52995|52675-J 金昌-52675|52533-J 酒泉-52533|71129-J 嘉峪关-71129|52984-L 临夏-52984|53915-P 平凉-53915|53923-Q 庆阳-53923|57006-T 天水-57006|52679-W 武威-52679|52652-Z 张掖-52652' +prov[15]='59287-G 广州-59287|59312-C 潮州-59312|59289-D 东莞-59289|59288-F 佛山-59288|59293-H 河源-59293|59297-H 惠州-59297|59473-J 江门-59473|59315-J 揭阳-59315|59109-M 梅州-59109|59659-M 茂名-59659|59280-Q 清远-59280|59493-S 深圳-59493|59316-S 汕头-59316|59082-S 韶关-59082|59501-S 汕尾-59501|59663-Y 阳江-59663|59471-Y 云浮-59471|59488-Z 珠海-59488|59485-Z 中山-59485|59658-Z 湛江-59658|59278-Z 肇庆-59278' +prov[16]='59431-N 南宁-59431|59644-B 北海-59644|59211-B 百色-59211|59425-C 崇左-59425|59635-F 防城港-59635|57957-G 桂林-57957|59249-G 贵港-59249|59065-H 贺州-59065|59023-H 河池-59023|59046-L 柳州-59046|59242-L 来宾-59242|59632-Q 钦州-59632|59265-W 梧州-59265|59453-Y 玉林-59453' +prov[17]='57816-G 贵阳-57816|57827-Q 黔南-57827|57825-Q 黔东南-57825|57806-A 安顺-57806|57707-B 毕节-57707|56693-L 六盘水-56693|70148-Q 黔西南-70148|57741-T 铜仁-57741|57713-Z 遵义-57713' +prov[18]='59758-H 海口-59758|59848-B 白沙-59848|59945-B 保亭-59945|59843-C 澄迈-59843|59847-C 昌江-59847|59845-D 儋州-59845|59851-D 定安-59851|59838-D 东方-59838|59842-L 临高-59842|59954-L 陵水-59954|59940-L 乐东-59940|59855-Q 琼海-59855|59849-Q 琼中-59849|59948-S 三亚-59948|71444-S 三沙-71444|59854-T 屯昌-59854|59856-W 文昌-59856|59951-W 万宁-59951|60651-W 五指山-60651' +prov[19]='53698-S 石家庄-53698|54602-B 保定-54602|54423-C 承德-54423|54616-C 沧州-54616|54702-H 衡水-54702|53892-H 邯郸-53892|54515-L 廊坊-54515|54449-Q 秦皇岛-54449|54534-T 唐山-54534|53798-X 邢台-53798|54401-Z 张家口-54401' +prov[20]='57083-Z 郑州-57083|53898-A 安阳-53898|53990-H 鹤壁-53990|53982-J 焦作-53982|53978-J 济源-53978|57091-K 开封-57091|57073-L 洛阳-57073|57186-L 漯河-57186|57178-N 南阳-57178|54900-P 濮阳-54900|71128-P 平顶山-71128|57051-S 三门峡-57051|58005-S 商丘-58005|53986-X 新乡-53986|57089-X 许昌-57089|57297-X 信阳-57297|57195-Z 周口-57195|57290-Z 驻马店-57290' +prov[21]='50953-H 哈尔滨-50953|50842-D 大庆-50842|50442-D 大兴安岭-50442|50775-H 鹤岗-50775|50468-H 黑河-50468|50873-J 佳木斯-50873|50978-J 鸡西-50978|54094-M 牡丹江-54094|50745-Q 齐齐哈尔-50745|50973-Q 七台河-50973|50884-S 双鸭山-50884|50853-S 绥化-50853|50774-Y 伊春-50774' +prov[22]='57494-W 武汉-57494|57496-E 鄂州-57496|57447-E 恩施-57447|58407-H 黄石-58407|57498-H 黄冈-57498|57476-J 荆州-57476|57377-J 荆门-57377|57475-Q 潜江-57475|57252-S 十堰-57252|57381-S 随州-57381|57362-S 神农架-57362|57483-T 天门-57483|57278-X 襄阳-57278|57482-X 孝感-57482|57590-X 咸宁-57590|57485-X 仙桃-57485|57461-Y 宜昌-57461' +prov[23]='57687-C 长沙-57687|60011-X 湘西-60011|57662-C 常德-57662|57972-C 郴州-57972|57872-H 衡阳-57872|57749-H 怀化-57749|57763-L 娄底-57763|70356-Q 黔阳-70356|57766-S 邵阳-57766|57773-X 湘潭-57773|57584-Y 岳阳-57584|57674-Y 益阳-57674|57865-Y 永州-57865|57780-Z 株洲-57780|57558-Z 张家界-57558' +prov[24]='54161-C 长春-54161|54371-B 白山-54371|50936-B 白城-50936|54172-J 吉林-54172|54260-L 辽源-54260|54157-S 四平-54157|50949-S 松原-50949|54363-T 通化-54363|71532-Y 延边-71532' +prov[25]='58238-N 南京-58238|58343-C 常州-58343|58141-H 淮安-58141|58044-L 连云港-58044|58259-N 南通-58259|58357-S 苏州-58357|58131-S 宿迁-58131|58246-T 泰州-58246|58354-W 无锡-58354|58027-X 徐州-58027|58151-Y 盐城-58151|58245-Y 扬州-58245|58248-Z 镇江-58248' +prov[26]='58606-N 南昌-58606|58617-F 抚州-58617|57993-G 赣州-57993|58502-J 九江-58502|58527-J 景德镇-58527|57799-J 吉安-57799|57786-P 萍乡-57786|58637-S 上饶-58637|57796-X 新余-57796|58627-Y 鹰潭-58627|57793-Y 宜春-57793' +prov[27]='54342-S 沈阳-54342|54339-A 鞍山-54339|54346-B 本溪-54346|54433-C 朝阳-54433|54662-D 大连-54662|54497-D 丹东-54497|54353-F 抚顺-54353|54237-F 阜新-54237|54453-H 葫芦岛-54453|54337-J 锦州-54337|54347-L 辽阳-54347|54338-P 盘锦-54338|54249-T 铁岭-54249|54471-Y 营口-54471' +prov[28]='53463-H 呼和浩特-53463|60150-W 乌兰察布-60150|60149-X 锡林郭勒-60149|60356-A 阿拉善盟-60356|53446-B 包头-53446|54218-C 赤峰-54218|71109-E 鄂尔多斯-71109|71108-H 呼伦贝尔-71108|60002-L 巴彦淖尔-60002|54135-T 通辽-54135|53512-W 乌海-53512|60001-X 兴安盟-60001' +prov[29]='53614-Y 银川-53614|53817-G 固原-53817|53518-S 石嘴山-53518|53612-W 吴忠-53612|53704-Z 中卫-53704' +prov[30]='52866-X 西宁-52866|71113-H 海西-71113|71729-G 果洛-71729|71112-H 海北-71112|71114-H 黄南-71114|71727-H 海东-71727|71728-H 海南-71728|70552-Y 玉树-70552' +prov[31]='54823-J 济南-54823|54734-B 滨州-54734|54736-D 东营-54736|54714-D 德州-54714|54906-H 菏泽-54906|54915-J 济宁-54915|54938-L 临沂-54938|54806-L 聊城-54806|54857-Q 青岛-54857|54945-R 日照-54945|54827-T 泰安-54827|54843-W 潍坊-54843|54774-W 威海-54774|54765-Y 烟台-54765|54830-Z 淄博-54830|58024-Z 枣庄-58024' +prov[32]='53772-T 太原-53772|53882-C 长治-53882|53487-D 大同-53487|53976-J 晋城-53976|71115-J 晋中-71115|53868-L 临汾-53868|71037-L 吕梁-71037|53578-S 朔州-53578|53674-X 忻州-53674|53782-Y 阳泉-53782|53959-Y 运城-53959' +prov[33]='57036-X 西安-57036|57245-A 安康-57245|57016-B 宝鸡-57016|57127-H 汉中-57127|71031-S 商洛-71031|53947-T 铜川-53947|57045-W 渭南-57045|57048-X 咸阳-57048|53845-Y 延安-53845|53646-Y 榆林-53646|71199-Y 杨凌-71199' +prov[35]='56294-C 成都-56294|56171-A 阿坝-56171|57313-B 巴中-57313|56198-D 德阳-56198|57328-D 达州-57328|57206-G 广元-57206|57415-G 广安-57415|56146-G 甘孜-56146|57602-L 泸州-57602|56386-L 乐山-56386|71118-L 凉山-71118|56196-M 绵阳-56196|56391-M 眉山-56391|57504-N 内江-57504|57411-N 南充-57411|56666-P 攀枝花-56666|57405-S 遂宁-57405|56492-Y 宜宾-56492|56287-Y 雅安-56287|56396-Z 自贡-56396|56298-Z 资阳-56298' +prov[38]='55591-L 拉萨-55591|55437-A 阿里-55437|56137-C 昌都-56137|56312-L 林芝-56312|70774-N 那曲-70774|55578-R 日喀则-55578|55597-S 山南-55597' +prov[40]='51463-W 乌鲁木齐-51463|51656-B 巴音郭楞-51656|51704-K 克州-51704|51628-A 阿克苏-51628|51076-A 阿勒泰-51076|51730-A 阿拉尔-51730|51238-B 博州-51238|71708-B 巴州-71708|71710-B 博尔塔拉-71710|71714-B 北屯-71714|51368-C 昌吉-51368|52203-H 哈密-52203|51828-H 和田-51828|51243-K 克拉玛依-51243|51709-K 喀什-51709|71717-K 可克达拉-71717|72108-K 昆玉市-72108|51356-S 石河子-51356|71716-S 双河-71716|51573-T 吐鲁番-51573|51133-T 塔城-51133|71712-T 图木舒克-71712|71715-T 铁门关-71715|71713-W 五家渠-71713|71709-Y 伊犁-71709' +prov[41]='56778-K 昆明-56778|70908-D 迪庆-70908|60839-X 西双版纳-60839|56748-B 保山-56748|56768-C 楚雄-56768|56751-D 大理-56751|71126-D 德宏-71126|56975-H 红河-56975|56651-L 丽江-56651|56951-L 临沧-56951|71127-N 怒江-71127|70887-P 普洱-70887|56783-Q 曲靖-56783|56994-W 文山-56994|56875-Y 玉溪-56875|56586-Z 昭通-56586' +prov[42]='58457-H 杭州-58457|58450-H 湖州-58450|58452-J 嘉兴-58452|58549-J 金华-58549|58646-L 丽水-58646|58465-N 宁波-58465|58633-Q 衢州-58633|58453-S 绍兴-58453|58651-T 台州-58651|58659-W 温州-58659|58477-Z 舟山-58477' + +var provqx=new Array(); +provqx[10]=['58321-H 合肥-58321|71873-B 包河-58321|70000-C 长丰-58321|58326-C 巢湖-58321|70005-F 肥东-58321|60765-F 肥西-58321|72115-H 合肥高新技术产业开发区-58321|72116-H 合肥经济技术开发区-58321|72117-H 合肥新站高新技术产业开发区-58321|60622-L 庐江-58321|71871-L 庐阳-58321|71872-S 蜀山-58321|71870-Y 瑶海-58321','58424-A 安庆-58424|72311-A 安徽安庆经济开发区-58424|71890-D 大观-58424|60606-H 怀宁-58424|60603-Q 潜山-58424|60587-S 宿松-58424|61039-T 太湖-58424|60318-T 桐城-58424|60313-W 望江-58424|60605-Y 岳西-58424|71889-Y 迎江-58424|71891-Y 宜秀-58424','60595-G 涡阳-58102|58102-B 亳州-58102|60772-L 利辛-58102|60596-M 蒙城-58102|71896-Q 谯城-58102','58221-B 蚌埠-58221|71875-B 蚌山-58221|72110-B 蚌埠市高新技术开发区-58221|72111-B 蚌埠市经济开发区-58221|60600-G 固镇-58221|60601-H 怀远-58221|71877-H 淮上-58221|71874-L 龙子湖-58221|60588-W 五河-58221|71876-Y 禹会-58221','58236-C 滁州-58236|72112-C 滁州经济技术开发区-58236|60602-D 定远-58236|60170-F 凤阳-58236|60172-L 来安-58236|71898-L 琅琊-58236|60171-M 明光-58236|71899-N 南谯-58236|60598-Q 全椒-58236|72118-S 苏滁现代产业园-58236|60599-T 天长-58236','58427-C 池州-58427|70003-D 东至-58427|71910-G 贵池-58427|70008-J 九华山-58427|60316-Q 青阳-58427|60319-S 石台-58427','58203-F 阜阳-58203|60773-F 阜南-58203|72113-F 阜阳合肥现代产业园区-58203|72114-F 阜阳经济技术开发区-58203|60767-J 界首-58203|60597-L 临泉-58203|60766-T 太和-58203|60169-Y 颍上-58203|71893-Y 颍州-58203|71894-Y 颍东-58203|71895-Y 颍泉-58203','71900-D 杜集-58116|58116-H 淮北-58116|71902-L 烈山-58116|70969-S 濉溪-58116|71901-X 相山-58116','71393-P 潘集-58224|71885-B 八公山-58224|71882-D 大通-58224|70006-F 凤台-58224|58224-H 淮南-58224|60593-S 寿县-58224|71883-T 田家庵-58224|71884-X 谢家集-58224','70931-H 黄山-70931|71091-H 黄山区-70931|71148-H 黄山风景区-70931|71897-H 徽州-70931|60769-Q 祁门-70931|60768-S 歙县-70931|60314-T 屯溪-70931|60589-X 休宁-70931|60590-Y 黟县-70931','60591-H 霍邱-58311|60315-H 霍山-58311|60713-J 金寨-58311|71907-J 金安-58311|58311-L 六安-58311|60592-S 舒城-58311|71908-Y 裕安-58311|71909-Y 叶集-58311','71888-B 博望-58336|70002-D 当涂-58336|61040-H 含山-58336|60770-H 和县-58336|71886-H 花山-58336|58336-M 马鞍山-58336|71887-Y 雨山-58336','70001-D 砀山-58122|70932-L 灵璧-58122|58122-S 宿州-58122|70010-S 泗县-58122|72120-S 宿州经济技术开发区-58122|72121-S 宿州马鞍山现代产业园区-58122|60771-X 萧县-58122|71892-Y 埇桥-58122','71905-J 郊区-58429|58429-T 铜陵-58429|71903-T 铜官-58429|71904-Y 义安-58429|60604-Z 枞阳-58429','72109-A 安徽芜湖长江大桥经济开发区-58334|70004-F 繁昌-58334|71878-J 镜湖-58334|71880-J 鸠江-58334|60168-N 南陵-58334|71881-S 三山-58334|60594-W 无为-58334|58334-W 芜湖-58334|60585-W 芜湖县-58334|72119-W 芜湖经济技术开发区-58334|71879-Y 弋江-58334','70007-G 广德-58433|60173-J 泾县-58433|60174-J 旌德-58433|60586-J 绩溪-58433|70009-L 郎溪-58433|60317-N 宁国-58433|58433-X 宣城-58433|71906-X 宣州-58433|72122-X 宣城市经济开发区-58433'] +provqx[11]=['45011-A 澳门-45011|71292-D 氹仔岛-45011|71293-L 路环岛-45011'] +provqx[12]=['54511-B 北京-54511|60198-C 昌平-54511|71141-C 朝阳-54511|60205-D 大兴-54511|71445-D 东城-54511|60206-F 房山-54511|71142-F 丰台-54511|60207-H 怀柔-54511|71144-H 海淀-54511|60247-M 密云-54511|60246-M 门头沟-54511|60204-P 平谷-54511|60202-S 顺义-54511|71143-S 石景山-54511|71071-T 通州-54511|71446-X 西城-54511|60199-Y 延庆-54511'] +provqx[13]=['58847-F 福州-58847|60396-C 长乐-58847|71913-C 仓山-58847|60084-F 福清-58847|71911-G 鼓楼-58847|71915-J 晋安-58847|60071-L 罗源-58847|60004-L 连江-58847|60073-M 闽清-58847|60301-M 闽侯-58847|71914-M 马尾-58847|60302-P 平潭-58847|71912-T 台江-58847|60072-Y 永泰-58847','71415-D 钓鱼岛-71415','70017-C 长汀-58927|58927-L 龙岩-58927|60873-L 连城-58927|60717-S 上杭-58927|60716-W 武平-58927|71929-X 新罗-58927|60077-Y 永定-58927|60607-Z 漳平-58927','70021-G 光泽-58834|60655-J 建阳-58834|60080-J 建瓯-58834|58834-N 南平-58834|60654-P 浦城-58834|60081-S 顺昌-58834|60079-S 邵武-58834|60705-S 松溪-58834|60082-W 武夷山-58834|71932-Y 延平-58834|60900-Z 政和-58834','60398-F 福安-58846|60401-F 福鼎-58846|70022-G 古田-58846|71921-J 蕉城-58846|58846-N 宁德-58846|60075-P 屏南-58846|60303-S 寿宁-58846|60397-X 霞浦-58846|60703-Z 周宁-58846|60656-Z 柘荣-58846','71397-C 城厢-58946|71394-H 涵江-58946|71396-L 荔城-58946|71395-X 秀屿-58946|58946-P 莆田-58946|60076-X 仙游-58946|70032-X 秀屿港-58946','71237-S 石狮-59131|70016-A 安溪-59131|70018-C 崇武-59131|60653-D 德化-59131|71924-F 丰泽-59131|71236-H 惠安-59131|71149-J 晋江-59131|71922-J 金门-59131|71923-L 鲤城-59131|71925-L 洛江-59131|60304-N 南安-59131|59131-Q 泉州-59131|71926-Q 泉港-59131|60085-Y 永春-59131','70019-D 大田-58828|70024-J 将乐-58828|70025-J 建宁-58828|70027-M 明溪-58828|71930-M 梅列-58828|60899-N 宁化-58828|60657-Q 清流-58828|58828-S 三明-58828|60400-S 沙县-58828|71931-S 三元-58828|60714-T 泰宁-58828|60715-Y 尤溪-58828|60083-Y 永安-58828','71917-H 海沧-59134|71918-H 湖里-59134|71919-J 集美-59134|71916-S 思明-59134|70030-T 同安-59134|59134-X 厦门-59134|71920-X 翔安-59134','61002-C 长泰-59126|70020-D 东山-59126|70023-H 华安-59126|60078-L 龙海-59126|71928-L 龙文-59126|70028-N 南靖-59126|70029-P 平和-59126|71927-X 芗城-59126|60399-Y 云霄-59126|59126-Z 漳州-59126|70034-Z 漳浦-59126|60702-Z 诏安-59126'] +provqx[14]=['52889-L 兰州-52889|71733-A 安宁-52889|71730-C 城关-52889|71150-G 皋兰-52889|71734-H 红古-52889|72124-L 兰州新区-52889|71731-Q 七里河-52889|71732-X 西固-52889|60473-Y 永登-52889|60468-Y 榆中-52889','56080-G 甘南-56080|70039-D 迭部-56080|71430-H 合作-56080|70058-L 临潭-56080|70060-L 碌曲-56080|70061-M 玛曲-56080|70072-X 夏河-56080|70076-Z 卓尼-56080|60487-Z 舟曲-56080','60472-L 陇南-60472|60481-C 成县-60472|60482-H 徽县-60472|60483-K 康县-60472|60167-L 礼县-60472|70056-L 两当-60472|70038-T 宕昌-60472|70069-W 文县-60472|71420-W 武都-60472|70073-X 西和-60472','71358-P 平川-52896|52896-B 白银-52896|72123-B 白银区-52896|70051-H 会宁-52896|60334-J 靖远-52896|60475-J 景泰-52896','71155-A 安定-52995|52995-D 定西-52995|60477-L 陇西-52995|60166-L 临洮-52995|60479-M 岷县-52995|60478-T 通渭-52995|60469-W 渭源-52995|70075-Z 漳县-52995','52675-J 金昌-52675|71736-J 金川-52675|60471-Y 永昌-52675','71355-A 阿克塞-52533|71356-Y 玉门-52533|60163-D 敦煌-52533|71092-G 瓜州-52533|52533-J 酒泉-52533|70054-J 金塔-52533|60164-S 肃北-52533|71738-S 肃州-52533|70074-Y 玉门镇-52533','71129-J 嘉峪关-71129','71357-J 积石山-52984|70041-D 东乡-52984|60485-G 广河-52984|70046-H 和政-52984|70055-K 康乐-52984|52984-L 临夏-52984|72125-L 临夏市-52984|72126-L 临夏县-52984|60484-Y 永靖-52984','70037-C 崇信-53915|70050-H 华亭-53915|70052-J 泾川-53915|70053-J 静宁-53915|71153-K 崆峒-53915|70057-L 灵台-53915|53915-P 平凉-53915|60165-Z 庄浪-53915','70049-H 环县-53923|70047-H 华池-53923|60333-H 合水-53923|60476-N 宁县-53923|53923-Q 庆阳-53923|71154-Q 庆城-53923|60161-X 西峰-53923|60470-Z 正宁-53923|60480-Z 镇原-53923','70042-G 甘谷-57006|71151-M 麦积-57006|70066-Q 清水-57006|70065-Q 秦安-57006|71739-Q 秦州-57006|57006-T 天水-57006|70070-W 武山-57006|60474-Z 张家川-57006','70045-G 古浪-52679|71735-L 凉州-52679|70064-M 民勤-52679|71152-T 天祝-52679|52679-W 武威-52679','70044-G 高台-52652|71737-G 甘州-52652|70059-L 临泽-52652|70063-M 民乐-52652|70068-S 肃南-52652|70067-S 山丹-52652|52652-Z 张掖-52652'] +provqx[15]=['59287-G 广州-59287|72026-B 白云-59287|70077-C 从化-59287|60024-H 花都-59287|72024-H 海珠-59287|72027-H 黄埔-59287|72022-L 荔湾-59287|72028-N 南沙-59287|60025-P 番禺-59287|72025-T 天河-59287|72023-Y 越秀-59287|60368-Z 增城-59287','71278-C 潮安-59312|59312-C 潮州-59312|60750-R 饶平-59312|72048-X 湘桥-59312','59289-D 东莞-59289','71257-G 高明-59288|72042-C 禅城-59288|59288-F 佛山-59288|60060-N 南海-59288|60061-S 顺德-59288|60059-S 三水-59288','71272-D 东源-59293|59293-H 河源-59293|60678-H 和平-59293|60370-L 连平-59293|60371-L 龙川-59293|72045-Y 源城-59293|60044-Z 紫金-59293','60047-B 博罗-59297|59297-H 惠州-59297|60048-H 惠东-59297|71158-H 惠阳-59297|72029-H 惠城-59297|60050-L 龙门-59297','71271-J 江海-59473|71267-P 蓬江-59473|70082-E 恩平-59473|71159-H 鹤山-59473|59473-J 江门-59473|60057-K 开平-59473|60056-T 台山-59473|60055-X 新会-59473','71284-J 揭东-59315|70087-H 惠来-59315|59315-J 揭阳-59315|60379-J 揭西-59315|60245-P 普宁-59315|72050-R 榕城-59315','70078-D 大埔-59109|70084-F 丰顺-59109|70088-J 蕉岭-59109|59109-M 梅州-59109|71157-M 梅县-59109|72030-M 梅江-59109|70096-P 平远-59109|60752-W 五华-59109|60380-X 兴宁-59109','71285-M 茂港-59659|70081-D 电白-59659|60377-G 高州-59659|60664-H 化州-59659|59659-M 茂名-59659|72051-M 茂南-59659|60053-X 信宜-59659','71274-Q 清新-59280|70085-F 佛冈-59280|70090-L 连南-59280|60372-L 连州-59280|70091-L 连山-59280|59280-Q 清远-59280|72046-Q 清城-59280|60751-Y 阳山-59280|60045-Y 英德-59280','72038-B 宝安-59493|72036-F 福田-59493|72127-G 光明区-59493|72035-L 罗湖-59493|72039-L 龙岗-59493|72128-L 龙华区-59493|72037-N 南山-59493|72129-P 坪山区-59493|59493-S 深圳-59493|72040-Y 盐田-59493','60665-C 潮阳-59316|70079-C 澄海-59316|72034-C 潮南-59316|72033-H 濠江-59316|72032-J 金平-59316|72031-L 龙湖-59316|70094-N 南澳-59316|59316-S 汕头-59316','71254-W 武江-59082|71252-Z 浈江-59082|70089-L 乐昌-59082|70095-N 南雄-59082|71156-Q 曲江-59082|70098-R 乳源-59082|70097-R 仁化-59082|59082-S 韶关-59082|60046-S 始兴-59082|60748-W 翁源-59082|60369-X 新丰-59082','71286-L 陆河-59501|72130-C 城区-59501|70086-H 海丰-59501|60373-L 陆丰-59501|59501-S 汕尾-59501','71280-Y 阳东-59663|71281-Y 阳西-59663|72049-J 江城-59663|59663-Y 阳江-59663|60052-Y 阳春-59663','71276-Y 云安-59471|70092-L 罗定-59471|60747-X 新兴-59471|59471-Y 云浮-59471|70103-Y 郁南-59471|72047-Y 云城-59471','71256-J 金湾-59488|60058-D 斗门-59488|72041-X 香洲-59488|59488-Z 珠海-59488','59485-Z 中山-59485','71258-C 赤坎-59658|71265-M 麻章-59658|71261-P 坡头-59658|71262-X 霞山-59658|60944-L 雷州-59658|60054-L 廉江-59658|71160-S 遂溪-59658|70101-W 吴川-59658|70102-X 徐闻-59658|59658-Z 湛江-59658','70080-D 德庆-59278|72043-D 端州-59278|72044-D 鼎湖-59278|70083-F 封开-59278|60374-G 广宁-59278|71161-G 高要-59278|60051-H 怀集-59278|60376-S 四会-59278|59278-Z 肇庆-59278'] +provqx[16]=['59431-N 南宁-59431|70105-B 宾阳-59431|60661-H 横县-59431|72065-J 江南-59431|61001-L 隆安-59431|72067-L 良庆-59431|70120-M 马山-59431|72064-Q 青秀-59431|60993-S 上林-59431|60023-W 武鸣-59431|72063-X 兴宁-59431|72066-X 西乡塘-59431|60022-Y 邕宁-59431','59644-B 北海-59644|60662-H 合浦-59644|72092-H 海城-59644|72094-T 铁山港-59644|72093-Y 银海-59644|70125-Z 涠洲岛-59644','59211-B 百色-59211|60999-D 德保-59211|60756-J 靖西-59211|60870-L 隆林-59211|60998-L 乐业-59211|61032-L 凌云-59211|60871-N 那坡-59211|60758-P 平果-59211|60090-T 田阳-59211|60757-T 田东-59211|61000-T 田林-59211|60869-X 西林-59211|72088-Y 右江-59211','59425-C 崇左-59425|70108-D 大新-59425|61042-F 扶绥-59425|72068-J 江州-59425|70119-L 龙州-59425|60995-N 宁明-59425|60996-P 凭祥-59425|60994-T 天等-59425','60031-D 东兴-59635|59635-F 防城港-59635|70111-F 防城-59635|72095-G 港口-59635|60759-S 上思-59635','72075-D 叠彩-57957|57957-G 桂林-57957|70114-G 灌阳-57957|70113-G 恭城-57957|61031-L 龙胜-57957|60089-L 临桂-57957|60700-L 灵川-57957|60088-L 荔浦-57957|60701-P 平乐-57957|60992-Q 全州-57957|72077-Q 七星-57957|60030-X 兴安-57957|72074-X 秀峰-57957|72076-X 象山-57957|60623-Y 永福-57957|60087-Y 阳朔-57957|72078-Y 雁山-57957|60872-Z 资源-57957','59249-G 贵港-59249|60663-G 桂平-59249|72083-G 港北-59249|72084-G 港南-59249|60033-P 平南-59249|72085-T 覃塘-59249','72082-B 八步-59065|61093-F 富川-59065|59065-H 贺州-59065|72096-P 平桂-59065|61034-Z 昭平-59065|60366-Z 钟山-59065','71231-D 大化-59023|70104-B 巴马-59023|70109-D 东兰-59023|70110-D 都安-59023|70112-F 凤山-59023|59023-H 河池-59023|61033-H 环江-59023|72091-J 金城江-59023|61078-L 罗城-59023|60645-N 南丹-59023|60997-T 天峨-59023|60032-Y 宜州-59023','72069-C 城中-59046|59046-L 柳州-59046|70117-L 柳城-59046|60698-L 鹿寨-59046|70118-L 柳江-59046|72071-L 柳南-59046|72072-L 柳北-59046|61079-R 融安-59046|60367-R 融水-59046|61080-S 三江-59046|72070-Y 鱼峰-59046','71289-H 合山-59242|70115-J 金秀-59242|59242-L 来宾-59242|61043-W 武宣-59242|61081-X 忻城-59242|60699-X 象州-59242|72073-X 兴宾-59242','70116-L 灵山-59632|70122-P 浦北-59632|59632-Q 钦州-59632|72089-Q 钦南-59632|72090-Q 钦北-59632','70107-C 苍梧-59265|61082-C 岑溪-59265|72080-C 长洲-59265|72081-L 龙圩-59265|70121-M 蒙山-59265|70124-T 藤县-59265|59265-W 梧州-59265|72079-W 万秀-59265','71416-X 兴业-59453|70106-B 博白-59453|60760-B 北流-59453|72087-F 福绵-59453|60761-L 陆川-59453|70123-R 容县-59453|59453-Y 玉林-59453|72086-Y 玉州-59453'] +provqx[17]=['57816-G 贵阳-57816|71413-N 南明-57816|71411-X 小河-57816|71412-Y 云岩-57816|70127-B 白云-57816|71979-G 观山湖-57816|60652-H 花溪-57816|60429-K 开阳-57816|60573-Q 清镇-57816|70159-W 乌当-57816|60952-X 息烽-57816|60953-X 修文-57816','57827-Q 黔南-57827|61028-C 长顺-57827|60630-D 独山-57827|71423-D 都匀-57827|60902-F 福泉-57827|60954-G 贵定-57827|70137-H 惠水-57827|70143-L 龙里-57827|70144-L 罗甸-57827|70141-L 荔波-57827|60901-P 平塘-57827|70149-S 三都-57827|60903-W 瓮安-57827','57825-Q 黔东南-57825|70129-C 岑巩-57825|70130-C 从江-57825|70131-D 丹寨-57825|60636-H 黄平-57825|70139-J 剑河-57825|70140-J 锦屏-57825|71431-K 凯里 -57825|60632-L 雷山-57825|60631-L 黎平-57825|60430-M 麻江-57825|60635-R 榕江-57825|60578-S 施秉-57825|60634-S 三穗-57825|60633-T 台江-57825|60637-T 天柱-57825|60579-Z 镇远-57825','57806-A 安顺-57806|70135-G 关岭-57806|70147-P 普定-57806|60577-P 平坝-57806|71980-X 西秀-57806|70165-Z 镇宁-57806|70167-Z 紫云-57806','57707-B 毕节-57707|60583-D 大方-57707|70136-H 赫章-57707|60584-J 金沙-57707|60581-N 纳雍-57707|60582-Q 黔西-57707|71982-Q 七星关-57707|60431-W 威宁-57707|70166-Z 织金-57707','56693-L 六盘水-56693|70142-L 六枝-56693|60955-P 盘州-56693|71163-S 水城-56693|71983-Z 钟山-56693','70126-A 安龙-70148|70128-C 册亨-70148|70146-P 普安-70148|70148-Q 黔西南-70148|71422-Q 晴隆-70148|70156-W 望谟-70148|70160-X 兴仁-70148|71130-X 兴义-70148|70163-Z 贞丰-70148','71981-B 碧江-57741|70133-D 德江-57741|70138-J 江口-57741|70152-S 思南-57741|70150-S 石阡-57741|70153-S 松桃-57741|57741-T 铜仁-57741|70157-W 万山-57741|61030-Y 玉屏-57741|60580-Y 印江-57741|61029-Y 沿河-57741','71414-H 红花岗-57713|71984-B 播州-57713|60576-C 赤水-57713|70132-D 道真-57713|70134-F 凤冈-57713|71164-H 汇川-57713|70145-M 湄潭-57713|60575-R 仁怀-57713|70154-S 绥阳-57713|70155-T 桐梓-57713|70158-W 务川-57713|70161-X 习水-57713|70162-Y 余庆-57713|57713-Z 遵义-57713|60574-Z 遵义县-57713|70164-Z 正安-57713'] +provqx[18]=['59758-H 海口-59758|72098-L 龙华-59758|72100-M 美兰-59758|72099-Q 琼山-59758|72097-X 秀英-59758','59848-B 白沙-59848','59945-B 保亭-59945','59843-C 澄迈-59843','59847-C 昌江-59847','59845-D 儋州-59845','59851-D 定安-59851','59838-D 东方-59838','59842-L 临高-59842','59954-L 陵水-59954','59940-L 乐东-59940','59855-Q 琼海-59855','59849-Q 琼中-59849','72101-H 海棠-59948|72102-J 吉阳-59948|59948-S 三亚-59948|72103-T 天涯-59948|72104-Y 崖州-59948','71417-Z 中沙-71444|70983-N 南沙岛-71444|71443-N 南海诸岛-71444|71444-S 三沙-71444|59981-X 西沙-71444','59854-T 屯昌-59854','59856-W 文昌-59856','59951-W 万宁-59951','60651-W 五指山-60651'] +provqx[19]=['53698-S 石家庄-53698|71611-C 长安-53698|70188-G 高邑-53698|70187-G 藁城-53698|70199-J 井陉-53698|71096-J 晋州-53698|71614-J 井陉矿区-53698|70210-L 栾城-53698|70206-L 灵寿-53698|71228-L 鹿泉-53698|70218-P 平山-53698|71612-Q 桥西-53698|70228-S 深泽-53698|72149-S 石家庄高新技术产业开发区-53698|72150-S 石家庄循环化工园区-53698|60095-W 无极-53698|60094-X 行唐-53698|60034-X 辛集-53698|60097-X 新乐-53698|71613-X 新华-53698|60091-Y 元氏-53698|71615-Y 裕华-53698|60096-Z 正定-53698|60092-Z 赞皇-53698|60093-Z 赵县-53698','71253-B 博野-54602|61051-L 蠡县-54602|71251-Q 清苑-54602|70171-A 安新-54602|70169-A 安国-54602|54602-B 保定-54602|72131-B 保定白沟新城-54602|72132-B 保定高新技术产业开发区-54602|60104-D 定州-54602|71235-D 定兴-54602|60098-F 阜平-54602|60102-G 高阳-54602|60099-G 高碑店-54602|71616-J 竞秀-54602|70203-L 涞源-54602|71250-L 涞水-54602|71617-L 莲池-54602|70214-M 满城-54602|71636-N 南市-54602|70225-Q 曲阳-54602|60101-R 容城-54602|60103-S 顺平-54602|60525-T 唐县-54602|60105-W 望都-54602|60519-X 徐水-54602|60975-X 雄县-54602|72105-X 雄安-54602|60100-Y 易县-54602|60523-Z 涿州-54602','54423-C 承德-54423|60110-C 承德县-54423|72136-C 承德高新技术产业开发区-54423|61053-F 丰宁-54423|60276-K 宽城-54423|60428-L 滦平-54423|70208-L 隆化-54423|60683-P 平泉-54423|71620-S 双桥-54423|71621-S 双滦-54423|60109-W 围场-54423|60275-X 兴隆-54423|71622-Y 鹰手营子矿-54423','71259-C 沧县-54616|60521-B 泊头-54616|54616-C 沧州-54616|72134-C 沧州渤海新区-54616|72135-C 沧州高新技术产业开发区-54616|61057-D 东光-54616|70195-H 海兴-54616|61056-H 黄骅-54616|60273-H 河间-54616|72139-H 河北沧州经济开发区-54616|61054-M 孟村-54616|60746-N 南皮-54616|60524-Q 青县-54616|60520-R 任丘-54616|60274-S 肃宁-54616|61055-W 吴桥-54616|61052-X 献县-54616|72154-X 新华区-54616|70236-Y 盐山-54616|71629-Y 运河-54616','70170-A 安平-54702|70185-F 阜城-54702|70193-G 故城-54702|54702-H 衡水-54702|72140-H 河北衡水高新技术产业开发区-54702|72143-H 衡水滨湖新区-54702|70198-J 景县-54702|70935-J 冀州-54702|60672-R 饶阳-54702|70241-S 深州-54702|71630-T 桃城-54702|61041-W 武邑-54702|70233-W 武强-54702|70239-Z 枣强-54702','70174-C 成安-53892|70177-C 磁县-53892|71632-C 丛台-53892|70180-D 大名-53892|70182-F 峰峰-53892|70181-F 肥乡-53892|71633-F 复兴-53892|70190-G 广平-53892|70192-G 馆陶-53892|53892-H 邯郸-53892|71631-H 邯山-53892|72137-H 邯郸冀南新区-53892|72138-H 邯郸经济技术开发区-53892|70200-J 鸡泽-53892|60108-L 临漳-53892|71099-Q 邱县-53892|60277-Q 曲周-53892|60278-S 涉县-53892|60974-W 魏县-53892|60106-W 武安-53892|60107-Y 永年-53892','71627-A 安次-54515|60112-B 霸州-54515|70179-D 大城-54515|70178-D 大厂-54515|70189-G 固安-54515|71628-G 广阳-54515|54515-L 廊坊-54515|72144-L 廊坊经济技术开发区-54515|60522-S 三河-54515|60743-W 文安-54515|60111-X 香河-54515|70237-Y 永清-54515','71098-B 北戴河-54449|72133-B 北戴河新区-54449|70173-C 昌黎-54449|70186-F 抚宁-54449|71634-H 海港-54449|70213-L 卢龙-54449|54449-Q 秦皇岛-54449|70223-Q 青龙-54449|72147-Q 秦皇岛市经济技术开发区-54449|71635-S 山海关-54449','71255-C 曹妃甸-54534|70183-F 丰南-54534|70184-F 丰润-54534|71625-G 古冶-54534|72141-H 河北唐山海港经济开发区-54534|71626-K 开平-54534|70212-L 滦州市-54534|70211-L 滦南-54534|70204-L 乐亭-54534|71623-L 路南-54534|71624-L 路北-54534|70221-Q 迁西-54534|70220-Q 迁安-54534|54534-T 唐山-54534|70229-T 唐海-54534|72151-T 唐山高新技术产业开发区-54534|72152-T 唐山市汉沽管理区-54534|72153-T 唐山市芦台经济技术开发区-54534|70238-Y 玉田-54534|60518-Z 遵化-54534','71260-N 内丘-53798|70172-B 柏乡-53798|70191-G 广宗-53798|72142-H 河北邢台经济开发区-53798|70201-J 巨鹿-53798|70205-L 临城-53798|70209-L 隆尧-53798|70207-L 临西-53798|70936-N 内邱-53798|70216-N 南和-53798|70217-N 宁晋-53798|70215-N 南宫-53798|70219-P 平乡-53798|70222-Q 清河-53798|72145-Q 桥东区-53798|72146-Q 桥西区-53798|71167-R 任县-53798|60745-S 沙河-53798|70231-W 威县-53798|53798-X 邢台-53798|70234-X 新河-53798|72155-X 邢台县-53798','70175-C 赤城-54401|70176-C 崇礼-54401|70194-G 沽源-54401|70196-H 怀安-54401|70197-H 怀来-54401|70202-K 康保-54401|71618-Q 桥东-54401|72148-Q 桥西区-54401|70227-S 尚义-54401|70230-W 万全-54401|70235-X 宣化-54401|71619-X 下花园-54401|70232-Y 蔚县-54401|60647-Y 阳原-54401|54401-Z 张家口-54401|70240-Z 张北-54401|60744-Z 涿鹿-54401|72156-Z 张家口市察北管理区-54401|72157-Z 张家口市高新技术产业开发区-54401|72158-Z 张家口市塞北管理区-54401'] +provqx[20]=['57083-Z 郑州-57083|71359-S 上街-57083|60800-D 登封-57083|71749-E 二七-57083|60451-G 巩义-57083|71750-G 管城-57083|71752-H 惠济-57083|71751-J 金水-57083|60453-X 荥阳-57083|60337-X 新密-57083|60687-X 新郑-57083|60799-Z 中牟-57083|71748-Z 中原-57083|72184-Z 郑州高新技术产业开发区-57083|72185-Z 郑州航空港经济综合实验区-57083|72186-Z 郑州经济技术开发区-57083','53898-A 安阳-53898|72159-A 安阳高新技术产业开发区-53898|72160-A 安阳县-53898|71754-B 北关-53898|60263-H 滑县-53898|70937-L 林州-53898|71756-L 龙安-53898|60264-N 内黄-53898|60262-T 汤阴-53898|71753-W 文峰-53898|71755-Y 殷都-53898','53990-H 鹤壁-53990|71785-H 鹤山-53990|72166-H 鹤壁经济技术开发区-53990|60257-Q 淇县-53990|71787-Q 淇滨-53990|71786-S 山城-53990|60256-X 浚县-53990','70265-B 博爱-53982|53982-J 焦作-53982|71781-J 解放-53982|72168-J 焦作城乡一体化示范区-53982|60252-M 孟州-53982|71783-M 马村-53982|60802-Q 沁阳-53982|71784-S 山阳-53982|60251-W 武陟-53982|60801-W 温县-53982|60250-X 修武-53982|71782-Z 中站-53982','53978-J 济源-53978','71771-G 鼓楼-57091|57091-K 开封-57091|60255-L 兰考-57091|71769-L 龙亭-57091|60979-Q 杞县-57091|71770-S 顺河-57091|60254-T 通许-57091|60253-W 尉氏-57091|71773-X 祥符-57091|71772-Y 禹王台-57091','71361-J 吉利-57073|71776-C 瀍河-57073|71777-J 涧西-57073|57073-L 洛阳-57073|70278-L 洛宁-57073|70277-L 栾川-57073|71774-L 老城-57073|71778-L 洛龙-57073|72169-L 洛阳高新技术产业开发区-57073|60268-M 孟津-57073|60258-R 汝阳-57073|70293-S 嵩县-57073|60267-X 新安-57073|71775-X 西工-57073|60266-Y 宜阳-57073|60265-Y 伊川-57073|60269-Y 偃师-57073','72170-H 漯河经济技术开发区-57186|57186-L 漯河-57186|70276-L 临颍-57186|71792-S 召陵-57186|60270-W 舞阳-57186|71790-Y 源汇-57186|71791-Y 郾城-57186','60804-D 邓州-57178|70267-F 方城-57178|57178-N 南阳-57178|60983-N 南召-57178|60981-N 内乡-57178|72171-N 南阳高新技术产业开发区-57178|72172-N 南阳市城乡一体化示范区-57178|60984-S 社旗-57178|60710-T 唐河-57178|60982-T 桐柏-57178|71767-W 宛城-57178|71768-W 卧龙-57178|60660-X 西峡-57178|60806-X 淅川-57178|60805-X 新野-57178|60803-Z 镇平-57178','70268-F 范县-54900|71788-H 华龙-54900|72161-H 河南濮阳工业园区-54900|70285-N 南乐-54900|54900-P 濮阳-54900|60272-Q 清丰-54900|60809-T 台前-54900|72175-Y 濮阳经济技术开发区-54900|72176-Y 濮阳县-54900','71360-S 石龙-71128|70264-B 宝丰-71128|70275-J 郏县-71128|70280-L 鲁山-71128|71128-P 平顶山-71128|72173-P 平顶山高新技术产业开发区-71128|72174-P 平顶山市新城区-71128|60608-R 汝州-71128|60452-W 舞钢-71128|71763-W 卫东-71128|71762-X 新华-71128|60985-Y 叶县-71128|71764-Z 湛河-71128','71363-S 陕县-57051|71362-Y 义马-57051|71794-H 湖滨-57051|72162-H 河南三门峡经济开发区-57051|60807-L 灵宝-57051|70281-L 卢氏-57051|60808-M 渑池-57051|57051-S 三门峡-57051|71795-S 陕州-57051','72163-H 河南商丘经济开发区-58005|71779-L 梁园-58005|70283-M 民权-58005|70286-N 宁陵-58005|58005-S 商丘-58005|70295-S 睢县-58005|71780-S 睢阳-58005|71168-X 夏邑-58005|60260-Y 虞城-58005|60259-Y 永城-58005|72183-Y 豫东综合物流产业聚集区-58005|60261-Z 柘城-58005','70266-C 长垣-53986|70269-F 封丘-53986|71759-F 凤泉-53986|60447-H 获嘉-53986|60448-H 辉县-53986|71757-H 红旗-53986|71760-M 牧野-53986|60980-W 卫辉-53986|71758-W 卫滨-53986|53986-X 新乡-53986|72177-X 新乡高新技术产业开发区-53986|72178-X 新乡经济技术开发区-53986|72179-X 新乡市平原城乡一体化示范区-53986|72180-X 新乡县-53986|60338-Y 原阳-53986|60446-Y 延津-53986','60973-C 长葛-57089|72167-J 建安区-57089|71761-W 魏都-57089|57089-X 许昌-57089|70297-X 襄城-57089|72182-X 许昌经济技术开发区-57089|60248-Y 鄢陵-57089|60249-Y 禹州-57089','70271-G 光山-57297|70272-G 固始-57297|70273-H 淮滨-57297|70274-H 潢川-57297|70279-L 罗山-57297|71766-P 平桥-57297|60810-S 商城-57297|71765-S 浉河-57297|57297-X 信阳-57297|60271-X 息县-57297|70300-X 新县-57297|72181-X 信阳高新技术产业开发区-57297','71789-C 川汇-57195|60629-D 郸城-57195|70270-F 扶沟-57195|60449-H 淮阳-57195|72164-H 河南周口经济开发区-57195|70282-L 鹿邑-57195|70291-S 商水-57195|70292-S 沈丘-57195|70296-T 太康-57195|70298-X 西华-57195|60450-X 项城-57195|57195-Z 周口-57195','70284-B 泌阳-57290|72165-H 河南驻马店经济开发区-57290|70287-P 平舆-57290|70288-Q 确山-57290|70289-R 汝南-57290|70294-S 遂平-57290|61085-S 上蔡-57290|70301-X 西平-57290|70299-X 新蔡-57290|71793-Y 驿城-57290|57290-Z 驻马店-57290|70302-Z 正阳-57290'] +provqx[21]=['50953-H 哈尔滨-50953|70242-A 阿城-50953|70245-B 宾县-50953|60741-B 巴彦-50953|71466-D 道里-50953|71468-D 道外-50953|60640-F 方正-50953|60424-H 呼兰-50953|60742-M 木兰-50953|71467-N 南岗-50953|71469-P 平房-50953|60509-S 双城-50953|60426-S 尚志-50953|71470-S 松北-50953|61045-T 通河-50953|60727-W 五常-50953|71471-X 香坊-50953|60737-Y 依兰-50953|60736-Y 延寿-50953','50842-D 大庆-50842|71169-D 杜蒙-50842|71241-D 杜尔伯特-50842|71505-D 大同-50842|72187-D 大庆高新技术产业开发区-50842|71504-H 红岗-50842|60732-L 林甸-50842|71502-L 龙凤-50842|71503-R 让胡路-50842|71501-S 萨尔图-50842|60514-Z 肇州-50842|60728-Z 肇源-50842','50442-D 大兴安岭-50442|60731-H 呼玛-50442|70251-H 呼中-50442|71171-J 加格达奇-50442|60735-M 漠河-50442|72189-S 松岭区-50442|60734-T 塔河-50442|70262-X 新林-50442','71518-D 东山-50775|71515-G 工农-50775|50775-H 鹤岗-50775|60461-L 萝北-50775|71516-N 南山-50775|70259-S 绥滨-50775|71517-X 兴安-50775|71519-X 兴山-50775|72190-X 向阳区-50775','71488-A 爱辉-50468|60114-B 北安-50468|50468-H 黑河-50468|60462-N 嫩江-50468|60740-S 孙吴-50468|60350-W 五大连池-50468|60115-X 逊克-50468','71485-D 东风-50873|60733-F 抚远-50873|70246-F 富锦-50873|70249-H 桦川-50873|70250-H 桦南-50873|50873-J 佳木斯-50873|71486-J 郊区-50873|71484-Q 前进-50873|60459-T 汤原-50873|60423-T 同江-50873|71483-X 向阳-50873','71513-C 城子河-50978|71511-D 滴道-50978|60223-H 虎林-50978|71510-H 恒山-50978|50978-J 鸡西-50978|70253-J 鸡东-50978|71509-J 鸡冠-50978|71512-L 梨树-50978|60463-M 密山-50978|71514-M 麻山-50978','71481-A 爱民-54094|60510-D 东宁-54094|71479-D 东安-54094|60511-H 海林-54094|60513-L 林口-54094|54094-M 牡丹江-54094|60726-M 穆棱-54094|72188-M 牡丹江经济技术开发区-54094|60512-N 宁安-54094|60464-S 绥芬河-54094|71482-X 西安-54094|71480-Y 阳明-54094','71475-A 昂昂溪-50745|70243-B 拜泉-50745|60738-F 富裕-50745|71476-F 富拉尔基-50745|70248-G 甘南-50745|71473-J 建华-50745|70256-K 克山-50745|70255-K 克东-50745|60460-L 龙江-50745|71472-L 龙沙-50745|71478-M 梅里斯-50745|60123-N 讷河-50745|71477-N 碾子山-50745|50745-Q 齐齐哈尔-50745|60515-T 泰来-50745|71474-T 铁锋-50745|60739-Y 依安-50745','71170-B 勃利-50973|50973-Q 七台河-50973|71508-Q 茄子河-50973|71507-T 桃山-50973|71506-X 新兴-50973','71242-Y 友谊-50884|70244-B 宝清-50884|71523-B 宝山-50884|70254-J 集贤-50884|71520-J 尖山-50884|71521-L 岭东-50884|70991-R 饶河-50884|50884-S 双鸭山-50884|71522-S 四方台-50884','60425-A 安达-50853|71487-B 北林-50853|60349-H 海伦-50853|60730-L 兰西-50853|70257-M 明水-50853|60729-Q 青冈-50853|70258-Q 庆安-50853|50853-S 绥化-50853|60427-S 绥棱-50853|60639-W 望奎-50853|60124-Z 肇东-50853','71492-C 翠峦-50774|71498-D 带岭-50774|71499-H 红星-50774|70252-J 嘉荫-50774|71495-J 金山屯-50774|71494-M 美溪-50774|71489-N 南岔-50774|71500-S 上甘岭-50774|61067-T 铁力-50774|71497-T 汤旺河-50774|70260-W 乌伊岭-50774|70261-W 五营-50774|71496-W 乌马河-50774|71491-X 西林-50774|71493-X 新青-50774|50774-Y 伊春-50774|71490-Y 友好-50774|72191-Y 伊春区-50774'] +provqx[22]=['57494-W 武汉-57494|71373-D 东西湖-57494|60012-C 蔡甸-57494|70313-H 黄陂-57494|71830-H 汉阳-57494|71833-H 洪山-57494|71834-H 汉南-57494|70939-J 江夏-57494|71827-J 江岸-57494|71828-J 江汉-57494|71829-Q 硚口-57494|71832-Q 青山-57494|71831-W 武昌-57494|60951-X 新洲-57494','71375-L 梁子湖-57496|57496-E 鄂州-57496|71838-E 鄂城-57496|71837-H 华容-57496','70303-B 巴东-57447|57447-E 恩施-57447|72192-E 恩施市-57447|60945-H 鹤峰-57447|60950-J 建始-57447|60534-L 利川-57447|60533-L 来凤-57447|60020-X 咸丰-57447|60532-X 宣恩-57447','71378-T 铁山-58407|71379-X 下陆-58407|71380-X 西塞山-58407|60017-D 大冶-58407|58407-H 黄石-58407|71841-H 黄石港-58407|60529-Y 阳新-58407','71377-T 团风-57498|57498-H 黄冈-57498|70312-H 红安-57498|60531-H 黄梅-57498|71840-H 黄州-57498|60016-L 罗田-57498|72195-L 龙感湖管理区-57498|60530-M 麻城-57498|60341-Q 蕲春-57498|60343-W 武穴-57498|60342-X 浠水-57498|60948-Y 英山-57498','71381-S 沙市-57476|70309-G 公安-57476|61046-H 洪湖-57476|57476-J 荆州-57476|70314-J 监利-57476|71173-J 江陵-57476|72193-J 荆州经济技术开发区-57476|72194-J 荆州区-57476|60013-S 石首-57476|60014-S 松滋-57476','71384-D 掇刀-57377|71385-S 沙洋-57377|71849-D 东宝-57377|57377-J 荆门-57377|60018-J 京山-57377|60346-Z 钟祥-57377','57475-Q 潜江-57475','71382-M 茅箭-57252|71383-Z 张湾-57252|60340-D 丹江口-57252|70308-F 房县-57252|57252-S 十堰-57252|60348-Y 郧西-57252|60527-Y 郧阳-57252|60680-Z 竹溪-57252|60528-Z 竹山-57252','60535-G 广水-57381|57381-S 随州-57381|71848-S 随县-57381|71847-Z 曾都-57381','57362-S 神农架-57362','57483-T 天门-57483','71374-X 襄州-57278|70304-B 保康-57278|71836-F 樊城-57278|70311-G 谷城-57278|70310-L 老河口-57278|70316-N 南漳-57278|57278-X 襄阳-57278|71835-X 襄城-57278|60015-Y 宜城-57278|60347-Z 枣阳-57278','71376-X 孝昌-57482|61065-A 安陆-57482|70307-D 大悟-57482|60949-H 汉川-57482|57482-X 孝感-57482|71839-X 孝南-57482|60344-Y 云梦-57482|60345-Y 应城-57482','60019-C 赤壁-57590|70306-C 崇阳-57590|70315-J 嘉鱼-57590|70319-T 通城-57590|70320-T 通山-57590|57590-X 咸宁-57590|71842-X 咸安-57590','57485-X 仙桃-57485','70305-C 长阳-57461|60526-D 当阳-57461|71845-D 点军-57461|70318-S 三峡-57461|70321-W 五峰-57461|71844-W 伍家岗-57461|70322-X 兴山-57461|71843-X 西陵-57461|71846-X 猇亭-57461|57461-Y 宜昌-57461|60947-Y 远安-57461|60935-Y 宜都-57461|71174-Y 夷陵-57461|60946-Z 秭归-57461|60339-Z 枝江-57461'] +provqx[23]=['57687-C 长沙-57687|71438-C 长沙县-57687|71405-W 望城-57687|71950-F 芙蓉-57687|71953-K 开福-57687|60388-L 浏阳-57687|70343-N 宁乡-57687|71951-T 天心-57687|71101-X 湘江新区-57687|71952-Y 岳麓-57687|71954-Y 雨花-57687','60011-X 湘西-60011|60883-B 保靖-60011|60880-F 凤凰-60011|60878-G 古丈-60011|60882-H 花垣-60011|72200-H 湖南吉首经济开发区-60011|72203-H 湖南永顺经济开发区-60011|71421-J 吉首-60011|60877-L 泸溪-60011|60879-L 龙山-60011|60881-Y 永顺-60011','71407-J 津市-57662|60885-A 安乡-57662|57662-C 常德-57662|72196-C 常德市西洞庭管理区-57662|71967-D 鼎城-57662|70329-H 汉寿-57662|70341-L 澧县-57662|70340-L 临澧-57662|70350-S 石门-57662|60681-T 桃源-57662|71966-W 武陵-57662','71406-S 苏仙-57972|60563-A 安仁-57972|71965-B 北湖-57972|57972-C 郴州-57972|60560-G 桂阳-57972|61094-G 桂东-57972|60561-J 嘉禾-57972|60559-L 临武-57972|70347-R 汝城-57972|60558-Y 宜章-57972|60556-Y 永兴-57972|60557-Z 资兴-57972','70324-C 常宁-57872|57872-H 衡阳-57872|70332-H 衡山-57872|70330-H 衡东-57872|60688-H 衡阳县-57872|70331-H 衡南-57872|72197-H 衡阳综合保税区-57872|72198-H 湖南衡阳高新技术产业园区-57872|72199-H 湖南衡阳松木经济开发区-57872|60555-L 耒阳-57872|60562-N 南岳-57872|61023-Q 祁东-57872|71963-S 石鼓-57872|71962-Y 雁峰-57872|71961-Z 珠晖-57872|71964-Z 蒸湘-57872','71409-Z 中方-57749|60550-C 辰溪-57749|57749-H 怀化-57749|60889-H 会同-57749|71175-H 洪江-57749|71977-H 鹤城-57749|72204-H 怀化市洪江管理区-57749|60613-J 靖州-57749|60552-M 麻阳-57749|60888-T 通道-57749|60553-X 新晃-57749|60890-X 溆浦-57749|60551-Y 沅陵-57749|60625-Z 芷江-57749','57763-L 娄底-57763|60884-L 冷水江-57763|60891-L 涟源-57763|71969-L 娄星-57763|61027-S 双峰-57763|60618-X 新化-57763','70356-Q 黔阳-70356','71972-B 北塔-57766|61025-C 城步-57766|70328-D 洞口-57766|71971-D 大祥-57766|70342-L 隆回-57766|57766-S 邵阳-57766|70349-S 邵东-57766|61095-S 绥宁-57766|60886-S 邵阳县-57766|71970-S 双清-57766|60887-W 武冈-57766|61024-X 新邵-57766|61026-X 新宁-57766','72201-H 湖南湘潭高新技术产业园区-57773|61022-S 韶山-57773|57773-X 湘潭-57773|60711-X 湘乡-57773|72207-X 湘潭县-57773|72208-X 湘潭昭山示范区-57773|72206-X 湘潭九华示范区-57773|71955-Y 雨湖-57773|71956-Y 岳塘-57773','70333-H 华容-57584|71975-J 君山-57584|70339-L 临湘-57584|60612-M 汨罗-57584|70345-P 平江-57584|70353-X 湘阴-57584|57584-Y 岳阳-57584|71973-Y 岳阳楼区-57584|71974-Y 云溪-57584|72213-Y 岳阳市屈原管理区-57584|72214-Y 岳阳县-57584','60624-A 安化-57674|71102-H 赫山区-57674|72202-H 湖南益阳高新技术产业园区-57674|61021-N 南县-57674|70352-T 桃江-57674|57674-Y 益阳-57674|60554-Y 沅江-57674|72209-Y 益阳市大通湖管理区-57674|71968-Z 资阳-57674','71410-L 冷水滩-57865|70327-D 东安-57865|70326-D 道县-57865|70335-J 江永-57865|70334-J 江华-57865|60626-L 蓝山-57865|71978-L 零陵-57865|70344-N 宁远-57865|70346-Q 祁阳-57865|70351-S 双牌-57865|70354-X 新田-57865|57865-Y 永州-57865|72210-Y 永州经济技术开发区-57865|72211-Y 永州市回龙圩管理区-57865|72212-Y 永州市金洞管理区-57865','60689-C 茶陵-57780|71957-H 荷塘-57780|72205-K 渌口区-57780|70337-L 醴陵-57780|71958-L 芦淞-57780|71959-S 石峰-57780|71960-T 天元-57780|70355-Y 攸县-57780|60876-Y 炎陵-57780|72215-Y 云龙示范区-57780|57780-Z 株洲-57780','71408-W 武陵源-57558|70325-C 慈利-57558|70348-S 桑植-57558|71976-Y 永定-57558|57558-Z 张家界-57558'] +provqx[24]=['54161-C 长春-54161|71436-E 二道-54161|71526-C 朝阳-54161|72221-C 长春高新技术产业开发区-54161|72222-C 长春经济技术开发区-54161|72223-C 长春净月高新技术产业开发区-54161|72224-C 长春汽车经济技术开发区-54161|60832-D 德惠-54161|60790-J 九台-54161|71525-K 宽城-54161|71527-L 绿园-54161|60831-N 农安-54161|71524-N 南关-54161|60829-S 双阳-54161|60641-Y 榆树-54161','71244-F 抚松-54371|71245-J 江源-54371|54371-B 白山-54371|70486-C 长白-54371|70488-D 东岗-54371|71541-H 浑江-54371|60682-J 靖宇-54371|60359-L 临江-54371','50936-B 白城-50936|60644-D 大安-50936|72216-J 吉林白城经济开发区-50936|60796-T 洮南-50936|60794-T 通榆-50936|71537-T 洮北-50936|60795-Z 镇赉-50936','71528-C 昌邑-54172|71530-C 船营-54172|71531-F 丰满-54172|60358-H 桦甸-54172|54172-J 吉林-54172|60833-J 蛟河-54172|72217-J 吉林高新技术产业开发区-54172|72218-J 吉林经济开发区-54172|72220-J 吉林中国新加坡食品区-54172|71529-L 龙潭-54172|60830-P 磐石-54172|60642-S 舒兰-54172|60360-Y 永吉-54172','70487-D 东丰-54260|71243-D 东辽-54260|54260-L 辽源-54260|71538-L 龙山-54260|71539-X 西安-54260','60432-G 公主岭-54157|60614-L 梨树-54157|54157-S 四平-54157|60617-S 双辽-54157|71533-T 铁西-54157|71534-T 铁东-54157|60791-Y 伊通-54157','60793-C 长岭-50949|70489-F 扶余-50949|72219-J 吉林松原经济开发区-50949|71540-N 宁江-50949|60792-Q 乾安-50949|60364-Q 前郭-50949|50949-S 松原-50949','71535-D 东昌-54363|71536-E 二道江-54363|60669-H 辉南-54363|60706-J 集安-54363|60798-L 柳河-54363|60363-M 梅河口-54363|54363-T 通化-54363|60797-T 通化县-54363','60836-A 安图-71532|60362-D 敦化-71532|60838-H 和龙-71532|60643-H 珲春-71532|60835-L 龙井-71532|60837-T 图们-71532|71016-W 汪清-71532|60361-Y 延吉-71532|71532-Y 延边-71532'] +provqx[25]=['58238-N 南京-58238|70442-G 高淳-58238|71799-G 鼓楼-58238|70447-J 江宁-58238|70448-J 江浦-58238|71798-J 建邺-58238|70451-L 溧水-58238|70452-L 六合-58238|71177-P 浦口-58238|71797-Q 秦淮-58238|71800-Q 栖霞-58238|71796-X 玄武-58238|71801-Y 雨花台-58238','71371-W 武进-58343|58343-C 常州-58343|60311-J 金坛-58343|60312-L 溧阳-58343|71821-T 天宁-58343|71823-X 新北-58343|71822-Z 钟楼-58343','71370-H 淮阴区-58141|71179-C 淮安区-58141|58141-H 淮安-58141|70446-H 洪泽-58141|71104-H 淮阴县-58141|72226-H 淮安经济技术开发区-58141|71011-J 金湖-58141|70450-L 涟水-58141|71818-Q 清河-58141|71819-Q 清江浦区-58141|70461-X 盱眙-58141','70438-D 东海-58044|70441-G 赣榆-58044|70444-G 灌云-58044|70443-G 灌南-58044|71820-H 海州-58044|58044-L 连云港-58044|72227-L 连云港高新技术产业开发区-58044|72228-L 连云港经济技术开发区-58044|72229-L 连云区-58044','71811-C 崇川-58259|71812-G 港闸-58259|70445-H 海安-58259|60674-H 海门-58259|58259-N 南通-58259|72230-N 南通经济技术开发区-58259|60673-Q 启东-58259|60310-R 如皋-58259|60382-R 如东-58259|71178-T 通州-58259','71366-W 吴中-58357|60038-C 常熟-58357|71810-G 姑苏-58357|71808-H 虎丘-58357|60037-K 昆山-58357|58357-S 苏州-58357|72231-S 苏州工业园区-58357|60041-T 太仓-58357|60036-W 吴江-58357|71809-X 相城-58357|60035-Z 张家港-58357','71372-S 宿豫-58131|58131-S 宿迁-58131|60686-S 沭阳-58131|70457-S 泗阳-58131|70456-S 泗洪-58131|71826-S 宿城-58131|72233-S 宿迁经济技术开发区-58131','71825-G 高港-58246|71824-H 海陵-58246|60931-J 姜堰-58246|60042-J 靖江-58246|58246-T 泰州-58246|60932-T 泰兴-58246|72232-T 泰州医药高新技术产业开发区-58246|60381-X 兴化-58246','71364-X 锡山-58354|71803-B 滨湖-58354|71802-H 惠山-58354|60040-J 江阴-58354|71804-L 梁溪-58354|58354-W 无锡-58354|71805-X 新吴-58354|60039-Y 宜兴-58354','71369-T 铜山-58027|70439-F 丰县-58027|72225-G 鼓楼区-58027|71816-J 贾汪-58027|70454-P 沛县-58027|60675-P 邳州-58027|71817-Q 泉山-58027|70458-S 睢宁-58027|58027-X 徐州-58027|60676-X 新沂-58027|72234-X 徐州经济技术开发区-58027|71815-Y 云龙-58027','71368-Y 盐都-58151|70436-B 滨海-58151|60043-D 东台-58151|70437-D 大丰-58151|70440-F 阜宁-58151|70449-J 建湖-58151|70455-S 射阳-58151|71814-T 亭湖-58151|70460-X 响水-58151|58151-Y 盐城-58151|72235-Y 盐城经济技术开发区-58151','71367-H 邗江-58245|70435-B 宝应-58245|60467-G 高邮-58245|71813-G 广陵-58245|60402-J 江都-58245|58245-Y 扬州-58245|60466-Y 仪征-58245|72236-Y 扬州经济技术开发区-58245','71365-D 丹徒-58248|60308-D 丹阳-58248|60307-J 句容-58248|71806-J 京口-58248|71807-R 润州-58248|60309-Y 扬中-58248|58248-Z 镇江-58248|72237-Z 镇江新区-58248'] +provqx[26]=['58606-N 南昌-58606|70463-A 安义-58606|71933-D 东湖-58606|60904-J 进贤-58606|71105-N 南昌县-58606|71935-Q 青云谱-58606|71937-Q 青山湖-58606|71936-W 湾里-58606|60868-X 新建-58606|71934-X 西湖-58606','70465-C 崇仁-58617|70470-D 东乡-58617|58617-F 抚州-58617|60501-G 广昌-58617|60858-J 金溪-58617|60857-L 乐安-58617|60908-L 黎川-58617|71941-L 临川-58617|60068-N 南城-58617|60069-N 南丰-58617|60500-Y 宜黄-58617|61036-Z 资溪-58617','71399-G 赣县-57993|70464-A 安远-57993|70466-C 崇义-57993|70467-D 大余-57993|70469-D 定南-57993|57993-G 赣州-57993|61035-H 会昌-57993|60503-L 龙南-57993|60504-N 南康-57993|60905-N 宁都-57993|60505-Q 全南-57993|60070-R 瑞金-57993|70483-S 上犹-57993|60860-S 石城-57993|60943-X 信丰-57993|60859-X 寻乌-57993|60906-X 兴国-57993|60506-Y 于都-57993|71945-Z 章贡-57993','72238-C 柴桑区-58502|70468-D 德安-58502|70471-D 都昌-58502|71939-G 共青城-58502|70476-H 湖口-58502|58502-J 九江-58502|60862-L 濂溪-58502|60690-P 彭泽-58502|60508-R 瑞昌-58502|60864-W 武宁-58502|60863-X 庐山-58502|60865-X 修水-58502|71938-X 浔阳-58502|60507-Y 永修-58502','71400-F 浮梁-58527|71946-C 昌江-58527|58527-J 景德镇-58527|60855-L 乐平-58527|71947-Z 珠山-58527','71398-J 吉安县-57799|70462-A 安福-57799|57799-J 吉安-57799|60854-J 吉水-57799|70478-J 井冈山-57799|71943-J 吉州-57799|70480-N 宁冈-57799|71944-Q 青原-57799|60907-S 遂川-57799|60495-T 泰和-57799|60867-W 万安-57799|60853-X 新干-57799|60933-X 峡江-57799|60627-Y 永丰-57799|60628-Y 永新-57799','71402-A 安源-57786|71403-L 芦溪-57786|71401-S 上栗-57786|71404-X 湘东-57786|70479-L 莲花-57786|57786-P 萍乡-57786','60305-D 德兴-58637|60866-G 广丰-58637|70475-H 横峰-58637|71013-P 鄱阳-58637|58637-S 上饶-58637|60497-S 上饶县-58637|60498-W 婺源-58637|61038-W 万年-58637|71940-X 信州-58637|60499-Y 余干-58637|60856-Y 弋阳-58637|70481-Y 铅山-58637|60496-Y 玉山-58637','70473-F 分宜-57796|57796-X 新余-57796|71948-Y 渝水-57796','60934-G 贵溪-58627|58627-Y 鹰潭-58627|60861-Y 余江-58627|71949-Y 月湖-58627','70472-F 奉新-57793|60502-F 丰城-57793|60942-G 高安-57793|70477-J 靖安-57793|70482-S 上高-57793|70484-T 铜鼓-57793|70485-W 万载-57793|57793-Y 宜春-57793|61037-Y 宜丰-57793|71942-Y 袁州-57793|60086-Z 樟树-57793'] +provqx[27]=['54342-S 沈阳-54342|71545-D 大东-54342|71594-D 东陵-54342|70497-F 法库-54342|71542-H 浑南-54342|71543-H 和平-54342|71546-H 皇姑-54342|70499-K 康平-54342|70500-L 辽中-54342|71544-S 沈河-54342|71548-S 苏家屯-54342|71549-S 沈北新区-54342|71547-T 铁西-54342|60615-X 新民-54342|71550-Y 于洪-54342','54339-A 鞍山-54339|60125-H 海城-54339|71556-L 立山-54339|71557-Q 千山-54339|60126-T 台安-54339|71555-T 铁东-54339|72243-T 铁西区-54339|60828-X 岫岩-54339','54346-B 本溪-54346|70491-B 本溪县-54346|60774-H 桓仁-54346|71564-M 明山-54346|71565-N 南芬-54346|71562-P 平山-54346|71563-X 溪湖-54346','70490-B 北票-54433|54433-C 朝阳-54433|72239-C 朝阳县-54433|70942-J 建平县-54433|60136-K 喀喇沁左翼蒙古族自治县-54433|60134-L 凌源-54433|71588-L 龙城-54433|71587-S 双塔-54433','70493-C 长海-54662|54662-D 大连-54662|71554-G 甘井子-54662|60063-J 金州-54662|60131-L 旅顺-54662|60062-P 普兰店-54662|71553-S 沙河口-54662|60130-W 瓦房店-54662|71552-X 西岗-54662|60129-Z 庄河-54662|71551-Z 中山-54662','54497-D 丹东-54497|71106-D 东港-54497|71183-D 东沟-54497|60065-F 凤城-54497|60777-K 宽甸-54497|71566-Y 元宝-54497|71567-Z 振兴-54497|71568-Z 振安-54497','71559-D 东洲-54353|54353-F 抚顺-54353|72240-F 抚顺县-54353|70501-Q 清原-54353|71561-S 顺城-54353|71560-W 望花-54353|71234-X 新宾-54353|71558-X 新抚-54353|70503-Z 章党-54353','54237-F 阜新-54237|72241-F 阜新蒙古族自治县-54237|71576-H 海州-54237|71579-Q 清河门-54237|71578-T 太平-54237|71577-X 新邱-54237|71580-X 细河-54237|60127-Z 彰武-54237','54453-H 葫芦岛-54453|61060-J 建昌-54453|71591-L 连山-54453|71592-L 龙港-54453|71593-N 南票-54453|61044-S 绥中-54453|60066-X 兴城-54453','71184-B 北镇-54337|71569-G 古塔-54337|70498-H 黑山-54337|54337-J 锦州-54337|60064-L 凌海-54337|71570-L 凌河-54337|71571-T 太和-54337|60693-Y 义县-54337','71246-G 弓长岭-54347|71581-B 白塔-54347|70496-D 灯塔-54347|71583-H 宏伟-54347|54347-L 辽阳-54347|60977-L 辽阳县-54347|71584-T 太子河-54347|71582-W 文圣-54347','70495-D 大洼-54338|54338-P 盘锦-54338|70506-P 盘山-54338|71589-S 双台子-54338|71590-X 兴隆台-54338','70494-C 昌图-54249|71247-D 调兵山-54249|60128-K 开原-54249|71586-Q 清河-54249|54249-T 铁岭-54249|72242-T 铁岭县-54249|61061-X 西丰-54249|71585-Y 银州-54249','71574-B 鲅鱼圈-54471|60133-D 大石桥-54471|60775-G 盖州-54471|71575-L 老边-54471|71573-X 西市-54471|54471-Y 营口-54471|71572-Z 站前-54471'] +provqx[28]=['53463-H 呼和浩特-53463|70385-H 和林格尔-53463|71596-H 回民-53463|72245-H 呼和浩特金海工业园区-53463|72246-H 呼和浩特经济技术开发区-53463|60987-Q 清水河-53463|71107-S 赛罕-53463|70412-T 土默特左旗-53463|60988-T 托克托-53463|70415-W 武川-53463|71595-X 新城-53463|71597-Y 玉泉-53463','60150-W 乌兰察布-60150|70401-C 察哈尔右前旗-60150|70402-C 察哈尔右中旗-60150|70404-C 察哈尔右后旗-60150|60991-F 丰镇-60150|60684-H 化德-60150|71425-J 集宁-60150|70394-L 凉城-60150|60764-S 商都-60150|70406-S 四子王旗-60150|60990-X 兴和-60150|70429-Z 卓资-60150','60149-X 锡林郭勒-60149|70357-A 阿巴嘎旗-60149|70365-B 博克图-60149|70370-D 东乌珠穆沁旗-60149|70371-D 多伦-60149|60148-E 二连浩特-60149|70408-S 苏尼特左旗-60149|70407-S 苏尼特右旗-60149|70434-T 太仆寺旗-60149|70416-W 乌拉盖-60149|70423-X 西乌珠穆沁旗-60149|70419-X 镶黄旗-60149|71426-X 锡林浩特-60149|70390-Z 朱日和-60149|70427-Z 正镶白旗-60149|70426-Z 正蓝旗-60149','71418-B 巴彦诺日公-60356|60356-A 阿拉善盟-60356|70358-A 阿拉善右旗-60356|71427-A 阿拉善左旗-60356|70943-B 巴彦诺尔贡-60356|70374-E 额济纳旗-60356|70378-G 拐子湖-60356|70389-J 吉兰太-60356|71187-L 孪井滩-60356|72248-N 内蒙古阿拉善经济开发区-60356|70409-T 头道湖-60356|71189-W 乌斯太-60356|71110-X 锡林高勒-60356|71188-Y 雅布赖-60356|70428-Z 中泉子-60356','53446-B 包头-53446|60989-B 白云鄂博-53446|72244-B 包头稀土高新技术产业开发区-53446|70945-D 达尔罕茂明安-53446|71598-D 东河-53446|70379-G 固阳-53446|71602-J 九原-53446|71599-K 昆都仑-53446|70395-M 满都拉-53446|71600-Q 青山-53446|71601-S 石拐-53446|70411-T 土默特右旗-53446|70421-X 希拉穆仁-53446','70360-A 阿鲁科尔沁旗-54218|70359-A 敖汉旗-54218|70363-B 巴林左旗-54218|70361-B 巴林右旗-54218|70362-B 八里罕-54218|70944-B 宝国吐-54218|54218-C 赤峰-54218|70376-G 岗子-54218|70383-H 浩尔吐-54218|71607-H 红山-54218|70392-K 克什克腾旗-54218|61058-K 喀喇沁旗-54218|71435-K 喀喇沁-54218|60146-L 林西-54218|60147-N 宁城-54218|71609-S 松山-54218|70414-W 翁牛特旗-54218|71608-Y 元宝山-54218','60976-D 达拉特旗-71109|71186-D 东胜-71109|71109-E 鄂尔多斯-71109|70400-E 鄂托克前旗-71109|70399-E 鄂托克旗-71109|70384-H 河南-71109|70382-H 杭锦旗-71109|72247-K 康巴什区-71109|70417-W 乌审旗-71109|70418-W 乌审召-71109|70373-Y 伊金霍洛旗-71109|60353-Z 准格尔旗-71109','61069-A 阿荣旗-71108|70366-C 陈巴尔虎旗-71108|71434-C 陈旗-71108|70398-E 鄂伦春旗-71108|70375-E 鄂温克旗-71108|70372-E 额尔古纳-71108|60649-G 根河-71108|71108-H 呼伦贝尔-71108|60144-H 海拉尔-71108|70396-M 莫力达瓦旗-71108|60143-M 满洲里-71108|70410-T 图里河-71108|70420-X 小二沟-71108|60145-X 新巴尔虎左旗-71108|70422-X 新巴尔虎右旗-71108|60003-Y 牙克石-71108|70425-Z 扎兰屯-71108|71610-Z 扎赉诺尔-71108','70369-D 磴口-60002|70368-D 大佘太-60002|70380-H 海力素-60002|70381-H 杭锦后旗-60002|60002-L 巴彦淖尔-60002|71424-L 临河-60002|70397-N 那仁宝力格-60002|60151-W 五原-60002|60763-W 乌拉特前旗-60002|61070-W 乌拉特中旗-60002|70413-W 乌拉特后旗-60002','70364-B 巴雅尔吐胡硕-54135|71185-H 霍林郭勒-54135|70431-K 科尔沁左中旗-54135|70386-K 科尔沁左后旗-54135|70391-K 开鲁-54135|70393-K 库伦旗-54135|71606-K 科尔沁-54135|60352-N 奈曼旗-54135|70403-Q 青龙山-54135|70405-S 舍伯吐-54135|54135-T 通辽-54135|72249-T 通辽经济技术开发区-54135|70388-Z 扎鲁特旗-54135','71603-H 海勃湾-53512|71604-H 海南-53512|53512-W 乌海-53512|71605-W 乌达-53512','71248-K 科尔沁右前旗-60001|61059-A 阿尔山-60001|70377-G 高力板-60001|70387-H 胡尔勒-60001|60355-K 科尔沁右中旗-60001|70946-S 索伦-60001|60335-T 突泉-60001|71238-W 乌兰浩特-60001|60001-X 兴安盟-60001|60357-Z 扎赉特旗-60001'] +provqx[29]=['53614-Y 银川-53614|70507-H 贺兰-53614|71742-J 金凤-53614|70509-L 灵武-53614|71740-X 兴庆-53614|71741-X 西夏-53614|60320-Y 永宁-53614','53817-G 固原-53817|60322-J 泾源-53817|70511-L 隆德-53817|71191-P 彭阳-53817|60321-X 西吉-53817|71746-Y 原州-53817','71743-D 大武口-53518|70508-H 惠农-53518|70513-P 平罗-53518|53518-S 石嘴山-53518|70515-T 陶乐-53518','71745-H 红寺堡-53612|71744-L 利通-53612|60754-Q 青铜峡-53612|70516-T 同心-53612|53612-W 吴忠-53612|60755-Y 盐池-53612','70518-H 海原-53704|71747-S 沙坡头-53704|53704-Z 中卫-53704|60753-Z 中宁-53704'] +provqx[30]=['52866-X 西宁-52866|71723-C 城东-52866|71724-C 城中-52866|71725-C 城西-52866|71726-C 城北-52866|70523-D 大通-52866|70533-H 湟源-52866|70534-H 湟中-52866','71442-D 都兰-71113|71440-D 德令哈-71113|71441-G 格尔木-71113|71113-H 海西-71113|71195-L 冷湖-71113|70521-D 大柴旦-71113|70540-M 茫崖-71113|60691-T 天峻-71113|70548-W 乌兰-71113','70519-B 班玛-71729|70522-D 达日-71729|70529-G 玛沁-71729|70525-G 甘德-71729|71729-G 果洛-71729|70537-J 久治-71729|70539-M 玛多-71729','71194-G 刚察-71112|71112-H 海北-71112|72107-H 海晏-71112|70541-M 门源-71112|60326-Q 祁连-71112','71114-H 黄南-71114|71196-H 河南-71114|70536-J 尖扎-71114|72106-T 同仁-71114|70554-Z 泽库-71114','52875-P 平安-71727|70535-H 互助-71727|70532-H 化隆-71727|71727-H 海东-71727|60324-L 乐都-71727|60325-M 民和-71727|70551-X 循化-71727','71111-G 共和-71728|70527-G 贵德-71728|70528-G 贵南-71728|71728-H 海南-71728|60327-T 同德-71728|70550-X 兴海-71728','71353-C 称多-70552|70542-N 囊谦-70552|70545-Q 曲麻莱-70552|70552-Y 玉树-70552|72250-Y 玉树市-70552|70555-Z 治多-70552|70553-Z 杂多-70552'] +provqx[31]=['54823-J 济南-54823|70607-C 长清-54823|71698-G 钢城-54823|71670-H 槐荫-54823|60817-J 济阳-54823|72258-J 济南高新技术产业开发区-54823|54828-L 莱芜-54823|71668-L 历下-54823|71672-L 历城-54823|70622-P 平阴-54823|70627-S 商河-54823|71669-S 市中-54823|71671-T 天桥-54823|60208-Z 章丘-54823','54734-B 滨州-54734|60972-B 博兴-54734|71692-B 滨城-54734|70645-H 惠民-54734|61050-W 无棣-54734|70638-Y 阳信-54734|60822-Z 沾化-54734|60937-Z 邹平-54734','54736-D 东营-54736|72253-D 东营港经济开发区-54736|72254-D 东营经济技术开发区-54736|72255-D 东营区-54736|60404-G 广饶-54736|70617-H 河口-54736|60821-K 垦利-54736|60827-L 利津-54736','54714-D 德州-54714|71678-D 德城-54714|72251-D 德州经济技术开发区-54714|72252-D 德州运河经济开发区-54714|60216-L 临邑-54714|60823-L 陵城-54714|60217-L 乐陵-54714|61083-N 宁津-54714|70623-P 平原-54714|70624-Q 齐河-54714|70625-Q 庆云-54714|70634-W 武城-54714|70635-X 夏津-54714|70642-Y 禹城-54714','70628-S 单县-54906|70606-C 曹县-54906|70610-C 成武-54906|60671-D 东明-54906|70612-D 定陶-54906|54906-H 菏泽-54906|72256-H 菏泽高新技术开发区-54906|72257-H 菏泽经济技术开发区-54906|60819-J 鄄城-54906|60818-J 巨野-54906|71691-M 牡丹-54906|60405-Y 郓城-54906','54915-J 济宁-54915|60610-J 嘉祥-54915|60826-J 金乡-54915|72259-J 济宁高新技术产业开发区-54915|60492-L 梁山-54915|60668-Q 曲阜-54915|71685-R 任城-54915|61086-S 泗水-54915|70632-W 微山-54915|70633-W 汶上-54915|70643-Y 鱼台-54915|60659-Y 兖州-54915|60936-Z 邹城-54915','70614-F 费县-54938|71690-H 河东-54938|70618-J 莒南-54938|54938-L 临沂-54938|70605-L 兰陵-54938|70619-L 临沭-54938|71688-L 兰山-54938|71689-L 罗庄-54938|72260-L 临沂高新技术产业开发区-54938|72261-L 临沂经济技术开发区-54938|72262-L 临沂临港经济开发区-54938|61049-M 蒙阴-54938|70621-P 平邑-54938|70631-T 郯城-54938|70640-Y 沂南-54938|70641-Y 沂水-54938','70611-C 茌平-54806|70613-D 东阿-54806|71699-D 东昌府-54806|70616-G 冠县-54806|70615-G 高唐-54806|54806-L 聊城-54806|61087-L 临清-54806|71198-S 莘县-54806|70637-Y 阳谷-54806','71676-C 城阳-54857|60813-H 黄岛-54857|60209-J 即墨-54857|60670-J 胶州-54857|60820-L 崂山-54857|60814-L 莱西-54857|71675-L 李沧-54857|70620-P 平度-54857|54857-Q 青岛-54857|72263-Q 青岛高新技术产业开发区-54857|71673-S 市南-54857|71674-S 市北-54857','71695-D 东港-54945|60490-J 莒县-54945|71696-L 岚山-54945|54945-R 日照-54945|72264-R 日照经济技术开发区-54945|60491-W 五莲-54945','61048-D 东平-54827|71687-D 岱岳-54827|60621-F 肥城-54827|60816-N 宁阳-54827|54827-T 泰安-54827|71686-T 泰山-54827|60221-X 新泰-54827','70948-A 安丘-54843|60212-C 昌乐-54843|60213-C 昌邑-54843|71683-F 坊子-54843|60214-G 高密-54843|71682-H 寒亭-54843|71684-K 奎文-54843|60211-L 临朐-54843|60444-Q 青州-54843|60493-S 寿光-54843|54843-W 潍坊-54843|71681-W 潍城-54843|72268-W 潍坊滨海经济技术开发区-54843|60215-Z 诸城-54843','70609-C 成山头-54774|71693-H 环翠-54774|70949-R 荣成-54774|60971-R 乳山-54774|70629-S 石岛-54774|54774-W 威海-54774|60220-W 文登-54774|72265-W 威海火炬高技术产业开发区-54774|72266-W 威海经济技术开发区-54774|72267-W 威海临港经济技术开发区-54774','60825-C 长岛-54765|60219-F 福山-54765|60812-H 海阳-54765|60824-L 莱州-54765|60488-L 龙口-54765|60218-L 莱阳-54765|71680-L 莱山-54765|60489-M 牟平-54765|60445-P 蓬莱-54765|70626-Q 栖霞-54765|54765-Y 烟台-54765|72269-Y 烟台高新技术产业开发区-54765|72270-Y 烟台经济技术开发区-54765|60021-Z 招远-54765|71679-Z 芝罘-54765','60210-B 博山-54830|61084-G 高青-54830|61047-H 桓台-54830|60815-L 临淄-54830|60667-Y 沂源-54830|54830-Z 淄博-54830|60244-Z 淄川-54830|70644-Z 周村-54830|71677-Z 张店-54830','71694-S 山亭-58024|72271-S 市中区-58024|70630-T 台儿庄-58024|60222-T 滕州-58024|70636-X 薛城-58024|70639-Y 峄城-58024|58024-Z 枣庄-58024'] +provqx[32]=['53772-T 太原-53772|71263-G 古交-53772|70950-J 尖草坪区-53772|71264-X 小店区-53772|71640-J 晋源-53772|70667-L 娄烦-53772|70673-Q 清徐-53772|72277-S 山西转型综合改革示范区-53772|70951-T 太原古交区-53772|70952-T 太原南郊-53772|71639-W 万柏林-53772|71638-X 杏花岭-53772|70695-Y 阳曲-53772|71637-Y 迎泽-53772','53882-C 长治-53882|70647-C 长子-53882|70657-H 壶关-53882|70664-L 黎城-53882|60225-L 潞城-53882|72272-L 潞州区-53882|70671-P 平顺-53882|61063-Q 沁县-53882|70674-Q 沁源-53882|72276-S 山西长治高新技术产业园区-53882|72278-S 上党区-53882|70680-T 屯留-53882|60224-W 武乡-53882|60707-X 襄垣-53882','71266-L 灵丘-53487|53487-D 大同-53487|60781-G 广灵-53487|70658-H 浑源-53487|70665-L 灵邱-53487|71642-N 南郊-53487|72273-P 平城区-53487|72274-S 山西大同经济开发区-53487|60782-T 天镇-53487|71643-X 新荣-53487|60697-Y 阳高-53487|70650-Y 云州区-53487|72279-Y 云冈区-53487|70694-Z 左云-53487','72280-C 城区-53976|60696-G 高平-53976|53976-J 晋城-53976|60227-L 陵川-53976|60226-Q 沁水-53976|60228-Y 阳城-53976|71268-Z 泽州-53976','60785-H 和顺-71115|71115-J 晋中-71115|60241-J 介休-71115|60242-L 灵石-71115|70672-P 平遥-71115|60240-Q 祁县-71115|70679-S 寿阳-71115|60336-T 太谷-71115|70689-X 昔阳-71115|60239-Y 榆次-71115|60784-Y 榆社-71115|70693-Z 左权-71115','70646-A 安泽-53868|70649-D 大宁-53868|70653-F 汾西-53868|70654-F 浮山-53868|70655-G 古县-53868|70656-H 洪洞-53868|60229-H 霍州-53868|60708-H 侯马-53868|70662-J 吉县-53868|53868-L 临汾-53868|71036-P 蒲县-53868|60709-Q 曲沃-53868|60779-X 隰县-53868|60694-X 襄汾-53868|60780-X 乡宁-53868|70690-Y 永和-53868|60778-Y 翼城-53868|71645-Y 尧都-53868','70652-F 方山-71037|60233-F 汾阳-71037|70660-J 交口-71037|60620-J 交城-71037|71037-L 吕梁-71037|60231-L 离石-71037|60783-L 临县-71037|60232-L 岚县-71037|60648-L 柳林-71037|70678-S 石楼-71037|60619-W 文水-71037|70687-X 兴县-71037|60230-X 孝义-71037|60234-Z 中阳-71037','60243-H 怀仁-53578|70669-P 平鲁-53578|53578-S 朔州-53578|70676-S 山阴-53578|71647-S 朔城-53578|72275-S 山西朔州经济开发区-53578|70691-Y 右玉-53578|60695-Y 应县-53578','60789-B 保德-53674|70651-D 定襄-53674|70648-D 代县-53674|60788-F 繁峙-53674|60685-H 河曲-53674|70661-J 静乐-53674|70663-K 岢岚-53674|61068-N 宁武-53674|61062-P 偏关-53674|70677-S 神池-53674|70953-W 五台县-53674|70683-W 五台山-53674|70685-W 五寨-53674|53674-X 忻州-53674|71648-X 忻府-53674|60067-Y 原平-53674','72281-C 城区-53782|71644-J 郊区-53782|71641-K 矿区-53782|70668-P 平定-53782|53782-Y 阳泉-53782|60237-Y 盂县-53782','60236-H 河津-53959|61064-J 稷山-53959|70659-J 绛县-53959|70666-L 临猗-53959|70670-P 平陆-53959|70675-R 芮城-53959|70681-W 万荣-53959|70682-W 闻喜-53959|70688-X 新绛-53959|70686-X 夏县-53959|53959-Y 运城-53959|70692-Y 垣曲-53959|60235-Y 永济-53959|71646-Y 盐湖-53959'] +provqx[33]=['57036-X 西安-57036|71650-B 碑林-57036|71652-B 灞桥-57036|70560-C 长安-57036|70573-G 高陵-57036|70580-HY 鄠邑区-57036|70584-L 临潼-57036|60549-L 蓝田-57036|71651-L 莲湖-57036|71653-W 未央-57036|71649-X 新城-57036|71654-Y 雁塔-57036|71655-Y 阎良-57036|60957-Z 周至-57036','57245-A 安康-57245|60961-B 白河-57245|60962-H 汉阴-57245|71661-H 汉滨-57245|60966-L 岚皋-57245|60965-N 宁陕-57245|70588-P 平利-57245|60964-S 石泉-57245|60960-X 旬阳-57245|60331-Z 紫阳-57245|60963-Z 镇坪-57245','57016-B 宝鸡-57016|71225-C 陈仓-57016|60543-F 凤翔-57016|60541-F 扶风-57016|60968-F 凤县-57016|71664-J 金台-57016|70585-L 麟游-57016|60956-L 陇县-57016|60386-M 眉县-57016|70591-Q 千阳-57016|60387-Q 岐山-57016|60542-T 太白-57016|71663-W 渭滨-57016','70562-C 城固-57127|70568-F 佛坪-57127|57127-H 汉中-57127|71662-H 汉台-57127|60544-L 略阳-57127|60547-L 留坝-57127|60329-M 勉县-57127|60546-N 宁强-57127|60385-N 南郑-57127|60384-X 西乡-57127|60328-Y 洋县-57127|60545-Z 镇巴-57127','71273-S 商州-71031|70565-D 丹凤-71031|60969-L 洛南-71031|71031-S 商洛-71031|60548-S 商南-71031|60970-S 山阳-71031|60967-Z 柞水-71031|70603-Z 镇安-71031','71275-Y 耀州-53947|53947-T 铜川-53947|71665-W 王益-53947|70600-Y 耀县-53947|70602-Y 宜君-53947|71666-Y 印台-53947','70558-B 白水-57045|70566-C 澄城-57045|70564-D 大荔-57045|70570-F 富平-57045|70579-H 华县-57045|70575-H 合阳-57045|60330-H 韩城-57045|60383-H 华阴-57045|71660-H 华州-57045|71659-L 临渭-57045|70589-P 蒲城-57045|70596-T 潼关-57045|57045-W 渭南-57045','70559-B 彬州市-57048|70563-C 淳化-57048|70561-C 长武-57048|70583-J 泾阳-57048|70586-L 礼泉-57048|70590-Q 乾县-57048|71656-Q 秦都-57048|70593-S 三原-57048|60679-W 武功-57048|71657-W 渭城-57048|57048-X 咸阳-57048|60958-X 旬邑-57048|60539-X 兴平-57048|60540-Y 永寿-57048|71667-Y 杨陵-57048','71269-W 吴起-53845|70557-A 安塞-53845|71658-B 宝塔-53845|70571-F 富县-53845|70572-G 甘泉-53845|70576-H 黄陵-53845|70577-H 黄龙-53845|71030-L 洛川-53845|70598-W 吴旗-53845|53845-Y 延安-53845|70599-Y 延长-53845|60538-Y 延川-53845|70601-Y 宜川-53845|60537-Z 子长-53845|60536-Z 志丹-53845','70567-D 定边-53646|70569-F 府谷-53646|70574-H 横山-53646|70581-J 佳县-53646|70582-J 靖边-53646|70587-M 米脂-53646|70592-Q 清涧-53646|70594-S 神木-53646|70595-S 绥德-53646|70597-W 吴堡-53646|53646-Y 榆林-53646|71270-Y 榆阳-53646|70604-Z 子洲-53646','71199-Y 杨凌-71199'] +provqx[34]=['58362-S 上海-58362|71072-B 宝山-58362|60005-C 崇明-58362|71448-C 长宁-58362|60298-F 奉贤-58362|71447-H 黄浦-58362|71451-H 虹口-58362|60010-J 嘉定-58362|60006-J 金山-58362|71449-J 静安-58362|60008-M 闵行-58362|60299-N 南汇-58362|71146-P 浦东-58362|71450-P 普陀-58362|60007-Q 青浦-58362|60009-S 松江-58362|71147-X 徐汇-58362|71452-Y 杨浦-58362'] +provqx[35]=['56294-C 成都-56294|71439-Q 青白江-56294|60910-C 崇州-56294|71989-C 成华-56294|60911-D 大邑-56294|60407-D 都江堰-56294|60720-J 金堂-56294|60919-J 简阳-56294|71985-J 锦江-56294|71987-J 金牛-56294|60704-L 龙泉驿-56294|60724-P 郫都-56294|61066-P 蒲江-56294|60930-P 彭州-56294|61019-Q 邛崃-56294|71986-Q 青羊-56294|60029-S 双流-56294|60909-W 温江-56294|71988-W 武侯-56294|60912-X 新都-56294|60616-X 新津-56294','56171-A 阿坝-56171|72282-A 阿坝县-56171|70718-H 黑水-56171|70720-H 红原-56171|60925-J 九寨沟-56171|70724-J 金川-56171|61090-L 理县-56171|60923-M 茂县-56171|60722-M 马尔康-56171|70741-R 壤塘-56171|70745-R 若尔盖-56171|60721-S 松潘-56171|60924-W 汶川-56171|70752-X 小金-56171','57313-B 巴中-57313|72005-B 巴州-57313|72283-B 巴中经济开发区-57313|72006-E 恩阳-57313|60921-N 南江-57313|60922-P 平昌-57313|60027-T 通江-57313','56198-D 德阳-56198|60026-G 广汉-56198|72017-J 旌阳-56198|71204-L 罗江-56198|60412-M 绵竹-56198|60028-S 什邡-56198|60564-Z 中江-56198','71249-D 达川-57328|57328-D 达州-57328|60915-D 大竹-57328|72284-D 达州经济开发区-57328|60913-K 开江-57328|60916-Q 渠县-57328|71206-T 通川-57328|60565-W 万源-57328|60914-X 宣汉-57328','70702-C 苍溪-57206|72020-C 朝天-57206|57206-G 广元-57206|60421-J 剑阁-57206|72018-L 利州-57206|60918-Q 青川-57206|60719-W 旺苍-57206|72019-Z 昭化-57206','57415-G 广安-57415|72286-G 广安区-57415|71205-H 华蓥-57415|60420-L 邻水-57415|72004-Q 前锋-57415|60418-W 武胜-57415|60419-Y 岳池-57415','70698-B 白玉-56146|70700-B 巴塘-56146|70704-D 丹巴-56146|70707-D 道孚-56146|70709-D 德格-56146|70706-D 稻城-56146|70710-D 得荣-56146|56146-G 甘孜-56146|72285-G 甘孜县-56146|60725-J 九龙-56146|60422-K 康定-56146|60723-L 泸定-56146|70732-L 炉霍-56146|70730-L 理塘-56146|70749-S 石渠-56146|70746-S 色达-56146|60718-X 新龙-56146|70751-X 乡城-56146|70754-Y 雅江-56146','70716-G 古蔺-57602|60570-H 合江-57602|72007-J 江阳-57602|57602-L 泸州-57602|71038-L 泸县-57602|72008-L 龙马潭-57602|71203-N 纳溪-57602|60929-X 叙永-57602','70711-E 峨边-56386|70712-E 峨眉山市-56386|70725-J 井研-56386|70723-J 夹江-56386|72014-J 金口河-56386|56386-L 乐山-56386|60414-M 沐川-56386|60413-M 马边-56386|60415-Q 犍为-56386|72012-S 沙湾-56386|72288-S 市中区-56386|72013-W 五通桥-56386','71209-B 布拖-71118|70708-D 德昌-71118|61092-G 甘洛-71118|70722-H 会理-71118|70721-H 会东-71118|70726-J 金阳-71118|71118-L 凉山-71118|70728-L 雷波-71118|70737-M 木里-71118|60928-M 冕宁-71118|70734-M 美姑-71118|61091-N 宁南-71118|70740-P 普格-71118|70753-X 喜德-71118|71208-X 西昌-71118|70755-Y 盐源-71118|70757-Y 越西-71118|70758-Z 昭觉-71118','70697-A 安县-56196|72021-A 安州-56196|70701-B 北川-56196|71996-F 涪城-56196|60410-J 江油-56196|56196-M 绵阳-56196|60411-P 平武-56196|60406-S 三台-56196|60409-Y 盐亭-56196|71997-Y 游仙-56196|60408-Z 梓潼-56196','70705-D 丹棱-56391|72015-D 东坡-56391|70719-H 洪雅-56391|56391-M 眉山-56391|60917-P 彭山-56391|61089-Q 青神-56391|60566-R 仁寿-56391','71117-D 东兴-57504|70731-L 隆昌-57504|57504-N 内江-57504|72287-N 内江经济开发区-57504|72010-S 市中-57504|60416-W 威远-57504|60365-Z 资中-57504','71999-G 高坪-57411|72000-J 嘉陵-57411|60568-L 阆中-57411|57411-N 南充-57411|60926-N 南部-57411|60572-P 蓬安-57411|71998-S 顺庆-57411|60417-X 西充-57411|60567-Y 营山-57411|60571-Y 仪陇-57411','71990-D 东区-56666|70736-M 米易-56666|56666-P 攀枝花-56666|70742-R 仁和-56666|71991-X 西区-56666|61018-Y 盐边-56666','72002-A 安居-57405|72001-C 船山-57405|72003-D 大英-57405|60920-P 蓬溪-57405|57405-S 遂宁-57405|70747-S 射洪-57405','70703-C 长宁-56492|72009-C 翠屏-56492|60569-G 高县-56492|70715-G 珙县-56492|61020-J 江安-56492|70727-J 筠连-56492|70738-N 南溪-56492|70739-P 屏山-56492|70756-X 叙州区-56492|60927-X 兴文-56492|56492-Y 宜宾-56492','70699-B 宝兴-56287|70717-H 汉源-56287|70733-L 芦山-56287|70735-M 名山-56287|70748-S 石棉-56287|70750-T 天全-56287|56287-Y 雅安-56287|70743-Y 荥经-56287|72016-Y 雨城-56287','71994-D 大安-56396|70714-F 富顺-56396|71993-G 贡井-56396|70744-R 荣县-56396|71995-Y 沿滩-56396|56396-Z 自贡-56396|71992-Z 自流井-56396','61088-A 安岳-56298|70729-L 乐至-56298|72011-Y 雁江-56298|56298-Z 资阳-56298'] +provqx[36]=['59554-G 高雄-59554|71301-F 屏东-71301|71305-H 花莲-71305|71298-J 嘉义-71298|71302-M 苗栗-71302|71304-N 南投-71304|71295-T 桃园-71294|71294-T 台北-71294|71296-X 新竹-71294|71297-Y 宜兰-71294|71299-T 台南-71299|71300-T 台东-71300|71306-Y 云林-71306|71303-Z 彰化-71303|71082-T 台中-71082'] +provqx[37]=['54527-T 天津-54527|60516-B 宝坻-54527|71074-B 北辰-54527|71077-B 滨海新区-54527|60140-D 东丽-54527|71453-H 和平-54527|71454-H 河东-54527|71455-H 河西-54527|71457-H 河北-54527|71458-H 红桥-54527|60712-J 静海-54527|71076-J 津南-54527|60139-J 蓟州-54527|60517-N 宁河-54527|71456-N 南开-54527|60138-W 武清-54527|71073-X 西青-54527'] +provqx[38]=['55591-L 拉萨-55591|71308-D 堆龙德庆-55591|71310-D 达孜-55591|71307-L 林周-55591|71311-M 墨竹工卡-55591|71309-Q 曲水-55591|71722-C 城关-55591|70764-D 当雄-55591|72289-D 达孜工业园区-55591|72290-G 格尔木藏青工业园区-55591|72291-L 拉萨经济技术开发区-55591|70777-N 尼木-55591|72293-X 西藏文化旅游创意园区-55591','71350-C 措勤-55437|71347-G 噶尔-55437|71349-G 革吉-55437|71348-R 日土-55437|71346-Z 札达-55437|55437-A 阿里-55437|70958-G 改则-55437|71211-P 普兰-55437|70782-S 狮泉河-55437','71335-B 边坝-56137|71337-B 八宿-56137|71339-C 察雅-56137|71340-G 贡觉-56137|71338-J 江达-56137|71336-L 类乌齐-56137|56137-C 昌都-56137|70765-D 丁青-56137|71721-K 卡若-56137|70790-L 洛隆-56137|70789-M 芒康-56137|70787-Z 左贡-56137','71332-G 工布江达-56312|71333-L 朗县-56312|71334-M 墨脱-56312|70763-B 波密-56312|71720-B 巴宜-56312|70785-C 察隅-56312|56312-L 林芝-56312|71045-M 米林-56312','71343-B 巴青-70774|71344-B 比如-70774|71341-N 尼玛-70774|71342-N 聂荣-70774|71345-S 双湖-70774|70760-A 安多-70774|70761-B 班戈-70774|70769-J 嘉黎-70774|70774-N 那曲-70774|70783-S 索县-70774|70784-S 申扎-70774|72292-S 色尼区-70774','71315-A 昂仁-55578|71320-B 白朗-55578|71316-D 定结-55578|71319-G 岗巴-55578|71314-J 吉隆-55578|71322-K 康马-55578|71323-R 仁布-55578|71313-S 萨嘎-55578|71317-S 萨迦-55578|71318-X 谢通门-55578|71321-Y 亚东-55578|71312-Z 仲巴-55578|70766-D 定日-55578|70768-J 江孜-55578|70770-L 拉孜-55578|70775-N 南木林-55578|70776-N 聂拉木-55578|70778-P 帕里-55578|55578-R 日喀则-55578|71719-S 桑珠孜-55578','71329-C 措美-55597|71324-G 贡嘎-55597|71328-L 洛扎-55597|71326-N 乃东-55597|71330-Q 琼结-55597|71331-Q 曲松-55597|71327-S 桑日-55597|71325-Z 扎囊-55597|71044-C 错那-55597|70767-J 加查-55597|70773-L 浪卡子-55597|70771-L 隆子-55597|55597-S 山南-55597|71210-Z 泽当-55597'] +provqx[39]=['45007-X 香港-45007|71291-J 九龙-45007|71079-X 新界-45007'] +provqx[40]=['51463-W 乌鲁木齐-51463|70795-B 巴仑台-51463|71212-B 白杨沟-51463|71120-D 达坂城-51463|71705-M 米东-51463|71701-S 沙依巴克-51463|71703-S 水磨沟-51463|70834-T 天池-51463|71700-T 天山-51463|71704-T 头屯河-51463|71121-W 乌市牧试站-51463|71718-W 乌鲁木齐县-51463|72303-W 乌鲁木齐经济技术开发区-51463|72304-W 乌鲁木齐高新技术产业开发区-51463|71119-X 小渠子-51463|71702-X 新市-51463','51656-B 巴音郭楞-51656|70797-B 巴音布鲁克-51656|71214-B 博湖-51656|70805-H 和静-51656|70808-H 和硕-51656|71419-K 库尔勒-51656|72301-K 库尔勒经济技术开发区-51656|60897-L 轮台-51656|70827-Q 且末-51656|70830-R 若羌-51656|70835-T 铁干里克-51656|71213-T 塔中-51656|71050-Y 尉犁-51656|60896-Y 焉耆-51656','51704-K 克州-51704|70792-A 阿克陶-51704|70791-A 阿合奇-51704|71428-A 阿图什-51704|70838-W 乌恰-51704','51628-A 阿克苏-51628|61072-A 阿瓦提-51628|72294-A 阿克苏市-51628|70794-B 拜城-51628|61071-K 库车-51628|70812-K 柯坪-51628|61073-S 沙雅-51628|70839-W 乌什-51628|70837-W 温宿-51628|70840-X 新和-51628','51076-A 阿勒泰-51076|72295-A 阿勒泰市-51076|70799-B 布尔津-51076|70802-F 福海-51076|70803-F 富蕴-51076|61077-H 哈巴河-51076|70810-J 吉木乃-51076|70828-Q 青河-51076','51730-A 阿拉尔-51730','51238-B 博州-51238','71708-B 巴州-71708','70793-A 阿拉山口-71710|71429-B 博乐-71710|71710-B 博尔塔拉-71710|60611-J 精河-71710|60692-W 温泉-71710','71714-B 北屯-71714','51368-C 昌吉-51368|72296-C 昌吉市-51368|60638-F 阜康-51368|60894-H 呼图壁-51368|70811-J 吉木萨尔-51368|60893-M 米泉-51368|60811-M 玛纳斯-51368|70821-M 木垒-51368|70829-Q 奇台-51368','70796-B 巴里坤-52203|52203-H 哈密-52203|70844-Y 伊吾-52203|71711-Y 伊州-52203','70800-C 策勒-51828|51828-H 和田-51828|72297-H 和田市-51828|72298-H 和田县-51828|70815-L 洛浦-51828|70820-M 墨玉-51828|70818-M 民丰-51828|60898-P 皮山-51828|60281-Y 于田-51828','71279-B 白碱滩-51243|71277-W 乌尔禾-51243|71706-D 独山子-51243|51243-K 克拉玛依-51243|72300-K 克拉玛依区-51243','71282-S 疏附-51709|71283-S 疏勒-51709|70817-B 巴楚-51709|70824-J 伽师-51709|51709-K 喀什-51709|72299-K 喀什市-51709|70816-M 麦盖提-51709|70841-S 莎车-51709|70849-T 塔什库尔干-51709|70842-Y 英吉沙-51709|70813-Y 叶城-51709|70846-Y 岳普湖-51709|70826-Z 泽普-51709','71717-K 可克达拉-71717','72108-K 昆玉市-72108','70819-M 莫索湾-51356|70825-P 炮台-51356|51356-S 石河子-51356','71716-S 双河-71716','71707-G 高昌-51573|60895-S 鄯善-51573|51573-T 吐鲁番-51573|70836-T 托克逊-51573','70801-E 额敏-51133|70806-H 和布克赛尔-51133|70831-S 沙湾-51133|51133-T 塔城-51133|60892-T 托里-51133|72302-T 塔城市-51133|60280-W 乌苏-51133|70845-Y 裕民-51133','71712-T 图木舒克-71712','71715-T 铁门关-71715','71048-C 蔡家湖-71713|71713-W 五家渠-71713','51431-Y 伊宁-71709|61075-C 察布查尔-71709|70804-G 巩留-71709|61074-H 霍城-71709|70809-H 霍尔果斯-71709|71233-K 奎屯-71709|70822-N 尼勒克-71709|70833-T 特克斯-71709|61076-X 新源-71709|70843-Y 伊宁县-71709|71709-Y 伊犁-71709|70847-Z 昭苏-71709'] +provqx[41]=['56778-K 昆明-56778|60848-A 安宁-56778|70852-C 呈贡-56778|70856-D 东川-56778|70859-F 富民-56778|72054-G 官渡-56778|70872-J 晋宁-56778|61016-L 禄劝-56778|72053-P 盘龙-56778|70960-S 石林-56778|61004-S 嵩明-56778|71063-T 太华山-56778|72052-W 五华-56778|70897-X 寻甸-56778|72055-X 西山-56778|61003-Y 宜良-56778','70908-D 迪庆-70908|60843-D 德钦-70908|71065-W 维西-70908|71432-X 香格里拉-70908|71216-Z 中甸-70908','60839-X 西双版纳-60839|71433-J 景洪-60839|61006-M 勐海-60839|70959-M 勐腊-60839','56748-B 保山-56748|61010-C 昌宁-56748|61009-L 龙陵-56748|72057-L 隆阳-56748|61007-S 施甸-56748|61008-T 腾冲-56748','56768-C 楚雄-56768|72305-C 楚雄市-56768|70855-D 大姚-56768|60845-L 禄丰-56768|61015-M 牟定-56768|60851-N 南华-56768|70889-S 双柏-56768|61011-W 武定-56768|70904-Y 元谋-56768|70899-Y 姚安-56768|70901-Y 永仁-56768','70850-B 宾川-56751|56751-D 大理-56751|72306-D 大理市-56751|70857-E 洱源-56751|70864-H 鹤庆-56751|60939-J 剑川-56751|60844-M 弥渡-56751|70885-N 南涧-56751|71125-W 巍山-56751|61005-X 祥云-56751|60941-Y 云龙-56751|70961-Y 漾濞-56751|60940-Y 永平-56751','71219-M 芒市-71126|71126-D 德宏-71126|70875-L 陇川-71126|70874-L 梁河-71126|60852-R 瑞丽-71126|60841-Y 盈江-71126','60454-G 个旧-56975|71055-H 河口-56975|56975-H 红河-56975|72307-H 红河县-56975|70869-J 建水-56975|60153-J 金平-56975|60456-K 开远-56975|70876-L 绿春-56975|60155-L 泸西-56975|60842-M 弥勒-56975|60152-M 蒙自-56975|60154-P 屏边-56975|60455-S 石屏-56975|70905-Y 元阳-56975','72061-G 古城-56651|71056-H 华坪-56651|56651-L 丽江-56651|70886-N 宁蒗-56651|70902-Y 永胜-56651|72062-Y 玉龙-56651','70851-C 沧源-56951|60157-F 凤庆-56951|70861-G 耿马-56951|56951-L 临沧-56951|72060-L 临翔-56951|70890-S 双江-56951|60156-Y 永德-56951|60938-Y 云县-56951|70906-Z 镇康-56951','61013-F 福贡-71127|71220-G 贡山-71127|70873-L 兰坪-71127|70909-L 六库-71127|71127-N 怒江-71127|71221-S 泸水-71127','70871-J 景谷-70887|70870-J 景东-70887|70867-J 江城-70887|60457-L 澜沧-70887|70884-M 墨江-70887|70883-M 孟连-70887|71217-N 宁洱-70887|70887-P 普洱-70887|56964-S 思茅-70887|70895-X 西盟-70887|71218-Z 镇沅-70887','70860-F 富源-56783|70866-H 会泽-56783|70878-L 陆良-56783|70879-L 罗平-56783|70882-M 马龙-56783|56783-Q 曲靖-56783|72056-Q 麒麟-56783|60850-S 师宗-56783|60847-X 宣威-56783|60849-Z 沾益-56783','71287-Q 丘北-56994|60458-F 富宁-56994|70863-G 广南-56994|70880-M 马关-56994|70881-M 麻栗坡-56994|71123-Q 邱北-56994|56994-W 文山-56994|72308-W 文山市-56994|70894-X 西畴-56994|61012-Y 砚山-56994','70853-C 澄江-56875|70858-E 峨山-56875|70865-H 华宁-56875|72058-H 红塔-56875|70868-J 江川-56875|70892-T 通海-56875|70896-X 新平-56875|56875-Y 玉溪-56875|61014-Y 易门-56875|70903-Y 元江-56875','71288-S 水富-56586|71122-D 大关-56586|70877-L 鲁甸-56586|70888-Q 巧家-56586|70891-S 绥江-56586|70893-W 威信-56586|70900-Y 彝良-56586|71067-Y 永善-56586|70898-Y 盐津-56586|56586-Z 昭通-56586|60846-Z 镇雄-56586|72059-Z 昭阳-56586'] +provqx[42]=['58457-H 杭州-58457|71855-B 滨江-58457|70914-C 淳安-58457|60658-F 富阳-58457|71853-G 拱墅-58457|60176-J 建德-58457|71852-J 江干-58457|60875-L 临安-58457|71850-S 上城-58457|60195-T 桐庐-58457|60175-X 萧山-58457|71851-X 下城-58457|71854-X 西湖-58457|71230-Y 余杭-58457','70910-A 安吉-58450|70913-C 长兴-58450|70917-D 德清-58450|58450-H 湖州-58450|71857-N 南浔-58450|71856-W 吴兴-58450','60119-H 海宁-58452|60121-H 海盐-58452|58452-J 嘉兴-58452|60194-J 嘉善-58452|71858-N 南湖-58452|60160-P 平湖-58452|60120-T 桐乡-58452|71859-X 秀洲-58452','60181-D 东阳-58549|58549-J 金华-58549|71868-J 金东-58549|60184-L 兰溪-58549|60196-P 浦江-58549|71232-P 磐安-58549|60183-W 武义-58549|71867-W 婺城-58549|60116-Y 义乌-58549|60182-Y 永康-58549','71239-J 景宁-58646|71391-S 松阳-58646|70921-J 缙云-58646|58646-L 丽水-58646|60188-L 龙泉-58646|71866-L 莲都-58646|60187-Q 青田-58646|60190-Q 庆元-58646|60191-S 遂昌-58646|60189-Y 云和-58646','71386-Y 鄞州-58465|71387-Z 镇海-58465|71222-B 北仑-58465|60192-C 慈溪-58465|70919-F 奉化-58465|71860-H 海曙-58465|71861-J 江东-58465|71862-J 江北-58465|58465-N 宁波-58465|60391-N 宁海-58465|60178-X 象山-58465|60177-Y 余姚-58465','71392-Q 衢江-58633|70912-C 常山-58633|60300-J 江山-58633|70922-K 开化-58633|71869-K 柯城-58633|70924-L 龙游-58633|58633-Q 衢州-58633','71437-K 柯桥-58453|58453-S 绍兴-58453|60646-S 上虞-58453|60118-S 嵊州-58453|60185-X 新昌-58453|72310-Y 越城区-58453|60186-Z 诸暨-58453','71389-H 黄岩-58651|71388-J 椒江-58651|71390-L 路桥-58651|70920-H 洪家-58651|71224-L 临海-58651|60395-S 三门-58651|58651-T 台州-58651|60159-T 天台-58651|60117-W 温岭-58651|60393-X 仙居-58651|60158-Y 玉环-58651','71229-C 苍南-58659|70918-D 洞头-58659|71863-L 鹿城-58659|71864-L 龙湾-58659|71865-O 瓯海-58659|70925-P 平阳-58659|60193-R 瑞安-58659|70927-T 泰顺-58659|58659-W 温州-58659|70929-W 文成-58659|72309-W 温州经济技术开发区-58659|60180-Y 乐清-58659|60179-Y 永嘉-58659','70916-D 岱山-58477|71223-D 定海-58477|60394-P 普陀-58477|60389-S 嵊泗-58477|58477-Z 舟山-58477'] +provqx[43]=['57516-C 重庆-57516|60293-B 北碚-57516|70964-B 巴南-57516|60436-B 璧山-57516|60290-C 长寿-57516|60438-C 城口-57516|60874-D 垫江-57516|60437-D 大足-57516|71460-D 大渡口-57516|60279-F 涪陵-57516|60441-F 奉节-57516|60440-F 丰都-57516|60433-H 合川-57516|60294-J 江津-57516|71461-J 江北-57516|71463-J 九龙坡-57516|60435-K 开县-57516|71465-K 开州-57516|60283-L 梁平-57516|60000-N 南川-57516|71464-N 南岸-57516|60978-P 彭水-57516|60286-Q 黔江-57516|60291-Q 綦江-57516|60296-R 荣昌-57516|60443-S 石柱-57516|71462-S 沙坪坝-57516|60292-T 潼南-57516|60434-T 铜梁-57516|60289-W 万盛-57516|70965-W 万州-57516|60442-W 巫溪-57516|60439-W 巫山-57516|60285-W 武隆-57516|60287-X 秀山-57516|60297-Y 永川-57516|70966-Y 渝北-57516|60295-Y 云阳-57516|60288-Y 酉阳-57516|71459-Y 渝中-57516|60284-Z 忠县-57516'] \ No newline at end of file diff --git "a/web/117 \344\270\212\346\265\267\345\270\202\345\233\276\344\271\246\351\246\206\345\244\247\345\261\217\347\234\213\346\235\277/static/common.js" "b/web/117 \344\270\212\346\265\267\345\270\202\345\233\276\344\271\246\351\246\206\345\244\247\345\261\217\347\234\213\346\235\277/static/common.js" new file mode 100644 index 00000000..3df88478 --- /dev/null +++ "b/web/117 \344\270\212\346\265\267\345\270\202\345\233\276\344\271\246\351\246\206\345\244\247\345\261\217\347\234\213\346\235\277/static/common.js" @@ -0,0 +1,818 @@ +// 新增馆藏/新增读者分析 +var dom = document.getElementById("echarts_1"); +var myChart = echarts.init(dom); +var app = {}; +option = null; +option = { + title: { + text: '' + }, + tooltip: { + trigger: 'axis', + axisPointer: { + type: 'cross', + label: { + backgroundColor: '#6a7985', + Color: '#fff' + } + } + }, + legend: { + textStyle: { + fontSize: 14, + color: '#a7cdff' + }, + bottom: 0, + data: ['新增馆藏', '新增读者'] + }, + grid: { + top: '3%', + left: '5%', + right: '5%', + bottom: '15%', + containLabel: true + }, + xAxis: [{ + type: 'category', + //刻度线 + axisTick: { + show: false + }, + // boundaryGap: false, + data: ['2016', '2017', '2018', '2019', '2020', '2021', '2022'], + axisLine: { + lineStyle: { + color: '#a7cdff', + width: 0, //这里是为了突出显示加上的 + } + }, + }, ], + yAxis: [{ + type: 'value', + boundaryGap: [0.2, 0.2], + //刻度线 + axisTick: { //y轴刻度线 + show: false + }, + //字体颜色 + axisLine: { + lineStyle: { + color: '#a7cdff', + width: 0, //这里是为了突出显示加上的 + } + }, + //网格线 + splitLine: { + show: true, + lineStyle: { + color: ['#23569b'], + width: 1, + type: 'dashed' + } + } + }], + color: ['#6dc1ff', '#f9b008'], + series: [{ + name: '新增馆藏', + type: 'line', + + areaStyle: { + normal: { + //颜色渐变函数 前四个参数分别表示四个位置依次为左、下、右、上 + color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{ + + offset: 0, + color: 'rgba(109,193,255,0.6)' + }, { + offset: .8, + color: 'rgba(56,155,255,0.4)' + }, { + offset: 1, + color: 'rgba(38,197,254,0.00)' + }]) + + } + }, + data: [25000, 30000, 55000, 70000, 90000, 105000, 111111] + }, + { + name: '新增读者', + type: 'line', + areaStyle: { + normal: { + //颜色渐变函数 前四个参数分别表示四个位置依次为左、下、右、上 + color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{ + + offset: 0, + color: 'rgba(249,176,8,0.8)' + }, { + offset: .34, + color: 'rgba(249,176,8,0.4)' + }, { + offset: 1, + color: 'rgba(249,176,8,0.1)' + }]) + } + }, + data: [19000, 24000, 35000, 49000, 70000, 85000, 91111] + } + ], + +}; +if (option && typeof option === "object") { + myChart.setOption(option, true); +} + + + +// 到馆人次/借阅册次分析 年 +var dom2 = document.getElementById("echarts_2"); +var myChart = echarts.init(dom2); +var app = {}; +option = null; +option = { + title: { + text: '' + }, + + tooltip: { + trigger: 'axis', + axisPointer: { + type: 'cross', + label: { + backgroundColor: '#6a7985', + Color: '#fff' + } + } + }, + legend: { + textStyle: { + fontSize: 13, + color: '#a7cdff' + }, + bottom: 0, + data: ['新增馆藏', '新增读者'] + }, + + grid: { + top: '3%', + left: '5%', + right: '5%', + bottom: '15%', + containLabel: true + }, + xAxis: [{ + type: 'category', + // boundaryGap: false, + //刻度线 + axisTick: { + show: false + }, + data: ['2010', '2011', '2012', '2013', '2014', '2015', '2016'], + axisLine: { + lineStyle: { + color: '#a7cdff', + width: 0, //这里是为了突出显示加上的 + } + }, + }, + ], + yAxis: [{ + type: 'value', + boundaryGap: [0.2, 0.2], + //刻度线 + axisTick: { //y轴刻度线 + show: false + }, + //字体颜色 + axisLine: { + lineStyle: { + color: '#a7cdff', + width: 0, //这里是为了突出显示加上的 + } + }, + //网格线 + splitLine: { + show: true, + lineStyle: { + color: ['#23569b'], + width: 1, + type: 'dashed' + } + } + } + ], + color: ['#00c5d1', '#007dec'], + series: [{ + name: '新增馆藏', + type: 'bar', + barWidth: '15', + barGap: 0, + data: [45000, 35000, 70000, 80200, 55800, 62200, 43000], + itemStyle: { + normal: { + barBorderRadius: [40, 40, 0, 0], + color: new echarts.graphic.LinearGradient( + 1, 0, 1, 1, + [{ + offset: 0, + color: '#00c7d2' + }, { + offset: 0.5, + color: '#0389b2' + }, + { + offset: 1, + color: '#045595' + } + ] + ) + }, + } + }, + { + name: '新增读者', + type: 'bar', + barWidth: '15', + barGap: 0, + itemStyle: { + normal: { + barBorderRadius: [40, 40, 0, 0], + color: new echarts.graphic.LinearGradient( + 1, 0, 1, 1, + [{ + offset: 0, + color: '#0083f5' + }, { + offset: 0.5, + color: '#0964c1' + }, + { + offset: 1, + color: '#04479b' + } + ] + ) + }, + }, + data: [56000, 65540, 69900, 45500, 52800, 62800, 59000] + } + ], + + +}; +if (option && typeof option === "object") { + myChart.setOption(option, true); +} + +// 到馆人次/借阅册次分析 月 +var dom21 = document.getElementById("echarts_21"); +var myChart = echarts.init(dom21); +var app = {}; +option = null; +option = { + title: { + text: '' + }, + + tooltip: { + trigger: 'axis', + axisPointer: { + type: 'cross', + label: { + backgroundColor: '#6a7985', + Color: '#fff' + } + } + }, + legend: { + textStyle: { + fontSize: 13, + color: '#a7cdff' + }, + bottom: 0, + data: ['新增馆藏', '新增读者'] + }, + + grid: { + top: '3%', + left: '5%', + right: '5%', + bottom: '15%', + containLabel: true + }, + xAxis: [{ + type: 'category', + // boundaryGap: false, + //刻度线 + axisTick: { + show: false + }, + data: ['01', '02', '03', '04', '05', '06', '07'], + axisLine: { + lineStyle: { + color: '#a7cdff', + width: 0, //这里是为了突出显示加上的 + } + }, + }, + ], + yAxis: [{ + type: 'value', + boundaryGap: [0.2, 0.2], + //刻度线 + axisTick: { //y轴刻度线 + show: false + }, + //字体颜色 + axisLine: { + lineStyle: { + color: '#a7cdff', + width: 0, //这里是为了突出显示加上的 + } + }, + //网格线 + splitLine: { + show: true, + lineStyle: { + color: ['#23569b'], + width: 1, + type: 'dashed' + } + } + } + ], + color: ['#00c5d1', '#007dec'], + series: [{ + name: '新增馆藏', + type: 'bar', + barWidth: '15', + barGap: 0, + data: [9800, 12000, 10000, 10200, 8800, 12200, 13000], + itemStyle: { + normal: { + barBorderRadius: [40, 40, 0, 0], + color: new echarts.graphic.LinearGradient( + 1, 0, 1, 1, + [{ + offset: 0, + color: '#00c7d2' + }, { + offset: 0.5, + color: '#0389b2' + }, + { + offset: 1, + color: '#045595' + } + ] + ) + }, + } + }, + { + name: '新增读者', + type: 'bar', + barWidth: '15', + barGap: 0, + itemStyle: { + normal: { + barBorderRadius: [40, 40, 0, 0], + color: new echarts.graphic.LinearGradient( + 1, 0, 1, 1, + [{ + offset: 0, + color: '#0083f5' + }, { + offset: 0.5, + color: '#0964c1' + }, + { + offset: 1, + color: '#04479b' + } + ] + ) + }, + }, + data: [5800, 11100, 12100, 9200, 11800, 12800, 7000] + } + ], + + +}; +if (option && typeof option === "object") { + myChart.setOption(option, true); +} + + +// 到馆人次/借阅册次分析 日 +var dom22 = document.getElementById("echarts_22"); +var myChart = echarts.init(dom22); +var app = {}; +option = null; +option = { + title: { + text: '' + }, + + tooltip: { + trigger: 'axis', + axisPointer: { + type: 'cross', + label: { + backgroundColor: '#6a7985', + Color: '#fff' + } + } + }, + legend: { + textStyle: { + fontSize: 13, + color: '#a7cdff' + }, + bottom: 0, + data: ['新增馆藏', '新增读者'] + }, + + grid: { + top: '3%', + left: '5%', + right: '5%', + bottom: '15%', + containLabel: true + }, + xAxis: [{ + type: 'category', + // boundaryGap: false, + //刻度线 + axisTick: { + show: false + }, + data: ['01', '02', '03', '04', '05', '06', '07'], + axisLine: { + lineStyle: { + color: '#a7cdff', + width: 0, //这里是为了突出显示加上的 + } + }, + }, + ], + yAxis: [{ + type: 'value', + boundaryGap: [0.2, 0.2], + //刻度线 + axisTick: { //y轴刻度线 + show: false + }, + //字体颜色 + axisLine: { + lineStyle: { + color: '#a7cdff', + width: 0, //这里是为了突出显示加上的 + } + }, + //网格线 + splitLine: { + show: true, + lineStyle: { + color: ['#23569b'], + width: 1, + type: 'dashed' + } + } + } + ], + color: ['#00c5d1', '#007dec'], + series: [{ + name: '新增馆藏', + type: 'bar', + barWidth: '15', + barGap: 0, + data: [1500, 2000, 1000, 1200, 800, 2200, 3000], + itemStyle: { + normal: { + barBorderRadius: [40, 40, 0, 0], + color: new echarts.graphic.LinearGradient( + 1, 0, 1, 1, + [{ + offset: 0, + color: '#00c7d2' + }, { + offset: 0.5, + color: '#0389b2' + }, + { + offset: 1, + color: '#045595' + } + ] + ) + }, + } + }, + { + name: '新增读者', + type: 'bar', + barWidth: '15', + barGap: 0, + itemStyle: { + normal: { + barBorderRadius: [40, 40, 0, 0], + color: new echarts.graphic.LinearGradient( + 1, 0, 1, 1, + [{ + offset: 0, + color: '#0083f5' + }, { + offset: 0.5, + color: '#0964c1' + }, + { + offset: 1, + color: '#04479b' + } + ] + ) + }, + }, + data: [500, 1500, 900, 500, 1800, 2800, 2000] + } + ], + + +}; +if (option && typeof option === "object") { + myChart.setOption(option, true); +} + + + +// 7小时内读者滞馆情况 +var dom3 = document.getElementById("echarts_3"); +var myChart = echarts.init(dom3); +var app = {}; +option = null; +option = { + title: { + text: '' + }, + tooltip: { + trigger: 'axis', + axisPointer: { + type: 'cross', + label: { + backgroundColor: '#6a7985', + Color: '#fff' + } + } + }, + legend: { + textStyle: { + fontSize: 14, + color: '#a7cdff' + }, + bottom: 0, + data: ['总数据'] + }, + grid: { + top: '3%', + left: '5%', + right: '5%', + bottom: '12%', + containLabel: true + }, + xAxis: [{ + type: 'category', + //刻度线 + axisTick: { + show: false + }, + // boundaryGap: false, + data: ['10:00', '11:00', '12:00', '13:00', '14:00', '15:00', '16:00'], + axisLine: { + lineStyle: { + color: '#a7cdff', + width: 0, //这里是为了突出显示加上的 + } + }, + }, ], + yAxis: [{ + type: 'value', + boundaryGap: [0.2, 0.2], + //刻度线 + axisTick: { //y轴刻度线 + show: false + }, + //字体颜色 + axisLine: { + lineStyle: { + color: '#a7cdff', + width: 0, //这里是为了突出显示加上的 + } + }, + //网格线 + splitLine: { + show: true, + lineStyle: { + color: ['#23569b'], + width: 1, + type: 'dashed' + } + } + }], + color: ['#6dc1ff', '#f9b008'], + series: [{ + name: '总数据', + type: 'line', + smooth: true, + areaStyle: { + normal: { + //颜色渐变函数 前四个参数分别表示四个位置依次为左、下、右、上 + color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{ + + offset: 0, + color: 'rgba(100,182,245,0.6)' + }, { + offset: .8, + color: 'rgba(100,182,245,0.3)' + }, { + offset: 1, + color: 'rgba(100,182,245,0.0)' + }]) + + } + }, + data: [35, 56, 41, 35, 49, 60, 70] + }], + +}; +if (option && typeof option === "object") { + myChart.setOption(option, true); +} + + + + + +// 男女比例 + +var dom4 = document.getElementById("echarts_4"); +var myChart = echarts.init(dom4); +var app = {}; +var option; +option = { + // title: { + // text: '男女比例' + // }, + tooltip: { + trigger: 'item', + formatter: '{a}
{b}: {c} ({d}%)' + }, + + legend: { + type: 'scroll', + // orient: 'vertical', + // right: 20, + // top: 0, + bottom: 20, + textStyle: { + color: "#fff", // 文字的颜色。 + }, + data: ['女', '男', ] + }, + color: ['#fc8cc6', '#1c9fff'], + + series: [ + + { + name: '男女比例', + type: 'pie', + radius: ['30%', '55%'], + + labelLine: { + length: -10 + }, + label: { + formatter: ' {b}{d}% ', + }, + data: [{ + value: 550, + name: '女' + }, + { + value: 450, + name: '男' + }, + ] + } + ] +}; + + +if (option && typeof option === 'object') { + myChart.setOption(option); +} + + +// 年龄段比例 + +var dom5 = document.getElementById("echarts_5"); +var myChart = echarts.init(dom5); +var app = {}; +var option; +option = { + tooltip: { + trigger: 'item', + formatter: '{a}
{b} {c} ' + }, + // title: { + // text: '年龄段比例' + // }, + + textStyle: { + color: "#fff", // 文字的颜色。 + }, + legend: { + type: 'scroll', + orient: 'vertical', + // right: 20, + // top: 0, + bottom: 20, + textStyle: { + color: "#fff", // 文字的颜色。 + }, + data: ['年龄段比例'] + }, + color: ['#2df3f2'], + radar: { + radius: 80, //大小 + textStyle: { + color: "#fff", // 文字的颜色。 + + }, + //雷达图背景的颜色,在这儿随便设置了一个颜色,完全不透明度为0,就实现了透明背景 + splitArea : { + show : false, + areaStyle : { + color: 'rgba(255,0,0,0)', // 图表背景的颜色 + }, + }, + splitLine : { + show : true, + lineStyle : { + width : 1, + color : 'rgba(255,255,255,.7)', // 设置网格的颜色 + }, + }, + // 设置雷达图中间射线的颜色 + axisLine: { + lineStyle: { + color: 'rgba(131,141,158,.0)', + }, + }, + + // center:[150,130],//雷达图位置:中心(圆心)坐标,数组的第一项是横坐标,第二项是纵坐标。 + // shape: 'circle', + + indicator: [{ + name: '0-6岁\n儿童', + max: 100 + }, + { + name: '7-17岁\n少年 ', + max: 100 + }, + { + name: '18-40岁\n青年 ', + max: 100 + }, + { + name: '41-65岁\n 中年', + max: 100 + }, + { + name: '65以上\n 老年', + max: 100 + } + ] + }, + series: [{ + + name: '年龄段比例', + type: 'radar', + symbolRotate: 0, + symbolSize: 0, + + data: [{ + areaStyle: { + color: 'rgba(45, 243, 242, 0.5)' + }, + value: [80, 98, 45, 78, 55], + + }] + }] +}; +if (option && typeof option === 'object') { + myChart.setOption(option); +} diff --git "a/web/117 \344\270\212\346\265\267\345\270\202\345\233\276\344\271\246\351\246\206\345\244\247\345\261\217\347\234\213\346\235\277/static/common2_v20160923084755.js" "b/web/117 \344\270\212\346\265\267\345\270\202\345\233\276\344\271\246\351\246\206\345\244\247\345\261\217\347\234\213\346\235\277/static/common2_v20160923084755.js" new file mode 100644 index 00000000..8aa1e24b --- /dev/null +++ "b/web/117 \344\270\212\346\265\267\345\270\202\345\233\276\344\271\246\351\246\206\345\244\247\345\261\217\347\234\213\346\235\277/static/common2_v20160923084755.js" @@ -0,0 +1,1842 @@ +var pluginColors = ["#ff8080", "#ffff80", "#80ff80", "#00ff80", "#80ffff", "#0080ff", "#ff80c0", "#ff80ff", "#ff0000", "#ffff00", "#80ff00", "#00ff40", "#00ffff", "#0080c0", "#8080c0", "#ff00ff", "#804040", "#ff8040", "#00ff00", "#008080", "#004080", "#8080ff", "#800040", "#ff0080", "#800000", "#ff8000", "#008000", "#008040", "#0000ff", "#0000a0", "#800080", "#8000ff", "#400000", "#804000", "#004000", "#004040", "#000080", "#000040", "#400040", "#400080", "#000000", "#808000", "#808040", "#808080", "#408080", "#c0c0c0", "#400040", "#ffffff"]; +var currentSelectProvinceName = ""; +var d = new Date(); +var hour = d.getHours(); +var ua = navigator.userAgent.toLowerCase(); +var theProvs = []; +theProvs[10] = "A 安徽"; +theProvs[11] = "A 澳门"; +theProvs[12] = "B 北京"; +theProvs[43] = "C 重庆"; +theProvs[13] = "F 福建"; +theProvs[14] = "G 甘肃"; +theProvs[15] = "G 广东"; +theProvs[16] = "G 广西"; +theProvs[17] = "G 贵州"; +theProvs[18] = "H 海南"; +theProvs[19] = "H 河北"; +theProvs[20] = "H 河南"; +theProvs[21] = "H 黑龙江"; +theProvs[22] = "H 湖北"; +theProvs[23] = "H 湖南"; +theProvs[24] = "J 吉林"; +theProvs[25] = "J 江苏"; +theProvs[26] = "J 江西"; +theProvs[27] = "L 辽宁"; +theProvs[28] = "N 内蒙古"; +theProvs[29] = "N 宁夏"; +theProvs[30] = "Q 青海"; +theProvs[31] = "S 山东"; +theProvs[32] = "S 山西"; +theProvs[33] = "S 陕西"; +theProvs[34] = "S 上海"; +theProvs[35] = "S 四川"; +theProvs[37] = "T 天津"; +theProvs[36] = "T 台湾"; +theProvs[38] = "X 西藏"; +theProvs[39] = "X 香港"; +theProvs[40] = "X 新疆"; +theProvs[41] = "Y 云南"; +theProvs[42] = "Z 浙江"; +var theInters = []; +theInters["africa"] = "非洲"; +theInters["america"] = "美洲"; +theInters["asia"] = "亚洲"; +theInters["europe"] = "欧洲"; +theInters["oceania"] = "大洋洲"; +var timeout = ""; +var submitByEnterBtn = false; +var searchInputTxt = "中文、拼音、电话区号 搜索城市/景点"; +function initSearchInput() { + if (typeof (pageType) != "undefined") { + if (pageType == "i18n") { + searchInputTxt = "中文、英文 搜索国际城市" + } else { + if (pageType == "timezone") { + searchInputTxt = "中文、英文 搜索世界时间" + } + } + } + if (typeof (domain) != "undefined" && domain == "7255.com") { + searchInputTxt = "中文、拼音、电话区号 搜索城市" + } + $("#searchForm").submit(function(a) { + if ($("#searchResult a.ui-state-error").length == 0 && $("#searchResult a.ui-state-selected").length > 0 && $("#inputSearchCity").val() != searchInputTxt) { + window.location.href = $("#searchResult a.ui-state-selected").attr("href"); + return false + } + submitByEnterBtn = true; + startSearch(); + a.preventDefault(); + return false + }); + $("#inputSearchCity").keydown(function(b) { + clearTimeout(timeout); + keycode = b.which; + if (keycode != 40 && keycode != 38) { + submitByEnterBtn = false; + timeout = setTimeout(startSearch, 250) + } + }).click(function(c) { + if ($(".ui-state-selected").length > 0) { + $(".ui-state-selected").removeClass("ui-state-selected") + } + var e = $("#inputSearchCity").val(); + if (e != searchInputTxt && e != "") { + $("#searchForm").submit(); + return false + } + if (typeof (pageType) !== "undefined" && pageType == "timezone") { + return false + } + isCurrentShowing = false; + mytoggleLayer(isCurrentShowing, $("#citySelect"), $("#citySelect")); + cancelEvent(c); + return false + }).focus(function() { + if ($(this).val() == searchInputTxt) { + $(this).val("").css("color", "#333") + } + }).blur(function() { + if ($(this).val().replace(/^\s*$/, "") == "") { + $(this).val(searchInputTxt).css("color", "#999") + } + }).val(searchInputTxt); + startAutocomplete() +} +function startSearch() { + if ($("#inputSearchCity").val().replace(/\?/, "") == "") { + $("#inputSearchCity").trigger("click"); + return + } + if (submitByEnterBtn && !$("#inputSearchCity").autocomplete("widget").is(":visible")) { + $("#inputSearchCity").autocomplete("search", $("#inputSearchCity").val()); + $("#searchResult").addClass("suggest-list-open"); + $("#searchResult ul").show(); + return false + } +} +function startAutocomplete() { + $("#inputSearchCity").autocomplete({ + source: function(b, a) { + $.ajax({ + url: "/t/searchCity.php", + data: { + q: $("#inputSearchCity").val(), + pType: pageType + }, + dataType: "json", + success: function(f) { + if (typeof (pageType) != "undefined" && pageType == "timezone") { + var e = "对不起,未找到您查询的世界时间。" + } else { + var e = "对不起,未找到您查询的地点天气。" + } + if (f.res.length > 0) { + a($.map(f.res, function(g) { + return { + href: g.href, + text: g.text + } + })) + } else { + var c = [{ + error: true, + text: e + }]; + a(c) + } + } + }) + }, + appendTo: "#searchResult", + position: { + my: "left-1 top", + at: "left bottom" + }, + delay: 300, + autoFocus: true, + select: function(a, b) { + if (b.item != undefined && !b.item.error) { + window.location.href = b.item.href + } else { + return false + } + }, + create: function(a, b) { + $(".ui-helper-hidden-accessible").remove() + }, + focus: function(a, b) { + if ($(".ui-state-focus").length > 0) { + $(".ui-state-focus").addClass("ui-state-selected"); + $(".ui-state-focus").parent().siblings().children(".ui-state-selected").removeClass("ui-state-selected") + } + }, + open: function(a, b) { + $("#searchResult").addClass("suggest-list-open"); + $("#citySelect").hide() + } + }); + $("#inputSearchCity").data("autocomplete")._renderItem = function(c, e) { + var a = $("#inputSearchCity").val(); + e.label = a; + e.value = a; + if (e.error) { + return $("
  • ").append($("").attr("class", "ui-state-error").html(e.text)).appendTo(c) + } else { + if (/[a-zA-Z]+/.test(a) && /span/.test(e.text)) { + var f = e.text.split(""); + if (f.length == 2) { + e.text = f[0].replace(a, "" + a + "") + "" + f[1] + } + } else { + e.text = e.text.replace(a, "" + a + "") + } + return $("
  • ").append($("").attr("href", e.href).html(e.text)).appendTo(c) + } + } + ; + $("#inputSearchCity").data("autocomplete")._renderMenu = function(b, a) { + var c = this; + $.each(a, function(e, f) { + c._renderItemData(b, f) + }); + if (a.length < 10) { + $(b).css("height", 26 * a.length) + } else { + $(b).css("height", 260) + } + } +} +function genColorPanel() { + var b = ['
      ']; + for (i in pluginColors) { + var a = pluginColors[i]; + b.push("
    • ") + } + b.push("
    "); + return b.join("") +} +function fillCitySearchForm() { + var e = [12, 34, 37, 43, 10, 13, 14, 15, 16, 17, 18, 21, 19, 20, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 35, 38, 40, 41, 42, 39, 11, 36]; + var b = []; + for (i in e) { + if (typeof (e[i]) == "function") { + continue + } + var a = e[i]; + matches = theProvs[a].match(/\s(.*)/); + var c = matches[1]; + if (i == 3) { + b.push('
  • ' + c + ""); + b.push('
  • ') + } else { + b.push('
  • ' + c + "") + } + } + $("#searchProvinceList").html(b.join("")) +} +function loadTopBanner() { + try { + window.external.RCCoralGetItemCacheType(); + var a = 1 + } catch (b) { + var a = 0 + } + $.get("/public/banner.php", { + ifCleverExplorer: a + }, function(c) { + $("#mainContainer").prepend(c) + }) +} +function aqiGuide(a) { + aqiGuides = { + "1": "多参加户外活动,呼吸清新空气啦。", + "2": "出去走走放松心情,感受下美好大自然吧。", + "3": "敏感体质的朋友要减少外出哦!", + "4": "敏感体质的朋友尽量不要出门啦!", + "5": "为了健康着想,各位朋友尽量减少外出吧!", + "6": "请尽量避免外出,外面红绿灯都看不见呢!", + "7": "请尽量避免外出,外面红绿灯都看不见呢!" + }; + if (typeof (aqiGuides[a]) != "undefined") { + return aqiGuides[a] + } else { + return "暂无" + } +} +function aqiPercent(a) { + if (a <= 200) { + aqiPercent = a / 4 + } else { + if (a <= 300) { + aqiPercent = 50 + (a - 200) / 4.78 + } else { + if (a <= 500) { + aqiPercent = 70.915 + (a - 300) / 6.876 + } else { + if (a <= 550) { + aqiPercent = 103 + } else { + aqiPercent = 104 + } + } + } + } + return aqiPercent +} +function reflow() { + var a = document.body; + a.style.zoom = a.style.zoom == "1" ? "100%" : "1" +} +function redirectIfMobile(b) { + if (/vmod=pc/.test(window.location)) { + document.cookie = "vmod=pc;path=/" + } + if (!/vmod=pc/.test(document.cookie)) { + var a = navigator.userAgent.toLowerCase(); + if (/(iphone|ipod|android|nokia|sony|ericsson|mot|htc|samsung|sgh|lg|philips|lenovo|ucweb|opera mobi|windows mobile|blackberry)/i.test(a) || a == "") { + location.href = b + } + if (/ipad/.test(a)) { + allCount("ipad_waptianqi"); + location.href = b + } + } +} +function hidePoplayer() { + $(".pop-layer").hide(); + $(".arrow").removeClass("uarr"); + $(".pm-info").removeClass("cur"); + $(".suggest-list").removeClass("suggest-list-open"); + $(".select-city").removeClass("select-city-hover") +} +function gotoMyHref(a) { + window.location.href = a.attr("href") +} +function blanktoHref(a) { + window.open(a.attr("href")) +} +function mytoggleLayer(a, c, b) { + hidePoplayer(); + if (a) { + c.hide(); + b.removeClass("uarr").removeClass("select-city-hover") + } else { + c.show(); + b.addClass("uarr").addClass("select-city-hover") + } +} +function indexPageWeaCallback(f) { + var a = nightTxt1 = f.day1.weather; + $("#dayIcon").addClass("w" + f.day1.img + "_l"); + $("#nightIcon").addClass("w" + f.day1.imgNight + "_l wnt"); + if (f.day1.weather.indexOf("转") > -1) { + var e = f.day1.weather.split("转"); + a = e[0]; + nightTxt1 = e[1] + } + $("#dayTxt").html(a); + $("#nightTxt").html(nightTxt1); + $("#lowT").html(f.day1.tempLow + "℃"); + $("#highT").html(f.day1.tempHigh + "℃"); + $("#wind").html(f.day1.wind); + $("#tomorrowLowT").html(f.day2.tempLow + "℃"); + $("#tomorrowIcon").addClass("w" + f.day2.img); + $("#tomorrowTxt").html(f.day2.weather); + $("#tomorrowHighT").html(f.day2.tempHigh + "℃"); + if (f.showDetail == "yes") { + $("#todayHref").attr("href", "/today-" + f.id + ".htm"); + $("#tomorrowHref").attr("href", "/tomorrow-" + f.id + ".htm") + } else { + $("#todayHref").attr("href", "/" + f.pinyin + "/" + f.id + ".htm"); + $("#tomorrowHref").attr("href", "/" + f.pinyin + "/" + f.id + ".htm") + } + if (f.dayType == 15) { + var b = "15" + } else { + var b = "7" + } + $("#localHref").attr("href", "/" + f.pinyin + "/" + f.id + ".htm").html("查看" + b + "日天气预报»"); + if ($("html").hasClass("ie6")) { + $(".days2 .today").hoverfix(); + $(".days2 .tomorrow").hoverfix() + } + $("#weaInfoAqi").attr("href", "/air-" + f.id + ".htm"); + $("#weaHistory").attr("href", "/wea_history/" + f.id + ".htm"); + $("#placeHolder").hide(); + var c = typeof (f.cityNameWithSuffix) == "undefined" ? f.city : f.cityNameWithSuffix; + $("#weatherInfo").show().find("h2").html(c + "天气预报") +} +function countDays() { + var m = ["一", "二", "三", "四", "五", "六", "七", "八", "九"]; + var q = new Date(); + var k = q.getMonth(); + if (k < 4) { + var l = q.getFullYear(); + var f = l.toString(); + var j = f.substr(2, 2) - 1; + var o = parseInt((j * 0.2422 + 21.94) - parseInt(j / 4)); + var c = new Date(l,0,1,0,0,0); + var p = parseInt((q.getTime() - c.getTime()) / 86400000); + var b = 31 - o; + var e = b + p + 1; + var a = parseInt(e / 9); + var h = e % 9; + if (a > 9) { + return "" + } else { + return "(" + m[a] + "九第" + m[h] + "天)" + } + } else { + if (k >= 12) { + var l = q.getFullYear(); + var f = l.toString(); + var j = f.substr(2, 2); + var o = parseInt((j * 0.2422 + 21.94) - parseInt(j / 4)); + var n = q.getDate(); + if (n > o) { + var g = n - o + 1; + var a = parseInt(g / 9) + 1; + var h = g % 9; + return "(" + m[a] + "九第" + m[h] + "天)" + } + return "" + } + } +} +function bindInitEvent() { + $(document).click(function(a) { + hidePoplayer() + }); + $(".pop-layer").click(function(a) { + cancelEvent(a); + return false + }); + $("#province a").click(function() { + if (match = $(this).attr("href").match(/#(\d+)/)) { + provId = match[1]; + cities = getCitiesByProvId(provId); + displaySearchDiv(cities, "city", provId, $(this).html()); + currentSelectProvinceName = $(this).html(); + bindCitySelect(); + bindCountySelect() + } + }); + ipJudgeError() +} +function bindCountySelect() { + $("#county").find("a").unbind().click(function() { + if (/返回全国/.test($(this).html())) { + $("#province").show(); + $("#city").hide(); + $("#county").hide() + } else { + if (/返回/.test($(this).html())) { + $("#province").hide(); + $("#city").show(); + $("#county").hide() + } else { + gotoMyHref($(this)) + } + } + }) +} +function bindCitySelect() { + $("#city").find("a").unbind().click(function() { + if (match = $(this).attr("href").match(/#(\d+),(\d+)/)) { + provId = match[1]; + cityIndex = match[2]; + counties = getCountiesByProvCity(provId, cityIndex); + displaySearchDiv(counties, "county", provId, $(this).html()); + bindCountySelect() + } else { + if (/返回全国/.test($(this).html())) { + $("#province").show(); + $("#city").hide(); + $("#county").hide() + } + } + }) +} +function addFav(f) { + if (!f) { + var f = "2345天气预报" + } else { + f = f + "--2345天气预报" + } + var a = location.href + "?shoucang"; + var b = navigator.userAgent.toLowerCase(); + var g = "您可以尝试通过快捷键 Ctrl+D 加入到收藏夹"; + if (b.indexOf("360se") > -1 || b.indexOf("lbbrowser") > -1 || b.indexOf("firefox") > -1 || b.indexOf("chrome") > -1) { + alert(g) + } else { + if (b.indexOf("msie 8") > -1) { + window.external.AddToFavoritesBar(a, f) + } else { + if (document.all) { + try { + window.external.addFavorite(a, f) + } catch (c) { + alert(g) + } + } else { + if (window.sidebar) { + window.sidebar.addPanel(f, a, "") + } else { + alert(g) + } + } + } + } +} +function allCount(e) { + var c = arguments[1] ? arguments[1] : ""; + var b = "//web.50bangzh.com/web/ajax21?uId2=SPTNPQRLSX&r=" + encodeURIComponent(location.href) + "&fBL=" + screen.width + "*" + screen.height + "&lO=" + encodeURIComponent(e) + "?nytjsplit=" + encodeURIComponent(location.href) + c; + var a = document.createElement("script"); + a.setAttribute("type", "text/javascript"); + a.setAttribute("src", b); + document.getElementsByTagName("head")[0].appendChild(a); + return true +} +function deleteCookie(a) { + var c = new Date(); + c.setTime(c.getTime() - 1); + var b = 0; + document.cookie = a + "=" + b + "; path=/;expires=" + c.toGMTString() +} +function getCookie(c) { + var a; + var f = document.cookie; + var e = f.indexOf(c + "="); + if (e > -1) { + start = f.indexOf("=", e) + 1; + var b = f.indexOf(";", start); + if (b == -1) { + b = f.length + } + a = f.substring(start, b) + } + return a +} +function setCookie(c, f, b, g) { + var a = ""; + if (typeof (b) != "undefined") { + var e = new Date(); + e.setTime(e.getTime() + Number(b) * 3600 * 1000); + a = "expires = " + e.toGMTString() + } + if (typeof (g) != "undefined") { + domainVal = ";domain=" + g + } else { + domainVal = "" + } + document.cookie = c + "=" + f + "; path=/;" + a + domainVal +} +function cancelEvent(a) { + if (a && a.stopPropagation) { + a.stopPropagation() + } else { + window.event.cancelBubble = true + } +} +function displaySearchDiv(c, f, b, e) { + $("#province").hide(); + $("#city").hide(); + $("#county").hide(); + var a = []; + if (f == "city" && c.length == 1) { + currentSelectProvinceName = "全国"; + c = getCountiesByProvCity(b, 0); + displaySearchDiv(c, "county", b, e) + } else { + if (f == "city" && c.length > 1) { + a.push("

    " + e + "主要城市<< 返回全国

    "); + a.push("
    "); + for (i in c) { + if (typeof (c[i]) == "function") { + continue + } + match = c[i].match(/\s(.+?)-/); + a.push("
  • " + match[1] + "
  • ") + } + a.push(""); + $("#city").html(a.join("")); + $("#city").show() + } else { + if (f == "county") { + a.push("

    " + e + "地区<< 返回" + currentSelectProvinceName + "

    "); + a.push("
    "); + for (i in c) { + if (typeof (c[i]) == "function") { + continue + } + match = c[i].match(/^(a?\d+)-.\s(.+?)-/); + a.push("
  • " + match[2] + "
  • ") + } + a.push("
    "); + $("#county").html(a.join("")); + $("#county").show() + } + } + } +} +function getCitiesByProvId(a) { + citiesStr = prov[a]; + if (citiesStr.indexOf("|") < 0) { + var b = [citiesStr] + } else { + var b = citiesStr.split("|") + } + return b +} +function getCountryByEg(a) { + citiesStr = country[a]; + if (citiesStr.indexOf("|") < 0) { + var b = [citiesStr] + } else { + var b = citiesStr.split("|") + } + return b +} +function getCountiesByProvCity(b, a) { + var c = provqx[b][a]; + return c.split("|") +} +function getCityByCountry(b, a) { + var c = city[b][a]; + return c.split("|") +} +function seedProvCityCountySelect(e, b, a) { + var c = []; + for (i in theProvs) { + if (theProvs.hasOwnProperty(i)) { + c.push("") + } + } + $("#" + e).html(c.join("")); + if ($("#" + e + " option:eq(33)").text().indexOf("重庆") > -1) { + $("#" + e + " option:eq(33)").insertBefore($("#" + e + " option:eq(3)")) + } + $("#" + e).change(function() { + var f = $(this).val(); + if (f == "") { + return + } + var h = getCitiesByProvId(f); + var g = []; + for (i in h) { + if (typeof (h[i]) == "function") { + continue + } + cityName = h[i].match(/\d+-([^-]+)/)[1]; + g.push("") + } + $("#" + b).html(g.join("")); + $("#" + b).trigger("change") + }); + $("#" + b).change(function() { + var h = $(this).val(); + if (h == "") { + return + } + var g = h.split(","); + var j = getCountiesByProvCity(g[0], g[1]); + var f = []; + for (i in j) { + if (typeof (j[i]) == "function") { + continue + } + countyInfo = j[i].match(/(a?\d+)-([^-]+)/); + countyId = countyInfo[1]; + countyName = countyInfo[2]; + f.push("") + } + $("#" + a).html(f.join("")).trigger("change") + }); + setTimeout(function() { + $("#" + e)[0].value = "12"; + $("#" + e).trigger("change") + }, 20) +} +function seedInterCityCountySelect(e, b, a) { + var c = []; + for (i in theInters) { + if (theInters.hasOwnProperty(i)) { + c.push("") + } + } + $("#" + e).html(c.join("")); + $("#" + e).change(function() { + var f = $(this).val(); + if (f == "" || f == null) { + return + } + var h = getCountryByEg(f); + var g = []; + for (i in h) { + if (typeof (h[i]) == "function") { + continue + } + countryName = h[i].match(/\S+-([^-]+)/)[1]; + g.push("") + } + $("#" + b).html(g.join("")); + $("#" + b).trigger("change") + }); + $("#" + b).change(function() { + var h = $(this).val(); + if (h == "" || h == null) { + return + } + var g = h.split(","); + var j = getCityByCountry(g[0], g[1]); + var f = []; + for (i in j) { + if (typeof (j[i]) == "function") { + continue + } + countyInfo = j[i].match(/(\S+)-([^-]+)/); + countyId = countyInfo[1]; + countyName = countyInfo[2]; + f.push("") + } + $("#" + a).html(f.join("")).trigger("change") + }); + setTimeout(function() { + $("#" + e)[0].value = "asia"; + $("#" + e).trigger("change") + }, 20) +} +function onSetCityByOwn(e, h, g) { + var b = $("#" + e).val(); + var a = $("#" + h).val().split(",")[1]; + var j = getCitiesByProvId(b)[a]; + var f = ""; + var c = j.match(/(\d*?)-/); + if (c.length > 1) { + f = c[1]; + if (f < 100) { + j = getCountiesByProvCity(b, 0)[0]; + c = j.match(/(\d*?)-/); + f = c[1] + } + } + $("#" + g).val(f) +} +function ipJudgeError() { + if (getCookie("defaultCityID") == "" || getCookie("defaultCityID") == "undefined" || getCookie("defaultCityID") == null) { + $("#defaultCity").attr("src", "/t/detect2009v2_defaultCiyt.php") + } else { + var a = getCookie("defaultCityName"); + $("#ipCheckError").html("更正您的地理位置"); + $("#ipCheckError").attr("href", "/tianqifk/index.htm") + } +} +function defaultCityCallBack(b, a) { + setCookie("defaultCityID", b, 24 * 365); + setCookie("defaultCityName", escape(a), 24 * 365); + $("#ipCheckError").html("IP判断错误反馈:我不在" + a); + $("#ipCheckError").attr("href", "/tianqifk/index.htm") +} +function parseQueryStrToJson(e) { + var c = e.replace(/\?/, "").split("&"); + var a = {}; + for (i in c) { + if (typeof (c[i]) != "string") { + continue + } + var b = c[i].split("="); + a[b[0]] = b[1] + } + return a +} +function judgeDayNightStr(b, a) { + if (hour >= 18) { + document.write(a) + } else { + document.write(b) + } +} +function todayFutureTempWidget() { + var a = new dhtmlXChart({ + view: "line", + container: "todayFutureTemp", + value: "#wenduB#", + label: "#curB##wenduB#", + tooltip: { + template: "#curB##wenduB#" + }, + item: { + borderColor: "#ff8f21", + color: "#ff8f21" + }, + line: { + color: "#ff8f21", + width: 3 + }, + padding: { + left: 0, + bottom: 20, + right: 0 + } + }); + a.addSeries({ + value: "#wenduH#", + label: "#curH##wenduH#", + tooltip: { + template: "#curH##wenduH#" + }, + item: { + borderColor: "#66d53f", + color: "#66d53f" + }, + line: { + color: "#66d53f", + width: 3 + } + }); + a.parse(data, "json") +} +function todayInterFuture() { + var a = new dhtmlXChart({ + view: "line", + container: "todayFutureTemp2", + value: "#wenduB#", + label: "
    #curB##wenduB#℃
    ", + tooltip: { + template: "#curB##wenduB#" + }, + item: { + borderColor: "#ff8f21", + color: "#ff8f21" + }, + line: { + color: "#ff8f21", + width: 2 + }, + padding: { + left: 0, + bottom: 20, + right: 0 + } + }); + a.addSeries({ + value: "#wenduH#", + label: "
    #curH##wenduH#℃
    ", + tooltip: { + template: "#curH##wenduH#" + }, + item: { + borderColor: "#268dea", + color: "#268dea" + }, + line: { + color: "#268dea", + width: 2 + } + }); + a.parse(data, "json") +} +function chartHisTempData() { + var a = new dhtmlXChart({ + view: "line", + container: "hisTemp", + value: "#wenduB#", + label: function(b) { + if (b.curB != "") { + return "
    " + b.curB + b.wenduB + "℃
    " + } else { + return "
    " + b.curB + b.wenduB + "℃
    " + } + }, + item: { + borderColor: "#ff8f21", + color: "#ff8f21" + }, + line: { + color: "#ff8f21", + width: 2 + }, + origin: "auto", + padding: { + top: 15, + left: 35 + }, + xAxis: { + template: function(b) { + if (b.curB != "") { + return "" + b.month + "" + } else { + return b.month + } + }, + color: "#f7f7f7", + lineColor: "#f7f7f7" + }, + yAxis: { + start: dataHisSection[1], + step: dataHisSection[2], + end: dataHisSection[0], + template: function(b) { + return b + "℃" + }, + color: "#f7f7f7", + lineColor: "#f7f7f7" + } + }); + a.addSeries({ + value: "#wenduH#", + label: function(b) { + if (b.curB != "") { + return "
    " + b.curH + b.wenduH + "℃
    " + } else { + return "
    " + b.curH + b.wenduH + "℃
    " + } + }, + item: { + borderColor: "#268dea", + color: "#268dea" + }, + line: { + color: "#268dea", + width: 2 + } + }); + $("#hisTemp").css({ + width: "980px", + height: "218px" + }); + a.parse(dataHisTemp, "json") +} +function todayHourWidget() { + var c = new Date(); + var a = c.getHours(); + html = ""; + for (i = 0; i < wea_h_hour.length; i++) { + var b = ""; + if (i <= 5 || i >= 19) { + b = "wnt_l" + } + html += "
    ' + wea_h_hour[i]["hour"] + '点

    ' + wea_h_hour[i]["tq"] + '

    ' + wea_h_hour[i]["temp"] + "℃
    " + } + $("#wea_hour ul").html(html); + hour24Slide() +} +function todayHourWidgetNew() { + var c = new Date(); + var a = c.getHours(); + html = ""; + for (i = 0; i < wea_h_hour.length; i++) { + var b = ""; + if (i <= 5 || i >= 19) { + b = "wnt" + } + html += "
    ' + wea_h_hour[i]["hour"] + '点

    ' + wea_h_hour[i]["tq"] + '

    ' + wea_h_hour[i]["temp"] + "℃
    " + } + $("#wea_hour ul").html(html); + hourNewSlide() +} +function todayHourWidgetInter(e) { + var c = new Date(); + var a = c.getHours() + e - 8; + html = ""; + for (i = 0; i < wea_h_hour.length; i++) { + var b = ""; + if (wea_h_hour[i]["hour"] <= 5 || wea_h_hour[i]["hour"] >= 19) { + b = "wnt_l" + } + html += "
    ' + wea_h_hour[i]["hour"] + '点

    ' + wea_h_hour[i]["tq"] + '

    ' + wea_h_hour[i]["temp"] + "℃
    " + } + $("#wea_hour ul").html(html); + hour24SlideInter() +} +function todayHourWidgetDistrict() { + if (typeof (wea_h_hour) == "undefined") { + return + } + var e = new Date(); + var a = wea_h_hour[0]["hour"] > e.getHours() ? wea_h_hour[0]["hour"] : e.getHours(); + html = ""; + for (i = 0; i < wea_h_hour.length; i++) { + var c = ""; + var b = wea_h_hour[i]["hour"]; + if (b <= 5 || b >= 19) { + c = "wnt_l" + } + html += "
    ' + wea_h_hour[i]["hour"] + '点

    ' + wea_h_hour[i]["tq"] + '

    ' + wea_h_hour[i]["temp"] + "℃
    " + } + $("#wea_hour ul").html(html); + hour24Slide() +} +function todayHourWidgetDistrictNew() { + if (typeof (wea_h_hour) == "undefined") { + return + } + var e = new Date(); + var a = wea_h_hour[0]["hour"] > e.getHours() ? wea_h_hour[0]["hour"] : e.getHours(); + html = ""; + for (i = 0; i < wea_h_hour.length; i++) { + var c = ""; + var b = wea_h_hour[i]["hour"]; + if (b <= 5 || b >= 19) { + c = "wnt" + } + html += "
    ' + wea_h_hour[i]["hour"] + '点

    ' + wea_h_hour[i]["tq"] + '

    ' + wea_h_hour[i]["temp"] + "℃
    " + } + $("#wea_hour ul").html(html); + hourNewSlide() +} +function airTrend(b) { + $("#chartFutureHour").hide(); + $("#chartHour").hide(); + $("#chartDay").hide(); + if (b == "futurehour") { + $("#futurehour").addClass("mt_curr"); + $("#hour").removeClass("mt_curr"); + $("#day").removeClass("mt_curr"); + $("#chartFutureHour").show(); + $(".module-qushitu .btitle h2").html("未来" + cityZhName + "空气质量指数24小时整点预报"); + var a = "chartFutureHour" + } else { + if (b == "hour") { + $("#futurehour").removeClass("mt_curr"); + $("#hour").addClass("mt_curr"); + $("#day").removeClass("mt_curr"); + $("#chartHour").show(); + $(".module-qushitu .btitle h2").html(cityZhName + "空气质量历史趋势图"); + var a = "chartHour" + } else { + if (b == "day") { + $("#futurehour").removeClass("mt_curr"); + $("#hour").removeClass("mt_curr"); + $("#day").addClass("mt_curr"); + $("#chartDay").show(); + $(".module-qushitu .btitle h2").html(cityZhName + "空气质量历史趋势图"); + var a = "chartDay" + } else { + if (b == "tomorrowhour") { + var a = "chartTomorrowHour" + } + } + } + } + if (b == "futurehour" && $("#chartFutureHour").html() != "") { + return + } + if (b == "hour" && $("#chartHour").html() != "") { + return + } + if (b == "day" && $("#chartDay").html() != "") { + return + } + if (b == "tomorrowhour" && $("#chartTomorrowHour").html() != "") { + return + } + var c = new dhtmlXChart({ + view: "bar", + container: a, + value: "#point#", + label: "#aqi#", + width: 15, + radius: 0, + border: false, + item: { + borderColor: "#268dea", + color: "#ffffff", + radius: 3 + }, + color: function(e) { + if (e.aqi <= 50) { + return "#a9d86b" + } else { + if (e.aqi <= 100) { + return "#fde37f" + } else { + if (e.aqi <= 150) { + return "#ffba6c" + } else { + if (e.aqi <= 200) { + return "#fa874d" + } else { + if (e.aqi <= 300) { + return "#ba6593" + } else { + return "#855666" + } + } + } + } + } + }, + xAxis: { + template: "#label#", + color: "#f7f7f7", + lineColor: "#f7f7f7" + }, + yAxis: { + color: "#f7f7f7", + lineColor: "#f7f7f7", + start: 0, + step: 1666, + end: 9996, + template: function(f) { + var e = [0, 50, 100, 150, 200, 300, 500]; + return e[f / 1666] + } + }, + padding: { + left: 35, + bottom: 75 + }, + origin: 0, + preset: "simple" + }); + if (b == "futurehour") { + $("#chartFutureHour").css("height", "300px").show(); + c.parse(future_hours24, "json") + } else { + if (b == "hour") { + $("#chartHour").css("height", "300px").show(); + c.parse(hours24, "json") + } else { + if (b == "day") { + $("#chartDay").css("height", "300px").show(); + c.parse(days30, "json") + } else { + if (b == "tomorrowhour") { + $("#chartTomorrowHour").css("height", "300px").show(); + c.parse(tomorrow_hours24, "json") + } + } + } + } +} +function publishTime() { + var c = new Date(); + var a = c.getHours(); + var b = c.getFullYear() + "-" + (c.getMonth() - 1 + 2) + "-" + c.getDate(); + if (a >= 0 && a < 8) { + c.setDate(c.getDate() - 1); + b = c.getFullYear() + "-" + (c.getMonth() - 1 + 2) + "-" + c.getDate() + " 18:00" + } else { + if (a >= 8 && a < 12) { + b += " 08:00" + } else { + if (a >= 12 && a < 18) { + b += " 12:00" + } else { + b += " 18:00" + } + } + } + document.write(b) +} +function checkSubmitSpam(c) { + var a = true; + var b = getCookie("lastSubmitTime"); + if (b != null && parseInt(((new Date()).valueOf() - b) / 1000) < 15) { + a = false + } + if (!a) { + alert("您提交的频率过快,请稍候再试"); + return false + } + $("#" + c + " input[type=text]").each(function(f, e) { + var g = $(e).val().length; + if (g < 5 || g > 50) { + a = false; + return + } + }); + if (!a) { + alert("各项长度须大于5个小于50个字符"); + return false + } + setCookie("lastSubmitTime", (new Date()).valueOf()); + return true +} +function loadJs(b) { + var e = arguments[1] || function() {} + ; + var c = arguments[2] || "gbk"; + var a = document.createElement("script"); + a.setAttribute("type", "text/javascript"); + a.setAttribute("charset", c); + a.setAttribute("defer", true); + a.setAttribute("src", b); + if (document.all) { + a.onreadystatechange = function() { + if (this.readyState == "loaded" || this.readyState == 4 || this.readyState == "complete") { + setTimeout(e, 10) + } + } + } else { + a.onload = function() { + e() + } + } + document.getElementsByTagName("head")[0].appendChild(a) +} +function loadJsInterhour(b) { + var f = arguments[1] || function() {} + ; + var e = "gbk"; + var c = arguments[2]; + var a = document.createElement("script"); + a.setAttribute("type", "text/javascript"); + a.setAttribute("charset", e); + a.setAttribute("defer", true); + a.setAttribute("src", b); + if (document.all) { + a.onreadystatechange = function() { + if (this.readyState == "loaded" || this.readyState == 4 || this.readyState == "complete") { + setTimeout(f, 10) + } + } + } else { + a.onload = function() { + f(c) + } + } + document.getElementsByTagName("head")[0].appendChild(a) +} +function seedMycities() { + mycitiesCookie = unescape(getCookie("qd_dz_ct")).replace("undefined", ""); + mycities = mycitiesCookie.split("|"); + if (mycities[0] == "") { + mycities = ["54511", "58362", "59287", "57494", "57516"] + } + if (mycities.length > 0) { + for (i in mycities) { + if (typeof (mycities[i]) != "string") { + continue + } + mycityId = mycities[i]; + if (mycityId != "" && mycityId.replace("/s*/", "") != "") { + loadJs("/t/his/" + mycityId + "his.js?" + (new Date()).valueOf()) + } + } + } +} +function removeMyCity(f) { + mycities = unescape(getCookie("qd_dz_ct")); + var c = "|" + f; + var b = f + "|"; + var a = f; + var e = mycities.replace(c, "").replace(b, "").replace(a, ""); + setCookie("qd_dz_ct", e, 24 * 300, ".2345.com"); + $("#" + f).remove(); + $("#mycityTr_" + f).remove(); + $("#deleteAdd").html("") +} +function addMyCity() { + var h = $("#selectCounty").val(); + var c = $("#selectCounty").find("option:selected").text().split(" ")[1]; + var g = unescape(getCookie("qd_dz_ct") || ""); + var f = g.split("|"); + var e = "|" + h; + var b = h + "|"; + var a = h; + $("#qd_ct").show(); + $("#btnConfirm").show(); + $("#deleteAdd").show(); + if (g.indexOf(e) < 0 && g.indexOf(b) < 0 && g.indexOf(a) < 0) { + if (g.split("|").length > 4) { + $("#deleteAdd").css("visibility", "visible"); + $("#deleteAdd").html("添加城市已达上限,请删除部分城市后再行添加"); + return false + } + if (f[0] == "") { + g += h; + $("#deleteAdd").html("您最多添加 5 个城市,还可添加 4 个") + } else { + g += "|" + h; + if (g.split("|").length > 4) { + $("#deleteAdd").html("添加城市已达上限") + } else { + $("#deleteAdd").html("您最多添加 5 个城市,还可添加 " + (5 - g.split("|").length) + " 个") + } + } + setCookie("qd_dz_ct", g, 24 * 300, ".2345.com"); + loadJs("/t/his/" + h + "his.js?" + (new Date()).valueOf()) + } else { + $("#deleteAdd").html("该城市已添加关注,请勿重复添加"); + if (g.split("|").length > 4) { + $("#deleteAdd").css("visibility", "visible"); + $("#deleteAdd").html("添加城市已达上限,请删除部分城市后再行添加") + } + } +} +function joinWeaStrHis(c, h, f, j, b, g, a) { + if (a == undefined) { + a = "暂无" + } + var e = '
    ' + c + '' + h + '' + f + '' + a + "
    "; + mycitiesCookie = unescape(getCookie("qd_dz_ct")).replace("undefined", ""); + mycities = mycitiesCookie.split("|"); + if (mycities != "") { + $("#myCitiesList")[0].innerHTML += e; + $("#qd_ct")[0].innerHTML += '' + } + if ($("#myMiddleCitiesList").length > 0) { + $("#myMiddleCitiesList")[0].innerHTML += e + } +} +function setLiveInfo() { + if (typeof (weatherinfovar) == "undefined") { + return + } + if ($("#liveInfoAqi").length == 0 && $("#liveInfoAqiNew").length == 0) { + return + } + var e = weatherinfovar.weatherinfo; + if (typeof (e.aqiLevel) != "undefined") { + var a = new Array(); + var c = aqiPercent(e.idx); + a[3] = "建议戴口罩"; + a[4] = "需要戴口罩"; + a[5] = "需要戴口罩"; + a[6] = "务必戴口罩"; + a[7] = "务必戴口罩"; + $("#liveInfoAqi").addClass("aqi-lv" + e.aqiLevel); + $("#liveInfoAqi h3 span").html(e.lv_hint); + $("#liveInfoAqi div.progess b").html(e.idx == null ? "暂无" : e.idx).css("left", c + "%"); + $("#liveInfoAqi p span").html(aqiGuide(e.aqiLevel)); + if (typeof a[e.aqiLevel] != "undefined") { + var b = '
    ' + a[e.aqiLevel] + "
    "; + $("#liveInfoAqi h3").after(b) + } + $("#aqi_container").html(e.lv_hint); + var z = aqiLevelIcon(e.idx); + $(".kqi-left").addClass("kqi-left" + z); + $(".kqi-num").addClass("kqi-num" + e.aqiLevel); + $(".kqi-num").html(e.idx); + $(".kqi-status b").addClass("kqi-level" + e.aqiLevel); + $(".kqi-status b").html(e.lv_hint); + if (typeof a[e.aqiLevel] != "undefined") { + $(".kqi-tips p").html(a[e.aqiLevel] + "," + aqiGuide(e.aqiLevel)) + } else { + $(".kqi-tips p").html(aqiGuide(e.aqiLevel)) + } + } +} +function aqiLevelIcon(a) { + var e; + if (a >= 0 && a <= 25) { + e = 1 + } else { + if (a >= 26 && a <= 50) { + e = 2 + } else { + if (a >= 51 && a <= 75) { + e = 3 + } else { + if (a >= 76 && a <= 100) { + e = 4 + } else { + if (a >= 101 && a <= 125) { + e = 5 + } else { + if (a >= 126 && a <= 150) { + e = 6 + } else { + if (a >= 151 && a <= 175) { + e = 7 + } else { + if (a >= 176 && a <= 200) { + e = 8 + } else { + if (a >= 201 && a <= 250) { + e = 9 + } else { + if (a >= 251 && a <= 300) { + e = 10 + } else { + if (a >= 301 && a <= 500) { + e = 11 + } else { + e = 12 + } + } + } + } + } + } + } + } + } + } + } + return e +} +function setRealTemp() { + if (typeof (weatherinfovar) == "undefined") { + return + } + var a = weatherinfovar.weatherinfo; + if (typeof (a.temp) != "undefined") { + $("#jingdianTemp strong").html("当前气温:"); + $("#jingdianTemp span").html(a.temp + "℃"); + $("#districtTemp").html("当前气温:" + a.temp + "℃") + } + setLiveInfo() +} +function setDetailInfo() { + if (typeof (weatherinfovar) == "undefined") { + return + } + var b = weatherinfovar.weatherinfo; + if (typeof (b.aqiLevel) != "undefined") { + if ($("#aqiHref")) { + var a = aqiPercent(b.idx); + $("#aqiHref").attr("class", "aqi-icon aqi-icon-lv" + b.aqiLevel); + $("#aqiText").html(b.lv_hint) + } + } +} +function weaInterAlert(a) { + if (a) { + var b = new String(a.title); + $("#alertCont h2").hide(); + $("#alertCont").append('
    ' + b + "
    ") + } +} +function weaAlertCallBack(b) { + if (b) { + var a = new String(b.title); + title = a.replace(/.*?发布/, ""); + title = title.replace(/道路/, ""); + color = alarmColor(title); + if ($("#alertLink").length > 0) { + $("#emoticonId").attr("class", "emoticon warn-" + color); + $("#emoticonId span").html(title + "
    小心自然灾害!"); + $("#emoticonId a").attr("href", "/t/shikuang/alert/" + b.url) + } else { + $("#emoticonId").addClass("warn-" + color); + $("#emoticonId i").attr("class", "warn"); + $("#emoticonId span").html(title + "
    小心自然灾害!"); + $("#emoticonId span").append('') + } + } +} +function alarmColor(a) { + if (a.indexOf("蓝色") >= 0) { + color = "blue" + } else { + if (a.indexOf("黄色") >= 0) { + color = "yellow" + } else { + if (a.indexOf("橙色") >= 0) { + color = "orange" + } else { + if (a.indexOf("红色") >= 0) { + color = "red" + } else { + color = "blue" + } + } + } + } + return color +} +function showAddFavPop() { + $("#add2fav-layer b").click(function() { + setCookie("closedAddFav", "y", 24 * 365); + $("#add2fav-layer").hide() + }); + if (!getCookie("closedAddFav")) { + $("#add2fav-layer").show() + } + setTimeout(function() { + setCookie("closedAddFav", "y", 24 * 365); + $("#add2fav-layer").hide() + }, 10000) +} +function hourChartInDetail() { + var a = (new Date).getHours(); + var b = new dhtmlXChart({ + view: "line", + container: "hourChart", + value: "#temp#", + label: function(e) { + var c = "w" + e.icon; + var f = ""; + if (e.hour < 6 || e.hour > 18) { + c = c + " wnt" + } + if (e.hour == a && typeof (tomorrowDetail) == "undefined") { + f = " data-cur" + } + return "
    " + e.temp + "℃
    " + }, + tooltip: { + template: "#tq#" + }, + item: { + borderColor: function(c) { + if (c.hour == a && typeof (tomorrowDetail) == "undefined") { + return "#268dea" + } else { + return "#fff" + } + }, + color: function(c) { + if (typeof (tomorrowDetail) != "undefined") { + return "#268dea" + } + if (c.hour < a) { + return "#ccc" + } else { + if (c.hour == a) { + return "#fff" + } else { + return "#268dea" + } + } + }, + radius: 4 + }, + line: { + color: function(c) { + if (typeof (tomorrowDetail) != "undefined") { + return "#b2daff" + } + if (c.hour < a) { + return "#e9e9e9" + } else { + return "#b2daff" + } + }, + width: 2 + }, + xAxis: { + template: "#hour#点", + color: "#d9d9d9", + lineColor: "#e9e9e9" + }, + yAxis: { + start: wea_h_section[1], + step: wea_h_section[2], + end: wea_h_section[0], + template: function(c) { + return c + "℃" + }, + color: "#d9d9d9", + lineColor: "#e9e9e9" + }, + preset: "simple" + }); + b.parse(wea_h_hour, "json") +} +function hourNewSlide() { + var hourUl = $("#wea_hour ul") + , curIndex = $("#wea_hour .inner .clearfix .current").index() + , prev = $("#hourRight") + , next = $("#hourLeft") + , stepArray = [0, -366, -732, -1098] + , stepIndex = 0; + if (curIndex <= 5) { + stepIndex = 0; + prev.addClass("disable") + } + if (curIndex >= 6 && curIndex <= 11) { + stepIndex = 1 + } + if (curIndex >= 12 && curIndex <= 17) { + stepIndex = 2 + } + if (curIndex >= 18 && curIndex <= 23) { + stepIndex = 3; + next.addClass("disable") + } + hourUl.css("margin-left", stepArray[stepIndex] + "px"); + prev.bind("click", function() { + if ($(this).hasClass("disable")) { + return + } else { + if (next.hasClass("disable")) { + next.removeClass("disable") + } + stepIndex--; + hourUl.animate({ + marginLeft: stepArray[stepIndex] + "px" + }, 200, "linear"); + if (stepIndex <= 0) { + $(this).addClass("disable") + } + } + }); + next.bind("click", function() { + if ($(this).hasClass("disable")) { + return + } else { + if (prev.hasClass("disable")) { + prev.removeClass("disable") + } + stepIndex++; + hourUl.animate({ + marginLeft: stepArray[stepIndex] + "px" + }, 200, "linear"); + if (stepIndex >= 3) { + $(this).addClass("disable") + } + } + }) +} +function hour24Slide() { + var e = $("#wea_hour ul") + , b = $("#wea_hour .tab-body .current").index() + , f = $("#hourPrev") + , c = $("#hourNext") + , a = [0, -366, -732, -1098] + , g = 0; + if (b <= 5) { + g = 0; + f.addClass("disable") + } + if (b >= 6 && b <= 11) { + g = 1 + } + if (b >= 12 && b <= 17) { + g = 2 + } + if (b >= 18 && b <= 23) { + g = 3; + c.addClass("disable") + } + e.css("margin-left", a[g] + "px"); + f.bind("click", function() { + if ($(this).hasClass("disable")) { + return + } else { + if (c.hasClass("disable")) { + c.removeClass("disable") + } + g--; + e.animate({ + marginLeft: a[g] + "px" + }, 200, "linear"); + if (g <= 0) { + $(this).addClass("disable") + } + allCount("hour_previous") + } + }); + c.bind("click", function() { + if ($(this).hasClass("disable")) { + return + } else { + if (f.hasClass("disable")) { + f.removeClass("disable") + } + g++; + e.animate({ + marginLeft: a[g] + "px" + }, 200, "linear"); + if (g >= 3) { + $(this).addClass("disable") + } + allCount("hour_next") + } + }) +} +function hour24SlideInter() { + var e = $("#wea_hour ul") + , b = $("#wea_hour .tab-body .current").index() + , f = $("#hourPrev") + , c = $("#hourNext") + , a = [0, -366, -732, -1098, -1464, -1830] + , g = 0; + if (b <= 5) { + g = 0; + f.addClass("disable") + } + if (b >= 6 && b <= 11) { + g = 1 + } + if (b >= 12 && b <= 17) { + g = 2 + } + if (b >= 18 && b <= 23) { + g = 3; + c.addClass("disable") + } + e.css("margin-left", a[g] + "px"); + f.bind("click", function() { + if ($(this).hasClass("disable")) { + return + } else { + if (c.hasClass("disable")) { + c.removeClass("disable") + } + g--; + e.animate({ + marginLeft: a[g] + "px" + }, 200, "linear"); + if (g <= 0) { + $(this).addClass("disable") + } + allCount("hour_previous") + } + }); + c.bind("click", function() { + if ($(this).hasClass("disable")) { + return + } else { + if (f.hasClass("disable")) { + f.removeClass("disable") + } + g++; + e.animate({ + marginLeft: a[g] + "px" + }, 200, "linear"); + if (g >= 5) { + $(this).addClass("disable") + } + allCount("hour_next") + } + }) +} +(function(a) { + a.fn.hoverfix = function() { + a(this).hover(function(b) { + a(this).addClass("hover") + }, function() { + a(this).removeClass("hover") + }); + return this + } + ; + a.fn.activefix = function() { + var b = a(this); + b.bind("mousedown", function() { + a(this).addClass("active") + }).bind("mouseup", function() { + a(this).removeClass("active") + }).bind("mouseout", function() { + a(this).removeClass("active") + }); + return this + } +} +)(jQuery); +if (!/plugin\/widget\/index/.test(location.href)) { + jQuery(window).bind("resize", function() { + var a; + a = jQuery("body"); + if (jQuery(this).width() <= 1000) { + a.css("width", "1000") + } else { + a.css("width", jQuery(window).width() + "px") + } + }).trigger("resize") +} +function scrollFixed() { + var c = $(".sidebar-money"); + if (c.length == 0) { + return + } + var a = c.offset().top; + var b = $("html").hasClass("ie6"); + $(window).scroll(function() { + if ($(this).scrollTop() >= a) { + c.addClass("sidebar-money-fixed"); + if (b) { + c.css({ + top: $(this).scrollTop() - 145 + }) + } + } else { + c.removeClass("sidebar-money-fixed"); + if (b) { + c.css({ + top: 0 + }) + } + } + }) +} +function setAqi15days() { + if (typeof (aqiForeast) == "undefined") { + return + } + var b = 0; + for (time in aqiForeast) { + if (aqiForeast[time].qualityStr == "优") { + aqiForeast[time].qualityStr = "空气优" + } else { + if (aqiForeast[time].qualityStr == "良") { + aqiForeast[time].qualityStr = "空气良" + } + } + var c = '
    ' + aqiForeast[time].qualityStr + "
    "; + if ($("#day7info li:eq(" + b + ")").length > 0) { + $(".week_day7 li:eq(" + b + ")").append(c) + } else { + var a = b - 7; + $("#day8info li:eq(" + a + ")").append(c) + } + b++ + } +} +function addToFavorite() { + var f = document.title + , b = location.href + , a = $("#lastBread").text() || "2345天气预报"; + try { + window.external.addFavorite(b, f) + } catch (c) { + try { + window.sidebar.addPanel(f, b, "") + } catch (c) { + alert("同时按下Ctrl+D键,将“" + a + "”加入收藏夹") + } + } +} +function getBrowserOs() { + if (navigator.userAgent.indexOf("MSIE") > 0) { + return "MSIE" + } + if (isFirefox = navigator.userAgent.indexOf("Firefox") > 0) { + return "Firefox" + } + if (isSafari = navigator.userAgent.indexOf("Safari") > 0) { + return "Safari" + } + if (isCamino = navigator.userAgent.indexOf("Camino") > 0) { + return "Camino" + } + if (isMozilla = navigator.userAgent.indexOf("Gecko/") > 0) { + return "Gecko" + } +} +function loadJsMulti(b) { + var e = arguments[1] || function() {} + ; + var f = arguments[2] || function() {} + ; + var g = arguments[3] || function() {} + ; + var c = "gbk"; + var a = document.createElement("script"); + a.setAttribute("type", "text/javascript"); + a.setAttribute("charset", c); + a.setAttribute("defer", true); + a.setAttribute("src", b); + if (document.all) { + a.onreadystatechange = function() { + if (this.readyState == "loaded" || this.readyState == 4 || this.readyState == "complete") { + setTimeout(e, 10); + setTimeout(f, 10); + setTimeout(g, 10) + } + } + } else { + a.onload = function() { + e() + } + } + document.getElementsByTagName("head")[0].appendChild(a) +} +; \ No newline at end of file diff --git "a/web/117 \344\270\212\346\265\267\345\270\202\345\233\276\344\271\246\351\246\206\345\244\247\345\261\217\347\234\213\346\235\277/static/detect2013_plugin.php" "b/web/117 \344\270\212\346\265\267\345\270\202\345\233\276\344\271\246\351\246\206\345\244\247\345\261\217\347\234\213\346\235\277/static/detect2013_plugin.php" new file mode 100644 index 00000000..17b15a20 --- /dev/null +++ "b/web/117 \344\270\212\346\265\267\345\270\202\345\233\276\344\271\246\351\246\206\345\244\247\345\261\217\347\234\213\346\235\277/static/detect2013_plugin.php" @@ -0,0 +1,3 @@ + +setDefaultDzWea('60010'); +var wea_ = {"city":"ζ","dayType":"15","day1":["2530","","","Ϸ","12","0621"],"day2":["2429","","С","Ϸ","11","0622"],"day3":["2332","","С","Ϸ","11","0623"],"day4":["2226","һ","С","Ϸ","11","0624"],"day5":["2527","","","Ϸ","64","0625"],"day6":["2428","","С","Ϸ","11","0626"],"day7":["2531","","С","ϷתϷ","11","0627"],"title":"ʾ鿴Ԥ밴Ctrl+F5ˢ£\u0026#10;0621,,תС,25~30,Ϸ\u0026#10;0622,,Сת,24~29,Ϸ\u0026#10;0623,,Сת,23~32,Ϸ\u0026#10;0624,һ,С,22~26,Ϸ\u0026#10;0625,ܶ,ת,25~27,Ϸ\u0026#10;0626,,С,24~28,Ϸ\u0026#10;0627,,Сת,25~31,Ϸ","id":60010,"pinyin":"JiaDing"};if(typeof(weaCallBack) != "undefined"){weaCallBack(wea_)} diff --git "a/web/117 \344\270\212\346\265\267\345\270\202\345\233\276\344\271\246\351\246\206\345\244\247\345\261\217\347\234\213\346\235\277/static/echarts.min.js" "b/web/117 \344\270\212\346\265\267\345\270\202\345\233\276\344\271\246\351\246\206\345\244\247\345\261\217\347\234\213\346\235\277/static/echarts.min.js" new file mode 100644 index 00000000..453bfab2 --- /dev/null +++ "b/web/117 \344\270\212\346\265\267\345\270\202\345\233\276\344\271\246\351\246\206\345\244\247\345\261\217\347\234\213\346\235\277/static/echarts.min.js" @@ -0,0 +1,22 @@ + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + + +!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e(t.echarts={})}(this,function(t){"use strict";var e=2311,n=function(){return e++},v="object"==typeof wx&&"function"==typeof wx.getSystemInfoSync?{browser:{},os:{},node:!1,wxa:!0,canvasSupported:!0,svgSupported:!1,touchEventsSupported:!0,domSupported:!1}:"undefined"==typeof document&&"undefined"!=typeof self?{browser:{},os:{},node:!1,worker:!0,canvasSupported:!0,domSupported:!1}:"undefined"==typeof navigator?{browser:{},os:{},node:!0,worker:!1,canvasSupported:!0,svgSupported:!0,domSupported:!1}:function(t){var e={},i=t.match(/Firefox\/([\d.]+)/),n=t.match(/MSIE\s([\d.]+)/)||t.match(/Trident\/.+?rv:(([\d.]+))/),o=t.match(/Edge\/([\d.]+)/),a=/micromessenger/i.test(t);i&&(e.firefox=!0,e.version=i[1]);n&&(e.ie=!0,e.version=n[1]);o&&(e.edge=!0,e.version=o[1]);a&&(e.weChat=!0);return{browser:e,os:{},node:!1,canvasSupported:!!document.createElement("canvas").getContext,svgSupported:"undefined"!=typeof SVGRect,touchEventsSupported:"ontouchstart"in window&&!e.ie&&!e.edge,pointerEventsSupported:"onpointerdown"in window&&(e.edge||e.ie&&11<=e.version),domSupported:"undefined"!=typeof document}}(navigator.userAgent);var s={"[object Function]":1,"[object RegExp]":1,"[object Date]":1,"[object Error]":1,"[object CanvasGradient]":1,"[object CanvasPattern]":1,"[object Image]":1,"[object Canvas]":1},l={"[object Int8Array]":1,"[object Uint8Array]":1,"[object Uint8ClampedArray]":1,"[object Int16Array]":1,"[object Uint16Array]":1,"[object Int32Array]":1,"[object Uint32Array]":1,"[object Float32Array]":1,"[object Float64Array]":1},u=Object.prototype.toString,i=Array.prototype,r=i.forEach,h=i.filter,o=i.slice,c=i.map,d=i.reduce,a={};function f(t,e){"createCanvas"===t&&(g=null),a[t]=e}function k(t){if(null==t||"object"!=typeof t)return t;var e=t,i=u.call(t);if("[object Array]"===i){if(!$(t)){e=[];for(var n=0,o=t.length;n>1)%2;s.cssText=["position: absolute","visibility: hidden","padding: 0","margin: 0","border-width: 0","user-select: none","width:0","height:0",n[l]+":0",o[u]+":0",n[1-l]+":auto",o[1-u]+":auto",""].join("!important;"),t.appendChild(r),i.push(r)}return i}(e,a),a,o);if(r)return r(t,i,n),!0}return!1}function zt(t){return"CANVAS"===t.nodeName.toUpperCase()}var Bt="undefined"!=typeof window&&!!window.addEventListener,Vt=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,Gt=[];function Ft(t,e,i,n){return i=i||{},n||!v.canvasSupported?Wt(t,e,i):v.browser.firefox&&null!=e.layerX&&e.layerX!==e.offsetX?(i.zrX=e.layerX,i.zrY=e.layerY):null!=e.offsetX?(i.zrX=e.offsetX,i.zrY=e.offsetY):Wt(t,e,i),i}function Wt(t,e,i){if(v.domSupported&&t.getBoundingClientRect){var n=e.clientX,o=e.clientY;if(zt(t)){var a=t.getBoundingClientRect();return i.zrX=n-a.left,void(i.zrY=o-a.top)}if(Rt(Gt,t,n,o))return i.zrX=Gt[0],void(i.zrY=Gt[1])}i.zrX=i.zrY=0}function Ht(t){return t||window.event}function Zt(t,e,i){if(null!=(e=Ht(e)).zrX)return e;var n=e.type;if(n&&0<=n.indexOf("touch")){var o="touchend"!==n?e.targetTouches[0]:e.changedTouches[0];o&&Ft(t,o,e,i)}else Ft(t,e,e,i),e.zrDelta=e.wheelDelta?e.wheelDelta/120:-(e.detail||0)/3;var a=e.button;return null==e.which&&void 0!==a&&Vt.test(e.type)&&(e.which=1&a?1:2&a?3:4&a?2:0),e}function Ut(t,e,i,n){Bt?t.addEventListener(e,i,n):t.attachEvent("on"+e,i)}var Xt=Bt?function(t){t.preventDefault(),t.stopPropagation(),t.cancelBubble=!0}:function(t){t.returnValue=!1,t.cancelBubble=!0};function Yt(t){return 2===t.which||3===t.which}function jt(){this._track=[]}function qt(t){var e=t[1][0]-t[0][0],i=t[1][1]-t[0][1];return Math.sqrt(e*e+i*i)}jt.prototype={constructor:jt,recognize:function(t,e,i){return this._doTrack(t,e,i),this._recognize(t)},clear:function(){return this._track.length=0,this},_doTrack:function(t,e,i){var n=t.touches;if(n){for(var o={points:[],touches:[],target:e,event:t},a=0,r=n.length;an.getWidth()||i<0||i>n.getHeight()}te.prototype={constructor:te,setHandlerProxy:function(e){this.proxy&&this.proxy.dispose(),e&&(E(ee,function(t){e.on&&e.on(t,this[t],this)},this),e.handler=this),this.proxy=e},mousemove:function(t){var e=t.zrX,i=t.zrY,n=ne(this,e,i),o=this._hovered,a=o.target;a&&!a.__zr&&(a=(o=this.findHover(o.x,o.y)).target);var r=this._hovered=n?{x:e,y:i}:this.findHover(e,i),s=r.target,l=this.proxy;l.setCursor&&l.setCursor(s?s.cursor:"default"),a&&s!==a&&this.dispatchToElement(o,"mouseout",t),this.dispatchToElement(r,"mousemove",t),s&&s!==a&&this.dispatchToElement(r,"mouseover",t)},mouseout:function(t){var e=t.zrEventControl,i=t.zrIsToLocalDOM;"only_globalout"!==e&&this.dispatchToElement(this._hovered,"mouseout",t),"no_globalout"!==e&&(i||this.trigger("globalout",{type:"globalout",event:t}))},resize:function(t){this._hovered={}},dispatch:function(t,e){var i=this[t];i&&i.call(this,e)},dispose:function(){this.proxy.dispose(),this.storage=this.proxy=this.painter=null},setCursorStyle:function(t){var e=this.proxy;e.setCursor&&e.setCursor(t)},dispatchToElement:function(t,e,i){var n=(t=t||{}).target;if(!n||!n.silent){for(var o="on"+e,a=function(t,e,i){return{type:t,event:i,target:e.target,topTarget:e.topTarget,cancelBubble:!1,offsetX:i.zrX,offsetY:i.zrY,gestureEvent:i.gestureEvent,pinchX:i.pinchX,pinchY:i.pinchY,pinchScale:i.pinchScale,wheelDelta:i.zrDelta,zrByTouch:i.zrByTouch,which:i.which,stop:Jt}}(e,t,i);n&&(n[o]&&(a.cancelBubble=n[o].call(n,a)),n.trigger(e,a),n=n.parent,!a.cancelBubble););a.cancelBubble||(this.trigger(e,a),this.painter&&this.painter.eachOtherLayer(function(t){"function"==typeof t[o]&&t[o].call(t,a),t.trigger&&t.trigger(e,a)}))}},findHover:function(t,e,i){for(var n=this.storage.getDisplayList(),o={x:t,y:e},a=n.length-1;0<=a;a--){var r;if(n[a]!==i&&!n[a].ignore&&(r=ie(n[a],t,e))&&(o.topTarget||(o.topTarget=n[a]),r!==$t)){o.target=n[a];break}}return o},processGesture:function(t,e){this._gestureMgr||(this._gestureMgr=new jt);var i=this._gestureMgr;"start"===e&&i.clear();var n=i.recognize(t,this.findHover(t.zrX,t.zrY,null).target,this.proxy.dom);if("end"===e&&i.clear(),n){var o=n.type;t.gestureEvent=o,this.dispatchToElement({target:n.target},o,n.event)}}},E(["click","mousedown","mouseup","mousewheel","dblclick","contextmenu"],function(r){te.prototype[r]=function(t){var e,i,n=t.zrX,o=t.zrY,a=ne(this,n,o);if("mouseup"===r&&a||(i=(e=this.findHover(n,o)).target),"mousedown"===r)this._downEl=i,this._downPoint=[t.zrX,t.zrY],this._upEl=i;else if("mouseup"===r)this._upEl=i;else if("click"===r){if(this._downEl!==this._upEl||!this._downPoint||4=this._maxSize&&0>4|(3840&n)>>8,240&n|(240&n)>>4,15&n|(15&n)<<4,1),Ge(t,e),e):void Re(e,0,0,0,1):7===o.length?0<=(n=parseInt(o.substr(1),16))&&n<=16777215?(Re(e,(16711680&n)>>16,(65280&n)>>8,255&n,1),Ge(t,e),e):void Re(e,0,0,0,1):void 0;var a=o.indexOf("("),r=o.indexOf(")");if(-1!==a&&r+1===o.length){var s=o.substr(0,a),l=o.substr(a+1,r-(a+1)).split(","),u=1;switch(s){case"rgba":if(4!==l.length)return void Re(e,0,0,0,1);u=Ne(l.pop());case"rgb":return 3!==l.length?void Re(e,0,0,0,1):(Re(e,Pe(l[0]),Pe(l[1]),Pe(l[2]),u),Ge(t,e),e);case"hsla":return 4!==l.length?void Re(e,0,0,0,1):(l[3]=Ne(l[3]),We(l,e),Ge(t,e),e);case"hsl":return 3!==l.length?void Re(e,0,0,0,1):(We(l,e),Ge(t,e),e);default:return}}Re(e,0,0,0,1)}}function We(t,e){var i=(parseFloat(t[0])%360+360)%360/360,n=Ne(t[1]),o=Ne(t[2]),a=o<=.5?o*(n+1):o+n-o*n,r=2*o-a;return Re(e=e||[],Le(255*Oe(r,a,i+1/3)),Le(255*Oe(r,a,i)),Le(255*Oe(r,a,i-1/3)),1),4===t.length&&(e[3]=t[3]),e}function He(t,e){var i=Fe(t);if(i){for(var n=0;n<3;n++)i[n]=e<0?i[n]*(1-e)|0:(255-i[n])*e+i[n]|0,255e);i++);i=Math.min(i-1,u-2)}C=e;var n=g[(D=i)+1]-g[i];if(0!=n)if(S=(e-g[i])/n,l)if(I=m[i],M=m[0===i?i:i-1],T=m[u-2=i.x&&t<=i.x+i.width&&e>=i.y&&e<=i.y+i.height},clone:function(){return new Di(this.x,this.y,this.width,this.height)},copy:function(t){this.x=t.x,this.y=t.y,this.width=t.width,this.height=t.height},plain:function(){return{x:this.x,y:this.y,width:this.width,height:this.height}}},Di.create=function(t){return new Di(t.x,t.y,t.width,t.height)};var Ci=function(t){for(var e in t=t||{},_i.call(this,t),t)t.hasOwnProperty(e)&&(this[e]=t[e]);this._children=[],this.__storage=null,this.__dirty=!0};Ci.prototype={constructor:Ci,isGroup:!0,type:"group",silent:!1,children:function(){return this._children.slice()},childAt:function(t){return this._children[t]},childOfName:function(t){for(var e=this._children,i=0;i>>1])<0?l=a:s=1+a;var u=n-s;switch(u){case 3:t[s+3]=t[s+2];case 2:t[s+2]=t[s+1];case 1:t[s+1]=t[s];break;default:for(;0>>1);0>>1);a(t,e[i+h])<0?l=h:r=h+1}return l}function Ri(p,g){var r,s,m=ki,l=0,v=[];function e(t){var e=r[t],i=s[t],n=r[t+1],o=s[t+1];s[t]=i+o,t===l-3&&(r[t+1]=r[t+2],s[t+1]=s[t+2]),l--;var a=Ei(p[n],p,e,i,0,g);e+=a,0!==(i-=a)&&0!==(o=Oi(p[e+i-1],p,n,o,o-1,g))&&(i<=o?function(t,e,i,n){var o=0;for(o=0;os[t+1])break;e(t)}},this.forceMergeRuns=function(){for(;1>=1;return t+e}(o);do{if((a=Pi(t,i,n,e))=e.maxIterations){t+=e.ellipsis;break}var s=0===r?bn(t,o,e.ascCharWidth,e.cnCharWidth):0f)return{lines:[],width:0,height:0};C.textWidth=pn(C.text,w);var S=x.textWidth,M=null==S||"auto"===S;if("string"==typeof S&&"%"===S.charAt(S.length-1))C.percentWidth=S,u.push(C),S=0;else{if(M){S=C.textWidth;var I=x.textBackgroundColor,T=I&&I.image;T&&sn(T=on(T))&&(S=Math.max(S,T.width*b/T.height))}var A=_?_[1]+_[3]:0;S+=A;var D=null!=d?d-v:null;null!=D&&Dn[0]){for(r=0;rt);r++);a=i[n[r]]}if(n.splice(r+1,0,t),!(i[t]=e).virtual)if(a){var l=a.dom;l.nextSibling?s.insertBefore(e.dom,l.nextSibling):s.appendChild(e.dom)}else s.firstChild?s.insertBefore(e.dom,s.firstChild):s.appendChild(e.dom)}else vi("Layer of zlevel "+t+" is not valid")},eachLayer:function(t,e){var i,n,o=this._zlevelList;for(n=0;n=a.length&&a.push({option:t})}}),a}function Zo(t){var r=Q();Eo(t,function(t,e){var i=t.exist;i&&r.set(i.id,t)}),Eo(t,function(t,e){var i=t.option;Y(!i||null==i.id||!r.get(i.id)||r.get(i.id)===t,"id duplicates: "+(i&&i.id)),i&&null!=i.id&&r.set(i.id,t),t.keyInfo||(t.keyInfo={})}),Eo(t,function(t,e){var i=t.exist,n=t.option,o=t.keyInfo;if(Ro(n)){if(o.name=null!=n.name?n.name+"":i?i.name:Bo+e,i)o.id=i.id;else if(null!=n.id)o.id=n.id+"";else for(var a=0;o.id="\0"+o.name+"\0"+a++,r.get(o.id););r.set(o.id,t)}})}function Uo(t){var e=t.name;return!(!e||!e.indexOf(Bo))}function Xo(t){return Ro(t)&&t.id&&0===(t.id+"").indexOf("\0_ec_\0")}function Yo(e,t){return null!=t.dataIndexInside?t.dataIndexInside:null!=t.dataIndex?L(t.dataIndex)?O(t.dataIndex,function(t){return e.indexOfRawIndex(t)}):e.indexOfRawIndex(t.dataIndex):null!=t.name?L(t.name)?O(t.name,function(t){return e.indexOfName(t)}):e.indexOfName(t.name):void 0}function jo(){var e="__\0ec_inner_"+qo+++"_"+Math.random().toFixed(5);return function(t){return t[e]||(t[e]={})}}var qo=0;function Ko(s,l,u){if(R(l)){var t={};t[l+"Index"]=0,l=t}var e=u&&u.defaultMainType;!e||$o(l,e+"Index")||$o(l,e+"Id")||$o(l,e+"Name")||(l[e+"Index"]=0);var h={};return Eo(l,function(t,e){t=l[e];if("dataIndex"!==e&&"dataIndexInside"!==e){var i=e.match(/^(\w+)(Index|Id|Name)$/)||[],n=i[1],o=(i[2]||"").toLowerCase();if(!(!n||!o||null==t||"index"===o&&"none"===t||u&&u.includeMainTypes&&_(u.includeMainTypes,n)<0)){var a={mainType:n};"index"===o&&"all"===t||(a[o]=t);var r=s.queryComponents(a);h[n+"Models"]=r,h[n+"Model"]=r[0]}}else h[e]=t}),h}function $o(t,e){return t&&t.hasOwnProperty(e)}function Jo(t,e,i){t.setAttribute?t.setAttribute(e,i):t[e]=i}function Qo(t){return"auto"===t?v.domSupported?"html":"richText":t||"html"}function ta(t,i){var n=Q(),o=[];return E(t,function(t){var e=i(t);(n.get(e)||(o.push(e),n.set(e,[]))).push(t)}),{keys:o,buckets:n}}var ea=".",ia="___EC__COMPONENT__CONTAINER___";function na(t){var e={main:"",sub:""};return t&&(t=t.split(ea),e.main=t[0]||"",e.sub=t[1]||""),e}function oa(t){(t.$constructor=t).extend=function(t){function e(){t.$constructor?t.$constructor.apply(this,arguments):i.apply(this,arguments)}var i=this;return P(e.prototype,t),e.extend=this.extend,e.superCall=sa,e.superApply=la,w(e,this),e.superClass=i,e}}var aa=0;function ra(t){var e=["__\0is_clz",aa++,Math.random().toFixed(3)].join("_");t.prototype[e]=!0,t.isInstance=function(t){return!(!t||!t[e])}}function sa(t,e){var i=U(arguments,2);return this.superClass.prototype[e].apply(t,i)}function la(t,e,i){return this.superClass.prototype[e].apply(t,i)}function ua(i,t){t=t||{};var o={};if(i.registerClass=function(t,e){if(e)if(function(t){Y(/^[a-zA-Z0-9_]+([.][a-zA-Z0-9_]+)?$/.test(t),'componentType "'+t+'" illegal')}(e),(e=na(e)).sub){if(e.sub!==ia){(function(t){var e=o[t.main];e&&e[ia]||((e=o[t.main]={})[ia]=!0);return e})(e)[e.sub]=t}}else o[e.main]=t;return t},i.getClass=function(t,e,i){var n=o[t];if(n&&n[ia]&&(n=e?n[e]:null),i&&!n)throw new Error(e?"Component "+t+"."+(e||"")+" not exists. Load it first.":t+".type should be specified.");return n},i.getClassesByMainType=function(t){t=na(t);var i=[],e=o[t.main];return e&&e[ia]?E(e,function(t,e){e!==ia&&i.push(t)}):i.push(e),i},i.hasClass=function(t){return t=na(t),!!o[t.main]},i.getAllClassMainTypes=function(){var i=[];return E(o,function(t,e){i.push(e)}),i},i.hasSubTypes=function(t){t=na(t);var e=o[t.main];return e&&e[ia]},i.parseClassType=na,t.registerWhenExtend){var n=i.extend;n&&(i.extend=function(t){var e=n.call(this,t);return i.registerClass(e,t.type)})}return i}function ha(s){for(var t=0;tthis._ux||or(e-this._yi)>this._uy||this._len<5;return this.addData(ja.L,t,e),this._ctx&&i&&(this._needsDash()?this._dashedLineTo(t,e):this._ctx.lineTo(t,e)),i&&(this._xi=t,this._yi=e),this},bezierCurveTo:function(t,e,i,n,o,a){return this.addData(ja.C,t,e,i,n,o,a),this._ctx&&(this._needsDash()?this._dashedBezierTo(t,e,i,n,o,a):this._ctx.bezierCurveTo(t,e,i,n,o,a)),this._xi=o,this._yi=a,this},quadraticCurveTo:function(t,e,i,n){return this.addData(ja.Q,t,e,i,n),this._ctx&&(this._needsDash()?this._dashedQuadraticTo(t,e,i,n):this._ctx.quadraticCurveTo(t,e,i,n)),this._xi=i,this._yi=n,this},arc:function(t,e,i,n,o,a){return this.addData(ja.A,t,e,i,i,n,o-n,0,a?0:1),this._ctx&&this._ctx.arc(t,e,i,n,o,a),this._xi=er(o)*i+t,this._yi=ir(o)*i+e,this},arcTo:function(t,e,i,n,o){return this._ctx&&this._ctx.arcTo(t,e,i,n,o),this},rect:function(t,e,i,n){return this._ctx&&this._ctx.rect(t,e,i,n),this.addData(ja.R,t,e,i,n),this},closePath:function(){this.addData(ja.Z);var t=this._ctx,e=this._x0,i=this._y0;return t&&(this._needsDash()&&this._dashedLineTo(e,i),t.closePath()),this._xi=e,this._yi=i,this},fill:function(t){t&&t.fill(),this.toStatic()},stroke:function(t){t&&t.stroke(),this.toStatic()},setLineDash:function(t){if(t instanceof Array){this._lineDash=t;for(var e=this._dashIdx=0,i=0;ie.length&&(this._expandData(),e=this.data);for(var i=0;il||or(r-o)>u||c===h-1)&&(t.lineTo(a,r),n=a,o=r);break;case ja.C:t.bezierCurveTo(s[c++],s[c++],s[c++],s[c++],s[c++],s[c++]),n=s[c-2],o=s[c-1];break;case ja.Q:t.quadraticCurveTo(s[c++],s[c++],s[c++],s[c++]),n=s[c-2],o=s[c-1];break;case ja.A:var f=s[c++],p=s[c++],g=s[c++],m=s[c++],v=s[c++],y=s[c++],x=s[c++],_=s[c++],w=m=yr[n=0]+t&&r<=yr[1]+t?h:0}if(a){l=n;n=cr(o),o=cr(l)}else n=cr(n),o=cr(o);oMath.PI/2&&p<1.5*Math.PI&&(h=-h),c+=h)}}return c}function Sr(t,e,i,n,o){for(var a=0,r=0,s=0,l=0,u=0,h=0;hMath.abs(a[1])?0=e[1])return i[1]}else{if(t>=e[0])return i[0];if(t<=e[1])return i[1]}else{if(t===e[0])return i[0];if(t===e[1])return i[1]}return(t-e[0])/o*a+i[0]}function Rl(t,e){switch(t){case"center":case"middle":t="50%";break;case"left":case"top":t="0%";break;case"right":case"bottom":t="100%"}return"string"==typeof t?function(t){return t.replace(/^\s+|\s+$/g,"")}(t).match(/%$/)?parseFloat(t)/100*e:parseFloat(t):null==t?NaN:+t}function zl(t,e,i){return null==e&&(e=10),e=Math.min(Math.max(0,e),20),t=(+t).toFixed(e),i?t:+t}function Bl(t){return t.sort(function(t,e){return t-e}),t}function Vl(t){if(t=+t,isNaN(t))return 0;for(var e=1,i=0;Math.round(t*e)/e!==t;)e*=10,i++;return i}function Gl(t){var e=t.toString(),i=e.indexOf("e");if(0h&&(h=u[d],c=d);++s[c],u[c]=0,++l}return s[e]/o}var Hl=9007199254740991;function Zl(t){var e=2*Math.PI;return(t%e+e)%e}function Ul(t){return-Ol"'])/g,ou={"&":"&","<":"<",">":">",'"':""","'":"'"};function au(t){return null==t?"":(t+"").replace(nu,function(t,e){return ou[e]})}function ru(t,e){return"{"+t+(null==e?"":e)+"}"}var su=["a","b","c","d","e","f","g"];function lu(t,e,i){L(e)||(e=[e]);var n=e.length;if(!n)return"";for(var o=e[0].$vars||[],a=0;a':'':{renderMode:o,content:"{marker"+a+"|} ",style:{color:i}}:""}function cu(t,e){return"0000".substr(0,e-(t+="").length)+t}function du(t,e,i){"week"!==t&&"month"!==t&&"quarter"!==t&&"half-year"!==t&&"year"!==t||(t="MM-dd\nyyyy");var n=Yl(e),o=i?"UTC":"",a=n["get"+o+"FullYear"](),r=n["get"+o+"Month"]()+1,s=n["get"+o+"Date"](),l=n["get"+o+"Hours"](),u=n["get"+o+"Minutes"](),h=n["get"+o+"Seconds"](),c=n["get"+o+"Milliseconds"]();return t=t.replace("MM",cu(r,2)).replace("M",r).replace("yyyy",a).replace("yy",a%100).replace("dd",cu(s,2)).replace("d",s).replace("hh",cu(l,2)).replace("h",l).replace("mm",cu(u,2)).replace("m",u).replace("ss",cu(h,2)).replace("s",h).replace("SSS",cu(c,3))}function fu(t){return t?t.charAt(0).toUpperCase()+t.substr(1):t}var pu=xn;function gu(t,e){if("_blank"===e||"blank"===e){var i=window.open();i.opener=null,i.location=t}else window.open(t,e)}var mu=(Object.freeze||Object)({addCommas:tu,toCamelCase:eu,normalizeCssArray:iu,encodeHTML:au,formatTpl:lu,formatTplSimple:uu,getTooltipMarker:hu,formatTime:du,capitalFirst:fu,truncateText:pu,getTextBoundingRect:function(t){return gn(t.text,t.font,t.textAlign,t.textVerticalAlign,t.textPadding,t.textLineHeight,t.rich,t.truncate)},getTextRect:function(t,e,i,n,o,a,r,s){return gn(t,e,i,n,o,s,a,r)},windowOpen:gu}),vu=E,yu=["left","right","top","bottom","width","height"],xu=[["width","left","right"],["height","top","bottom"]];function _u(h,c,d,f,p){var g=0,m=0;null==f&&(f=1/0),null==p&&(p=1/0);var v=0;c.eachChild(function(t,e){var i,n,o=t.position,a=t.getBoundingRect(),r=c.childAt(e+1),s=r&&r.getBoundingRect();if("horizontal"===h){var l=a.width+(s?-s.x+a.x:0);v=f<(i=g+l)||t.newline?(g=0,i=l,m+=v+d,a.height):Math.max(v,a.height)}else{var u=a.height+(s?-s.y+a.y:0);v=p<(n=m+u)||t.newline?(g+=v+d,m=0,n=u,a.width):Math.max(v,a.width)}t.newline||(o[0]=g,o[1]=m,"horizontal"===h?g=i+d:m=n+d)})}var wu=_u;T(_u,"vertical"),T(_u,"horizontal");function bu(t,e,i){i=iu(i||0);var n=e.width,o=e.height,a=Rl(t.left,n),r=Rl(t.top,o),s=Rl(t.right,n),l=Rl(t.bottom,o),u=Rl(t.width,n),h=Rl(t.height,o),c=i[2]+i[0],d=i[1]+i[3],f=t.aspect;switch(isNaN(u)&&(u=n-s-d-a),isNaN(h)&&(h=o-l-c-r),null!=f&&(isNaN(u)&&isNaN(h)&&(n/oe)return t[n];return t[i-1]}(s,i):r;if((l=l||r)&&l.length){var u=l[o];return t&&(a[t]=u),n.colorIdx=(o+1)%l.length,u}}},zu="original",Bu="arrayRows",Vu="objectRows",Gu="keyedColumns",Fu="unknown",Wu="typedArray",Hu="column",Zu="row";function Uu(t){this.fromDataset=t.fromDataset,this.data=t.data||(t.sourceFormat===Gu?{}:[]),this.sourceFormat=t.sourceFormat||Fu,this.seriesLayoutBy=t.seriesLayoutBy||Hu,this.dimensionsDefine=t.dimensionsDefine,this.encodeDefine=t.encodeDefine&&Q(t.encodeDefine),this.startIndex=t.startIndex||0,this.dimensionsDetectCount=t.dimensionsDetectCount}Uu.seriesDataToSource=function(t){return new Uu({data:t,sourceFormat:V(t)?Wu:zu,fromDataset:!1})},ra(Uu);var Xu={Must:1,Might:2,Not:3},Yu=jo();function ju(t){var e=t.option,i=e.data,n=V(i)?Wu:zu,o=!1,a=e.seriesLayoutBy,r=e.sourceHeader,s=e.dimensions,l=Qu(t);if(l){var u=l.option;i=u.source,n=Yu(l).sourceFormat,o=!0,a=a||u.seriesLayoutBy,null==r&&(r=u.sourceHeader),s=s||u.dimensions}var h=function(t,e,i,n,o){if(!t)return{dimensionsDefine:qu(o)};var a,r;if(e===Bu)"auto"===n||null==n?Ku(function(t){null!=t&&"-"!==t&&(R(t)?null==r&&(r=1):r=0)},i,t,10):r=n?1:0,o||1!==r||(o=[],Ku(function(t,e){o[e]=null!=t?t:""},i,t)),a=o?o.length:i===Zu?t.length:t[0]?t[0].length:null;else if(e===Vu)o=o||function(t){var e,i=0;for(;i":"\n",f="richText"===c,p={},g=0;function i(t){return{renderMode:c,content:au(tu(t)),style:p}}var m=this.getData(),a=m.mapDimension("defaultedTooltip",!0),n=a.length,r=this.getRawValue(o),s=L(r),v=m.getItemVisual(o,"color");z(v)&&v.colorStops&&(v=(v.colorStops[0]||{}).color),v=v||"transparent";var l=(1":"",n=i+u.join(i||", ");return{renderMode:c,content:n,style:p}}(r):i(n?Hh(m,o,a[0]):s?r[0]:r)).content,u=d.seriesIndex+"at"+g,y=hu({color:v,type:"item",renderMode:c,markerId:u});p[u]=v,++g;var x=m.getName(o),_=this.name;Uo(this)||(_=""),_=_?au(_)+(h?": ":e):"";var w="string"==typeof y?y:y.content;return{html:h?w+_+l:_+w+(x?au(x)+": "+l:l),markers:p}},isAnimationEnabled:function(){if(v.node)return!1;var t=this.getShallow("animation");return t&&this.getData().count()>this.getShallow("animationThreshold")&&(t=!1),t},restoreData:function(){this.dataTask.dirty()},getColorFromPalette:function(t,e,i){var n=this.ecModel,o=Ru.getColorFromPalette.call(this,t,e,i);return o=o||n.getColorFromPalette(t,e,i)},coordDimToDataDim:function(t){return this.getRawData().mapDimension(t,!0)},getProgressive:function(){return this.get("progressive")},getProgressiveThreshold:function(){return this.get("progressiveThreshold")},getAxisTooltipData:null,getTooltipPosition:null,pipeTask:null,preventIncremental:null,pipelineContext:null});function lc(t){var e=t.name;Uo(t)||(t.name=function(t){var i=t.getRawData(),e=i.mapDimension("seriesName",!0),n=[];return E(e,function(t){var e=i.getDimensionInfo(t);e.displayName&&n.push(e.displayName)}),n.join(" ")}(t)||e)}function uc(t){return t.model.getRawData().count()}function hc(t){var e=t.model;return e.setData(e.getRawData().cloneShallow()),cc}function cc(t,e){e.outputData&&t.end>e.outputData.count()&&e.model.getRawData().cloneShallow(e.outputData)}function dc(e,i){E(e.CHANGABLE_METHODS,function(t){e.wrapMethod(t,T(fc,i))})}function fc(t){var e=pc(t);e&&e.setOutputEnd(this.count())}function pc(t){var e=(t.ecModel||{}).scheduler,i=e&&e.getPipeline(t.uid);if(i){var n=i.currentTask;if(n){var o=n.agentStubMap;o&&(n=o.get(t.uid))}return n}}b(sc,Xh),b(sc,Ru);var gc=function(){this.group=new Ci,this.uid=Nl("viewComponent")};gc.prototype={constructor:gc,init:function(t,e){},render:function(t,e,i,n){},dispose:function(){},filterForExposedEvent:null};var mc=gc.prototype;mc.updateView=mc.updateLayout=mc.updateVisual=function(t,e,i,n){},oa(gc),ua(gc,{registerWhenExtend:!0});function vc(){var s=jo();return function(t){var e=s(t),i=t.pipelineContext,n=e.large,o=e.progressiveRender,a=e.large=i&&i.large,r=e.progressiveRender=i&&i.progressiveRender;return!!(n^a||o^r)&&"reset"}}var yc=jo(),xc=vc();function _c(){this.group=new Ci,this.uid=Nl("viewChart"),this.renderTask=Yh({plan:Mc,reset:Ic}),this.renderTask.context={view:this}}var wc=_c.prototype={type:"chart",init:function(t,e){},render:function(t,e,i,n){},highlight:function(t,e,i,n){Sc(t.getData(),n,"emphasis")},downplay:function(t,e,i,n){Sc(t.getData(),n,"normal")},remove:function(t,e){this.group.removeAll()},dispose:function(){},incrementalPrepareRender:null,incrementalRender:null,updateTransform:null,filterForExposedEvent:null};function bc(t,e,i){if(t&&(t.trigger(e,i),t.isGroup&&!Qs(t)))for(var n=0,o=t.childCount();nc?i+=p(g("data.partialData"),{displayCnt:c}):i+=g("data.allData");for(var r=[],s=0;si.blockIndex?i.step:null,a=n&&n.modDataCount;return{step:o,modBy:null!=a?Math.ceil(a/o):null,modDataCount:a}}},Bc.getPipeline=function(t){return this._pipelineMap.get(t)},Bc.updateStreamModes=function(t,e){var i=this._pipelineMap.get(t.uid),n=t.getData().count(),o=i.progressiveEnabled&&e.incrementalPrepareRender&&n>=i.threshold,a=t.get("large")&&n>=t.get("largeThreshold"),r="mod"===t.get("progressiveChunkMode")?n:null;t.pipelineContext=i.context={progressiveRender:o,modDataCount:r,large:a}},Bc.restorePipelines=function(t){var n=this,o=n._pipelineMap=Q();t.eachSeries(function(t){var e=t.getProgressive(),i=t.uid;o.set(i,{id:i,head:null,tail:null,threshold:t.getProgressiveThreshold(),progressiveEnabled:e&&!(t.preventIncremental&&t.preventIncremental()),blockIndex:-1,step:Math.round(e||700),count:0}),Kc(n,t,t.dataTask)})},Bc.prepareStageTasks=function(){var i=this._stageTaskMap,n=this.ecInstance.getModel(),o=this.api;E(this._allHandlers,function(t){var e=i.get(t.uid)||i.set(t.uid,[]);t.reset&&function(n,o,t,a,r){var s=t.seriesTaskMap||(t.seriesTaskMap=Q()),e=o.seriesType,i=o.getTargetSeries;o.createOnAllSeries?a.eachRawSeries(l):e?a.eachRawSeriesByType(e,l):i&&i(a,r).each(l);function l(t){var e=t.uid,i=s.get(e)||s.set(e,Yh({plan:Uc,reset:Xc,count:qc}));i.context={model:t,ecModel:a,api:r,useClearVisual:o.isVisual&&!o.isLayout,plan:o.plan,reset:o.reset,scheduler:n},Kc(n,t,i)}var u=n._pipelineMap;s.each(function(t,e){u.get(e)||(t.dispose(),s.removeKey(e))})}(this,t,e,n,o),t.overallReset&&function(n,t,e,i,o){var a=e.overallTask=e.overallTask||Yh({reset:Fc});a.context={ecModel:i,api:o,overallReset:t.overallReset,scheduler:n};var r=a.agentStubMap=a.agentStubMap||Q(),s=t.seriesType,l=t.getTargetSeries,u=!0,h=t.modifyOutputEnd;s?i.eachRawSeriesByType(s,c):l?l(i,o).each(c):(u=!1,E(i.getSeries(),c));function c(t){var e=t.uid,i=r.get(e);i||(i=r.set(e,Yh({reset:Wc,onDirty:Zc})),a.dirty()),i.context={model:t,overallProgress:u,modifyOutputEnd:h},i.agent=a,i.__block=u,Kc(n,t,i)}var d=n._pipelineMap;r.each(function(t,e){d.get(e)||(t.dispose(),a.dirty(),r.removeKey(e))})}(this,t,e,n,o)},this)},Bc.prepareView=function(t,e,i,n){var o=t.renderTask,a=o.context;a.model=e,a.ecModel=i,a.api=n,o.__block=!t.incrementalPrepareRender,Kc(this,e,o)},Bc.performDataProcessorTasks=function(t,e){Vc(this,this._dataProcessorHandlers,t,e,{block:!0})},Bc.performVisualTasks=function(t,e,i){Vc(this,this._visualHandlers,t,e,i)},Bc.performSeriesTasks=function(t){var e;t.eachSeries(function(t){e|=t.dataTask.perform()}),this.unfinished|=e},Bc.plan=function(){this._pipelineMap.each(function(t){var e=t.tail;do{if(e.__block){t.blockIndex=e.__idxInPipeline;break}e=e.getUpstream()}while(e)})};var Gc=Bc.updatePayload=function(t,e){"remain"!==e&&(t.context.payload=e)};function Fc(t){t.overallReset(t.ecModel,t.api,t.payload)}function Wc(t,e){return t.overallProgress&&Hc}function Hc(){this.agent.dirty(),this.getDownstream().dirty()}function Zc(){this.agent&&this.agent.dirty()}function Uc(t){return t.plan&&t.plan(t.model,t.ecModel,t.api,t.payload)}function Xc(t){t.useClearVisual&&t.data.clearAllVisual();var e=t.resetDefines=Vo(t.reset(t.model,t.ecModel,t.api,t.payload));return 1'+t.dom+""}),p.painter.getSvgRoot().innerHTML=g,o.connectedBackgroundColor&&p.painter.setBackgroundColor(o.connectedBackgroundColor),p.refreshImmediately(),p.painter.toDataURL()}return o.connectedBackgroundColor&&p.add(new rs({shape:{x:0,y:0,width:t,height:e},style:{fill:o.connectedBackgroundColor}})),Td(f,function(t){var e=new Qn({style:{x:t.left*i-u,y:t.top*i-h,image:t.dom}});p.add(e)}),p.refreshImmediately(),n.toDataURL("image/"+(o&&o.type||"png"))}return this.getDataURL(o)}},zd.convertToPixel=T(Bd,"convertToPixel"),zd.convertFromPixel=T(Bd,"convertFromPixel"),zd.containPixel=function(t,o){var a;if(!this._disposed)return E(t=Ko(this._model,t),function(t,n){0<=n.indexOf("Models")&&E(t,function(t){var e=t.coordinateSystem;if(e&&e.containPoint)a|=!!e.containPoint(o);else if("seriesModels"===n){var i=this._chartsMap[t.__viewId];i&&i.containPoint&&(a|=i.containPoint(o,t))}},this)},this),!!a},zd.getVisual=function(t,e){var i=(t=Ko(this._model,t,{defaultMainType:"series"})).seriesModel.getData(),n=t.hasOwnProperty("dataIndexInside")?t.dataIndexInside:t.hasOwnProperty("dataIndex")?i.indexOfRawIndex(t.dataIndex):null;return null!=n?i.getItemVisual(n,e):i.getVisual(e)},zd.getViewOfComponentModel=function(t){return this._componentsMap[t.__viewId]},zd.getViewOfSeriesModel=function(t){return this._chartsMap[t.__viewId]};var Vd={prepareAndUpdate:function(t){Gd(this),Vd.update.call(this,t)},update:function(t){var e=this._model,i=this._api,n=this._zr,o=this._coordSysMgr,a=this._scheduler;if(e){a.restoreData(e,t),a.performSeriesTasks(e),o.create(e,i),a.performDataProcessorTasks(e,t),Wd(this,e),o.update(e,i),Yd(e),a.performVisualTasks(e,t),jd(this,e,i,t);var r=e.get("backgroundColor")||"transparent";if(v.canvasSupported)n.setBackgroundColor(r);else{var s=Fe(r);r=$e(s,"rgb"),0===s[3]&&(r="transparent")}Kd(e,i)}},updateTransform:function(o){var a=this._model,r=this,s=this._api;if(a){var l=[];a.eachComponent(function(t,e){var i=r.getViewOfComponentModel(e);if(i&&i.__alive)if(i.updateTransform){var n=i.updateTransform(e,a,s,o);n&&n.update&&l.push(i)}else l.push(i)});var n=Q();a.eachSeries(function(t){var e=r._chartsMap[t.__viewId];if(e.updateTransform){var i=e.updateTransform(t,a,s,o);i&&i.update&&n.set(t.uid,1)}else n.set(t.uid,1)}),Yd(a),this._scheduler.performVisualTasks(a,o,{setDirty:!0,dirtyMap:n}),qd(r,a,s,o,n),Kd(a,this._api)}},updateView:function(t){var e=this._model;e&&(_c.markUpdateMethod(t,"updateView"),Yd(e),this._scheduler.performVisualTasks(e,t,{setDirty:!0}),jd(this,this._model,this._api,t),Kd(e,this._api))},updateVisual:function(t){Vd.update.call(this,t)},updateLayout:function(t){Vd.update.call(this,t)}};function Gd(t){var e=t._model,i=t._scheduler;i.restorePipelines(e),i.prepareStageTasks(),Xd(t,"component",e,i),Xd(t,"chart",e,i),i.plan()}function Fd(e,i,n,o,t){var a=e._model;if(o){var r={};r[o+"Id"]=n[o+"Id"],r[o+"Index"]=n[o+"Index"],r[o+"Name"]=n[o+"Name"];var s={mainType:o,query:r};t&&(s.subType=t);var l=n.excludeSeriesId;null!=l&&(l=Q(Vo(l))),a&&a.eachComponent(s,function(t){l&&null!=l.get(t.id)||u(e["series"===o?"_chartsMap":"_componentsMap"][t.__viewId])},e)}else Td(e._componentsViews.concat(e._chartsViews),u);function u(t){t&&t.__alive&&t[i]&&t[i](t.__model,a,e._api,n)}}function Wd(t,e){var i=t._chartsMap,n=t._scheduler;e.eachSeries(function(t){n.updateStreamModes(t,i[t.__viewId])})}function Hd(e,t){var i=e.type,n=e.escapeConnect,o=tf[i],a=o.actionInfo,r=(a.update||"update").split(":"),s=r.pop();r=null!=r[0]&&Cd(r[0]),this[kd]=!0;var l=[e],u=!1;e.batch&&(u=!0,l=O(e.batch,function(t){return(t=D(P({},t),e)).batch=null,t}));var h,c=[],d="highlight"===i||"downplay"===i;Td(l,function(t){(h=(h=o.action(t,this._model,this._api))||P({},t)).type=a.event||h.type,c.push(h),d?Fd(this,s,t,"series"):r&&Fd(this,s,t,r.main,r.sub)},this),"none"===s||d||r||(this[Pd]?(Gd(this),Vd.update.call(this,e),this[Pd]=!1):Vd[s].call(this,e)),h=u?{type:a.event||i,escapeConnect:n,batch:c}:c[0],this[kd]=!1,t||this._messageCenter.trigger(h.type,h)}function Zd(t){for(var e=this._pendingActions;e.length;){var i=e.shift();Hd.call(this,i,t)}}function Ud(t){t||this.trigger("updated")}function Xd(t,e,o,a){for(var r="component"===e,s=r?t._componentsViews:t._chartsViews,l=r?t._componentsMap:t._chartsMap,u=t._zr,h=t._api,i=0;it.get("hoverLayerThreshold")&&!v.node&&t.eachSeries(function(t){if(!t.preventUsingHoverLayer){var e=i._chartsMap[t.__viewId];e.__alive&&e.group.traverse(function(t){t.useHoverLayer=!0})}})}(n,t),Ec(n._zr.dom,t)}function Kd(e,i){Td(af,function(t){t(e,i)})}zd.resize=function(t){if(!this._disposed){this._zr.resize(t);var e=this._model;if(this._loadingFX&&this._loadingFX.resize(),e){var i=e.resetOption("media"),n=t&&t.silent;this[kd]=!0,i&&Gd(this),Vd.update.call(this),this[kd]=!1,Zd.call(this,n),Ud.call(this,n)}}},zd.showLoading=function(t,e){if(!this._disposed&&(Dd(t)&&(e=t,t=""),t=t||"default",this.hideLoading(),lf[t])){var i=lf[t](this._api,e),n=this._zr;this._loadingFX=i,n.add(i)}},zd.hideLoading=function(){this._disposed||(this._loadingFX&&this._zr.remove(this._loadingFX),this._loadingFX=null)},zd.makeActionFromEvent=function(t){var e=P({},t);return e.type=ef[t.type],e},zd.dispatchAction=function(t,e){this._disposed||(Dd(e)||(e={silent:!!e}),tf[t.type]&&this._model&&(this[kd]?this._pendingActions.push(t):(Hd.call(this,t,e.silent),e.flush?this._zr.flush(!0):!1!==e.flush&&v.browser.weChat&&this._throttledZrFlush(),Zd.call(this,e.silent),Ud.call(this,e.silent))))},zd.appendData=function(t){if(!this._disposed){var e=t.seriesIndex;this.getModel().getSeriesByIndex(e).appendData(t),this._scheduler.unfinished=!0}},zd.on=Od("on",!1),zd.off=Od("off",!1),zd.one=Od("one",!1);var $d=["click","dblclick","mouseover","mouseout","mousemove","mousedown","mouseup","globalout","contextmenu"];function Jd(t,e){var i=t.get("z"),n=t.get("zlevel");e.group.traverse(function(t){"group"!==t.type&&(null!=i&&(t.z=i),null!=n&&(t.zlevel=n))})}function Qd(){this.eventInfo}zd._initEvents=function(){Td($d,function(u){function t(t){var e,i=this.getModel(),n=t.target;if("globalout"===u)e={};else if(n&&null!=n.dataIndex){var o=n.dataModel||i.getSeriesByIndex(n.seriesIndex);e=o&&o.getDataParams(n.dataIndex,n.dataType,n)||{}}else n&&n.eventData&&(e=P({},n.eventData));if(e){var a=e.componentType,r=e.componentIndex;"markLine"!==a&&"markPoint"!==a&&"markArea"!==a||(a="series",r=e.seriesIndex);var s=a&&null!=r&&i.getComponent(a,r),l=s&&this["series"===s.mainType?"_chartsMap":"_componentsMap"][s.__viewId];e.event=t,e.type=u,this._ecEventProcessor.eventInfo={targetEl:n,packedEvent:e,model:s,view:l},this.trigger(u,e)}}t.zrEventfulCallAtLast=!0,this._zr.on(u,t,this)},this),Td(ef,function(t,e){this._messageCenter.on(e,function(t){this.trigger(e,t)},this)},this)},zd.isDisposed=function(){return this._disposed},zd.clear=function(){this._disposed||this.setOption({series:[]},!0)},zd.dispose=function(){if(!this._disposed){this._disposed=!0,Jo(this.getDom(),ff,"");var e=this._api,i=this._model;Td(this._componentsViews,function(t){t.dispose(i,e)}),Td(this._chartsViews,function(t){t.dispose(i,e)}),this._zr.dispose(),delete uf[this.id]}},b(Rd,Ct),Qd.prototype={constructor:Qd,normalizeQuery:function(t){var s={},l={},u={};if(R(t)){var e=Cd(t);s.mainType=e.main||null,s.subType=e.sub||null}else{var h=["Index","Name","Id"],c={name:1,dataIndex:1,dataType:1};E(t,function(t,e){for(var i=!1,n=0;nx[1]&&(x[1]=y)}e&&(this._nameList[d]=e[f])}this._rawCount=this._count=l,this._extent={},Kf(this)},jf._initDataFromProvider=function(t,e){if(!(e<=t)){for(var i,n=this._chunkSize,o=this._rawData,a=this._storage,r=this.dimensions,s=r.length,l=this._dimensionInfos,u=this._nameList,h=this._idList,c=this._rawExtent,d=this._nameRepeatCount={},f=this._chunkCount,p=0;pM[1]&&(M[1]=S)}if(!o.pure){var I=u[v];if(m&&null==I)if(null!=m.name)u[v]=I=m.name;else if(null!=i){var T=r[i],A=a[T][y];if(A){I=A[x];var D=l[T].ordinalMeta;D&&D.categories.length&&(I=D.categories[I])}}var C=null==m?null:m.id;null==C&&null!=I&&(d[I]=d[I]||0,0=this._rawCount||t<0)return-1;if(!this._indices)return t;var e=this._indices,i=e[t];if(null!=i&&it))return a;o=a-1}}return-1},jf.indicesOfNearest=function(t,e,i){var n=[];if(!this._storage[t])return n;null==i&&(i=1/0);for(var o=1/0,a=-1,r=0,s=0,l=this.count();st[I][1])&&(M=!1)}M&&(a[r++]=this.getRawIndex(m))}return rw[1]&&(w[1]=_)}}}return o},jf.downSample=function(t,e,i,n){for(var o=ip(this,[t]),a=o._storage,r=[],s=Math.floor(1/e),l=a[t],u=this.count(),h=this._chunkSize,c=o._rawExtent[t],d=new(Hf(this))(u),f=0,p=0;pc[1]&&(c[1]=x),d[f++]=_}return o._count=f,o._indices=d,o.getRawIndex=Qf,o},jf.getItemModel=function(t){var e=this.hostModel;return new Cl(this.getRawDataItem(t),e,e&&e.ecModel)},jf.diff=function(e){var i=this;return new kf(e?e.getIndices():[],this.getIndices(),function(t){return tp(e,t)},function(t){return tp(i,t)})},jf.getVisual=function(t){var e=this._visual;return e&&e[t]},jf.setVisual=function(t,e){if(zf(t))for(var i in t)t.hasOwnProperty(i)&&this.setVisual(i,t[i]);else this._visual=this._visual||{},this._visual[t]=e},jf.setLayout=function(t,e){if(zf(t))for(var i in t)t.hasOwnProperty(i)&&this.setLayout(i,t[i]);else this._layout[t]=e},jf.getLayout=function(t){return this._layout[t]},jf.getItemLayout=function(t){return this._itemLayouts[t]},jf.setItemLayout=function(t,e,i){this._itemLayouts[t]=i?P(this._itemLayouts[t]||{},e):e},jf.clearItemLayouts=function(){this._itemLayouts.length=0},jf.getItemVisual=function(t,e,i){var n=this._itemVisuals[t],o=n&&n[e];return null!=o||i?o:this.getVisual(e)},jf.setItemVisual=function(t,e,i){var n=this._itemVisuals[t]||{},o=this.hasItemVisual;if(this._itemVisuals[t]=n,zf(e))for(var a in e)e.hasOwnProperty(a)&&(n[a]=e[a],o[a]=!0);else n[e]=i,o[e]=!0},jf.clearAllVisual=function(){this._visual={},this._itemVisuals=[],this.hasItemVisual={}};function ap(t){t.seriesIndex=this.seriesIndex,t.dataIndex=this.dataIndex,t.dataType=this.dataType}function rp(t,e,i){Uu.isInstance(e)||(e=Uu.seriesDataToSource(e)),i=i||{},t=(t||[]).slice();for(var n=(i.dimsDef||[]).slice(),o=Q(),a=Q(),l=[],r=function(t,e,i,n){var o=Math.max(t.dimensionsDetectCount||1,e.length,i.length,n||0);return E(e,function(t){var e=t.dimsDef;e&&(o=Math.max(o,e.length))}),o}(e,t,n,i.dimCount),s=0;s=e[0]&&t<=e[1]},mp.prototype.normalize=function(t){var e=this._extent;return e[1]===e[0]?.5:(t-e[0])/(e[1]-e[0])},mp.prototype.scale=function(t){var e=this._extent;return t*(e[1]-e[0])+e[0]},mp.prototype.unionExtent=function(t){var e=this._extent;t[0]e[1]&&(e[1]=t[1])},mp.prototype.unionExtentFromData=function(t,e){this.unionExtent(t.getApproximateExtent(e))},mp.prototype.getExtent=function(){return this._extent.slice()},mp.prototype.setExtent=function(t,e){var i=this._extent;isNaN(t)||(i[0]=t),isNaN(e)||(i[1]=e)},mp.prototype.isBlank=function(){return this._isBlank},mp.prototype.setBlank=function(t){this._isBlank=t},mp.prototype.getLabel=null,oa(mp),ua(mp,{registerWhenExtend:!0}),vp.createByAxisModel=function(t){var e=t.option,i=e.data,n=i&&O(i,_p);return new vp({categories:n,needCollect:!n,deduplication:!1!==e.dedplication})};var yp=vp.prototype;function xp(t){return t._map||(t._map=Q(t.categories))}function _p(t){return z(t)&&null!=t.value?t.value:t+""}yp.getOrdinal=function(t){return xp(this).get(t)},yp.parseAndCollect=function(t){var e,i=this._needCollect;if("string"!=typeof t&&!i)return t;if(i&&!this._deduplication)return e=this.categories.length,this.categories[e]=t,e;var n=xp(this);return null==(e=n.get(t))&&(i?(e=this.categories.length,this.categories[e]=t,n.set(t,e)):e=NaN),e};var wp=mp.prototype,bp=mp.extend({type:"ordinal",init:function(t,e){t&&!L(t)||(t=new vp({categories:t})),this._ordinalMeta=t,this._extent=e||[0,t.categories.length-1]},parse:function(t){return"string"==typeof t?this._ordinalMeta.getOrdinal(t):Math.round(t)},contain:function(t){return t=this.parse(t),wp.contain.call(this,t)&&null!=this._ordinalMeta.categories[t]},normalize:function(t){return wp.normalize.call(this,this.parse(t))},scale:function(t){return Math.round(wp.scale.call(this,t))},getTicks:function(){for(var t=[],e=this._extent,i=e[0];i<=e[1];)t.push(i),i++;return t},getLabel:function(t){if(!this.isBlank())return this._ordinalMeta.categories[t]},count:function(){return this._extent[1]-this._extent[0]+1},unionExtentFromData:function(t,e){this.unionExtent(t.getApproximateExtent(e))},getOrdinalMeta:function(){return this._ordinalMeta},niceTicks:et,niceExtent:et});bp.create=function(){return new bp};var Sp=zl;function Mp(t){return Gl(t)+2}function Ip(t,e,i){t[e]=Math.max(Math.min(t[e],i[1]),i[0])}function Tp(t,e){isFinite(t[0])||(t[0]=e[0]),isFinite(t[1])||(t[1]=e[1]),Ip(t,0,e),Ip(t,1,e),t[0]>t[1]&&(t[0]=t[1])}var Ap=zl,Dp=mp.extend({type:"interval",_interval:0,_intervalPrecision:2,setExtent:function(t,e){var i=this._extent;isNaN(t)||(i[0]=parseFloat(t)),isNaN(e)||(i[1]=parseFloat(e))},unionExtent:function(t){var e=this._extent;t[0]e[1]&&(e[1]=t[1]),Dp.prototype.setExtent.call(this,e[0],e[1])},getInterval:function(){return this._interval},setInterval:function(t){this._interval=t,this._niceExtent=this._extent.slice(),this._intervalPrecision=Mp(t)},getTicks:function(t){var e=this._interval,i=this._extent,n=this._niceExtent,o=this._intervalPrecision,a=[];if(!e)return a;i[0]s&&(t?a.push(Ap(s+e,o)):a.push(i[1])),a},getMinorTicks:function(t){for(var e=this.getTicks(!0),i=[],n=this.getExtent(),o=1;on[0]&&h>>1;t[o][1]>1^-(1&s),l=l>>1^-(1&l),o=s+=o,a=l+=a,n.push([s/i,l/i])}return n}Ag.prototype={constructor:Ag,properties:null,getBoundingRect:function(){var t=this._rect;if(t)return t;for(var e=Number.MAX_VALUE,i=[e,e],n=[-e,-e],o=[],a=[],r=this.geometries,s=0;ss[1];d(e[0].coord,s[0])&&(n?e[0].coord=s[0]:e.shift());n&&d(s[0],e[0].coord)&&e.unshift({coord:s[0]});d(s[1],a.coord)&&(n?a.coord=s[1]:e.pop());n&&d(a.coord,s[1])&&e.push({coord:s[1]});function d(t,e){return t=zl(t),e=zl(e),c?en[0]&&(n[0]=a[0]),a[1]>n[1]&&(n[1]=a[1])}return{min:e?i:n,max:e?n:i}}var xm=Ar.extend({type:"ec-polyline",shape:{points:[],smooth:0,smoothConstraint:!0,smoothMonotone:null,connectNulls:!1},style:{fill:null,stroke:"#000"},brush:Xr(Ar.prototype.brush),buildPath:function(t,e){var i=e.points,n=0,o=i.length,a=ym(i,e.smoothConstraint);if(e.connectNulls){for(;0n)return!1;return!0}(a,e))){var r=e.mapDimension(a.dim),s={};return E(a.getViewLabels(),function(t){s[t.tickValue]=1}),function(t){return!s.hasOwnProperty(e.get(r,t))}}}}function Cm(t,e,i){if("cartesian2d"!==t.type)return bm(t,e,i);var n=t.getBaseAxis().isHorizontal(),o=wm(t,e,i);if(!i.get("clip",!0)){var a=o.shape,r=Math.max(a.width,a.height);n?(a.y-=r,a.height+=2*r):(a.x-=r,a.width+=2*r)}return o}_c.extend({type:"line",init:function(){var t=new Ci,e=new im;this.group.add(e.group),this._symbolDraw=e,this._lineGroup=t},render:function(t,e,i){var n=t.coordinateSystem,o=this.group,a=t.getData(),r=t.getModel("lineStyle"),s=t.getModel("areaStyle"),l=a.mapArray(a.getItemLayout),u="polar"===n.type,h=this._coordSys,c=this._symbolDraw,d=this._polyline,f=this._polygon,p=this._lineGroup,g=t.get("animation"),m=!s.isEmpty(),v=s.get("origin"),y=function(t,e,i){if(!i.valueDim)return[];for(var n=[],o=0,a=e.count();oh[c-1].coord&&(h.reverse(),d.reverse());var f=h[0].coord-10,p=h[c-1].coord+10,g=p-f;if(g<.001)return"transparent";E(h,function(t){t.offset=(t.coord-f)/g}),h.push({offset:c?h[c-1].offset:.5,color:d[1]||"transparent"}),h.unshift({offset:c?h[0].offset:.5,color:d[0]||"transparent"});var m=new gs(0,0,0,0,h,!0);return m[n]=f,m[n+"2"]=p,m}}}(a,n)||a.getVisual("color");d.useStyle(D(r.getLineStyle(),{fill:"none",stroke:M,lineJoin:"bevel"}));var I=t.get("smooth");if(I=Tm(t.get("smooth")),d.setShape({smooth:I,smoothMonotone:t.get("smoothMonotone"),connectNulls:t.get("connectNulls")}),f){var T=a.getCalculationInfo("stackedOnSeries"),A=0;f.useStyle(D(s.getAreaStyle(),{fill:M,opacity:.7,lineJoin:"bevel"})),T&&(A=Tm(T.get("smooth"))),f.setShape({smooth:I,stackedOnSmooth:A,smoothMonotone:t.get("smoothMonotone"),connectNulls:t.get("connectNulls")})}this._data=a,this._coordSys=n,this._stackedOnPoints=y,this._points=l,this._step=S,this._valueOrigin=v},dispose:function(){},highlight:function(t,e,i,n){var o=t.getData(),a=Yo(o,n);if(!(a instanceof Array)&&null!=a&&0<=a){var r=o.getItemGraphicEl(a);if(!r){var s=o.getItemLayout(a);if(!s)return;if(this._clipShapeForSymbol&&!this._clipShapeForSymbol.contain(s[0],s[1]))return;(r=new Xg(o,a)).position=s,r.setZ(t.get("zlevel"),t.get("z")),r.ignore=isNaN(s[0])||isNaN(s[1]),r.__temp=!0,o.setItemGraphicEl(a,r),r.stopSymbolAnimation(!0),this.group.add(r)}r.highlight()}else _c.prototype.highlight.call(this,t,e,i,n)},downplay:function(t,e,i,n){var o=t.getData(),a=Yo(o,n);if(null!=a&&0<=a){var r=o.getItemGraphicEl(a);r&&(r.__temp?(o.setItemGraphicEl(a,null),this.group.remove(r)):r.downplay())}else _c.prototype.downplay.call(this,t,e,i,n)},_newPolyline:function(t){var e=this._polyline;return e&&this._lineGroup.remove(e),e=new xm({shape:{points:t},silent:!0,z2:10}),this._lineGroup.add(e),this._polyline=e},_newPolygon:function(t,e){var i=this._polygon;return i&&this._lineGroup.remove(i),i=new _m({shape:{points:t,stackedOnPoints:e},silent:!0}),this._lineGroup.add(i),this._polygon=i},_updateAnimation:function(t,e,i,n,o,a){var r=this._polyline,s=this._polygon,l=t.hostModel,u=function(t,e,i,n,o,a,r,s){for(var l=function(t,e){var i=[];return e.diff(t).add(function(t){i.push({cmd:"+",idx:t})}).update(function(t,e){i.push({cmd:"=",idx:e,idx1:t})}).remove(function(t){i.push({cmd:"-",idx:t})}).execute(),i}(t,e),u=[],h=[],c=[],d=[],f=[],p=[],g=[],m=sm(o,e,r),v=sm(a,t,s),y=0;ye&&(e=t[i]);return isFinite(e)?e:NaN},min:function(t){for(var e=1/0,i=0;ie[1]&&e.reverse(),e},getOtherAxis:function(){this.grid.getOtherAxis()},pointToData:function(t,e){return this.coordToData(this.toLocalCoord(t["x"===this.dim?0:1]),e)},toLocalCoord:null,toGlobalCoord:null},w(zm,Gg);var Bm={show:!0,zlevel:0,z:0,inverse:!1,name:"",nameLocation:"end",nameRotate:null,nameTruncate:{maxWidth:null,ellipsis:"...",placeholder:"."},nameTextStyle:{},nameGap:15,silent:!1,triggerEvent:!1,tooltip:{show:!1},axisPointer:{},axisLine:{show:!0,onZero:!0,onZeroAxisIndex:null,lineStyle:{color:"#333",width:1,type:"solid"},symbol:["none","none"],symbolSize:[10,15]},axisTick:{show:!0,inside:!1,length:5,lineStyle:{width:1}},axisLabel:{show:!0,inside:!1,rotate:0,showMinLabel:null,showMaxLabel:null,margin:8,fontSize:12},splitLine:{show:!0,lineStyle:{color:["#ccc"],width:1,type:"solid"}},splitArea:{show:!1,areaStyle:{color:["rgba(250,250,250,0.3)","rgba(200,200,200,0.3)"]}}},Vm={};Vm.categoryAxis=m({boundaryGap:!0,deduplication:null,splitLine:{show:!1},axisTick:{alignWithLabel:!1,interval:"auto"},axisLabel:{interval:"auto"}},Bm),Vm.valueAxis=m({boundaryGap:[0,0],splitNumber:5,minorTick:{show:!1,splitNumber:5,length:3,lineStyle:{}},minorSplitLine:{show:!1,lineStyle:{color:"#eee",width:1}}},Bm),Vm.timeAxis=D({scale:!0,min:"dataMin",max:"dataMax"},Vm.valueAxis),Vm.logAxis=D({scale:!0,logBase:10},Vm.valueAxis);function Gm(a,t,r,e){E(Fm,function(o){t.extend({type:a+"Axis."+o,mergeDefaultAndTheme:function(t,e){var i=this.layoutMode,n=i?Iu(t):{};m(t,e.getTheme().get(o+"Axis")),m(t,this.getDefaultOption()),t.type=r(a,t),i&&Mu(t,n,i)},optionUpdated:function(){"category"===this.option.type&&(this.__ordinalMeta=vp.createByAxisModel(this))},getCategories:function(t){var e=this.option;if("category"===e.type)return t?e.data:this.__ordinalMeta.categories},getOrdinalMeta:function(){return this.__ordinalMeta},defaultOption:p([{},Vm[o+"Axis"],e],!0)})}),ku.registerSubTypeDefaulter(a+"Axis",T(r,a))}var Fm=["value","category","time","log"],Wm=ku.extend({type:"cartesian2dAxis",axis:null,init:function(){Wm.superApply(this,"init",arguments),this.resetRange()},mergeOption:function(){Wm.superApply(this,"mergeOption",arguments),this.resetRange()},restoreData:function(){Wm.superApply(this,"restoreData",arguments),this.resetRange()},getCoordSysModel:function(){return this.ecModel.queryComponents({mainType:"grid",index:this.option.gridIndex,id:this.option.gridId})[0]}});function Hm(t,e){return e.type||(e.data?"category":"value")}m(Wm.prototype,dg);var Zm={offset:0};function Um(t,e){return t.getCoordSysModel()===e}function Xm(t,e,i){this._coordsMap={},this._coordsList=[],this._axesMap={},this._axesList=[],this._initCartesian(t,e,i),this.model=t}Gm("x",Wm,Hm,Zm),Gm("y",Wm,Hm,Zm),ku.extend({type:"grid",dependencies:["xAxis","yAxis"],layoutMode:"box",coordinateSystem:null,defaultOption:{show:!1,zlevel:0,z:0,left:"10%",top:60,right:"10%",bottom:60,containLabel:!1,backgroundColor:"rgba(0,0,0,0)",borderWidth:1,borderColor:"#ccc"}});var Ym=Xm.prototype;function jm(t,e,i,n){i.getAxesOnZeroOf=function(){return o?[o]:[]};var o,a=t[e],r=i.model,s=r.get("axisLine.onZero"),l=r.get("axisLine.onZeroAxisIndex");if(s){if(null!=l)qm(a[l])&&(o=a[l]);else for(var u in a)if(a.hasOwnProperty(u)&&qm(a[u])&&!n[h(a[u])]){o=a[u];break}o&&(n[h(o)]=!0)}function h(t){return t.dim+"_"+t.index}}function qm(t){return t&&"category"!==t.type&&"time"!==t.type&&function(t){var e=t.scale.getExtent(),i=e[0],n=e[1];return!(0u[1]?-1:1,c=["start"===a?u[0]-h*l:"end"===a?u[1]+h*l:(u[0]+u[1])/2,sv(a)?t.labelOffset+r*l:0],d=e.get("nameRotate");null!=d&&(d=d*tv/180),sv(a)?n=nv(t.rotation,null!=d?d:t.rotation,r):(n=function(t,e,i,n){var o,a,r=Zl(i-t.rotation),s=n[0]>n[1],l="start"===e&&!s||"start"!==e&&s;o=Ul(r-tv/2)?(a=l?"bottom":"top","center"):Ul(r-1.5*tv)?(a=l?"top":"bottom","center"):(a="middle",r<1.5*tv&&tv/2l[1]&&l.reverse(),(null==r||r>l[1])&&(r=l[1]),r=i.r0}}});var ny=Math.PI/180;function oy(o,t,e,i,n,a,r,s,l,u){function h(t,e,i){for(var n=t;nl+r);n++)if(o[n].y+=i,to[n].y+o[n].height)return void c(n,i/2);c(e-1,i/2)}function c(t,e){for(var i=t;0<=i&&!(o[i].y-eo[i-1].y+o[i-1].height));i--);}function d(t,e,i,n,o,a){for(var r=e?Number.MAX_VALUE:0,s=0,l=t.length;s=e?v.push(o[y]):m.push(o[y]);d(m,!1,t,e,i,n),d(v,!0,t,e,i,n)}function ay(t){return"center"===t.position}function ry(L,k,P,t,N,e){var O,E,R=L.getData(),z=[],B=!1,V=(L.get("minShowLabelAngle")||0)*ny;R.each(function(t){var e=R.getItemLayout(t),i=R.getItemModel(t),n=i.getModel("label"),o=n.get("position")||i.get("emphasis.label.position"),a=n.get("distanceToLabelLine"),r=n.get("alignTo"),s=Rl(n.get("margin"),P),l=n.get("bleedMargin"),u=n.getFont(),h=i.getModel("labelLine"),c=h.get("length");c=Rl(c,P);var d=h.get("length2");if(d=Rl(d,P),!(e.anglei[0]&&isFinite(h)&&isFinite(i[0]););else{var l=o.getTicks().length-1;c"+O(t,function(t,e){var i=o.get(o.mapDimension(t.dim),n);return au(t.name+" : "+i)}).join("
    ")},getTooltipPosition:function(t){if(null!=t)for(var e=this.getData(),i=this.coordinateSystem,n=e.getValues(O(i.dimensions,function(t){return e.mapDimension(t)}),t,!0),o=0,a=n.length;o"+au(n+" : "+i)},getTooltipPosition:function(t){if(null!=t){var e=this.getData().getName(t),i=this.coordinateSystem,n=i.getRegion(e);return n&&i.dataToPoint(n.center)}},setZoom:function(t){this.option.zoom=t},setCenter:function(t){this.option.center=t},defaultOption:{zlevel:0,z:2,coordinateSystem:"geo",map:"",left:"center",top:"center",aspectScale:.75,showLegendSymbol:!0,dataRangeHoverLink:!0,boundingCoords:null,center:null,zoom:1,scaleLimit:null,label:{show:!1,color:"#000"},itemStyle:{borderWidth:.5,borderColor:"#444",areaColor:"#eee"},emphasis:{label:{show:!0,color:"rgb(100,0,0)"},itemStyle:{areaColor:"rgba(255,215,0,0.8)"}},nameProperty:"name"}}),jv);var Ry="\0_ec_interaction_mutex";function zy(t,e){return!!By(t)[e]}function By(t){return t[Ry]||(t[Ry]={})}function Vy(i){this.pointerChecker,this._zr=i,this._opt={};var t=A,n=t(Gy,this),o=t(Fy,this),a=t(Wy,this),r=t(Hy,this),s=t(Zy,this);Ct.call(this),this.setPointerChecker=function(t){this.pointerChecker=t},this.enable=function(t,e){this.disable(),this._opt=D(k(e)||{},{zoomOnMouseWheel:!0,moveOnMouseMove:!0,moveOnMouseWheel:!1,preventDefaultMouseMove:!0}),null==t&&(t=!0),!0!==t&&"move"!==t&&"pan"!==t||(i.on("mousedown",n),i.on("mousemove",o),i.on("mouseup",a)),!0!==t&&"scale"!==t&&"zoom"!==t||(i.on("mousewheel",r),i.on("pinch",s))},this.disable=function(){i.off("mousedown",n),i.off("mousemove",o),i.off("mouseup",a),i.off("mousewheel",r),i.off("pinch",s)},this.dispose=this.disable,this.isDragging=function(){return this._dragging},this.isPinching=function(){return this._pinching}}function Gy(t){if(!(Yt(t)||t.target&&t.target.draggable)){var e=t.offsetX,i=t.offsetY;this.pointerChecker&&this.pointerChecker(t,e,i)&&(this._x=e,this._y=i,this._dragging=!0)}}function Fy(t){if(this._dragging&&Yy("moveOnMouseMove",t,this._opt)&&"pinch"!==t.gestureEvent&&!zy(this._zr,"globalPan")){var e=t.offsetX,i=t.offsetY,n=this._x,o=this._y,a=e-n,r=i-o;this._x=e,this._y=i,this._opt.preventDefaultMouseMove&&Xt(t.event),Xy(this,"pan","moveOnMouseMove",t,{dx:a,dy:r,oldX:n,oldY:o,newX:e,newY:i})}}function Wy(t){Yt(t)||(this._dragging=!1)}function Hy(t){var e=Yy("zoomOnMouseWheel",t,this._opt),i=Yy("moveOnMouseWheel",t,this._opt),n=t.wheelDelta,o=Math.abs(n),a=t.offsetX,r=t.offsetY;if(0!==n&&(e||i)){if(e){var s=3e&&(e=n.height)}this.height=e+1},getNodeById:function(t){if(this.getId()===t)return this;for(var e=0,i=this.children,n=i.length;ei&&(i=t.depth)});var a=t.expandAndCollapse&&0<=t.initialTreeDepth?t.initialTreeDepth:i;return o.root.eachNode("preorder",function(t){var e=t.hostTree.data.getRawDataItem(t.dataIndex);t.isExpand=e&&null!=e.collapsed?!e.collapsed:t.depth<=a}),o.data},getOrient:function(){var t=this.get("orient");return"horizontal"===t?t="LR":"vertical"===t&&(t="TB"),t},setZoom:function(t){this.option.zoom=t},setCenter:function(t){this.option.center=t},formatTooltip:function(t){for(var e=this.getData().tree,i=e.root.children[0],n=e.getNodeByDataIndex(t),o=n.getValue(),a=n.name;n&&n!==i;)a=n.parentNode.name+"."+a,n=n.parentNode;return au(a+(isNaN(o)||null==o?"":" : "+o))},defaultOption:{zlevel:0,z:2,coordinateSystem:"view",left:"12%",top:"12%",right:"12%",bottom:"12%",layout:"orthogonal",edgeShape:"curve",edgeForkPosition:"50%",roam:!1,nodeScaleRatio:.4,center:null,zoom:1,orient:"LR",symbol:"emptyCircle",symbolSize:7,expandAndCollapse:!0,initialTreeDepth:2,lineStyle:{color:"#ccc",width:1.5,curveness:.5},itemStyle:{color:"lightsteelblue",borderColor:"#c23531",borderWidth:1.5},label:{show:!0,color:"#555"},leaves:{label:{show:!0}},animationEasing:"linear",animationDuration:700,animationDurationUpdate:1e3}});var zx=Cs({shape:{parentPoint:[],childPoints:[],orient:"",forkPosition:""},style:{stroke:"#000",fill:null},buildPath:function(t,e){var i=e.childPoints,n=i.length,o=e.parentPoint,a=i[0],r=i[n-1];if(1===n)return t.moveTo(o[0],o[1]),void t.lineTo(a[0],a[1]);var s=e.orient,l="TB"===s||"BT"===s?0:1,u=1-l,h=Rl(e.forkPosition,1),c=[];c[l]=o[l],c[u]=o[u]+(r[u]-o[u])*h,t.moveTo(o[0],o[1]),t.lineTo(c[0],c[1]),t.moveTo(a[0],a[1]),c[l]=a[l],t.lineTo(c[0],c[1]),c[l]=r[l],t.lineTo(c[0],c[1]),t.lineTo(r[0],r[1]);for(var d=1;dx.x)||(m-=Math.PI);var b=v?"left":"right",S=a.labelModel.get("rotate"),M=S*(Math.PI/180);g.setStyle({textPosition:a.labelModel.get("position")||b,textRotation:null==S?-m:M,textOrigin:"center",verticalAlign:"middle"})}!function(t,e,i,n,o,a,r,s,l){var u=l.edgeShape,h=n.__edge;if("curve"===u)e.parentNode&&e.parentNode!==i&&cl(h=h||(n.__edge=new ds({shape:Wx(l,o,o),style:D({opacity:0,strokeNoScale:!0},l.lineStyle)})),{shape:Wx(l,a,r),style:{opacity:1}},t);else if("polyline"===u&&"orthogonal"===l.layout&&e!==i&&e.children&&0!==e.children.length&&!0===e.isExpand){for(var c=e.children,d=[],f=0;fh.getLayout().x&&(h=t),t.depth>c.depth&&(c=t)});var d=u===h?1:r(u,h)/2,f=d-u.getLayout().x,p=0,g=0,m=0,v=0;if("radial"===n)p=o/(h.getLayout().x+d+f),g=a/(c.depth-1||1),Hx(l,function(t){m=(t.getLayout().x+f)*p,v=(t.depth-1)*g;var e=Px(m,v);t.setLayout({x:e.x,y:e.y,rawX:m,rawY:v},!0)});else{var y=t.getOrient();"RL"===y||"LR"===y?(g=a/(h.getLayout().x+d+f),p=o/(c.depth-1||1),Hx(l,function(t){v=(t.getLayout().x+f)*g,m="LR"===y?(t.depth-1)*p:o-(t.depth-1)*p,t.setLayout({x:m,y:v},!0)})):"TB"!==y&&"BT"!==y||(p=o/(h.getLayout().x+d+f),g=a/(c.depth-1||1),Hx(l,function(t){m=(t.getLayout().x+f)*p,v="TB"===y?(t.depth-1)*g:a-(t.depth-1)*g,t.setLayout({x:m,y:v},!0)}))}}}(t,e)})}),sc.extend({type:"series.treemap",layoutMode:"box",dependencies:["grid","polar"],preventUsingHoverLayer:!0,_viewRoot:null,defaultOption:{progressive:0,left:"center",top:"middle",right:null,bottom:null,width:"80%",height:"80%",sort:!0,clipWindow:"origin",squareRatio:.5*(1+Math.sqrt(5)),leafDepth:null,drillDownIcon:"▶",zoomToNodeRatio:.1024,roam:!0,nodeClick:"zoomToNode",animation:!0,animationDurationUpdate:900,animationEasing:"quinticInOut",breadcrumb:{show:!0,height:22,left:"center",top:"bottom",emptyItemWidth:25,itemStyle:{color:"rgba(0,0,0,0.7)",borderColor:"rgba(255,255,255,0.7)",borderWidth:1,shadowColor:"rgba(150,150,150,1)",shadowBlur:3,shadowOffsetX:0,shadowOffsetY:0,textStyle:{color:"#fff"}},emphasis:{textStyle:{}}},label:{show:!0,distance:0,padding:5,position:"inside",color:"#fff",ellipsis:!0},upperLabel:{show:!1,position:[0,"50%"],height:20,color:"#fff",ellipsis:!0,verticalAlign:"middle"},itemStyle:{color:null,colorAlpha:null,colorSaturation:null,borderWidth:0,gapWidth:0,borderColor:"#fff",borderColorSaturation:null},emphasis:{upperLabel:{show:!0,position:[0,"50%"],color:"#fff",ellipsis:!0,verticalAlign:"middle"}},visualDimension:0,visualMin:null,visualMax:null,color:[],colorAlpha:null,colorSaturation:null,colorMappingBy:"index",visibleMin:10,childrenVisibleMin:null,levels:[]},getInitialData:function(t,e){var i={name:t.name,children:t.data};!function i(t){var n=0;E(t.children,function(t){i(t);var e=t.value;L(e)&&(e=e[0]),n+=e});var e=t.value;L(e)&&(e=e[0]);null!=e&&!isNaN(e)||(e=n);e<0&&(e=0);L(t.value)?t.value[0]=e:t.value=e}(i);var n=t.levels||[],o=O((n=t.levels=function(t,e){var n,i=e.get("color");if(!i)return;if(E(t=t||[],function(t){var e=new Cl(t),i=e.get("color");(e.get("itemStyle.color")||i&&"none"!==i)&&(n=!0)}),!n){(t[0]||(t[0]={})).color=i.slice()}return t}(n,e))||[],function(t){return new Cl(t,this,e)},this),a=Ax.createTree(i,this,null,function(t){t.wrapMethod("getItemModel",function(t,e){var i=a.getNodeByDataIndex(e),n=o[i.depth];return n&&(t.parentModel=n),t})});return a.data},optionUpdated:function(){this.resetViewRoot()},formatTooltip:function(t){var e=this.getData(),i=this.getRawValue(t),n=L(i)?tu(i[0]):tu(i);return au(e.getName(t)+": "+n)},getDataParams:function(t){var e=sc.prototype.getDataParams.apply(this,arguments),i=this.getData().tree.getNodeByDataIndex(t);return e.treePathInfo=Yx(i,this),e},setLayoutInfo:function(t){this.layoutInfo=this.layoutInfo||{},P(this.layoutInfo,t)},mapIdToIndex:function(t){var e=this._idIndexMap;e||(e=this._idIndexMap=Q(),this._idIndexMapCount=0);var i=e.get(t);return null==i&&e.set(t,i=this._idIndexMapCount++),i},getViewRoot:function(){return this._viewRoot},resetViewRoot:function(t){t?this._viewRoot=t:t=this._viewRoot;var e=this.getRawData().tree.root;t&&(t===e||e.contains(t))||(this._viewRoot=e)}});var jx=5;function qx(t){this.group=new Ci,t.add(this.group)}function Kx(t,e,i,n,o,a){var r=[[o?t:t-jx,e],[t+i,e],[t+i,e+n],[o?t:t-jx,e+n]];return a||r.splice(2,0,[t+i+jx,e+n/2]),o||r.push([t,e+n/2]),r}qx.prototype={constructor:qx,render:function(t,e,i,n){var o=t.getModel("breadcrumb"),a=this.group;if(a.removeAll(),o.get("show")&&i){var r=o.getModel("itemStyle"),s=r.getModel("textStyle"),l={pos:{left:o.get("left"),right:o.get("right"),top:o.get("top"),bottom:o.get("bottom")},box:{width:e.getWidth(),height:e.getHeight()},emptyItemWidth:o.get("emptyItemWidth"),totalWidth:0,renderList:[]};this._prepare(i,l,s),this._renderContent(t,l,r,s,n),Su(a,l.pos,l.box)}},_prepare:function(t,e,i){for(var n=t;n;n=n.parentNode){var o=n.getModel().get("name"),a=i.getTextRect(o),r=Math.max(a.width+16,e.emptyItemWidth);e.totalWidth+=r+8,e.renderList.push({node:n,text:o,width:r})}},_renderContent:function(t,e,i,n,o){for(var a,r,s=0,l=e.emptyItemWidth,u=t.get("breadcrumb.height"),h=function(t,e,i){var n=e.width,o=e.height,a=Rl(t.x,n),r=Rl(t.y,o),s=Rl(t.x2,n),l=Rl(t.y2,o);return(isNaN(a)||isNaN(parseFloat(t.x)))&&(a=0),(isNaN(s)||isNaN(parseFloat(t.x2)))&&(s=n),(isNaN(r)||isNaN(parseFloat(t.y)))&&(r=0),(isNaN(l)||isNaN(parseFloat(t.y2)))&&(l=o),i=iu(i||0),{width:Math.max(s-a-i[1]-i[3],0),height:Math.max(l-r-i[0]-i[2],0)}}(e.pos,e.box),c=e.totalWidth,d=e.renderList,f=d.length-1;0<=f;f--){var p=d[f],g=p.node,m=p.width,v=p.text;c>h.width&&(c-=m-l,m=l,v=null);var y=new Qr({shape:{points:Kx(s,0,m,u,f===d.length-1,0===f)},style:D(i.getItemStyle(),{lineJoin:"bevel",text:v,textFill:n.getTextColor(),textFont:n.getFont()}),z:10,onclick:T(o,g)});this.group.add(y),a=t,r=g,y.eventData={componentType:"series",componentSubType:"treemap",componentIndex:a.componentIndex,seriesIndex:a.componentIndex,seriesName:a.name,seriesType:"treemap",selfType:"breadcrumb",nodeData:{dataIndex:r&&r.dataIndex,name:r&&r.name},treePathInfo:r&&Yx(r,a)},s+=m+8}},remove:function(){this.group.removeAll()}};function $x(t){var e=s_(t);return e.stroke=e.fill=e.lineWidth=null,e}var Jx=A,Qx=Ci,t_=rs,e_=E,i_=["label"],n_=["emphasis","label"],o_=["upperLabel"],a_=["emphasis","upperLabel"],r_=10,s_=ha([["fill","color"],["stroke","strokeColor"],["lineWidth","strokeWidth"],["shadowBlur"],["shadowOffsetX"],["shadowOffsetY"],["shadowColor"]]);function l_(h,r,s,l,u,e,c,t,i,n){if(c){var d=c.getLayout(),o=h.getData();if(o.setItemGraphicEl(c.dataIndex,null),d&&d.isInView){var f=d.width,p=d.height,g=d.borderWidth,m=d.invisible,v=c.getRawIndex(),y=t&&t.getRawIndex(),a=c.viewChildren,x=d.upperHeight,_=a&&a.length,w=c.getModel("itemStyle"),b=c.getModel("emphasis.itemStyle"),S=L("nodeGroup",Qx);if(S){if(i.add(S),S.attr("position",[d.x||0,d.y||0]),S.__tmNodeWidth=f,S.__tmNodeHeight=p,d.isAboveViewRoot)return S;var M=c.getModel(),I=L("background",t_,n,1);if(I&&function(t,e,i){if(e.dataIndex=c.dataIndex,e.seriesIndex=h.seriesIndex,e.setShape({x:0,y:0,width:f,height:p}),m)A(e);else{e.invisible=!1;var n=c.getVisual("borderColor",!0),o=b.get("borderColor"),a=$x(w);a.fill=n;var r=s_(b);if(r.fill=o,i){var s=f-2*g;D(a,r,n,s,x,{x:g,y:0,width:s,height:x})}else a.text=r.text=null;e.setStyle(a),Us(e,r)}t.add(e)}(S,I,_&&d.upperLabelHeight),_)Qs(S)&&Js(S,!1),I&&(Js(I,!0),o.setItemGraphicEl(c.dataIndex,I));else{var T=L("content",t_,n,2);T&&function(t,e){e.dataIndex=c.dataIndex,e.seriesIndex=h.seriesIndex;var i=Math.max(f-2*g,0),n=Math.max(p-2*g,0);if(e.culling=!0,e.setShape({x:g,y:g,width:i,height:n}),m)A(e);else{e.invisible=!1;var o=c.getVisual("color",!0),a=$x(w);a.fill=o;var r=s_(b);D(a,r,o,i,n),e.setStyle(a),Us(e,r)}t.add(e)}(S,T),I&&Qs(I)&&Js(I,!1),Js(S,!0),o.setItemGraphicEl(c.dataIndex,S)}return S}}}function A(t){t.invisible||e.push(t)}function D(t,e,i,n,o,a){var r=M.get("name"),s=M.getModel(a?o_:i_),l=M.getModel(a?a_:n_),u=s.getShallow("show");el(t,e,s,l,{defaultText:u?r:null,autoColor:i,isRectText:!0,labelFetcher:h,labelDataIndex:c.dataIndex,labelProp:a?"upperLabel":"label"}),C(t,a,d),C(e,a,d),a&&(t.textRect=k(a)),t.truncate=u&&s.get("ellipsis")?{outerWidth:n,outerHeight:o,minChar:2}:null}function C(t,e,i){var n=t.text;if(!e&&i.isLeafRoot&&null!=n){var o=h.get("drillDownIcon",!0);t.text=o?o+" "+n:n}}function L(t,e,i,n){var o=null!=y&&s[t][y],a=u[t];return o?(s[t][y]=null,function(t,e,i){(t[v]={}).old="nodeGroup"===i?e.position.slice():P({},e.shape)}(a,o,t)):m||((o=new e({z:function(t,e){var i=t*r_+e;return(i-1)/i}(i,n)})).__tmDepth=i,function(t,e,i){var n=t[v]={},o=c.parentNode;if(o&&(!l||"drillDown"===l.direction)){var a=0,r=0,s=u.background[o.getRawIndex()];!l&&s&&s.old&&(a=s.old.width,r=s.old.height),n.old="nodeGroup"===i?[0,r]:{x:a,y:r,width:0,height:0}}n.fadein="nodeGroup"!==i}(a,0,o.__tmStorageName=t)),r[t][v]=o}}Cf({type:"treemap",init:function(t,e){this._containerGroup,this._storage={nodeGroup:[],background:[],content:[]},this._oldTree,this._breadcrumb,this._controller,this._state="ready"},render:function(t,e,i,n){if(!(_(e.findComponents({mainType:"series",subType:"treemap",query:n}),t)<0)){this.seriesModel=t,this.api=i,this.ecModel=e;var o=Zx(n,["treemapZoomToNode","treemapRootToNode"],t),a=n&&n.type,r=t.layoutInfo,s=!this._oldTree,l=this._storage,u="treemapRootToNode"===a&&o&&l?{rootNodeGroup:l.nodeGroup[o.node.getRawIndex()],direction:n.direction}:null,h=this._giveContainerGroup(r),c=this._doRender(h,t,u);s||a&&"treemapZoomToNode"!==a&&"treemapRootToNode"!==a?c.renderFinally():this._doAnimation(h,c,t,u),this._resetController(i),this._renderBreadcrumb(t,i,o)}},_giveContainerGroup:function(t){var e=this._containerGroup;return e||(e=this._containerGroup=new Qx,this._initEvents(e),this.group.add(e)),e.attr("position",[t.x,t.y]),e},_doRender:function(t,e,i){var n=e.getData().tree,o=this._oldTree,a={nodeGroup:[],background:[],content:[]},r={nodeGroup:[],background:[],content:[]},s=this._storage,l=[],c=T(l_,e,r,s,i,a,l);!function a(r,s,l,u,h){u?e_(s=r,function(t,e){t.isRemoved()||i(e,e)}):new kf(s,r,t,t).add(i).update(i).remove(T(i,null)).execute();function t(t){return t.getId()}function i(t,e){var i=null!=t?r[t]:null,n=null!=e?s[e]:null,o=c(i,n,l,h);o&&a(i&&i.viewChildren||[],n&&n.viewChildren||[],o,u,h+1)}}(n.root?[n.root]:[],o&&o.root?[o.root]:[],t,n===o||!o,0);var u,h,d=(h={nodeGroup:[],background:[],content:[]},(u=s)&&e_(u,function(t,e){var i=h[e];e_(t,function(t){t&&(i.push(t),t.__tmWillDelete=1)})}),h);return this._oldTree=n,this._storage=r,{lastsForAnimation:a,willDeleteEls:d,renderFinally:function(){e_(d,function(t){e_(t,function(t){t.parent&&t.parent.remove(t)})}),e_(l,function(t){t.invisible=!0,t.dirty()})}}},_doAnimation:function(t,a,e,s){if(e.get("animation")){var l=e.get("animationDurationUpdate"),u=e.get("animationEasing"),h=function(){var a,r=[],s={};return{add:function(t,e,i,n,o){return R(n)&&(o=n,n=0),!s[t.id]&&(s[t.id]=1,r.push({el:t,target:e,time:i,delay:n,easing:o}),!0)},done:function(t){return a=t,this},start:function(){for(var t=r.length,e=0,i=r.length;e=r.length||t===r[t.depth]){var i=R_(l,c,t,e,y,s);n(t,i,o,a,r,s)}})}else p=P_(c),t.setVisual("color",p)}(a,{},O(o.levelModels,function(t){return t?t.get(C_):null}),r,t.getViewRoot().getAncestors(),t)}};function k_(i,n,o,a){var r=P({},n);return E(["color","colorAlpha","colorSaturation"],function(t){var e=i.get(t,!0);null==e&&o&&(e=o[t]),null==e&&(e=n[t]),null==e&&(e=a.get(t)),null!=e&&(r[t]=e)}),r}function P_(t){var e=N_(t,"color");if(e){var i=N_(t,"colorAlpha"),n=N_(t,"colorSaturation");return n&&(e=qe(e,null,null,n)),i&&(e=Ke(e,i)),e}}function N_(t,e){var i=t[e];if(null!=i&&"none"!==i)return i}function O_(t,e,i,n,o,a){if(a&&a.length){var r=E_(e,"color")||null!=o.color&&"none"!==o.color&&(E_(e,"colorAlpha")||E_(e,"colorSaturation"));if(r){var s=e.get("visualMin"),l=e.get("visualMax"),u=i.dataExtent.slice();null!=s&&su[1]&&(u[1]=l);var h=e.get("colorMappingBy"),c={type:r.name,dataExtent:u,visual:r.range};"color"!==c.type||"index"!==h&&"id"!==h?c.mappingMethod="linear":(c.mappingMethod="category",c.loop=!0);var d=new g_(c);return d.__drColorMappingBy=h,d}}}function E_(t,e){var i=t.get(e);return D_(i)&&i.length?{name:e,range:i}:null}function R_(t,e,i,n,o,a){var r=P({},e);if(o){var s=o.type,l="color"===s&&o.__drColorMappingBy,u="index"===l?n:"id"===l?a.mapIdToIndex(i.getId()):i.getValue(t.get("visualDimension"));r[s]=o.mapValueToVisual(u)}return r}var z_=Math.max,B_=Math.min,V_=W,G_=E,F_=["itemStyle","borderWidth"],W_=["itemStyle","gapWidth"],H_=["upperLabel","show"],Z_=["upperLabel","height"],U_={seriesType:"treemap",reset:function(t,e,i,n){var o=i.getWidth(),a=i.getHeight(),r=t.option,s=bu(t.getBoxLayoutParams(),{width:i.getWidth(),height:i.getHeight()}),l=r.size||[],u=Rl(V_(s.width,l[0]),o),h=Rl(V_(s.height,l[1]),a),c=n&&n.type,d=Zx(n,["treemapZoomToNode","treemapRootToNode"],t),f="treemapRender"===c||"treemapMove"===c?n.rootRect:null,p=t.getViewRoot(),g=Ux(p);if("treemapMove"!==c){var m="treemapZoomToNode"===c?function(t,e,i,n,o){var a,r=(e||{}).node,s=[n,o];if(!r||r===i)return s;var l=n*o,u=l*t.option.zoomToNodeRatio;for(;a=r.parentNode;){for(var h=0,c=a.children,d=0,f=c.length;ds[1]&&(s[1]=e)})}else s=[NaN,NaN];return{sum:n,dataExtent:s}}(e,r,s);if(0===u.sum)return t.viewChildren=[];if(u.sum=function(t,e,i,n,o){if(!n)return i;for(var a=t.get("visibleMin"),r=o.length,s=r,l=r-1;0<=l;l--){var u=o["asc"===n?r-l-1:l].getValue();u/i*ei[l[r]])&&(h=i[l[r]]);for(var c=0,d=t.length;c "+d)),u++)}var f,p=i.get("coordinateSystem");if("cartesian2d"===p||"polar"===p)f=gp(t,i);else{var g=lh.get(p),m=g&&"view"!==g.type&&g.dimensions||[];_(m,"value")<0&&m.concat(["value"]);var v=lp(t,{coordDimensions:m});(f=new Yf(v,i)).initData(t)}var y=new Yf(["value"],i);return y.initData(l,s),o&&o(f,y),yx({mainData:f,struct:a,structAttr:"graph",datas:{node:f,edge:y},datasAttr:{node:"data",edge:"edgeData"}}),a.update(),a}var nw=Df({type:"series.graph",init:function(t){nw.superApply(this,"init",arguments);var e=this;function i(){return e._categoriesData}this.legendVisualProvider=new qv(i,i),this.fillDataTextStyle(t.edges||t.links),this._updateCategoriesData()},mergeOption:function(t){nw.superApply(this,"mergeOption",arguments),this.fillDataTextStyle(t.edges||t.links),this._updateCategoriesData()},mergeDefaultAndTheme:function(t){nw.superApply(this,"mergeDefaultAndTheme",arguments),Go(t,["edgeLabel"],["show"])},getInitialData:function(t,s){var e=t.edges||t.links||[],i=t.data||t.nodes||[],l=this;if(i&&e)return iw(i,e,this,!0,function(t,e){t.wrapMethod("getItemModel",function(t){var e=l._categoriesModels[t.getShallow("category")];return e&&(e.parentModel=t.parentModel,t.parentModel=e),t});var i=l.getModel("edgeLabel"),n=new Cl({label:i.option},i.parentModel,s),o=l.getModel("emphasis.edgeLabel"),a=new Cl({emphasis:{label:o.option}},o.parentModel,s);function r(t){return(t=this.parsePath(t))&&"label"===t[0]?n:t&&"emphasis"===t[0]&&"label"===t[1]?a:this.parentModel}e.wrapMethod("getItemModel",function(t){return t.customizeGetParent(r),t})}).data},getGraph:function(){return this.getData().graph},getEdgeData:function(){return this.getGraph().edgeData},getCategoriesData:function(){return this._categoriesData},formatTooltip:function(t,e,i){if("edge"!==i)return nw.superApply(this,"formatTooltip",arguments);var n=this.getData(),o=this.getDataParams(t,i),a=n.graph.getEdgeByIndex(t),r=n.getName(a.node1.dataIndex),s=n.getName(a.node2.dataIndex),l=[];return null!=r&&l.push(r),null!=s&&l.push(s),l=au(l.join(" > ")),o.value&&(l+=" : "+au(o.value)),l},_updateCategoriesData:function(){var t=O(this.option.categories||[],function(t){return null!=t.value?t:P({value:0},t)}),e=new Yf(["value"],this);e.initData(t),this._categoriesData=e,this._categoriesModels=e.mapArray(function(t){return e.getItemModel(t,!0)})},setZoom:function(t){this.option.zoom=t},setCenter:function(t){this.option.center=t},isAnimationEnabled:function(){return nw.superCall(this,"isAnimationEnabled")&&!("force"===this.get("layout")&&this.get("force.layoutAnimation"))},defaultOption:{zlevel:0,z:2,coordinateSystem:"view",legendHoverLink:!0,hoverAnimation:!0,layout:null,focusNodeAdjacency:!1,circular:{rotateLabel:!1},force:{initLayout:null,repulsion:[0,50],gravity:.1,friction:.6,edgeLength:30,layoutAnimation:!0},left:"center",top:"center",symbol:"circle",symbolSize:10,edgeSymbol:["none","none"],edgeSymbolSize:10,edgeLabel:{position:"middle",distance:5},draggable:!1,roam:!1,center:null,zoom:1,nodeScaleRatio:.6,label:{show:!1,formatter:"{b}"},itemStyle:{},lineStyle:{color:"#aaa",width:1,curveness:0,opacity:.5},emphasis:{label:{show:!0}}}}),ow=ls.prototype,aw=ds.prototype;function rw(t){return isNaN(+t.cpx1)||isNaN(+t.cpy1)}var sw=Cs({type:"ec-line",style:{stroke:"#000",fill:null},shape:{x1:0,y1:0,x2:0,y2:0,percent:1,cpx1:null,cpy1:null},buildPath:function(t,e){this[rw(e)?"_buildPathLine":"_buildPathCurve"](t,e)},_buildPathLine:ow.buildPath,_buildPathCurve:aw.buildPath,pointAt:function(t){return this[rw(this.shape)?"_pointAtLine":"_pointAtCurve"](t)},_pointAtLine:ow.pointAt,_pointAtCurve:aw.pointAt,tangentAt:function(t){var e=this.shape,i=rw(e)?[e.x2-e.x1,e.y2-e.y1]:this._tangentAtCurve(t);return mt(i,i)},_tangentAtCurve:aw.tangentAt}),lw=["fromSymbol","toSymbol"];function uw(t){return"_"+t+"Type"}function hw(t,e,i){var n=e.getItemVisual(i,"color"),o=e.getItemVisual(i,t),a=e.getItemVisual(i,t+"Size");if(o&&"none"!==o){L(a)||(a=[a,a]);var r=wg(o,-a[0]/2,-a[1]/2,a[0],a[1],n);return r.name=t,r}}function cw(t,e){t.x1=e[0][0],t.y1=e[0][1],t.x2=e[1][0],t.y2=e[1][1],t.percent=1;var i=e[2];i?(t.cpx1=i[0],t.cpy1=i[1]):(t.cpx1=NaN,t.cpy1=NaN)}function dw(t,e,i){Ci.call(this),this._createLine(t,e,i)}var fw=dw.prototype;function pw(t){this._ctor=t||dw,this.group=new Ci}fw.beforeUpdate=function(){var t=this.childOfName("fromSymbol"),e=this.childOfName("toSymbol"),i=this.childOfName("label");if(t||e||!i.ignore){for(var n=1,o=this.parent;o;)o.scale&&(n/=o.scale[0]),o=o.parent;var a=this.childOfName("line");if(this.__dirty||a.__dirty){var r=a.shape.percent,s=a.pointAt(0),l=a.pointAt(r),u=ht([],l,s);if(mt(u,u),t){t.attr("position",s);var h=a.tangentAt(0);t.attr("rotation",Math.PI/2-Math.atan2(h[1],h[0])),t.attr("scale",[n*r,n*r])}if(e){e.attr("position",l);h=a.tangentAt(1);e.attr("rotation",-Math.PI/2-Math.atan2(h[1],h[0])),e.attr("scale",[n*r,n*r])}if(!i.ignore){var c,d,f,p;i.attr("position",l);var g=i.__labelDistance,m=g[0]*n,v=g[1]*n,y=r/2,x=[(h=a.tangentAt(y))[1],-h[0]],_=a.pointAt(y);0=t&&(0===e?0:n[e-1][0])a&&(e[1-n]=e[n]+c.sign*a),e}function Qw(t,e){var i=t[e]-t[1-e];return{span:Math.abs(i),sign:0o*(1-h[0])?(l="jump",r=s-o*(1-h[2])):0<=(r=s-o*h[1])&&(r=s-o*(1-h[1]))<=0&&(r=0),(r*=e.axisExpandWidth/u)?Jw(r,n,a,"all"):l="none";else{o=n[1]-n[0];(n=[nb(0,a[1]*s/o-o/2)])[1]=ib(a[1],n[0]+o),n[0]=n[1]-o}return{axisExpandWindow:n,behavior:l}}},lh.register("parallel",{create:function(n,o){var a=[];return n.eachComponent("parallel",function(t,e){var i=new lb(t,n,o);i.name="parallel_"+e,i.resize(t,o),(t.coordinateSystem=i).model=t,a.push(i)}),n.eachSeries(function(t){if("parallel"===t.get("coordinateSystem")){var e=n.queryComponents({mainType:"parallel",index:t.get("parallelIndex"),id:t.get("parallelId")})[0];t.coordinateSystem=e.coordinateSystem}}),a}});var hb=ku.extend({type:"baseParallelAxis",axis:null,activeIntervals:[],getAreaSelectStyle:function(){return ha([["fill","color"],["lineWidth","borderWidth"],["stroke","borderColor"],["width","width"],["opacity","opacity"]])(this.getModel("areaSelectStyle"))},setActiveIntervals:function(t){var e=this.activeIntervals=k(t);if(e)for(var i=e.length-1;0<=i;i--)Bl(e[i])},getActiveState:function(t){var e=this.activeIntervals;if(!e.length)return"normal";if(null==t||isNaN(t))return"inactive";if(1===e.length){var i=e[0];if(i[0]<=t&&t<=i[1])return"active"}else for(var n=0,o=e.length;nn.getWidth()||i<0||i>n.getHeight()}(t,e)){var n=t._zr,o=t._covers,a=Pb(t,e,i);if(!t._dragging)for(var r=0;rf&&(f=m.depth),g.setLayout({depth:v?m.depth:c},!0),"vertical"===a?g.setLayout({dy:i},!0):g.setLayout({dx:i},!0);for(var y=0;y "))},preventIncremental:function(){return!!this.get("effect.show")},getProgressive:function(){var t=this.option.progressive;return null==t?this.option.large?1e4:this.get("progressive"):t},getProgressiveThreshold:function(){var t=this.option.progressiveThreshold;return null==t?this.option.large?2e4:this.get("progressiveThreshold"):t},defaultOption:{coordinateSystem:"geo",zlevel:0,z:2,legendHoverLink:!0,hoverAnimation:!0,xAxisIndex:0,yAxisIndex:0,symbol:["none","none"],symbolSize:[10,10],geoIndex:0,effect:{show:!1,period:4,constantSpeed:0,symbol:"circle",symbolSize:3,loop:!0,trailLength:.2},large:!1,largeThreshold:2e3,polyline:!1,clip:!0,label:{show:!1,position:"end"},lineStyle:{opacity:.5}}});function fM(t,e,i){Ci.call(this),this.add(this.createLine(t,e,i)),this._updateEffectSymbol(t,e)}var pM=fM.prototype;function gM(t,e,i){Ci.call(this),this._createPolyline(t,e,i)}pM.createLine=function(t,e,i){return new dw(t,e,i)},pM._updateEffectSymbol=function(t,e){var i=t.getItemModel(e).getModel("effect"),n=i.get("symbolSize"),o=i.get("symbol");L(n)||(n=[n,n]);var a=i.get("color")||t.getItemVisual(e,"color"),r=this.childAt(1);this._symbolType!==o&&(this.remove(r),(r=wg(o,-.5,-.5,1,1,a)).z2=100,r.culling=!0,this.add(r)),r&&(r.setStyle("shadowColor",a),r.setStyle(i.getItemStyle(["color"])),r.attr("scale",n),r.setColor(a),r.attr("scale",n),this._symbolType=o,this._symbolScale=n,this._updateEffectAnimation(t,i,e))},pM._updateEffectAnimation=function(e,t,i){var n=this.childAt(1);if(n){var o=this,a=e.getItemLayout(i),r=1e3*t.get("period"),s=t.get("loop"),l=t.get("constantSpeed"),u=W(t.get("delay"),function(t){return t/e.count()*r/3}),h="function"==typeof u;if(n.ignore=!0,this.updateAnimationPoints(n,a),0e);r++);r=Math.min(r-1,o-2)}wt(t.position,i[r],i[r+1],(e-n[r])/(n[r+1]-n[r]));var s=i[r+1][0]-i[r][0],l=i[r+1][1]-i[r][1];t.rotation=-Math.atan2(l,s)-Math.PI/2,this._lastFrame=r,this._lastFramePercent=e,t.ignore=!1}},w(vM,fM);var xM=Cs({shape:{polyline:!1,curveness:0,segs:[]},buildPath:function(t,e){var i=e.segs,n=e.curveness;if(e.polyline)for(var o=0;o=e[0]&&t<=e[1]}}(y,e.option.range):function(e,n,o){var i=e[1]-e[0],a=(n=O(n,function(t){return{interval:[(t.interval[0]-e[0])/i,(t.interval[1]-e[0])/i]}})).length,r=0;return function(t){for(var e=r;e=e.y&&t[1]<=e.y+e.height:i.contain(i.toLocalCoord(t[1]))&&t[0]>=e.y&&t[0]<=e.y+e.height},pointToData:function(t){var e=this.getAxis();return[e.coordToData(e.toLocalCoord(t["horizontal"===e.orient?0:1]))]},dataToPoint:function(t){var e=this.getAxis(),i=this.getRect(),n=[],o="horizontal"===e.orient?0:1;return t instanceof Array&&(t=t[0]),n[o]=e.toGlobalCoord(e.dataToCoord(+t)),n[1-o]=0==o?i.y+i.height/2:i.x+i.width/2,n}}).dimensions});var JM=["axisLine","axisTickLabel","axisName"],QM=["splitArea","splitLine"],tI=mv.extend({type:"singleAxis",axisPointerClass:"SingleAxisPointer",render:function(e,t,i,n){var o=this.group;o.removeAll();var a=this._axisGroup;this._axisGroup=new Ci;var r=$M(e),s=new Qm(e,r);E(JM,s.add,s),o.add(this._axisGroup),o.add(s.getGroup()),E(QM,function(t){e.get(t+".show")&&this["_"+t](e)},this),ml(a,this._axisGroup,e),tI.superCall(this,"render",e,t,i,n)},remove:function(){bv(this)},_splitLine:function(t){var e=t.axis;if(!e.scale.isBlank()){var i=t.getModel("splitLine"),n=i.getModel("lineStyle"),o=n.get("width"),a=n.get("color");a=a instanceof Array?a:[a];for(var r=t.coordinateSystem.getRect(),s=e.isHorizontal(),l=[],u=0,h=e.getTicksCoords({tickModel:i}),c=[],d=[],f=0;fr)return!0;if(a){var s=fv(t).seriesDataCount,l=n.getExtent();return Math.abs(l[0]-l[1])/s>r}return!1},makeElOption:function(t,e,i,n,o){},createPointerEl:function(t,e,i,n){var o=e.pointer;if(o){var a=yI(t).pointerEl=new bl[o.type](xI(e.pointer));t.add(a)}},createLabelEl:function(t,e,i,n){if(e.label){var o=yI(t).labelEl=new rs(xI(e.label));t.add(o),SI(o,n)}},updatePointerEl:function(t,e,i){var n=yI(t).pointerEl;n&&e.pointer&&(n.setStyle(e.pointer.style),i(n,{shape:e.pointer.shape}))},updateLabelEl:function(t,e,i,n){var o=yI(t).labelEl;o&&(o.setStyle(e.label.style),i(o,{shape:e.label.shape,position:e.label.position}),SI(o,n))},_renderHandle:function(t){if(!this._dragging&&this.updateHandleTransform){var e,i=this._axisPointerModel,n=this._api.getZr(),o=this._handle,a=i.getModel("handle"),r=i.get("status");if(!a.get("show")||!r||"hide"===r)return o&&n.remove(o),void(this._handle=null);this._handle||(e=!0,o=this._handle=yl(a.get("icon"),{cursor:"move",draggable:!0,onmousemove:function(t){Xt(t.event)},onmousedown:_I(this._onHandleDragMove,this,0,0),drift:_I(this._onHandleDragMove,this),ondragend:_I(this._onHandleDragEnd,this)}),n.add(o)),II(o,i,!1);o.setStyle(a.getItemStyle(null,["color","borderColor","borderWidth","opacity","shadowColor","shadowBlur","shadowOffsetX","shadowOffsetY"]));var s=a.get("size");L(s)||(s=[s,s]),o.attr("scale",[s[0]/2,s[1]/2]),kc(this,"_doDispatchAxisPointer",a.get("throttle")||0,"fixRate"),this._moveHandleToValue(t,e)}},_moveHandleToValue:function(t,e){bI(this._axisPointerModel,!e&&this._moveAnimation,this._handle,MI(this.getHandleTransform(t,this._axisModel,this._axisPointerModel)))},_onHandleDragMove:function(t,e){var i=this._handle;if(i){this._dragging=!0;var n=this.updateHandleTransform(MI(i),[t,e],this._axisModel,this._axisPointerModel);this._payloadInfo=n,i.stopAnimation(),i.attr(MI(n)),yI(i).lastProp=null,this._doDispatchAxisPointer()}},_doDispatchAxisPointer:function(){if(this._handle){var t=this._payloadInfo,e=this._axisModel;this._api.dispatchAction({type:"updateAxisPointer",x:t.cursorPoint[0],y:t.cursorPoint[1],tooltipOption:t.tooltipOption,axesInfo:[{axisDim:e.axis.dim,axisIndex:e.componentIndex}]})}},_onHandleDragEnd:function(t){if(this._dragging=!1,this._handle){var e=this._axisPointerModel.get("value");this._moveHandleToValue(e),this._api.dispatchAction({type:"hideTip"})}},getHandleTransform:null,updateHandleTransform:null,clear:function(t){this._lastValue=null,this._lastStatus=null;var e=t.getZr(),i=this._group,n=this._handle;e&&i&&(this._lastGraphicKey=null,i&&e.remove(i),n&&e.remove(n),this._group=null,this._handle=null,this._payloadInfo=null)},doClear:function(){},buildLabel:function(t,e,i){return{x:t[i=i||0],y:t[1-i],width:e[i],height:e[1-i]}}}).constructor=wI);var OI=wI.extend({makeElOption:function(t,e,i,n,o){var a=i.axis,r=a.grid,s=n.get("type"),l=EI(r,a).getOtherAxis(a).getGlobalExtent(),u=a.toGlobalCoord(a.dataToCoord(e,!0));if(s&&"none"!==s){var h=TI(n),c=RI[s](a,u,l);c.style=h,t.graphicKey=c.type,t.pointer=c}LI(e,t,_v(r.model,i),i,n,o)},getHandleTransform:function(t,e,i){var n=_v(e.axis.grid.model,e,{labelInside:!1});return n.labelMargin=i.get("handle.margin"),{position:CI(e.axis,t,n),rotation:n.rotation+(n.labelDirection<0?Math.PI:0)}},updateHandleTransform:function(t,e,i,n){var o=i.axis,a=o.grid,r=o.getGlobalExtent(!0),s=EI(a,o).getOtherAxis(o).getGlobalExtent(),l="x"===o.dim?0:1,u=t.position;u[l]+=e[l],u[l]=Math.min(r[1],u[l]),u[l]=Math.max(r[0],u[l]);var h=(s[1]+s[0])/2,c=[h,h];c[l]=u[l];return{position:u,rotation:t.rotation,cursorPoint:c,tooltipOption:[{verticalAlign:"middle"},{align:"center"}][l]}}});function EI(t,e){var i={};return i[e.dim+"AxisIndex"]=e.index,t.getCartesian(i)}var RI={line:function(t,e,i){return{type:"Line",subPixelOptimize:!0,shape:kI([e,i[0]],[e,i[1]],zI(t))}},shadow:function(t,e,i){var n=Math.max(1,t.getBandWidth()),o=i[1]-i[0];return{type:"Rect",shape:PI([e-n/2,i[0]],[n,o],zI(t))}}};function zI(t){return"x"===t.dim?0:1}mv.registerAxisPointerClass("CartesianAxisPointer",OI),yf(function(t){if(t){t.axisPointer&&0!==t.axisPointer.length||(t.axisPointer={});var e=t.axisPointer.link;e&&!L(e)&&(t.axisPointer.link=[e])}}),xf(Ld.PROCESSOR.STATISTIC,function(t,e){t.getComponent("axisPointer").coordSysAxesInfo=cv(t,e)}),_f({type:"updateAxisPointer",event:"updateAxisPointer",update:":updateAxisPointer"},function(t,e,i){var n=t.currTrigger,r=[t.x,t.y],o=t,a=t.dispatchAction||A(i.dispatchAction,i),s=e.getComponent("axisPointer").coordSysAxesInfo;if(s){hI(r)&&(r=iI({seriesIndex:o.seriesIndex,dataIndex:o.dataIndex},e).point);var l=hI(r),u=o.axesInfo,h=s.axesInfo,c="leave"===n||hI(r),d={},f={},p={list:[],map:{}},g={showPointer:oI(sI,f),showTooltip:oI(lI,p)};nI(s.coordSysMap,function(t,e){var a=l||t.containPoint(r);nI(s.coordSysAxesInfo[e],function(t,e){var i=t.axis,n=function(t,e){for(var i=0;i<(t||[]).length;i++){var n=t[i];if(e.axis.dim===n.axisDim&&e.axis.model.componentIndex===n.axisIndex)return n}}(u,t);if(!c&&a&&(!u||n)){var o=n&&n.value;null!=o||l||(o=i.pointToData(r)),null!=o&&rI(t,o,g,!1,d)}})});var m={};return nI(h,function(o,t){var a=o.linkGroup;a&&!f[t]&&nI(a.axesInfo,function(t,e){var i=f[e];if(t!==o&&i){var n=i.value;a.mapper&&(n=o.axis.scale.parse(a.mapper(n,uI(t),uI(o)))),m[o.key]=n}})}),nI(m,function(t,e){rI(h[e],t,g,!0,d)}),function(o,t,e){var a=e.axesInfo=[];nI(t,function(t,e){var i=t.axisPointerModel.option,n=o[e];n?(t.useHandle||(i.status="show"),i.value=n.value,i.seriesDataIndices=(n.payloadBatch||[]).slice()):t.useHandle||(i.status="hide"),"show"===i.status&&a.push({axisDim:t.axis.dim,axisIndex:t.axis.model.componentIndex,value:i.value})})}(f,h,d),function(t,e,i,n){if(hI(e)||!t.list.length)return n({type:"hideTip"});var o=((t.list[0].dataByAxis[0]||{}).seriesDataIndices||[])[0]||{};n({type:"showTip",escapeConnect:!0,x:e[0],y:e[1],tooltipOption:i.tooltipOption,position:i.position,dataIndexInside:o.dataIndexInside,dataIndex:o.dataIndex,seriesIndex:o.seriesIndex,dataByCoordSys:t.list})}(p,r,t,a),function(t,e,i){var n=i.getZr(),o="axisPointerLastHighlights",a=aI(n)[o]||{},r=aI(n)[o]={};nI(t,function(t,e){var i=t.axisPointerModel.option;"show"===i.status&&nI(i.seriesDataIndices,function(t){var e=t.seriesIndex+" | "+t.dataIndex;r[e]=t})});var s=[],l=[];E(a,function(t,e){r[e]||l.push(t)}),E(r,function(t,e){a[e]||s.push(t)}),l.length&&i.dispatchAction({type:"downplay",escapeConnect:!0,batch:l}),s.length&&i.dispatchAction({type:"highlight",escapeConnect:!0,batch:s})}(h,0,i),d}});var BI=["x","y"],VI=["width","height"],GI=wI.extend({makeElOption:function(t,e,i,n,o){var a=i.axis,r=a.coordinateSystem,s=HI(r,1-WI(a)),l=r.dataToPoint(e)[0],u=n.get("type");if(u&&"none"!==u){var h=TI(n),c=FI[u](a,l,s);c.style=h,t.graphicKey=c.type,t.pointer=c}LI(e,t,$M(i),i,n,o)},getHandleTransform:function(t,e,i){var n=$M(e,{labelInside:!1});return n.labelMargin=i.get("handle.margin"),{position:CI(e.axis,t,n),rotation:n.rotation+(n.labelDirection<0?Math.PI:0)}},updateHandleTransform:function(t,e,i,n){var o=i.axis,a=o.coordinateSystem,r=WI(o),s=HI(a,r),l=t.position;l[r]+=e[r],l[r]=Math.min(s[1],l[r]),l[r]=Math.max(s[0],l[r]);var u=HI(a,1-r),h=(u[1]+u[0])/2,c=[h,h];return c[r]=l[r],{position:l,rotation:t.rotation,cursorPoint:c,tooltipOption:{verticalAlign:"middle"}}}}),FI={line:function(t,e,i){return{type:"Line",subPixelOptimize:!0,shape:kI([e,i[0]],[e,i[1]],WI(t))}},shadow:function(t,e,i){var n=t.getBandWidth(),o=i[1]-i[0];return{type:"Rect",shape:PI([e-n/2,i[0]],[n,o],WI(t))}}};function WI(t){return t.isHorizontal()?0:1}function HI(t,e){var i=t.getRect();return[i[BI[e]],i[BI[e]]+i[VI[e]]]}mv.registerAxisPointerClass("SingleAxisPointer",GI),Af({type:"single"});var ZI=sc.extend({type:"series.themeRiver",dependencies:["singleAxis"],nameMap:null,init:function(t){ZI.superApply(this,"init",arguments),this.legendVisualProvider=new qv(A(this.getData,this),A(this.getRawData,this))},fixData:function(t){var e=t.length,i=ta(t,function(t){return t[2]}),n=[];i.buckets.each(function(t,e){n.push({name:e,dataList:t})});for(var o=n.length,a=-1,r=-1,s=0;sMath.PI/2?"right":"left"):y&&"center"!==y?"left"===y?(d=l.r0+v,f>Math.PI/2&&(y="right")):"right"===y&&(d=l.r-v,f>Math.PI/2&&(y="left")):(d=(l.r+l.r0)/2,y="center"),c.attr("style",{text:s,textAlign:y,textVerticalAlign:S("verticalAlign")||"middle",opacity:S("opacity")});var x=d*p+l.cx,_=d*g+l.cy;c.attr("position",[x,_]);var w=S("rotate"),b=0;function S(t){var e=a.get(t);return null==e?o.get(t):e}"radial"===w?(b=-f)<-Math.PI/2&&(b+=Math.PI):"tangential"===w?(b=Math.PI/2-f)>Math.PI/2?b-=Math.PI:b<-Math.PI/2&&(b+=Math.PI):"number"==typeof w&&(b=w*Math.PI/180),c.attr("rotation",b)},JI._initEvents=function(t,e,i,n){t.off("mouseover").off("mouseout").off("emphasis").off("normal");function o(){r.onEmphasis(n)}function a(){r.onNormal()}var r=this;i.isAnimationEnabled()&&t.on("mouseover",o).on("mouseout",a).on("emphasis",o).on("normal",a).on("downplay",function(){r.onDownplay()}).on("highlight",function(){r.onHighlight()})},w($I,Ci);_c.extend({type:"sunburst",init:function(){},render:function(o,a,t,e){var n=this;this.seriesModel=o,this.api=t,this.ecModel=a;var r=o.getData(),s=r.tree.root,i=o.getViewRoot(),l=this.group,u=o.get("renderLabelForZeroData"),h=[];i.eachNode(function(t){h.push(t)});var c=this._oldChildren||[];if(function(i,n){if(0===i.length&&0===n.length)return;function t(t){return t.getId()}function e(t,e){!function(t,e){u||!t||t.getValue()||(t=null);if(t!==s&&e!==s)if(e&&e.piece)t?(e.piece.updateData(!1,t,"normal",o,a),r.setItemGraphicEl(t.dataIndex,e.piece)):function(t){if(!t)return;t.piece&&(l.remove(t.piece),t.piece=null)}(e);else if(t){var i=new $I(t,o,a);l.add(i),r.setItemGraphicEl(t.dataIndex,i)}}(null==t?null:i[t],null==e?null:n[e])}new kf(n,i,t,t).add(e).update(e).remove(T(e,null)).execute()}(h,c),function(t,e){if(0=i.r0}}});var QI="sunburstRootToNode";_f({type:QI,update:"updateView"},function(o,t){t.eachComponent({mainType:"series",subType:"sunburst",query:o},function(t,e){var i=Zx(o,[QI],t);if(i){var n=t.getViewRoot();n&&(o.direction=Xx(n,i.node)?"rollUp":"drillDown"),t.resetViewRoot(i.node)}})});var tT="sunburstHighlight";_f({type:tT,update:"updateView"},function(n,t){t.eachComponent({mainType:"series",subType:"sunburst",query:n},function(t,e){var i=Zx(n,[tT],t);i&&(n.highlight=i.node)})});_f({type:"sunburstUnhighlight",update:"updateView"},function(i,t){t.eachComponent({mainType:"series",subType:"sunburst",query:i},function(t,e){i.unhighlight=!0})});var eT=Math.PI/180;function iT(t,e){if("function"==typeof e)return t.sort(e);var n="asc"===e;return t.sort(function(t,e){var i=(t.getValue()-e.getValue())*(n?1:-1);return 0==i?(t.dataIndex-e.dataIndex)*(n?-1:1):i})}function nT(a,r){return r=r||[0,0],O(["x","y"],function(t,e){var i=this.getAxis(t),n=r[e],o=a[e]/2;return"category"===i.type?i.getBandWidth():Math.abs(i.dataToCoord(n-o)-i.dataToCoord(n+o))},this)}Sf(T(iy,"sunburst")),bf(T(function(t,e,C,i){e.eachSeriesByType(t,function(t){var e=t.get("center"),i=t.get("radius");L(i)||(i=[0,i]),L(e)||(e=[e,e]);var n=C.getWidth(),o=C.getHeight(),h=Math.min(n,o),c=Rl(e[0],n),d=Rl(e[1],o),f=Rl(i[0],h/2),a=Rl(i[1],h/2),r=-t.get("startAngle")*eT,p=t.get("minAngle")*eT,g=t.getData().tree.root,s=t.getViewRoot(),m=s.depth,l=t.get("sort");null!=l&&!function e(t,i){var n=t.children||[];t.children=iT(n,i);n.length&&E(t.children,function(t){e(t,i)})}(s,l);var u=0;E(s.children,function(t){isNaN(t.getValue())||u++});var v=s.getValue(),y=Math.PI/(v||u)*2,x=0t[1]&&t.reverse(),{coordSys:{type:"polar",cx:o.cx,cy:o.cy,r:t[1],r0:t[0]},api:{coord:A(function(t){var e=a.dataToRadius(t[0]),i=r.dataToAngle(t[1]),n=o.coordToPoint([e,i]);return n.push(e,i*Math.PI/180),n}),size:A(rT,o)}}},calendar:function(i){var t=i.getRect(),e=i.getRangeInfo();return{coordSys:{type:"calendar",x:t.x,y:t.y,width:t.width,height:t.height,cellWidth:i.getCellWidth(),cellHeight:i.getCellHeight(),rangeInfo:{start:e.start,end:e.end,weeks:e.weeks,dayCount:e.allDay}},api:{coord:function(t,e){return i.dataToPoint(t,e)}}}}};function pT(t,e,i,n,o){null==i[t]||o||(e[t]=i[t],i[t]=n[t])}function gT(a,r,e,t){var i=a.get("renderItem"),n=a.coordinateSystem,o={};n&&(o=n.prepareCustoms?n.prepareCustoms():fT[n.type](n));var s,l,u,h,c,d=D({getWidth:t.getWidth,getHeight:t.getHeight,getZr:t.getZr,getDevicePixelRatio:t.getDevicePixelRatio,value:function(t,e){return null==e&&(e=s),r.get(r.getDimension(t||0),e)},style:function(t,e){null==e&&(e=s),g(e);var i=l.getModel(lT).getItemStyle();null!=c&&(i.fill=c);var n=r.getItemVisual(e,"opacity");null!=n&&(i.opacity=n);var o=t?_T(t,u):u;return nl(i,o,null,{autoColor:c,isRectText:!0}),i.text=o.getShallow("show")?H(a.getFormattedLabel(e,"normal"),Ug(r,e)):null,t&&wT(i,t),i},styleEmphasis:function(t,e){null==e&&(e=s),g(e);var i=l.getModel(uT).getItemStyle(),n=t?_T(t,h):h;return nl(i,n,null,{isRectText:!0},!0),i.text=n.getShallow("show")?Z(a.getFormattedLabel(e,"emphasis"),a.getFormattedLabel(e,"normal"),Ug(r,e)):null,t&&wT(i,t),i},visual:function(t,e){return null==e&&(e=s),r.getItemVisual(e,t)},barLayout:function(t){if(n.getBaseAxis){return function(t){var e=[],i=t.axis;if("category"===i.type){for(var n=i.getBandWidth(),o=0;oe[1]&&e.reverse();var i=t.getExtent(),n=Math.PI/180;return{cx:this.cx,cy:this.cy,r0:e[0],r:e[1],startAngle:-i[0]*n,endAngle:-i[1]*n,clockwise:t.inverse,contain:function(t,e){var i=t-this.cx,n=e-this.cy,o=i*i+n*n,a=this.r,r=this.r0;return o<=a*a&&r*r<=o}}}};var kT=ku.extend({type:"polarAxis",axis:null,getCoordSysModel:function(){return this.ecModel.queryComponents({mainType:"polar",index:this.option.polarIndex,id:this.option.polarId})[0]}});m(kT.prototype,dg);var PT={splitNumber:5};function NT(t,e){return e.type||(e.data?"category":"value")}function OT(t,e){var i=this,n=i.getAngleAxis(),o=i.getRadiusAxis();if(n.scale.setExtent(1/0,-1/0),o.scale.setExtent(1/0,-1/0),t.eachSeries(function(t){if(t.coordinateSystem===i){var e=t.getData();E(e.mapDimension("radius",!0),function(t){o.scale.unionExtentFromData(e,pp(e,t))}),E(e.mapDimension("angle",!0),function(t){n.scale.unionExtentFromData(e,pp(e,t))})}}),rg(n.scale,n.model),rg(o.scale,o.model),"category"===n.type&&!n.onBand){var a=n.getExtent(),r=360/n.scale.count();n.inverse?a[1]+=r:a[1]-=r,n.setExtent(a[0],a[1])}}function ET(t,e){if(t.type=e.get("type"),t.scale=sg(e),t.onBand=e.get("boundaryGap")&&"category"===t.type,t.inverse=e.get("inverse"),"angleAxis"===e.mainType){t.inverse^=e.get("clockwise");var i=e.get("startAngle");t.setExtent(i,i+(t.inverse?-360:360))}(e.axis=t).model=e}Gm("angle",kT,NT,{startAngle:90,clockwise:!0,splitNumber:12,axisLabel:{rotate:!1}}),Gm("radius",kT,NT,PT),Tf({type:"polar",dependencies:["polarAxis","angleAxis"],coordinateSystem:null,findAxisModel:function(t){var e;return this.ecModel.eachComponent(t,function(t){t.getCoordSysModel()===this&&(e=t)},this),e},defaultOption:{zlevel:0,z:0,center:["50%","50%"],radius:"80%"}}),lh.register("polar",{dimensions:LT.prototype.dimensions,create:function(i,s){var l=[];return i.eachComponent("polar",function(t,e){var i=new LT(e);i.update=OT;var n=i.getRadiusAxis(),o=i.getAngleAxis(),a=t.findAxisModel("radiusAxis"),r=t.findAxisModel("angleAxis");ET(n,a),ET(o,r),function(t,e,i){var n=e.get("center"),o=i.getWidth(),a=i.getHeight();t.cx=Rl(n[0],o),t.cy=Rl(n[1],a);var r=t.getRadiusAxis(),s=Math.min(o,a)/2,l=e.get("radius");null==l?l=[0,"100%"]:L(l)||(l=[0,l]),l=[Rl(l[0],s),Rl(l[1],s)],r.inverse?r.setExtent(l[1],l[0]):r.setExtent(l[0],l[1])}(i,t,s),l.push(i),(t.coordinateSystem=i).model=t}),i.eachSeries(function(t){if("polar"===t.get("coordinateSystem")){var e=i.queryComponents({mainType:"polar",index:t.get("polarIndex"),id:t.get("polarId")})[0];t.coordinateSystem=e.coordinateSystem}}),l}});var RT=["axisLine","axisLabel","axisTick","minorTick","splitLine","minorSplitLine","splitArea"];function zT(t,e,i){e[1]>e[0]&&(e=e.slice().reverse());var n=t.coordToPoint([e[0],i]),o=t.coordToPoint([e[1],i]);return{x1:n[0],y1:n[1],x2:o[0],y2:o[1]}}function BT(t){return t.getRadiusAxis().inverse?0:1}function VT(t){var e=t[0],i=t[t.length-1];e&&i&&Math.abs(Math.abs(e.coord-i.coord)-360)<1e-4&&t.pop()}mv.extend({type:"angleAxis",axisPointerClass:"PolarAxisPointer",render:function(e,t){if(this.group.removeAll(),e.get("show")){var i=e.axis,n=i.polar,o=n.getRadiusAxis().getExtent(),a=i.getTicksCoords(),r=i.getMinorTicksCoords(),s=O(i.getViewLabels(),function(t){return(t=k(t)).coord=i.dataToCoord(t.tickValue),t});VT(s),VT(a),E(RT,function(t){!e.get(t+".show")||i.scale.isBlank()&&"axisLine"!==t||this["_"+t](e,n,a,r,o,s)},this)}},_axisLine:function(t,e,i,n,o){var a,r=t.getModel("axisLine.lineStyle"),s=BT(e),l=s?0:1;(a=0===o[l]?new Yr({shape:{cx:e.cx,cy:e.cy,r:o[s]},style:r.getLineStyle(),z2:1,silent:!0}):new Kr({shape:{cx:e.cx,cy:e.cy,r:o[s],r0:o[l]},style:r.getLineStyle(),z2:1,silent:!0})).style.fill=null,this.group.add(a)},_axisTick:function(t,e,i,n,o){var a=t.getModel("axisTick"),r=(a.get("inside")?-1:1)*a.get("length"),s=o[BT(e)],l=O(i,function(t){return new ls({shape:zT(e,[s,s+r],t.coord)})});this.group.add(Es(l,{style:D(a.getModel("lineStyle").getLineStyle(),{stroke:t.get("axisLine.lineStyle.color")})}))},_minorTick:function(t,e,i,n,o){if(n.length){for(var a=t.getModel("axisTick"),r=t.getModel("minorTick"),s=(a.get("inside")?-1:1)*r.get("length"),l=o[BT(e)],u=[],h=0;hr?"left":"right",u=Math.abs(a[1]-s)/o<.3?"middle":a[1]>s?"top":"bottom";p&&p[n]&&p[n].textStyle&&(i=new Cl(p[n].textStyle,g,g.ecModel));var h=new Ur({silent:Qm.isLabelSilent(c)});this.group.add(h),nl(h.style,i,{x:a[0],y:a[1],textFill:i.getTextColor()||c.get("axisLine.lineStyle.color"),text:t.formattedLabel,textAlign:l,textVerticalAlign:u}),v&&(h.eventData=Qm.makeAxisEventDataBase(c),h.eventData.targetType="axisLabel",h.eventData.value=t.rawLabel)},this)},_splitLine:function(t,e,i,n,o){var a=t.getModel("splitLine").getModel("lineStyle"),r=a.get("color"),s=0;r=r instanceof Array?r:[r];for(var l=[],u=0;um?"left":"right",h=Math.abs(l[1]-v)/g<.3?"middle":l[1]>v?"top":"bottom"}return{position:l,align:u,verticalAlign:h}}(e,i,0,s,d))}});var HT={line:function(t,e,i,n,o){return"angle"===t.dim?{type:"Line",shape:kI(e.coordToPoint([n[0],i]),e.coordToPoint([n[1],i]))}:{type:"Circle",shape:{cx:e.cx,cy:e.cy,r:i}}},shadow:function(t,e,i,n,o){var a=Math.max(1,t.getBandWidth()),r=Math.PI/180;return"angle"===t.dim?{type:"Sector",shape:NI(e.cx,e.cy,n[0],n[1],(-i-a/2)*r,(a/2-i)*r)}:{type:"Sector",shape:NI(e.cx,e.cy,i-a/2,i+a/2,0,2*Math.PI)}}};function ZT(n,t){t.update="updateView",_f(t,function(t,e){var i={};return e.eachComponent({mainType:"geo",query:t},function(e){e[n](t.name),E(e.coordinateSystem.regions,function(t){i[t.name]=e.isSelected(t.name)||!1})}),{selected:i,name:t.name}})}mv.registerAxisPointerClass("PolarAxisPointer",WT),bf(T(function(t,e,i){var N={},O=function(t){var g={};E(t,function(t,e){var i=t.getData(),n=t.coordinateSystem,o=n.getBaseAxis(),a=TT(n,o),r=o.getExtent(),s="category"===o.type?o.getBandWidth():Math.abs(r[1]-r[0])/i.count(),l=g[a]||{bandWidth:s,remainedWidth:s,autoWidthCount:0,categoryGap:"20%",gap:"30%",stacks:{}},u=l.stacks;g[a]=l;var h=IT(t);u[h]||l.autoWidthCount++,u[h]=u[h]||{width:0,maxWidth:0};var c=Rl(t.get("barWidth"),s),d=Rl(t.get("barMaxWidth"),s),f=t.get("barGap"),p=t.get("barCategoryGap");c&&!u[h].width&&(c=Math.min(l.remainedWidth,c),u[h].width=c,l.remainedWidth-=c),d&&(u[h].maxWidth=d),null!=f&&(l.gap=f),null!=p&&(l.categoryGap=p)});var d={};return E(g,function(t,i){d[i]={};var e=t.stacks,n=t.bandWidth,o=Rl(t.categoryGap,n),a=Rl(t.gap,1),r=t.remainedWidth,s=t.autoWidthCount,l=(r-o)/(s+(s-1)*a);l=Math.max(l,0),E(e,function(t,e){var i=t.maxWidth;i&&i=n.start.time&&i.timea.end.time&&t.reverse(),t},_getRangeInfo:function(t){var e;(t=[this.getDateInfo(t[0]),this.getDateInfo(t[1])])[0].time>t[1].time&&(e=!0,t.reverse());var i=Math.floor(t[1].time/864e5)-Math.floor(t[0].time/864e5)+1,n=new Date(t[0].time),o=n.getDate(),a=t[1].date.getDate();n.setDate(o+i-1);var r=n.getDate();if(r!==a)for(var s=0n.weeks||0===t&&en.lweek)return!1;var o=7*(t-1)-n.fweek+e,a=new Date(n.start.time);return a.setDate(n.start.d+o),this.getDateInfo(a)}},UT.dimensions=UT.prototype.dimensions,UT.getDimensionsInfo=UT.prototype.getDimensionsInfo,UT.create=function(i,n){var o=[];return i.eachComponent("calendar",function(t){var e=new UT(t,i,n);o.push(e),t.coordinateSystem=e}),i.eachSeries(function(t){"calendar"===t.get("coordinateSystem")&&(t.coordinateSystem=o[t.get("calendarIndex")||0])}),o},lh.register("calendar",UT);var YT=ku.extend({type:"calendar",coordinateSystem:null,defaultOption:{zlevel:0,z:2,left:80,top:60,cellSize:20,orient:"horizontal",splitLine:{show:!0,lineStyle:{color:"#000",width:1,type:"solid"}},itemStyle:{color:"#fff",borderWidth:1,borderColor:"#ccc"},dayLabel:{show:!0,firstDay:0,position:"start",margin:"50%",nameMap:"en",color:"#000"},monthLabel:{show:!0,position:"start",margin:5,align:"center",nameMap:"en",formatter:null,color:"#000"},yearLabel:{show:!0,position:null,margin:30,formatter:null,color:"#ccc",fontFamily:"sans-serif",fontWeight:"bolder",fontSize:20}},init:function(t,e,i,n){var o=Iu(t);YT.superApply(this,"init",arguments),jT(t,o)},mergeOption:function(t,e){YT.superApply(this,"mergeOption",arguments),jT(this.option,t)}});function jT(t,e){var i=t.cellSize;L(i)?1===i.length&&(i[1]=i[0]):i=t.cellSize=[i,i];var n=O([0,1],function(t){return function(t,e){return null!=t[xu[e][0]]||null!=t[xu[e][1]]&&null!=t[xu[e][2]]}(e,t)&&(i[t]="auto"),null!=i[t]&&"auto"!==i[t]});Mu(t,e,{type:"box",ignoreSize:n})}var qT={EN:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],CN:["一月","二月","三月","四月","五月","六月","七月","八月","九月","十月","十一月","十二月"]},KT={EN:["S","M","T","W","T","F","S"],CN:["日","一","二","三","四","五","六"]};Af({type:"calendar",_tlpoints:null,_blpoints:null,_firstDayOfMonth:null,_firstDayPoints:null,render:function(t,e,i){var n=this.group;n.removeAll();var o=t.coordinateSystem,a=o.getRangeInfo(),r=o.getOrient();this._renderDayRect(t,a,n),this._renderLines(t,a,r,n),this._renderYearText(t,a,r,n),this._renderMonthText(t,r,n),this._renderWeekText(t,a,r,n)},_renderDayRect:function(t,e,i){for(var n=t.coordinateSystem,o=t.getModel("itemStyle").getItemStyle(),a=n.getCellWidth(),r=n.getCellHeight(),s=e.start.time;s<=e.end.time;s=n.getNextNDay(s,1).time){var l=n.dataToRect([s],!1).tl,u=new rs({shape:{x:l[0],y:l[1],width:a,height:r},cursor:"default",style:o});i.add(u)}},_renderLines:function(i,t,n,o){var a=this,r=i.coordinateSystem,s=i.getModel("splitLine.lineStyle").getLineStyle(),l=i.get("splitLine.show"),e=s.lineWidth;this._tlpoints=[],this._blpoints=[],this._firstDayOfMonth=[],this._firstDayPoints=[];for(var u=t.start,h=0;u.time<=t.end.time;h++){d(u.formatedDate),0===h&&(u=r.getDateInfo(t.start.y+"-"+t.start.m));var c=u.date;c.setMonth(c.getMonth()+1),u=r.getDateInfo(c)}function d(t){a._firstDayOfMonth.push(r.getDateInfo(t)),a._firstDayPoints.push(r.dataToRect([t],!1).tl);var e=a._getLinePointsOfOneWeek(i,t,n);a._tlpoints.push(e[0]),a._blpoints.push(e[e.length-1]),l&&a._drawSplitline(e,s,o)}d(r.getNextNDay(t.end.time,1).formatedDate),l&&this._drawSplitline(a._getEdgesPoints(a._tlpoints,e,n),s,o),l&&this._drawSplitline(a._getEdgesPoints(a._blpoints,e,n),s,o)},_getEdgesPoints:function(t,e,i){var n=[t[0].slice(),t[t.length-1].slice()],o="horizontal"===i?0:1;return n[0][o]=n[0][o]-e/2,n[1][o]=n[1][o]+e/2,n},_drawSplitline:function(t,e,i){var n=new ts({z2:20,shape:{points:t},style:e});i.add(n)},_getLinePointsOfOneWeek:function(t,e,i){var n=t.coordinateSystem;e=n.getDateInfo(e);for(var o=[],a=0;a<7;a++){var r=n.getNextNDay(e.time,a),s=n.dataToRect([r.time],!1);o[2*r.day]=s.tl,o[2*r.day+1]=s["horizontal"===i?"bl":"tr"]}return o},_formatterLabel:function(t,e){return"string"==typeof t&&t?uu(t,e):"function"==typeof t?t(e):e.nameMap},_yearTextPositionControl:function(t,e,i,n,o){e=e.slice();var a=["center","bottom"];"bottom"===n?(e[1]+=o,a=["center","top"]):"left"===n?e[0]-=o:"right"===n?(e[0]+=o,a=["center","top"]):e[1]-=o;var r=0;return"left"!==n&&"right"!==n||(r=Math.PI/2),{rotation:r,position:e,style:{textAlign:a[0],textVerticalAlign:a[1]}}},_renderYearText:function(t,e,i,n){var o=t.getModel("yearLabel");if(o.get("show")){var a=o.get("margin"),r=o.get("position");r=r||("horizontal"!==i?"top":"left");var s=[this._tlpoints[this._tlpoints.length-1],this._blpoints[0]],l=(s[0][0]+s[1][0])/2,u=(s[0][1]+s[1][1])/2,h="horizontal"===i?0:1,c={top:[l,s[h][1]],bottom:[l,s[1-h][1]],left:[s[1-h][0],u],right:[s[h][0],u]},d=e.start.y;+e.end.y>+e.start.y&&(d=d+"-"+e.end.y);var f=o.get("formatter"),p={start:e.start.y,end:e.end.y,nameMap:d},g=this._formatterLabel(f,p),m=new Ur({z2:30});nl(m.style,o,{text:g}),m.attr(this._yearTextPositionControl(m,c[r],i,r,a)),n.add(m)}},_monthTextPositionControl:function(t,e,i,n,o){var a="left",r="top",s=t[0],l=t[1];return"horizontal"===i?(l+=o,e&&(a="center"),"start"===n&&(r="bottom")):(s+=o,e&&(r="middle"),"start"===n&&(a="right")),{x:s,y:l,textAlign:a,textVerticalAlign:r}},_renderMonthText:function(t,e,i){var n=t.getModel("monthLabel");if(n.get("show")){var o=n.get("nameMap"),a=n.get("margin"),r=n.get("position"),s=n.get("align"),l=[this._tlpoints,this._blpoints];R(o)&&(o=qT[o.toUpperCase()]||[]);var u="start"===r?0:1,h="horizontal"===e?0:1;a="start"===r?-a:a;for(var c="center"===s,d=0;dd.getHeight()&&(i.textPosition="top",a=!0);var r=a?-5-n.height:p+8;o+n.width/2>d.getWidth()?(i.textPosition=["100%",r],i.textAlign="right"):o-n.width/2<0&&(i.textPosition=[0,r],i.textAlign="left")}})}function t(t,e){var i,n=m[t],o=m[e],a=u[n],r=new Cl(a,h,h.ecModel);if(l&&null!=l.newTitle&&l.featureName===n&&(a.title=l.newTitle),n&&!o){if(function(t){return 0===t.indexOf("my")}(n))i={model:r,onclick:r.option.onclick,featureName:n};else{var s=oA(n);if(!s)return;i=new s(r,c,d)}g[n]=i}else{if(!(i=g[o]))return;i.model=r,i.ecModel=c,i.api=d}n||!o?r.get("show")&&!i.unusable?(function(o,a,t){var r=o.getModel("iconStyle"),s=o.getModel("emphasis.iconStyle"),e=a.getIcons?a.getIcons():o.get("icon"),l=o.get("title")||{};if("string"==typeof e){var i=e,n=l;l={},(e={})[t]=i,l[t]=n}var u=o.iconPaths={};E(e,function(t,e){var i=yl(t,{},{x:-p/2,y:-p/2,width:p,height:p});i.setStyle(r.getItemStyle()),i.hoverStyle=s.getItemStyle(),i.setStyle({text:l[e],textAlign:s.get("textAlign"),textBorderRadius:s.get("textBorderRadius"),textPadding:s.get("textPadding"),textFill:null});var n=h.getModel("tooltip");n&&n.get("show")&&i.attr("tooltip",P({content:l[e],formatter:n.get("formatter",!0)||function(){return l[e]},formatterParams:{componentType:"toolbox",name:e,title:l[e],$vars:["name","title"]},position:n.get("position",!0)||"bottom"},n.option)),$s(i),h.get("showTitle")&&(i.__title=l[e],i.on("mouseover",function(){var t=s.getItemStyle(),e="vertical"===h.get("orient")?null==h.get("right")?"right":"left":null==h.get("bottom")?"bottom":"top";i.setStyle({textFill:s.get("textFill")||t.fill||t.stroke||"#000",textBackgroundColor:s.get("textBackgroundColor"),textPosition:s.get("textPosition")||e})}).on("mouseout",function(){i.setStyle({textFill:null,textBackgroundColor:null})})),i.trigger(o.get("iconStatus."+e)||"normal"),f.add(i),i.on("click",A(a.onclick,a,c,d,e)),u[e]=i})}(r,i,n),r.setIconStatus=function(t,e){var i=this.option,n=this.iconPaths;i.iconStatus=i.iconStatus||{},i.iconStatus[t]=e,n[t]&&n[t].trigger(e)},i.render&&i.render(r,c,d,l)):i.remove&&i.remove(c,d):i.dispose&&i.dispose(c,d)}},updateView:function(t,e,i,n){E(this._features,function(t){t.updateView&&t.updateView(t.model,e,i,n)})},remove:function(e,i){E(this._features,function(t){t.remove&&t.remove(e,i)}),this.group.removeAll()},dispose:function(e,i){E(this._features,function(t){t.dispose&&t.dispose(e,i)})}});var sA=Oc.toolbox.saveAsImage;function lA(t){this.model=t}lA.defaultOption={show:!0,icon:"M4.7,22.9L29.3,45.5L54.7,23.4M4.6,43.6L4.6,58L53.8,58L53.8,43.6M29.2,45.1L29.2,0",title:sA.title,type:"png",connectedBackgroundColor:"#fff",name:"",excludeComponents:["toolbox"],pixelRatio:1,lang:sA.lang.slice()},lA.prototype.unusable=!v.canvasSupported,lA.prototype.onclick=function(t,e){var i=this.model,n=i.get("name")||t.get("title.0.text")||"echarts",o="svg"===e.getZr().painter.getType()?"svg":i.get("type",!0)||"png",a=e.getConnectedDataURL({type:o,backgroundColor:i.get("backgroundColor",!0)||t.get("backgroundColor")||"#fff",connectedBackgroundColor:i.get("connectedBackgroundColor"),excludeComponents:i.get("excludeComponents"),pixelRatio:i.get("pixelRatio")});if("function"!=typeof MouseEvent||v.browser.ie||v.browser.edge)if(window.navigator.msSaveOrOpenBlob){for(var r=atob(a.split(",")[1]),s=r.length,l=new Uint8Array(s);s--;)l[s]=r.charCodeAt(s);var u=new Blob([l]);window.navigator.msSaveOrOpenBlob(u,n+"."+o)}else{var h=i.get("lang"),c='';window.open().document.write(c)}else{var d=document.createElement("a");d.download=n+"."+o,d.target="_blank",d.href=a;var f=new MouseEvent("click",{view:window,bubbles:!0,cancelable:!1});d.dispatchEvent(f)}},nA("saveAsImage",lA);var uA=Oc.toolbox.magicType,hA="__ec_magicType_stack__";function cA(t){this.model=t}cA.defaultOption={show:!0,type:[],icon:{line:"M4.1,28.9h7.1l9.3-22l7.4,38l9.7-19.7l3,12.8h14.9M4.1,58h51.4",bar:"M6.7,22.9h10V48h-10V22.9zM24.9,13h10v35h-10V13zM43.2,2h10v46h-10V2zM3.1,58h53.7",stack:"M8.2,38.4l-8.4,4.1l30.6,15.3L60,42.5l-8.1-4.1l-21.5,11L8.2,38.4z M51.9,30l-8.1,4.2l-13.4,6.9l-13.9-6.9L8.2,30l-8.4,4.2l8.4,4.2l22.2,11l21.5-11l8.1-4.2L51.9,30z M51.9,21.7l-8.1,4.2L35.7,30l-5.3,2.8L24.9,30l-8.4-4.1l-8.3-4.2l-8.4,4.2L8.2,30l8.3,4.2l13.9,6.9l13.4-6.9l8.1-4.2l8.1-4.1L51.9,21.7zM30.4,2.2L-0.2,17.5l8.4,4.1l8.3,4.2l8.4,4.2l5.5,2.7l5.3-2.7l8.1-4.2l8.1-4.2l8.1-4.1L30.4,2.2z"},title:k(uA.title),option:{},seriesIndex:{}};var dA=cA.prototype;dA.getIcons=function(){var t=this.model,e=t.get("icon"),i={};return E(t.get("type"),function(t){e[t]&&(i[t]=e[t])}),i};var fA={line:function(t,e,i,n){if("bar"===t)return m({id:e,type:"line",data:i.get("data"),stack:i.get("stack"),markPoint:i.get("markPoint"),markLine:i.get("markLine")},n.get("option.line")||{},!0)},bar:function(t,e,i,n){if("line"===t)return m({id:e,type:"bar",data:i.get("data"),stack:i.get("stack"),markPoint:i.get("markPoint"),markLine:i.get("markLine")},n.get("option.bar")||{},!0)},stack:function(t,e,i,n){var o=i.get("stack")===hA;if("line"===t||"bar"===t)return n.setIconStatus("stack",o?"normal":"emphasis"),m({id:e,stack:o?"":hA},n.get("option.stack")||{},!0)}},pA=[["line","bar"],["stack"]];dA.onclick=function(u,t,h){var c=this.model,e=c.get("seriesIndex."+h);if(fA[h]){var i,d={series:[]};if(E(pA,function(t){0<=_(t,h)&&E(t,function(t){c.setIconStatus(t,"normal")})}),c.setIconStatus(h,"emphasis"),u.eachComponent({mainType:"series",query:null==e?null:{seriesIndex:e}},function(t){var e=t.subType,i=t.id,n=fA[h](e,i,t,c);n&&(D(n,t.option),d.series.push(n));var o=t.coordinateSystem;if(o&&"cartesian2d"===o.type&&("line"===h||"bar"===h)){var a=o.getAxesByScale("ordinal")[0];if(a){var r=a.dim+"Axis",s=u.queryComponents({mainType:r,index:t.get(name+"Index"),id:t.get(name+"Id")})[0].componentIndex;d[r]=d[r]||[];for(var l=0;l<=s;l++)d[r][s]=d[r][s]||{};d[r][s].boundaryGap="bar"===h}}}),"stack"===h)i=d.series&&d.series[0]&&d.series[0].stack===hA?m({stack:uA.title.tiled},uA.title):k(uA.title);t.dispatchAction({type:"changeMagicType",currentType:h,newOption:d,newTitle:i,featureName:"magicType"})}},_f({type:"changeMagicType",event:"magicTypeChanged",update:"prepareAndUpdate"},function(t,e){e.mergeOption(t.newOption)}),nA("magicType",cA);var gA=Oc.toolbox.dataView,mA=new Array(60).join("-"),vA="\t";function yA(t){var e=function(t){var o={},a=[],r=[];return t.eachRawSeries(function(t){var e=t.coordinateSystem;if(!e||"cartesian2d"!==e.type&&"polar"!==e.type)a.push(t);else{var i=e.getBaseAxis();if("category"===i.type){var n=i.dim+"_"+i.index;o[n]||(o[n]={categoryAxis:i,valueAxis:e.getOtherAxis(i),series:[]},r.push({axisDim:i.dim,axisIndex:i.index})),o[n].series.push(t)}else a.push(t)}}),{seriesGroupByCategoryAxis:o,other:a,meta:r}}(t);return{value:M([function(t){var h=[];return E(t,function(t,e){var i=t.categoryAxis,n=t.valueAxis.dim,o=[" "].concat(O(t.series,function(t){return t.name})),a=[i.model.getCategories()];E(t.series,function(t){a.push(t.getRawData().mapArray(n,function(t){return t}))});for(var r=[o.join(vA)],s=0;st[1]&&t.reverse(),t}function kA(t,e){return Ko(t,e,{includeMainTypes:AA})}CA.setOutputRanges=function(t,e){this.matchOutputRanges(t,e,function(t,e,i){if((t.coordRanges||(t.coordRanges=[])).push(e),!t.coordRange){t.coordRange=e;var n=EA[t.brushType](0,i,e);t.__rangeOffset={offset:zA[t.brushType](n.values,t.range,[1,1]),xyMinMax:n.xyMinMax}}})},CA.matchOutputRanges=function(t,n,o){SA(t,function(i){var t=this.findTargetInfo(i,n);t&&!0!==t&&E(t.coordSyses,function(t){var e=EA[i.brushType](1,t,i.range);o(i,e.values,t,n)})},this)},CA.setInputRanges=function(t,o){SA(t,function(t){var e=this.findTargetInfo(t,o);if(t.range=t.range||[],e&&!0!==e){t.panelId=e.panelId;var i=EA[t.brushType](0,e.coordSys,t.coordRange),n=t.__rangeOffset;t.range=n?zA[t.brushType](i.values,n.offset,function(t,e){var i=VA(t),n=VA(e),o=[i[0]/n[0],i[1]/n[1]];return isNaN(o[0])&&(o[0]=1),isNaN(o[1])&&(o[1]=1),o}(i.xyMinMax,n.xyMinMax)):i.values}},this)},CA.makePanelOpts=function(i,n){return O(this._targetInfoList,function(t){var e=t.getPanelRect();return{panelId:t.panelId,defaultBrushType:n&&n(t),clipPath:eS(e),isTargetByCursor:nS(e,i,t.coordSysModel),getLinearBrushOtherExtent:iS(e)}})},CA.controlSeries=function(t,e,i){var n=this.findTargetInfo(t,i);return!0===n||n&&0<=MA(n.coordSyses,e.coordinateSystem)},CA.findTargetInfo=function(t,e){for(var i=this._targetInfoList,n=kA(e,t),o=0;on[1]&&(n[1]=e[1])})}),n[1]c[1];if(r&&!s&&!l)return!0;r&&(n=!0),s&&(e=!0),l&&(i=!0)}return n&&e&&i}):$A(h,function(t){if("empty"===o)i.setData(u=u.map(t,function(t){return function(t){return t>=c[0]&&t<=c[1]}(t)?t:NaN}));else{var e={};e[t]=c,u.selectRange(e)}}),$A(h,function(t){u.setApproximateExtent(c,t)}))})}}};var tD=E,eD=jA,iD=Tf({type:"dataZoom",dependencies:["xAxis","yAxis","zAxis","radiusAxis","angleAxis","singleAxis","series"],defaultOption:{zlevel:0,z:4,orient:null,xAxisIndex:null,yAxisIndex:null,filterMode:"filter",throttle:null,start:0,end:100,startValue:null,endValue:null,minSpan:null,maxSpan:null,minValueSpan:null,maxValueSpan:null,rangeMode:null},init:function(t,e,i){this._dataIntervalByAxis={},this._dataInfo={},this._axisProxies={},this.textStyleModel,this._autoThrottle=!0,this._rangePropMode=["percent","percent"];var n=nD(t);this.settledOption=n,this.mergeDefaultAndTheme(t,i),this.doInit(n)},mergeOption:function(t){var e=nD(t);m(this.option,t,!0),m(this.settledOption,e,!0),this.doInit(e)},doInit:function(t){var i=this.option;v.canvasSupported||(i.realtime=!1),this._setDefaultThrottle(t),oD(this,t);var n=this.settledOption;tD([["start","startValue"],["end","endValue"]],function(t,e){"value"===this._rangePropMode[e]&&(i[t[0]]=n[t[0]]=null)},this),this.textStyleModel=this.getModel("textStyle"),this._resetTarget(),this._giveAxisProxies()},_giveAxisProxies:function(){var r=this._axisProxies;this.eachTargetAxis(function(t,e,i,n){var o=this.dependentModels[t.axis][e],a=o.__dzAxisProxy||(o.__dzAxisProxy=new KA(t.name,e,this,n));r[t.name+"_"+e]=a},this)},_resetTarget:function(){var i=this.option,t=this._judgeAutoMode();eD(function(t){var e=t.axisIndex;i[e]=Vo(i[e])},this),"axisIndex"===t?this._autoSetAxisIndex():"orient"===t&&this._autoSetOrient()},_judgeAutoMode:function(){var e=this.option,i=!1;eD(function(t){null!=e[t.axisIndex]&&(i=!0)},this);var t=e.orient;return null==t&&i?"orient":i?void 0:(null==t&&(e.orient="horizontal"),"axisIndex")},_autoSetAxisIndex:function(){var a=!0,e=this.get("orient",!0),r=this.option,t=this.dependentModels;if(a){var i="vertical"===e?"y":"x";t[i+"Axis"].length?(r[i+"AxisIndex"]=[0],a=!1):tD(t.singleAxis,function(t){a&&t.get("orient",!0)===e&&(r.singleAxisIndex=[t.componentIndex],a=!1)})}a&&eD(function(t){if(a){var e=[],i=this.dependentModels[t.axis];if(i.length&&!e.length)for(var n=0,o=i.length;ne[0][1]&&(e[0][1]=a[0]),a[1]e[1][1]&&(e[1][1]=a[1])}return e&&UD(e)}};function UD(t){return new Di(t[0][0],t[1][0],t[0][1]-t[0][0],t[1][1]-t[1][0])}var XD=["#ddd"];Tf({type:"brush",dependencies:["geo","grid","xAxis","yAxis","parallel","series"],defaultOption:{toolbox:null,brushLink:null,seriesIndex:"all",geoIndex:null,xAxisIndex:null,yAxisIndex:null,brushType:"rect",brushMode:"single",transformable:!0,brushStyle:{borderWidth:1,color:"rgba(120,140,180,0.3)",borderColor:"rgba(120,140,180,0.8)"},throttleType:"fixRate",throttleDelay:0,removeOnClick:!0,z:1e4},areas:[],brushType:null,brushOption:{},coordInfoList:[],optionUpdated:function(t,e){var i=this.option;e||PD(i,t,["inBrush","outOfBrush"]);var n=i.inBrush=i.inBrush||{};i.outOfBrush=i.outOfBrush||{color:XD},n.hasOwnProperty("liftZ")||(n.liftZ=5)},setAreas:function(t){t&&(this.areas=O(t,function(t){return YD(this.option,t)},this))},setBrushOption:function(t){this.brushOption=YD(this.option,t),this.brushType=this.brushOption.brushType}});function YD(t,e){return m({brushType:t.brushType,brushMode:t.brushMode,transformable:t.transformable,brushStyle:new Cl(t.brushStyle).getItemStyle(),removeOnClick:t.removeOnClick,z:t.z},e,!0)}function jD(t,e,i,n){n&&n.$from===t.id||this._brushController.setPanels(t.brushTargetManager.makePanelOpts(i)).enableBrush(t.brushOption).updateCovers(t.areas.slice())}Af({type:"brush",init:function(t,e){this.ecModel=t,this.api=e,this.model,(this._brushController=new Ib(e.getZr())).on("brush",A(this._onBrush,this)).mount()},render:function(t){return this.model=t,jD.apply(this,arguments)},updateTransform:function(t,e){return GD(e),jD.apply(this,arguments)},updateView:jD,dispose:function(){this._brushController.dispose()},_onBrush:function(t,e){var i=this.model.id;this.model.brushTargetManager.setOutputRanges(t,this.ecModel),e.isEnd&&!e.removeOnClick||this.api.dispatchAction({type:"brush",brushId:i,areas:k(t),$from:i}),e.isEnd&&this.api.dispatchAction({type:"brushEnd",brushId:i,areas:k(t),$from:i})}}),_f({type:"brush",event:"brush"},function(e,t){t.eachComponent({mainType:"brush",query:e},function(t){t.setAreas(e.areas)})}),_f({type:"brushSelect",event:"brushSelected",update:"none"},function(){}),_f({type:"brushEnd",event:"brushEnd",update:"none"},function(){});var qD=Oc.toolbox.brush;function KD(t,e,i){this.model=t,this.ecModel=e,this.api=i,this._brushType,this._brushMode}KD.defaultOption={show:!0,type:["rect","polygon","lineX","lineY","keep","clear"],icon:{rect:"M7.3,34.7 M0.4,10V-0.2h9.8 M89.6,10V-0.2h-9.8 M0.4,60v10.2h9.8 M89.6,60v10.2h-9.8 M12.3,22.4V10.5h13.1 M33.6,10.5h7.8 M49.1,10.5h7.8 M77.5,22.4V10.5h-13 M12.3,31.1v8.2 M77.7,31.1v8.2 M12.3,47.6v11.9h13.1 M33.6,59.5h7.6 M49.1,59.5 h7.7 M77.5,47.6v11.9h-13",polygon:"M55.2,34.9c1.7,0,3.1,1.4,3.1,3.1s-1.4,3.1-3.1,3.1 s-3.1-1.4-3.1-3.1S53.5,34.9,55.2,34.9z M50.4,51c1.7,0,3.1,1.4,3.1,3.1c0,1.7-1.4,3.1-3.1,3.1c-1.7,0-3.1-1.4-3.1-3.1 C47.3,52.4,48.7,51,50.4,51z M55.6,37.1l1.5-7.8 M60.1,13.5l1.6-8.7l-7.8,4 M59,19l-1,5.3 M24,16.1l6.4,4.9l6.4-3.3 M48.5,11.6 l-5.9,3.1 M19.1,12.8L9.7,5.1l1.1,7.7 M13.4,29.8l1,7.3l6.6,1.6 M11.6,18.4l1,6.1 M32.8,41.9 M26.6,40.4 M27.3,40.2l6.1,1.6 M49.9,52.1l-5.6-7.6l-4.9-1.2",lineX:"M15.2,30 M19.7,15.6V1.9H29 M34.8,1.9H40.4 M55.3,15.6V1.9H45.9 M19.7,44.4V58.1H29 M34.8,58.1H40.4 M55.3,44.4 V58.1H45.9 M12.5,20.3l-9.4,9.6l9.6,9.8 M3.1,29.9h16.5 M62.5,20.3l9.4,9.6L62.3,39.7 M71.9,29.9H55.4",lineY:"M38.8,7.7 M52.7,12h13.2v9 M65.9,26.6V32 M52.7,46.3h13.2v-9 M24.9,12H11.8v9 M11.8,26.6V32 M24.9,46.3H11.8v-9 M48.2,5.1l-9.3-9l-9.4,9.2 M38.9-3.9V12 M48.2,53.3l-9.3,9l-9.4-9.2 M38.9,62.3V46.4",keep:"M4,10.5V1h10.3 M20.7,1h6.1 M33,1h6.1 M55.4,10.5V1H45.2 M4,17.3v6.6 M55.6,17.3v6.6 M4,30.5V40h10.3 M20.7,40 h6.1 M33,40h6.1 M55.4,30.5V40H45.2 M21,18.9h62.9v48.6H21V18.9z",clear:"M22,14.7l30.9,31 M52.9,14.7L22,45.7 M4.7,16.8V4.2h13.1 M26,4.2h7.8 M41.6,4.2h7.8 M70.3,16.8V4.2H57.2 M4.7,25.9v8.6 M70.3,25.9v8.6 M4.7,43.2v12.6h13.1 M26,55.8h7.8 M41.6,55.8h7.8 M70.3,43.2v12.6H57.2"},title:k(qD.title)};var $D=KD.prototype;$D.render=$D.updateView=function(e,t,i){var n,o,a;t.eachComponent({mainType:"brush"},function(t){n=t.brushType,o=t.brushOption.brushMode||"single",a|=t.areas.length}),this._brushType=n,this._brushMode=o,E(e.get("type",!0),function(t){e.setIconStatus(t,("keep"===t?"multiple"===o:"clear"===t?a:t===n)?"emphasis":"normal")})},$D.getIcons=function(){var t=this.model,e=t.get("icon",!0),i={};return E(t.get("type",!0),function(t){e[t]&&(i[t]=e[t])}),i},$D.onclick=function(t,e,i){var n=this._brushType,o=this._brushMode;"clear"===i?(e.dispatchAction({type:"axisAreaSelect",intervals:[]}),e.dispatchAction({type:"brush",command:"clear",areas:[]})):e.dispatchAction({type:"takeGlobalCursor",key:"brush",brushOption:{brushType:"keep"===i?n:n!==i&&i,brushMode:"keep"===i?"multiple"===o?"single":"multiple":o}})},nA("brush",KD),yf(function(t,e){var i=t&&t.brush;if(L(i)||(i=i?[i]:[]),i.length){var n=[];E(i,function(t){var e=t.hasOwnProperty("toolbox")?t.toolbox:[];e instanceof Array&&(n=n.concat(e))});var o=t&&t.toolbox;L(o)&&(o=o[0]),o||(o={feature:{}},t.toolbox=[o]);var a=o.feature||(o.feature={}),r=a.brush||(a.brush={}),s=r.type||(r.type=[]);s.push.apply(s,n),function(i){var e={};E(i,function(t){e[t]=1}),i.length=0,E(e,function(t,e){i.push(e)})}(s),e&&!s.length&&s.push.apply(s,DD)}}),Tf({type:"title",layoutMode:{type:"box",ignoreSize:!0},defaultOption:{zlevel:0,z:6,show:!0,text:"",target:"blank",subtext:"",subtarget:"blank",left:0,top:0,backgroundColor:"rgba(0,0,0,0)",borderColor:"#ccc",borderWidth:0,padding:5,itemGap:10,textStyle:{fontSize:18,fontWeight:"bolder",color:"#333"},subtextStyle:{color:"#aaa"}}}),Af({type:"title",render:function(t,e,i){if(this.group.removeAll(),t.get("show")){var n=this.group,o=t.getModel("textStyle"),a=t.getModel("subtextStyle"),r=t.get("textAlign"),s=H(t.get("textBaseline"),t.get("textVerticalAlign")),l=new Ur({style:nl({},o,{text:t.get("text"),textFill:o.getTextColor()},{disableBox:!0}),z2:10}),u=l.getBoundingRect(),h=t.get("subtext"),c=new Ur({style:nl({},a,{text:h,textFill:a.getTextColor(),y:u.height+t.get("itemGap"),textVerticalAlign:"top"},{disableBox:!0}),z2:10}),d=t.get("link"),f=t.get("sublink"),p=t.get("triggerEvent",!0);l.silent=!d&&!p,c.silent=!f&&!p,d&&l.on("click",function(){gu(d,"_"+t.get("target"))}),f&&c.on("click",function(){gu(d,"_"+t.get("subtarget"))}),l.eventData=c.eventData=p?{componentType:"title",componentIndex:t.componentIndex}:null,n.add(l),h&&n.add(c);var g=n.getBoundingRect(),m=t.getBoxLayoutParams();m.width=g.width,m.height=g.height;var v=bu(m,{width:i.getWidth(),height:i.getHeight()},t.get("padding"));r||("middle"===(r=t.get("left")||t.get("right"))&&(r="center"),"right"===r?v.x+=v.width:"center"===r&&(v.x+=v.width/2)),s||("center"===(s=t.get("top")||t.get("bottom"))&&(s="middle"),"bottom"===s?v.y+=v.height:"middle"===s&&(v.y+=v.height/2),s=s||"top"),n.attr("position",[v.x,v.y]);var y={textAlign:r,textVerticalAlign:s};l.setStyle(y),c.setStyle(y),g=n.getBoundingRect();var x=v.margin,_=t.getItemStyle(["color","opacity"]);_.fill=t.get("backgroundColor");var w=new rs({shape:{x:g.x-x[3],y:g.y-x[0],width:g.width+x[1]+x[3],height:g.height+x[0]+x[2],r:t.get("borderRadius")},style:_,subPixelOptimize:!0,silent:!0});n.add(w)}}});function JD(t){var e=t.itemStyle||(t.itemStyle={}),i=e.emphasis||(e.emphasis={}),n=t.label||t.label||{},o=n.normal||(n.normal={}),a={normal:1,emphasis:1};E(n,function(t,e){a[e]||QD(o,e)||(o[e]=t)}),i.label&&!QD(n,"emphasis")&&(n.emphasis=i.label,delete i.label)}function QD(t,e){return t.hasOwnProperty(e)}ku.registerSubTypeDefaulter("timeline",function(){return"slider"}),_f({type:"timelineChange",event:"timelineChanged",update:"prepareAndUpdate"},function(t,e){var i=e.getComponent("timeline");return i&&null!=t.currentIndex&&(i.setCurrentIndex(t.currentIndex),!i.get("loop",!0)&&i.isIndexMax()&&i.setPlayState(!1)),e.resetOption("timeline"),D({currentIndex:i.option.currentIndex},t)}),_f({type:"timelinePlayChange",event:"timelinePlayChanged",update:"update"},function(t,e){var i=e.getComponent("timeline");i&&null!=t.playState&&i.setPlayState(t.playState)});var tC=ku.extend({type:"timeline",layoutMode:"box",defaultOption:{zlevel:0,z:4,show:!0,axisType:"time",realtime:!0,left:"20%",top:null,right:"20%",bottom:0,width:null,height:40,padding:5,controlPosition:"left",autoPlay:!1,rewind:!1,loop:!0,playInterval:2e3,currentIndex:0,itemStyle:{},label:{color:"#000"},data:[]},init:function(t,e,i){this._data,this._names,this.mergeDefaultAndTheme(t,i),this._initData()},mergeOption:function(t){tC.superApply(this,"mergeOption",arguments),this._initData()},setCurrentIndex:function(t){null==t&&(t=this.option.currentIndex);var e=this._data.count();this.option.loop?t=(t%e+e)%e:(e<=t&&(t=e-1),t<0&&(t=0)),this.option.currentIndex=t},getCurrentIndex:function(){return this.option.currentIndex},isIndexMax:function(){return this.getCurrentIndex()>=this._data.count()-1},setPlayState:function(t){this.option.autoPlay=!!t},getPlayState:function(){return!!this.option.autoPlay},_initData:function(){var t=this.option,e=t.data||[],i=t.axisType,o=this._names=[];if("category"===i){var a=[];E(e,function(t,e){var i,n=Wo(t);z(t)?(i=k(t)).value=e:i=e,a.push(i),R(n)||null!=n&&!isNaN(n)||(n=""),o.push(n+"")}),e=a}var n={category:"ordinal",time:"time"}[i]||"number";(this._data=new Yf([{name:"value",type:n}],this)).initData(e,o)},getData:function(){return this._data},getCategories:function(){if("category"===this.get("axisType"))return this._names.slice()}});b(tC.extend({type:"timeline.slider",defaultOption:{backgroundColor:"rgba(0,0,0,0)",borderColor:"#ccc",borderWidth:0,orient:"horizontal",inverse:!1,tooltip:{trigger:"item"},symbol:"emptyCircle",symbolSize:10,lineStyle:{show:!0,width:2,color:"#304654"},label:{position:"auto",show:!0,interval:"auto",rotate:0,color:"#304654"},itemStyle:{color:"#304654",borderWidth:1},checkpointStyle:{symbol:"circle",symbolSize:13,color:"#c23531",borderWidth:5,borderColor:"rgba(194,53,49, 0.5)",animation:!0,animationDuration:300,animationEasing:"quinticInOut"},controlStyle:{show:!0,showPlayBtn:!0,showPrevBtn:!0,showNextBtn:!0,itemSize:22,itemGap:12,position:"left",playIcon:"path://M31.6,53C17.5,53,6,41.5,6,27.4S17.5,1.8,31.6,1.8C45.7,1.8,57.2,13.3,57.2,27.4S45.7,53,31.6,53z M31.6,3.3 C18.4,3.3,7.5,14.1,7.5,27.4c0,13.3,10.8,24.1,24.1,24.1C44.9,51.5,55.7,40.7,55.7,27.4C55.7,14.1,44.9,3.3,31.6,3.3z M24.9,21.3 c0-2.2,1.6-3.1,3.5-2l10.5,6.1c1.899,1.1,1.899,2.9,0,4l-10.5,6.1c-1.9,1.1-3.5,0.2-3.5-2V21.3z",stopIcon:"path://M30.9,53.2C16.8,53.2,5.3,41.7,5.3,27.6S16.8,2,30.9,2C45,2,56.4,13.5,56.4,27.6S45,53.2,30.9,53.2z M30.9,3.5C17.6,3.5,6.8,14.4,6.8,27.6c0,13.3,10.8,24.1,24.101,24.1C44.2,51.7,55,40.9,55,27.6C54.9,14.4,44.1,3.5,30.9,3.5z M36.9,35.8c0,0.601-0.4,1-0.9,1h-1.3c-0.5,0-0.9-0.399-0.9-1V19.5c0-0.6,0.4-1,0.9-1H36c0.5,0,0.9,0.4,0.9,1V35.8z M27.8,35.8 c0,0.601-0.4,1-0.9,1h-1.3c-0.5,0-0.9-0.399-0.9-1V19.5c0-0.6,0.4-1,0.9-1H27c0.5,0,0.9,0.4,0.9,1L27.8,35.8L27.8,35.8z",nextIcon:"path://M18.6,50.8l22.5-22.5c0.2-0.2,0.3-0.4,0.3-0.7c0-0.3-0.1-0.5-0.3-0.7L18.7,4.4c-0.1-0.1-0.2-0.3-0.2-0.5 c0-0.4,0.3-0.8,0.8-0.8c0.2,0,0.5,0.1,0.6,0.3l23.5,23.5l0,0c0.2,0.2,0.3,0.4,0.3,0.7c0,0.3-0.1,0.5-0.3,0.7l-0.1,0.1L19.7,52 c-0.1,0.1-0.3,0.2-0.5,0.2c-0.4,0-0.8-0.3-0.8-0.8C18.4,51.2,18.5,51,18.6,50.8z",prevIcon:"path://M43,52.8L20.4,30.3c-0.2-0.2-0.3-0.4-0.3-0.7c0-0.3,0.1-0.5,0.3-0.7L42.9,6.4c0.1-0.1,0.2-0.3,0.2-0.5 c0-0.4-0.3-0.8-0.8-0.8c-0.2,0-0.5,0.1-0.6,0.3L18.3,28.8l0,0c-0.2,0.2-0.3,0.4-0.3,0.7c0,0.3,0.1,0.5,0.3,0.7l0.1,0.1L41.9,54 c0.1,0.1,0.3,0.2,0.5,0.2c0.4,0,0.8-0.3,0.8-0.8C43.2,53.2,43.1,53,43,52.8z",color:"#304654",borderColor:"#304654",borderWidth:1},emphasis:{label:{show:!0,color:"#c23531"},itemStyle:{color:"#c23531"},controlStyle:{color:"#c23531",borderColor:"#c23531",borderWidth:2}},data:[]}}),Xh);function eC(t,e,i,n){Gg.call(this,t,e,i),this.type=n||"value",this.model=null}var iC=gc.extend({type:"timeline"});eC.prototype={constructor:eC,getLabelModel:function(){return this.model.getModel("label")},isHorizontal:function(){return"horizontal"===this.model.get("orient")}},w(eC,Gg);var nC=A,oC=E,aC=Math.PI;function rC(t,e,i,n,o,a){var r=e.get("color");o?(o.setColor(r),i.add(o),a&&a.onUpdate(o)):((o=wg(t.get("symbol"),-1,-1,2,2,r)).setStyle("strokeNoScale",!0),i.add(o),a&&a.onCreate(o));var s=e.getItemStyle(["color","symbol","symbolSize"]);o.setStyle(s),n=m({rectHover:!0,z2:100},n,!0);var l=t.get("symbolSize");(l=l instanceof Array?l.slice():[+l,+l])[0]/=2,l[1]/=2,n.scale=l;var u=t.get("symbolOffset");if(u){var h=n.position=n.position||[0,0];h[0]+=Rl(u[0],l[0]),h[1]+=Rl(u[1],l[1])}var c=t.get("symbolRotate");return n.rotation=(c||0)*Math.PI/180||0,o.attr(n),o.updateTransform(),o}function sC(t,e,i,n,o){if(!t.dragging){var a=n.getModel("checkpointStyle"),r=i.dataToCoord(n.getData().get(["value"],e));o||!a.get("animation",!0)?t.attr({position:[r,0]}):(t.stopAnimation(!0),t.animateTo({position:[r,0]},a.get("animationDuration",!0),a.get("animationEasing",!0)))}}iC.extend({type:"timeline.slider",init:function(t,e){this.api=e,this._axis,this._viewRect,this._timer,this._currentPointer,this._mainGroup,this._labelGroup},render:function(e,t,i,n){if(this.model=e,this.api=i,this.ecModel=t,this.group.removeAll(),e.get("show",!0)){var o=this._layout(e,i),a=this._createGroup("mainGroup"),r=this._createGroup("labelGroup"),s=this._axis=this._createAxis(o,e);e.formatTooltip=function(t){return au(s.scale.getLabel(t))},oC(["AxisLine","AxisTick","Control","CurrentPointer"],function(t){this["_render"+t](o,a,s,e)},this),this._renderAxisLabel(o,r,s,e),this._position(o,e)}this._doPlayStop()},remove:function(){this._clearTimer(),this.group.removeAll()},dispose:function(){this._clearTimer()},_layout:function(t,e){var i=t.get("label.position"),n=t.get("orient"),o=function(t,e){return bu(t.getBoxLayoutParams(),{width:e.getWidth(),height:e.getHeight()},t.get("padding"))}(t,e);null==i||"auto"===i?i="horizontal"===n?o.y+o.height/2n[1]&&(i=n[1]),i"),o&&(a+=uC(o),null!=i&&(a+=" : ")),null!=i&&(a+=uC(n)),a},getData:function(){return this._data},setData:function(t){this._data=t}});b(cC,Xh),cC.extend({type:"markPoint",defaultOption:{zlevel:0,z:5,symbol:"pin",symbolSize:50,tooltip:{trigger:"item"},label:{show:!0,position:"inside"},itemStyle:{borderWidth:2},emphasis:{label:{show:!0}}}});var dC=_;function fC(t,e,i,n,o,a){var r=[],s=fp(e,n)?e.getCalculationInfo("stackResultDimension"):n,l=_C(e,s,t),u=e.indicesOfNearest(s,l)[0];r[o]=e.get(i,u),r[a]=e.get(s,u);var h=e.get(n,u),c=Vl(e.get(n,u));return 0<=(c=Math.min(c,20))&&(r[a]=+r[a].toFixed(c)),[r,h]}var pC=T,gC={min:pC(fC,"min"),max:pC(fC,"max"),average:pC(fC,"average")};function mC(t,e){var i=t.getData(),n=t.coordinateSystem;if(e&&!function(t){return!isNaN(parseFloat(t.x))&&!isNaN(parseFloat(t.y))}(e)&&!L(e.coord)&&n){var o=n.dimensions,a=vC(e,i,n,t);if((e=k(e)).type&&gC[e.type]&&a.baseAxis&&a.valueAxis){var r=dC(o,a.baseAxis.dim),s=dC(o,a.valueAxis.dim),l=gC[e.type](i,a.baseDataDim,a.valueDataDim,r,s);e.coord=l[0],e.value=l[1]}else{for(var u=[null!=e.xAxis?e.xAxis:e.radiusAxis,null!=e.yAxis?e.yAxis:e.angleAxis],h=0;h<2;h++)gC[u[h]]&&(u[h]=_C(i,i.mapDimension(o[h]),u[h]));e.coord=u}}return e}function vC(t,e,i,n){var o={};return null!=t.valueIndex||null!=t.valueDim?(o.valueDataDim=null!=t.valueIndex?e.getDimension(t.valueIndex):t.valueDim,o.valueAxis=i.getAxis(function(t,e){var i=t.getData(),n=i.dimensions;e=i.getDimension(e);for(var o=0;oi[o],f=[-h.x,-h.y];e||(f[n]=s.position[n]);var p=[0,0],g=[-c.x,-c.y],m=H(t.get("pageButtonGap",!0),t.get("itemGap",!0));d&&("end"===t.get("pageButtonPosition",!0)?g[n]+=i[o]-c[o]:p[n]+=c[o]+m);g[1-n]+=h[a]/2-c[a]/2,s.attr("position",f),l.attr("position",p),u.attr("position",g);var v={x:0,y:0};if(v[o]=d?i[o]:h[o],v[a]=Math.max(h[a],c[a]),v[r]=Math.min(0,c[r]+g[1-n]),l.__rectSize=i[o],d){var y={x:0,y:0};y[o]=Math.max(i[o]-c[o]-m,0),y[a]=v[a],l.setClipPath(new rs({shape:y})),l.__rectSize=y[o]}else u.eachChild(function(t){t.attr({invisible:!0,silent:!0})});var x=this._getPageInfo(t);return null!=x.pageIndex&&cl(s,{position:x.contentPosition},d&&t),this._updatePageInfoView(t,x),v},_pageGo:function(t,e,i){var n=this._getPageInfo(e)[t];null!=n&&i.dispatchAction({type:"legendScroll",scrollDataIndex:n,legendId:e.id})},_updatePageInfoView:function(n,o){var a=this._controllerGroup;E(["pagePrev","pageNext"],function(t){var e=null!=o[t+"DataIndex"],i=a.childOfName(t);i&&(i.setStyle("fill",e?n.get("pageIconColor",!0):n.get("pageIconInactiveColor",!0)),i.cursor=e?"pointer":"default")});var t=a.childOfName("pageText"),e=n.get("pageFormatter"),i=o.pageIndex,r=null!=i?i+1:0,s=o.pageCount;t&&e&&t.setStyle("text",R(e)?e.replace("{current}",r).replace("{total}",s):e({current:r,total:s}))},_getPageInfo:function(t){var e=t.get("scrollDataIndex",!0),i=this.getContentGroup(),n=this._containerGroup.__rectSize,o=t.getOrient().index,a=qC[o],r=KC[o],s=this._findTargetItemIndex(e),l=i.children(),u=l[s],h=l.length,c=h?1:0,d={contentPosition:i.position.slice(),pageCount:c,pageIndex:c-1,pagePrevDataIndex:null,pageNextDataIndex:null};if(!u)return d;var f=y(u);d.contentPosition[o]=-f.s;for(var p=s+1,g=f,m=f,v=null;p<=h;++p)(!(v=y(l[p]))&&m.e>g.s+n||v&&!x(v,g.s))&&(g=m.i>g.i?m:v)&&(null==d.pageNextDataIndex&&(d.pageNextDataIndex=g.i),++d.pageCount),m=v;for(p=s-1,g=f,m=f,v=null;-1<=p;--p)(v=y(l[p]))&&x(m,v.s)||!(g.i=e&&t.s<=e+n}},_findTargetItemIndex:function(n){return this._showController?(this.getContentGroup().eachChild(function(t,e){var i=t.__legendDataIndex;null==a&&null!=i&&(a=e),i===n&&(o=e)}),null!=o?o:a):0;var o,a}});_f("legendScroll","legendscroll",function(t,e){var i=t.scrollDataIndex;null!=i&&e.eachComponent({mainType:"legend",subType:"scroll",query:t},function(t){t.setScrollDataIndex(i)})});iD.extend({type:"dataZoom.slider",layoutMode:"box",defaultOption:{show:!0,right:"ph",top:"ph",width:"ph",height:"ph",left:null,bottom:null,backgroundColor:"rgba(47,69,84,0)",dataBackground:{lineStyle:{color:"#2f4554",width:.5,opacity:.3},areaStyle:{color:"rgba(47,69,84,0.3)",opacity:.3}},borderColor:"#ddd",fillerColor:"rgba(167,183,204,0.4)",handleIcon:"M8.2,13.6V3.9H6.3v9.7H3.1v14.9h3.3v9.7h1.8v-9.7h3.3V13.6H8.2z M9.7,24.4H4.8v-1.4h4.9V24.4z M9.7,19.1H4.8v-1.4h4.9V19.1z",handleSize:"100%",handleStyle:{color:"#a7b7cc"},labelPrecision:null,labelFormatter:null,showDetail:!0,showDataShadow:"auto",realtime:!0,zoomLock:!1,textStyle:{color:"#333"}}});var JC=rs,QC=El,tL=Bl,eL=A,iL=E,nL="horizontal",oL="vertical",aL=["line","bar","candlestick","scatter"],rL=aD.extend({type:"dataZoom.slider",init:function(t,e){this._displayables={},this._orient,this._range,this._handleEnds,this._size,this._handleWidth,this._handleHeight,this._location,this._dragging,this._dataShadowInfo,this.api=e},render:function(t,e,i,n){rL.superApply(this,"render",arguments),kc(this,"_dispatchZoomAction",this.dataZoomModel.get("throttle"),"fixRate"),this._orient=t.get("orient"),!1!==this.dataZoomModel.get("show")?(n&&"dataZoom"===n.type&&n.from===this.uid||this._buildView(),this._updateView()):this.group.removeAll()},remove:function(){rL.superApply(this,"remove",arguments),Pc(this,"_dispatchZoomAction")},dispose:function(){rL.superApply(this,"dispose",arguments),Pc(this,"_dispatchZoomAction")},_buildView:function(){var t=this.group;t.removeAll(),this._resetLocation(),this._resetInterval();var e=this._displayables.barGroup=new Ci;this._renderBackground(),this._renderHandle(),this._renderDataShadow(),t.add(e),this._positionGroup()},_resetLocation:function(){var t=this.dataZoomModel,e=this.api,i=this._findCoordRect(),n={width:e.getWidth(),height:e.getHeight()},o=this._orient===nL?{right:n.width-i.x-i.width,top:n.height-30-7,width:i.width,height:30}:{right:7,top:i.y,width:30,height:i.height},a=Iu(t.option);E(["right","top","width","height"],function(t){"ph"===a[t]&&(a[t]=o[t])});var r=bu(a,n,t.padding);this._location={x:r.x,y:r.y},this._size=[r.width,r.height],this._orient===oL&&this._size.reverse()},_positionGroup:function(){var t=this.group,e=this._location,i=this._orient,n=this.dataZoomModel.getFirstTargetAxisModel(),o=n&&n.get("inverse"),a=this._displayables.barGroup,r=(this._dataShadowInfo||{}).otherAxisInverse;a.attr(i!==nL||o?i===nL&&o?{scale:r?[-1,1]:[-1,-1]}:i!==oL||o?{scale:r?[-1,-1]:[-1,1],rotation:Math.PI/2}:{scale:r?[1,-1]:[1,1],rotation:Math.PI/2}:{scale:r?[1,1]:[1,-1]});var s=t.getBoundingRect([a]);t.attr("position",[e.x-s.x,e.y-s.y])},_getViewExtent:function(){return[0,this._size[0]]},_renderBackground:function(){var t=this.dataZoomModel,e=this._size,i=this._displayables.barGroup;i.add(new JC({silent:!0,shape:{x:0,y:0,width:e[0],height:e[1]},style:{fill:t.get("backgroundColor")},z2:-40})),i.add(new JC({shape:{x:0,y:0,width:e[0],height:e[1]},style:{fill:"transparent"},z2:0,onclick:A(this._onClickPanelClick,this)}))},_renderDataShadow:function(){var t=this._dataShadowInfo=this._prepareDataShadowInfo();if(t){var e=this._size,i=t.series,n=i.getRawData(),o=i.getShadowDim?i.getShadowDim():t.otherDim;if(null!=o){var a=n.getDataExtent(o),r=.3*(a[1]-a[0]);a=[a[0]-r,a[1]+r];var s,l=[0,e[1]],u=[0,e[0]],h=[[e[0],0],[0,0]],c=[],d=u[1]/(n.count()-1),f=0,p=Math.round(n.count()/e[0]);n.each([o],function(t,e){if(0e[0]||i[1]<0||i[1]>e[1])){var n=this._handleEnds,o=(n[0]+n[1])/2,a=this._updateInterval("all",i[0]-o);this._updateView(),a&&this._dispatchZoomAction()}},_dispatchZoomAction:function(){var t=this._range;this.api.dispatchAction({type:"dataZoom",from:this.uid,dataZoomId:this.dataZoomModel.id,start:t[0],end:t[1]})},_findCoordRect:function(){var i;if(iL(this.getTargetCoordInfo(),function(t){if(!i&&t.length){var e=t[0].model.coordinateSystem;i=e.getRect&&e.getRect()}}),!i){var t=this.api.getWidth(),e=this.api.getHeight();i={x:.2*t,y:.2*e,width:.6*t,height:.6*e}}return i}});function sL(t){return"vertical"===t?"ns-resize":"ew-resize"}iD.extend({type:"dataZoom.inside",defaultOption:{disabled:!1,zoomLock:!1,zoomOnMouseWheel:!0,moveOnMouseMove:!0,moveOnMouseWheel:!1,preventDefaultMouseMove:!0}});var lL="\0_ec_dataZoom_roams";function uL(t,n){var e=cL(t),o=n.dataZoomId,a=n.coordId;E(e,function(t,e){var i=t.dataZoomInfos;i[o]&&_(n.allCoordIds,a)<0&&(delete i[o],t.count--)}),dL(e);var i=e[a];i||((i=e[a]={coordId:a,dataZoomInfos:{},count:0}).controller=function(t,r){var e=new Vy(t.getZr());return E(["pan","zoom","scrollMove"],function(a){e.on(a,function(n){var o=[];E(r.dataZoomInfos,function(t){if(n.isAvailableBehavior(t.dataZoomModel.option)){var e=(t.getRange||{})[a],i=e&&e(r.controller,n);!t.dataZoomModel.get("disabled",!0)&&i&&o.push({dataZoomId:t.dataZoomId,start:i[0],end:i[1]})}}),o.length&&r.dispatchAction(o)})}),e}(t,i),i.dispatchAction=T(fL,t)),i.dataZoomInfos[o]||i.count++,i.dataZoomInfos[o]=n;var r=function(t){var n,o={type_true:2,type_move:1,type_false:0,type_undefined:-1},a=!0;return E(t,function(t){var e=t.dataZoomModel,i=!e.get("disabled",!0)&&(!e.get("zoomLock",!0)||"move");o["type_"+n]"],L(t)&&(t=t.slice(),n=!0),o=e?t:n?[u(t[0]),u(t[1])]:u(t),R(l)?l.replace("{value}",n?o[0]:o).replace("{value2}",n?o[1]:o):C(l)?n?l(t[0],t[1]):l(t):n?t[0]===s[0]?i[0]+" "+o[1]:t[1]===s[1]?i[1]+" "+o[0]:o[0]+" - "+o[1]:o;function u(t){return t===s[0]?"min":t===s[1]?"max":(+t).toFixed(Math.min(r,20))}},resetExtent:function(){var t=this.option,e=LL([t.min,t.max]);this._dataExtent=e},getDataDimension:function(t){var e=this.option.dimension,i=t.dimensions;if(null!=e||i.length){if(null!=e)return t.getDimension(e);for(var n=t.dimensions,o=n.length-1;0<=o;o--){var a=n[o];if(!t.getDimensionInfo(a).isCalculationCoord)return a}}},getExtent:function(){return this._dataExtent.slice()},completeVisualOption:function(){var t=this.ecModel,e=this.option,i={inRange:e.inRange,outOfRange:e.outOfRange},n=e.target||(e.target={}),o=e.controller||(e.controller={});m(n,i),m(o,i);var u=this.isCategory();function a(n){DL(e.color)&&!n.inRange&&(n.inRange={color:e.color.slice().reverse()}),n.inRange=n.inRange||{color:t.get("gradientColor")},CL(this.stateList,function(t){var e=n[t];if(R(e)){var i=ML(e,"active",u);i?(n[t]={},n[t][e]=i):delete n[t]}},this)}a.call(this,n),a.call(this,o),function(t,e,i){var n=t[e],o=t[i];n&&!o&&(o=t[i]={},CL(n,function(t,e){if(g_.isValidType(e)){var i=ML(e,"inactive",u);null!=i&&(o[e]=i,"color"!==e||o.hasOwnProperty("opacity")||o.hasOwnProperty("colorAlpha")||(o.opacity=[0,0]))}}))}.call(this,n,"inRange","outOfRange"),function(a){var r=(a.inRange||{}).symbol||(a.outOfRange||{}).symbol,s=(a.inRange||{}).symbolSize||(a.outOfRange||{}).symbolSize,l=this.get("inactiveColor");CL(this.stateList,function(t){var e=this.itemSize,i=a[t];null==(i=i||(a[t]={color:u?l:[l]})).symbol&&(i.symbol=r&&k(r)||(u?"roundRect":["roundRect"])),null==i.symbolSize&&(i.symbolSize=s&&k(s)||(u?e[0]:[e[0],e[0]])),i.symbol=TL(i.symbol,function(t){return"none"===t||"square"===t?"roundRect":t});var n=i.symbolSize;if(null!=n){var o=-1/0;AL(n,function(t){oe[1]&&e.reverse(),e[0]=Math.max(e[0],t[0]),e[1]=Math.min(e[1],t[1]))},completeVisualOption:function(){PL.prototype.completeVisualOption.apply(this,arguments),E(this.stateList,function(t){var e=this.option.controller[t].symbolSize;e&&e[0]!==e[1]&&(e[0]=0)},this)},setSelected:function(t){this.option.range=t.slice(),this._resetRange()},getSelected:function(){var t=this.getExtent(),e=Bl((this.get("range")||[]).slice());return e[0]>t[1]&&(e[0]=t[1]),e[1]>t[1]&&(e[1]=t[1]),e[0]=i[1]||t<=e[1])?"inRange":"outOfRange"},findTargetDataIndices:function(n){var o=[];return this.eachTargetSeries(function(t){var i=[],e=t.getData();e.each(this.getDataDimension(e),function(t,e){n[0]<=t&&t<=n[1]&&i.push(e)},this),o.push({seriesId:t.id,dataIndex:i})},this),o},getVisualMeta:function(i){var t=EL(this,"outOfRange",this.getExtent()),e=EL(this,"inRange",this.option.range.slice()),n=[];function o(t,e){n.push({value:t,color:i(t,e)})}for(var a=0,r=0,s=e.length,l=t.length;rt[1])break;i.push({color:this.getControllerVisual(a,"color",e),offset:o/100})}return i.push({color:this.getControllerVisual(t[1],"color",e),offset:1}),i},_createBarPoints:function(t,e){var i=this.visualMapModel.itemSize;return[[i[0]-e[0],t[0]],[i[0],t[0]],[i[0],t[1]],[i[0]-e[1],t[1]]]},_createBarGroup:function(t){var e=this._orient,i=this.visualMapModel.get("inverse");return new Ci("horizontal"!==e||i?"horizontal"===e&&i?{scale:"bottom"===t?[-1,1]:[1,1],rotation:-Math.PI/2}:"vertical"!==e||i?{scale:"left"===t?[1,1]:[-1,1]}:{scale:"left"===t?[1,-1]:[-1,-1]}:{scale:"bottom"===t?[1,1]:[-1,1],rotation:Math.PI/2})},_updateHandle:function(n,o){if(this._useHandle){var a=this._shapes,r=this.visualMapModel,s=a.handleThumbs,l=a.handleLabels;GL([0,1],function(t){var e=s[t];e.setStyle("fill",o.handlesColor[t]),e.position[1]=n[t];var i=pl(a.handleLabelPoints[t],fl(e,this.group));l[t].setStyle({x:i[0],y:i[1],text:r.formatValueText(this._dataInterval[t]),textVerticalAlign:"middle",textAlign:this._applyTransform("horizontal"===this._orient?0===t?"bottom":"top":"left",a.barGroup)})},this)}},_showIndicator:function(t,e,i,n){var o=this.visualMapModel,a=o.getExtent(),r=o.itemSize,s=[0,r[1]],l=VL(t,a,s,!0),u=this._shapes,h=u.indicator;if(h){h.position[1]=l,h.attr("invisible",!1),h.setShape("points",function(t,e,i,n){return t?[[0,-FL(e,WL(i,0))],[6,0],[0,FL(e,WL(n-i,0))]]:[[0,0],[5,-5],[5,5]]}(!!i,n,l,r[1]));var c=this.getControllerVisual(t,"color",{convertOpacityToAlpha:!0});h.setStyle("fill",c);var d=pl(u.indicatorLabelPoint,fl(h,this.group)),f=u.indicatorLabel;f.attr("invisible",!1);var p=this._applyTransform("left",u.barGroup),g=this._orient;f.setStyle({text:(i||"")+o.formatValueText(e),textVerticalAlign:"horizontal"===g?p:"middle",textAlign:"horizontal"===g?"center":p,x:d[0],y:d[1]})}},_enableHoverLinkToSeries:function(){var n=this;this._shapes.barGroup.on("mousemove",function(t){if(n._hovering=!0,!n._dragging){var e=n.visualMapModel.itemSize,i=n._applyTransform([t.offsetX,t.offsetY],n._shapes.barGroup,!0,!0);i[1]=FL(WL(0,i[1]),e[1]),n._doHoverLinkToSeries(i[1],0<=i[0]&&i[0]<=e[0])}}).on("mouseout",function(){n._hovering=!1,n._dragging||n._clearHoverLinkToSeries()})},_enableHoverLinkFromSeries:function(){var t=this.api.getZr();this.visualMapModel.option.hoverLink?(t.on("mouseover",this._hoverLinkFromSeriesMouseOver,this),t.on("mouseout",this._hideIndicator,this)):this._clearHoverLinkFromSeries()},_doHoverLinkToSeries:function(t,e){var i=this.visualMapModel,n=i.itemSize;if(i.option.hoverLink){var o=[0,n[1]],a=i.getExtent();t=FL(WL(o[0],t),o[1]);var r=function(t,e,i){var n=6,o=t.get("hoverLinkDataSize");o&&(n=VL(o,e,i,!0)/2);return n}(i,a,o),s=[t-r,t+r],l=VL(t,o,a,!0),u=[VL(s[0],o,a,!0),VL(s[1],o,a,!0)];s[0] ",r):this._showIndicator(l,l,"≈ ",r));var h=this._hoverLinkDataIndices,c=[];(e||UL(i))&&(c=this._hoverLinkDataIndices=i.findTargetDataIndices(u));var d=function(t,e){var i={},n={};return o(t||[],i),o(e||[],n,i),[a(i),a(n)];function o(t,e,i){for(var n=0,o=t.length;ni&&n([i,e[0]],"outOfRange"),n(e.slice()),i=e[1])},this),{stops:a,outerColors:r}}function n(t,e){var i=s.getRepresentValue({interval:t});e=e||s.getValueState(i);var n=o(i,e);t[0]===-1/0?r[0]=n:t[1]===1/0?r[1]=n:a.push({value:t[0],color:n},{value:t[1],color:n})}}}),jL={splitNumber:function(){var t=this.option,e=this._pieceList,i=Math.min(t.precision,20),n=this.getExtent(),o=t.splitNumber;o=Math.max(parseInt(o,10),1),t.splitNumber=o;for(var a=(n[1]-n[0])/o;+a.toFixed(i)!==a&&i<5;)i++;t.precision=i,a=+a.toFixed(i),t.minOpen&&e.push({interval:[-1/0,n[0]],close:[0,0]});for(var r=0,s=n[0];r","≥"][e[0]]];t.text=t.text||this.formatValueText(null!=t.value?t.value:t.interval,!1,i)},this)}};function qL(t,e){var i=t.inverse;("vertical"===t.orient?!i:i)&&e.reverse()}RL.extend({type:"visualMap.piecewise",doRender:function(){var a=this.group;a.removeAll();var r=this.visualMapModel,s=r.get("textGap"),t=r.textStyleModel,l=t.getFont(),u=t.getTextColor(),h=this._getItemAlign(),c=r.itemSize,e=this._getViewData(),i=e.endsText,d=W(r.get("showLabel",!0),!i);i&&this._renderEndsText(a,i[0],c,d,h),E(e.viewPieceList,function(t){var e=t.piece,i=new Ci;i.onclick=A(this._onItemClick,this,e),this._enableHoverLink(i,t.indexInModelPieceList);var n=r.getRepresentValue(e);if(this._createItemSymbol(i,n,[0,0,c[0],c[1]]),d){var o=this.visualMapModel.getValueState(n);i.add(new Ur({style:{x:"right"===h?-s:c[0]+s,y:c[1]/2,text:e.text,textVerticalAlign:"middle",textAlign:h,textFont:l,textFill:u,opacity:"outOfRange"===o?.5:1}}))}a.add(i)},this),i&&this._renderEndsText(a,i[1],c,d,h),wu(r.get("orient"),a,r.get("itemGap")),this.renderBackground(a),this.positionGroup(a)},_enableHoverLink:function(t,i){function e(t){var e=this.visualMapModel;e.option.hoverLink&&this.api.dispatchAction({type:t,batch:BL(e.findTargetDataIndices(i),e)})}t.on("mouseover",A(e,this,"highlight")).on("mouseout",A(e,this,"downplay"))},_getItemAlign:function(){var t=this.visualMapModel,e=t.option;if("vertical"===e.orient)return zL(t,this.api,t.itemSize);var i=e.align;return i&&"auto"!==i||(i="left"),i},_renderEndsText:function(t,e,i,n,o){if(e){var a=new Ci,r=this.visualMapModel.textStyleModel;a.add(new Ur({style:{x:n?"right"===o?i[0]:0:i[0]/2,y:i[1]/2,textVerticalAlign:"middle",textAlign:n?o:"center",text:e,textFont:r.getFont(),textFill:r.getTextColor()}})),t.add(a)}},_getViewData:function(){var t=this.visualMapModel,e=O(t.getPieceList(),function(t,e){return{piece:t,indexInModelPieceList:e}}),i=t.get("text"),n=t.get("orient"),o=t.get("inverse");return("horizontal"===n?o:!o)?e.reverse():i=i&&i.slice().reverse(),{viewPieceList:e,endsText:i}},_createItemSymbol:function(t,e,i){t.add(wg(this.getControllerVisual(e,"symbol"),i[0],i[1],i[2],i[3],this.getControllerVisual(e,"color")))},_onItemClick:function(t){var e=this.visualMapModel,i=e.option,n=k(i.selected),o=e.getSelectedMapKey(t);"single"===i.selectedMode?(n[o]=!0,E(n,function(t,e){n[e]=e===o})):n[o]=!n[o],this.api.dispatchAction({type:"selectDataRange",from:this.uid,visualMapId:this.visualMapModel.id,selected:n})}});yf(yL);var KL,$L="urn:schemas-microsoft-com:vml",JL="undefined"==typeof window?null:window,QL=!1,tk=JL&&JL.document;function ek(t){return KL(t)}if(tk&&!v.canvasSupported)try{tk.namespaces.zrvml||tk.namespaces.add("zrvml",$L),KL=function(t){return tk.createElement("')}}catch(t){KL=function(t){return tk.createElement("<"+t+' xmlns="'+$L+'" class="zrvml">')}}var ik,nk=rr.CMD,ok=Math.round,ak=Math.sqrt,rk=Math.abs,sk=Math.cos,lk=Math.sin,uk=Math.max;if(!v.canvasSupported){var hk=",",ck="progid:DXImageTransform.Microsoft",dk=21600,fk=dk/2,pk=function(t){t.style.cssText="position:absolute;left:0;top:0;width:1px;height:1px;",t.coordsize=dk+","+dk,t.coordorigin="0,0"},gk=function(t,e,i){return"rgb("+[t,e,i].join(",")+")"},mk=function(t,e){e&&t&&e.parentNode!==t&&t.appendChild(e)},vk=function(t,e){e&&t&&e.parentNode===t&&t.removeChild(e)},yk=function(t,e,i){return 1e5*(parseFloat(t)||0)+1e3*(parseFloat(e)||0)+i},xk=Yn,_k=function(t,e,i){var n=Fe(e);i=+i,isNaN(i)&&(i=1),n&&(t.color=gk(n[0],n[1],n[2]),t.opacity=i*n[3])},wk=function(t,e,i,n){var o="fill"===e,a=t.getElementsByTagName(e)[0];null!=i[e]&&"none"!==i[e]&&(o||!o&&i.lineWidth)?(t[o?"filled":"stroked"]="true",i[e]instanceof cs&&vk(t,a),a=a||ek(e),o?function(t,e,i){var n,o,a=e.fill;if(null!=a)if(a instanceof cs){var r,s=0,l=[0,0],u=0,h=1,c=i.getBoundingRect(),d=c.width,f=c.height;if("linear"===a.type){r="gradient";var p=i.transform,g=[a.x*d,a.y*f],m=[a.x2*d,a.y2*f];p&&(bt(g,g,p),bt(m,m,p));var v=m[0]-g[0],y=m[1]-g[1];(s=180*Math.atan2(v,y)/Math.PI)<0&&(s+=360),s<1e-6&&(s=0)}else{r="gradientradial";g=[a.x*d,a.y*f],p=i.transform;var x=i.scale,_=d,w=f;l=[(g[0]-c.x)/_,(g[1]-c.y)/w],p&&bt(g,g,p),_/=x[0]*dk,w/=x[1]*dk;var b=uk(_,w);u=0/b,h=2*a.r/b-u}var S=a.colorStops.slice();S.sort(function(t,e){return t.offset-e.offset});for(var M=S.length,I=[],T=[],A=0;A=c&&d<=i+1){for(var n=[],o=0;o=c&&d<=o+1)return hP(h,e.components,u,l);p[t]=e}else p[t]=void 0}var s;f++}for(;f<=e;){var r=a();if(r)return r}},pushComponent:function(t,e,i){var n=t[t.length-1];n&&n.added===e&&n.removed===i?t[t.length-1]={count:n.count+1,added:e,removed:i}:t.push({count:1,added:e,removed:i})},extractCommon:function(t,e,i,n){for(var o=e.length,a=i.length,r=t.newPos,s=r-n,l=0;r+1\n\r<"))}},E(["getLayer","insertLayer","eachLayer","eachBuiltinLayer","eachOtherLayer","getLayers","modLayer","delLayer","clearLayer","pathToImage"],function(t){MP.prototype[t]=function(t){return function(){vi('In SVG mode painter not support method "'+t+'"')}}(t)}),Po("svg",MP),t.version="4.8.0",t.dependencies={zrender:"4.3.1"},t.PRIORITY=Ld,t.init=function(t,e,i){var n=mf(t);if(n)return n;var o=new Rd(t,e,i);return o.id="ec_"+cf++,uf[o.id]=o,Jo(t,ff,o.id),function(n){var o="__connectUpdateStatus";function a(t,e){for(var i=0;i + + + + + + + + + + + + +
    +
    +
    + + +
    +
    + +
    +
    + + + + + + +
    + +
    + +
    + + + \ No newline at end of file diff --git "a/web/117 \344\270\212\346\265\267\345\270\202\345\233\276\344\271\246\351\246\206\345\244\247\345\261\217\347\234\213\346\235\277/static/interCitySelectData.js" "b/web/117 \344\270\212\346\265\267\345\270\202\345\233\276\344\271\246\351\246\206\345\244\247\345\261\217\347\234\213\346\235\277/static/interCitySelectData.js" new file mode 100644 index 00000000..7cfb3003 --- /dev/null +++ "b/web/117 \344\270\212\346\265\267\345\270\202\345\233\276\344\271\246\351\246\206\345\244\247\345\261\217\347\234\213\346\235\277/static/interCitySelectData.js" @@ -0,0 +1,13 @@ +var country = []; +country['africa']="algeria-A 阿尔及利亚-algeria|angola-A 安哥拉-angola|egypt-A 埃及-egypt|ethiopia-A 埃塞俄比亚-ethiopia|botswana-B 博茨瓦纳-botswana|burkina-faso-B 布基纳法索-burkina-faso|burkina-faso-B 布基纳法索-burkina-faso|burundi-B 布隆迪-burundi|benin-B 贝宁-benin|equatorial-guinea-C 赤道几内亚-equatorial-guinea|togo-D 多哥-togo|eritrea-E 厄立特里亚-eritrea|cape-verde-F 佛得角-cape-verde|cape-verde-islands-F 佛得角-cape-verde-islands|gambia-G 冈比亚-gambia|the-republic-of-congo-G 刚果(布)-the-republic-of-congo|republic-of-the-congo-G 刚果共和国-republic-of-the-congo|democratic-republic-of-the-congo-G 刚果民主共和国-democratic-republic-of-the-congo|zimbabwe-J 津巴布韦-zimbabwe|djibouti-J 吉布提共和国-djibouti|ghana-J 加纳-ghana|guinea-J 几内亚-guinea|guinea-bissau-J 几内亚比绍共和国-guinea-bissau|gabon-J 加蓬-gabon|cameroon-K 喀麦隆-cameroon|comoros-K 科摩罗-comoros|kenya-K 肯尼亚-kenya|cote-d'ivoire-K 科特迪瓦-cote-d'ivoire|liberia-L 利比里亚-liberia|libya-L 利比亚-libya|rwanda-L 卢旺达-rwanda|madagascar-M 马达加斯加-madagascar|morocco-M 摩洛哥-morocco|mali-M 马里共和国-mali|malawi-M 马拉维-malawi|mozambique-M 莫桑比克-mozambique|south-africa-N 南非-south-africa|namibia-N 纳米比亚-namibia|nigeria-N 尼日利亚-nigeria|sudan-S 苏丹-sudan|sierra-S 塞拉利昂-sierra|somalia-S 索马里-somalia|senegal-S 塞内加尔-senegal|tunisia-T 突尼斯-tunisia|tansania-T 坦桑尼亚-tansania|tanzania-T 坦桑尼亚联合共和国-tanzania|uganda-W 乌干达-uganda|spain-X 西班牙属加纳利群岛-spain|western-sahara-X 西撒哈拉-western-sahara|zambia-Z 赞比亚-zambia|chad-Z 乍得-chad|central-african-republic-Z 中非共和国-central-african-republic"; +country['america']="anguilla-A 安圭拉-anguilla|argentina-A 阿根廷-argentina|aruba-A 阿鲁巴-aruba|barbados-B 巴巴多斯-barbados|bahamas-B 巴哈马-bahamas|paraguay-B 巴拉圭-paraguay|bolivia-B 玻利维亚-bolivia|belize-B 伯利兹-belize|panama-B 巴拿马-panama|brazil-B 巴西-brazil|dominican-republic-D 多米尼加共和国-dominican-republic|dominican-republic-D 多米尼亚-dominican-republic|ecuador-E 厄瓜多尔-ecuador|french-guiana-F 法属圭亚那-french-guiana|cuba-G 古巴-cuba|guadeloupe-G 瓜德罗普-guadeloupe|colombia-G 哥伦比亚-colombia|costa-rica-G 哥斯达黎加-costa-rica|haiti-H 海地-haiti|honduras-H 洪都拉斯-honduras|nederlandse-antillen-H 荷属安的列斯群岛-nederlandse-antillen|canada-J 加拿大-canada|united-states-M 美国-united-states|peru-M 秘鲁-peru|martinique-M 马提尼克-martinique|mexico-M 墨西哥-mexico|nicaragua-N 尼加拉瓜-nicaragua|el-salvador-S 萨尔瓦多-el-salvador|suriname-S 苏里南-suriname|saint-lucia-S 圣卢西亚-saint-lucia|saint-vincent-and-the-grenadines-S 圣文森特和格林纳丁斯-saint-vincent-and-the-grenadines|trinidad-and-tobago-T 特立尼达和多巴哥-trinidad-and-tobago|guatemala-W 危地马拉-guatemala|uruguay-W 乌拉圭-uruguay|venezuela-W 委内瑞拉-venezuela|jamaica-Y 牙买加-jamaica|chile-Z 智利-chile"; +country['asia']="afghanistan-A 阿富汗-afghanistan|united-arab-emirates-A 阿拉伯联合酋长国-united-arab-emirates|oman-A 阿曼-oman|azerbaijan-A 阿塞拜疆-azerbaijan|bhutan-B 不丹-bhutan|pakistan-B 巴基斯坦-pakistan|bahrain-B 巴林-bahrain|north-korea-C 朝鲜-north-korea|timor-leste-D 东帝汶-timor-leste|philippines-F 菲律宾-philippines|georgia-G 格鲁吉亚-georgia|south-korea-H 韩国-south-korea|kazakhstan-H 哈萨克斯坦-kazakhstan|kyrgyzstan-J 吉尔吉斯斯坦-kyrgyzstan|cambodia-J 柬埔寨-cambodia|qatar-K 卡塔尔-qatar|kuwait-K 科威特-kuwait|lebanon-L 黎巴嫩-lebanon|laos-L 老挝-laos|myanmar-M 缅甸-myanmar|maldives-M 马尔代夫-maldives|mongolia-M 蒙古-mongolia|bangladesh-M 孟加拉-bangladesh|malaysia-M 马来西亚-malaysia|nepal-N 尼泊尔-nepal|west-bank-N 南非-west-bank|japan-R 日本-japan|sri-lanka-S 斯里兰卡-sri-lanka|cyprus-S 塞浦路斯-cyprus|saudi-arabia-S 沙特阿拉伯-saudi-arabia|turkey-T 土耳其-turkey|thailand-T 泰国-thailand|tajikistan-T 塔吉克斯坦-tajikistan|turkmenistan-T 土库曼斯坦-turkmenistan|brunei-W 文莱-brunei|uzbekistan-W 乌兹别克斯坦-uzbekistan|singapore-X 新加坡-singapore|syria-X 叙利亚-syria|india-Y 印度-india|jordan-Y 约旦-jordan|west-bank-Y 约旦河西岸-west-bank|indonesia-Y 印度尼西亚-indonesia|iran-Y 伊朗-iran|iraq-Y 伊拉克-iraq|yemen-Y 也门-yemen|armenia-Y 亚美尼亚-armenia|vietnam-Y 越南-vietnam|israel-Y 以色列-israel"; +country['europe']="austria-A 奥地利-austria|albania-A 阿尔巴尼亚-albania|ireland-A 爱尔兰-ireland|estonia-A 爱沙尼亚-estonia|iceland-B 冰岛-iceland|belarus-B 白俄罗斯-belarus|bosnia-and-herzegovina-B 波黑-bosnia-and-herzegovina|bulgaria-B 保加利亚-bulgaria|poland-B 波兰-poland|belgium-B 比利时-belgium|bosnia-and-herzegovina-B 波斯尼亚和黑塞哥维那-bosnia-and-herzegovina|germany-D 德国-germany|denmark-D 丹麦-denmark|russia-E 俄罗斯-russia|france-F 法国-france|finland-F 芬兰-finland|greenland-G 格陵兰-greenland|greenland-G 格陵兰(丹)-greenland|netherlands-H 荷兰-netherlands|montenegro-H 黑山-montenegro|czech-republic-J 捷克-czech-republic|czech-republic-J 捷克共和国-czech-republic|czechoslovakia-J 捷克斯洛伐克-czechoslovakia|croatia-K 克罗地亚-croatia|romania-L 罗马尼亚-romania|luxembourg-L 卢森堡-luxembourg|lithuania-L 立陶宛-lithuania|latvia-L 拉脱维亚-latvia|principality-of-liechtenstein-L 列支敦士登-principality-of-liechtenstein|moldova-M 摩尔多瓦-moldova|macedonia-M 马其顿-macedonia|norway-N 挪威-norway|portugal-P 葡萄牙-portugal|sweden-R 瑞典-sweden|switzerland-R 瑞士-switzerland|serbia-S 塞尔维亚-serbia|slovakia-S 斯洛伐克-slovakia|slovenia-S 斯洛文尼亚-slovenia|turkey-T 土耳其-turkey|ukraine-W 乌克兰-ukraine|spain-X 西班牙-spain|greece-X 希腊-greece|hungary-X 匈牙利-hungary|italy-Y 意大利-italy|united-kingdom-Y 英国-united-kingdom|gibraltar-Z 直布罗陀-gibraltar"; +country['oceania']="australia-A 澳大利亚-australia|papua-new-guinea-B 巴布亚新几内亚-papua-new-guinea|fiji-J 斐济-fiji|kiribati-J 基里巴斯-kiribati|australia-M 美国-australia|solomon-S 所罗门群岛-solomon|new-zealand-X 新西兰-new-zealand"; + +var city = []; +city['africa']=["adrar-A 阿德拉尔-algeria|algiers-A 阿尔及尔-algeria|arzew-A 阿尔泽-algeria|el-golea-A 埃尔果累阿-algeria|laghouat-A 艾格瓦特-algeria|ain-sefra-A 艾因塞夫拉-algeria|annaba-A 阿纳巴-algeria|annaba-A 安纳巴-algeria|oran-A 奥兰-algeria|oran-port-A 奥兰港-algeria|barika-B 巴里卡-algeria|batna-B 巴特纳-algeria|bejaia-B 贝贾亚-algeria|bejaia-port-B 贝贾亚港-algeria|bejaia-aeroport-B 贝贾亚机场-algeria|beni-abbes-B 贝尼阿巴斯-algeria|beni-saf-B 贝尼萨夫-algeria|bechar-B 贝沙尔-algeria|biskra-B 比斯克拉-algeria|bordj-bou-arreridj-B 布阿拉里季堡-algeria|bouira-B 布维拉-algeria|dellys-D 代利斯-algeria|ghardaia-G 盖尔达耶-algeria|guelma-G 盖勒马-algeria|ghardaia-J 加达亚-algeria|el-kala-J 加莱-algeria|djanet-J 贾奈特-algeria|ghazaouet-J 加扎乌埃特-algeria|djelfa-J 杰勒法-algeria|jijel-port-J 吉杰勒港-algeria|jijel-achouat-J 吉杰勒机场-algeria|constantine-J 君士坦丁-algeria|mecheria-M 迈舍里耶-algeria|miliana-M 米利亚纳-algeria|mostaganem-M 穆斯塔加奈姆-algeria|m-sila-M 姆西拉-algeria|naama-N 纳马-algeria|saida-S 赛达-algeria|setif-S 塞提夫-algeria|skikda-S 斯基克达-algeria|soukahras-S 苏克阿赫拉斯-algeria|tebessa-T 泰贝萨-algeria|tamanrasset-T 塔曼拉塞特-algeria|tahifet-T 塔希费特-algeria|tlemcen-zenata-T 特莱姆森赞塔那机场-algeria|tenes-T 特内斯-algeria|tizi-ouzou-T 提济乌祖-algeria|timimoun-T 提米蒙-algeria|tenes-T 提奈斯-algeria|tindouf-T 廷杜夫-algeria|tiaret-T 提亚雷特-algeria|touggourt-T 图古尔特-algeria|ouargla-W 瓦尔格拉-algeria|sidi-bel-abbes-X 西迪贝勒阿巴斯-algeria|chlef-X 谢利夫-algeria|illizi-Y 伊利济-algeria|illizi-Y 伊利齐-algeria|in-guezzam-Y 英盖扎姆-algeria|in-amenas-Y 英纳梅那斯-algeria|in-salah-Y 因萨拉赫-algeria","luanda-L 罗安达-angola","abusimbel-A 阿布辛拜勒-egypt|asyut-A 艾斯尤特-egypt|asyut-agrimet-A 艾斯尤特农业气象组-egypt|helwan-A 阿勒旺-egypt|aswan-A 阿斯旺-egypt|baltim-B 巴尔的姆-egypt|baharia-B 巴哈利亚-egypt|dahab-D 达哈布-egypt|damietta-D 杜姆亚特-egypt|fayoum-F 法尤姆-egypt|farafra-F 费拉菲拉-egypt|khargaagrimet-H 哈里杰农业气象组(哈里杰农业气象站)-egypt|elhasana-H 哈萨纳-egypt|hurghada-H 赫尔格达-egypt|hurguada-H 洪加达-egypt|hurguadapollution-H 洪加达污染区-egypt|qena-J 基纳-egypt|giza-agrimet-J 吉萨-egypt|cairo-K 开罗-egypt|kosseir-K 库赛尔-egypt|rafah-L 拉法赫-egypt|elarish-L 里士-egypt|al-uqsur-L 卢克索-egypt|rosetta-L 罗塞塔-egypt|minya-M 明亚-egypt|south-of-valley-university-N 南谷大学-egypt|nouzha-N 努扎-egypt|el-arish-S 萨尔瓦多阿里什-egypt|sharm-el-sheikh-S 沙姆沙伊赫-egypt|as-suways-S 苏伊士-egypt|taba-T 他巴-egypt|tahrir-T 塔里尔-egypt|shebinelkom-X 希宾库姆-egypt|siwa-X 锡瓦-egypt|al-ismailiyah-Y 伊斯梅利亚-egypt|az-zaqaziq-Z 扎加齐格-egypt","awassa-A 阿瓦萨-ethiopia|bahardar-B 巴赫达尔-ethiopia|diredawa-D 德雷达瓦-ethiopia|gode-G 戈德-ethiopia|gore-G 戈尔-ethiopia|gonder-G 贡德尔-ethiopia|jimma-J 季马-ethiopia|metehara-M 梅特哈拉-ethiopia|makale-M 默克莱-ethiopia|addis-ababa-Y 亚的斯亚贝巴-ethiopia","tshane-C 察内-botswana|francistown-F 弗朗西斯敦-botswana|gaborone-H 哈博罗内-botswana|gaberones-H 哈伯罗内-botswana|ghanzi-H 杭济-botswana|kasane-K 卡萨内-botswana|letlhakane-L 莱特拉卡内-botswana|mahalapye-M 马哈拉佩-botswana|maun-M 马翁-botswana|mafikeng-M 梅富根-botswana|selebi-phikwe-X 西雷毕菲克威-botswana|jwaneng-Z 朱瓦能-botswana","bobo-dioulasso-B 博博迪乌拉索-burkina-faso|boromo-B 博罗莫-burkina-faso|dori-D 多里-burkina-faso|fadan-gourma-F 法达恩古尔马-burkina-faso|gaoua-J 加瓦-burkina-faso|ouagadougou-W 瓦加杜古-burkina-faso|ouahigouya-W 瓦希古亚-burkina-faso","bobo-dioulasso-B 博博迪乌拉索-burkina-faso|boromo-B 博罗莫-burkina-faso|dori-D 多里-burkina-faso|fadan-gourma-F 法达恩古尔马-burkina-faso|gaoua-J 加瓦-burkina-faso|ouagadougou-W 瓦加杜古-burkina-faso|ouahigouya-W 瓦希古亚-burkina-faso","bujumbura-B 布琼布拉-burundi","porto-novo-B 波多诺伏-benin","malabo-M 马拉博-equatorial-guinea","lome-L 洛美-togo","asmara-A 阿斯马拉-eritrea","praia-P 普拉亚-cape-verde","praia-P 普腊亚-cape-verde-islands","banjul-B 班珠尔-gambia|basse-B 贝士-gambia|kerewan-K 凯雷万-gambia|georgetown-Q 乔治城-gambia|sapu-S 萨普-gambia","brazzaville-B 布拉柴维尔-the-republic-of-congo|dolisie-D 多利西-the-republic-of-congo|gamboma-G 甘博马-the-republic-of-congo|djambala-J 兼巴拉-the-republic-of-congo|kelle-K 凯莱-the-republic-of-congo|makabana-M 马卡巴纳-the-republic-of-congo|makoua-M 马夸-the-republic-of-congo|mouyondzi-M 穆永济-the-republic-of-congo|souanke-S 苏安凯-the-republic-of-congo|ouesso-W 韦索-the-republic-of-congo|sibiti-X 锡比提-the-republic-of-congo|impfondo-Y 英普丰多-the-republic-of-congo","pointe-noire-H 黑角-republic-of-the-congo|madingo-kayes-M 马丁戈-卡伊-republic-of-the-congo|impfondo-Y 因普丰多-republic-of-the-congo","boma-B 博马-democratic-republic-of-the-congo|kinshasa-J 金沙萨-democratic-republic-of-the-congo|kisangani-J 基桑加尼-democratic-republic-of-the-congo|kananga-K 卡南加-democratic-republic-of-the-congo|likasi-L 利卡西-democratic-republic-of-the-congo|lubumbashi-L 卢本巴希-democratic-republic-of-the-congo|matadi-M 马塔迪-democratic-republic-of-the-congo|mbandaka-M 姆班达卡-democratic-republic-of-the-congo|uvira-W 乌维拉-democratic-republic-of-the-congo","beitbridge-B 拜特布里奇-zimbabwe|buffalorange-B 布法罗伦奇-zimbabwe|bulawayo-B 布拉瓦约-zimbabwe|bulawayo-airport-B 布拉瓦约机场-zimbabwe|grasslands-D 大草原-zimbabwe|mountdarwin-D 达尔文山-zimbabwe|thyolo-D 蒂约罗-zimbabwe|ngabu-E 恩伽布-zimbabwe|nkayi-E 恩卡伊-zimbabwe|gokwe-G 戈奎-zimbabwe|gweru-G 格韦鲁-zimbabwe|harare-H 哈拉雷-zimbabwe|kadoma-K 卡多马-zimbabwe|kariba-K 卡里巴-zimbabwe|karoi-K 卡罗伊-zimbabwe|kanyemba-K 卡尼耶恩巴-zimbabwe|kwekwe-K 奎奎-zimbabwe|rusape-L 鲁萨佩-zimbabwe|makanga-M 玛卡恩伽-zimbabwe|masvingo-M 马斯温哥-zimbabwe|masvingo-M 马旬戈-zimbabwe|chinhoyi-Q 奇诺伊-zimbabwe|chipinge-Q 奇平加-zimbabwe|hwange-national-park-W 万基国家公园-zimbabwe|victoria-falls-W 维多利亚瀑布城-zimbabwe|west-nnicholson-X 西尼科尔森-zimbabwe|zvishavane-Z 兹维沙瓦内-zimbabwe","djibouti-J 吉布提-djibouti","ada-A 阿达-ghana|akatsi-A 阿卡赤-ghana|accra-A 阿克拉-ghana|axim-A 阿克西姆-ghana|akuse-A 阿库斯-ghana|akimoda-A 阿奇莫达-ghana|atakpame-A 阿塔帕梅-ghana|bole-B 玻尔-ghana|kara-K 喀拉海-ghana|koforidua-K 科福里杜亚-ghana|kete-krachi-K 克特克拉契-ghana|kumasi-K 库马西-ghana|niamtougou-L 拉马卡拉-ghana|mango-M 芒戈-ghana|navrongo-N 纳维荣古-ghana|saltpond-S 萨尔特庞德-ghana|sunyani-S 苏尼亚尼-ghana|sokode-S 索科德-ghana|takoradi-T 塔科腊迪-ghana|tamale-T 塔马利-ghana|tema-T 特马-ghana|wa-W 瓦-ghana|wenchi-W 温奇-ghana|yendi-Y 延迪-ghana","bafata-B 巴法塔-guinea|boffa-B 博法-guinea|boke-B 博凯-guinea|bolama-B 博拉马-guinea|kindia-J 金迪亚-guinea|kissidougou-J 基西杜古-guinea|kankan-K 康康-guinea|conakry-K 科纳克里-guinea|labe-L 拉贝-guinea|mamou-M 马木-guinea|macenta-M 马森塔-guinea|siguiri-X 锡吉里-guinea","bissau-B 比绍-guinea-bissau","bitam-B 比塔姆-gabon|lambarene-L 兰巴雷内-gabon|libreville-L 利伯维尔-gabon|makokou-M 马得库-gabon|mayumba-M 马永巴-gabon|mitzic-M 米齐克-gabon|tchibanga-Q 奇班加-gabon|port-gentil-R 让蒂尔港-gabon","abong-mbang-A 阿邦姆邦-cameroon|edea-A 埃代阿-cameroon|bafoussam-B 巴富萨姆-cameroon|bamenda-B 巴门达-cameroon|batouri-B 巴陶里-cameroon|bertoua-B 贝尔图阿-cameroon|buea-B 布埃亚-cameroon|douala-D 杜阿拉-cameroon|ngaoundere-E 恩冈代雷-cameroon|nkongsamba-E 恩康桑巴-cameroon|garoua-J 加鲁阿-cameroon|kribi-K 克里比-cameroon|maroua-salak-M 马鲁阿萨拉克-cameroon|mamfe-M 马姆菲-cameroon|yaounde-Y 雅温得-cameroon","ouani-A 昂儒昂-comoros|pamandzi-M 马约特-comoros|moroni-M 莫罗尼-comoros|moroni-airport-M 莫洛尼机场-comoros","eldoret-A 埃尔多雷特-kenya|athi-river-A 阿西河-kenya|gulu-G 古鲁-kenya|garissa-J 加里萨-kenya|kisumu-J 基苏木-kenya|kitale-J 基塔莱-kenya|kisii-J 基西-kenya|kakamega-K 卡卡梅加-kenya|lamu-L 拉姆-kenya|lodwar-L 洛德瓦尔-kenya|marsabit-M 马萨比特-kenya|masindi-M 马辛迪-kenya|mombasa-M 蒙巴萨-kenya|nakuru-N 纳库鲁-kenya|nairobi-N 内罗毕-kenya|soroti-S 索罗蒂-kenya|wajir-W 瓦吉尔-kenya|voi-W 沃伊-kenya|thika-X 锡卡-kenya","","monrovia-M 蒙罗维亚-liberia","agedabia-A 阿格达比亚-libya|obari-A 奥巴里-libya|elhamada-A 奥哈马德-libya|benina-B 贝尼纳-libya|derna-D 德尔纳-libya|tripoli-D 的黎波里-libya|hon-H 厚恩-libya|ghadames-J 加达迈斯-libya|ghat-J 加特-libya|kufra-K 库夫拉-libya|jalo-L 伽罗-libya|al-marj-M 迈尔季-libya|misurata-M 米苏拉塔-libya|nalut-N 纳卢特-libya|elkhoms-O 欧胡姆斯-libya|shahat-S 萨哈特-libya|sebha-S 塞卜哈-libya|swani-S 斯瓦尼-libya|sirte-S 苏尔特-libya|tobruk-T 托布鲁克-libya|yefren-Y 耶夫兰-libya|zuara-Z 兹瓦拉-libya","kigali-J 基加利-rwanda","analalava-A 阿纳拉拉瓦-madagascar|andapa-A 安达帕-madagascar|antsiranana-A 安齐拉纳纳-madagascar|antsohihy-A 安特索依希-madagascar|farquhar-F 法夸尔-madagascar|fascene-N 诺西贝-madagascar|tananarive-T 塔那那利佛-madagascar|vohemar-W 武希马里纳-madagascar","errachidia-A 埃拉契迪亚-morocco|laayoune-A 阿尤恩-morocco|beni-mellal-B 贝尼梅拉尔-morocco|tetuan-D 得土安-morocco|tan-tan-F 番摊-morocco|kenitra-G 盖尼特拉-morocco|khouribga-H 胡里卜盖-morocco|alhoceima-H 胡塞马群岛-morocco|eljadida-J 贾迪达-morocco|casablanca-K 卡萨布兰卡-morocco|casablanca-K 卡萨布兰卡市-morocco|kasba-tadla-K 卡斯巴泰德拉-morocco|rabat-L 拉巴特-morocco|larache-L 拉腊什-morocco|marrakech-M 马拉喀什-morocco|meknes-M 梅克内斯-morocco|midelt-M 米德特-morocco|mohammedia-M 穆罕默迪耶-morocco|safi-S 萨非-morocco|chefchaouen-S 舍夫沙万-morocco|essaouira-S 索维拉-morocco|taroudant-T 塔鲁丹特-morocco|tanger-airport-T 坦吉尔机场-morocco|tiznit-T 提兹尼特-morocco|ouarzazate-W 瓦尔扎扎特-morocco|oujda-W 乌季达-morocco|ifrane-Y 伊夫兰-morocco","bamako-B 巴马科-mali","lilongwe-L 利隆圭-malawi","maputo-M 马普托-mozambique","addoelephant-park-A 阿多大象公园-south-africa|port-edward-A 爱德华港-south-africa|ermelo-A 埃尔默洛-south-africa|uitenhage-A 埃滕哈赫-south-africa|estcourt-A 艾斯特科特-south-africa|umtata-A 阿姆塔塔-south-africa|uitenhage-A 奥埃滕哈赫-south-africa|oudtshoorn-A 奥茨胡恩-south-africa|augrabiesfalls-A 奥赫拉比斯瀑布-south-africa|upington-A 阿平顿-south-africa|paarl-B 柏尔-south-africa|barkly-west-B 巴克利西-south-africa|butterworth-B 巴特沃斯-south-africa|bethal-B 贝瑟-south-africa|pietermaritzburg-B 彼得马里茨堡-south-africa|oribi-airport-B 彼得马里茨堡机场-south-africa|pietersburg-B 彼得斯堡-south-africa|pretoria-administrative-B 比勒陀利亚-south-africa|bisho-B 毕斯合-south-africa|fortbeaufort-B 波福堡-south-africa|polokwane-B 波罗克瓦尼-south-africa|porterville-B 波特维尔-south-africa|bloemfontein-B 布隆方丹-south-africa|bloemfontein-airport-B 布隆方丹机场-south-africa|bouvet-island-B 布韦岛-south-africa|tsabong-C 柴邦-south-africa|dassen-island-D 达森岛-south-africa|durban-D 德班-south-africa|durban-virginia-D 德班弗吉尼亚-south-africa|durban-int'l-airport-D 德班国际机场-south-africa|barklyeast-D 东巴克利-south-africa|eastlondon-D 东伦敦-south-africa|somerseteast-D 东索美塞特-south-africa|capeagulhas-E 厄加勒斯岬-south-africa|vanreenen-F 范瑞恩-south-africa|ficksburg-F 费克斯堡-south-africa|fauresmith-F 福尔史密斯-south-africa|fraserburg-F 夫拉则堡-south-africa|vryburg-F 弗雷堡-south-africa|vredendal-F 弗雷登达尔-south-africa|vryheid-F 弗雷黑德-south-africa|vereeniging-F 弗里尼欣-south-africa|koingnaas-G 高林奈思-south-africa|gariepdam-G 嘎瑞普水库-south-africa|gough-island-G 戈夫岛-south-africa|graskop-G 格拉斯科普-south-africa|grahamstown-G 格雷厄姆斯敦-south-africa|greytown-G 格雷镇-south-africa|haga-haga-H 哈加-哈加-south-africa|goodhope-H 好望角-south-africa|graaff-reinet-H 赫拉夫·里内特-south-africa|hermanus-H 赫曼努斯-south-africa|hoedspruit-H 侯斯普瑞特-south-africa|royalnational-park-H 皇家国家公园-south-africa|qacha-snek-J 加查斯内克-south-africa|germiston-J 杰米斯顿-south-africa|kimberley-J 金伯利-south-africa|keetmanshoop-J 基特曼斯胡普-south-africa|giants-castle-J 巨人城堡-south-africa|calvinia-K 卡尔维尼亚-south-africa|calvinia-K 卡尔文尼亚-south-africa|coffeebay-K 咖啡湾-south-africa|cape-town-legislative-K 开普敦-south-africa|capetown-port-K 开普敦港-south-africa|carolina-K 卡罗莱纳-south-africa|kathu-K 卡图-south-africa|cofimvaba-K 科菲蒙瓦巴-south-africa|klerksdorp-K 克莱克斯多普-south-africa|clanwilliam-K 克兰威廉-south-africa|kroonstad-K 克龙斯塔德-south-africa|krugersdorp-K 克鲁格斯多普-south-africa|knysna-K 克尼斯纳-south-africa|kempton-park-K 肯普顿公园-south-africa|kuruman-K 库鲁曼-south-africa|queenstown-K 昆斯敦-south-africa|lephalale-L 拉法拉勒-south-africa|lydenburg-L 莱登堡-south-africa|ladysmith-L 莱迪史密斯-south-africa|laingsburg-L 兰斯堡-south-africa|richardsbay-L 理查兹湾-south-africa|riversdale-L 里佛斯达-south-africa|lichtenburg-L 利克田堡-south-africa|robertson-L 罗伯森-south-africa|robben-island-L 罗布恩岛-south-africa|rustenburg-L 鲁斯登堡-south-africa|luderitz-airport-L 吕德里茨机场-south-africa|marken-M 马尔肯-south-africa|margate-M 马盖特-south-africa|mara-M 马拉-south-africa|malmesbury-M 马姆斯伯里-south-africa|maseru-M 马塞卢-south-africa|matatiele-M 马塔泰勒-south-africa|mazeppabay-M 马泽帕湾-south-africa|moltenoreservior-M 莫尔蒂诺湖-south-africa|mokhotlong-M 莫霍特隆-south-africa|mooiriver-M 穆伊河-south-africa|nelspruit-N 内尔斯普雷特-south-africa|nelspruit-N 内斯普利特-south-africa|nieuwoudtville-N 尼湖德维-south-africa|newcastle-N 纽卡斯尔-south-africa|port-nolloth-N 诺洛斯港-south-africa|paddock-P 帕多克-south-africa|paarl-P 帕尔-south-africa|phalaborwa-P 帕拉博鲁瓦-south-africa|pongola-P 蓬戈拉-south-africa|pilanesberg-P 匹兰斯堡-south-africa|plettenbergbay-P 普利登堡湾-south-africa|prieska-P 普里斯卡-south-africa|george-airport-Q 乔治机场-south-africa|tshipise-Q 奇皮塞-south-africa|tsitsikamma-Q 齐齐卡马-south-africa|sutherland-S 萨瑟兰-south-africa|kingshaka-int'l-airport-S 沙卡王国际机场-south-africa|cape-st.-blaize-S 圣布雷兹岬-south-africa|cape-st.francis-S 圣弗朗西斯角-south-africa|skukuza-S 史库库莎-south-africa|springbok-S 斯普林博克-south-africa|springs-S 斯普林斯-south-africa|worcester-S 渥斯特-south-africa|strand-S 斯特兰德-south-africa|thohoyandou-S 索赫燕杜-south-africa|soweto-S 索韦托-south-africa|thabazimbi-T 塔巴津比-south-africa|taung-T 汤恩-south-africa|tongaat-T 通加特-south-africa|welkom-W 韦尔科姆-south-africa|wepener-W 维佩纳-south-africa|witbank-W 威特班克-south-africa|ventersdorp-W 温特斯多普-south-africa|ulundi-W 乌伦迪-south-africa|alexander-bay-Y 亚历山大湾-south-africa|port-elizabeth-Y 伊丽莎白港-south-africa|elliot-Y 伊里亚德-south-africa|illovo-Y 伊洛沃-south-africa|johannesburg-Y 约翰内斯堡-south-africa|johannesburg-Y 约翰尼斯堡-south-africa|johannesburg-international-airport-Y 约翰尼斯堡国际机场-south-africa|jamestown-Z 詹姆斯敦-south-africa|grandcentral-Z 中央-south-africa","windhoek-W 温得和克-namibia","abeokuta-A 阿贝奥库塔-nigeria|abuja-A 阿布贾-nigeria|enugu-A 埃努古-nigeria|onitsha-A 奥尼查-nigeria|oshogbo-A 奥绍博-nigeria|oyo-A 奥约-nigeria|bauchi-B 包奇-nigeria|benincity-B 贝宁城-nigeria|bida-B 比达-nigeria|birnin-kebbi-B 比尔宁凯比-nigeria|potiskum-B 波提斯昆-nigeria|nguru-E 恩古鲁-nigeria|gunited-states-of-americau-G 古绍-nigeria|porth-arcourt-H 哈科特港-nigeria|kaduna-K 卡杜纳-nigeria|calabar-K 卡拉巴尔-nigeria|kandi-K 康迪-nigeria|kano-K 卡诺-nigeria|katsina-K 卡齐纳-nigeria|lagos-L 拉各斯-nigeria|lokoja-L 洛科贾-nigeria|maiduguri-M 迈杜古里-nigeria|makurdi-M 马库尔迪-nigeria|minna-M 米纳-nigeria|natitingou-N 纳蒂廷古-nigeria|parakou-P 帕拉库-nigeria|jos-Q 乔斯-nigeria|save-S 萨瓦河-nigeria|sokoto-S 索科托-nigeria|warri-W 瓦里-nigeria|ondo-W 翁多-nigeria|yelwa-Y 耶卢瓦-nigeria|ibi-Y 揖斐-nigeria|ibadan-Y 伊巴丹-nigeria|ikom-Y 伊科姆-nigeria|ilorin-Y 伊洛林-nigeria|yola-Y 约拉-nigeria|zaria-Z 扎里亚-nigeria","khartoum-K 喀土穆-sudan|malakal-M 马拉卡尔-sudan|nyala-N 尼亚拉-sudan|bur-sudan-S 苏丹港-sudan|wad-madani-W 瓦德马达尼-sudan","freetown-F 弗里敦-sierra","mogadishu-M 摩加迪沙-somalia","podor-B 波多尔-senegal|dakar-D 达喀尔-senegal|thies-nones-J 捷斯-senegal|ziguinchor-J 济金绍尔-senegal|diourbel-J 久尔贝勒-senegal|kaolack-K 考拉克-senegal|kedougou-K 克杜古-senegal|kolda-K 科尔达-senegal|linguere-L 林盖尔-senegal|matam-M 马塔姆-senegal|mbour-M 姆布尔-senegal|saint-louis-S 圣路易斯-senegal|cap-skirring-S 斯基灵角-senegal|tambacounda-T 坦巴昆达-senegal","bizerte-B 比塞大-tunisia|gabes-J 加贝斯-tunisia|gafsa-J 加夫萨-tunisia|kelibia-J 加利比亚-tunisia|jendouba-J 坚杜拜-tunisia|kebili-J 吉比利-tunisia|kasserine-K 凯塞林-tunisia|remada-L 雷马达-tunisia|mahdia-M 马赫迪耶-tunisia|medenine-M 梅德宁-tunisia|nabeul-N 纳布勒-tunisia|safaqis-S 斯法克斯-tunisia|as-susah-S 苏塞-tunisia|tabarka-T 泰巴尔-tunisia|tataouine-T 泰塔温-tunisia|thala-T 塔莱-tunisia|tunis-T 突尼斯-tunisia|tozeur-T 托泽尔-tunisia|sidibouzid-X 西吉布吉特-tunisia|siliana-X 锡勒亚奈-tunisia|zaghouan-Z 宰格万-tunisia","arusha-A 阿鲁沙-tansania|bukoba-B 布科巴-tansania|dodoma-D 多多玛-tansania|kigoma-J 基戈马-tansania|morogoro-M 莫罗戈罗-tansania|moshi-M 莫希-tansania|mombasa-int'l-airport-M 莫伊国际机场-tansania|mbeya-M 姆贝亚-tansania|musoma-M 穆索马-tansania|nachingwea-N 纳钦吉阿-tansania|sumbawanga-S 松巴万加-tansania|songea-S 松盖阿-tansania|tabora-airport-T 塔波拉机场-tansania|shinyanga-X 希尼安加-tansania|singida-X 辛吉达-tansania|iringa-Y 伊林加-tansania","dar-es-salaam-D 达累斯萨拉姆-tanzania|dodoma-D 多多马-tanzania|maruku-M 马鲁库-tanzania|mtwara-M 姆特瓦拉-tanzania|mwanza-M 姆万扎-tanzania|zanzibar-S 桑给巴尔-tanzania|tanga-T 坦噶-tanzania","entebbe-E 恩德培-uganda|kampala-K 坎帕拉-uganda","albacete-losllanos-A 阿尔巴塞特-spain|algeciras-A 阿尔赫西拉斯-spain|almeria-aeropuerto-A 阿尔梅里亚-spain|elche-A 埃尔切-spain|alicante-A 阿利坎特-spain|alicante-A 阿里坎特-spain|orense-A 奥伦塞-spain|oviedo-A 奥维耶多-spain|avila-A 阿维拉-spain|valladolid-B 巴利亚多利德-spain|valencia-B 巴伦西亚-spain|barcelona-B 巴塞罗那-spain|bilbao-B 毕尔巴鄂-spain|granada-G 格拉纳达-spain|guadalajara-G 瓜达拉哈拉-spain|jerez-dela-frontera-aeropuerto-H 赫雷斯德拉弗龙特拉机场-spain|caceres-K 卡塞雷斯-spain|castellon-K 卡斯特利翁-spain|castellon-de-la-plana-K 卡斯特利翁-德拉普拉纳-spain|cordoba-aeropuerto-K 科尔多瓦机场-spain|lleida-L 莱里达-spain|lacoruna-L 拉柯鲁尼亚-spain|lamolina-L 拉磨利那-spain|ciudad-real-L 雷阿尔城-spain|logrono-agoncillo-L 洛格罗尼奥-spain|rota-L 罗塔岛-spain|madrid-M 马德里-spain|madrid-barajas-M 马德里·巴拉哈斯-spain|malaga-M 马拉加-spain|mallorca-M 马略卡岛-spain|palma-de-mallorca-airport-M 马略卡岛帕尔马机场-spain|melilla-M 梅利利亚-spain|menorca-mahon-M 梅诺卡岛-spain|murcia-M 穆尔西亚-spain|navacerrada-N 那瓦塞拉达-spain|pamplona-P 潘普洛纳-spain|ponferrada-P 蓬费拉达-spain|pontevedra-P 蓬特韦德拉-spain|segovia-S 塞哥维亚-spain|zaragoza-aeropuerto-S 萨拉戈萨-spain|salamanca-matacan-S 萨拉曼卡-spain|zamora-S 萨莫拉-spain|soria-S 索里亚-spain|tarifa-T 塔里法-spain|teruel-T 特鲁埃尔-spain|tenerife-guimar-T 特纳利夫·吉马尔-spain|tortosa-T 托尔托萨-spain|toledo-city-T 托莱多-spain|valencia-aeropuerto-W 瓦伦西亚-spain|vitoria-W 维多利亚-spain|huelva-W 韦尔瓦-spain|gijon-X 希洪-spain|ceuta-X 休达-spain|ibiza-Y 伊比沙岛-spain|izana-Y 伊萨纳-spain","ad-dakhla-B 别墅西斯内罗斯-western-sahara|dakhla-D 达赫莱-western-sahara","binga-B 宾加-zambia|ndola-E 恩多拉-zambia|ndola-E 恩多拉市-zambia|nkhatabay-E 恩卡塔贝-zambia|kaoma-K 卡奥马-zambia|kabwe-K 卡布韦-zambia|kasama-K 卡塞马-zambia|kasempa-K 卡森帕县-zambia|kawambwa-K 卡万布瓦-zambia|livingstone-L 利文斯敦-zambia|lusaka-L 卢萨卡-zambia|lunited-states-of-americaka-city-airport-L 卢萨卡市机场-zambia|mountmakulu-M 玛库鲁山-zambia|mongu-M 芒古-zambia|mansa-M 曼萨-zambia|mumbwa-M 蒙布瓦-zambia|mbala-M 姆巴拉-zambia|mfuwe-M 姆富韦-zambia|mzimba-M 姆津巴-zambia|mpika-M 姆皮卡-zambia|mwinilunga-M 姆维尼伦加-zambia|mzuzu-M 姆祖祖-zambia|petauke-P 佩陶克县-zambia|choma-Q 乔马-zambia|chingolo-Q 钦戈洛-zambia|chipata-Q 奇帕塔-zambia|sesheke-S 塞谢凯-zambia|solwezi-S 索卢韦齐-zambia|isoka-Y 伊索卡-zambia|zambezi-Z 赞比西河-zambia","ndjamena-E 恩贾梅纳-chad","bangui-B 班吉-central-african-republic"]; +city['america']=["crocus-hill-H 红花山-anguilla","buenos-aires-B 布宜诺斯艾利斯-argentina|san-fernando-del-valle-de-catamarca-K 卡塔马卡-argentina|mendoza-M 门多萨-argentina|neuquen-N 内乌肯-argentina|salta-S 萨尔塔-argentina","oranjestad-A 奥拉涅斯塔克-aruba","bridgetown-B 布里奇敦-barbados","andros-town-A 安德罗斯镇-bahamas|bimini-fl-B 比米尼群岛-bahamas|bay-spring-ri-K 卡特岛-bahamas|matthew-town-M 马修镇-bahamas|nassau-N 拿骚-bahamas","mariscal-estigarribia-A 埃斯蒂加里维亚元帅镇-paraguay|ciudad-del-este-A 埃斯特城-paraguay|coronel-oviedo-A 奥维多上校-paraguay|fuerte-olimpo-B 堡奥林波-paraguay|punta-rieles-P 蓬塔里埃雷斯-paraguay|nueva-asuncion-X 新亚松森-paraguay|asuncion-Y 亚松森-paraguay","oruro-A 奥鲁罗-bolivia|potosi-B 波托西-bolivia|guayaramerin-G 瓜亚拉美林-bolivia|coroico-K 科罗伊科-bolivia|cochabamba-K 科恰班巴-bolivia|quillacollo-K 奎拉乔洛-bolivia|rurrenabaque-L 鲁雷纳瓦克-bolivia|robore-L 罗沃雪-bolivia|bolivia-M 马格达莱纳-bolivia|sucre-S 苏克雷-bolivia|tarija-T 塔里哈-bolivia","belmopan-B 贝尔莫潘-belize","bocas-del-toro-B 博卡斯德尔托罗-panama|coronado-K 科罗纳多-panama","aracaju-A 阿拉卡茹-brazil|porto-alegre-A 阿雷格里港-brazil|brasilia-B 巴西利亚-brazil|belo-horizonte-B 贝洛奥里藏特-brazil|campo-grande-D 大坎普-brazil|florianopolis-F 弗洛里亚诺波利斯-brazil|fortaleza-F 福塔莱萨-brazil|curitiba-K 库里蒂巴-brazil|cuiaba-K 库亚巴-brazil|recife-L 累西腓-brazil|rio-de-janeiro-L 里约热内卢-brazil|macapa-M 马卡帕-brazil|manaus-M 马瑙斯-brazil|palmas-P 帕尔马斯-brazil|joao-pessoa-R 若昂佩索阿-brazil|salvador-S 萨尔瓦多-brazil|sao-paulo-S 圣保罗-brazil|teresina-T 特雷西纳-brazil","bavaro-B 巴瓦罗-dominican-republic|cabarete-K 卡巴雷特-dominican-republic|cotui-K 科图伊-dominican-republic|roseau-L 罗索-dominican-republic|luperon-L 卢佩龙-dominican-republic|monte-plata-M 蒙普拉塔-dominican-republic|pantanal-P 蓬塔卡纳-dominican-republic|santo-domingo-S 圣多明各-dominican-republic|sosua-S 索苏阿-dominican-republic|higuey-Y 伊圭-dominican-republic","bavaro-B 巴瓦罗-dominican-republic|cabarete-K 卡巴雷特-dominican-republic|cotui-K 科图伊-dominican-republic|roseau-L 罗索-dominican-republic|luperon-L 卢佩龙-dominican-republic|monte-plata-M 蒙普拉塔-dominican-republic|pantanal-P 蓬塔卡纳-dominican-republic|santo-domingo-S 圣多明各-dominican-republic|sosua-S 索苏阿-dominican-republic|higuey-Y 伊圭-dominican-republic","ambato-A 安巴托-ecuador|portoviejo-B 波托维耶霍-ecuador|guayaquil-G 瓜亚基尔-ecuador|puerto-baquerizo-moreno-J 加拉帕戈斯群岛-ecuador|quito-J 基多-ecuador|cayambe-K 凯扬波-ecuador|cuenca-K 昆卡-ecuador|latacunga-L 拉塔昆加-ecuador|riobamba-L 里奥班巴-ecuador|loja-L 洛哈-ecuador|machala-M 马查拉-ecuador|manta-M 曼塔-ecuador|salinas-S 萨利纳斯-ecuador","cayenne-K 卡宴-french-guiana|sinnamary-X 锡纳马里-french-guiana","holguin-A 奥尔金-cuba|bayamo-B 巴亚莫-cuba|pinar-del-rio-B 比那尔德里奥-cuba|santiago-de-cuba-G 古巴圣地亚哥-cuba|havana-H 哈瓦那-cuba|camaguey-K 卡马圭-cuba|manzanillo-M 曼萨尼约-cuba|matanzas-M 马坦萨斯-cuba|playa-giron-P 普拉亚吉隆滩-cuba|cienfuegos-X 西恩富戈斯-cuba","basse-terre-B 巴斯特尔-guadeloupe|pointe-a-pitre-B 彼得尔角城-guadeloupe|petit-bourg-D 珀蒂堡-guadeloupe|port-louis-L 路易港-guadeloupe","puerto-colombia-A 阿劳卡-colombia|apartado-A 阿帕-colombia|barranquilla-B 巴兰基亚-colombia|valledupar-B 巴耶杜帕尔-colombia|villavicencio-B 比亚维森西奥-colombia|bogota-B 波哥大-colombia|popayan-B 波帕扬-colombia|buenaventura-B 布埃纳文图拉-colombia|bucaramanga-B 布卡拉曼加-colombia|envigado-E 恩维加多-colombia|quibdo-J 基布多-colombia|cali-K 卡利-colombia|cucuta-K 库库塔-colombia|riohacha-L 里奥阿查-colombia|medellin-M 麦德林-colombia|manizales-M 马尼萨莱斯-colombia|monteria-M 蒙特里亚-colombia|neiva-N 内瓦-colombia|palmira-P 帕尔米拉-colombia|pasto-P 帕斯托-colombia|pereira-P 佩雷拉-colombia|pijao-P 皮豪-colombia|sogamoso-S 索加莫索-colombia|soledad-S 索莱达-colombia|tunja-T 通哈-colombia|tumaco-T 图马科-colombia|ipiales-Y 伊皮亚莱斯-colombia|itagui-Y 伊塔古伊-colombia","alajuela-A 阿拉胡埃拉-costa-rica|puerto-limon-L 利蒙港-costa-rica|turrialba-T 图里亚尔瓦-costa-rica","gonaives-G 戈纳伊夫-haiti|petionville-P 佩蒂翁维尔-haiti|port-au-prince-T 太子港-haiti","roatan-L 罗阿坦-honduras|tegucigalpa-T 特古西加尔巴-honduras","kralendijk-K 克拉伦迪吉克-nederlandse-antillen","edmonton-A 埃德蒙顿-canada|antigonish-A 安提格尼斯-canada|oakville-A 奥克维尔-canada|oshawa-A 奥沙瓦-canada|baker-lake-B 贝克湖-canada|north-battleford-B 北战堡-canada|burnaby-B 本那比-canada|penticton-B 宾迪顿-canada|dease-lake-D 迪斯湖-canada|toronto-D 多伦多-canada|fredericton-F 弗雷德里克顿-canada|kamloops-G 甘露市-canada|cobourg-G 高堡-canada|glace-bay-G 格莱斯湾-canada|hay-river-H 海河-canada|red-deer-H 红鹿-canada|yellowknife-H 黄刀镇-canada|gatineau-J 加蒂诺-canada|gillam-J 焦林-canada|corner-brook-J 角落卜克-canada|kirkland-lake-J 吉兰湖-canada|kelowna-J 基隆拿-canada|old-crow-J 旧克罗-canada|calgary-K 卡尔加里-canada|quebec-K 魁北克-canada|rankin-inlet-L 兰今湾-canada|la-ronge-L 勒红斯-canada|thunder-bay-L 雷湾-canada|revelstoke-L 里福斯多克-canada|regina-L 里贾纳-canada|prince-rupert-L 鲁珀特王子港-canada|fort-mcmurray-M 麦梅里堡-canada|moncton-M 蒙克顿-canada|montreal-M 蒙特利尔-canada|mississauga-M 密西沙加-canada|moose-jaw-M 穆斯乔-canada|fort-nelson-N 纳尔逊堡-canada|nanaimo-N 纳奈莫-canada|natashquan-N 纳塔诗昆-canada|nipigon-N 尼皮贡-canada|pickle-lake-P 皮克尔湖-canada|saskatoon-S 萨斯卡通-canada|sarnia-S 珊尼亚-canada|chapleau-S 沙普洛-canada|chicoutimi-S 诗古提米-canada|ottawa-T 渥太华-canada|timmins-T 天明-canada|williams-lake-W 威廉斯湖-canada|vancouver-W 温哥华-canada|winnipeg-W 温尼伯-canada|chibougamau-X 希布加莫-canada|medicine-hat-Y 药帽-canada|iqaluit-Y 伊魁特-canada|inuvik-Y 伊努维克-canada|chilliwack-Z 支里画-canada","escondido-ca-A 埃斯孔迪多-united-states|evansville-in-A 埃文斯维尔-united-states|akron-oh-A 阿克伦-united-states|ontario-ca-A 安大略-united-states|ann-arbor-mi-A 安娜堡-united-states|anaheim-ca-A 安那罕-united-states|augusta-A 奥古斯塔-united-states|oklahoma-city-ok-A 奥克拉荷马市-united-states|oxnard-ca-A 奥克斯纳德-united-states|orlando-fl-A 奥兰多-united-states|omaha-ne-A 奥马哈-united-states|austin-tx-A 奥斯汀-united-states|bellevue-wa-B 贝尔维尤-united-states|bakersfield-ca-B 贝克斯菲尔德-united-states|north-las-vegas-nv-B 北拉斯维加斯-united-states|burbank-ca-B 伯班克-united-states|pomona-ca-B 波莫纳-united-states|boston-ma-B 波士顿-united-states|charleston-wv-C 查尔斯顿-united-states|long-beach-ca-C 长滩-united-states|daly-city-ca-D 戴利城-united-states|dallas-tx-D 达拉斯-united-states|denver-co-D 丹佛-united-states|detroit-mi-D 底特律-united-states|independence-mo-D 独立城-united-states|philadelphia-pa-F 费城-united-states|phoenix-az-F 菲尼克斯-united-states|fresno-ca-F 弗雷斯诺-united-states|fremont-ca-F 弗里蒙特-united-states|greensboro-nc-G 格林斯伯勒-united-states|columbus-oh-G 哥伦布-united-states|hialeah-fl-H 海厄利亚-united-states|hollywood-fl-H 好莱坞-united-states|washington-dc-H 华盛顿特区-united-states|garland-tx-J 加兰-united-states|gilbert-az-J 吉尔伯特-united-states|san-francisco-ca-J 旧金山-united-states|cape-coral-fl-K 开普科勒尔-united-states|concord-ca-K 康科德-united-states|clarksville-tn-K 克拉克斯维尔-united-states|coral-springs-fl-K 科勒尔斯普林斯-united-states|clearwater-fl-K 克利尔沃特-united-states|fort-collins-co-K 科林斯堡-united-states|colorado-springs-co-K 科罗拉多泉-united-states|costa-mesa-ca-K 科斯塔梅萨-united-states|laredo-tx-L 拉雷多-united-states|fort-lauderdale-fl-L 劳德代尔堡-united-states|las-vegas-nv-L 拉斯维加斯-united-states|rockford-il-L 罗克福德-united-states|raleigh-nc-L 罗利-united-states|los-angeles-ca-L 洛杉矶-united-states|miami-fl-M 迈阿密-united-states|mesquite-tx-M 梅斯基特-united-states|milwaukee-wi-M 密尔沃基-united-states|minneapolis-mn-M 明尼阿波利斯-united-states|mobile-al-M 莫比尔-united-states|modesto-ca-M 莫德斯托-united-states|moreno-valley-ca-M 莫雷诺谷-united-states|new-york-ny-N 纽约-united-states|norfolk-va-N 诺福克-united-states|knoxville-tn-N 诺克斯维尔-united-states|norwalk-ca-N 诺沃克-united-states|oceanside-ca-O 欧申赛德-united-states|pembroke-pines-fl-P 潘布鲁克派恩斯-united-states|pompano-beach-fl-P 庞帕诺比奇-united-states|chandler-az-Q 钱德勒-united-states|joliet-il-Q 乔利埃特-united-states|chesapeake-va-Q 切萨皮克-united-states|sacramento-ca-S 萨克拉门托-united-states|san-bernardino-ca-S 圣贝纳迪诺-united-states|san-diego-ca-S 圣地亚哥-united-states|shreveport-la-S 什里夫波特-united-states|stockton-ca-S 斯托克顿-united-states|sioux-falls-sd-S 苏瀑-united-states|tallahassee-fl-T 塔拉哈西-united-states|downey-ca-T 唐尼-united-states|honolulu-hi-T 檀香山-united-states|tulsa-ok-T 图尔萨-united-states|tucson-az-T 图森-united-states|vallejo-ca-W 瓦列霍-united-states|fort-wayne-in-W 韦恩堡-united-states|winston-salem-nc-W 温斯顿-赛伦-united-states|warren-mi-W 沃伦-united-states|waterbury-ct-W 沃特伯里-united-states|charlotte-nc-X 夏洛特-united-states|cedar-rapids-ia-X 锡达拉皮兹-united-states|simi-valley-ca-X 西米谷-united-states|houston-tx-X 休斯顿-united-states|west-valley-city-ut-X 西瓦利城-united-states|seattle-wa-X 西雅图-united-states|yonkers-ny-Y 扬克斯-united-states|atlanta-ga-Y 亚特兰大-united-states|indianapolis-in-Y 印第安纳波利斯-united-states|inglewood-ca-Y 英格尔伍德-united-states|eugene-or-Y 尤金-united-states|jersey-city-nj-Z 泽西城-united-states|chicago-il-Z 芝加哥-united-states","arequipa-A 阿雷基帕-peru|andahuaylas-A 安达韦拉斯-peru|chachapoyas-C 查查波亚斯-peru|juanjui-H 胡安惠-peru|juliaca-H 胡利亚卡-peru|cajamarca-K 卡哈马卡-peru|cusco-K 库斯科-peru|lima-L 利马-peru|matucana-M 马图卡纳-peru|moquegua-M 莫克瓜-peru|piura-P 皮乌拉-peru|pucallpa-P 普卡尔帕-peru|chimbote-Q 钦博特-peru|chincha-alta-Q 钦查阿尔塔-peru|tacna-T 塔克纳-peru|huaral-W 瓦拉-peru|huanuco-W 瓦努科-peru|vitarte-W 维塔尔特-peru|iquitos-Y 伊基托斯-peru|ica-Y 伊卡-peru|yurimaguas-Y 尤里马瓜斯-peru","fort-de-france-F 法兰西堡-martinique|saint-pierre-S 圣皮埃尔-martinique","campeche-K 坎佩切-mexico|puerto-maldonado-M 马尔多纳多港-mexico|morelos-M 莫雷洛斯-mexico|mexico-city-M 墨西哥城-mexico|puebla-P 普埃布拉-mexico|chihuahua-Q 奇瓦瓦-mexico|zacatecas-S 萨卡特卡斯-mexico|tlaxcala-T 特拉斯卡拉-mexico|oaxaca-de-juarez-W 瓦哈卡-mexico|veracruz-W 韦拉克鲁斯-mexico|hidalgo-Y 伊达尔戈-mexico","puerto-cabezas-K 卡贝萨斯港-nicaragua|managua-M 马那瓜-nicaragua|chinandega-Q 奇南德加-nicaragua|jinotega-X 希诺特加-nicaragua","acajutla-A 阿卡胡特拉-el-salvador|san-salvador-S 圣萨尔瓦多-el-salvador|sonsonate-S 松索-el-salvador|usulutan-W 乌苏卢坦-el-salvador","paramaribo-P 帕拉马里博-suriname|paranam-P 帕拉南-suriname","dennery-D 丹讷里-saint-lucia|castries-K 卡斯特里-saint-lucia|micoud-M 米库-saint-lucia","bequia-B 比奎阿-saint-vincent-and-the-grenadines|kingston-J 金斯敦-saint-vincent-and-the-grenadines","port-of-spain-X 西班牙港-trinidad-and-tobago","puerto-barrios-B 巴里奥斯港-guatemala|poptun-B 波普通-guatemala|jalapa-H 哈拉帕-guatemala|retalhuleu-L 雷塔卢-guatemala|mazatenango-M 马萨特南戈-guatemala|quetzaltenango-N 南戈-guatemala|chimaltenango-Q 奇马尔特南戈省-guatemala|huehuetenango-W 韦韦特南戈-guatemala","paso-de-los-toros-A 埃尔帕索德洛斯托罗斯-uruguay|punta-del-este-A 埃斯特角-uruguay|chapicuy-C 查皮库伊-uruguay|paysandu-P 派桑杜-uruguay|treinta-y-tres-T 特雷塔伊特雷斯-uruguay","acarigua-A 阿卡里瓜-venezuela|antimano-A 安蒂马诺-venezuela|barquisimeto-B 巴基西梅托-venezuela|valera-B 巴莱拉-venezuela|barinas-B 巴里纳斯-venezuela|porlamar-B 波拉马尔-venezuela|guarenas-G 瓜雷纳斯-venezuela|ciudad-guayana-G 圭亚那城-venezuela|caracas-J 加拉加斯-venezuela|cantaura-K 坎陶拉-venezuela|cabimas-K 卡维马斯-venezuela|coro-K 科罗-venezuela|colonia-tovar-K 科洛尼亚托瓦尔-venezuela|cumana-K 库马纳-venezuela|maracay-M 马拉凯-venezuela|maracaibo-M 马拉开波-venezuela|mene-grande-M 梅内格兰德-venezuela|tumeremo-T 图梅雷莫-venezuela|upata-W 乌帕塔-venezuela","ocho-rios-A 奥乔里奥斯-jamaica|negril-N 内格里尔-jamaica","puerto-aisen-A 艾森港-chile|villa-alemana-A 阿莱马纳镇-chile|arica-A 阿里卡-chile|antofagasta-A 安托法加斯塔-chile|osorno-A 奥索尔诺-chile|ovalle-A 奥瓦列-chile|vina-del-mar-B 比尼亚德尔马-chile|calama-K 卡拉马-chile|copiapo-K 科皮亚波-chile|curico-K 库里-chile|rancagua-L 兰卡瓜-chile|punta-arenas-P 蓬塔阿雷纳斯-chile|pucon-P 普孔-chile|chaiten-S 沙伊顿-chile|santiago-S 圣地亚哥-chile|talca-T 塔尔卡-chile|talcahuano-T 塔尔卡诺瓦-chile|talagante-T 塔拉甘特-chile|temuco-T 特木科-chile|valdivia-W 瓦尔迪维亚-chile|valparaiso-W 瓦尔帕莱索-chile|vitacura-W 维塔库拉-chile|rocas-de-santo-domingo-Y 岩德圣多明各-chile|iquique-Y 伊基克-chile"]; +city['asia']=["andkhoi-A 安德胡伊-afghanistan|baghlan-farm-B 巴格兰农场-afghanistan|bamiyan-B 巴米扬-afghanistan|north-salang-B 北沙浪-afghanistan|farah-F 法拉赫-afghanistan|hairatan-H 海拉顿-afghanistan|herat-H 赫拉特-afghanistan|khost-H 霍斯特-afghanistan|ghazni-J 加慈尼-afghanistan|gardiz-J 加德兹-afghanistan|jalalabad-J 贾拉拉巴德-afghanistan|ghaziabad-J 加兹阿巴德-afghanistan|kabul-K 喀布尔-afghanistan|kabul-airport-K 喀布尔机场-afghanistan|kandahar-K 坎大哈-afghanistan|kandahar-airport-K 坎大哈机场-afghanistan|kunduz-K 昆都士-afghanistan|laghman-L 拉格曼-afghanistan|logar-L 洛加尔省-afghanistan|south-salang-N 南沙浪-afghanistan|chakhcharan-Q 恰赫恰兰-afghanistan|sarobi-S 萨罗比-afghanistan|tirinkot-T 提林库特-afghanistan|shindand-X 辛丹德-afghanistan|zaranj-Z 扎兰季-afghanistan","abu-dhabi-A 阿布扎比-united-arab-emirates|alain-int'l-airport-A 阿兰国际机场-united-arab-emirates|ajman-A 阿治曼-united-arab-emirates|dubai-D 迪拜-united-arab-emirates|al-fujayrah-F 富查伊拉-united-arab-emirates|ras-al-khaimah-H 哈伊马角-united-arab-emirates|sharjah-S 沙迦-united-arab-emirates|sharjah-int'l-airport-S 沙迦国际机场-united-arab-emirates|umm-al-qaywayn-W 乌姆盖万-united-arab-emirates","as-sib-A 阿斯布-oman|bahla-B 巴赫拉-oman|buraimi-B 布赖米-oman|diba-D 迪贝-oman|fahud-F 费胡德-oman|qalhat-G 盖勒哈特-oman|khassab-H 海塞卜-oman|khasab-port-H 海塞卜港-oman|khasab-airport-H 海塞卜机场-oman|rustaq-L 鲁斯塔克-oman|mamul-M 迈尔穆勒-oman|minasalalah-M 迈纳塞拉莱-oman|muscat-M 马斯哈特-oman|muscat-M 马斯喀特-oman|matrah-M 马特拉-oman|masirah-M 马西拉-oman|nizwa-N 奈兹瓦-oman|nizwa-N 尼日瓦-oman|salalah-S 塞拉莱-oman|thumrait-S 塞迈里-oman|samail-S 塞马伊勒-oman|sur-S 苏尔-oman|taqah-T 塔卡-oman|seeb-int'l-airport-X 希伯国际机场-oman|adam-Y 亚当-oman|ibra-Y 伊布拉-oman","agdam-A 阿格达姆-azerbaijan|ordubad-A 奥尔杜巴德-azerbaijan|astara-A 阿斯塔拉-azerbaijan|barda-B 巴尔达-azerbaijan|baku-B 巴库-azerbaijan|beylagan-aerodrome-B 贝拉甘机场-azerbaijan|bilasuvar-B 比利亚苏瓦尔-azerbaijan|dashkasan-D 达什卡桑-azerbaijan|goychay-G 盖奥克恰伊-azerbaijan|goris-G 戈里斯-azerbaijan|guba-G 古巴-azerbaijan|khachmaz-aerodrome-H 哈奇马斯机场-azerbaijan|jermuk-J 杰姆克-azerbaijan|qabala-K 卡巴拉-azerbaijan|gadabay-K 凯达贝克-azerbaijan|lachin-L 拉钦-azerbaijan|lankaran-L 连科兰-azerbaijan|lerik-L 列里克-azerbaijan|meghri-M 梅格里-azerbaijan|mingachevir-M 明盖恰乌尔-azerbaijan|nabran-N 纳布兰-azerbaijan|naftalan-airport-N 纳夫塔兰机场-azerbaijan|naxcivan-N 纳希切万-azerbaijan|neftchala-N 涅夫捷恰拉-azerbaijan|kurdamir-Q 丘尔达米尔-azerbaijan|sabirabad-S 萨比拉巴德-azerbaijan|salyan-S 萨利亚纳-azerbaijan|sharur-S 沙鲁尔-azerbaijan|shamkir-S 沙姆基尔-azerbaijan|shusha-S 舒沙-azerbaijan|sumgait-S 苏姆盖特-azerbaijan|tar-tar-T 塔塔-azerbaijan|oguz-W 乌古斯-azerbaijan|evlakh-airport-Y 叶夫拉赫机场-azerbaijan|zardab-Z 扎尔多布-azerbaijan|gandja-Z 占贾-azerbaijan","thimphu-T 廷布-bhutan","badin-A 阿拉丁-pakistan|okara-A 奥卡拉-pakistan|astore-A 阿斯多-pakistan|barkhan-B 巴尔汗-pakistan|bahawalpur-B 巴哈瓦尔布尔-pakistan|bahawalpur-airport-B 巴哈瓦尔布尔机场-pakistan|bahawalnagar-B 巴哈瓦尔讷格尔-pakistan|peshawar-B 白沙瓦-pakistan|balakot-B 巴拉科特-pakistan|bannu-B 巴努-pakistan|bunji-B 本及-pakistan|panjgur-B 本杰古尔-pakistan|pasni-B 伯斯尼-pakistan|dalbandin-D 达尔本丁-pakistan|faisalabad-F 费萨尔巴德-pakistan|faisalabad-F 费萨拉巴德-pakistan|gawadar-G 瓜达尔-pakistan|gupis-G 古比斯-pakistan|gujranwala-G 古杰兰瓦拉-pakistan|gujrat-G 古杰拉特-pakistan|hyderabad-H 海得拉巴-pakistan|hunza-H 罕萨-pakistan|khuzdar-H 胡兹达尔-pakistan|chitral-J 吉德拉尔-pakistan|jhelum-J 杰勒姆-pakistan|gilgit-J 吉尔吉特-pakistan|cherat-J 杰瑞特-pakistan|chiniot-J 吉尼奥德-pakistan|jiwani-J 吉沃尼-pakistan|kalam-K 卡拉姆-pakistan|karachi-K 卡拉奇-pakistan|kalat-K 卡拉特-pakistan|khanpur-K 坎布尔-pakistan|kasur-K 卡苏尔-pakistan|kohat-K 科哈特-pakistan|kohat-K 克哈特-pakistan|nokkundi-K 克昆迪-pakistan|quetta-K 奎达-pakistan|quetta-airport-K 奎达机场-pakistan|lahore-L 拉合尔-pakistan|lahore-airport-L 拉合尔机场-pakistan|lahore-city-L 拉合尔市-pakistan|rawalpindi-L 拉瓦尔品第-pakistan|rawalakot-L 拉沃拉科特-pakistan|risalpur-L 里沙浦-pakistan|rohri-L 罗赫里-pakistan|mardan-M 马尔丹-pakistan|mangla-M 曼格拉-pakistan|mianwali-M 米扬瓦里-pakistan|multan-M 木尔坦-pakistan|murree-M 穆里-pakistan|muzaffarabad-M 穆扎法阿巴德-pakistan|nawabshah-N 纳瓦布沙-pakistan|okara-O 欧卡拉-pakistan|parachinar-P 帕拉奇纳-pakistan|pattan-P 帕坦-pakistan|zhob-R 若布-pakistan|sargodha-S 萨戈达-pakistan|sahiwal-S 萨希瓦尔-pakistan|skardu-S 斯卡杜-pakistan|sukkur-S 苏库尔-pakistan|turbat-T 图尔伯德-pakistan|nawabshah-W 讷瓦布沙阿-pakistan|sibi-X 锡比-pakistan|shekhupura-X 谢胡布尔-pakistan|sialkot-X 锡亚尔科特-pakistan|sialkot-international-airport-X 锡亚尔科特国际机场-pakistan|jacobabad-Y 雅各布阿巴德-pakistan|islamabad-Y 伊斯兰堡-pakistan|islamabad-city-Y 伊斯兰堡市-pakistan|jhang-Z 章-pakistan|jhang-sadr-Z 章萨德尔-pakistan","manama-M 麦纳麦-bahrain","anju-A 安居-north-korea|anju-A 安州-north-korea|changjin-C 长津-north-korea|pungsan-F 丰山-north-korea|kusong-G 圭城-north-korea|haeju-H 海州-north-korea|hyesan-H 惠山-north-korea|kanggye-J 江界-north-korea|kimchaek-J 金策-north-korea|kaesong-K 开城-north-korea|ryongyon-L 龙渊-north-korea|pucheng-N 南浦-north-korea|pyonggang-P 平康-north-korea|pyongyang-P 平壤-north-korea|chongjin-Q 清津-north-korea|samjiyon-up-S 三池渊-north-korea|sariwon-S 沙里院-north-korea|supung-S 水丰-north-korea|senbong-X 先锋-north-korea|hamhung-X 咸兴-north-korea|huichon-X 熙川-north-korea|xinpu-X 新浦-north-korea|sinuiju-X 新义州-north-korea|yangdok-Y 阳德-north-korea|wonsan-Y 元山-north-korea|chunggang-Z 中江-north-korea","baucau-B 包考-timor-leste|dili-D 帝力-timor-leste|viqueque-W 维克克-timor-leste","alabat-A 阿拉巴特-philippines|ambulong-A 安布隆-philippines|olongapo-city-A 奥隆阿波-philippines|olutanga-A 奥卢丹牙岛-philippines|aparri-A 阿帕里-philippines|bacoor-B 巴科奥尔-philippines|pampanga-B 邦板牙-philippines|basa-airbase-B 巴萨航空基地-philippines|basco-B 巴斯科-philippines|basco-radar-B 巴斯科雷达区-philippines|virac-B 比拉克-philippines|baguio-city-B 碧瑶-philippines|borongan-B 博龙岸-philippines|dagupan-D 达古潘-philippines|tarlac-D 打拉-philippines|tandag-D 丹达-philippines|daet-D 达特-philippines|davao-city-D 达沃-philippines|davao-airport-D 达沃机场-philippines|dipolog-D 第波罗-philippines|dumaguete-D 杜马格特-philippines|fernando-airbase-F 费尔南多航空基地-philippines|guiuan-G 圭乌安-philippines|hinatuan-H 海纳图安-philippines|jolo-H 霍洛岛-philippines|calayan-J 加拉彦-philippines|cabanatuan-city-J 甲万那端-philippines|catbalogan-K 卡巴洛甘-philippines|cagayandetawi-tawi-K 卡加延德塔威塔威-philippines|cagayandeoro-K 卡加延德寨多-philippines|calapan-K 卡拉潘-philippines|catarman-K 卡塔曼-philippines|catanduanesradar-K 卡坦端内斯雷达区-philippines|casiguran-K 卡西古兰-philippines|clark-airbase-K 克拉克航空基地-philippines|coron-K 科隆-philippines|sciencegarden-K 科学园-philippines|quezon-city-K 奎松市-philippines|cuyo-K 库约-philippines|dagupan-L 拉古板-philippines|iloilo-L 怡朗-philippines|romblon-L 朗布隆-philippines|laoag-L 拉瓦格-philippines|lahug-L 拉巫格-philippines|libagon-L 利巴岗-philippines|legazpi-city-L 黎牙实比-philippines|lumbia-airport-L 伦比亚机场-philippines|roxas-L 罗哈斯-philippines|maasin-M 马阿辛-philippines|mactan-M 麦克坦-philippines|malaybalay-M 马拉巴拉-philippines|malolos-M 马洛洛斯-philippines|manila-M 马尼拉-philippines|masbate-M 马斯巴特-philippines|meycauayan-M 梅卡瓦延-philippines|munoz-M 穆诺斯-philippines|naula-point-N 诺拉站-philippines|pagadian-city-P 帕加迪安-philippines|zamboanga-S 三宝颜-philippines|sangleypoint-S 桑莱岬-philippines|general-santos-S 桑托斯将军城-philippines|generalsantos-S 三投斯将军市-philippines|san-jose-S 圣荷西-philippines|subicbay-weather-station-S 苏比克湾气象站-philippines|surigao-city-S 苏里高-philippines|cebu-S 宿务市-philippines|tagbilaran-T 塔比拉兰-philippines|tacloban-city-T 塔克洛班-philippines|tacloban-T 塔克洛班市-philippines|tayabas-T 塔亚巴斯-philippines|tuguegarao-T 土格加劳-philippines|port-prince-W 王子港-philippines|butuan-city-W 武端-philippines|sinait-synoptic-station-X 希纳特天气站-philippines|iloilo-Y 伊洛伊洛-philippines|infanta-Y 英凡达-philippines|itbayat-Y 伊特巴亚特-philippines","tbilisi-D 第比利斯-georgia|rustavi-L 鲁斯塔维-georgia","andong-A 安东-south-korea|chunchon-C 春川-south-korea|taegu-D 大邱-south-korea|polgyo-F 筏桥-south-korea|busan-F 釜山-south-korea|waegwan-G 倭馆-south-korea|seoul-H 汉城-south-korea|chinju-J 晋州-south-korea|pohang-P 浦项-south-korea|chupungnyong-Q 秋风岭-south-korea|kunsan-Q 群山-south-korea|ichon-R 仁川-south-korea|seoul-S 首尔-south-korea|sokcho-S 束草-south-korea|suwon-S 水原-south-korea|ulsan-W 蔚山-south-korea|ulchin-W 蔚珍-south-korea|wonju-Y 原州-south-korea","aqmola-A 阿克穆拉-kazakhstan|aktobe-A 阿克托比-kazakhstan|akkuduk-A 阿库杜克-kazakhstan|almaty-A 阿拉木图-kazakhstan|orsk-A 奥尔斯克-kazakhstan|atbasar-A 阿特巴萨尔-kazakhstan|atyrau-A 阿特劳-kazakhstan|balhash-B 巴尔喀什-kazakhstan|pavlodar-B 巴甫洛达尔-kazakhstan|bakanas-B 巴卡纳斯-kazakhstan|petropavlovsk-B 彼得罗巴甫洛夫斯克-kazakhstan|berlik-B 伯雷克-kazakhstan|dzhambejty-J 江贝提-kazakhstan|zhezkazgan-J 杰兹卡兹甘-kazakhstan|qaraghandy-K 卡拉干达-kazakhstan|kazalinsk-K 卡扎林斯克-kazakhstan|kosh-agach-K 科什阿加赤-kazakhstan|kyzyl-K 克孜勒-kazakhstan|kzyl-orda-K 克孜勒奥尔达-kazakhstan|kustanay-K 库斯塔奈-kazakhstan|ridder-L 里德尔-kazakhstan|rodino-L 罗迪诺-kazakhstan|ruzaevka-L 鲁扎耶夫卡-kazakhstan|otar-O 欧塔-kazakhstan|chapaevo-Q 恰帕耶夫-kazakhstan|shymkent-Q 奇姆肯特-kazakhstan|sigande-S 塞贡蒂-kazakhstan|semipalatinsk-S 塞米巴拉金斯克-kazakhstan|sam-S 山姆-kazakhstan|fortshevchenko-S 舍甫琴柯堡-kazakhstan|shymkent-S 什姆肯特-kazakhstan|stepnogorsk-S 斯捷普诺戈尔斯克-kazakhstan|talgar-T 塔尔戈哈尔-kazakhstan|taipak-T 泰帕克-kazakhstan|taraz-T 塔拉兹-kazakhstan|temir-T 铁米尔-kazakhstan|temirtau-T 铁米尔套-kazakhstan|turkestan-T 土耳其斯坦-kazakhstan|turocak-T 图罗恰克-kazakhstan|urdzhar-W 乌尔贾尔-kazakhstan|uralsk-W 乌拉尔斯克-kazakhstan|esil-Y 叶西尔-kazakhstan|zharkent-Z 扎尔肯特-kazakhstan|zhaltyr-Z 扎尔特尔-kazakhstan|dzhusaly-Z 朱萨雷-kazakhstan|zlikha-Z 兹利克哈-kazakhstan|zmeinogorsk-Z 兹梅伊诺戈尔斯克-kazakhstan","bishkek-B 比什凯克-kyrgyzstan|kara-suu-K 卡拉苏-kyrgyzstan|naryn-N 纳伦-kyrgyzstan|talas-T 塔拉斯-kyrgyzstan|tokmak-T 托克马克-kyrgyzstan","kompong-cham-B 磅湛-cambodia|svayrieng-C 柴桢-cambodia|krakor-G 格罗戈-cambodia|kampot-G 贡布-cambodia|phnom-penh-J 金边-cambodia|siemreap-L 暹粒-cambodia|battambang-M 马德望-cambodia|stungtreng-S 上丁省-cambodia","doha-D 多哈-qatar|doha-port-D 多哈港-qatar","abdaly-A 阿卜杜利-kuwait|ahmadi-A 艾哈迈迪-kuwait|bubiyan-B 巴比延-kuwait|failaka-island-F 费拉卡岛-kuwait|kuwait-K 科威特-kuwait|experimental-farm-S 实验农场-kuwait|shuwaikh-S 舒瓦克-kuwait|warba-W 瓦巴-kuwait","beirut-B 贝鲁特-lebanon|juniyah-Z 朱尼耶-lebanon","pakse-B 巴色-laos|bounneua-B 奔讷-laos|luang-prabang-L 琅勃拉邦-laos|paksong-P 帕克松-laos|seno-S 塞诺-laos|saravane-S 沙拉湾-laos|savannakhet-S 沙湾拿吉-laos|sayaboury-S 沙耶武里-laos|thakhek-T 他曲-laos|vientiane-W 万象-laos|oudomxay-W 乌多姆塞-laos","bhamo-B 八莫-myanmar|prome-B 卑谬-myanmar|pyinmana-B 彬马那-myanmar|bago-B 勃固-myanmar|pathein-B 勃生-myanmar|sandoway-D 丹兑-myanmar|mergui-D 丹老-myanmar|tharrawaddy-D 达雅瓦底-myanmar|toungoo-D 东吁-myanmar|taunggyi-D 东枝区-myanmar|kalewa-G 葛礼瓦-myanmar|homalin-H 霍马林-myanmar|kengtung-J 景栋-myanmar|hkamti-K 坎迪县-myanmar|katha-K 卡萨-myanmar|coco-island-K 可可岛-myanmar|lashio-L 腊戍-myanmar|nyaung-u-L 良乌县-myanmar|mandalay-M 曼德勒-myanmar|moulmein-M 毛淡棉-myanmar|maubin-M 马乌宾-myanmar|mingaladon-M 明加拉当-myanmar|minbu-M 敏巫-myanmar|meiktila-M 密铁拉-myanmar|myitkyina-M 密支那-myanmar|mawlaik-M 莫莱县-myanmar|hpa-an-P 帕安-myanmar|papun-P 帕本-myanmar|kyaukpyu-P 皎漂-myanmar|putao-P 葡萄-myanmar|sittwe-S 实兑-myanmar|dawei-T 土瓦-myanmar|monywa-W 望濑县-myanmar|victoria-point-W 维多利亚角-myanmar|shwebo-X 雪布-myanmar|rangoon-Y 仰光-myanmar","hanimaadhoo-H 哈霓玛阿都-maldives|kaadedhdhoo-J 佳特土-maldives|kadhdhoo-J 加途-maldives|male-M 马累-maldives","arvaiheer-A 阿尔拜赫雷-mongolia|aldar-A 阿尔达尔-mongolia|altai-A 阿尔泰-mongolia|baruunturuun-B 巴伦图伦-mongolia|bayan-ovoo-B 巴彦敖包-mongolia|bayanbulag-B 巴彦布拉格-mongolia|bayanhongor-B 巴彦洪戈尔-mongolia|bulgan-B 布尔干-mongolia|tsogt-ovoo-C 朝格特敖包-mongolia|tsetserleg-C 车车尔勒格-mongolia|dalanzadgad-D 达兰扎达嗄德-mongolia|dashbalbar-D 达什巴勒巴尔-mongolia|erdenetsagaan-E 额尔德尼查干-mongolia|hujirt-H 胡季尔特-mongolia|hutag-H 呼塔格-mongolia|halhaiin-sume-K 卡勒克戈尔-mongolia|hovd-K 科布多-mongolia|mandalgovi-M 曼达尔戈壁-mongolia|mandalgobi-M 曼达勒戈壁-mongolia|maanti-M 曼提-mongolia|matad-M 马塔德-mongolia|muren-M 慕仁-mongolia|choibalsan-Q 乔巴山-mongolia|sainshand-S 赛音山达-mongolia|tarialan-T 塔里亚兰-mongolia|tosontsengel-T 托孙臣格勒-mongolia|ulan-bator-W 乌兰巴托-mongolia|ulaangom-W 乌兰固木-mongolia|uliastai-W 乌里雅苏台-mongolia|baruun-urt-X 西乌尔特-mongolia|zamyn-uud-Z 扎门乌德-mongolia","barisal-B 巴瑞索-bangladesh|patuakhali-B 博杜阿卡利-bangladesh|bogra-B 博格拉-bangladesh|bhola-B 波拉-bangladesh|barisal-B 博里萨尔-bangladesh|teknaf-D 代格纳夫-bangladesh|dhaka-D 达卡-bangladesh|dinajpur-D 迪纳杰布尔-bangladesh|feni-F 芬尼-bangladesh|faridpur-F 福里德布尔-bangladesh|hatia-H 哈蒂亚-bangladesh|chandpur-J 坚德布尔-bangladesh|comilla-J 窖米而纳-bangladesh|chittagong-J 吉大港-bangladesh|jamalpur-J 杰马勒布尔-bangladesh|jessore-J 杰索尔-bangladesh|khulna-K 库尔纳-bangladesh|kutubdia-K 库图布迪亚-bangladesh|mongla-L 勐腊-bangladesh|rajshahi-L 拉杰沙希-bangladesh|rangpur-L 朗布尔-bangladesh|rangamati-L 兰加马蒂-bangladesh|madaripur-M 马达里布尔-bangladesh|mymensingh-M 迈门辛-bangladesh|narayanganj-N 纳拉扬甘杰-bangladesh|satkhira-S 萨德基拉-bangladesh|saidpur-S 塞德普尔-bangladesh|srimangal-S 斯里曼高-bangladesh|sandwip-S 松迪布-bangladesh|tangail-T 坦盖尔-bangladesh|sylhet-X 锡尔赫特-bangladesh|chuadanga-Z 朱瓦当加-bangladesh","ipoh-B 怡保-malaysia|batu-pahat-B 巴株巴辖-malaysia|simanggang-C 成邦江-malaysia|tawau-D 斗湖-malaysia|mersing-F 丰盛港-malaysia|kota-kinabalu-G 哥打基纳巴卢-malaysia|kuala-terengganu-G 瓜拉丁加奴-malaysia|kuantan-G 关丹-malaysia|kudat-G 古达-malaysia|kuching-G 古晋-malaysia|kuala-lumpur-J 吉隆坡-malaysia|dungun-J 吉隆坡龙运-malaysia|melaka-M 马六甲-malaysia|bintulu-M 民都鲁-malaysia|seremban-R 芙蓉-malaysia|johor-baharu-R 柔佛州新山市-malaysia|sabah-S 沙巴-malaysia|sandakan-S 山打根-malaysia|sibu-S 诗巫-malaysia|sitiawan-S 实兆远-malaysia|segamat-X 昔加末-malaysia","okhaldhunga-A 奥卡尔东加-nepal|bhairawa-airport-B 拜尔瓦机场-nepal|bhaktapur-B 巴克塔普尔-nepal|biratnagar-airport-B 比拉特纳加尔机场-nepal|pokhara-airport-B 博卡拉机场-nepal|dhangadhi-D 丹尔加希-nepal|dang-D 当斯-nepal|dhankuta-D 丹库塔-nepal|dadeldhura-D 登代尔图拉-nepal|kathmandu-J 加德满都-nepal|jumla-J 久姆拉-nepal|nepalgunj-airport-N 尼泊尔根杰机场-nepal|surkhet-S 苏尔凯德-nepal|taplejung-T 塔普勒琼-nepal|simara-airport-X 锡马拉机场-nepal","bethlehem-B 伯利恒-west-bank|qalandiyah-G 盖兰迪耶-west-bank|ramla-L 拉马拉-west-bank","akune-A 阿久根-japan|kishiwada-A 岸和田-japan|hachioji-B 八王子-japan|kitakyushu-B 北九州-japan|hamamatsu-B 滨松-japan|nagasaki-C 长崎-japan|nagano-C 长野-japan|okinawa-C 冲绳-japan|kasugai-C 春日井-japan|osaka-D 大阪-japan|omiya-D 大宫-japan|omuta-D 大牟田-japan|ogaki-D 大垣-japan|tokuyama-D 德山-japan|higashi-osaka-D 东大阪-japan|tokyo-D 东京-japan|toyonaka-F 丰中-japan|fukuoka-F 福冈-japan|toyama-F 富山-japan|okaya-G 冈谷-japan|okazaki-G 冈崎-japan|okayama-G 冈山-japan|takamatsu-G 高松-japan|miyazaki-G 宫崎-japan|hiroshima-G 广岛-japan|hakodate-H 函馆-japan|hegang-H 鹤冈-japan|wakayama-H 和歌山-japan|kofu-J 甲府-japan|ebetsu-J 江别-japan|himeji-J 姬路-japan|kyoto-fu-J 京都-japan|shizuoka-J 静冈县-japan|jinshi-J 津市-japan|kanazawa-J 金泽-japan|suzuka-L 铃鹿-japan|kagoshima-L 鹿儿岛-japan|motegi-M 茂木-japan|nagoya-M 名古屋-japan|yonago-M 米子-japan|nara-N 奈良-japan|noshiro-N 能代-japan|amagasaki-N 尼崎-japan|chiba-Q 千叶-japan|aomori-Q 青森-japan|akita-Q 秋田-japan|hitachi-R 日立-japan|morioka-S 森冈-japan|joetsu-S 上越-japan|yamaguchi-S 山口-japan|kobe-S 神户-japan|mito-S 水户-japan|yokkaichi-S 四日-japan|matsudo-S 松户-japan|matsuto-S 松任-japan|karatsu-T 唐津-japan|machida-T 町田-japan|sagamihara-X 相模原-japan|sendai-X 仙台-japan|otaru-X 小樽-japan|yukuhashi-X 行桥-japan|niigata-X 新泻-japan|kumamoto-X 熊本-japan|asahikawa-X 旭川-japan|iwakuni-Y 岩国-japan|ichinomiya-Y 一宫-japan|utsunomiya-Y 宇都宫-japan|sapporo-Z 札幌-japan|sasebo-Z 佐世保-japan","anuradhapura-A 阿奴拉达普勒-sri-lanka|badulla-B 巴杜勒-sri-lanka|batticaloa-B 拜蒂克洛-sri-lanka|bandarawela-B 班德勒韦勒-sri-lanka|pottuvil-B 波士维尔-sri-lanka|hambantota-H 汉班托塔-sri-lanka|jaffna-J 贾夫纳-sri-lanka|kandy-K 康堤-sri-lanka|katunayake-K 卡图那亚克-sri-lanka|colombo-K 科伦坡-sri-lanka|kurunegala-K 库鲁内格勒-sri-lanka|ratmalana-L 拉特默勒讷-sri-lanka|ratnapura-L 拉特纳普勒-sri-lanka|mannar-M 马纳尔-sri-lanka|mullaittivu-M 穆莱蒂武-sri-lanka|puttalam-P 普塔勒姆-sri-lanka|trincomalee-T 亭可马里-sri-lanka|vavuniya-W 瓦武尼亚-sri-lanka","famagusta-F 法马古斯塔-cyprus|ktima-K 克蒂马-cyprus|larnaca-L 拉纳卡-cyprus|limassol-L 利马索尔-cyprus|nicosia-N 尼科西亚-cyprus|paphos-P 帕福斯-cyprus|troodos-T 特罗-cyprus","al-ahsa-A 阿尔阿萨-saudi-arabia|al-khafji-A 阿尔卡夫及-saudi-arabia|abha-A 艾卜哈-saudi-arabia|al-ahsa-A 艾赫萨-saudi-arabia|arar-A 阿拉尔-saudi-arabia|al-jouf-A 奥尔朱夫-saudi-arabia|al-baha-B 巴哈-saudi-arabia|al-baha-airport-B 巴哈机场-saudi-arabia|bisha-B 比舍-saudi-arabia|ad-dawadimi-D 代瓦迪米-saudi-arabia|dhahran-D 达兰-saudi-arabia|dammam-D 达曼-saudi-arabia|dammam-aws-D 达曼航空气象处-saudi-arabia|kingfahad-int'l-airport-F 法赫德国王国际机场-saudi-arabia|guriat-G 古里亚特-saudi-arabia|al-hada-H 哈达-saudi-arabia|kingkhaled-int'l-airport-H 哈立德国王国际机场-saudi-arabia|hail-H 哈伊勒-saudi-arabia|hail-airport-H 哈伊勒机场-saudi-arabia|gassim-J 加西姆-saudi-arabia|gassim-airport-J 加西姆机场-saudi-arabia|jeddah-J 吉大-saudi-arabia|jeddah-J 吉达-saudi-arabia|jeddah-marine-J 吉达港-saudi-arabia|gizan-J 季赞-saudi-arabia|giran-J 吉赞-saudi-arabia|al-qatif-K 卡提福-saudi-arabia|rabigh-L 拉比格-saudi-arabia|rafha-L 拉夫哈-saudi-arabia|riyadh-L 利雅得-saudi-arabia|medina-M 麦地那-saudi-arabia|mecca-M 麦加-saudi-arabia|mina-M 迈纳-saudi-arabia|muzdalifah-M 穆兹达里法-saudi-arabia|najran-N 奈季兰-saudi-arabia|sakaka-S 塞卡凯-saudi-arabia|sajer-S 萨杰-saudi-arabia|tabuk-T 塔布克-saudi-arabia|tayma-T 泰马-saudi-arabia|al-taif-T 塔伊夫-saudi-arabia|turaif-T 图拉伊夫-saudi-arabia|al-wejh-W 沃季-saudi-arabia|al-jubail-Z 朱拜勒-saudi-arabia","adana-A 阿达纳-turkey|afyon-A 阿菲永-turkey|aydin-A 艾登-turkey|edirne-A 埃迪尔内-turkey|erzincan-A 埃尔津詹-turkey|erzurum-A 埃尔祖鲁姆-turkey|elazig-A 埃拉泽-turkey|eskisehir-A 埃斯基谢希尔-turkey|anamur-A 阿纳穆尔-turkey|ankara-A 安卡拉-turkey|antalya-A 安塔利亚-turkey|balikesir-B 巴勒克希尔-turkey|bandirma-B 班德尔玛-turkey|bergama-B 贝加盟-turkey|bismil-B 比斯米尔-turkey|bursa-B 布尔萨-turkey|diyarbakir-D 迪亚巴克尔-turkey|finike-F 菲尼克-turkey|gaziantep-J 加济安泰普-turkey|ceyhan-J 杰伊汉-turkey|kirsehir-K 克尔谢希尔-turkey|kirikkale-K 克鲁兹卡雷-turkey|konya-K 科尼亚-turkey|kusadasi-K 库沙达瑟-turkey|lapseki-L 拉普塞基-turkey|manavgat-M 马纳夫加特-turkey|merzifon-M 梅尔济丰-turkey|nevsehir-N 内夫谢希尔-turkey|pamukkale-P 帕莫卡莱-turkey|canakkale-Q 恰纳卡莱-turkey|corum-Q 乔鲁姆-turkey|samsun-S 萨姆松-turkey|tarsus-T 塔尔苏斯-turkey|tekirdag-T 泰基尔达-turkey|trabzon-T 特拉布宗-turkey|urla-W 乌拉-turkey|usak-W 乌沙克-turkey|siirt-X 锡尔特-turkey|silifke-X 西利夫克-turkey|inegol-Y 伊内格尔-turkey|iskenderun-Y 伊斯肯德伦-turkey|isparta-Y 伊斯帕尔塔-turkey|istanbul-Y 伊斯坦布尔-turkey|istanbul-ataturk-Y 伊斯坦布尔·阿塔图尔克-turkey|izmir-Y 伊兹密尔-turkey|zonguldak-Z 宗古尔达克-turkey","bangna-agrimet-B 邦那农业气象组-thailand|saraphi-B 班沙拉披-thailand|phatthaya-B 芭提雅-thailand|prachin-buri-B 巴武-thailand|prachinburi-B 巴真武里-thailand|kanchanaburi-B 北碧府-thailand|pakchong-agrimet-B 北冲农业气象组-thailand|chachoengsao-agrimet-B 北柳农业气象组-thailand|phetchaburi-B 碧武里-thailand|chaiyaphum-C 猜也蓬-thailand|chum-phae-C 春蓬-thailand|chon-buri-C 春武里-thailand|phetchaburi-F 佛丕-thailand|nakhonpathom-agrimet-F 佛统农业气象组-thailand|nakhon-ratchasima-H 呵叻-thailand|hat-yai-H 合艾-thailand|mae-hong-son-H 湄宏顺-thailand|lopburi-H 华富里-thailand|hua-hin-H 华欣-thailand|kabinburi-J 甲民武里-thailand|chanthaburi-J 尖竹汶-thailand|kosichang-K 考斯昌-thailand|nakhon-pathom-K 空巴吞-thailand|khon-kaen-K 孔敬-thailand|donmuang-L 廊曼-thailand|mae-rim-L 湄林-thailand|roi-et-L 黎逸-thailand|lop-buri-L 罗富里-thailand|rayong-L 罗永-thailand|maha-sarakham-M 玛哈沙拉堪-thailand|bangkok-M 曼谷-thailand|bangkok-port-M 曼谷港-thailand|mukdahan-M 莫达汉府-thailand|narathiwat-N 那拉提瓦-thailand|lamphun-N 南奔-thailand|nangrong-N 娘隆-thailand|ratchaburi-agrimet-N 叻丕农业气象组-thailand|phra-nakhon-si-ayutthaya-P 帕府市大城府-thailand|phayao-P 帕尧-thailand|phitsanulok-P 彭世洛-thailand|phuket-P 普吉岛-thailand|chiang-mai-Q 清迈-thailand|srakaew-S 沙缴市-thailand|samut-prakan-S 沙没巴干-thailand|samut-sakhon-S 沙木沙空-thailand|songkhla-S 宋卡府-thailand|suvarnabhumi-int'l-airport-S 苏凡纳布国际机场-thailand|surin-S 素林-thailand|surin-agrimet-S 素林农业气象组-thailand|ko-samui-S 苏梅岛-thailand|mae-sot-S 湄索-thailand|surat-thani-S 索叻他尼-thailand|sattahip-S 梭桃邑-thailand|suphan-buri-S 素攀武里-thailand|thai-muang-T 泰国芒-thailand|thalang-T 他朗-thailand|wichian-buri-W 威齐伯里-thailand|ubon-ratchathani-W 乌汶-thailand|buriram-W 武里南-thailand|uthong-agrimet-X 辛芳卡尔托农业气象组-thailand|aranyaprathet-Y 亚兰-thailand|chanthaburi-Z 庄他武里(尖竹汶)-thailand","pendzhikent-B 本吉肯特-tajikistan|darvaz-D 达沃滋-tajikistan|dushanbe-D 杜尚别-tajikistan|khorog-H 霍罗格-tajikistan|kurgan-tyube-K 库尔干秋别-tajikistan|kulyab-K 库利亚布-tajikistan|rushan-L 鲁雄-tajikistan|ishkashim-Y 伊什卡希姆-tajikistan","ashgabat-A 阿什哈巴德-turkmenistan|keshi-A 阿什哈巴德凯希-turkmenistan|bajramaly-B 巴依拉马利-turkmenistan|buzmeyin-B 别济梅恩-turkmenistan|darganata-D 达尔甘阿塔-turkmenistan|dashkhovuz-D 达什克霍夫兹-turkmenistan|erbent-E 厄本特-turkmenistan|gazandzhyk-J 加兹甘-turkmenistan|tejen-J 捷詹-turkmenistan|kaka-K 卡卡-turkmenistan|garrygala-K 卡拉卡拉-turkmenistan|kerki-K 克尔基-turkmenistan|murgab-M 穆尔加布-turkmenistan|nebitdag-N 涅比特达格-turkmenistan|carsanga-Q 恰尔尚加-turkmenistan|sarahs-S 萨拉戈特-turkmenistan|turkmenbashy-T 土库曼巴什-turkmenistan|ufra-W 乌夫拉-turkmenistan","bandar-seri-begawan-S 斯里巴加湾-brunei|bandar-seribegawan-S 斯里巴加湾市-brunei","olmaliq-A 阿尔马雷克-uzbekistan|bukhoro-B 布哈拉-uzbekistan|chardzhev-C 查尔哲夫-uzbekistan|fergana-F 费尔干纳-uzbekistan|kokand-H 浩罕-uzbekistan|chim-J 金武-uzbekistan|dzizak-J 吉扎克-uzbekistan|karakul-K 卡拉库耳-uzbekistan|karshi-K 喀什-uzbekistan|kattaqurghon-K 卡塔库尔干-uzbekistan|kungrad-K 昆格勒-uzbekistan|namangan-N 纳曼干-uzbekistan|nukus-N 努库斯-uzbekistan|nurata-N 努拉塔-uzbekistan|pskem-P 普斯凯姆-uzbekistan|chardara-Q 恰尔达拉-uzbekistan|samarqand-S 撒马尔罕-uzbekistan|tamdy-T 塔姆德-uzbekistan|tashkent-T 塔什干-uzbekistan|termez-T 铁尔梅兹-uzbekistan|urganch-W 乌尔根奇-uzbekistan|isfara-Y 伊斯法拉-uzbekistan","paya-lebar-B 巴耶利-singapore|serangoon-S 实龙岗-singapore|bukit-panjang-new-town-W 武吉班让-singapore|bukit-timah-estate-W 武吉知马-singapore|singapore-X 新加坡-singapore","etheria-A 艾特利亚-syria|palmyra-B 巴尔米拉-syria|damascus-D 大马士革-syria|deirezzor-D 德尔佐尔-syria|darayya-D 德拉雅-syria|furqlus-F 富尔格卢斯-syria|hama-H 哈马-syria|homs-H 霍姆斯-syria|kamishli-K 卡米什利-syria|raqqa-L 拉卡-syria|baselassad-int'l-airport-L 拉萨德基地国际机场-syria|lattakia-L 拉塔基亚-syria|tartous-T 塔尔图斯-syria|idlib-Y 伊德利卜-syria","mountabu-A 阿布山-india|adilabad-A 阿迪拉巴德-india|alwar-A 阿尔瓦尔-india|agra-A 阿格拉-india|ahmadabad-A 艾哈迈达巴德-india|elamanchili-A 埃拉曼奇利-india|ahmadnagar-A 艾迈德纳格-india|etawah-A 埃塔瓦-india|anakapalle-A 阿讷加伯莱-india|agartala-A 阿加尔塔拉-india|ajmer-A 阿杰梅尔-india|akola-A 阿科拉-india|arrah-A 阿拉-india|alleppey-A 阿勒皮-india|aligarh-A 阿里格尔-india|ariyalur-A 阿立亚鲁-india|aruppukkottai-A 阿鲁布戈代-india|ahmadabad-A 阿默达巴德-india|amravati-A 阿姆劳蒂-india|amritsar-A 阿姆利则-india|ambala-A 安巴拉-india|androth-A 安德罗特-india|angul-A 安古尔-india|amreli-A 安雷利-india|anupgarh-A 阿奴普加-india|okha-A 奥卡-india|auraiya-A 奥赖亚-india|aurangabad-A 奥兰加巴德-india|aurangabad-chikalthan-aerodrome-A 奥兰加巴德机场-india|guwahati-A 阿萨姆邦-india|azamgarh-A 阿扎姆加尔-india|baghdogra-B 巴多格拉-india|barmer-B 巴尔梅尔-india|burdwan-B 柏德旺-india|berhampore-B 柏蓝波-india|bagalkote-B 巴加尔科特-india|paradip-B 巴拉迪布-india|balasore-B 巴拉索尔-india|bharatpur-B 巴拉特普尔-india|ballia-B 巴利亚-india|balurghat-B 巴卢尔卡德-india|baroda-aerodrome-B 巴罗达机场-india|pamban-B 班本-india|banda-B 班达-india|bangalore-B 班加罗尔-india|bankura-B 班库拉-india|banswara-B 班斯瓦拉-india|bhavnagar-B 包纳加尔-india|bareilly-B 巴瑞利-india|patna-B 巴特那-india|belgaum-B 贝尔高姆-india|bailadila-B 贝拉迪拉-india|bellary-B 贝拉里-india|betul-B 贝土尔-india|bundi-B 本迪-india|pondicherry-B 本地治里-india|bidar-B 比德尔-india|bhilwara-B 比尔瓦拉-india|bijapur-B 比贾布尔-india|bikaner-B 比卡内尔-india|bhira-B 比拉-india|pilani-B 彼拉尼-india|bilaspur-B 比拉斯布尔-india|pilibhit-B 比利皮德-india|porbandar-B 波尔班达尔-india|porbandar-B 博尔本德尔-india|palakkad-B 伯拉卡德-india|banihal-B 伯尼哈尔-india|bhopal-B 波帕尔-india|basti-B 伯斯蒂-india|basirhat-B 伯西尔哈德-india|bhubaneswar-B 布巴内斯瓦尔-india|bhuntar-B 布恩塔-india|purnea-B 布尔尼亚-india|port-blair-B 布莱尔港-india|jammu-C 查谟-india|long-island-C 长岛-india|chandigarh-C 昌迪加尔-india|daltonganj-D 达顿干吉-india|dhar-D 达尔-india|darbhanga-D 达尔班加-india|dalhousie-D 达尔胡西-india|dharmapuri-D 达尔马布里-india|nanded-D 楠代德-india|diamond-harbour-D 戴蒙德港-india|darjeeling-D 大吉岭-india|mandi-D 大集市-india|dharmsala-D 达兰萨拉-india|damoh-D 达摩-india|dhanbad-D 丹巴德-india|daund-D 道恩德-india|dehra-dun-D 德拉敦-india|dehri-D 德里-india|nautanwa-D 瑙登瓦-india|dwarka-D 德瓦尔卡-india|digha-D 迪格哈-india|tirupati-D 蒂鲁帕蒂-india|thiruvananthapuram-D 蒂鲁文南特不勒姆-india|bhatinda-D 珀丁达-india|dindigul-D 丁迪古尔-india|deesa-D 迪萨-india|dispur-D 迪斯普尔-india|diu-D 第乌-india|nadiad-D 讷迪亚德-india|tondi-D 栋迪-india|tonk-D 栋格-india|dungarpur-D 栋格尔布尔-india|dhubri-D 杜布里-india|tuticorinnew-port-D 杜蒂戈林新港-india|durg-D 杜尔格-india|dohad-D 都哈-india|duraha-D 杜拉哈-india|dumka-D 杜姆卡-india|tuni-D 杜尼-india|dod-ballapur-D 多德伯拉布尔-india|dholpur-D 多尔浦-india|fatehpur-F 法特普尔-india|faizabad-F 法扎巴德-india|kalimpang-G 噶伦堡-india|gandhinagar-G 甘地讷格尔-india|gondia-G 冈迪亚-india|canning-G 甘宁-india|gangtok-G 甘托克-india|gopalpur-G 戈巴尔布尔-india|kota-aerodrome-G 哥打机场-india|gadag-G 格德格-india|kolhapur-G 戈尔哈布尔-india|nagercoil-G 讷格尔科伊-india|golaghat-G 哥拉加特-india|gorakhpur-G 戈勒克布尔-india|kanniyakumari-G 根尼亚古马里-india|godhra-G 戈特拉-india|coimbatore-G 哥印拜陀市-india|gonda-G 贡达-india|gulmarg-G 贡马-india|gwalior-G 瓜廖尔-india|cuddapah-G 古德伯-india|cuddalore-G 古德洛尔-india|gulbarga-G 古尔伯加-india|gurgaon-G 古尔冈-india|guwahati-G 古瓦哈蒂-india|hardoi-H 哈多伊-india|haflong-H 哈佛隆-india|hyderabad-airport-H 海得拉巴机场-india|hamirpur-H 哈默普尔-india|haora-H 豪拉-india|hassan-H 哈桑-india|harnai-H 赫尔奈-india|hazaribagh-H 赫札里巴克-india|haldia-H 霍尔迪亚-india|honavar-H 霍纳沃尔-india|hoshangabad-H 霍申加巴德-india|jabalpur-J 贾巴尔普尔-india|gadag-J 加达格-india|jalgaon-J 贾尔冈-india|kolkata-J 加尔各答-india|ghaziabad-J 加济阿巴德-india|ghazipur-J 加济布尔-india|jhalawar-J 贾拉瓦尔-india|jalore-J 贾洛尔-india|jamnagar-J 贾姆讷格尔-india|jamui-J 加木伊-india|jorhat-J 焦尔哈德-india|jodhpur-J 焦特布尔-india|kasaragod-J 加瑟勒戈德-india|jaisalmer-J 贾沙梅尔-india|jashpurnagar-J 加什普纳加-india|jatani-J 加特尼-india|chitradurga-J 吉德勒杜尔加-india|jalpaiguri-J 杰尔拜古里-india|jagdalpur-J 杰格德尔布尔-india|kailashahar-K 凯拉沙哈尔-india|kakinada-K 卡基纳达-india|karaikal-K 卡来卡-india|kalimpong-K 卡林朋-india|karnal-K 卡纳尔-india|kandla-aerodrome-K 坎德拉机场-india|conoor-K 康纳-india|khammam-K 坎曼-india|kanpur-K 坎普尔-india|kurnool-K 卡努尔-india|cuddalore-K 卡塔尔洛-india|kavali-K 卡瓦利-india|karwar-K 卡沃-india|qazigund-K 卡兹古德-india|kodaikanal-K 科代卡那-india|khajuraho-K 克久拉霍-india|kolar-K 科拉尔-india|kolar-goldfields-K 科拉尔金矿区-india|koraput-K 科拉普特-india|khandwa-K 肯德瓦-india|cochin-K 科钦-india|cuttack-K 克塔克-india|kottayam-K 科塔亚姆-india|keshod-K 克肖德-india|kohima-K 科希马-india|kozhikode-K 科泽科德-india|karipur-int'l-airport-K 科泽科德国际机场-india|kondul-K 孔杜尔岛-india|guna-K 库拿-india|raipur-L 赖布尔-india|raigarh-L 赖格尔-india|raichur-L 赖久尔-india|raisen-L 赖森-india|rajapalaiyam-L 拉杰巴莱亚姆-india|rajkot-L 拉杰果德-india|rajgarh-L 拉吉加尔-india|rangia-L 朗吉亚-india|ranchi-L 兰契-india|ratlam-L 拉特兰-india|ratnagiri-L 勒德纳吉里-india|rewa-L 雷瓦-india|lucknow-L 勒克瑙-india|rae-bareli-L 李博伯雷利-india|ludhiana-L 鲁得希阿那-india|ludhiana-L 卢迪亚纳-india|rourkela-L 罗尔凯勒-india|roorkee-L 罗克-india|rohtak-L 罗塔克-india|madurai-M 马都赖-india|madurai-M 马杜赖-india|malda-M 马尔达-india|mahbubnagar-M 马赫布卜讷格尔-india|mahuva-M 马湖华-india|mysore-M 迈索尔-india|malegaon-M 马莱冈-india|malegaon-M 马勒冈-india|mana-M 马那-india|mandvi-M 曼德维-india|mandya-M 曼迪亚-india|mainpuri-M 曼普里-india|matheran-M 曼斯仁-india|mathura-M 马图拉-india|medak-M 梅达克-india|medinipur-M 梅迪尼布尔-india|mumbai-M 孟买-india|midnapore-M 米德纳普尔-india|meerut-M 密鲁特-india|minicoy-M 米尼科伊岛-india|mormugao-M 莫尔穆冈-india|mahesana-M 默黑萨纳-india|moga-M 莫加-india|machilipatnam-M 默吉利伯德讷-india|moradabad-M 莫拉达巴德-india|motihari-M 莫提哈里-india|mussoorie-M 慕苏里-india|muzaffarpur-M 穆扎法尔布尔-india|muzaffarpur-aerodrome-M 穆扎法尔布尔机场-india|muzaffarnagar-M 穆扎法尔讷格尔-india|nalgonda-N 纳尔贡达-india|nagaur-N 纳高尔-india|nagappattinam-N 纳格伯蒂讷姆-india|nahan-N 纳汉-india|nainital-N 奈尼陶-india|najibabad-N 纳吉巴巴德-india|nancowry-N 南考雷-india|nasik-N 纳西克-india|nasik-city-N 纳西克城-india|nellore-N 内洛尔-india|nimach-N 尼默杰-india|nizamabad-N 尼扎马巴德-india|patiala-P 帕蒂亚拉-india|bhagalpur-P 帕戈尔布尔-india|panna-P 潘纳-india|pasighat-P 帕西加特-india|bhongir-P 蓬吉尔-india|vidisha-P 毗底沙-india|bhind-P 平德-india|bhiwandi-P 皮瓦恩迪-india|bhiwani-P 皮瓦尼-india|phulbani-P 普巴尼-india|bhuj-P 普杰-india|puri-P 普里-india|purulia-P 普路赖-india|pune-P 浦那-india|chandrapur-Q 钱德拉布尔-india|chickmagalur-Q 奇克马加卢尔-india|cherrapunji-Q 乞拉朋齐-india|chhindwara-Q 清德瓦拉-india|chennai-Q 钦奈-india|chintamani-Q 钦塔马尼-india|chittorgarh-Q 奇特多咖-india|chitradurga-Q 奇特拉达加-india|chittoor-Q 奇图尔-india|satara-S 萨达拉-india|salem-S 塞勒姆-india|sagar-S 萨加尔-india|sangli-S 桑迦利-india|shantiniketan-S 桑提尼克坦-india|satna-S 萨特纳-india|sambalpur-S 森伯尔布尔-india|shahjahanpur-S 斯哈赫贾汉普尔-india|siliguri-S 斯里古里-india|srinagar-S 斯利那加-india|supaul-S 苏包尔-india|sultanpur-S 苏尔坦普尔-india|surat-S 苏拉特-india|solapur-S 索拉布尔-india|solapur-S 索拉普-india|sonipat-S 索尼帕特-india|surendranagar-S 苏仁德拉那加-india|tadong-T 塔东-india|dharwad-T 塔尔瓦德-india|thane-T 塔纳-india|tambaram-T 坦巴拉-india|tangla-T 唐拉-india|thanjavur-T 坦贾武尔-india|tehri-T 特赫里-india|thiruvananthapuram-T 特拉凡德伦-india|thrissur-T 特里苏尔-india|tezpur-T 提斯浦尔-india|tezpur-T 提斯普尔-india|tura-T 图拉-india|valparai-W 瓦尔巴赖-india|wardha-W 瓦尔达-india|vadodara-W 瓦尔道拉-india|varanasi-W 瓦拉纳西-india|warangal-W 瓦朗加尔-india|vijayawada-W 维杰亚瓦达-india|vizianagaram-W 维济亚讷格勒姆-india|veraval-W 韦拉沃尔-india|virudunagar-W 维鲁杜讷格尔-india|vellore-W 韦洛尔-india|visakhapatnam-W 维萨卡帕特南-india|visakhapatnam-W 维沙卡帕特南-india|unnao-W 温瑙-india|ongole-W 翁戈尔-india|vengurla-W 文古尔拉-india|udaipur-W 乌代布尔-india|udaipurdabok-W 乌代布尔机场-india|udaipur-W 乌代普尔-india|udupi-W 乌都皮-india|ujjain-W 乌贾因-india|ulhasnagar-W 乌拉斯讷格尔-india|umaria-W 乌玛利亚-india|udhagamandalam-W 乌塔卡蒙德-india|sholapur-X 肖拉普尔-india|sibsagar-X 锡布萨格尔-india|sheopur-X 谢奥布尔-india|silchar-X 锡尔杰尔-india|shirali-X 希拉利-india|shillong-X 西隆-india|shimoga-X 希莫加-india|shimla-X 西姆拉-india|new-delhi-X 新德里-india|newkandla-X 新坎德拉-india|hisar-X 希萨尔-india|sivakasi-X 锡瓦卡西-india|shivpuri-X 希沃布里-india|yeotmal-Y 亚瓦特马尔-india|gaya-Y 伽耶-india|idar-Y 伊达尔-india|indore-Y 印多尔-india|imphal-Y 因帕尔-india|itanagar-Y 伊塔纳加尔-india|jaisalmer-Z 斋沙默尔-india|champa-Z 占城-india|jaunpur-Z 章普尔-india|jhansi-Z 占夕-india|jamshedpur-Z 詹谢普尔-india|jamshedpur-Z 哲雪铺-india","amman-A 安曼-jordan|jericho-J 杰利科-jordan|ma-an-M 马安-jordan|mafraq-M 马夫拉克-jordan|safi-S 萨菲-jordan|tafileh-T 塔菲拉-jordan|al-aqabah-Y 亚喀巴-jordan|aqaba-airport-Y 亚喀巴机场-jordan|jerunited-states-of-americalem-airport-Y 耶路撒冷机场-jordan|jafer-Z 斋福尔-jordan|zuwayza-Z 祖韦扎-jordan","bethlehem-B 伯利恒-west-bank|qalandiyah-G 盖兰迪耶-west-bank|ramla-L 拉马拉-west-bank","enarotali-A 埃纳罗塔利-indonesia|amahai-A 阿马哈尔-indonesia|amahai-A 阿马哈伊-indonesia|nangapinoh-A 楠阿皮诺-indonesia|bangil-B 邦义尔-indonesia|bitung-B 毕栋-indonesia|tanjungkarang-telukbetung-D 丹戒加兰-indonesia|tarempa-D 达仁巴-indonesia|denpasar-D 登巴萨-indonesia|timika-D 迪米卡-indonesia|pangkalpinang-G 槟港-indonesia|kotabaru-G 哥打巴鲁-indonesia|geser-G 格斯尔-indonesia|cirebon-J 井里汶-indonesia|palembang-J 巨港-indonesia|kalianget-K 卡利昂厄特-indonesia|cocos-island-airport-K 科科斯岛机场-indonesia|rangkasbitung-L 兰加士勿洞-indonesia|namlea-L 楠勒阿-indonesia|majene-M 马杰内-indonesia|bogor-M 茂物-indonesia|medan-M 棉兰-indonesia|bengkulu-M 明古鲁省-indonesia|nabire-N 纳比尔-indonesia|nabire-N 纳比雷-indonesia|ranai-N 那雷尼-indonesia|natal-N 纳塔尔-indonesia|pamekasan-P 帕梅卡桑-indonesia|purwakarta-P 普哇加达-indonesia|yogyakarta-R 日惹-indonesia|sanana-S 萨拉纳-indonesia|semarang-S 三宝垄-indonesia|semarang-S 三堡垄港市-indonesia|samarinda-S 三马林达-indonesia|serang-S 瑟朗-indonesia|christmas-island-airport-S 圣诞岛机场-indonesia|situbondo-S 诗都文罗-indonesia|sungaigerong-S 双溪格龙-indonesia|sumbawa-besar-S 松巴哇岛-indonesia|tanahmerah-T 塔纳默拉-indonesia|tegal-T 特加尔-indonesia|banyuwangi-W 外南梦-indonesia|wamena-W 瓦梅纳-indonesia|bandung-W 万隆-indonesia|manado-W 万鸦老-indonesia|sintang-X 新当-indonesia|jakarta-Y 雅加达-indonesia|tegal-Z 直葛-indonesia|cilacap-Z 芝拉扎-indonesia","abadeh-A 阿巴代-iran|abadan-A 阿巴丹-iran|abadan-A 阿巴丹岛-iran|abumunited-states-of-america-A 阿布穆萨岛-iran|ardebil-A 阿德比尔-iran|ahar-A 阿哈尔-iran|arak-A 阿拉克-iran|anzali-A 安扎里-iran|ahvaz-A 阿瓦士-iran|ahwaz-A 阿瓦兹-iran|azar-shahr-A 阿扎尔沙赫尔-iran|bam-B 巴姆-iran|bandarabbass-B 班达阿巴斯-iran|bandar-e-anzali-B 班娥安扎里-iran|bandar-e-mahshahr-B 班娥港-iran|birjand-B 比尔詹德-iran|bojnurd-B 博季努尔德-iran|bushehr-B 布什尔-iran|bushehr-airport-B 布什尔机场-iran|tabriz-D 大不里士-iran|do-gonbadan-D 道戈巴但-iran|tehran-D 德黑兰-iran|gorgan-G 戈尔甘-iran|shahreza-G 戈姆-iran|gorgan-G 古尔甘-iran|kharg-H 哈格岛-iran|hamedan-H 哈麦丹-iran|khor-H 豪尔-iran|khorramabad-H 霍拉马巴德-iran|khoy-H 霍伊-iran|jask-J 贾斯克-iran|ghazvin-J 加兹温-iran|kish-island-J 基什岛-iran|kanavis-K 卡纳维斯-iran|kashan-K 卡珊-iran|kerman-K 克尔曼-iran|konarak-K 克拉那克-iran|kermanshah-K 科曼莎-iran|ramsar-L 拉姆萨尔-iran|rasht-L 雷什特-iran|bandar-lengeh-L 伦格港-iran|makko-M 马库-iran|maragheh-M 马拉盖-iran|mashhad-M 马什哈德-iran|masjed-soleyman-M 马斯吉德苏来曼-iran|mehriz-M 梅赫里兹-iran|sabzevar-S 萨卜泽瓦尔-iran|semnan-S 塞姆南-iran|sarab-S 萨拉-iran|sarakhs-S 萨拉赫斯-iran|saravan-S 萨拉万-iran|sanandaj-S 萨南达季-iran|noshahr-S 瑙沙赫尔-iran|shahrud-S 沙鲁德-iran|shiraz-S 设拉子-iran|tabas-T 塔巴斯-iran|torbat-heydarieh-T 托儿巴特海达里耶-iran|orumieh-W 乌尔米耶-iran|sirjan-X 锡尔詹-iran|yazd-Y 亚兹德-iran|ilam-Y 伊拉姆-iran|iranshahr-Y 伊朗沙赫尔-iran|isfahan-Y 伊斯法罕-iran|zanjan-Z 赞詹-iran|zabol-Z 扎布尔-iran|zargan-Z 扎尔甘-iran|zahedan-Z 扎黑丹-iran","amara-A 阿玛拉-iraq|badrah-B 巴德拉-iraq|baghdad-B 巴格达-iraq|baqubah-B 巴古拜-iraq|baiji-B 拜伊吉-iraq|basra-B 巴士拉-iraq|basrah-port-B 巴斯拉港-iraq|diwaniya-D 迪瓦尼耶-iraq|hadithah-H 哈迪塔-iraq|hella-H 海拉-iraq|khanaqin-H 哈奈根-iraq|kirkuk-J 基尔库克-iraq|kerbela-K 卡尔巴拉-iraq|kut-K 库特-iraq|rafaei-L 拉发雷尔-iraq|ramadi-L 拉马迪-iraq|rutbah-L 鲁特拜-iraq|mosul-M 摩苏尔-iraq|najaf-N 纳贾夫-iraq|an-najaf-al-ashraf-N 纳杰夫-iraq|nasiriya-N 纳西里耶-iraq|salahaddin-S 撒拉丁-iraq|samawa-S 萨马沃-iraq|soran-S 索兰-iraq|tikrit-T 提克里特-iraq|tuz-T 图兹-iraq|al-hillah-X 希拉-iraq|sinjar-X 辛贾尔-iraq|anah-Y 亚拿-iraq|zakho-Z 扎胡-iraq","ataq-A 阿塔克-yemen|al-ghaydah-G 盖达-yemen|ghayl-ba-wazir-G 盖勒钡瓦齐尔-yemen|hajjah-H 哈杰-yemen|hodeidah-H 荷台达-yemen|kamaran-K 卡马朗-yemen|lahij-L 拉赫季-yemen|riyan-L 里雅恩-yemen|marib-M 马利卜-yemen|mokha-M 摩卡-yemen|mukeiras-M 穆赫拉斯-yemen|mukayris-M 姆凯拉斯-yemen|saada-S 萨达-yemen|thamud-S 赛莫德-yemen|sana-S 萨那-yemen|socotra-S 索科特拉岛-yemen|taizz-T 塔伊兹-yemen|ash-shaykh-uthman-X 谢赫欧斯曼-yemen|adan-Y 亚丁-yemen|ibb-Y 伊卜-yemen|dhamar-Z 扎马尔-yemen","yerevan-A 埃里温-armenia|areni-A 阿雷尼-armenia|ararat-A 阿勒山-armenia|amasia-A 阿马西亚-armenia|amberd-A 安伯-armenia|ashtarak-A 阿什塔拉克-armenia|artashat-A 阿塔沙特-armenia|fantan-F 法坦-armenia|gavar-J 嘉瓦-armenia|gyumri-J 久姆里-armenia|shorja-S 绍尔哈-armenia|vanadzor-W 瓦纳佐尔-armenia|yerevan-airport-Y 耶烈万机场-armenia|idjevan-Y 伊杰万-armenia","an-nhon-A 安宁-vietnam|bachlongvi-B 白龙尾县-vietnam|bac-giang-B 北江-vietnam|bien-hoa-B 边和-vietnam|phanthiet-F 藩切市-vietnam|fuguo-F 富国-vietnam|da-nang-G 岘港-vietnam|vinh-G 光荣-vietnam|quy-nhon-G 贵仁-vietnam|hai-phong-H 海防-vietnam|hanoi-H 河内-vietnam|ho-chi-minh-city-H 胡志明市-vietnam|ca-mau-J 金瓯-vietnam|conson-K 康森-vietnam|lao-cai-L 老街-vietnam|langson-L 谅山-vietnam|nam-dinh-N 南定省-vietnam|phan-thiet-P 潘切-vietnam|can-tho-Q 芹苴-vietnam|vinh-R 荣市-vietnam|song-cau-S 宋科-vietnam|vung-tau-T 头顿-vietnam|nha-trang-Y 芽庄-vietnam|nhatrang-Y 衙庄市-vietnam","elat-A 埃拉特-israel|acre-A 阿克里-israel|ovda-A 奥华特-israel|qiryat-ata-A 阿塔村-israel|bat-yam-B 巴特亚姆-israel|ashdod-north-B 北阿什杜德-israel|beer-sheva-B 贝尔谢巴-israel|beersheva-city-B 贝尔谢巴市-israel|bene-beraq-B 贝内贝拉克-israel|qiryat-bialik-B 比亚利克村-israel|zova-C 措瓦-israel|herzliyya-H 海尔兹利亚-israel|haifa-H 海法-israel|holon-H 霍隆-israel|ramat-gan-L 拉马特甘-israel|rehovot-L 雷霍沃特-israel|rishon-leziyyon-L 里雄来锡安-israel|qiryat-motzkin-M 莫茨金村-israel|nahariyya-N 纳哈里亚-israel|netanya-N 内坦亚-israel|nesher-N 内谢尔-israel|petah-tiqwa-P 佩塔提克瓦-israel|tel-aviv-T 特拉维夫-israel|qiryat-yam-Y 亚姆村-israel|jerusalem-Y 耶路撒冷-israel|jerunited-states-of-americalem-centre-Y 耶路撒冷中央区-israel|yotvata-Y 约特瓦塔-israel"]; +city['europe']=["achenkirch-A 阿亨基希-austria|eferding-A 埃弗丁-austria|eisenstadt-A 艾森斯塔特-austria|amstetten-A 阿姆施泰滕-austria|obergurgl-A 奥伯谷尔格-austria|baden-B 巴登-austria|bad-gleichenberg-B 巴特格莱兴贝格-austria|bad-hofgastein-B 巴特霍夫加施泰因-austria|badgastein-B 巴特加施泰因-austria|bad-ischl-B 巴特伊施尔-austria|zell-am-see-B 滨湖采尔-austria|neusiedl-am-see-B 滨湖新锡德尔-austria|bischofshofen-B 比绍夫斯霍芬-austria|poysdorf-B 波伊斯多夫-austria|brand-B 布兰德-austria|bregenz-B 布雷根茨-austria|bludenz-B 布鲁登茨-austria|brenner-B 布伦纳-austria|zeltweg-C 采尔特维格-austria|zwettl-stadt-C 茨韦特尔城-austria|deutschlandsberg-D 德意志兰茨贝格-austria|deutschlandsberg-D 德意志兰兹博格-austria|dornbirn-D 多恩比恩-austria|donaufeld-D 多瑙费尔德-austria|enns-E 恩斯-austria|feldbach-F 费尔德巴赫-austria|feldkirch-F 费尔德基希-austria|feldkirchen-F 费尔德基兴-austria|furstenfeld-F 菲尔斯滕费尔德-austria|villach-F 菲拉赫-austria|fischbach-F 费施巴赫-austria|warth-F 风怒角-austria|volkermarkt-F 弗尔克马克特-austria|vocklabruck-F 弗克拉布鲁克-austria|freistadt-F 福莱斯塔特-austria|friesach-F 弗里萨赫-austria|ganserndorf-G 甘瑟恩多夫-austria|graz-G 格拉茨-austria|gleisdorf-G 格莱斯多夫-austria|gratkorn-G 格兰特科恩-austria|grieskirchen-G 格里斯科尔琴-austria|grossenzersdorf-G 格洛森哲斯多夫-austria|gmunden-G 格蒙登-austria|hallein-H 哈莱恩-austria|hermagor-H 黑马戈尔-austria|holzgau-H 霍尔茨高-austria|kitzbuhel-J 基茨比厄尔-austria|kitzbuehel-J 基茨比尔-austria|gussing-J 居辛-austria|kapfenberg-K 卡芬堡-austria|kapfenberg-K 卡普芬贝格-austria|korneuburg-K 科恩堡-austria|klagenfurt-K 克拉根福-austria|klagenfurt-airport-K 克拉根福机场-austria|krems-K 克雷姆斯-austria|kremsmuenster-K 克雷姆斯明斯特-austria|krimml-K 克里姆勒-austria|klosterneuburg-K 克洛斯特新堡-austria|knittelfeld-K 克尼特尔费尔德-austria|kufstein-K 库夫施泰因-austria|leonding-L 莱昂丁-austria|leibnitz-L 莱布尼茨-austria|leibnitz-L 莱布尼兹-austria|bruck-an-der-leitha-L 莱塔河畔布鲁克-austria|landeck-L 兰德克-austria|langenlois-L 朗根罗伊斯-austria|lannach-L 兰纳克-austria|ranshofen-L 兰舍芬-austria|rauris-L 劳里斯-austria|retz-L 雷茨-austria|radstadt-L 雷德斯塔特-austria|liezen-L 利岑-austria|lienz-L 利恩茨-austria|lilienfeld-L 利林费尔德-austria|linz-L 林茨-austria|rohrbach-L 罗尔巴赫-austria|lofer-L 洛费尔-austria|reutte-L 罗伊特-austria|mayrhofen-M 迈尔霍芬-austria|mariaalm-M 玛丽亚草甸-austria|mattersburg-M 马特斯-austria|melk-M 梅尔克-austria|murzzuschlag-M 米尔茨楚施拉格-austria|millstatt-M 米尔施塔特-austria|mistelbach-M 米斯特巴尔赫-austria|mistelbach-M 密斯特巴赫-austria|modling-M 莫德灵-austria|bruck-an-der-mur-M 穆尔河畔布鲁克-austria|murau-M 穆劳-austria|neumarkt-N 诺伊马克特-austria|neusiedl-N 诺伊希德尔-austria|patscherkofel-P 帕茨科托弗-austria|poertschach-P 帕特沙赫-austria|perg-P 佩尔戈-austria|puchberg-P 普赫贝格-austria|salzburg-S 萨尔茨堡-austria|seibersdorf-S 塞贝斯多夫-austria|seiersberg-S 塞尔斯博格-austria|semmering-S 塞默灵-austria|oberpullendorf-S 上普伦多尔夫-austria|obertauern-S 上陶恩-austria|oberwart-S 上瓦特-austria|scheibbs-S 沙伊布斯-austria|schaerding-S 舍尔丁-austria|schladming-S 施拉德明-austria|steyregg-S 施泰雷格-austria|stockerau-S 施托克劳-austria|schwaz-S 施瓦茨-austria|steyr-S 斯太尔-austria|sonnblick-S 松布利克-austria|tamsweg-T 塔姆斯维格-austria|tulln-T 图尔恩-austria|weiz-W 魏茨-austria|waidhofen-an-der-thaya-W 魏德霍芬河畔塔亚-austria|waidhofen-an-der-ybbs-W 魏德霍芬河畔伊布斯-austria|wien-schwechat-airport-W 维恩施威夏特机场-austria|villach-W 维拉克-austria|vienna-W 维也纳-austria|wiener-neustadt-W 维也纳新城-austria|windischgarsten-W 温迪施加斯滕-austria|unken-W 温肯-austria|wolfsburg-W 沃尔夫斯堡-austria|sillian-X 锡利安-austria|imst-Y 伊姆斯特-austria|innsbruck-Y 因斯布鲁克-austria|innsbruck-airport-Y 因斯布鲁克机场-austria|ischgl-Y 伊施格尔-austria|judenburg-Y 尤登堡-austria|mondsee-Y 月亮湖-austria|seefeld-Z 泽费尔德-austria|jennersdorf-Z 詹纳斯多夫-austria|jenbach-Z 珍巴赫-austria|zurs-Z 祖尔斯-austria","tirane-D 地拉那-albania|durres-D 都拉斯-albania|vlore-F 夫罗勒-albania|gjirokastra-J 吉诺卡斯特-albania|korca-K 科尔察-albania|kukes-K 库奇斯-albania|peshkopi-P 佩什科比-albania|shkoder-S 斯库台-albania","arklow-A 阿克洛-ireland|oranmore-A 奥兰莫尔-ireland|aasleagh-A 阿斯利-ireland|ballycanew-B 巴利卡纽-ireland|ballymahon-B 巴利马洪-ireland|ballinasloe-B 巴利纳斯洛-ireland|ballincollig-B 巴林克利格-ireland|belmullet-B 贝尔马利特-ireland|portmarnock-B 波特马诺克-ireland|drogheda-D 德罗伊达-ireland|dun-laoghaire-D 邓莱里-ireland|dublin-D 都柏林-ireland|dublin-airport-D 都柏林<爱尔兰首都>机场-ireland|galway-G 戈尔韦-ireland|killadysert-J 基拉迪瑟特-ireland|casement-aerodrome-K 凯斯门特机场-ireland|carrigaline-K 卡里加林-ireland|carrickmacross-K 卡里克马克罗斯-ireland|connaught-airport-K 康诺特机场-ireland|castlebar-K 卡斯尔巴-ireland|castlemartyr-K 卡斯尔马特-ireland|cork-K 科克-ireland|cork-airport-K 科克机场-ireland|claremorris-K 克莱尔莫里斯-ireland|clones-K 克朗斯-ireland|crookhaven-K 克鲁克黑文-ireland|clonakilty-K 克洛纳基尔蒂-ireland|leixlip-L 莱克斯利普-ireland|letterkenny-L 莱特肯尼-ireland|port-laoise-L 莱伊什港-ireland|limerick-L 利默里克-ireland|ringaskiddy-L 灵厄斯基迪-ireland|portlaw-L 洛港-ireland|loughrea-L 洛赫雷-ireland|roscrea-L 罗斯克雷-ireland|rosslare-L 罗斯莱尔-ireland|maringa-M 马林加-ireland|malinhead-M 马林角-ireland|midleton-M 米德尔顿-ireland|moycullen-M 莫伊库伦-ireland|mullingar-M 穆林加尔-ireland|newmarket-on-fergus-N 纽马基特弗格斯-ireland|pallaskenry-P 帕拉斯金利-ireland|shercock-S 舍考克-ireland|carrick-on-suir-S 舒尔河畔卡里克-ireland|tallaght-T 塔拉特-ireland|valentia-observatory-W 瓦伦蒂亚天文台-ireland|carrick-on-shannon-X 香农河畔卡里克-ireland|shannon-airport-X 香农机场-ireland|sherkin-island-X 谢尔金岛-ireland|edenderry-Y 伊登德里-ireland","kunda-K 昆达-estonia|tallinn-T 塔林-estonia|turi-T 图里-estonia|virtsu-W 维尔楚-estonia|jogeva-Y 约格瓦-estonia","egilsstadir-A 埃基斯蒂尔-iceland|eyrarbakki-A 埃拉巴几-iceland|akureyri-A 阿库雷里-iceland|bolungavik-B 博隆加维克-iceland|blonduos-B 布伦迪欧斯-iceland|dalvik-D 达尔维克-iceland|dalatangi-D 达拉角-iceland|grundartangi-G 格兰达坦基-iceland|grimsey-G 格雷姆塞岛-iceland|grimsstadir-G 格里姆斯塔迪尔-iceland|grindavik-G 格林达维克-iceland|hofn-H 赫本-iceland|hveravellir-H 惠拉维德利-iceland|keflavikurflugvollur-K 凯夫拉维克-iceland|reykjavik-L 雷克雅维克-iceland|reykjavik-L 雷克雅未克-iceland|raufarhofn-L 勒伊法赫本-iceland|patreksfjordur-P 帕特雷克斯尧德-iceland|stykkisholmur-S 斯蒂基斯霍尔米-iceland|straumsvik-S 斯特勒伊姆维克-iceland|kaupstadhur-W 韦斯特曼纳群岛-iceland|hveragerdi-W 温泉城-iceland|gjogur-Z 哲居尔-iceland","orsha-A 奥尔沙-belarus|baranavichy-B 巴拉诺维奇-belarus|barysaw-B 鲍里索夫-belarus|polotsk-B 波洛茨克-belarus|brest-B 布雷斯特-belarus|dobrush-D 多布鲁什-belarus|dokshitsy-D 多克西泽-belarus|gorki-G 高尔基-belarus|gomel-G 高美尔-belarus|hrodna-G 格罗德诺-belarus|homyel-G 戈梅利-belarus|kobrin-K 科布林-belarus|lida-L 利达-belarus|lyntupy-L 林图皮-belarus|lepel-L 利普-belarus|minsk-M 明斯克-belarus|mozyr-M 莫济里-belarus|mogilev-M 莫吉廖夫-belarus|pinsk-P 平斯克-belarus|slavgorod-S 斯拉夫戈罗德-belarus|spas-demensk-S 斯帕斯-杰缅斯克-belarus|vitsyebsk-W 维捷布斯克-belarus|vitebsk-W 维特伯斯克-belarus|senno-X 仙纳-belarus","banja-luka-B 巴尼亚卢卡-bosnia-and-herzegovina|bihac-B 比哈奇-bosnia-and-herzegovina|brcko-B 布尔奇科-bosnia-and-herzegovina|bugojno-B 布戈伊诺-bosnia-and-herzegovina|gradacac-G 格拉达卡奇-bosnia-and-herzegovina|kotor-varos-K 科托尔城-bosnia-and-herzegovina|livno-L 利夫诺-bosnia-and-herzegovina|mostar-M 莫斯塔-bosnia-and-herzegovina|mostar-M 莫斯塔尔-bosnia-and-herzegovina|neum-N 涅姆-bosnia-and-herzegovina|sarajevo-S 萨拉热窝-bosnia-and-herzegovina|sanski-most-S 桑斯基莫斯特-bosnia-and-herzegovina|tuzla-T 图兹拉-bosnia-and-herzegovina|jajce-Y 伊策-bosnia-and-herzegovina|zenica-Z 泽尼察-bosnia-and-herzegovina","burgas-B 布尔加斯-bulgaria|blagoevgrad-B 布拉戈耶-bulgaria|dragoman-D 德拉格曼-bulgaria|vratsa-F 弗拉察-bulgaria|vratza-F 弗拉塔-bulgaria|gotse-delchev-G 戈采代尔切夫-bulgaria|stara-zagora-J 旧扎戈拉-bulgaria|kavarna-K 卡瓦尔纳-bulgaria|kurdjali-K 库尔德加里-bulgaria|razgrad-L 拉兹格勒-bulgaria|lovetch-L 洛夫奇-bulgaria|rousse-L 鲁塞-bulgaria|montana-M 蒙大纳-bulgaria|pazardzhik-P 帕扎尔吉克-bulgaria|pernik-P 佩尔尼克-bulgaria|pleven-P 普列文-bulgaria|plovdiv-P 普罗夫迪夫-bulgaria|sandanski-S 桑丹斯基-bulgaria|shabla-S 沙布拉-bulgaria|sliven-S 斯利文-bulgaria|svilengrad-S 斯维林格勒-bulgaria|sofia-S 索菲亚-bulgaria|sofia-S 索非亚-bulgaria|tolbukhin-T 托尔布欣-bulgaria|varna-W 瓦尔纳-bulgaria|vidin-W 维丁-bulgaria|silistra-X 锡利斯特拉-bulgaria|ivailo-Y 伊瓦依洛-bulgaria","elblag-A 埃尔布隆格-poland|opole-A 奥波莱-poland|olsztyn-A 奥尔什丁-poland|ostroleka-A 奥斯特罗文卡-poland|otwock-A 奥特沃克-poland|babimost-B 巴比莫斯特机场-poland|belchatow-B 贝尔恰托-poland|belsk-B 贝沃兹-poland|bydgoszcz-B 彼得哥什-poland|bielsko-biala-B 别尔斯克·比亚瓦-poland|bialystok-B 比亚韦斯托克-poland|poznan-B 波兹南-poland|gorzow-wielkopolski-D 大波兰地区戈茹夫-poland|danzig-nd-D 但泽-poland|tychy-D 蒂黑-poland|wroclaw-F 弗罗茨瓦夫-poland|wlodawa-F 符沃达瓦-poland|gdansk-G 格但斯克-poland|gdansk-rebiechowo-G 格但斯克机场-poland|gdynia-G 格丁尼亚-poland|goleniow-G 戈莱纽夫-poland|grudziadz-G 格鲁德柴兹-poland|gniezno-G 格涅兹诺-poland|hel-H 赫尔-poland|warsaw-H 华沙-poland|kielce-K 凯尔采-poland|kalisz-K 卡利什-poland|katowice-K 卡托维兹-poland|katowice-pyrzowice-K 卡托维兹佩朔维茨-poland|kozienice-K 科杰尼采-poland|cracow-K 克拉科夫-poland|kolo-K 科洛-poland|krosno-K 克罗斯诺-poland|ketrzyn-K 肯琴-poland|koszalin-K 科沙林-poland|ketrzyn-K 克特钦-poland|kolobrzeg-K 科沃布热格-poland|klodzko-K 克沃兹科-poland|koszalin-K 科扎林-poland|legnica-L 莱格尼察-poland|leszno-L 莱什诺-poland|lesko-L 莱斯科-poland|lebork-L 劳恩堡-poland|raciborz-L 拉齐布日-poland|leba-L 勒巴-poland|rybnik-L 雷布尼克-poland|lublin-L 卢布林-poland|lodz-L 罗兹市-poland|zielonagora-L 绿山城-poland|malczyce-M 马尔克兹伊切-poland|mielec-M 梅莱茨-poland|mikolajki-M 米科瓦伊基-poland|mlawa-M 姆拉沃-poland|mlawa-M 姆瓦瓦-poland|pila-P 皮拉-poland|przemysl-P 普热梅希尔-poland|pulawy-P 普瓦维-poland|plock-P 普沃茨克-poland|chojnice-Q 乔伊尼斯-poland|czestochowa-Q 琴斯托霍瓦-poland|rzeszow-R 热舒夫-poland|sandomierz-S 桑多梅日-poland|szczecinek-S 什切齐内克-poland|szczecin-S 什切青-poland|sniezka-S 斯涅兹卡-poland|stargard-szczecinski-S 斯塔加德什切青-poland|starachowice-S 斯塔拉乔维切-poland|slubice-S 斯武比采-poland|sosnowiec-S 索斯诺维茨-poland|suwalki-S 苏瓦乌基-poland|tarnow-T 塔尔努夫-poland|terespol-T 特雷斯波尔-poland|torun-T 托伦-poland|wielun-W 维隆-poland|ustka-W 乌斯特卡-poland|siedlce-X 谢德尔采-poland|nowysacz-X 新松奇-poland|swinoujscie-X 希维诺乌伊希切-poland|jeleniagora-Y 耶列尼亚古拉-poland|zabrze-Z 扎布热-poland|zakopane-Z 扎科帕内-poland|zamosc-Z 扎莫希奇-poland|zawiercie-Z 扎维尔切-poland","elsenborn-A 埃尔森博恩-belgium|herstal-A 埃斯塔勒-belgium|aywaille-A 艾瓦耶-belgium|anderlecht-A 安德莱赫特-belgium|antwerp-A 安特卫普-belgium|oostende-A 奥斯坦德-belgium|oostende-airport-A 奥斯坦德机场-belgium|beauvechain-B 博弗尚-belgium|brasschaat-B 布拉斯哈特-belgium|brussels-B 布鲁塞尔-belgium|brusselsnational-airport-B 布鲁塞尔国家机场-belgium|dendermonde-D 登德尔蒙德-belgium|diepenbeek-D 迪彭贝克-belgium|florennes-F 弗洛雷讷-belgium|florennes-F 夫洛雷恩-belgium|ghent-G 根特-belgium|genk-H 亨克-belgium|koksijde-K 科克赛德-belgium|bierset-L 列日-belgium|liege-L 列日市-belgium|retie-L 里提-belgium|melle-M 麦尔市-belgium|mont-rigi-M 蒙特瑞奇-belgium|namur-N 那慕尔-belgium|semmerzake-S 塞梅尔扎克-belgium|seraing-S 瑟兰-belgium|charleroi-S 沙勒罗瓦-belgium|charleroi-gosselies-S 沙勒罗瓦·戈斯利-belgium|san-nicolas-de-los-arroyos-S 圣尼古拉斯-belgium|vilvoorde-W 维尔福德-belgium|kleine-brogel-X 小布罗赫尔-belgium|chievres-X 谢夫尔-belgium|st-hubert-X 休伯特-belgium|ukkel-Y 于克勒-belgium|zeebrugge-Z 泽布吕赫-belgium","banja-luka-B 巴尼亚卢卡-bosnia-and-herzegovina|bihac-B 比哈奇-bosnia-and-herzegovina|brcko-B 布尔奇科-bosnia-and-herzegovina|bugojno-B 布戈伊诺-bosnia-and-herzegovina|gradacac-G 格拉达卡奇-bosnia-and-herzegovina|kotor-varos-K 科托尔城-bosnia-and-herzegovina|livno-L 利夫诺-bosnia-and-herzegovina|mostar-M 莫斯塔-bosnia-and-herzegovina|mostar-M 莫斯塔尔-bosnia-and-herzegovina|neum-N 涅姆-bosnia-and-herzegovina|sarajevo-S 萨拉热窝-bosnia-and-herzegovina|sanski-most-S 桑斯基莫斯特-bosnia-and-herzegovina|tuzla-T 图兹拉-bosnia-and-herzegovina|jajce-Y 伊策-bosnia-and-herzegovina|zenica-Z 泽尼察-bosnia-and-herzegovina","artern-A 阿尔滕-germany|alfeld-A 阿尔费尔德-germany|arkona-A 阿尔科纳-germany|altenstadt-A 阿尔腾斯塔特-germany|ahaus-A 阿豪斯-germany|erding-A 埃尔丁-germany|erfurt-A 爱尔福特-germany|erlangen-A 埃尔朗根-germany|emden-A 埃姆登-germany|essen-A 埃森-germany|eisenach-A 爱森纳赫-germany|angermuende-A 昂格明德-germany|oberhausen-A 奥伯豪森-germany|oberstdorf-A 奥伯斯多夫-germany|oldenburg-A 奥尔登堡-germany|offenbach-wetterpark-A 奥芬巴赫-germany|offenburg-A 奥芬堡-germany|augsburg-A 奥格斯堡-germany|oschatz-A 奥沙茨-germany|osterfeld-A 奥斯特费尔德-germany|aschaffenburg-A 阿沙芬堡-germany|barthes-B 巴尔特-germany|berlin-B 柏林-germany|berus-B 柏洛斯-germany|bayreuth-B 拜罗伊特-germany|baruth-B 巴鲁特-germany|bamberg-B 班贝格-germany|badkissingen-B 巴特辛根-germany|bergisch-gladbach-B 贝尔吉施格拉德巴赫-germany|belm-B 贝尔姆-germany|bendorf-B 本多夫-germany|potsdam-B 波茨坦-germany|bonn-B 波恩-germany|boltenhagen-B 博尔滕哈根-germany|bottrop-B 博特罗普-germany|bremen-B 不来梅-germany|bremer-haven-B 不来梅港-germany|braunlage-B 布劳恩拉格-germany|brunswick-B 不伦瑞克-germany|braunschweig-B 布伦瑞克-germany|brocken-B 布罗肯山-germany|celle-C 策勒-germany|zugspitze-C 楚格峰-germany|zwickau-C 茨维考-germany|zwiesel-C 茨维瑟尔-germany|dahlem-D 达伦-germany|delmenhorst-D 德尔门霍斯特-germany|dresden-D 德累斯顿-germany|deutsche-bucht-D 德意志湾-germany|diepholz-D 迪普霍尔次-germany|dusseldorf-D 杜塞尔多夫-germany|duisburg-D 杜伊斯堡-germany|oehringen-E 厄林根-germany|frankfurt-am-main-F 法兰克福-germany|fassberg-F 法斯伯格-germany|feldberg-F 费尔德伯格-germany|furstenzell-F 菲尔斯滕采尔-germany|villingen-schwenningen-F 菲林根-施文宁根-germany|fehmarn-F 费马恩-germany|fichtelberg-F 菲希特尔山-germany|hoherodskopf-vogelsberg-F 福格尔斯贝格-germany|freiburg-F 弗赖堡-germany|fritzlar-airport-F 弗里茨拉机场-germany|flensburg-F 弗伦斯堡-germany|freudenstadt-F 弗罗伊登施塔特-germany|feuchtwangen-F 福伊希特旺根-germany|gelsenkirchen-G 盖尔森基兴-germany|geisenheim-G 盖森海姆-germany|goldberg-G 戈德堡-germany|goerlitz-G 格尔利茨-germany|gera-G 格拉-germany|greifswald-G 格赖夫斯瓦尔德-germany|greifswalder-oie-G 格赖夫斯瓦尔德岛-germany|geilenkirchen-G 格林克钦-germany|gluecksburg-G 格吕克斯堡-germany|genthin-G 根廷-germany|goettingen-G 哥廷根-germany|hanau-H 哈瑙-germany|hahn-H 哈恩-germany|harburg-H 哈尔堡-germany|harzgerode-H 哈尔茨格罗德-germany|hagen-H 哈根-germany|heilbronn-H 海尔布隆-germany|halle-H 哈勒-germany|hamm-H 哈姆-germany|hamburg-H 汉堡-germany|hanover-H 汉诺威-germany|helgoland-H 赫尔戈兰-germany|herne-H 黑尔讷-germany|warburg-H 华宝-germany|weissenburg-H 怀森堡-germany|hohn-H 霍恩-germany|hof-H 霍夫-germany|hoyerswerda-H 霍耶斯韦达-germany|gardelegen-J 加德勒根-germany|garmisch-partenkirchen-J 加米施·帕滕基-germany|kiel-J 基尔-germany|chieming-J 基明-germany|giessen-J 吉森-germany|guetersloh-J 居特斯洛-germany|kalkar-K 卡尔卡-germany|chemnitz-K 开姆尼茨-germany|constance-K 康斯坦茨-germany|kassel-K 卡塞尔-germany|koblenz-K 科布伦茨-germany|krefeld-K 克雷费尔德-germany|koeln-bonn-K 科隆·波恩-germany|kempten-K 肯普滕-germany|cottbus-K 科特布斯-germany|cuxhaven-K 库克斯港-germany|lahr-L 拉尔-germany|laage-airport-L 拉格机场-germany|rheine-bentlage-L 赖讷-germany|leipzig-L 莱比锡-germany|leipzig-L 莱比锡城-germany|leck-L 莱克-germany|lechfeld-L 莱西菲尔德-germany|rheinstetten-L 莱茵斯泰腾-germany|langen-L 兰金-germany|landsberg-L 兰兹伯格-germany|laupheim-L 劳普海姆-germany|regensburg-L 雷根斯堡-germany|recklinghausen-L 雷克林豪森-germany|remscheid-L 雷姆沙伊德-germany|leverkusen-L 勒沃库森-germany|lindenberg-L 林登贝格-germany|lingen-L 林根-germany|ludwigshafen-am-rhein-L 路德维希港-germany|rostock-L 罗斯托克-germany|roth-L 罗特-germany|leutkirch-L 洛伊特基希-germany|lubeck-L 吕贝克-germany|luedenscheid-L 吕登沙伊德-germany|luechow-L 吕肖-germany|magdeburg-M 马格德堡-germany|meiningen-M 迈宁根-germany|marienberg-M 玛利恩城堡-germany|mannheim-M 曼海姆-germany|meppen-M 梅佩恩-germany|mainz-M 美因茨-germany|monchengladbach-M 门兴格拉德巴赫-germany|muehldorf-M 米尔多夫-germany|muehlacker-M 米赫拉克尔-germany|mutitz-M 米里茨-germany|muenster-M 明斯特-germany|michelstadt-vielbrunn-M 米歇尔城-germany|munich-M 慕尼黑-germany|nuerburg-N 纽伯格-germany|nuernberg-N 纽伦堡-germany|nordholz-airport-N 诺德霍尔兹机场-germany|norderney-N 诺德奈-germany|neuburg-donau-N 诺伊堡·多瑙河-germany|neuss-N 诺伊斯-germany|paderborn-P 帕德博恩-germany|buechel-airport-P 皮歇尔机场-germany|pforzheim-P 普福尔茨海姆-germany|plauen-P 普劳恩-germany|putbus-P 普特布斯-germany|kuemmersbruck-Q 屈梅斯布鲁克-germany|saarbruecken-ensheim-S 萨尔布吕肯-germany|salzgitter-S 萨尔茨吉特-germany|schleiz-S 施莱茨-germany|schleswig-S 石勒苏益格-germany|stoetten-S 施特滕-germany|straubing-S 施特劳宾-germany|schwerin-S 什未林-germany|schweinfurt-S 施韦因富特-germany|klippeneck-S 施文宁根(克里佩内克)-germany|seehausen-S 斯豪森-germany|stuttgart-S 斯图加特-germany|soltau-S 索尔陶-germany|solingen-S 索林根-germany|taunus-T 陶努斯-germany|friedrichshafen-T 腓特烈港-germany|trier-T 特里尔-germany|trier-petrisberg-T 特里尔匹兹堡-germany|tholey-T 托莱-germany|waren-W 瓦伦-germany|wasserkuppe-W 瓦瑟山-germany|witten-W 维滕-germany|wittenberg-W 维滕贝格-germany|weiden-W 魏登-germany|weihenstephan-W 威恩施蒂凡-germany|werl-W 韦尔-germany|wuerzburg-W 维尔茨堡-germany|wilhelmshaven-W 威廉港-germany|wilhelms-haven-airport-W 威廉港机场-germany|wernigerode-W 韦尼格罗德-germany|wiesbaden-W 威斯巴登-germany|wittmund-haven-W 维特蒙德港-germany|wendelstein-W 温德斯泰因-germany|wunstorf-W 文斯托夫-germany|ulm-W 乌尔姆-germany|wuppertal-W 伍珀塔尔-germany|hildesheim-X 希尔德斯海姆-germany|siegen-X 锡根-germany|neuruppin-X 新鲁平-germany|sylt-X 叙尔特岛-germany|aachen-Y 亚琛-germany|alexanderplatz-Y 亚历山大广场-germany|jever-Y 耶弗尔-germany|itzehoe-Y 伊策霍-germany|ingolstadt-Y 因戈尔施塔特-germany|ingolstadt-airport-Y 因戈尔施塔特机场-germany","abed-A 阿拜德-denmark|aarhus-airport-A 阿尔胡斯机场-denmark|aarslev-A 阿尔斯列夫-denmark|esbjerg-A 埃斯比约-denmark|abenra-A 奥本罗-denmark|aalborg-A 奥尔堡-denmark|augustenborg-A 奥古斯滕堡-denmark|arhus-A 奥胡斯-denmark|osterild-A 奥斯特利尔德-denmark|birkerod-B 比克勒-denmark|billund-B 比隆-denmark|billund-airport-B 比隆德机场-denmark|bramming-B 布拉明-denmark|filskov-F 菲尔斯考-denmark|frederikshavn-F 弗雷德里克斯-denmark|fredericia-F 弗雷德里西亚-denmark|gedser-G 盖瑟-denmark|copenhagen-G 哥本哈根-denmark|hanstholm-H 汉斯特霍尔姆-denmark|helsingor-H 赫尔辛格-denmark|hornsrev-a-H 荷斯韦夫-A-denmark|hornsrev-b-H 荷斯韦夫-B-denmark|holstebro-H 霍尔斯特布罗-denmark|kalundborg-K 凯隆堡-denmark|randers-L 兰德斯-denmark|roskilde-L 罗斯基勒-denmark|nykobing-N 尼克宾-denmark|odenselufthavn-O 欧登赛-denmark|thisted-Q 齐斯泰兹-denmark|thistedlufthavn-Q 齐斯泰兹机场-denmark|sonderborg-S 森纳堡-denmark|skive-S 斯基弗-denmark|skagen-S 斯卡恩-denmark|skanderborg-S 斯坎讷堡-denmark|skrydstrup-S 斯克吕斯楚普-denmark|stauninglufthavn-S 斯陶宁机场-denmark|svendborg-S 斯文堡-denmark|torshavn-T 托尔斯港-denmark|varde-W 瓦尔德-denmark|veslos-W 韦斯勒斯-denmark|hillerod-X 希勒罗德-denmark","abakan-A 阿巴坎-russia|adler-A 阿德勒-russia|armavir-A 阿尔马维尔-russia|arzamas-A 阿尔扎马斯-russia|efremov-A 埃夫雷莫夫-russia|elista-A 埃利斯塔-russia|emeck-A 艾麦克-russia|anapa-A 阿纳帕-russia|anna-A 安娜-russia|orel-A 奥廖尔-russia|orenburg-A 奥伦堡-russia|onega-A 奥涅加-russia|ozerki-A 奥则基-russia|okulovka-A 奥_洛夫卡-russia|apatity-A 阿帕季特-russia|atkarsk-A 阿特卡尔斯克-russia|barnaul-B 巴尔瑙尔-russia|balashov-B 巴拉绍夫-russia|borisoglebsk-B 鲍里索格列布斯克-russia|penza-B 奔萨-russia|petrovsk-B 彼得罗夫斯克-russia|petrozavodsk-B 彼得罗扎沃茨克-russia|belgorod-B 别尔哥罗德-russia|belozersk-B 别洛焦尔斯克-russia|bologoe-B 博洛戈耶-russia|budennovsk-B 布登诺夫斯克-russia|bobruisk-B 布鲁伊斯克-russia|brjansk-B 布斯克-russia|chelyabinsk-C 车里雅宾斯克-russia|chita-C 赤塔-russia|demjansk-D 德米杨斯克-russia|dno-D 德诺-russia|rostov-na-donu-D 顿河畔罗斯托夫-russia|omsk-E 鄂木斯克-russia|engozero-E 恩戈泽罗-russia|volgograd-F 伏尔加格勒-russia|vladivostok-F 符拉迪沃斯托克-russia|vladikavkaz-F 弗拉基高加索-russia|vladimir-F 弗拉基米尔-russia|gdov-G 格多夫-russia|georgievsk-G 格鲁吉夫斯克-russia|gorodovikovsk-G 戈罗多维科夫斯克-russia|groznyj-G 格罗兹尼-russia|gulbene-G 古尔贝内-russia|gudermes-G 古杰尔梅斯-russia|habarovsk-H 哈巴罗夫斯克-russia|khabarovsk-H 哈巴罗夫斯克(伯力)-russia|karabulak-H 哈拉布拉克-russia|holm-H 霍尔姆-russia|gigant-J 贾甘特-russia|gagarin-J 加加林-russia|kaliningrad-J 加里宁格勒-russia|galic-J 加利奇-russia|teberda-J 捷别尔达-russia|kirsanov-J 基尔萨诺夫-russia|gelendzik-J 基联恩金克-russia|kirishi-J 基里希-russia|kirov-J 基洛夫-russia|kingisepp-J 金吉谢普-russia|kihnu-J 基努-russia|kasira-K 凯西琳-russia|kalevala-K 卡勒瓦拉-russia|kaluga-K 卡卢加-russia|petropavlovsk-kamchatskiy-K 堪察加彼得巴甫洛夫斯克-russia|kandalaksha-K 坎达拉克沙-russia|konstantinovsk-K 康斯坦丁诺夫斯克-russia|kazan-K 喀山-russia|kasin-K 卡西恩-russia|kovda-K 科夫达-russia|krasnodar-K 克拉斯诺达尔-russia|klin-K 克林-russia|kolomna-K 科洛姆纳-russia|kropotkin-K 克鲁泡特金-russia|kemerovo-K 克麦罗沃-russia|kostroma-K 科斯特罗马-russia|kotel-K 科泰尔-russia|kotlas-K 科特拉斯-russia|kondopoga-K 孔多波加-russia|kolka-K 寇尔卡-russia|kurgan-K 库尔干-russia|kursk-K 库尔斯克-russia|kuressaare-roomassaare-K 库雷萨雷-russia|elan-L 怡莱-russia|rybinsk-L 雷宾斯克-russia|livny-L 利夫内-russia|liman-L 里曼-russia|lipetsk-L 利佩茨克-russia|liski-L 利斯基-russia|rostov-L 罗斯托夫-russia|lovozero-L 洛沃泽罗-russia|louhi-L 路希-russia|maykop-M 迈科普-russia|magadan-M 马加丹-russia|mariupol-M 马里乌波尔-russia|medvezegorsk-M 梅德韦日耶戈尔斯克-russia|melitopol-M 梅利托波尔-russia|mihajlov-M 米赫路夫-russia|murmansk-M 摩尔曼斯克-russia|morozovsk-M 莫罗佐夫斯克-russia|moscow-M 莫斯科-russia|mozajsk-M 莫扎伊斯克-russia|mozdok-M 莫兹多克-russia|murom-M 穆罗姆-russia|naro-fominsk-N 纳罗福明斯克-russia|yuzhno-sakhalinsk-N 南萨哈林斯克-russia|nevinnomyssk-N 涅温诺梅斯克-russia|novgorod-N 诺夫哥罗德-russia|nolinsk-N 诺林斯克-russia|pavelets-P 帕韦列茨-russia|pinega-P 皮涅加-russia|proletarskaya-P 普洛列塔尔斯卡亚-russia|pskov-P 普斯科夫-russia|saransk-S 萨兰斯克-russia|saratov-S 萨拉托夫-russia|salekhard-S 萨列哈尔德-russia|samara-S 萨马拉-russia|sasovo-S 萨索沃-russia|savelovo-S 萨维奥洛夫-russia|syktyvkar-S 瑟克特夫卡尔-russia|saint-petersburg-S 圣彼得堡-russia|shenkursk-S 申库尔斯克-russia|slutsk-S 斯卢茨克-russia|smolensk-S 斯摩棱斯克-russia|stavropol-S 斯塔夫罗波尔-russia|staritsa-S 斯塔里察-russia|svetlograd-S 斯韦特洛格勒-russia|sura-S 苏拉-russia|sortavala-S 索尔塔瓦拉-russia|sosnovo-S 索斯诺伏奥-russia|suja-S 苏亚-russia|taganrog-T 塔甘罗格-russia|tambov-T 坦波夫-russia|trubchevsk-T 特鲁布切夫斯克-russia|temnikov-T 特姆尼科夫-russia|tver-T 特维尔-russia|teriberka-T 提瑞博卡-russia|tuapse-T 图阿普谢-russia|tomsk-T 托木斯克-russia|valga-W 瓦尔加-russia|valaam-W 瓦拉姆-russia|vyborg-W 维堡-russia|viljandi-W 维尔扬迪-russia|vytegra-W 维捷格拉-russia|vyksa-W 维克萨-russia|vetluga-W 韦特卢加-russia|voru-W 沃鲁-russia|vologda-W 沃洛格达-russia|volokolamsk-W 沃洛科拉姆斯克-russia|voronez-W 沃罗涅日-russia|volosovo-W 沃洛索沃-russia|ufa-W 乌法-russia|ulyanovsk-W 乌里扬诺夫斯克-russia|nizhniy-novgorod-X 下诺夫哥罗德州-russia|serpuhov-X 谢尔普霍夫-russia|semenov-X 谢苗诺夫-russia|novorossijsk-X 新罗西斯克-russia|novosibirsk-X 新西伯利亚-russia|yakutsk-Y 雅库茨克-russia|aleksandrov-Y 亚历山德罗夫-russia|aluksne-Y 亚鲁克斯尼-russia|azov-Y 亚速-russia|yekaterinburg-Y 叶卡捷琳堡-russia|irkutsk-Y 伊尔库茨克-russia|ivanovo-Y 伊凡诺沃-russia|indiga-Y 印迪加-russia|ershov-Y 尹尔肖夫-russia|incy-Y 印塞-russia|izhevsk-Y 伊热夫斯克-russia|ivanovo-Y 伊万诺沃-russia|umba-Y 尤巴-russia","abbeville-A 阿比维尔-france|albi-A 阿尔比-france|evreux-A 埃夫勒-france|alencon-A 阿朗松-france|amberieu-A 昂贝略-france|embrun-A 昂布伦-france|antibes-A 昂蒂布-france|angers-A 昂热-france|orleans-A 奥尔良-france|agen-A 阿让-france|argenteuil-A 阿让特伊-france|avignon-A 阿维尼昂-france|avord-A 阿沃德-france|annecy-A 阿讷西-france|ajaccio-A 阿雅克肖-france|paris-B 巴黎-france|paris-montsouris-B 巴黎蒙苏里-france|bastia-B 巴斯蒂亚-france|bergerac-B 贝尔热拉克-france|beziers-B 贝济耶-france|besancon-B 贝桑松-france|biscarosse-B 比斯加奥斯-france|bordeaux-B 波尔多-france|bourges-B 布尔日-france|brest-B 布列斯特-france|brive-B 布里夫-france|brignogan-B 布里诺冈-france|boulogne-B 布伦-france|boulogne-billancourt-B 布洛涅-比扬古-france|blois-B 布洛瓦-france|chateaudun-C 查特顿-france|dax-D 达克斯-france|drancy-D 德朗西-france|dinard-D 迪纳尔-france|dijon-D 第戎-france|dieppe-D 迪耶普-france|dunkerque-D 敦刻尔克-france|figari-F 菲加里-france|grenoble-G 格勒诺布尔-france|gourdon-G 古尔东-france|calais-J 加来-france|caen-K 卡昂-france|carcassonne-K 卡尔卡松-france|calvi-K 卡尔维-france|quimper-K 坎佩尔-france|carpentras-K 卡庞特拉-france|clermont-ferrand-K 克莱蒙费朗-france|creil-K 克里尔-france|luxeuil-K 克瑟伊莱班-france|langres-L 朗格勒-france|lannion-L 拉尼永-france|reims-L 兰斯-france|le-havre-L 勒阿弗尔-france|lebourget-L 勒布尔热-france|rennes-L 雷恩-france|le-mans-L 勒芒-france|lepuy-velay-L 勒皮-france|letouquet-L 勒图凯-france|levallois-perret-L 勒瓦卢瓦-佩雷-france|lyon-L 里昂-france|lille-lesquin-L 里尔·莱斯坎-france|limoges-L 利摩日-france|rouen-L 鲁昂-france|lorient-L 洛里昂-france|romorantin-L 罗莫朗坦-france|rueil-malmaison-L 吕埃尔-马尔迈松-france|leucate-L 吕卡特港-france|champigny-sur-marne-M 马恩河畔尚皮尼-france|macon-M 马孔-france|marignane-M 马里尼亚讷-france|marseille-M 马赛-france|melun-M 梅伦-france|metz-M 梅斯-france|mende-M 门德-france|montpellier-M 蒙彼利埃-france|mont-marsan-M 蒙德马桑-france|montelimar-M 蒙特利马尔-france|montauban-M 蒙托邦-france|mulhouse-M 米卢斯-france|millau-M 米约-france|cannes-N 戛纳-france|nanterre-N 南泰尔-france|nantes-N 南特-france|nancy-N 南锡-france|niort-N 尼奥尔-france|nimes-N 尼姆-france|nice-N 尼斯-france|aurillac-O 欧里亚克-france|aulnay-sous-bois-O 欧奈-france|auxerre-O 欧塞尔-france|auch-O 欧什-france|perpignan-P 佩皮尼昂-france|aix-en-provence-P 普罗旺斯地区艾克斯-france|salondeprovence-P 普罗旺斯地区萨隆-france|poitiers-P 普瓦捷-france|sete-S 塞蒂-france|vitry-sur-seine-S 塞纳河畔维特里-france|cergy-S 塞日-france|charleville-mezieres-S 沙勒维尔-梅济耶尔-france|chartres-S 沙特尔-france|st-girons-S 圣日龙-france|strasbourg-S 斯特拉斯堡-france|chalon-sur-saone-S 索恩河畔沙隆-france|solenzara-S 索兰扎拉-france|tarbes-T 塔布-france|trappes-T 特拉佩-france|troyes-T 特鲁瓦-france|troyes-T 特耶斯-france|tours-T 图尔-france|tourcoing-T 图尔宽-france|toulon-T 土伦-france|toulouse-T 图卢兹-france|villeurbanne-W 维勒班-france|amiens-Y 亚眠-france|hyeres-Y 耶尔-france|istres-Y 伊斯特-france","ahtari-A 艾赫泰里-finland|espoo-A 埃斯波-finland|oravainen-A 奥拉瓦伊内恩-finland|oulu-A 奥卢-finland|porvoo-B 波尔沃-finland|pori-B 波里-finland|hailuoto-H 海卢奥托-finland|helsinki-H 赫尔辛基-finland|kilpisjarvi-J 基尔皮斯耶尔维-finland|kerava-K 凯拉瓦-finland|kevo-K 凯沃-finland|kalajoki-K 卡拉河-finland|ulkokalla-K 卡拉河乌尔科卡拉岛-finland|kauhava-K 卡乌哈瓦-finland|kajaani-K 卡亚尼-finland|valassaaret-K 科什霍尔姆瓦尔斯群岛-finland|kuopio-K 库奥皮奥-finland|kuusamo-K 库萨莫-finland|kuusankoski-K 库桑科斯基-finland|raahe-L 拉赫-finland|lahti-L 拉赫蒂-finland|laihia-L 莱希亚-finland|rankki-L 兰基-finland|lappeenranta-L 拉彭兰塔-finland|rovaniemi-L 罗瓦涅米-finland|russaro-L 鲁萨洛-finland|mynamaki-M 米奈迈基-finland|muonio-M 穆奥尼奥-finland|nyhamn-N 尼汉姆-finland|niinisalo-N 尼尼萨洛-finland|nivala-N 尼瓦拉-finland|pello-P 佩洛-finland|seinajoki-S 塞伊奈约基-finland|savonlinna-S 萨翁林纳-finland|ylivieska-S 上维耶斯卡-finland|sodankyla-S 索丹屈莱-finland|tammisaari-T 塔米萨阿里-finland|tampere-pirkkala-T 坦佩雷·皮尔卡拉-finland|turku-T 图尔库-finland|vantaa-W 万塔-finland|vaasa-W 瓦萨-finland|vaasa-airport-W 瓦萨机场-finland|viitasaari-W 维塔萨里-finland|utti-W 乌堤-finland|hyvinkaa-X 许温凯-finland|ilomantsi-Y 伊洛曼齐-finland|imatra-Y 伊马特拉-finland|ivalo-Y 伊瓦洛-finland|joensuu-Y 约恩苏-finland|jokioinen-Y 约基奥伊宁-finland|jokioinen-Y 约基奥因内恩-finland|jomala-Y 约马拉-finland|uto-Y 于特-finland|jyvaskyla-Y 于韦斯屈莱-finland","akinatsiait-A 阿基奈特赛特-greenland|daneborg-D 达讷堡-greenland|godthaab-G 戈特霍布-greenland|humboldt-H 洪堡特-greenland|qeqertarsuaq-heliport-K 凯凯塔苏瓦克岛直升飞机场-greenland|qaqortoq-K 卡科尔托克-greenland|qaqortoq-heliport-K 卡科尔托克直升飞机场-greenland|kangerlussuaq-K 康克鲁斯瓦克-greenland|qasigiannguit-heliport-K 卡西江吉特直升飞机场-greenland|narsarsuaq-N 纳萨尔苏瓦克-greenland|narsaq-heliport-N 纳萨克直升飞机场-greenland|swiss-camp-R 瑞士训练营-greenland|maniitsoq-S 苏克托彭-greenland|tasiilaq-T 塔西拉克-greenland|jakobshavn-Y 雅各布沙温-greenland|aasiaat-Y 亚西亚特-greenland|ittoqqortoormiit-Y 伊托考托米特-greenland|qaqortoq-Y 尤利安娜霍布-greenland","akinatsiait-A 阿基奈特赛特-greenland|daneborg-D 达讷堡-greenland|godthaab-G 戈特霍布-greenland|humboldt-H 洪堡特-greenland|qeqertarsuaq-heliport-K 凯凯塔苏瓦克岛直升飞机场-greenland|qaqortoq-K 卡科尔托克-greenland|qaqortoq-heliport-K 卡科尔托克直升飞机场-greenland|kangerlussuaq-K 康克鲁斯瓦克-greenland|qasigiannguit-heliport-K 卡西江吉特直升飞机场-greenland|narsarsuaq-N 纳萨尔苏瓦克-greenland|narsaq-heliport-N 纳萨克直升飞机场-greenland|swiss-camp-R 瑞士训练营-greenland|maniitsoq-S 苏克托彭-greenland|tasiilaq-T 塔西拉克-greenland|jakobshavn-Y 雅各布沙温-greenland|aasiaat-Y 亚西亚特-greenland|ittoqqortoormiit-Y 伊托考托米特-greenland|qaqortoq-Y 尤利安娜霍布-greenland","eindhovenap-A 艾恩德霍芬-netherlands|emmeloord-A 埃默洛尔德-netherlands|amsterdam-A 阿姆斯特丹-netherlands|drachten-D 德拉赫滕-netherlands|tilburg-D 蒂尔堡-netherlands|deelen-D 迪莱-netherlands|groningenapeelde-D 蒂纳洛德伦特-netherlands|dordrecht-D 多德雷赫特-netherlands|valkenburg-aws-F 法肯堡航空气象处-netherlands|vlaardingen-F 弗拉尔丁恩-netherlands|vlieland-F 弗利兰岛-netherlands|groningen-G 格罗宁根-netherlands|hoogeveen-H 霍赫芬-netherlands|hoogeveen-aws-H 霍赫芬航空气象处-netherlands|hook-of-holland-H 霍克范荷兰-netherlands|leiden-L 莱顿-netherlands|lelystad-L 莱利斯塔德-netherlands|rotterdam-L 鹿特丹-netherlands|leeuwarden-L 吕伐登-netherlands|maastricht-M 马斯特里赫特-netherlands|stadskanaal-S 斯塔茨卡纳尔-netherlands|wassenaar-W 瓦森纳-netherlands|westdorpe-aws-W 韦斯特多玻航空气象处-netherlands|volkel-W 沃尔凯尔-netherlands|hilversum-X 希尔弗苏姆-netherlands|nieuw-milligen-X 新米利根-netherlands","podgorica-B 波德戈里察-montenegro|tivat-D 蒂瓦特-montenegro|ulcinj-W 乌尔齐尼-montenegro","olomouc-A 奥洛穆茨-czech-republic|plzen-B 比尔森-czech-republic|brno-B 布尔诺-czech-republic|prague-B 布拉格-czech-republic|breclav-B 布热茨拉夫-czech-republic|ostrava-E 俄斯特拉发-czech-republic|usti-nad-orlici-H 河畔乌斯季奥尔利-czech-republic|holesov-H 霍莱绍夫-czech-republic|chomutov-H 霍穆托夫-czech-republic|cesky-tesin-J 捷克捷欣-czech-republic|karlovy-vary-K 卡罗维发利-czech-republic|karvina-K 卡维纳-czech-republic|klatovy-K 克拉托维-czech-republic|kocelovice-K 科切罗维奇-czech-republic|kostelni-myslova-K 科斯泰尔尼-米斯洛瓦-czech-republic|usti-nad-labem-L 拉贝河畔乌斯季-czech-republic|liberec-L 利贝雷茨-czech-republic|pardubice-P 帕尔杜比采-czech-republic|prostejov-P 普罗斯捷约夫-czech-republic|primda-P 普日姆达-czech-republic|cervena-Q 切尔韦纳-czech-republic|churanov-Q 丘兰诺夫-czech-republic|sumperk-S 顺佩尔克-czech-republic|strakonice-S 斯特拉科尼采-czech-republic|trutnov-T 特鲁特诺夫-czech-republic|trebic-T 特热比奇-czech-republic|turnov-T 图尔诺夫-czech-republic|jesenik-Y 耶塞尼克-czech-republic|jindrichuv-hradec-Y 因德日赫城堡-czech-republic|jicin-Y 伊钦-czech-republic","olomouc-A 奥洛穆茨-czech-republic|plzen-B 比尔森-czech-republic|brno-B 布尔诺-czech-republic|prague-B 布拉格-czech-republic|breclav-B 布热茨拉夫-czech-republic|ostrava-E 俄斯特拉发-czech-republic|usti-nad-orlici-H 河畔乌斯季奥尔利-czech-republic|holesov-H 霍莱绍夫-czech-republic|chomutov-H 霍穆托夫-czech-republic|cesky-tesin-J 捷克捷欣-czech-republic|karlovy-vary-K 卡罗维发利-czech-republic|karvina-K 卡维纳-czech-republic|klatovy-K 克拉托维-czech-republic|kocelovice-K 科切罗维奇-czech-republic|kostelni-myslova-K 科斯泰尔尼-米斯洛瓦-czech-republic|usti-nad-labem-L 拉贝河畔乌斯季-czech-republic|liberec-L 利贝雷茨-czech-republic|pardubice-P 帕尔杜比采-czech-republic|prostejov-P 普罗斯捷约夫-czech-republic|primda-P 普日姆达-czech-republic|cervena-Q 切尔韦纳-czech-republic|churanov-Q 丘兰诺夫-czech-republic|sumperk-S 顺佩尔克-czech-republic|strakonice-S 斯特拉科尼采-czech-republic|trutnov-T 特鲁特诺夫-czech-republic|trebic-T 特热比奇-czech-republic|turnov-T 图尔诺夫-czech-republic|jesenik-Y 耶塞尼克-czech-republic|jindrichuv-hradec-Y 因德日赫城堡-czech-republic|jicin-Y 伊钦-czech-republic","namestnadoslavou-A 奥斯拉瓦河畔纳梅什季-czechoslovakia|poprad-tatry-B 波普拉德·塔特拉山-czechoslovakia|brno-turany-B 布尔诺机场-czechoslovakia|praha-kbely-B 布拉格科贝里-czechoslovakia|dudince-D 杜丁西-czechoslovakia|dukovany-D 杜库凡尼-czechoslovakia|hurbanovo-H 胡尔巴诺沃-czechoslovakia|luka-L 卢卡-czechoslovakia|milesovka-M 迈尔索夫卡-czechoslovakia|mochovce-M 莫霍夫采-czechoslovakia|presov-P 普雷绍夫-czechoslovakia|prerov-P 普热罗夫-czechoslovakia|pribyslav-P 普日比斯拉夫-czechoslovakia|caslav-Q 恰斯拉夫-czechoslovakia|cheb-Q 切布-czechoslovakia|churanov-Q 丘拉诺夫-czechoslovakia|zilina-hricov-R 日利纳-czechoslovakia|sliac-S 斯历亚科-czechoslovakia|temelin-T 泰梅林-czechoslovakia","osijek-A 奥西耶克-croatia|biograd-B 比奥格勒-croatia|bjelovar-B 别洛瓦尔-croatia|cres-C 茨雷斯-croatia|daruvar-D 达鲁瓦尔-croatia|dubrovnik-D 杜布罗夫尼克-croatia|varazdin-F 法拉兹丁-croatia|gradiste-G 格拉迪什泰-croatia|gospic-G 戈斯皮奇-croatia|hvar-H 赫瓦尔岛-croatia|korcula-K 科尔丘拉-croatia|krapina-K 克拉皮纳-croatia|krizevci-K 克里扎维奇-croatia|knin-K 克宁-croatia|rab-L 拉布岛-croatia|lastovo-L 拉斯托伏-croatia|rijeka-L 里耶卡-croatia|rovinj-L 罗维尼-croatia|split-marjan-M 马尔让山-croatia|makarska-M 马卡斯卡-croatia|mali-ston-M 马里通-croatia|komiza-M 米扎-croatia|mali-losinj-M 木洛希尼-croatia|pazin-P 帕津-croatia|ploce-P 普洛切-croatia|zagreb-S 萨格勒布-croatia|senj-S 塞尼-croatia|gornji-humac-S 上胡马克-croatia|slavonski-brod-S 斯拉沃尼亚布罗德-croatia|split-S 斯普利特-croatia|sibenik-X 希贝尼克-croatia|sisak-X 锡萨克-croatia","adjud-A 阿德茹德-romania|arad-A 阿拉德-romania|oradea-A 奥拉迪亚-romania|bacau-B 巴克乌-romania|petrosani-B 彼得罗沙尼-romania|bechet-B 比切特-romania|bistrita-B 比斯特里察-romania|barlad-B 伯尔拉德-romania|botosani-B 博托沙尼-romania|bucuresti-B 布加勒斯特-romania|bucurestibaneasa-B 布加勒斯特伯尼亚萨-romania|brasov-B 布拉索夫-romania|braila-B 布勒伊拉-romania|predeal-B 布列地尔-romania|buzau-B 布泽乌-romania|deva-D 德瓦-romania|timisoara-D 蒂米什瓦拉-romania|fagaras-F 法加拉斯-romania|focsani-F 福克沙尼-romania|gheorgheni-G 格奥尔基尼-romania|harsova-H 哈索瓦-romania|huedin-H 胡埃丁-romania|galati-J 加拉茨-romania|jimbolia-J 金波耶-romania|el-calafate-K 卡拉法特-romania|caransebes-K 卡兰赛贝什-romania|caransebes-K 卡兰塞贝什-romania|constanta-K 康斯坦察-romania|campina-K 坎皮纳-romania|craiova-K 克拉约瓦-romania|calarasi-K 克勒拉希-romania|cluj-napoca-K 克卢日-纳波卡-romania|cluj-napoca-K 克卢日·纳波卡-romania|radauti-L 勒德乌茨-romania|resita-L 雷希察-romania|ramnicu-valcea-L 勒姆尼库沃尔恰-romania|lugoj-L 卢戈日-romania|roman-L 罗曼-romania|rosiori-de-vede-L 洛西奥里-德维德-romania|mahmudia-M 马哈茂迪亚-romania|medgidia-M 麦德基迪亚-romania|mangalia-M 曼加利亚-romania|miercureaciuc-M 米耶尔库雷亚丘克-romania|parang-P 帕朗-romania|penteleu-P 朋特琉-romania|pitesti-P 皮特什蒂-romania|piatraneamt-P 皮亚特拉-romania|ploiesti-P 普洛耶什蒂-romania|viile-satu-mare-S 萨图马雷-romania|sulina-S 舒利纳-romania|slatina-S 斯拉蒂纳-romania|slobozia-S 斯洛博齐亚-romania|suceava-S 苏恰瓦-romania|talmaciu-T 塔尔马齐乌-romania|targoviste-T 塔高维斯塔-romania|titu-T 提图-romania|turda-T 图尔达-romania|tulcea-T 图尔恰-romania|vaslui-W 瓦斯卢伊-romania|urziceni-W 乌尔济切尼-romania|sibiu-X 锡比乌-romania|sighetu-marmatiei-X 西格赫图-马尔马蒂耶-romania|siria-X 锡里亚-romania|sinaia-X 锡纳亚-romania|moldova-veche-X 新摩尔多瓦-romania|alexandria-Y 亚历山大港-romania|jassy-Y 雅西-romania|zalau-Z 扎勒乌-romania|giurgiu-Z 朱尔朱-romania","echternach-A 埃希特纳赫-luxembourg|clervaux-K 克莱沃-luxembourg|luxembourg-L 卢森堡-luxembourg","kaunas-K 考纳斯-lithuania|klaipeda-K 克莱佩达-lithuania|klaipeda-K 克莱佩达港-lithuania|nida-N 尼达-lithuania|palanga-P 帕兰加-lithuania|panevezys-P 帕涅韦日斯-lithuania|verhnedvinsk-S 上第文斯基-lithuania|silute-S 斯路特-lithuania|telsiai-T 特尔希艾-lithuania|vilnius-W 维尔纽斯-lithuania|ukmerge-W 乌克梅尔盖-lithuania|siauliai-X 希奥利艾-lithuania|utena-Y 佑天兰-lithuania","ogre-A 奥格雷-latvia|bauska-B 包斯卡-latvia|dobele-D 多贝莱-latvia|rezekne-L 雷泽克内-latvia|riga-L 里加-latvia|liepaja-L 利耶帕亚-latvia|madona-M 马多纳-latvia|saldus-S 萨尔杜斯-latvia|daugavpils-T 陶格夫匹尔斯-latvia|valmiera-W 瓦尔米耶拉-latvia|ventspils-W 文茨皮尔斯-latvia|jelgava-Y 叶尔加瓦-latvia","vaduz-W 瓦杜兹-principality-of-liechtenstein","balti-B 巴尔蒂-moldova|tiraspol-D 蒂拉斯波尔-moldova|dubasari-D 杜博萨雷-moldova|falesti-F 弗列什蒂-moldova|chisinau-J 基希纳乌-moldova|chisinau-J 基希讷乌-moldova|cahul-K 卡胡尔-moldova|mikolaiv-M 麦克莱-moldova|nikopol-N 尼科波尔-moldova|straseni-S 斯特拉瑟尼-moldova|ribnita-Y 伊斯克拉斯塔尔-moldova","ohrid-A 奥赫里德-macedonia|ohrid-aerodrome-A 奥赫里德机场-macedonia|berovo-B 贝罗沃-macedonia|bitola-B 比托拉-macedonia|debar-D 德巴尔-macedonia|demir-kapija-D 德米尔卡皮亚-macedonia|gevgelija-G 盖夫盖利亚-macedonia|gevgelija-G 格夫戈里亚-macedonia|gostivar-G 戈斯蒂瓦尔-macedonia|stip-G 革新-macedonia|kavadarci-K 卡瓦达尔齐-macedonia|kriva-palanka-K 克里瓦河帕兰卡-macedonia|krusevo-K 克鲁塞沃-macedonia|lazaropole-L 拉扎罗波勒-macedonia|mavrovo-M 马夫罗沃-macedonia|prilep-P 普里莱普-macedonia|pretor-P 普瑞特-macedonia|skopje-S 斯科普里-macedonia|strumica-S 斯图米加-macedonia|tetovo-T 泰托沃-macedonia|veles-W 韦莱斯-macedonia","alta-airport-A 阿尔塔机场-norway|edgeoya-A 埃季岛-norway|evenes-A 埃沃内斯-norway|aurskog-A 艾于什库格-norway|oslo-A 奥斯陆-norway|oslo-gardermoen-A 奥斯陆·加勒穆恩-norway|bardufoss-B 巴尔杜福斯-norway|banak-B 班纳克-norway|bergen-B 卑尔根-norway|batsfjord-B 博茨菲尤尔-norway|porsgrunn-B 波什格伦-norway|bronnoysund-B 布伦讷于松-norway|drammen-D 德拉门-norway|fagernes-F 法格内斯-norway|fredrikstad-F 费德列斯达-norway|fedje-F 费迪厄-norway|filefjell-F 菲勒弗捷尔-norway|floro-F 弗洛罗-norway|harstad-H 哈尔斯塔-norway|haugesund-H 海于格松-norway|hamar-H 哈马尔-norway|hammerfest-H 哈默弗斯特-norway|herjangen-H 赫尔简根-norway|honefoss-H 赫讷福斯-norway|honefoss-H 侯尼霍斯-norway|hornsund-H 霍恩松-norway|kautokeino-K 凯于图凯努-norway|karasjok-K 卡拉绍克-norway|kragero-K 克拉格勒-norway|krakenes-K 克罗克内斯-norway|kongsvinger-K 孔斯温厄尔-norway|larvik-L 拉尔维克-norway|levanger-L 莱旺厄尔-norway|rena-L 雷纳-norway|roros-L 勒罗斯-norway|lillehammer-L 利勒哈默尔-norway|lillesand-L 利勒桑-norway|rjukan-L 留坎-norway|myken-M 米克-norway|mosjoen-M 莫斯乔恩-norway|namsos-N 纳姆索斯-norway|norheimsund-N 诺尔哈依姆森-norway|skrovalh-N 诺尔兰郡-norway|notodden-N 诺托登-norway|obrestad-O 欧布瑞丝塔德-norway|sauda-S 赛于达-norway|sandefjord-S 桑讷菲尤尔-norway|sorkjosen-S 瑟休森-norway|tonsberg-S 滕斯贝格-norway|skrova-S 斯克勒瓦-norway|stjordalshalsen-S 斯切达尔沙尔森-norway|stavanger-S 斯塔万格-norway|stryn-S 斯特林-norway|sogndal-S 松达尔-norway|sortland-S 苏特兰-norway|tafjord-T 塔菲尤尔-norway|trondheim-T 特隆赫姆-norway|tromso-T 特罗姆瑟-norway|tynset-T 廷瑟-norway|verdal-reppe-W 瓦达尔瑞普-norway|vangsnes-W 旺斯内斯-norway|verdalsora-W 韦尔达尔瑟拉-norway|volda-W 沃尔达-norway|skibotn-X 希博滕-norway|skien-X 希恩-norway|kirkenes-X 希尔克内斯-norway|bjornoya-X 熊岛-norway|gjosund-Y 约松-norway|gjovik-Y 约维克-norway|utsiralh-Y 于特西拉-norway","evora-A 埃武拉-portugal|horta-A 奥尔塔-portugal|horta-A 奥尔塔岛-portugal|beja-B 贝雅-portugal|vilareal-B 比利亚雷亚尔-portugal|porto-B 波尔图-portugal|porto-pedrasrubras-B 波尔图?佩德拉什-鲁布拉什-portugal|portalegre-B 波塔莱格雷-portugal|braganca-B 布拉干萨-portugal|castelobranco-B 布朗库堡-portugal|faro-aeroporto-F 法鲁机场-portugal|flores-F 弗洛勒斯岛-portugal|corvo-K 科尔沃岛-portugal|coimbra-K 科英布拉-portugal|lajes-L 拉日什-portugal|lisbon-L 里斯本-portugal|montijo-M 蒙蒂霍-portugal|montereal-M 蒙特垒-portugal|pontadelgada-P 蓬塔德尔加达-portugal|sagres-S 萨格里什-portugal|santa-maria-S 圣玛丽亚-portugal|tancos-T 坦措什-portugal|viseu-W 维塞乌-portugal|sines-X 锡尼什-portugal|angra-do-heroismo-Y 英雄港-portugal","abisko-A 阿比斯库-sweden|arvika-A 阿尔维卡-sweden|arvidsjaur-A 阿尔维斯尧尔-sweden|arjeplog-A 阿尔耶普卢格市-sweden|alvdalen-A 艾尔夫达伦-sweden|eksjo-A 埃克舍-sweden|amot-A 艾莫特-sweden|edsbyn-A 埃斯宾-sweden|eskilstuna-A 埃斯基尔斯蒂纳-sweden|axstal-A 阿克斯图-sweden|hamra-A 阿拉曼-sweden|overkalix-A 奥佛卡利克斯-sweden|asele-A 奥瑟勒-sweden|atvidaberg-A 奥特维达贝里-sweden|bjuroklubb-B 比勒克勒布-sweden|boden-B 博登-sweden|bollnas-B 博尔奈斯-sweden|borgholm-B 博戈霍尔姆-sweden|borlange-B 博伦厄-sweden|tidaholm-D 蒂达霍尔姆-sweden|timra-D 蒂姆罗-sweden|osthammar-D 东哈马尔-sweden|oland-E 厄兰岛-sweden|orebro-E 厄勒布鲁-sweden|oregrund-E 厄勒格伦德-sweden|angelholm-E 恩厄尔霍尔姆-sweden|ornskoldsvik-E 恩金尔兹维克-sweden|enkoping-E 恩科平-sweden|ornskoldsvik-E 恩舍尔兹维克-sweden|enkoping-E 恩雪平-sweden|ostersundfroson-E 厄斯特松德-sweden|falsterbo-F 法尔斯特布-sweden|falsterboa-F 法尔斯特布机场-sweden|falkoping-F 法尔雪平-sweden|vinga-F 伐拉-sweden|farila-F 法里拉-sweden|finspang-F 芬斯蓬-sweden|floda-F 弗卢达-sweden|goteborg-G 哥德堡-sweden|goteborg-landvetter-G 哥德堡-兰德维特机场-sweden|gunnarn-G 贡纳恩-sweden|gunnarna-G 贡纳恩机场-sweden|hagfors-H 哈格福什-sweden|hedemora-H 海德穆拉-sweden|herrljunga-H 海尔利永阿-sweden|harnosand-H 海讷桑德-sweden|hallandsvadero-H 哈兰斯韦德岛-sweden|hano-H 哈诺-sweden|haparanda-H 哈帕兰达-sweden|haparandaa-H 哈帕兰达机场-sweden|hassleholm-H 哈瑟勒霍尔姆-sweden|harstena-H 哈什特纳-sweden|helsingborg-H 赫尔辛堡-sweden|hoberg-mo-H 胡布里-sweden|hoburga-H 胡布里机场-sweden|huddinge-H 胡丁厄-sweden|holmon-H 霍尔曼-sweden|hofors-H 霍弗尔斯-sweden|huskvarna-H 胡斯克瓦纳-sweden|kiruna-J 基律纳-sweden|kalmar-K 卡尔马-sweden|karlsborg-K 卡尔斯堡-sweden|karlskrona-K 卡尔斯克鲁纳-sweden|karlskoga-K 卡尔斯库加-sweden|karlstadflygplats-K 卡尔斯塔德机场-sweden|karesuando-K 卡雷苏安多-sweden|kolback-K 科尔拜克-sweden|kristianstad-K 克里斯蒂安斯塔德-sweden|krangede-K 克龙厄德-sweden|kloten-K 克洛腾-sweden|kosta-K 科斯达-sweden|nordkoster-K 科斯特群岛-sweden|kvikkjokk-K 克维克约克-sweden|kungalv-K 孔艾尔夫-sweden|leksand-L 莱克桑德-sweden|lakatrask-L 拉卡特拉斯克-sweden|laxa-L 拉克索-sweden|landskrona-L 兰德斯克-sweden|landsort-L 兰德索尔特-sweden|lidingo-L 利丁厄-sweden|linkoping-malmslatt-L 林雪平-sweden|ronneby-L 龙讷比-sweden|rangedala-L 龙厄达拉-sweden|robertsfors-L 罗伯茨弗尔斯-sweden|lycksele-L 吕克瑟勒-sweden|lulea-L 吕勒奥-sweden|lysekil-L 吕瑟希尔-sweden|malmo-M 马尔默-sweden|malmo-airport-M 马尔默机场-sweden|mariefred-M 玛丽弗雷德-sweden|malung-M 马隆-sweden|molndal-M 默恩达尔-sweden|mora-M 莫拉-sweden|malilla-M 莫利拉-sweden|sodertalje-N 南泰利耶-sweden|nikkaluokta-N 尼卡卢奥克塔-sweden|nykoping-N 尼雪平-sweden|norrkoping-N 诺尔雪平-sweden|norsjo-N 诺斯约-sweden|partille-P 帕尔蒂勒-sweden|pajala-P 帕亚拉-sweden|soderhamn-flygplats-S 瑟德港机场-sweden|solvesborg-S 瑟尔沃斯堡-sweden|sollentuna-S 绍伦吐纳-sweden|stockholm-S 斯德哥尔摩-sweden|stockholm-arlanda-S 斯德哥尔摩阿兰达机场-sweden|storlien-S 斯图利恩-sweden|storlien-aeroport-S 斯图利恩机场-sweden|sveg-S 斯韦格-sweden|svega-S 斯韦格机场-sweden|sundbyberg-S 松德比贝里-sweden|sundsvall-S 松兹瓦尔-sweden|sunne-S 孙讷-sweden|solleftea-S 索莱夫特奥-sweden|tarfala-T 塔法拉-sweden|tannas-T 坦奈斯-sweden|trelleborg-T 特雷勒堡-sweden|trollhattan-T 特罗尔海坦-sweden|tullinge-T 图灵厄-sweden|valmasen-W 瓦尔马森-sweden|vidsel-W 维德塞尔-sweden|vaxjo-W 韦克舍-sweden|vilhelmina-W 威廉敏娜市-sweden|vanersborg-W 维纳什堡-sweden|visby-W 维斯比-sweden|vasteras-W 韦斯特罗斯-sweden|vetlanda-W 韦特兰达-sweden|uddevalla-W 乌德瓦拉-sweden|ulricehamn-W 乌尔里瑟港-sweden|upplands-vasby-W 乌普兰斯韦斯比-sweden|uppsala-W 乌普萨拉-sweden|skelleftea-X 谢莱夫特奥-sweden|skillinge-X 希灵厄-sweden|jonkoping-axamo-Y 延雪平-sweden|gaddede-Y 耶代德-sweden|gavle-Y 耶夫勒-sweden|gallivare-Y 耶利瓦勒-sweden|junsele-Y 永瑟勒-sweden|hjo-Y 尤城-sweden|jokkmokkfpl-Y 约克莫克-sweden|umea-Y 于默奥-sweden|ystad-Y 于斯塔德-sweden","adelboden-A 阿德尔博登-switzerland|altenrhein-A 阿尔滕莱茵-switzerland|altdorf-A 阿尔特多夫-switzerland|aigle-A 艾高-switzerland|aigle-A 艾格勒-switzerland|emmenbrucke-A 埃门布鲁克-switzerland|einsiedeln-A 艾因西德伦-switzerland|aarau-A 阿劳-switzerland|arosa-A 阿罗萨-switzerland|olten-A 奥尔滕-switzerland|basel-B 巴塞尔-switzerland|bellinzona-B 贝林佐纳-switzerland|beznau-B 贝兹瑙-switzerland|bir-B 比尔-switzerland|bern-B 伯尔尼-switzerland|bern-belpmoos-B 伯尔尼贝尔普机场-switzerland|poschiavo-B 波斯基亚沃-switzerland|brienz-B 布里恩茨-switzerland|zermatt-C 采尔马特-switzerland|zermatt-C 策马特-switzerland|chasseral-C 查榭哈峰-switzerland|zollikon-C 措理孔-switzerland|davos-D 达沃斯-switzerland|disentis-D 迪森蒂斯-switzerland|disentis-sedrun-D 迪森蒂斯·塞德龙-switzerland|fahy-F 法伊-switzerland|visp-F 菲斯普-switzerland|flims-F 弗利姆斯-switzerland|glarus-G 格拉鲁斯-switzerland|grenchen-G 格兰岑-switzerland|grindelwald-G 格林德尔瓦尔德-switzerland|gornergrat-G 哥纳葛特山-switzerland|gstaad-G 格施塔德-switzerland|hoernli-H 荷恩利-switzerland|hinterrhein-H 后莱茵河-switzerland|giswil-J 吉斯维-switzerland|cham-K 卡姆-switzerland|koniz-K 科尼兹-switzerland|chur-K 库尔-switzerland|quinten-K 昆腾-switzerland|leibstadt-L 莱布施塔特-switzerland|lachaux-defonds-L 拉绍德封-switzerland|liestal-L 利斯塔尔-switzerland|lugano-L 卢加诺-switzerland|locarno-L 洛迦诺-switzerland|lausanne-L 洛桑-switzerland|launited-states-of-americanne-L 洛桑市-switzerland|lucerne-L 卢塞恩-switzerland|meiringen-M 迈林根-switzerland|magadino-M 马加迪诺-switzerland|montana-M 蒙塔纳-switzerland|monterosa-M 蒙特罗萨-switzerland|muehleberg-M 米勒贝格-switzerland|napf-N 纳普夫-switzerland|neuchatel-N 纳沙泰尔-switzerland|payerne-P 帕耶讷-switzerland|payerne-P 佩耶纳-switzerland|pilatus-P 皮拉图斯山-switzerland|cimetta-Q 奇梅塔-switzerland|geneva-R 日内瓦-switzerland|geneva-cointrin-R 日内瓦克万特兰国际机场-switzerland|samedan-S 萨梅丹-switzerland|saentis-S 桑蒂斯峰-switzerland|schaffhausen-S 沙夫豪森-switzerland|jungfraujoch-S 少女峰-switzerland|st-gallen-S 圣加仑-switzerland|scuol-S 施库尔-switzerland|stabio-S 斯塔比奥-switzerland|zurich-S 苏黎世-switzerland|wynau-W 维瑙-switzerland|verbier-W 韦比尔-switzerland|winterthur-W 温特图尔-switzerland|uster-W 乌斯特-switzerland|chaumont-X 肖蒙-switzerland|sion-X 锡永-switzerland|engelberg-Y 英格堡-switzerland|interlaken-Y 因特拉肯-switzerland","bar-B 巴尔-serbia|belgrade-B 贝尔格莱德-serbia|beograd-surcin-B 贝尔格莱德·苏尔津-serbia|podgorica-grad-B 波德戈里察格拉德-serbia|cacak-C 查查克-serbia|veliko-gradiste-D 大格拉迪什泰-serbia|vrsac-F 弗尔沙茨-serbia|vranje-F 弗拉涅-serbia|kikinda-J 基金达-serbia|dimitrovgrad-J 季米特洛夫格勒-serbia|kragujevac-K 克拉古耶瓦茨-serbia|kraljevo-K 克拉列沃-serbia|kolasin-K 科拉欣-serbia|krusevac-K 克鲁舍瓦茨-serbia|kopaonik-K 科帕奥尼克-serbia|leskovac-L 莱斯科瓦茨-serbia|ratari-L 拉塔利-serbia|zrenjanin-L 雷尼亚宁-serbia|loznica-L 洛兹尼察-serbia|negotin-N 内戈廷-serbia|niksic-N 尼克希奇-serbia|crnivrh-N 尼沙瓦州-serbia|nis-N 尼什-serbia|novi-sad-N 诺维萨德-serbia|pancevo-P 潘切沃-serbia|pec-P 佩克-serbia|pljevlja-P 普列夫利亚-serbia|pristina-P 普里什蒂纳-serbia|prizren-P 普里兹伦-serbia|cuprija-Q 丘普里亚-serbia|sremska-mitrovica-S 斯雷姆斯卡米特罗维察-serbia|smederevo-S 斯梅代雷沃-serbia|sombor-S 松博尔-serbia|valjevo-W 瓦列沃-serbia|sjenica-X 谢尼察-serbia|zabljak-Z 扎布利亚克-serbia|zlatibor-Z 兹拉蒂博尔-serbia|zrenjanin-Z 兹雷尼亚宁-serbia","bardejov-B 巴尔代约夫-slovakia|banska-stiavnica-B 班斯卡-什佳夫尼察-slovakia|poprad-B 波普拉德-slovakia|bratislava-B 布拉迪斯拉发-slovakia|handlova-H 汉德洛瓦-slovakia|humenne-H 胡门内-slovakia|kosice-K 科希策-slovakia|rimavska-sobota-L 里马夫斯卡索博塔-slovakia|roznava-L 罗兹纳瓦-slovakia|lucenec-L 卢切内茨-slovakia|nitra-N 尼特拉-slovakia|piestany-P 皮耶什佳尼-slovakia|prievidza-P 普列维扎-slovakia|cadca-Q 恰德察-slovakia|sliac-S 斯里阿奇-slovakia|snina-S 斯尼纳-slovakia|stropkov-S 斯特罗普科夫-slovakia|topolcany-T 托波尔恰尼-slovakia","postojna-B 波斯托-slovenia|celje-C 采列-slovenia|krsko-K 克尔斯科-slovenia|kranj-K 克拉尼-slovenia|kocevje-K 科切维-slovenia|lisca-L 利斯卡-slovenia|ljubljana-L 卢布尔雅那-slovenia|ljubljana-brnik-L 卢布尔雅那奔尼克机场-slovenia|maribor-slivnica-M 马里博尔-slovenia|murska-sobota-M 穆尔斯卡索博塔-slovenia|slovenska-bistrica-S 斯洛伐克比斯特里察-slovenia|novo-mesto-X 新梅斯托-slovenia","adana-A 阿达纳-turkey|afyon-A 阿菲永-turkey|aydin-A 艾登-turkey|edirne-A 埃迪尔内-turkey|erzincan-A 埃尔津詹-turkey|erzurum-A 埃尔祖鲁姆-turkey|elazig-A 埃拉泽-turkey|eskisehir-A 埃斯基谢希尔-turkey|anamur-A 阿纳穆尔-turkey|ankara-A 安卡拉-turkey|antalya-A 安塔利亚-turkey|balikesir-B 巴勒克希尔-turkey|bandirma-B 班德尔玛-turkey|bergama-B 贝加盟-turkey|bismil-B 比斯米尔-turkey|bursa-B 布尔萨-turkey|diyarbakir-D 迪亚巴克尔-turkey|finike-F 菲尼克-turkey|gaziantep-J 加济安泰普-turkey|ceyhan-J 杰伊汉-turkey|kirsehir-K 克尔谢希尔-turkey|kirikkale-K 克鲁兹卡雷-turkey|konya-K 科尼亚-turkey|kusadasi-K 库沙达瑟-turkey|lapseki-L 拉普塞基-turkey|manavgat-M 马纳夫加特-turkey|merzifon-M 梅尔济丰-turkey|nevsehir-N 内夫谢希尔-turkey|pamukkale-P 帕莫卡莱-turkey|canakkale-Q 恰纳卡莱-turkey|corum-Q 乔鲁姆-turkey|samsun-S 萨姆松-turkey|tarsus-T 塔尔苏斯-turkey|tekirdag-T 泰基尔达-turkey|trabzon-T 特拉布宗-turkey|urla-W 乌拉-turkey|usak-W 乌沙克-turkey|siirt-X 锡尔特-turkey|silifke-X 西利夫克-turkey|inegol-Y 伊内格尔-turkey|iskenderun-Y 伊斯肯德伦-turkey|isparta-Y 伊斯帕尔塔-turkey|istanbul-Y 伊斯坦布尔-turkey|istanbul-ataturk-Y 伊斯坦布尔·阿塔图尔克-turkey|izmir-Y 伊兹密尔-turkey|zonguldak-Z 宗古尔达克-turkey","ai-petri-A 埃佩特里-ukraine|aleksandrov-gaj-A 阿列散竹山形机场-ukraine|alushta-A 阿卢什塔-ukraine|odesa-A 敖德萨-ukraine|ovruch-A 奥夫鲁赤-ukraine|boryspil-B 鲍里斯皮尔-ukraine|berezhany-B 别列扎内-ukraine|poltava-B 波尔塔瓦-ukraine|briceni-B 布里恰内-ukraine|brody-B 布罗迪-ukraine|drogobych-D 德罗戈贝奇-ukraine|druzhba-D 德鲁日巴-ukraine|donetsk-D 顿涅茨克-ukraine|frolovo-F 弗罗洛沃-ukraine|kharkov-H 哈尔科夫-ukraine|kherson-H 赫尔松-ukraine|ternopil-J 捷尔诺波尔-ukraine|kyiv-J 基辅-ukraine|kirovohrad-J 基洛夫格勒-ukraine|kerch-K 刻赤-ukraine|kolomyia-K 科洛梅亚-ukraine|konotop-K 科诺托普-ukraine|lviv-L 利沃夫-ukraine|lubny-L 卢布内-ukraine|rivne-L 罗夫诺-ukraine|romny-L 罗姆内-ukraine|millerovo-M 米列罗沃-ukraine|pallasovka-P 帕拉索夫卡-ukraine|cherkasy-Q 切尔卡瑟-ukraine|chernihiv-Q 切尔尼戈夫-ukraine|chornobyl-Q 切尔诺贝利-ukraine|chernivtsi-Q 切尔诺夫策-ukraine|zhytomyr-R 日托米尔-ukraine|sarny-S 萨尔内-ukraine|sumy-S 苏梅-ukraine|soroca-S 索罗卡-ukraine|vinnitsa-W 文尼察-ukraine|uzhhorod-W 乌日霍罗德-ukraine|simferopol-X 辛菲罗波尔-ukraine|yalta-Y 雅尔塔-ukraine|izmail-Y 伊兹梅尔-ukraine|zaporizhzhia-Z 扎波罗热-ukraine","albacete-losllanos-A 阿尔巴塞特-spain|algeciras-A 阿尔赫西拉斯-spain|almeria-aeropuerto-A 阿尔梅里亚-spain|elche-A 埃尔切-spain|alicante-A 阿利坎特-spain|alicante-A 阿里坎特-spain|orense-A 奥伦塞-spain|oviedo-A 奥维耶多-spain|avila-A 阿维拉-spain|valladolid-B 巴利亚多利德-spain|valencia-B 巴伦西亚-spain|barcelona-B 巴塞罗那-spain|bilbao-B 毕尔巴鄂-spain|granada-G 格拉纳达-spain|guadalajara-G 瓜达拉哈拉-spain|jerez-dela-frontera-aeropuerto-H 赫雷斯德拉弗龙特拉机场-spain|caceres-K 卡塞雷斯-spain|castellon-K 卡斯特利翁-spain|castellon-de-la-plana-K 卡斯特利翁-德拉普拉纳-spain|cordoba-aeropuerto-K 科尔多瓦机场-spain|lleida-L 莱里达-spain|lacoruna-L 拉柯鲁尼亚-spain|lamolina-L 拉磨利那-spain|ciudad-real-L 雷阿尔城-spain|logrono-agoncillo-L 洛格罗尼奥-spain|rota-L 罗塔岛-spain|madrid-M 马德里-spain|madrid-barajas-M 马德里·巴拉哈斯-spain|malaga-M 马拉加-spain|mallorca-M 马略卡岛-spain|palma-de-mallorca-airport-M 马略卡岛帕尔马机场-spain|melilla-M 梅利利亚-spain|menorca-mahon-M 梅诺卡岛-spain|murcia-M 穆尔西亚-spain|navacerrada-N 那瓦塞拉达-spain|pamplona-P 潘普洛纳-spain|ponferrada-P 蓬费拉达-spain|pontevedra-P 蓬特韦德拉-spain|segovia-S 塞哥维亚-spain|zaragoza-aeropuerto-S 萨拉戈萨-spain|salamanca-matacan-S 萨拉曼卡-spain|zamora-S 萨莫拉-spain|soria-S 索里亚-spain|tarifa-T 塔里法-spain|teruel-T 特鲁埃尔-spain|tenerife-guimar-T 特纳利夫·吉马尔-spain|tortosa-T 托尔托萨-spain|toledo-city-T 托莱多-spain|valencia-aeropuerto-W 瓦伦西亚-spain|vitoria-W 维多利亚-spain|huelva-W 韦尔瓦-spain|gijon-X 希洪-spain|ceuta-X 休达-spain|ibiza-Y 伊比沙岛-spain|izana-Y 伊萨纳-spain","arta-A 阿尔塔-greece|agrinio-A 阿格里尼翁-greece|agrinion-airport-A 阿格里尼翁机场-greece|ios-A 艾奥斯-greece|elefsis-airport-A 埃莱夫西西机场-greece|araxos-A 阿拉科斯-greece|araxos-airport-A 阿拉科斯机场-greece|amorgos-A 阿摩尔戈斯-greece|anafi-A 阿纳菲-greece|andravida-airport-A 安德拉韦达机场-greece|andros-A 安德罗斯-greece|pireas-B 比雷埃夫斯-greece|polichnitos-B 波利赫尼托斯-greece|tilospuszta-D 蒂洛斯-greece|tinos-D 蒂诺斯-greece|folegandros-F 福莱甘兹罗斯-greece|florina-F 弗劳利纳-greece|chalkida-H 哈尔基斯-greece|kimolos-J 基莫洛斯-greece|kythnos-J 基斯诺斯-greece|kythira-J 基西拉-greece|karditsa-K 喀迪察-greece|karpathos-K 卡尔帕索斯-greece|kalamata-K 卡拉迈-greece|kalamakion-K 卡拉马孔-greece|kalamata-airport-K 卡拉马塔机场-greece|kalymnos-K 卡里姆诺斯-greece|kastoria-airport-K 卡斯托利亚机场-greece|kerkyra-K 克基拉-greece|korinthos-K 科林斯-greece|xanthi-K 克桑西-greece|kozani-K 科扎尼-greece|kozani-airport-K 科扎尼机场-greece|larissa-airport-L 拉里萨-greece|lamia-L 拉米亚-greece|rethymnon-L 雷斯蒙-greece|limnos-L 利姆诺斯-greece|limnos-airport-L 利姆诺斯岛-greece|rhodes-airport-L 罗兹机场-greece|methoni-M 迈索尼-greece|mytilini-M 米蒂利尼-greece|mytilini-airport-M 米蒂利尼机场-greece|mykonos-M 米科诺斯-greece|milos-M 米洛斯-greece|milos-M 米洛斯岛-greece|nafplio-N 纳夫普利翁-greece|naxos-N 纳克索斯-greece|naxos-N 纳克索斯岛-greece|patra-P 帕特雷-greece|preveza-P 普雷韦扎-greece|serres-S 塞雷-greece|serifos-S 塞里福斯-greece|thessaloniki-airport-S 塞萨罗尼基-greece|salamina-S 萨拉米斯-greece|thessaloniki-S 萨洛尼卡-greece|samos-S 萨摩斯-greece|ayia-paraskevi-S 圣帕拉斯凯维-greece|skyros-S 斯基罗斯-greece|skyros-airport-S 斯基罗斯岛机场-greece|skiathos-S 斯基亚奈斯-greece|souda-airport-S 苏达-greece|tanagra-airport-T 塔纳格拉-greece|tatoi-T 塔托伊-greece|tripolis-airport-T 特里波利斯机场-greece|trikala-T 特里卡拉-greece|volos-W 沃洛斯-greece|chios-X 希俄斯-greece|chios-airport-X 希俄斯机场-greece|sikinos-X 锡基诺斯-greece|thira-airport-X 锡拉机场-greece|siros-X 锡罗斯-greece|sitia-X 西提亚-greece|athina-Y 雅典-greece|alexandroupoli-Y 亚历山德鲁波利斯-greece|alexandroupoli-airport-Y 亚历山德鲁波利斯机场-greece|heraklion-airport-Y 伊拉克里翁机场-greece|ilioupoli-Y 伊利奥普里斯-greece|ioannina-airport-Y 约阿尼纳机场-greece|zakynthos-Z 扎金索斯-greece|zografos-Z 佐格拉夫斯-greece","erd-A 埃尔德-hungary|eger-A 埃格尔-hungary|egyek-A 埃杰克-hungary|agard-A 阿加德-hungary|abaujszanto-A 奥包乌伊桑托-hungary|ofeherto-A 奥费赫尔托-hungary|berettyoujfalu-B 拜赖焦新村-hungary|balatonboglar-B 巴拉顿博格拉-hungary|baja-B 包姚-hungary|bekescsaba-B 贝凯什乔包-hungary|polgar-B 波尔加-hungary|paks-B 波克什-hungary|poroszlo-B 波罗兹洛-hungary|budapest-B 布达佩斯-hungary|cegled-C 采格莱德-hungary|letavertes-D 大莱陶-hungary|debrecen-D 德布勒森-hungary|tiszafured-D 蒂萨福尔德-hungary|tiszanana-D 蒂萨纳拉-hungary|tiszavasvari-D 蒂萨铁堡-hungary|dunaujvaros-D 多瑙新城-hungary|gyor-J 杰尔-hungary|nagykanizsa-J 瑙吉考尼饶-hungary|kecel-K 凯采尔-hungary|kecskemet-K 凯奇凯梅特-hungary|kecskemet-K 凯奇凯米特-hungary|keszthely-K 凯斯特海伊-hungary|kunszentmarton-K 孔圣马尔通-hungary|mezocsat-M 迈泽恰特-hungary|miskolc-M 密什科尔茨-hungary|miskolc-M 米什科尔茨-hungary|mosonmagyarovar-M 莫雄马扎尔古堡-hungary|nyiregyhaza-N 尼赖吉哈佐-hungary|oroshaza-O 欧罗什哈佐-hungary|palic-P 帕里奇-hungary|papa-P 帕帕-hungary|pecs-P 佩奇-hungary|puspokladany-P 皮什珀克洛达尼-hungary|sarbogard-S 萨尔博加德-hungary|szeged-S 塞格德-hungary|szekesfehervar-S 塞克希费黑瓦尔-hungary|szecseny-S 塞切尼-hungary|szombathely-S 松博特海伊-hungary|szolnok-S 索尔诺克-hungary|sopron-S 索普朗-hungary|tapolca-T 塔波尔卡-hungary|tatabanya-T 陶陶巴尼奥-hungary|taszar-T 塔萨-hungary|tokol-T 托科-hungary|vac-W 瓦克-hungary|ujfeherto-W 乌伊费赫托-hungary|siofok-X 希欧福克-hungary|zahony-Z 扎霍尼-hungary","albenga-A 阿尔本加-italy|alghero-A 阿尔盖罗-italy|alcamo-A 阿尔卡莫-italy|altamura-A 阿尔塔姆拉-italy|agnone-A 阿戈内-italy|acquapendente-A 阿夸彭登泰-italy|arezzo-A 阿雷佐-italy|amendola-A 阿门多拉-italy|ancona-A 安科纳-italy|anzio-A 安齐奥-italy|olbia-A 奥尔比亚-italy|olbia-costa-smeralda-A 奥尔比亚机场-italy|orvieto-A 奥尔维托-italy|orzinuovi-A 奥齐诺维-italy|ostiglia-A 奥斯蒂利亚-italy|aosta-A 奥斯塔-italy|otranto-A 奥特兰托-italy|apecchio-A 阿佩基奥-italy|acireale-A 阿奇雷亚莱-italy|ascoli-piceno-A 阿斯科利皮切诺-italy|aviano-A 阿维亚诺-italy|avezzano-A 阿韦扎诺-italy|assisi-A 阿西斯-italy|bagheria-B 巴盖里亚-italy|palermo-B 巴勒莫-italy|palermopuntaraisi-B 巴勒莫省西西里-italy|bari-B 巴里-italy|barletta-B 巴列塔-italy|bari-palese-B 巴里·佩雷斯-italy|barcellona-pozzo-di-gotto-B 巴切洛纳波佐迪戈图-italy|bassano-del-grappa-B 巴萨诺-德尔格拉帕-italy|bergamo-B 贝加莫-italy|castelnuovo-berardenga-B 贝拉登加新堡-italy|belluno-B 贝卢诺-italy|capobellavista-B 贝亚维斯塔角-italy|pisa-B 比萨-italy|pisas-giusto-B 比萨·圭斯托-italy|biella-B 比耶拉-italy|bobbio-B 博比奥-italy|bormio-B 博尔米奥-italy|bolzano-B 博尔扎诺-italy|poggibonsi-B 波基博恩西-italy|porassey-B 波拉希-italy|policoro-B 波利克洛-italy|bologna-B 博洛尼亚-italy|pomarance-B 波马兰切-italy|bonifati-B 波尼法蒂-italy|potenza-B 波坦察-italy|positano-B 波西塔诺-italy|bojano-B 博亚诺-italy|brescia-B 布雷西亚-italy|brescia-ghedi-B 布雷西亚·盖迪-italy|brindisi-B 布林迪西-italy|broni-B 布龙尼-italy|bronzolo-B 布龙佐洛-italy|brunico-B 布鲁尼科-italy|decimomannu-D 代齐莫曼努-italy|desenzano-D 代森扎诺-italy|castellammare-del-golfo-D 德尔堡湾-italy|trieste-D 的里雅斯特-italy|desenzano-D 德森扎诺-italy|dicomano-D 迪科马诺-italy|tirano-D 蒂拉诺-italy|turin-D 都灵-italy|dobbiaco-D 多比亚科-italy|domodossola-D 多莫多索拉-italy|donnaz-D 多纳-italy|empoli-E 恩波利-italy|volterra-E 渥尔特拉-italy|falconara-F 法尔科纳拉-italy|ventimiglia-F 凡提米利亚-italy|castelfiorentino-F 菲奥伦蒂诺堡-italy|ferrara-F 费拉拉-italy|fivizzano-F 菲韦扎诺-italy|florence-F 佛罗伦萨-italy|florence-F 佛洛伦萨-italy|furbara-F 富尔巴拉-italy|formia-F 福尔米亚-italy|fornovo-di-taro-F 福尔诺沃-迪塔洛-italy|foggia-F 福贾-italy|francavilla-fontana-F 弗兰卡维拉丰塔纳-italy|forli-F 弗利-italy|frontone-F 弗龙托内-italy|follonica-F 福洛尼卡-italy|fucino-F 富齐诺-italy|grazzanise-G 格拉赞尼塞-italy|gorizia-G 戈里齐亚-italy|grosseto-G 格罗塞托-italy|grottaglie-G 格罗塔里埃-italy|guardia-lombardi-G 瓜尔迪亚-隆巴尔迪-italy|gualdo-tadino-G 瓜尔多塔迪亚-italy|gubbio-G 古比奥-italy|guidonia-G 圭多尼亚-italy|gravedona-H 赫拉弗多纳-italy|castelnuovo-di-garfagnana-J 加尔法尼亚纳新堡-italy|gallarate-J 加拉拉特-italy|gaiole-in-chianti-J 基安蒂盖奥勒-italy|greve-in-chianti-J 基安蒂格雷沃-italy|castellina-in-chianti-J 基安蒂卡斯特利纳-italy|chioggia-J 基奥贾-italy|gioia-del-colle-J 焦亚省科莱-italy|chivasso-J 基瓦索-italy|chieti-J 基耶蒂-italy|capos-lorenzo-K 卡玻斯罗伦佐-italy|carbonia-K 卡尔博尼亚-italy|carmagnola-K 卡尔马戈诺拉-italy|carpi-K 卡尔皮-italy|caltagirone-K 卡尔塔吉罗-italy|cagliari-K 卡利亚里-italy|carloforte-K 卡洛福泰-italy|camaiore-K 卡麦奥雷-italy|campobasso-K 坎波巴索-italy|campomarino-K 坎波马里诺-italy|capopalinuro-K 坎帕尼亚帕利努罗角-italy|capranica-K 卡普拉尼卡-italy|capri-K 卡普里-italy|capocaccia-K 卡恰角-italy|caserta-K 卡塞塔-italy|castenaso-K 卡斯泰纳索-italy|castelvetrano-K 卡斯特尔韦特拉诺-italy|caltanissetta-K 卡塔尼塞塔-italy|catania-K 卡塔尼亚-italy|catania-sigonella-K 卡塔尼亚西格内拉机场-italy|catanzaro-K 卡坦扎罗-italy|cortona-K 科尔托纳-italy|collegno-K 科莱戈诺-italy|cles-K 克莱斯-italy|crotone-K 克罗托内-italy|cuneo-K 库内奥-italy|latina-L 拉蒂纳-italy|castiglione-del-lago-L 拉戈堡-italy|ragusa-L 拉古萨-italy|lecco-L 莱科-italy|lecce-L 莱切-italy|lampedusa-L 兰佩杜萨-italy|lampedunited-states-of-america-L 蓝佩杜萨岛-italy|lanciano-L 兰恰诺-italy|lanuvio-L 拉努韦奥-italy|laurino-L 劳利诺-italy|rapallo-L 拉帕洛-italy|lavello-L 拉韦洛-italy|ravenna-L 拉文纳-italy|reggio-di-calabria-L 雷焦卡拉布里亚娣-italy|reggello-L 雷杰诺-italy|radda-in-chianti-L 联合会在基安蒂-italy|rieti-L 列蒂-italy|licata-L 利卡塔-italy|rimini-L 里米尼-italy|riccia-L 里齐亚-italy|riva-del-garda-L 里瓦-德勒加尔达-italy|livigno-L 利维尼奥-italy|livorno-L 利沃诺-italy|rieti-L 里耶提-italy|ronchideilegionari-L 龙基代莱焦纳里-italy|rufina-L 鲁菲娜-italy|luqa-L 鲁卡-italy|vibo-valentia-L 伦蒂亚-italy|loreto-L 洛雷托-italy|rolo-L 罗罗-italy|rome-L 罗马-italy|rovigo-L 罗维戈-italy|lovere-L 洛韦雷-italy|marina-di-ginosa-M 马里纳-迪吉诺萨-italy|massa-lubrense-M 马萨卢布伦塞-italy|massarosa-M 马萨罗萨-italy|massa-martana-M 马萨马尔塔纳-italy|matera-M 马泰拉-italy|matelica-M 马泰利卡-italy|martinafranca-M 马天尼芬卡-italy|merano-M 梅拉诺-italy|mestre-M 梅斯特-italy|mondragone-M 蒙德拉贡-italy|mondovi-M 蒙多维-italy|moncalieri-M 蒙卡列里-italy|montalcino-M 蒙塔尔奇诺-italy|montepulciano-M 蒙泰普尔恰诺-italy|montaione-M 蒙塔约内-italy|monteargentario-M 蒙特阿根塔略-italy|montecatini-terme-M 蒙特卡蒂尼-泰尔梅-italy|monteriggioni-M 蒙特利齐约尼-italy|montecchio-M 蒙特切利奥-italy|montecimone-M 蒙特奇莫尼-italy|montes.angelo-M 蒙特斯-安吉洛-italy|montescuro-M 蒙特斯库罗-italy|montespertoli-M 蒙特斯佩托利-italy|montesilvano-M 蒙特西瓦诺-italy|monza-M 蒙扎-italy|milan-M 米兰-italy|milano-linate-M 米兰·利纳特-italy|modena-M 摩德纳-italy|molfetta-M 莫尔费塔-italy|mola-di-bari-M 莫拉弟巴里-italy|monopoli-M 莫诺波利-italy|moscufo-M 莫斯库夫-italy|messina-M 墨西拿-italy|muravera-M 穆拉沃拉-italy|naples-N 拿波里-italy|naples-N 那不勒斯-italy|nuoro-N 努奥罗-italy|novara-N 诺瓦拉-italy|padova-P 帕多瓦-italy|parma-P 帕尔马-italy|palmi-P 帕尔米-italy|pachino-P 帕基诺-italy|palaia-P 帕拉亚-italy|pompei-P 庞贝-italy|pantelleria-P 潘泰莱里亚-italy|porto-empedocle-P 佩恩多克莱港-italy|pelago-P 佩拉戈-italy|perugia-P 佩鲁贾-italy|perugias-egidio-P 佩鲁贾埃吉迪奥-italy|peccioli-P 佩乔利-italy|pescara-P 佩斯卡拉-italy|pescina-P 佩希纳-italy|pesaro-P 佩扎罗-italy|ponte-di-legno-P 蓬迪雷格诺-italy|ponza-P 蓬扎岛-italy|pitigliano-P 皮蒂利亚诺-italy|piombino-P 皮翁比诺-italy|piacenzas-damiano-P 皮亚琴察·达米亚诺-italy|pizzoferrato-P 皮佐费拉图-italy|pratica-di-mare-P 普拉提卡·迪马雷-italy|prato-P 普拉托-italy|preganziol-P 普雷甘兹佐-italy|prizzi-P 普里兹-italy|ciampino-Q 恰姆皮诺-italy|cervia-Q 切尔维亚-italy|cerreto-guidi-Q 切雷托圭迪-italy|celico-Q 切里科-italy|certaldo-Q 切塔尔多-italy|cinigiano-Q 奇尼基亚诺-italy|cisternino-Q 奇斯特尼诺-italy|civitavecchia-Q 奇维塔韦基亚-italy|chiavari-Q 齐亚瓦里-italy|randazzo-R 冉达佐-italy|genoa-R 热那亚-italy|salerno-S 萨莱诺-italy|sassari-S 萨萨里-italy|borgo-san-lorenzo-S 圣洛伦佐镇-italy|s.mariadileuca-S 圣玛利亚迪勒乌卡-italy|spoleto-S 斯波莱托-italy|stia-S 斯蒂亚-italy|scauri-S 斯考利-italy|tarvisio-T 塔尔维西奥-italy|termini-imerese-T 泰尔米尼-伊梅雷塞-italy|termoli-T 泰尔莫利-italy|teramo-T 泰拉莫-italy|terracina-T 泰拉奇纳-italy|taranto-T 塔兰托-italy|taormina-T 陶尔米纳-italy|taurianova-T 陶里阿诺瓦-italy|tavarnelle-val-di-pesa-T 塔韦尔内尔-瓦尔第-italy|terni-T 特尔尼-italy|trento-T 特兰托-italy|terranuova-bracciolini-T 特拉诺瓦-布拉乔利尼-italy|trapani-T 特拉帕尼-italy|trapani-birgi-T 特拉帕尼毕_吉机场-italy|treviso-istrana-T 特雷维索·伊斯楚阿纳-italy|trento-T 特伦托-italy|teulada-T 特乌拉达-italy|torgiano-T 托尔吉亚诺-italy|tortoli-T 托尔托利-italy|torre-del-greco-T 托雷德格雷科-italy|vallata-W 瓦拉塔-italy|varese-ligure-W 瓦雷泽古雷-italy|villasimius-W 维拉西米乌斯-italy|verona-W 维罗纳-italy|verona-villafranca-W 维罗纳·维拉弗兰卡-italy|venice-W 威尼斯-italy|vipiteno-W 维皮泰诺-italy|vicenza-W 维琴察-italy|viterbo-W 维泰博-italy|viareggio-W 维亚雷焦-italy|vieste-W 维耶斯泰-italy|volano-W 沃兰诺-italy|udine-W 乌迪内-italy|urbania-W 乌尔巴尼亚-italy|oulx-W 乌尔克斯-italy|sciacca-X 夏卡-italy|siderno-X 锡代诺-italy|sirmione-X 锡尔米奥内-italy|siracunited-states-of-america-X 锡拉库萨-italy|ciro-marina-X 西罗滨海-italy|alessandria-Y 亚历山德里亚-italy|enna-Y 伊恩-italy|imperia-Y 因佩里亚-italy","aberdeen-A 阿伯丁-united-kingdom|dyce-A 阿伯丁小镇-united-kingdom|aberporth-A 阿伯珀斯-united-kingdom|aldergrove-A 阿达高夫-united-kingdom|albemarle-A 阿尔比马尔-united-kingdom|aberdaron-A 埃布尔达伦-united-kingdom|edinburgh-A 爱丁堡-united-kingdom|exeter-A 埃克塞特-united-kingdom|islay-A 艾拉岛-united-kingdom|andrewsfield-A 安德鲁斯机场-united-kingdom|aviemore-A 阿维莫尔-united-kingdom|ballypatrickforest-B 巴利帕特里克森林-united-kingdom|benson-B 班森-united-kingdom|bedford-B 贝德福德-united-kingdom|belfast-B 贝尔法斯特-united-kingdom|peterhead-harbour-B 彼得赫德港-united-kingdom|birmingham-B 伯明翰-united-kingdom|boscombedown-B 波斯坎比当-united-kingdom|brizenorton-B 布莱兹诺顿-united-kingdom|bridlingtonmrsc-B 布里德灵顿-united-kingdom|charlwood-C 查伍德-united-kingdom|aultbea-no.2-E 二号奥比亚-united-kingdom|baltasound-no.2-E 二号鲍尔塔桑德-united-kingdom|bingley-no.2-E 二号宾利-united-kingdom|foula-no.2-E 二号福拉-united-kingdom|glenanne-no.2-E 二号格莱纳妮-united-kingdom|lakevyrnwy-no.2-E 二号韦尔努伊湖-united-kingdom|wainfleet-no.2-E 二号威因夫利-united-kingdom|aboyne-no.2-E 二号亚波恩-united-kingdom|filton-F 菲尔顿-united-kingdom|fylingdales-F 费林戴尔斯-united-kingdom|glasgow-G 格拉斯哥-united-kingdom|gravesend-broadness-G 格雷夫森德浅水湖-united-kingdom|gloucester-G 格洛斯特-united-kingdom|guernsey-G 根西岛-united-kingdom|hurn-H 赫恩-united-kingdom|kingston-upon-hull-H 赫尔河畔京士顿-united-kingdom|holbeach-no.2-H 霍尔比齐二号-united-kingdom|hawarden-airport-H 霍瓦登机场-united-kingdom|kinloss-J 金洛斯-united-kingdom|culdrose-K 卡尔德罗斯-united-kingdom|cardinham-bodmin-K 凯蒂汉姆博德明-united-kingdom|keswick-K 凯斯维克-united-kingdom|carlisle-K 卡莱尔-united-kingdom|campbeltown-K 坎贝尔敦-united-kingdom|camborne-K 坎伯恩-united-kingdom|coventry-K 考文垂-united-kingdom|cottesmore-K 柯茨摩尔-united-kingdom|kirkwall-K 柯克沃尔-united-kingdom|cranwell-K 克兰威尔-united-kingdom|crosby-K 克罗斯比-united-kingdom|coningsby-K 科宁斯比-united-kingdom|kenleyairfield-K 垦利机场-united-kingdom|lyneham-L 莱恩汉姆-united-kingdom|leicester-L 莱斯特-united-kingdom|larkhill-L 拉克希尔-united-kingdom|lerwick-L 勒威克-united-kingdom|leeming-L 利明-united-kingdom|leuchars-L 琉查尔斯-united-kingdom|liverpool-L 利物浦-united-kingdom|london-L 伦敦-united-kingdom|londonderry-L 伦敦德里-united-kingdom|loftus-L 洛夫特斯-united-kingdom|lossiemouth-L 洛西茅斯-united-kingdom|marham-M 马勒姆-united-kingdom|manchester-M 曼彻斯特-united-kingdom|manston-M 曼斯顿-united-kingdom|mona-M 莫娜-united-kingdom|southampton-N 南安普敦-united-kingdom|newport-N 纽波特-united-kingdom|oxford-N 牛津-united-kingdom|nottingham-N 诺丁汉-united-kingdom|northolt-N 诺里霍兹-united-kingdom|pymouth-P 普利茅斯-united-kingdom|chichester-Q 奇切斯特-united-kingdom|churchfenton-Q 丘奇芬顿-united-kingdom|sheffield-S 设菲尔德-united-kingdom|st.athan-S 圣阿桑-united-kingdom|shawbury-S 什罗普郡-united-kingdom|skye-S 斯凯岛-united-kingdom|scampton-S 斯坎普顿-united-kingdom|stornoway-airport-S 斯托诺韦-united-kingdom|swansea-S 斯旺西-united-kingdom|shobdon-airfield-S 索登机场-united-kingdom|solent-S 索伦特-united-kingdom|tulloch-bridge-T 塔洛克桥-united-kingdom|stoke-on-trent-T 特伦特河畔斯托克-united-kingdom|thorney-island-T 托尼岛-united-kingdom|wick-W 威克-united-kingdom|waddington-W 沃丁顿-united-kingdom|wattisham-W 沃提夏姆-united-kingdom|wolverhampton-W 伍尔弗汉普顿-united-kingdom|worcester-W 伍斯特-united-kingdom|pershore-X 珀肖尔-united-kingdom|shoreham-airport-X 肖勒姆机场-united-kingdom|scilly-X 锡利-united-kingdom|yeovilton-Y 约维尔顿-united-kingdom|jersey-airport-Z 泽西机场-united-kingdom","gibraltar-Z 直布罗陀-gibraltar"]; +city['oceania']=["adelaide-A 阿得雷德-australia|alice-springs-A 艾丽斯斯普林斯-australia|balladonia-B 巴拉多尼亚-australia|bankstown-B 班克斯-australia|sisalana-B 巴朱尔-australia|stanmore-B 宾利-australia|maryfield-B 伯德姆-australia|snug-cove-B 博尔达角-australia|bowral-B 波拉尔-australia|nambucca-heads-B 楠布卡黑兹-australia|blackall-B 布莱科尔-australia|brisbane-B 布里斯班-australia|boulia-B 布利亚-australia|brunette-downs-B 布鲁内特唐斯-australia|boologooro-B 布洛古罗-australia|dubbo-D 达博-australia|darwin-D 达尔文-australia|kalala-D 戴利沃特斯-australia|stock-yards-D 丹德农-australia|dampier-D 丹皮尔-australia|derby-D 德比-australia|dwellingup-D 德韦令阿普-australia|mall-frankston-F 弗兰克斯顿-australia|south-fremantle-F 弗里曼特尔-australia|gayndah-G 盖恩达-australia|gunnedah-G 冈尼达-australia|granite-downs-G 格拉尼特道恩斯-australia|langford-G 戈斯内尔斯-australia|mulyie-G 戈兹沃西-australia|goulburn-G 古尔本-australia|prospect-H 黑镇-australia|heron-island-me-H 赫伦岛-australia|hobart-H 霍巴特-australia|apollo-bay-H 霍登谷-australia|erowal-bay-J 杰维斯湾-australia|yednia-J 吉姆纳-australia|kimberly-downs-J 金伯利唐斯-australia|kingaroy-J 金格罗伊-australia|kalbarri-K 卡尔巴里-australia|kalgoorlie-boulder-K 卡尔古利-australia|kyamba-park-K 凯恩卡塔-australia|kealba-K 凯乐尔-australia|caloundra-K 卡拉德拉-australia|kalamunda-K 卡拉曼达-australia|camooweal-K 卡穆威尔-australia|combienbar-park-K 康比恩巴尔-australia|cunnamulla-K 坎纳马拉-australia|canberra-K 堪培拉-australia|katoomba-K 卡通巴-australia|river-coles-K 科尔斯点-australia|coffs-harbour-K 科夫斯港-australia|corrigin-K 科里金-australia|coober-pedy-K 库伯佩迪-australia|kulgera-K 库尔戈拉-australia|quilpie-K 奎尔皮-australia|kwinana-K 奎纳纳-australia|queanbeyan-K 昆比恩-australia|kununurra-K 库奴纳拉-australia|maryfield-L 拉里马-australia|lameroo-L 拉默鲁-australia|meneling-L 拉姆丛林-australia|lancelin-L 兰斯林-australia|normanville-L 拉皮德湾-australia|mintaro-L 雷德斯代尔-australia|learmonth-L 里尔莫斯-australia|kanbrae-L 鲁穆拉-australia|renmark-L 伦马克-australia|roebourne-L 罗伯恩-australia|rockhampton-L 洛坎普顿-australia|rottnest-island-L 罗特尼斯特岛-australia|marble-bar-M 马布尔巴-australia|macquarie-island-M 麦夸里岛-australia|marla-M 玛拉-australia|corella-park-M 玛丽凯瑟琳-australia|murrurundi-M 马鲁兰迪-australia|mandurah-M 曼德拉-australia|maningrida-M 马宁里达-australia|mataranka-M 马塔兰卡-australia|meekatharra-M 米卡萨拉-australia|milingimbi-M 米灵金比-australia|merbein-M 默宾-australia|melbourne-M 墨尔本-australia|moruya-heads-M 莫鲁亚海兹-australia|nullarbor-N 纳拉伯-australia|naracoorte-N 纳拉库特-australia|tennant-creek-N 滕南特克里克-australia|nyngan-N 宁根-australia|nuriootpa-N 努里乌特帕-australia|norseman-N 诺斯曼-australia|north-parramatta-P 帕拉马塔-australia|goodingnow-P 佩恩斯范恩德-australia|thargomindah-S 萨戈明达-australia|thangoo-S 桑古-australia|perth-S 珀斯-australia|swanbourne-S 斯旺伯恩-australia|sorell-midway-point-S 索雷尔-australia|onslow-T 泰弗纳德岛-australia|mount-divide-T 特尔弗采矿中心-australia|swans-island-me-T 天鹅岛-australia|tibooburra-T 提伯布拉-australia|tindal-sc-T 廷德尔-australia|woodvale-W 旺内鲁-australia|warruwi-W 瓦努韦-australia|victor-harbor-W 维克多港-australia|werris-creek-W 韦里斯溪-australia|walgett-W 沃盖特-australia|woolgoolga-W 伍尔古尔加-australia|wooramel-W 伍拉梅尔-australia|kilmany-park-W 伍鲁克-australia|wollongong-W 伍伦贡-australia|wollogorang-W 伍洛格朗-australia|woomera-W 武麦拉-australia|san-jose-X 谢奥克斯-australia|shepparton-mooroopna-X 谢珀顿-australia|kiama-X 谢尔哈伯-australia|sydney-X 悉尼-australia|alexandra-Y 亚历山德拉-australia|mount-denison-Y 延杜穆-australia|yongala-Y 扬加拉-australia|teetulpa-Y 扬塔-australia|yass-Y 亚斯-australia|yeppoon-Y 耶蓬-australia|elizabeth-nj-Y 伊丽莎白-australia|eudunda-Y 尤丹达-australia|thorner-Y 尤兰丹吉-australia|geelong-Z 哲朗-australia","morobe-M 莫罗贝-papua-new-guinea|samarai-S 萨马赖-papua-new-guinea","matuku-M 马图库-fiji|suva-S 苏瓦-fiji","butaritari-B 布塔里塔里-kiribati|bairiki-T 塔拉瓦-kiribati","adelaide-A 阿得雷德-australia|alice-springs-A 艾丽斯斯普林斯-australia|balladonia-B 巴拉多尼亚-australia|bankstown-B 班克斯-australia|sisalana-B 巴朱尔-australia|stanmore-B 宾利-australia|maryfield-B 伯德姆-australia|snug-cove-B 博尔达角-australia|bowral-B 波拉尔-australia|nambucca-heads-B 楠布卡黑兹-australia|blackall-B 布莱科尔-australia|brisbane-B 布里斯班-australia|boulia-B 布利亚-australia|brunette-downs-B 布鲁内特唐斯-australia|boologooro-B 布洛古罗-australia|dubbo-D 达博-australia|darwin-D 达尔文-australia|kalala-D 戴利沃特斯-australia|stock-yards-D 丹德农-australia|dampier-D 丹皮尔-australia|derby-D 德比-australia|dwellingup-D 德韦令阿普-australia|mall-frankston-F 弗兰克斯顿-australia|south-fremantle-F 弗里曼特尔-australia|gayndah-G 盖恩达-australia|gunnedah-G 冈尼达-australia|granite-downs-G 格拉尼特道恩斯-australia|langford-G 戈斯内尔斯-australia|mulyie-G 戈兹沃西-australia|goulburn-G 古尔本-australia|prospect-H 黑镇-australia|heron-island-me-H 赫伦岛-australia|hobart-H 霍巴特-australia|apollo-bay-H 霍登谷-australia|erowal-bay-J 杰维斯湾-australia|yednia-J 吉姆纳-australia|kimberly-downs-J 金伯利唐斯-australia|kingaroy-J 金格罗伊-australia|kalbarri-K 卡尔巴里-australia|kalgoorlie-boulder-K 卡尔古利-australia|kyamba-park-K 凯恩卡塔-australia|kealba-K 凯乐尔-australia|caloundra-K 卡拉德拉-australia|kalamunda-K 卡拉曼达-australia|camooweal-K 卡穆威尔-australia|combienbar-park-K 康比恩巴尔-australia|cunnamulla-K 坎纳马拉-australia|canberra-K 堪培拉-australia|katoomba-K 卡通巴-australia|river-coles-K 科尔斯点-australia|coffs-harbour-K 科夫斯港-australia|corrigin-K 科里金-australia|coober-pedy-K 库伯佩迪-australia|kulgera-K 库尔戈拉-australia|quilpie-K 奎尔皮-australia|kwinana-K 奎纳纳-australia|queanbeyan-K 昆比恩-australia|kununurra-K 库奴纳拉-australia|maryfield-L 拉里马-australia|lameroo-L 拉默鲁-australia|meneling-L 拉姆丛林-australia|lancelin-L 兰斯林-australia|normanville-L 拉皮德湾-australia|mintaro-L 雷德斯代尔-australia|learmonth-L 里尔莫斯-australia|kanbrae-L 鲁穆拉-australia|renmark-L 伦马克-australia|roebourne-L 罗伯恩-australia|rockhampton-L 洛坎普顿-australia|rottnest-island-L 罗特尼斯特岛-australia|marble-bar-M 马布尔巴-australia|macquarie-island-M 麦夸里岛-australia|marla-M 玛拉-australia|corella-park-M 玛丽凯瑟琳-australia|murrurundi-M 马鲁兰迪-australia|mandurah-M 曼德拉-australia|maningrida-M 马宁里达-australia|mataranka-M 马塔兰卡-australia|meekatharra-M 米卡萨拉-australia|milingimbi-M 米灵金比-australia|merbein-M 默宾-australia|melbourne-M 墨尔本-australia|moruya-heads-M 莫鲁亚海兹-australia|nullarbor-N 纳拉伯-australia|naracoorte-N 纳拉库特-australia|tennant-creek-N 滕南特克里克-australia|nyngan-N 宁根-australia|nuriootpa-N 努里乌特帕-australia|norseman-N 诺斯曼-australia|north-parramatta-P 帕拉马塔-australia|goodingnow-P 佩恩斯范恩德-australia|thargomindah-S 萨戈明达-australia|thangoo-S 桑古-australia|perth-S 珀斯-australia|swanbourne-S 斯旺伯恩-australia|sorell-midway-point-S 索雷尔-australia|onslow-T 泰弗纳德岛-australia|mount-divide-T 特尔弗采矿中心-australia|swans-island-me-T 天鹅岛-australia|tibooburra-T 提伯布拉-australia|tindal-sc-T 廷德尔-australia|woodvale-W 旺内鲁-australia|warruwi-W 瓦努韦-australia|victor-harbor-W 维克多港-australia|werris-creek-W 韦里斯溪-australia|walgett-W 沃盖特-australia|woolgoolga-W 伍尔古尔加-australia|wooramel-W 伍拉梅尔-australia|kilmany-park-W 伍鲁克-australia|wollongong-W 伍伦贡-australia|wollogorang-W 伍洛格朗-australia|woomera-W 武麦拉-australia|san-jose-X 谢奥克斯-australia|shepparton-mooroopna-X 谢珀顿-australia|kiama-X 谢尔哈伯-australia|sydney-X 悉尼-australia|alexandra-Y 亚历山德拉-australia|mount-denison-Y 延杜穆-australia|yongala-Y 扬加拉-australia|teetulpa-Y 扬塔-australia|yass-Y 亚斯-australia|yeppoon-Y 耶蓬-australia|elizabeth-nj-Y 伊丽莎白-australia|eudunda-Y 尤丹达-australia|thorner-Y 尤兰丹吉-australia|geelong-Z 哲朗-australia","honiara-H 霍尼亚拉-solomon","okarito-A 奥卡里托-new-zealand|auckland-A 奥克兰-new-zealand|palmerston-north-B 北帕默斯顿-new-zealand|porirua-B 波里鲁瓦-new-zealand|dunedin-D 达尼丁-new-zealand|greymouth-G 格雷茅斯-new-zealand|hawera-H 哈韦拉-new-zealand|waihola-H 怀霍拉-new-zealand|waiouru-H 怀欧鲁-new-zealand|waipara-H 怀帕拉-new-zealand|waitati-H 怀塔提-new-zealand|waiwera-H 怀韦拉-new-zealand|wellington-H 惠灵顿-new-zealand|hokitika-H 霍基蒂卡-new-zealand|whangarei-J 璜加雷-new-zealand|christchurch-J 基督城-new-zealand|culverden-K 卡尔弗登-new-zealand|kaiapoi-K 凯厄波伊-new-zealand|kaikoura-K 凯库拉-new-zealand|kaitaia-K 凯塔亚-new-zealand|kaniere-K 卡尼里-new-zealand|castlepoint-K 卡斯尔波因特-new-zealand|riccarton-L 里卡顿-new-zealand|rotorua-L 罗托鲁瓦-new-zealand|martinborough-M 马丁堡-new-zealand|makarewa-M 马卡雷瓦-new-zealand|manukau-M 玛努考-new-zealand|masterton-M 马斯特顿-new-zealand|mosgiel-M 摩斯吉尔-new-zealand|papakura-P 帕波库拉-new-zealand|paraparaumu-P 帕拉帕拉乌穆-new-zealand|papatoetoe-P 帕帕托伊托伊-new-zealand|arrowtown-P 普雷-new-zealand|purerua-P 普雷鲁阿-new-zealand|sefton-S 塞夫顿-new-zealand|upper-hutt-S 上哈特-new-zealand|takapuna-T 塔卡普纳-new-zealand|taradale-T 塔拉岱尔-new-zealand|taumarunui-T 陶玛鲁努伊-new-zealand|taupo-T 塔坡-new-zealand|warkworth-W 沃克沃思-new-zealand|lower-hutt-X 下哈特-new-zealand|hicks-bay-X 希克斯湾-new-zealand|invercargill-Y 因弗卡吉尔-new-zealand"]; \ No newline at end of file diff --git "a/web/117 \344\270\212\346\265\267\345\270\202\345\233\276\344\271\246\351\246\206\345\244\247\345\261\217\347\234\213\346\235\277/static/jquery-1.8.3.min.js" "b/web/117 \344\270\212\346\265\267\345\270\202\345\233\276\344\271\246\351\246\206\345\244\247\345\261\217\347\234\213\346\235\277/static/jquery-1.8.3.min.js" new file mode 100644 index 00000000..213d9d33 --- /dev/null +++ "b/web/117 \344\270\212\346\265\267\345\270\202\345\233\276\344\271\246\351\246\206\345\244\247\345\261\217\347\234\213\346\235\277/static/jquery-1.8.3.min.js" @@ -0,0 +1,2 @@ +/*! jQuery v1.8.3 jquery.com | jquery.org/license */ +(function (e, t) { function _ (e) { var t = M[e] = {}; return v.each(e.split(y), function (e, n) { t[n] = !0 }), t } function H (e, n, r) { if (r === t && e.nodeType === 1) { var i = "data-" + n.replace(P, "-$1").toLowerCase(); r = e.getAttribute(i); if (typeof r == "string") { try { r = r === "true" ? !0 : r === "false" ? !1 : r === "null" ? null : +r + "" === r ? +r : D.test(r) ? v.parseJSON(r) : r } catch (s) { } v.data(e, n, r) } else r = t } return r } function B (e) { var t; for (t in e) { if (t === "data" && v.isEmptyObject(e[t])) continue; if (t !== "toJSON") return !1 } return !0 } function et () { return !1 } function tt () { return !0 } function ut (e) { return !e || !e.parentNode || e.parentNode.nodeType === 11 } function at (e, t) { do e = e[t]; while (e && e.nodeType !== 1); return e } function ft (e, t, n) { t = t || 0; if (v.isFunction(t)) return v.grep(e, function (e, r) { var i = !!t.call(e, r, e); return i === n }); if (t.nodeType) return v.grep(e, function (e, r) { return e === t === n }); if (typeof t == "string") { var r = v.grep(e, function (e) { return e.nodeType === 1 }); if (it.test(t)) return v.filter(t, r, !n); t = v.filter(t, r) } return v.grep(e, function (e, r) { return v.inArray(e, t) >= 0 === n }) } function lt (e) { var t = ct.split("|"), n = e.createDocumentFragment(); if (n.createElement) while (t.length) n.createElement(t.pop()); return n } function Lt (e, t) { return e.getElementsByTagName(t)[0] || e.appendChild(e.ownerDocument.createElement(t)) } function At (e, t) { if (t.nodeType !== 1 || !v.hasData(e)) return; var n, r, i, s = v._data(e), o = v._data(t, s), u = s.events; if (u) { delete o.handle, o.events = {}; for (n in u) for (r = 0, i = u[n].length; r < i; r++)v.event.add(t, n, u[n][r]) } o.data && (o.data = v.extend({}, o.data)) } function Ot (e, t) { var n; if (t.nodeType !== 1) return; t.clearAttributes && t.clearAttributes(), t.mergeAttributes && t.mergeAttributes(e), n = t.nodeName.toLowerCase(), n === "object" ? (t.parentNode && (t.outerHTML = e.outerHTML), v.support.html5Clone && e.innerHTML && !v.trim(t.innerHTML) && (t.innerHTML = e.innerHTML)) : n === "input" && Et.test(e.type) ? (t.defaultChecked = t.checked = e.checked, t.value !== e.value && (t.value = e.value)) : n === "option" ? t.selected = e.defaultSelected : n === "input" || n === "textarea" ? t.defaultValue = e.defaultValue : n === "script" && t.text !== e.text && (t.text = e.text), t.removeAttribute(v.expando) } function Mt (e) { return typeof e.getElementsByTagName != "undefined" ? e.getElementsByTagName("*") : typeof e.querySelectorAll != "undefined" ? e.querySelectorAll("*") : [] } function _t (e) { Et.test(e.type) && (e.defaultChecked = e.checked) } function Qt (e, t) { if (t in e) return t; var n = t.charAt(0).toUpperCase() + t.slice(1), r = t, i = Jt.length; while (i--) { t = Jt[i] + n; if (t in e) return t } return r } function Gt (e, t) { return e = t || e, v.css(e, "display") === "none" || !v.contains(e.ownerDocument, e) } function Yt (e, t) { var n, r, i = [], s = 0, o = e.length; for (; s < o; s++) { n = e[s]; if (!n.style) continue; i[s] = v._data(n, "olddisplay"), t ? (!i[s] && n.style.display === "none" && (n.style.display = ""), n.style.display === "" && Gt(n) && (i[s] = v._data(n, "olddisplay", nn(n.nodeName)))) : (r = Dt(n, "display"), !i[s] && r !== "none" && v._data(n, "olddisplay", r)) } for (s = 0; s < o; s++) { n = e[s]; if (!n.style) continue; if (!t || n.style.display === "none" || n.style.display === "") n.style.display = t ? i[s] || "" : "none" } return e } function Zt (e, t, n) { var r = Rt.exec(t); return r ? Math.max(0, r[1] - (n || 0)) + (r[2] || "px") : t } function en (e, t, n, r) { var i = n === (r ? "border" : "content") ? 4 : t === "width" ? 1 : 0, s = 0; for (; i < 4; i += 2)n === "margin" && (s += v.css(e, n + $t[i], !0)), r ? (n === "content" && (s -= parseFloat(Dt(e, "padding" + $t[i])) || 0), n !== "margin" && (s -= parseFloat(Dt(e, "border" + $t[i] + "Width")) || 0)) : (s += parseFloat(Dt(e, "padding" + $t[i])) || 0, n !== "padding" && (s += parseFloat(Dt(e, "border" + $t[i] + "Width")) || 0)); return s } function tn (e, t, n) { var r = t === "width" ? e.offsetWidth : e.offsetHeight, i = !0, s = v.support.boxSizing && v.css(e, "boxSizing") === "border-box"; if (r <= 0 || r == null) { r = Dt(e, t); if (r < 0 || r == null) r = e.style[t]; if (Ut.test(r)) return r; i = s && (v.support.boxSizingReliable || r === e.style[t]), r = parseFloat(r) || 0 } return r + en(e, t, n || (s ? "border" : "content"), i) + "px" } function nn (e) { if (Wt[e]) return Wt[e]; var t = v("<" + e + ">").appendTo(i.body), n = t.css("display"); t.remove(); if (n === "none" || n === "") { Pt = i.body.appendChild(Pt || v.extend(i.createElement("iframe"), { frameBorder: 0, width: 0, height: 0 })); if (!Ht || !Pt.createElement) Ht = (Pt.contentWindow || Pt.contentDocument).document, Ht.write(""), Ht.close(); t = Ht.body.appendChild(Ht.createElement(e)), n = Dt(t, "display"), i.body.removeChild(Pt) } return Wt[e] = n, n } function fn (e, t, n, r) { var i; if (v.isArray(t)) v.each(t, function (t, i) { n || sn.test(e) ? r(e, i) : fn(e + "[" + (typeof i == "object" ? t : "") + "]", i, n, r) }); else if (!n && v.type(t) === "object") for (i in t) fn(e + "[" + i + "]", t[i], n, r); else r(e, t) } function Cn (e) { return function (t, n) { typeof t != "string" && (n = t, t = "*"); var r, i, s, o = t.toLowerCase().split(y), u = 0, a = o.length; if (v.isFunction(n)) for (; u < a; u++)r = o[u], s = /^\+/.test(r), s && (r = r.substr(1) || "*"), i = e[r] = e[r] || [], i[s ? "unshift" : "push"](n) } } function kn (e, n, r, i, s, o) { s = s || n.dataTypes[0], o = o || {}, o[s] = !0; var u, a = e[s], f = 0, l = a ? a.length : 0, c = e === Sn; for (; f < l && (c || !u); f++)u = a[f](n, r, i), typeof u == "string" && (!c || o[u] ? u = t : (n.dataTypes.unshift(u), u = kn(e, n, r, i, u, o))); return (c || !u) && !o["*"] && (u = kn(e, n, r, i, "*", o)), u } function Ln (e, n) { var r, i, s = v.ajaxSettings.flatOptions || {}; for (r in n) n[r] !== t && ((s[r] ? e : i || (i = {}))[r] = n[r]); i && v.extend(!0, e, i) } function An (e, n, r) { var i, s, o, u, a = e.contents, f = e.dataTypes, l = e.responseFields; for (s in l) s in r && (n[l[s]] = r[s]); while (f[0] === "*") f.shift(), i === t && (i = e.mimeType || n.getResponseHeader("content-type")); if (i) for (s in a) if (a[s] && a[s].test(i)) { f.unshift(s); break } if (f[0] in r) o = f[0]; else { for (s in r) { if (!f[0] || e.converters[s + " " + f[0]]) { o = s; break } u || (u = s) } o = o || u } if (o) return o !== f[0] && f.unshift(o), r[o] } function On (e, t) { var n, r, i, s, o = e.dataTypes.slice(), u = o[0], a = {}, f = 0; e.dataFilter && (t = e.dataFilter(t, e.dataType)); if (o[1]) for (n in e.converters) a[n.toLowerCase()] = e.converters[n]; for (; i = o[++f];)if (i !== "*") { if (u !== "*" && u !== i) { n = a[u + " " + i] || a["* " + i]; if (!n) for (r in a) { s = r.split(" "); if (s[1] === i) { n = a[u + " " + s[0]] || a["* " + s[0]]; if (n) { n === !0 ? n = a[r] : a[r] !== !0 && (i = s[0], o.splice(f--, 0, i)); break } } } if (n !== !0) if (n && e["throws"]) t = n(t); else try { t = n(t) } catch (l) { return { state: "parsererror", error: n ? l : "No conversion from " + u + " to " + i } } } u = i } return { state: "success", data: t } } function Fn () { try { return new e.XMLHttpRequest } catch (t) { } } function In () { try { return new e.ActiveXObject("Microsoft.XMLHTTP") } catch (t) { } } function $n () { return setTimeout(function () { qn = t }, 0), qn = v.now() } function Jn (e, t) { v.each(t, function (t, n) { var r = (Vn[t] || []).concat(Vn["*"]), i = 0, s = r.length; for (; i < s; i++)if (r[i].call(e, t, n)) return }) } function Kn (e, t, n) { var r, i = 0, s = 0, o = Xn.length, u = v.Deferred().always(function () { delete a.elem }), a = function () { var t = qn || $n(), n = Math.max(0, f.startTime + f.duration - t), r = n / f.duration || 0, i = 1 - r, s = 0, o = f.tweens.length; for (; s < o; s++)f.tweens[s].run(i); return u.notifyWith(e, [f, i, n]), i < 1 && o ? n : (u.resolveWith(e, [f]), !1) }, f = u.promise({ elem: e, props: v.extend({}, t), opts: v.extend(!0, { specialEasing: {} }, n), originalProperties: t, originalOptions: n, startTime: qn || $n(), duration: n.duration, tweens: [], createTween: function (t, n, r) { var i = v.Tween(e, f.opts, t, n, f.opts.specialEasing[t] || f.opts.easing); return f.tweens.push(i), i }, stop: function (t) { var n = 0, r = t ? f.tweens.length : 0; for (; n < r; n++)f.tweens[n].run(1); return t ? u.resolveWith(e, [f, t]) : u.rejectWith(e, [f, t]), this } }), l = f.props; Qn(l, f.opts.specialEasing); for (; i < o; i++) { r = Xn[i].call(f, e, l, f.opts); if (r) return r } return Jn(f, l), v.isFunction(f.opts.start) && f.opts.start.call(e, f), v.fx.timer(v.extend(a, { anim: f, queue: f.opts.queue, elem: e })), f.progress(f.opts.progress).done(f.opts.done, f.opts.complete).fail(f.opts.fail).always(f.opts.always) } function Qn (e, t) { var n, r, i, s, o; for (n in e) { r = v.camelCase(n), i = t[r], s = e[n], v.isArray(s) && (i = s[1], s = e[n] = s[0]), n !== r && (e[r] = s, delete e[n]), o = v.cssHooks[r]; if (o && "expand" in o) { s = o.expand(s), delete e[r]; for (n in s) n in e || (e[n] = s[n], t[n] = i) } else t[r] = i } } function Gn (e, t, n) { var r, i, s, o, u, a, f, l, c, h = this, p = e.style, d = {}, m = [], g = e.nodeType && Gt(e); n.queue || (l = v._queueHooks(e, "fx"), l.unqueued == null && (l.unqueued = 0, c = l.empty.fire, l.empty.fire = function () { l.unqueued || c() }), l.unqueued++, h.always(function () { h.always(function () { l.unqueued--, v.queue(e, "fx").length || l.empty.fire() }) })), e.nodeType === 1 && ("height" in t || "width" in t) && (n.overflow = [p.overflow, p.overflowX, p.overflowY], v.css(e, "display") === "inline" && v.css(e, "float") === "none" && (!v.support.inlineBlockNeedsLayout || nn(e.nodeName) === "inline" ? p.display = "inline-block" : p.zoom = 1)), n.overflow && (p.overflow = "hidden", v.support.shrinkWrapBlocks || h.done(function () { p.overflow = n.overflow[0], p.overflowX = n.overflow[1], p.overflowY = n.overflow[2] })); for (r in t) { s = t[r]; if (Un.exec(s)) { delete t[r], a = a || s === "toggle"; if (s === (g ? "hide" : "show")) continue; m.push(r) } } o = m.length; if (o) { u = v._data(e, "fxshow") || v._data(e, "fxshow", {}), "hidden" in u && (g = u.hidden), a && (u.hidden = !g), g ? v(e).show() : h.done(function () { v(e).hide() }), h.done(function () { var t; v.removeData(e, "fxshow", !0); for (t in d) v.style(e, t, d[t]) }); for (r = 0; r < o; r++)i = m[r], f = h.createTween(i, g ? u[i] : 0), d[i] = u[i] || v.style(e, i), i in u || (u[i] = f.start, g && (f.end = f.start, f.start = i === "width" || i === "height" ? 1 : 0)) } } function Yn (e, t, n, r, i) { return new Yn.prototype.init(e, t, n, r, i) } function Zn (e, t) { var n, r = { height: e }, i = 0; t = t ? 1 : 0; for (; i < 4; i += 2 - t)n = $t[i], r["margin" + n] = r["padding" + n] = e; return t && (r.opacity = r.width = e), r } function tr (e) { return v.isWindow(e) ? e : e.nodeType === 9 ? e.defaultView || e.parentWindow : !1 } var n, r, i = e.document, s = e.location, o = e.navigator, u = e.jQuery, a = e.$, f = Array.prototype.push, l = Array.prototype.slice, c = Array.prototype.indexOf, h = Object.prototype.toString, p = Object.prototype.hasOwnProperty, d = String.prototype.trim, v = function (e, t) { return new v.fn.init(e, t, n) }, m = /[\-+]?(?:\d*\.|)\d+(?:[eE][\-+]?\d+|)/.source, g = /\S/, y = /\s+/, b = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, w = /^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/, E = /^<(\w+)\s*\/?>(?:<\/\1>|)$/, S = /^[\],:{}\s]*$/, x = /(?:^|:|,)(?:\s*\[)+/g, T = /\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g, N = /"[^"\\\r\n]*"|true|false|null|-?(?:\d\d*\.|)\d+(?:[eE][\-+]?\d+|)/g, C = /^-ms-/, k = /-([\da-z])/gi, L = function (e, t) { return (t + "").toUpperCase() }, A = function () { i.addEventListener ? (i.removeEventListener("DOMContentLoaded", A, !1), v.ready()) : i.readyState === "complete" && (i.detachEvent("onreadystatechange", A), v.ready()) }, O = {}; v.fn = v.prototype = { constructor: v, init: function (e, n, r) { var s, o, u, a; if (!e) return this; if (e.nodeType) return this.context = this[0] = e, this.length = 1, this; if (typeof e == "string") { e.charAt(0) === "<" && e.charAt(e.length - 1) === ">" && e.length >= 3 ? s = [null, e, null] : s = w.exec(e); if (s && (s[1] || !n)) { if (s[1]) return n = n instanceof v ? n[0] : n, a = n && n.nodeType ? n.ownerDocument || n : i, e = v.parseHTML(s[1], a, !0), E.test(s[1]) && v.isPlainObject(n) && this.attr.call(e, n, !0), v.merge(this, e); o = i.getElementById(s[2]); if (o && o.parentNode) { if (o.id !== s[2]) return r.find(e); this.length = 1, this[0] = o } return this.context = i, this.selector = e, this } return !n || n.jquery ? (n || r).find(e) : this.constructor(n).find(e) } return v.isFunction(e) ? r.ready(e) : (e.selector !== t && (this.selector = e.selector, this.context = e.context), v.makeArray(e, this)) }, selector: "", jquery: "1.8.3", length: 0, size: function () { return this.length }, toArray: function () { return l.call(this) }, get: function (e) { return e == null ? this.toArray() : e < 0 ? this[this.length + e] : this[e] }, pushStack: function (e, t, n) { var r = v.merge(this.constructor(), e); return r.prevObject = this, r.context = this.context, t === "find" ? r.selector = this.selector + (this.selector ? " " : "") + n : t && (r.selector = this.selector + "." + t + "(" + n + ")"), r }, each: function (e, t) { return v.each(this, e, t) }, ready: function (e) { return v.ready.promise().done(e), this }, eq: function (e) { return e = +e, e === -1 ? this.slice(e) : this.slice(e, e + 1) }, first: function () { return this.eq(0) }, last: function () { return this.eq(-1) }, slice: function () { return this.pushStack(l.apply(this, arguments), "slice", l.call(arguments).join(",")) }, map: function (e) { return this.pushStack(v.map(this, function (t, n) { return e.call(t, n, t) })) }, end: function () { return this.prevObject || this.constructor(null) }, push: f, sort: [].sort, splice: [].splice }, v.fn.init.prototype = v.fn, v.extend = v.fn.extend = function () { var e, n, r, i, s, o, u = arguments[0] || {}, a = 1, f = arguments.length, l = !1; typeof u == "boolean" && (l = u, u = arguments[1] || {}, a = 2), typeof u != "object" && !v.isFunction(u) && (u = {}), f === a && (u = this, --a); for (; a < f; a++)if ((e = arguments[a]) != null) for (n in e) { r = u[n], i = e[n]; if (u === i) continue; l && i && (v.isPlainObject(i) || (s = v.isArray(i))) ? (s ? (s = !1, o = r && v.isArray(r) ? r : []) : o = r && v.isPlainObject(r) ? r : {}, u[n] = v.extend(l, o, i)) : i !== t && (u[n] = i) } return u }, v.extend({ noConflict: function (t) { return e.$ === v && (e.$ = a), t && e.jQuery === v && (e.jQuery = u), v }, isReady: !1, readyWait: 1, holdReady: function (e) { e ? v.readyWait++ : v.ready(!0) }, ready: function (e) { if (e === !0 ? --v.readyWait : v.isReady) return; if (!i.body) return setTimeout(v.ready, 1); v.isReady = !0; if (e !== !0 && --v.readyWait > 0) return; r.resolveWith(i, [v]), v.fn.trigger && v(i).trigger("ready").off("ready") }, isFunction: function (e) { return v.type(e) === "function" }, isArray: Array.isArray || function (e) { return v.type(e) === "array" }, isWindow: function (e) { return e != null && e == e.window }, isNumeric: function (e) { return !isNaN(parseFloat(e)) && isFinite(e) }, type: function (e) { return e == null ? String(e) : O[h.call(e)] || "object" }, isPlainObject: function (e) { if (!e || v.type(e) !== "object" || e.nodeType || v.isWindow(e)) return !1; try { if (e.constructor && !p.call(e, "constructor") && !p.call(e.constructor.prototype, "isPrototypeOf")) return !1 } catch (n) { return !1 } var r; for (r in e); return r === t || p.call(e, r) }, isEmptyObject: function (e) { var t; for (t in e) return !1; return !0 }, error: function (e) { throw new Error(e) }, parseHTML: function (e, t, n) { var r; return !e || typeof e != "string" ? null : (typeof t == "boolean" && (n = t, t = 0), t = t || i, (r = E.exec(e)) ? [t.createElement(r[1])] : (r = v.buildFragment([e], t, n ? null : []), v.merge([], (r.cacheable ? v.clone(r.fragment) : r.fragment).childNodes))) }, parseJSON: function (t) { if (!t || typeof t != "string") return null; t = v.trim(t); if (e.JSON && e.JSON.parse) return e.JSON.parse(t); if (S.test(t.replace(T, "@").replace(N, "]").replace(x, ""))) return (new Function("return " + t))(); v.error("Invalid JSON: " + t) }, parseXML: function (n) { var r, i; if (!n || typeof n != "string") return null; try { e.DOMParser ? (i = new DOMParser, r = i.parseFromString(n, "text/xml")) : (r = new ActiveXObject("Microsoft.XMLDOM"), r.async = "false", r.loadXML(n)) } catch (s) { r = t } return (!r || !r.documentElement || r.getElementsByTagName("parsererror").length) && v.error("Invalid XML: " + n), r }, noop: function () { }, globalEval: function (t) { t && g.test(t) && (e.execScript || function (t) { e.eval.call(e, t) })(t) }, camelCase: function (e) { return e.replace(C, "ms-").replace(k, L) }, nodeName: function (e, t) { return e.nodeName && e.nodeName.toLowerCase() === t.toLowerCase() }, each: function (e, n, r) { var i, s = 0, o = e.length, u = o === t || v.isFunction(e); if (r) { if (u) { for (i in e) if (n.apply(e[i], r) === !1) break } else for (; s < o;)if (n.apply(e[s++], r) === !1) break } else if (u) { for (i in e) if (n.call(e[i], i, e[i]) === !1) break } else for (; s < o;)if (n.call(e[s], s, e[s++]) === !1) break; return e }, trim: d && !d.call("\ufeff\u00a0") ? function (e) { return e == null ? "" : d.call(e) } : function (e) { return e == null ? "" : (e + "").replace(b, "") }, makeArray: function (e, t) { var n, r = t || []; return e != null && (n = v.type(e), e.length == null || n === "string" || n === "function" || n === "regexp" || v.isWindow(e) ? f.call(r, e) : v.merge(r, e)), r }, inArray: function (e, t, n) { var r; if (t) { if (c) return c.call(t, e, n); r = t.length, n = n ? n < 0 ? Math.max(0, r + n) : n : 0; for (; n < r; n++)if (n in t && t[n] === e) return n } return -1 }, merge: function (e, n) { var r = n.length, i = e.length, s = 0; if (typeof r == "number") for (; s < r; s++)e[i++] = n[s]; else while (n[s] !== t) e[i++] = n[s++]; return e.length = i, e }, grep: function (e, t, n) { var r, i = [], s = 0, o = e.length; n = !!n; for (; s < o; s++)r = !!t(e[s], s), n !== r && i.push(e[s]); return i }, map: function (e, n, r) { var i, s, o = [], u = 0, a = e.length, f = e instanceof v || a !== t && typeof a == "number" && (a > 0 && e[0] && e[a - 1] || a === 0 || v.isArray(e)); if (f) for (; u < a; u++)i = n(e[u], u, r), i != null && (o[o.length] = i); else for (s in e) i = n(e[s], s, r), i != null && (o[o.length] = i); return o.concat.apply([], o) }, guid: 1, proxy: function (e, n) { var r, i, s; return typeof n == "string" && (r = e[n], n = e, e = r), v.isFunction(e) ? (i = l.call(arguments, 2), s = function () { return e.apply(n, i.concat(l.call(arguments))) }, s.guid = e.guid = e.guid || v.guid++, s) : t }, access: function (e, n, r, i, s, o, u) { var a, f = r == null, l = 0, c = e.length; if (r && typeof r == "object") { for (l in r) v.access(e, n, l, r[l], 1, o, i); s = 1 } else if (i !== t) { a = u === t && v.isFunction(i), f && (a ? (a = n, n = function (e, t, n) { return a.call(v(e), n) }) : (n.call(e, i), n = null)); if (n) for (; l < c; l++)n(e[l], r, a ? i.call(e[l], l, n(e[l], r)) : i, u); s = 1 } return s ? e : f ? n.call(e) : c ? n(e[0], r) : o }, now: function () { return (new Date).getTime() } }), v.ready.promise = function (t) { if (!r) { r = v.Deferred(); if (i.readyState === "complete") setTimeout(v.ready, 1); else if (i.addEventListener) i.addEventListener("DOMContentLoaded", A, !1), e.addEventListener("load", v.ready, !1); else { i.attachEvent("onreadystatechange", A), e.attachEvent("onload", v.ready); var n = !1; try { n = e.frameElement == null && i.documentElement } catch (s) { } n && n.doScroll && function o () { if (!v.isReady) { try { n.doScroll("left") } catch (e) { return setTimeout(o, 50) } v.ready() } }() } } return r.promise(t) }, v.each("Boolean Number String Function Array Date RegExp Object".split(" "), function (e, t) { O["[object " + t + "]"] = t.toLowerCase() }), n = v(i); var M = {}; v.Callbacks = function (e) { e = typeof e == "string" ? M[e] || _(e) : v.extend({}, e); var n, r, i, s, o, u, a = [], f = !e.once && [], l = function (t) { n = e.memory && t, r = !0, u = s || 0, s = 0, o = a.length, i = !0; for (; a && u < o; u++)if (a[u].apply(t[0], t[1]) === !1 && e.stopOnFalse) { n = !1; break } i = !1, a && (f ? f.length && l(f.shift()) : n ? a = [] : c.disable()) }, c = { add: function () { if (a) { var t = a.length; (function r (t) { v.each(t, function (t, n) { var i = v.type(n); i === "function" ? (!e.unique || !c.has(n)) && a.push(n) : n && n.length && i !== "string" && r(n) }) })(arguments), i ? o = a.length : n && (s = t, l(n)) } return this }, remove: function () { return a && v.each(arguments, function (e, t) { var n; while ((n = v.inArray(t, a, n)) > -1) a.splice(n, 1), i && (n <= o && o--, n <= u && u--) }), this }, has: function (e) { return v.inArray(e, a) > -1 }, empty: function () { return a = [], this }, disable: function () { return a = f = n = t, this }, disabled: function () { return !a }, lock: function () { return f = t, n || c.disable(), this }, locked: function () { return !f }, fireWith: function (e, t) { return t = t || [], t = [e, t.slice ? t.slice() : t], a && (!r || f) && (i ? f.push(t) : l(t)), this }, fire: function () { return c.fireWith(this, arguments), this }, fired: function () { return !!r } }; return c }, v.extend({ Deferred: function (e) { var t = [["resolve", "done", v.Callbacks("once memory"), "resolved"], ["reject", "fail", v.Callbacks("once memory"), "rejected"], ["notify", "progress", v.Callbacks("memory")]], n = "pending", r = { state: function () { return n }, always: function () { return i.done(arguments).fail(arguments), this }, then: function () { var e = arguments; return v.Deferred(function (n) { v.each(t, function (t, r) { var s = r[0], o = e[t]; i[r[1]](v.isFunction(o) ? function () { var e = o.apply(this, arguments); e && v.isFunction(e.promise) ? e.promise().done(n.resolve).fail(n.reject).progress(n.notify) : n[s + "With"](this === i ? n : this, [e]) } : n[s]) }), e = null }).promise() }, promise: function (e) { return e != null ? v.extend(e, r) : r } }, i = {}; return r.pipe = r.then, v.each(t, function (e, s) { var o = s[2], u = s[3]; r[s[1]] = o.add, u && o.add(function () { n = u }, t[e ^ 1][2].disable, t[2][2].lock), i[s[0]] = o.fire, i[s[0] + "With"] = o.fireWith }), r.promise(i), e && e.call(i, i), i }, when: function (e) { var t = 0, n = l.call(arguments), r = n.length, i = r !== 1 || e && v.isFunction(e.promise) ? r : 0, s = i === 1 ? e : v.Deferred(), o = function (e, t, n) { return function (r) { t[e] = this, n[e] = arguments.length > 1 ? l.call(arguments) : r, n === u ? s.notifyWith(t, n) : --i || s.resolveWith(t, n) } }, u, a, f; if (r > 1) { u = new Array(r), a = new Array(r), f = new Array(r); for (; t < r; t++)n[t] && v.isFunction(n[t].promise) ? n[t].promise().done(o(t, f, n)).fail(s.reject).progress(o(t, a, u)) : --i } return i || s.resolveWith(f, n), s.promise() } }), v.support = function () { var t, n, r, s, o, u, a, f, l, c, h, p = i.createElement("div"); p.setAttribute("className", "t"), p.innerHTML = "
    a", n = p.getElementsByTagName("*"), r = p.getElementsByTagName("a")[0]; if (!n || !r || !n.length) return {}; s = i.createElement("select"), o = s.appendChild(i.createElement("option")), u = p.getElementsByTagName("input")[0], r.style.cssText = "top:1px;float:left;opacity:.5", t = { leadingWhitespace: p.firstChild.nodeType === 3, tbody: !p.getElementsByTagName("tbody").length, htmlSerialize: !!p.getElementsByTagName("link").length, style: /top/.test(r.getAttribute("style")), hrefNormalized: r.getAttribute("href") === "/a", opacity: /^0.5/.test(r.style.opacity), cssFloat: !!r.style.cssFloat, checkOn: u.value === "on", optSelected: o.selected, getSetAttribute: p.className !== "t", enctype: !!i.createElement("form").enctype, html5Clone: i.createElement("nav").cloneNode(!0).outerHTML !== "<:nav>", boxModel: i.compatMode === "CSS1Compat", submitBubbles: !0, changeBubbles: !0, focusinBubbles: !1, deleteExpando: !0, noCloneEvent: !0, inlineBlockNeedsLayout: !1, shrinkWrapBlocks: !1, reliableMarginRight: !0, boxSizingReliable: !0, pixelPosition: !1 }, u.checked = !0, t.noCloneChecked = u.cloneNode(!0).checked, s.disabled = !0, t.optDisabled = !o.disabled; try { delete p.test } catch (d) { t.deleteExpando = !1 } !p.addEventListener && p.attachEvent && p.fireEvent && (p.attachEvent("onclick", h = function () { t.noCloneEvent = !1 }), p.cloneNode(!0).fireEvent("onclick"), p.detachEvent("onclick", h)), u = i.createElement("input"), u.value = "t", u.setAttribute("type", "radio"), t.radioValue = u.value === "t", u.setAttribute("checked", "checked"), u.setAttribute("name", "t"), p.appendChild(u), a = i.createDocumentFragment(), a.appendChild(p.lastChild), t.checkClone = a.cloneNode(!0).cloneNode(!0).lastChild.checked, t.appendChecked = u.checked, a.removeChild(u), a.appendChild(p); if (p.attachEvent) for (l in { submit: !0, change: !0, focusin: !0 }) f = "on" + l, c = f in p, c || (p.setAttribute(f, "return;"), c = typeof p[f] == "function"), t[l + "Bubbles"] = c; return v(function () { var n, r, s, o, u = "padding:0;margin:0;border:0;display:block;overflow:hidden;", a = i.getElementsByTagName("body")[0]; if (!a) return; n = i.createElement("div"), n.style.cssText = "visibility:hidden;border:0;width:0;height:0;position:static;top:0;margin-top:1px", a.insertBefore(n, a.firstChild), r = i.createElement("div"), n.appendChild(r), r.innerHTML = "
    t
    ", s = r.getElementsByTagName("td"), s[0].style.cssText = "padding:0;margin:0;border:0;display:none", c = s[0].offsetHeight === 0, s[0].style.display = "", s[1].style.display = "none", t.reliableHiddenOffsets = c && s[0].offsetHeight === 0, r.innerHTML = "", r.style.cssText = "box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;", t.boxSizing = r.offsetWidth === 4, t.doesNotIncludeMarginInBodyOffset = a.offsetTop !== 1, e.getComputedStyle && (t.pixelPosition = (e.getComputedStyle(r, null) || {}).top !== "1%", t.boxSizingReliable = (e.getComputedStyle(r, null) || { width: "4px" }).width === "4px", o = i.createElement("div"), o.style.cssText = r.style.cssText = u, o.style.marginRight = o.style.width = "0", r.style.width = "1px", r.appendChild(o), t.reliableMarginRight = !parseFloat((e.getComputedStyle(o, null) || {}).marginRight)), typeof r.style.zoom != "undefined" && (r.innerHTML = "", r.style.cssText = u + "width:1px;padding:1px;display:inline;zoom:1", t.inlineBlockNeedsLayout = r.offsetWidth === 3, r.style.display = "block", r.style.overflow = "visible", r.innerHTML = "
    ", r.firstChild.style.width = "5px", t.shrinkWrapBlocks = r.offsetWidth !== 3, n.style.zoom = 1), a.removeChild(n), n = r = s = o = null }), a.removeChild(p), n = r = s = o = u = a = p = null, t }(); var D = /(?:\{[\s\S]*\}|\[[\s\S]*\])$/, P = /([A-Z])/g; v.extend({ cache: {}, deletedIds: [], uuid: 0, expando: "jQuery" + (v.fn.jquery + Math.random()).replace(/\D/g, ""), noData: { embed: !0, object: "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000", applet: !0 }, hasData: function (e) { return e = e.nodeType ? v.cache[e[v.expando]] : e[v.expando], !!e && !B(e) }, data: function (e, n, r, i) { if (!v.acceptData(e)) return; var s, o, u = v.expando, a = typeof n == "string", f = e.nodeType, l = f ? v.cache : e, c = f ? e[u] : e[u] && u; if ((!c || !l[c] || !i && !l[c].data) && a && r === t) return; c || (f ? e[u] = c = v.deletedIds.pop() || v.guid++ : c = u), l[c] || (l[c] = {}, f || (l[c].toJSON = v.noop)); if (typeof n == "object" || typeof n == "function") i ? l[c] = v.extend(l[c], n) : l[c].data = v.extend(l[c].data, n); return s = l[c], i || (s.data || (s.data = {}), s = s.data), r !== t && (s[v.camelCase(n)] = r), a ? (o = s[n], o == null && (o = s[v.camelCase(n)])) : o = s, o }, removeData: function (e, t, n) { if (!v.acceptData(e)) return; var r, i, s, o = e.nodeType, u = o ? v.cache : e, a = o ? e[v.expando] : v.expando; if (!u[a]) return; if (t) { r = n ? u[a] : u[a].data; if (r) { v.isArray(t) || (t in r ? t = [t] : (t = v.camelCase(t), t in r ? t = [t] : t = t.split(" "))); for (i = 0, s = t.length; i < s; i++)delete r[t[i]]; if (!(n ? B : v.isEmptyObject)(r)) return } } if (!n) { delete u[a].data; if (!B(u[a])) return } o ? v.cleanData([e], !0) : v.support.deleteExpando || u != u.window ? delete u[a] : u[a] = null }, _data: function (e, t, n) { return v.data(e, t, n, !0) }, acceptData: function (e) { var t = e.nodeName && v.noData[e.nodeName.toLowerCase()]; return !t || t !== !0 && e.getAttribute("classid") === t } }), v.fn.extend({ data: function (e, n) { var r, i, s, o, u, a = this[0], f = 0, l = null; if (e === t) { if (this.length) { l = v.data(a); if (a.nodeType === 1 && !v._data(a, "parsedAttrs")) { s = a.attributes; for (u = s.length; f < u; f++)o = s[f].name, o.indexOf("data-") || (o = v.camelCase(o.substring(5)), H(a, o, l[o])); v._data(a, "parsedAttrs", !0) } } return l } return typeof e == "object" ? this.each(function () { v.data(this, e) }) : (r = e.split(".", 2), r[1] = r[1] ? "." + r[1] : "", i = r[1] + "!", v.access(this, function (n) { if (n === t) return l = this.triggerHandler("getData" + i, [r[0]]), l === t && a && (l = v.data(a, e), l = H(a, e, l)), l === t && r[1] ? this.data(r[0]) : l; r[1] = n, this.each(function () { var t = v(this); t.triggerHandler("setData" + i, r), v.data(this, e, n), t.triggerHandler("changeData" + i, r) }) }, null, n, arguments.length > 1, null, !1)) }, removeData: function (e) { return this.each(function () { v.removeData(this, e) }) } }), v.extend({ queue: function (e, t, n) { var r; if (e) return t = (t || "fx") + "queue", r = v._data(e, t), n && (!r || v.isArray(n) ? r = v._data(e, t, v.makeArray(n)) : r.push(n)), r || [] }, dequeue: function (e, t) { t = t || "fx"; var n = v.queue(e, t), r = n.length, i = n.shift(), s = v._queueHooks(e, t), o = function () { v.dequeue(e, t) }; i === "inprogress" && (i = n.shift(), r--), i && (t === "fx" && n.unshift("inprogress"), delete s.stop, i.call(e, o, s)), !r && s && s.empty.fire() }, _queueHooks: function (e, t) { var n = t + "queueHooks"; return v._data(e, n) || v._data(e, n, { empty: v.Callbacks("once memory").add(function () { v.removeData(e, t + "queue", !0), v.removeData(e, n, !0) }) }) } }), v.fn.extend({ queue: function (e, n) { var r = 2; return typeof e != "string" && (n = e, e = "fx", r--), arguments.length < r ? v.queue(this[0], e) : n === t ? this : this.each(function () { var t = v.queue(this, e, n); v._queueHooks(this, e), e === "fx" && t[0] !== "inprogress" && v.dequeue(this, e) }) }, dequeue: function (e) { return this.each(function () { v.dequeue(this, e) }) }, delay: function (e, t) { return e = v.fx ? v.fx.speeds[e] || e : e, t = t || "fx", this.queue(t, function (t, n) { var r = setTimeout(t, e); n.stop = function () { clearTimeout(r) } }) }, clearQueue: function (e) { return this.queue(e || "fx", []) }, promise: function (e, n) { var r, i = 1, s = v.Deferred(), o = this, u = this.length, a = function () { --i || s.resolveWith(o, [o]) }; typeof e != "string" && (n = e, e = t), e = e || "fx"; while (u--) r = v._data(o[u], e + "queueHooks"), r && r.empty && (i++, r.empty.add(a)); return a(), s.promise(n) } }); var j, F, I, q = /[\t\r\n]/g, R = /\r/g, U = /^(?:button|input)$/i, z = /^(?:button|input|object|select|textarea)$/i, W = /^a(?:rea|)$/i, X = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i, V = v.support.getSetAttribute; v.fn.extend({ attr: function (e, t) { return v.access(this, v.attr, e, t, arguments.length > 1) }, removeAttr: function (e) { return this.each(function () { v.removeAttr(this, e) }) }, prop: function (e, t) { return v.access(this, v.prop, e, t, arguments.length > 1) }, removeProp: function (e) { return e = v.propFix[e] || e, this.each(function () { try { this[e] = t, delete this[e] } catch (n) { } }) }, addClass: function (e) { var t, n, r, i, s, o, u; if (v.isFunction(e)) return this.each(function (t) { v(this).addClass(e.call(this, t, this.className)) }); if (e && typeof e == "string") { t = e.split(y); for (n = 0, r = this.length; n < r; n++) { i = this[n]; if (i.nodeType === 1) if (!i.className && t.length === 1) i.className = e; else { s = " " + i.className + " "; for (o = 0, u = t.length; o < u; o++)s.indexOf(" " + t[o] + " ") < 0 && (s += t[o] + " "); i.className = v.trim(s) } } } return this }, removeClass: function (e) { var n, r, i, s, o, u, a; if (v.isFunction(e)) return this.each(function (t) { v(this).removeClass(e.call(this, t, this.className)) }); if (e && typeof e == "string" || e === t) { n = (e || "").split(y); for (u = 0, a = this.length; u < a; u++) { i = this[u]; if (i.nodeType === 1 && i.className) { r = (" " + i.className + " ").replace(q, " "); for (s = 0, o = n.length; s < o; s++)while (r.indexOf(" " + n[s] + " ") >= 0) r = r.replace(" " + n[s] + " ", " "); i.className = e ? v.trim(r) : "" } } } return this }, toggleClass: function (e, t) { var n = typeof e, r = typeof t == "boolean"; return v.isFunction(e) ? this.each(function (n) { v(this).toggleClass(e.call(this, n, this.className, t), t) }) : this.each(function () { if (n === "string") { var i, s = 0, o = v(this), u = t, a = e.split(y); while (i = a[s++]) u = r ? u : !o.hasClass(i), o[u ? "addClass" : "removeClass"](i) } else if (n === "undefined" || n === "boolean") this.className && v._data(this, "__className__", this.className), this.className = this.className || e === !1 ? "" : v._data(this, "__className__") || "" }) }, hasClass: function (e) { var t = " " + e + " ", n = 0, r = this.length; for (; n < r; n++)if (this[n].nodeType === 1 && (" " + this[n].className + " ").replace(q, " ").indexOf(t) >= 0) return !0; return !1 }, val: function (e) { var n, r, i, s = this[0]; if (!arguments.length) { if (s) return n = v.valHooks[s.type] || v.valHooks[s.nodeName.toLowerCase()], n && "get" in n && (r = n.get(s, "value")) !== t ? r : (r = s.value, typeof r == "string" ? r.replace(R, "") : r == null ? "" : r); return } return i = v.isFunction(e), this.each(function (r) { var s, o = v(this); if (this.nodeType !== 1) return; i ? s = e.call(this, r, o.val()) : s = e, s == null ? s = "" : typeof s == "number" ? s += "" : v.isArray(s) && (s = v.map(s, function (e) { return e == null ? "" : e + "" })), n = v.valHooks[this.type] || v.valHooks[this.nodeName.toLowerCase()]; if (!n || !("set" in n) || n.set(this, s, "value") === t) this.value = s }) } }), v.extend({ valHooks: { option: { get: function (e) { var t = e.attributes.value; return !t || t.specified ? e.value : e.text } }, select: { get: function (e) { var t, n, r = e.options, i = e.selectedIndex, s = e.type === "select-one" || i < 0, o = s ? null : [], u = s ? i + 1 : r.length, a = i < 0 ? u : s ? i : 0; for (; a < u; a++) { n = r[a]; if ((n.selected || a === i) && (v.support.optDisabled ? !n.disabled : n.getAttribute("disabled") === null) && (!n.parentNode.disabled || !v.nodeName(n.parentNode, "optgroup"))) { t = v(n).val(); if (s) return t; o.push(t) } } return o }, set: function (e, t) { var n = v.makeArray(t); return v(e).find("option").each(function () { this.selected = v.inArray(v(this).val(), n) >= 0 }), n.length || (e.selectedIndex = -1), n } } }, attrFn: {}, attr: function (e, n, r, i) { var s, o, u, a = e.nodeType; if (!e || a === 3 || a === 8 || a === 2) return; if (i && v.isFunction(v.fn[n])) return v(e)[n](r); if (typeof e.getAttribute == "undefined") return v.prop(e, n, r); u = a !== 1 || !v.isXMLDoc(e), u && (n = n.toLowerCase(), o = v.attrHooks[n] || (X.test(n) ? F : j)); if (r !== t) { if (r === null) { v.removeAttr(e, n); return } return o && "set" in o && u && (s = o.set(e, r, n)) !== t ? s : (e.setAttribute(n, r + ""), r) } return o && "get" in o && u && (s = o.get(e, n)) !== null ? s : (s = e.getAttribute(n), s === null ? t : s) }, removeAttr: function (e, t) { var n, r, i, s, o = 0; if (t && e.nodeType === 1) { r = t.split(y); for (; o < r.length; o++)i = r[o], i && (n = v.propFix[i] || i, s = X.test(i), s || v.attr(e, i, ""), e.removeAttribute(V ? i : n), s && n in e && (e[n] = !1)) } }, attrHooks: { type: { set: function (e, t) { if (U.test(e.nodeName) && e.parentNode) v.error("type property can't be changed"); else if (!v.support.radioValue && t === "radio" && v.nodeName(e, "input")) { var n = e.value; return e.setAttribute("type", t), n && (e.value = n), t } } }, value: { get: function (e, t) { return j && v.nodeName(e, "button") ? j.get(e, t) : t in e ? e.value : null }, set: function (e, t, n) { if (j && v.nodeName(e, "button")) return j.set(e, t, n); e.value = t } } }, propFix: { tabindex: "tabIndex", readonly: "readOnly", "for": "htmlFor", "class": "className", maxlength: "maxLength", cellspacing: "cellSpacing", cellpadding: "cellPadding", rowspan: "rowSpan", colspan: "colSpan", usemap: "useMap", frameborder: "frameBorder", contenteditable: "contentEditable" }, prop: function (e, n, r) { var i, s, o, u = e.nodeType; if (!e || u === 3 || u === 8 || u === 2) return; return o = u !== 1 || !v.isXMLDoc(e), o && (n = v.propFix[n] || n, s = v.propHooks[n]), r !== t ? s && "set" in s && (i = s.set(e, r, n)) !== t ? i : e[n] = r : s && "get" in s && (i = s.get(e, n)) !== null ? i : e[n] }, propHooks: { tabIndex: { get: function (e) { var n = e.getAttributeNode("tabindex"); return n && n.specified ? parseInt(n.value, 10) : z.test(e.nodeName) || W.test(e.nodeName) && e.href ? 0 : t } } } }), F = { get: function (e, n) { var r, i = v.prop(e, n); return i === !0 || typeof i != "boolean" && (r = e.getAttributeNode(n)) && r.nodeValue !== !1 ? n.toLowerCase() : t }, set: function (e, t, n) { var r; return t === !1 ? v.removeAttr(e, n) : (r = v.propFix[n] || n, r in e && (e[r] = !0), e.setAttribute(n, n.toLowerCase())), n } }, V || (I = { name: !0, id: !0, coords: !0 }, j = v.valHooks.button = { get: function (e, n) { var r; return r = e.getAttributeNode(n), r && (I[n] ? r.value !== "" : r.specified) ? r.value : t }, set: function (e, t, n) { var r = e.getAttributeNode(n); return r || (r = i.createAttribute(n), e.setAttributeNode(r)), r.value = t + "" } }, v.each(["width", "height"], function (e, t) { v.attrHooks[t] = v.extend(v.attrHooks[t], { set: function (e, n) { if (n === "") return e.setAttribute(t, "auto"), n } }) }), v.attrHooks.contenteditable = { get: j.get, set: function (e, t, n) { t === "" && (t = "false"), j.set(e, t, n) } }), v.support.hrefNormalized || v.each(["href", "src", "width", "height"], function (e, n) { v.attrHooks[n] = v.extend(v.attrHooks[n], { get: function (e) { var r = e.getAttribute(n, 2); return r === null ? t : r } }) }), v.support.style || (v.attrHooks.style = { get: function (e) { return e.style.cssText.toLowerCase() || t }, set: function (e, t) { return e.style.cssText = t + "" } }), v.support.optSelected || (v.propHooks.selected = v.extend(v.propHooks.selected, { get: function (e) { var t = e.parentNode; return t && (t.selectedIndex, t.parentNode && t.parentNode.selectedIndex), null } })), v.support.enctype || (v.propFix.enctype = "encoding"), v.support.checkOn || v.each(["radio", "checkbox"], function () { v.valHooks[this] = { get: function (e) { return e.getAttribute("value") === null ? "on" : e.value } } }), v.each(["radio", "checkbox"], function () { v.valHooks[this] = v.extend(v.valHooks[this], { set: function (e, t) { if (v.isArray(t)) return e.checked = v.inArray(v(e).val(), t) >= 0 } }) }); var $ = /^(?:textarea|input|select)$/i, J = /^([^\.]*|)(?:\.(.+)|)$/, K = /(?:^|\s)hover(\.\S+|)\b/, Q = /^key/, G = /^(?:mouse|contextmenu)|click/, Y = /^(?:focusinfocus|focusoutblur)$/, Z = function (e) { return v.event.special.hover ? e : e.replace(K, "mouseenter$1 mouseleave$1") }; v.event = { add: function (e, n, r, i, s) { var o, u, a, f, l, c, h, p, d, m, g; if (e.nodeType === 3 || e.nodeType === 8 || !n || !r || !(o = v._data(e))) return; r.handler && (d = r, r = d.handler, s = d.selector), r.guid || (r.guid = v.guid++), a = o.events, a || (o.events = a = {}), u = o.handle, u || (o.handle = u = function (e) { return typeof v == "undefined" || !!e && v.event.triggered === e.type ? t : v.event.dispatch.apply(u.elem, arguments) }, u.elem = e), n = v.trim(Z(n)).split(" "); for (f = 0; f < n.length; f++) { l = J.exec(n[f]) || [], c = l[1], h = (l[2] || "").split(".").sort(), g = v.event.special[c] || {}, c = (s ? g.delegateType : g.bindType) || c, g = v.event.special[c] || {}, p = v.extend({ type: c, origType: l[1], data: i, handler: r, guid: r.guid, selector: s, needsContext: s && v.expr.match.needsContext.test(s), namespace: h.join(".") }, d), m = a[c]; if (!m) { m = a[c] = [], m.delegateCount = 0; if (!g.setup || g.setup.call(e, i, h, u) === !1) e.addEventListener ? e.addEventListener(c, u, !1) : e.attachEvent && e.attachEvent("on" + c, u) } g.add && (g.add.call(e, p), p.handler.guid || (p.handler.guid = r.guid)), s ? m.splice(m.delegateCount++, 0, p) : m.push(p), v.event.global[c] = !0 } e = null }, global: {}, remove: function (e, t, n, r, i) { var s, o, u, a, f, l, c, h, p, d, m, g = v.hasData(e) && v._data(e); if (!g || !(h = g.events)) return; t = v.trim(Z(t || "")).split(" "); for (s = 0; s < t.length; s++) { o = J.exec(t[s]) || [], u = a = o[1], f = o[2]; if (!u) { for (u in h) v.event.remove(e, u + t[s], n, r, !0); continue } p = v.event.special[u] || {}, u = (r ? p.delegateType : p.bindType) || u, d = h[u] || [], l = d.length, f = f ? new RegExp("(^|\\.)" + f.split(".").sort().join("\\.(?:.*\\.|)") + "(\\.|$)") : null; for (c = 0; c < d.length; c++)m = d[c], (i || a === m.origType) && (!n || n.guid === m.guid) && (!f || f.test(m.namespace)) && (!r || r === m.selector || r === "**" && m.selector) && (d.splice(c--, 1), m.selector && d.delegateCount--, p.remove && p.remove.call(e, m)); d.length === 0 && l !== d.length && ((!p.teardown || p.teardown.call(e, f, g.handle) === !1) && v.removeEvent(e, u, g.handle), delete h[u]) } v.isEmptyObject(h) && (delete g.handle, v.removeData(e, "events", !0)) }, customEvent: { getData: !0, setData: !0, changeData: !0 }, trigger: function (n, r, s, o) { if (!s || s.nodeType !== 3 && s.nodeType !== 8) { var u, a, f, l, c, h, p, d, m, g, y = n.type || n, b = []; if (Y.test(y + v.event.triggered)) return; y.indexOf("!") >= 0 && (y = y.slice(0, -1), a = !0), y.indexOf(".") >= 0 && (b = y.split("."), y = b.shift(), b.sort()); if ((!s || v.event.customEvent[y]) && !v.event.global[y]) return; n = typeof n == "object" ? n[v.expando] ? n : new v.Event(y, n) : new v.Event(y), n.type = y, n.isTrigger = !0, n.exclusive = a, n.namespace = b.join("."), n.namespace_re = n.namespace ? new RegExp("(^|\\.)" + b.join("\\.(?:.*\\.|)") + "(\\.|$)") : null, h = y.indexOf(":") < 0 ? "on" + y : ""; if (!s) { u = v.cache; for (f in u) u[f].events && u[f].events[y] && v.event.trigger(n, r, u[f].handle.elem, !0); return } n.result = t, n.target || (n.target = s), r = r != null ? v.makeArray(r) : [], r.unshift(n), p = v.event.special[y] || {}; if (p.trigger && p.trigger.apply(s, r) === !1) return; m = [[s, p.bindType || y]]; if (!o && !p.noBubble && !v.isWindow(s)) { g = p.delegateType || y, l = Y.test(g + y) ? s : s.parentNode; for (c = s; l; l = l.parentNode)m.push([l, g]), c = l; c === (s.ownerDocument || i) && m.push([c.defaultView || c.parentWindow || e, g]) } for (f = 0; f < m.length && !n.isPropagationStopped(); f++)l = m[f][0], n.type = m[f][1], d = (v._data(l, "events") || {})[n.type] && v._data(l, "handle"), d && d.apply(l, r), d = h && l[h], d && v.acceptData(l) && d.apply && d.apply(l, r) === !1 && n.preventDefault(); return n.type = y, !o && !n.isDefaultPrevented() && (!p._default || p._default.apply(s.ownerDocument, r) === !1) && (y !== "click" || !v.nodeName(s, "a")) && v.acceptData(s) && h && s[y] && (y !== "focus" && y !== "blur" || n.target.offsetWidth !== 0) && !v.isWindow(s) && (c = s[h], c && (s[h] = null), v.event.triggered = y, s[y](), v.event.triggered = t, c && (s[h] = c)), n.result } return }, dispatch: function (n) { n = v.event.fix(n || e.event); var r, i, s, o, u, a, f, c, h, p, d = (v._data(this, "events") || {})[n.type] || [], m = d.delegateCount, g = l.call(arguments), y = !n.exclusive && !n.namespace, b = v.event.special[n.type] || {}, w = []; g[0] = n, n.delegateTarget = this; if (b.preDispatch && b.preDispatch.call(this, n) === !1) return; if (m && (!n.button || n.type !== "click")) for (s = n.target; s != this; s = s.parentNode || this)if (s.disabled !== !0 || n.type !== "click") { u = {}, f = []; for (r = 0; r < m; r++)c = d[r], h = c.selector, u[h] === t && (u[h] = c.needsContext ? v(h, this).index(s) >= 0 : v.find(h, this, null, [s]).length), u[h] && f.push(c); f.length && w.push({ elem: s, matches: f }) } d.length > m && w.push({ elem: this, matches: d.slice(m) }); for (r = 0; r < w.length && !n.isPropagationStopped(); r++) { a = w[r], n.currentTarget = a.elem; for (i = 0; i < a.matches.length && !n.isImmediatePropagationStopped(); i++) { c = a.matches[i]; if (y || !n.namespace && !c.namespace || n.namespace_re && n.namespace_re.test(c.namespace)) n.data = c.data, n.handleObj = c, o = ((v.event.special[c.origType] || {}).handle || c.handler).apply(a.elem, g), o !== t && (n.result = o, o === !1 && (n.preventDefault(), n.stopPropagation())) } } return b.postDispatch && b.postDispatch.call(this, n), n.result }, props: "attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "), fixHooks: {}, keyHooks: { props: "char charCode key keyCode".split(" "), filter: function (e, t) { return e.which == null && (e.which = t.charCode != null ? t.charCode : t.keyCode), e } }, mouseHooks: { props: "button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "), filter: function (e, n) { var r, s, o, u = n.button, a = n.fromElement; return e.pageX == null && n.clientX != null && (r = e.target.ownerDocument || i, s = r.documentElement, o = r.body, e.pageX = n.clientX + (s && s.scrollLeft || o && o.scrollLeft || 0) - (s && s.clientLeft || o && o.clientLeft || 0), e.pageY = n.clientY + (s && s.scrollTop || o && o.scrollTop || 0) - (s && s.clientTop || o && o.clientTop || 0)), !e.relatedTarget && a && (e.relatedTarget = a === e.target ? n.toElement : a), !e.which && u !== t && (e.which = u & 1 ? 1 : u & 2 ? 3 : u & 4 ? 2 : 0), e } }, fix: function (e) { if (e[v.expando]) return e; var t, n, r = e, s = v.event.fixHooks[e.type] || {}, o = s.props ? this.props.concat(s.props) : this.props; e = v.Event(r); for (t = o.length; t;)n = o[--t], e[n] = r[n]; return e.target || (e.target = r.srcElement || i), e.target.nodeType === 3 && (e.target = e.target.parentNode), e.metaKey = !!e.metaKey, s.filter ? s.filter(e, r) : e }, special: { load: { noBubble: !0 }, focus: { delegateType: "focusin" }, blur: { delegateType: "focusout" }, beforeunload: { setup: function (e, t, n) { v.isWindow(this) && (this.onbeforeunload = n) }, teardown: function (e, t) { this.onbeforeunload === t && (this.onbeforeunload = null) } } }, simulate: function (e, t, n, r) { var i = v.extend(new v.Event, n, { type: e, isSimulated: !0, originalEvent: {} }); r ? v.event.trigger(i, null, t) : v.event.dispatch.call(t, i), i.isDefaultPrevented() && n.preventDefault() } }, v.event.handle = v.event.dispatch, v.removeEvent = i.removeEventListener ? function (e, t, n) { e.removeEventListener && e.removeEventListener(t, n, !1) } : function (e, t, n) { var r = "on" + t; e.detachEvent && (typeof e[r] == "undefined" && (e[r] = null), e.detachEvent(r, n)) }, v.Event = function (e, t) { if (!(this instanceof v.Event)) return new v.Event(e, t); e && e.type ? (this.originalEvent = e, this.type = e.type, this.isDefaultPrevented = e.defaultPrevented || e.returnValue === !1 || e.getPreventDefault && e.getPreventDefault() ? tt : et) : this.type = e, t && v.extend(this, t), this.timeStamp = e && e.timeStamp || v.now(), this[v.expando] = !0 }, v.Event.prototype = { preventDefault: function () { this.isDefaultPrevented = tt; var e = this.originalEvent; if (!e) return; e.preventDefault ? e.preventDefault() : e.returnValue = !1 }, stopPropagation: function () { this.isPropagationStopped = tt; var e = this.originalEvent; if (!e) return; e.stopPropagation && e.stopPropagation(), e.cancelBubble = !0 }, stopImmediatePropagation: function () { this.isImmediatePropagationStopped = tt, this.stopPropagation() }, isDefaultPrevented: et, isPropagationStopped: et, isImmediatePropagationStopped: et }, v.each({ mouseenter: "mouseover", mouseleave: "mouseout" }, function (e, t) { v.event.special[e] = { delegateType: t, bindType: t, handle: function (e) { var n, r = this, i = e.relatedTarget, s = e.handleObj, o = s.selector; if (!i || i !== r && !v.contains(r, i)) e.type = s.origType, n = s.handler.apply(this, arguments), e.type = t; return n } } }), v.support.submitBubbles || (v.event.special.submit = { setup: function () { if (v.nodeName(this, "form")) return !1; v.event.add(this, "click._submit keypress._submit", function (e) { var n = e.target, r = v.nodeName(n, "input") || v.nodeName(n, "button") ? n.form : t; r && !v._data(r, "_submit_attached") && (v.event.add(r, "submit._submit", function (e) { e._submit_bubble = !0 }), v._data(r, "_submit_attached", !0)) }) }, postDispatch: function (e) { e._submit_bubble && (delete e._submit_bubble, this.parentNode && !e.isTrigger && v.event.simulate("submit", this.parentNode, e, !0)) }, teardown: function () { if (v.nodeName(this, "form")) return !1; v.event.remove(this, "._submit") } }), v.support.changeBubbles || (v.event.special.change = { setup: function () { if ($.test(this.nodeName)) { if (this.type === "checkbox" || this.type === "radio") v.event.add(this, "propertychange._change", function (e) { e.originalEvent.propertyName === "checked" && (this._just_changed = !0) }), v.event.add(this, "click._change", function (e) { this._just_changed && !e.isTrigger && (this._just_changed = !1), v.event.simulate("change", this, e, !0) }); return !1 } v.event.add(this, "beforeactivate._change", function (e) { var t = e.target; $.test(t.nodeName) && !v._data(t, "_change_attached") && (v.event.add(t, "change._change", function (e) { this.parentNode && !e.isSimulated && !e.isTrigger && v.event.simulate("change", this.parentNode, e, !0) }), v._data(t, "_change_attached", !0)) }) }, handle: function (e) { var t = e.target; if (this !== t || e.isSimulated || e.isTrigger || t.type !== "radio" && t.type !== "checkbox") return e.handleObj.handler.apply(this, arguments) }, teardown: function () { return v.event.remove(this, "._change"), !$.test(this.nodeName) } }), v.support.focusinBubbles || v.each({ focus: "focusin", blur: "focusout" }, function (e, t) { var n = 0, r = function (e) { v.event.simulate(t, e.target, v.event.fix(e), !0) }; v.event.special[t] = { setup: function () { n++ === 0 && i.addEventListener(e, r, !0) }, teardown: function () { --n === 0 && i.removeEventListener(e, r, !0) } } }), v.fn.extend({ on: function (e, n, r, i, s) { var o, u; if (typeof e == "object") { typeof n != "string" && (r = r || n, n = t); for (u in e) this.on(u, n, r, e[u], s); return this } r == null && i == null ? (i = n, r = n = t) : i == null && (typeof n == "string" ? (i = r, r = t) : (i = r, r = n, n = t)); if (i === !1) i = et; else if (!i) return this; return s === 1 && (o = i, i = function (e) { return v().off(e), o.apply(this, arguments) }, i.guid = o.guid || (o.guid = v.guid++)), this.each(function () { v.event.add(this, e, i, r, n) }) }, one: function (e, t, n, r) { return this.on(e, t, n, r, 1) }, off: function (e, n, r) { var i, s; if (e && e.preventDefault && e.handleObj) return i = e.handleObj, v(e.delegateTarget).off(i.namespace ? i.origType + "." + i.namespace : i.origType, i.selector, i.handler), this; if (typeof e == "object") { for (s in e) this.off(s, n, e[s]); return this } if (n === !1 || typeof n == "function") r = n, n = t; return r === !1 && (r = et), this.each(function () { v.event.remove(this, e, r, n) }) }, bind: function (e, t, n) { return this.on(e, null, t, n) }, unbind: function (e, t) { return this.off(e, null, t) }, live: function (e, t, n) { return v(this.context).on(e, this.selector, t, n), this }, die: function (e, t) { return v(this.context).off(e, this.selector || "**", t), this }, delegate: function (e, t, n, r) { return this.on(t, e, n, r) }, undelegate: function (e, t, n) { return arguments.length === 1 ? this.off(e, "**") : this.off(t, e || "**", n) }, trigger: function (e, t) { return this.each(function () { v.event.trigger(e, t, this) }) }, triggerHandler: function (e, t) { if (this[0]) return v.event.trigger(e, t, this[0], !0) }, toggle: function (e) { var t = arguments, n = e.guid || v.guid++, r = 0, i = function (n) { var i = (v._data(this, "lastToggle" + e.guid) || 0) % r; return v._data(this, "lastToggle" + e.guid, i + 1), n.preventDefault(), t[i].apply(this, arguments) || !1 }; i.guid = n; while (r < t.length) t[r++].guid = n; return this.click(i) }, hover: function (e, t) { return this.mouseenter(e).mouseleave(t || e) } }), v.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "), function (e, t) { v.fn[t] = function (e, n) { return n == null && (n = e, e = null), arguments.length > 0 ? this.on(t, null, e, n) : this.trigger(t) }, Q.test(t) && (v.event.fixHooks[t] = v.event.keyHooks), G.test(t) && (v.event.fixHooks[t] = v.event.mouseHooks) }), function (e, t) { function nt (e, t, n, r) { n = n || [], t = t || g; var i, s, a, f, l = t.nodeType; if (!e || typeof e != "string") return n; if (l !== 1 && l !== 9) return []; a = o(t); if (!a && !r) if (i = R.exec(e)) if (f = i[1]) { if (l === 9) { s = t.getElementById(f); if (!s || !s.parentNode) return n; if (s.id === f) return n.push(s), n } else if (t.ownerDocument && (s = t.ownerDocument.getElementById(f)) && u(t, s) && s.id === f) return n.push(s), n } else { if (i[2]) return S.apply(n, x.call(t.getElementsByTagName(e), 0)), n; if ((f = i[3]) && Z && t.getElementsByClassName) return S.apply(n, x.call(t.getElementsByClassName(f), 0)), n } return vt(e.replace(j, "$1"), t, n, r, a) } function rt (e) { return function (t) { var n = t.nodeName.toLowerCase(); return n === "input" && t.type === e } } function it (e) { return function (t) { var n = t.nodeName.toLowerCase(); return (n === "input" || n === "button") && t.type === e } } function st (e) { return N(function (t) { return t = +t, N(function (n, r) { var i, s = e([], n.length, t), o = s.length; while (o--) n[i = s[o]] && (n[i] = !(r[i] = n[i])) }) }) } function ot (e, t, n) { if (e === t) return n; var r = e.nextSibling; while (r) { if (r === t) return -1; r = r.nextSibling } return 1 } function ut (e, t) { var n, r, s, o, u, a, f, l = L[d][e + " "]; if (l) return t ? 0 : l.slice(0); u = e, a = [], f = i.preFilter; while (u) { if (!n || (r = F.exec(u))) r && (u = u.slice(r[0].length) || u), a.push(s = []); n = !1; if (r = I.exec(u)) s.push(n = new m(r.shift())), u = u.slice(n.length), n.type = r[0].replace(j, " "); for (o in i.filter) (r = J[o].exec(u)) && (!f[o] || (r = f[o](r))) && (s.push(n = new m(r.shift())), u = u.slice(n.length), n.type = o, n.matches = r); if (!n) break } return t ? u.length : u ? nt.error(e) : L(e, a).slice(0) } function at (e, t, r) { var i = t.dir, s = r && t.dir === "parentNode", o = w++; return t.first ? function (t, n, r) { while (t = t[i]) if (s || t.nodeType === 1) return e(t, n, r) } : function (t, r, u) { if (!u) { var a, f = b + " " + o + " ", l = f + n; while (t = t[i]) if (s || t.nodeType === 1) { if ((a = t[d]) === l) return t.sizset; if (typeof a == "string" && a.indexOf(f) === 0) { if (t.sizset) return t } else { t[d] = l; if (e(t, r, u)) return t.sizset = !0, t; t.sizset = !1 } } } else while (t = t[i]) if (s || t.nodeType === 1) if (e(t, r, u)) return t } } function ft (e) { return e.length > 1 ? function (t, n, r) { var i = e.length; while (i--) if (!e[i](t, n, r)) return !1; return !0 } : e[0] } function lt (e, t, n, r, i) { var s, o = [], u = 0, a = e.length, f = t != null; for (; u < a; u++)if (s = e[u]) if (!n || n(s, r, i)) o.push(s), f && t.push(u); return o } function ct (e, t, n, r, i, s) { return r && !r[d] && (r = ct(r)), i && !i[d] && (i = ct(i, s)), N(function (s, o, u, a) { var f, l, c, h = [], p = [], d = o.length, v = s || dt(t || "*", u.nodeType ? [u] : u, []), m = e && (s || !t) ? lt(v, h, e, u, a) : v, g = n ? i || (s ? e : d || r) ? [] : o : m; n && n(m, g, u, a); if (r) { f = lt(g, p), r(f, [], u, a), l = f.length; while (l--) if (c = f[l]) g[p[l]] = !(m[p[l]] = c) } if (s) { if (i || e) { if (i) { f = [], l = g.length; while (l--) (c = g[l]) && f.push(m[l] = c); i(null, g = [], f, a) } l = g.length; while (l--) (c = g[l]) && (f = i ? T.call(s, c) : h[l]) > -1 && (s[f] = !(o[f] = c)) } } else g = lt(g === o ? g.splice(d, g.length) : g), i ? i(null, o, g, a) : S.apply(o, g) }) } function ht (e) { var t, n, r, s = e.length, o = i.relative[e[0].type], u = o || i.relative[" "], a = o ? 1 : 0, f = at(function (e) { return e === t }, u, !0), l = at(function (e) { return T.call(t, e) > -1 }, u, !0), h = [function (e, n, r) { return !o && (r || n !== c) || ((t = n).nodeType ? f(e, n, r) : l(e, n, r)) }]; for (; a < s; a++)if (n = i.relative[e[a].type]) h = [at(ft(h), n)]; else { n = i.filter[e[a].type].apply(null, e[a].matches); if (n[d]) { r = ++a; for (; r < s; r++)if (i.relative[e[r].type]) break; return ct(a > 1 && ft(h), a > 1 && e.slice(0, a - 1).join("").replace(j, "$1"), n, a < r && ht(e.slice(a, r)), r < s && ht(e = e.slice(r)), r < s && e.join("")) } h.push(n) } return ft(h) } function pt (e, t) { var r = t.length > 0, s = e.length > 0, o = function (u, a, f, l, h) { var p, d, v, m = [], y = 0, w = "0", x = u && [], T = h != null, N = c, C = u || s && i.find.TAG("*", h && a.parentNode || a), k = b += N == null ? 1 : Math.E; T && (c = a !== g && a, n = o.el); for (; (p = C[w]) != null; w++) { if (s && p) { for (d = 0; v = e[d]; d++)if (v(p, a, f)) { l.push(p); break } T && (b = k, n = ++o.el) } r && ((p = !v && p) && y--, u && x.push(p)) } y += w; if (r && w !== y) { for (d = 0; v = t[d]; d++)v(x, m, a, f); if (u) { if (y > 0) while (w--) !x[w] && !m[w] && (m[w] = E.call(l)); m = lt(m) } S.apply(l, m), T && !u && m.length > 0 && y + t.length > 1 && nt.uniqueSort(l) } return T && (b = k, c = N), x }; return o.el = 0, r ? N(o) : o } function dt (e, t, n) { var r = 0, i = t.length; for (; r < i; r++)nt(e, t[r], n); return n } function vt (e, t, n, r, s) { var o, u, f, l, c, h = ut(e), p = h.length; if (!r && h.length === 1) { u = h[0] = h[0].slice(0); if (u.length > 2 && (f = u[0]).type === "ID" && t.nodeType === 9 && !s && i.relative[u[1].type]) { t = i.find.ID(f.matches[0].replace($, ""), t, s)[0]; if (!t) return n; e = e.slice(u.shift().length) } for (o = J.POS.test(e) ? -1 : u.length - 1; o >= 0; o--) { f = u[o]; if (i.relative[l = f.type]) break; if (c = i.find[l]) if (r = c(f.matches[0].replace($, ""), z.test(u[0].type) && t.parentNode || t, s)) { u.splice(o, 1), e = r.length && u.join(""); if (!e) return S.apply(n, x.call(r, 0)), n; break } } } return a(e, h)(r, t, s, n, z.test(e)), n } function mt () { } var n, r, i, s, o, u, a, f, l, c, h = !0, p = "undefined", d = ("sizcache" + Math.random()).replace(".", ""), m = String, g = e.document, y = g.documentElement, b = 0, w = 0, E = [].pop, S = [].push, x = [].slice, T = [].indexOf || function (e) { var t = 0, n = this.length; for (; t < n; t++)if (this[t] === e) return t; return -1 }, N = function (e, t) { return e[d] = t == null || t, e }, C = function () { var e = {}, t = []; return N(function (n, r) { return t.push(n) > i.cacheLength && delete e[t.shift()], e[n + " "] = r }, e) }, k = C(), L = C(), A = C(), O = "[\\x20\\t\\r\\n\\f]", M = "(?:\\\\.|[-\\w]|[^\\x00-\\xa0])+", _ = M.replace("w", "w#"), D = "([*^$|!~]?=)", P = "\\[" + O + "*(" + M + ")" + O + "*(?:" + D + O + "*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|(" + _ + ")|)|)" + O + "*\\]", H = ":(" + M + ")(?:\\((?:(['\"])((?:\\\\.|[^\\\\])*?)\\2|([^()[\\]]*|(?:(?:" + P + ")|[^:]|\\\\.)*|.*))\\)|)", B = ":(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + O + "*((?:-\\d)?\\d*)" + O + "*\\)|)(?=[^-]|$)", j = new RegExp("^" + O + "+|((?:^|[^\\\\])(?:\\\\.)*)" + O + "+$", "g"), F = new RegExp("^" + O + "*," + O + "*"), I = new RegExp("^" + O + "*([\\x20\\t\\r\\n\\f>+~])" + O + "*"), q = new RegExp(H), R = /^(?:#([\w\-]+)|(\w+)|\.([\w\-]+))$/, U = /^:not/, z = /[\x20\t\r\n\f]*[+~]/, W = /:not\($/, X = /h\d/i, V = /input|select|textarea|button/i, $ = /\\(?!\\)/g, J = { ID: new RegExp("^#(" + M + ")"), CLASS: new RegExp("^\\.(" + M + ")"), NAME: new RegExp("^\\[name=['\"]?(" + M + ")['\"]?\\]"), TAG: new RegExp("^(" + M.replace("w", "w*") + ")"), ATTR: new RegExp("^" + P), PSEUDO: new RegExp("^" + H), POS: new RegExp(B, "i"), CHILD: new RegExp("^:(only|nth|first|last)-child(?:\\(" + O + "*(even|odd|(([+-]|)(\\d*)n|)" + O + "*(?:([+-]|)" + O + "*(\\d+)|))" + O + "*\\)|)", "i"), needsContext: new RegExp("^" + O + "*[>+~]|" + B, "i") }, K = function (e) { var t = g.createElement("div"); try { return e(t) } catch (n) { return !1 } finally { t = null } }, Q = K(function (e) { return e.appendChild(g.createComment("")), !e.getElementsByTagName("*").length }), G = K(function (e) { return e.innerHTML = "", e.firstChild && typeof e.firstChild.getAttribute !== p && e.firstChild.getAttribute("href") === "#" }), Y = K(function (e) { e.innerHTML = ""; var t = typeof e.lastChild.getAttribute("multiple"); return t !== "boolean" && t !== "string" }), Z = K(function (e) { return e.innerHTML = "", !e.getElementsByClassName || !e.getElementsByClassName("e").length ? !1 : (e.lastChild.className = "e", e.getElementsByClassName("e").length === 2) }), et = K(function (e) { e.id = d + 0, e.innerHTML = "
    ", y.insertBefore(e, y.firstChild); var t = g.getElementsByName && g.getElementsByName(d).length === 2 + g.getElementsByName(d + 0).length; return r = !g.getElementById(d), y.removeChild(e), t }); try { x.call(y.childNodes, 0)[0].nodeType } catch (tt) { x = function (e) { var t, n = []; for (; t = this[e]; e++)n.push(t); return n } } nt.matches = function (e, t) { return nt(e, null, null, t) }, nt.matchesSelector = function (e, t) { return nt(t, null, null, [e]).length > 0 }, s = nt.getText = function (e) { var t, n = "", r = 0, i = e.nodeType; if (i) { if (i === 1 || i === 9 || i === 11) { if (typeof e.textContent == "string") return e.textContent; for (e = e.firstChild; e; e = e.nextSibling)n += s(e) } else if (i === 3 || i === 4) return e.nodeValue } else for (; t = e[r]; r++)n += s(t); return n }, o = nt.isXML = function (e) { var t = e && (e.ownerDocument || e).documentElement; return t ? t.nodeName !== "HTML" : !1 }, u = nt.contains = y.contains ? function (e, t) { var n = e.nodeType === 9 ? e.documentElement : e, r = t && t.parentNode; return e === r || !!(r && r.nodeType === 1 && n.contains && n.contains(r)) } : y.compareDocumentPosition ? function (e, t) { return t && !!(e.compareDocumentPosition(t) & 16) } : function (e, t) { while (t = t.parentNode) if (t === e) return !0; return !1 }, nt.attr = function (e, t) { var n, r = o(e); return r || (t = t.toLowerCase()), (n = i.attrHandle[t]) ? n(e) : r || Y ? e.getAttribute(t) : (n = e.getAttributeNode(t), n ? typeof e[t] == "boolean" ? e[t] ? t : null : n.specified ? n.value : null : null) }, i = nt.selectors = { cacheLength: 50, createPseudo: N, match: J, attrHandle: G ? {} : { href: function (e) { return e.getAttribute("href", 2) }, type: function (e) { return e.getAttribute("type") } }, find: { ID: r ? function (e, t, n) { if (typeof t.getElementById !== p && !n) { var r = t.getElementById(e); return r && r.parentNode ? [r] : [] } } : function (e, n, r) { if (typeof n.getElementById !== p && !r) { var i = n.getElementById(e); return i ? i.id === e || typeof i.getAttributeNode !== p && i.getAttributeNode("id").value === e ? [i] : t : [] } }, TAG: Q ? function (e, t) { if (typeof t.getElementsByTagName !== p) return t.getElementsByTagName(e) } : function (e, t) { var n = t.getElementsByTagName(e); if (e === "*") { var r, i = [], s = 0; for (; r = n[s]; s++)r.nodeType === 1 && i.push(r); return i } return n }, NAME: et && function (e, t) { if (typeof t.getElementsByName !== p) return t.getElementsByName(name) }, CLASS: Z && function (e, t, n) { if (typeof t.getElementsByClassName !== p && !n) return t.getElementsByClassName(e) } }, relative: { ">": { dir: "parentNode", first: !0 }, " ": { dir: "parentNode" }, "+": { dir: "previousSibling", first: !0 }, "~": { dir: "previousSibling" } }, preFilter: { ATTR: function (e) { return e[1] = e[1].replace($, ""), e[3] = (e[4] || e[5] || "").replace($, ""), e[2] === "~=" && (e[3] = " " + e[3] + " "), e.slice(0, 4) }, CHILD: function (e) { return e[1] = e[1].toLowerCase(), e[1] === "nth" ? (e[2] || nt.error(e[0]), e[3] = +(e[3] ? e[4] + (e[5] || 1) : 2 * (e[2] === "even" || e[2] === "odd")), e[4] = +(e[6] + e[7] || e[2] === "odd")) : e[2] && nt.error(e[0]), e }, PSEUDO: function (e) { var t, n; if (J.CHILD.test(e[0])) return null; if (e[3]) e[2] = e[3]; else if (t = e[4]) q.test(t) && (n = ut(t, !0)) && (n = t.indexOf(")", t.length - n) - t.length) && (t = t.slice(0, n), e[0] = e[0].slice(0, n)), e[2] = t; return e.slice(0, 3) } }, filter: { ID: r ? function (e) { return e = e.replace($, ""), function (t) { return t.getAttribute("id") === e } } : function (e) { return e = e.replace($, ""), function (t) { var n = typeof t.getAttributeNode !== p && t.getAttributeNode("id"); return n && n.value === e } }, TAG: function (e) { return e === "*" ? function () { return !0 } : (e = e.replace($, "").toLowerCase(), function (t) { return t.nodeName && t.nodeName.toLowerCase() === e }) }, CLASS: function (e) { var t = k[d][e + " "]; return t || (t = new RegExp("(^|" + O + ")" + e + "(" + O + "|$)")) && k(e, function (e) { return t.test(e.className || typeof e.getAttribute !== p && e.getAttribute("class") || "") }) }, ATTR: function (e, t, n) { return function (r, i) { var s = nt.attr(r, e); return s == null ? t === "!=" : t ? (s += "", t === "=" ? s === n : t === "!=" ? s !== n : t === "^=" ? n && s.indexOf(n) === 0 : t === "*=" ? n && s.indexOf(n) > -1 : t === "$=" ? n && s.substr(s.length - n.length) === n : t === "~=" ? (" " + s + " ").indexOf(n) > -1 : t === "|=" ? s === n || s.substr(0, n.length + 1) === n + "-" : !1) : !0 } }, CHILD: function (e, t, n, r) { return e === "nth" ? function (e) { var t, i, s = e.parentNode; if (n === 1 && r === 0) return !0; if (s) { i = 0; for (t = s.firstChild; t; t = t.nextSibling)if (t.nodeType === 1) { i++; if (e === t) break } } return i -= r, i === n || i % n === 0 && i / n >= 0 } : function (t) { var n = t; switch (e) { case "only": case "first": while (n = n.previousSibling) if (n.nodeType === 1) return !1; if (e === "first") return !0; n = t; case "last": while (n = n.nextSibling) if (n.nodeType === 1) return !1; return !0 } } }, PSEUDO: function (e, t) { var n, r = i.pseudos[e] || i.setFilters[e.toLowerCase()] || nt.error("unsupported pseudo: " + e); return r[d] ? r(t) : r.length > 1 ? (n = [e, e, "", t], i.setFilters.hasOwnProperty(e.toLowerCase()) ? N(function (e, n) { var i, s = r(e, t), o = s.length; while (o--) i = T.call(e, s[o]), e[i] = !(n[i] = s[o]) }) : function (e) { return r(e, 0, n) }) : r } }, pseudos: { not: N(function (e) { var t = [], n = [], r = a(e.replace(j, "$1")); return r[d] ? N(function (e, t, n, i) { var s, o = r(e, null, i, []), u = e.length; while (u--) if (s = o[u]) e[u] = !(t[u] = s) }) : function (e, i, s) { return t[0] = e, r(t, null, s, n), !n.pop() } }), has: N(function (e) { return function (t) { return nt(e, t).length > 0 } }), contains: N(function (e) { return function (t) { return (t.textContent || t.innerText || s(t)).indexOf(e) > -1 } }), enabled: function (e) { return e.disabled === !1 }, disabled: function (e) { return e.disabled === !0 }, checked: function (e) { var t = e.nodeName.toLowerCase(); return t === "input" && !!e.checked || t === "option" && !!e.selected }, selected: function (e) { return e.parentNode && e.parentNode.selectedIndex, e.selected === !0 }, parent: function (e) { return !i.pseudos.empty(e) }, empty: function (e) { var t; e = e.firstChild; while (e) { if (e.nodeName > "@" || (t = e.nodeType) === 3 || t === 4) return !1; e = e.nextSibling } return !0 }, header: function (e) { return X.test(e.nodeName) }, text: function (e) { var t, n; return e.nodeName.toLowerCase() === "input" && (t = e.type) === "text" && ((n = e.getAttribute("type")) == null || n.toLowerCase() === t) }, radio: rt("radio"), checkbox: rt("checkbox"), file: rt("file"), password: rt("password"), image: rt("image"), submit: it("submit"), reset: it("reset"), button: function (e) { var t = e.nodeName.toLowerCase(); return t === "input" && e.type === "button" || t === "button" }, input: function (e) { return V.test(e.nodeName) }, focus: function (e) { var t = e.ownerDocument; return e === t.activeElement && (!t.hasFocus || t.hasFocus()) && !!(e.type || e.href || ~e.tabIndex) }, active: function (e) { return e === e.ownerDocument.activeElement }, first: st(function () { return [0] }), last: st(function (e, t) { return [t - 1] }), eq: st(function (e, t, n) { return [n < 0 ? n + t : n] }), even: st(function (e, t) { for (var n = 0; n < t; n += 2)e.push(n); return e }), odd: st(function (e, t) { for (var n = 1; n < t; n += 2)e.push(n); return e }), lt: st(function (e, t, n) { for (var r = n < 0 ? n + t : n; --r >= 0;)e.push(r); return e }), gt: st(function (e, t, n) { for (var r = n < 0 ? n + t : n; ++r < t;)e.push(r); return e }) } }, f = y.compareDocumentPosition ? function (e, t) { return e === t ? (l = !0, 0) : (!e.compareDocumentPosition || !t.compareDocumentPosition ? e.compareDocumentPosition : e.compareDocumentPosition(t) & 4) ? -1 : 1 } : function (e, t) { if (e === t) return l = !0, 0; if (e.sourceIndex && t.sourceIndex) return e.sourceIndex - t.sourceIndex; var n, r, i = [], s = [], o = e.parentNode, u = t.parentNode, a = o; if (o === u) return ot(e, t); if (!o) return -1; if (!u) return 1; while (a) i.unshift(a), a = a.parentNode; a = u; while (a) s.unshift(a), a = a.parentNode; n = i.length, r = s.length; for (var f = 0; f < n && f < r; f++)if (i[f] !== s[f]) return ot(i[f], s[f]); return f === n ? ot(e, s[f], -1) : ot(i[f], t, 1) }, [0, 0].sort(f), h = !l, nt.uniqueSort = function (e) { var t, n = [], r = 1, i = 0; l = h, e.sort(f); if (l) { for (; t = e[r]; r++)t === e[r - 1] && (i = n.push(r)); while (i--) e.splice(n[i], 1) } return e }, nt.error = function (e) { throw new Error("Syntax error, unrecognized expression: " + e) }, a = nt.compile = function (e, t) { var n, r = [], i = [], s = A[d][e + " "]; if (!s) { t || (t = ut(e)), n = t.length; while (n--) s = ht(t[n]), s[d] ? r.push(s) : i.push(s); s = A(e, pt(i, r)) } return s }, g.querySelectorAll && function () { var e, t = vt, n = /'|\\/g, r = /\=[\x20\t\r\n\f]*([^'"\]]*)[\x20\t\r\n\f]*\]/g, i = [":focus"], s = [":active"], u = y.matchesSelector || y.mozMatchesSelector || y.webkitMatchesSelector || y.oMatchesSelector || y.msMatchesSelector; K(function (e) { e.innerHTML = "", e.querySelectorAll("[selected]").length || i.push("\\[" + O + "*(?:checked|disabled|ismap|multiple|readonly|selected|value)"), e.querySelectorAll(":checked").length || i.push(":checked") }), K(function (e) { e.innerHTML = "

    ", e.querySelectorAll("[test^='']").length && i.push("[*^$]=" + O + "*(?:\"\"|'')"), e.innerHTML = "", e.querySelectorAll(":enabled").length || i.push(":enabled", ":disabled") }), i = new RegExp(i.join("|")), vt = function (e, r, s, o, u) { if (!o && !u && !i.test(e)) { var a, f, l = !0, c = d, h = r, p = r.nodeType === 9 && e; if (r.nodeType === 1 && r.nodeName.toLowerCase() !== "object") { a = ut(e), (l = r.getAttribute("id")) ? c = l.replace(n, "\\$&") : r.setAttribute("id", c), c = "[id='" + c + "'] ", f = a.length; while (f--) a[f] = c + a[f].join(""); h = z.test(e) && r.parentNode || r, p = a.join(",") } if (p) try { return S.apply(s, x.call(h.querySelectorAll(p), 0)), s } catch (v) { } finally { l || r.removeAttribute("id") } } return t(e, r, s, o, u) }, u && (K(function (t) { e = u.call(t, "div"); try { u.call(t, "[test!='']:sizzle"), s.push("!=", H) } catch (n) { } }), s = new RegExp(s.join("|")), nt.matchesSelector = function (t, n) { n = n.replace(r, "='$1']"); if (!o(t) && !s.test(n) && !i.test(n)) try { var a = u.call(t, n); if (a || e || t.document && t.document.nodeType !== 11) return a } catch (f) { } return nt(n, null, null, [t]).length > 0 }) }(), i.pseudos.nth = i.pseudos.eq, i.filters = mt.prototype = i.pseudos, i.setFilters = new mt, nt.attr = v.attr, v.find = nt, v.expr = nt.selectors, v.expr[":"] = v.expr.pseudos, v.unique = nt.uniqueSort, v.text = nt.getText, v.isXMLDoc = nt.isXML, v.contains = nt.contains }(e); var nt = /Until$/, rt = /^(?:parents|prev(?:Until|All))/, it = /^.[^:#\[\.,]*$/, st = v.expr.match.needsContext, ot = { children: !0, contents: !0, next: !0, prev: !0 }; v.fn.extend({ find: function (e) { var t, n, r, i, s, o, u = this; if (typeof e != "string") return v(e).filter(function () { for (t = 0, n = u.length; t < n; t++)if (v.contains(u[t], this)) return !0 }); o = this.pushStack("", "find", e); for (t = 0, n = this.length; t < n; t++) { r = o.length, v.find(e, this[t], o); if (t > 0) for (i = r; i < o.length; i++)for (s = 0; s < r; s++)if (o[s] === o[i]) { o.splice(i--, 1); break } } return o }, has: function (e) { var t, n = v(e, this), r = n.length; return this.filter(function () { for (t = 0; t < r; t++)if (v.contains(this, n[t])) return !0 }) }, not: function (e) { return this.pushStack(ft(this, e, !1), "not", e) }, filter: function (e) { return this.pushStack(ft(this, e, !0), "filter", e) }, is: function (e) { return !!e && (typeof e == "string" ? st.test(e) ? v(e, this.context).index(this[0]) >= 0 : v.filter(e, this).length > 0 : this.filter(e).length > 0) }, closest: function (e, t) { var n, r = 0, i = this.length, s = [], o = st.test(e) || typeof e != "string" ? v(e, t || this.context) : 0; for (; r < i; r++) { n = this[r]; while (n && n.ownerDocument && n !== t && n.nodeType !== 11) { if (o ? o.index(n) > -1 : v.find.matchesSelector(n, e)) { s.push(n); break } n = n.parentNode } } return s = s.length > 1 ? v.unique(s) : s, this.pushStack(s, "closest", e) }, index: function (e) { return e ? typeof e == "string" ? v.inArray(this[0], v(e)) : v.inArray(e.jquery ? e[0] : e, this) : this[0] && this[0].parentNode ? this.prevAll().length : -1 }, add: function (e, t) { var n = typeof e == "string" ? v(e, t) : v.makeArray(e && e.nodeType ? [e] : e), r = v.merge(this.get(), n); return this.pushStack(ut(n[0]) || ut(r[0]) ? r : v.unique(r)) }, addBack: function (e) { return this.add(e == null ? this.prevObject : this.prevObject.filter(e)) } }), v.fn.andSelf = v.fn.addBack, v.each({ parent: function (e) { var t = e.parentNode; return t && t.nodeType !== 11 ? t : null }, parents: function (e) { return v.dir(e, "parentNode") }, parentsUntil: function (e, t, n) { return v.dir(e, "parentNode", n) }, next: function (e) { return at(e, "nextSibling") }, prev: function (e) { return at(e, "previousSibling") }, nextAll: function (e) { return v.dir(e, "nextSibling") }, prevAll: function (e) { return v.dir(e, "previousSibling") }, nextUntil: function (e, t, n) { return v.dir(e, "nextSibling", n) }, prevUntil: function (e, t, n) { return v.dir(e, "previousSibling", n) }, siblings: function (e) { return v.sibling((e.parentNode || {}).firstChild, e) }, children: function (e) { return v.sibling(e.firstChild) }, contents: function (e) { return v.nodeName(e, "iframe") ? e.contentDocument || e.contentWindow.document : v.merge([], e.childNodes) } }, function (e, t) { v.fn[e] = function (n, r) { var i = v.map(this, t, n); return nt.test(e) || (r = n), r && typeof r == "string" && (i = v.filter(r, i)), i = this.length > 1 && !ot[e] ? v.unique(i) : i, this.length > 1 && rt.test(e) && (i = i.reverse()), this.pushStack(i, e, l.call(arguments).join(",")) } }), v.extend({ filter: function (e, t, n) { return n && (e = ":not(" + e + ")"), t.length === 1 ? v.find.matchesSelector(t[0], e) ? [t[0]] : [] : v.find.matches(e, t) }, dir: function (e, n, r) { var i = [], s = e[n]; while (s && s.nodeType !== 9 && (r === t || s.nodeType !== 1 || !v(s).is(r))) s.nodeType === 1 && i.push(s), s = s[n]; return i }, sibling: function (e, t) { var n = []; for (; e; e = e.nextSibling)e.nodeType === 1 && e !== t && n.push(e); return n } }); var ct = "abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video", ht = / jQuery\d+="(?:null|\d+)"/g, pt = /^\s+/, dt = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi, vt = /<([\w:]+)/, mt = /]", "i"), Et = /^(?:checkbox|radio)$/, St = /checked\s*(?:[^=]|=\s*.checked.)/i, xt = /\/(java|ecma)script/i, Tt = /^\s*\s*$/g, Nt = { option: [1, ""], legend: [1, "
    ", "
    "], thead: [1, "", "
    "], tr: [2, "", "
    "], td: [3, "", "
    "], col: [2, "", "
    "], area: [1, "", ""], _default: [0, "", ""] }, Ct = lt(i), kt = Ct.appendChild(i.createElement("div")); Nt.optgroup = Nt.option, Nt.tbody = Nt.tfoot = Nt.colgroup = Nt.caption = Nt.thead, Nt.th = Nt.td, v.support.htmlSerialize || (Nt._default = [1, "X
    ", "
    "]), v.fn.extend({ text: function (e) { return v.access(this, function (e) { return e === t ? v.text(this) : this.empty().append((this[0] && this[0].ownerDocument || i).createTextNode(e)) }, null, e, arguments.length) }, wrapAll: function (e) { if (v.isFunction(e)) return this.each(function (t) { v(this).wrapAll(e.call(this, t)) }); if (this[0]) { var t = v(e, this[0].ownerDocument).eq(0).clone(!0); this[0].parentNode && t.insertBefore(this[0]), t.map(function () { var e = this; while (e.firstChild && e.firstChild.nodeType === 1) e = e.firstChild; return e }).append(this) } return this }, wrapInner: function (e) { return v.isFunction(e) ? this.each(function (t) { v(this).wrapInner(e.call(this, t)) }) : this.each(function () { var t = v(this), n = t.contents(); n.length ? n.wrapAll(e) : t.append(e) }) }, wrap: function (e) { var t = v.isFunction(e); return this.each(function (n) { v(this).wrapAll(t ? e.call(this, n) : e) }) }, unwrap: function () { return this.parent().each(function () { v.nodeName(this, "body") || v(this).replaceWith(this.childNodes) }).end() }, append: function () { return this.domManip(arguments, !0, function (e) { (this.nodeType === 1 || this.nodeType === 11) && this.appendChild(e) }) }, prepend: function () { return this.domManip(arguments, !0, function (e) { (this.nodeType === 1 || this.nodeType === 11) && this.insertBefore(e, this.firstChild) }) }, before: function () { if (!ut(this[0])) return this.domManip(arguments, !1, function (e) { this.parentNode.insertBefore(e, this) }); if (arguments.length) { var e = v.clean(arguments); return this.pushStack(v.merge(e, this), "before", this.selector) } }, after: function () { if (!ut(this[0])) return this.domManip(arguments, !1, function (e) { this.parentNode.insertBefore(e, this.nextSibling) }); if (arguments.length) { var e = v.clean(arguments); return this.pushStack(v.merge(this, e), "after", this.selector) } }, remove: function (e, t) { var n, r = 0; for (; (n = this[r]) != null; r++)if (!e || v.filter(e, [n]).length) !t && n.nodeType === 1 && (v.cleanData(n.getElementsByTagName("*")), v.cleanData([n])), n.parentNode && n.parentNode.removeChild(n); return this }, empty: function () { var e, t = 0; for (; (e = this[t]) != null; t++) { e.nodeType === 1 && v.cleanData(e.getElementsByTagName("*")); while (e.firstChild) e.removeChild(e.firstChild) } return this }, clone: function (e, t) { return e = e == null ? !1 : e, t = t == null ? e : t, this.map(function () { return v.clone(this, e, t) }) }, html: function (e) { return v.access(this, function (e) { var n = this[0] || {}, r = 0, i = this.length; if (e === t) return n.nodeType === 1 ? n.innerHTML.replace(ht, "") : t; if (typeof e == "string" && !yt.test(e) && (v.support.htmlSerialize || !wt.test(e)) && (v.support.leadingWhitespace || !pt.test(e)) && !Nt[(vt.exec(e) || ["", ""])[1].toLowerCase()]) { e = e.replace(dt, "<$1>"); try { for (; r < i; r++)n = this[r] || {}, n.nodeType === 1 && (v.cleanData(n.getElementsByTagName("*")), n.innerHTML = e); n = 0 } catch (s) { } } n && this.empty().append(e) }, null, e, arguments.length) }, replaceWith: function (e) { return ut(this[0]) ? this.length ? this.pushStack(v(v.isFunction(e) ? e() : e), "replaceWith", e) : this : v.isFunction(e) ? this.each(function (t) { var n = v(this), r = n.html(); n.replaceWith(e.call(this, t, r)) }) : (typeof e != "string" && (e = v(e).detach()), this.each(function () { var t = this.nextSibling, n = this.parentNode; v(this).remove(), t ? v(t).before(e) : v(n).append(e) })) }, detach: function (e) { return this.remove(e, !0) }, domManip: function (e, n, r) { e = [].concat.apply([], e); var i, s, o, u, a = 0, f = e[0], l = [], c = this.length; if (!v.support.checkClone && c > 1 && typeof f == "string" && St.test(f)) return this.each(function () { v(this).domManip(e, n, r) }); if (v.isFunction(f)) return this.each(function (i) { var s = v(this); e[0] = f.call(this, i, n ? s.html() : t), s.domManip(e, n, r) }); if (this[0]) { i = v.buildFragment(e, this, l), o = i.fragment, s = o.firstChild, o.childNodes.length === 1 && (o = s); if (s) { n = n && v.nodeName(s, "tr"); for (u = i.cacheable || c - 1; a < c; a++)r.call(n && v.nodeName(this[a], "table") ? Lt(this[a], "tbody") : this[a], a === u ? o : v.clone(o, !0, !0)) } o = s = null, l.length && v.each(l, function (e, t) { t.src ? v.ajax ? v.ajax({ url: t.src, type: "GET", dataType: "script", async: !1, global: !1, "throws": !0 }) : v.error("no ajax") : v.globalEval((t.text || t.textContent || t.innerHTML || "").replace(Tt, "")), t.parentNode && t.parentNode.removeChild(t) }) } return this } }), v.buildFragment = function (e, n, r) { var s, o, u, a = e[0]; return n = n || i, n = !n.nodeType && n[0] || n, n = n.ownerDocument || n, e.length === 1 && typeof a == "string" && a.length < 512 && n === i && a.charAt(0) === "<" && !bt.test(a) && (v.support.checkClone || !St.test(a)) && (v.support.html5Clone || !wt.test(a)) && (o = !0, s = v.fragments[a], u = s !== t), s || (s = n.createDocumentFragment(), v.clean(e, n, s, r), o && (v.fragments[a] = u && s)), { fragment: s, cacheable: o } }, v.fragments = {}, v.each({ appendTo: "append", prependTo: "prepend", insertBefore: "before", insertAfter: "after", replaceAll: "replaceWith" }, function (e, t) { v.fn[e] = function (n) { var r, i = 0, s = [], o = v(n), u = o.length, a = this.length === 1 && this[0].parentNode; if ((a == null || a && a.nodeType === 11 && a.childNodes.length === 1) && u === 1) return o[t](this[0]), this; for (; i < u; i++)r = (i > 0 ? this.clone(!0) : this).get(), v(o[i])[t](r), s = s.concat(r); return this.pushStack(s, e, o.selector) } }), v.extend({ clone: function (e, t, n) { var r, i, s, o; v.support.html5Clone || v.isXMLDoc(e) || !wt.test("<" + e.nodeName + ">") ? o = e.cloneNode(!0) : (kt.innerHTML = e.outerHTML, kt.removeChild(o = kt.firstChild)); if ((!v.support.noCloneEvent || !v.support.noCloneChecked) && (e.nodeType === 1 || e.nodeType === 11) && !v.isXMLDoc(e)) { Ot(e, o), r = Mt(e), i = Mt(o); for (s = 0; r[s]; ++s)i[s] && Ot(r[s], i[s]) } if (t) { At(e, o); if (n) { r = Mt(e), i = Mt(o); for (s = 0; r[s]; ++s)At(r[s], i[s]) } } return r = i = null, o }, clean: function (e, t, n, r) { var s, o, u, a, f, l, c, h, p, d, m, g, y = t === i && Ct, b = []; if (!t || typeof t.createDocumentFragment == "undefined") t = i; for (s = 0; (u = e[s]) != null; s++) { typeof u == "number" && (u += ""); if (!u) continue; if (typeof u == "string") if (!gt.test(u)) u = t.createTextNode(u); else { y = y || lt(t), c = t.createElement("div"), y.appendChild(c), u = u.replace(dt, "<$1>"), a = (vt.exec(u) || ["", ""])[1].toLowerCase(), f = Nt[a] || Nt._default, l = f[0], c.innerHTML = f[1] + u + f[2]; while (l--) c = c.lastChild; if (!v.support.tbody) { h = mt.test(u), p = a === "table" && !h ? c.firstChild && c.firstChild.childNodes : f[1] === "" && !h ? c.childNodes : []; for (o = p.length - 1; o >= 0; --o)v.nodeName(p[o], "tbody") && !p[o].childNodes.length && p[o].parentNode.removeChild(p[o]) } !v.support.leadingWhitespace && pt.test(u) && c.insertBefore(t.createTextNode(pt.exec(u)[0]), c.firstChild), u = c.childNodes, c.parentNode.removeChild(c) } u.nodeType ? b.push(u) : v.merge(b, u) } c && (u = c = y = null); if (!v.support.appendChecked) for (s = 0; (u = b[s]) != null; s++)v.nodeName(u, "input") ? _t(u) : typeof u.getElementsByTagName != "undefined" && v.grep(u.getElementsByTagName("input"), _t); if (n) { m = function (e) { if (!e.type || xt.test(e.type)) return r ? r.push(e.parentNode ? e.parentNode.removeChild(e) : e) : n.appendChild(e) }; for (s = 0; (u = b[s]) != null; s++)if (!v.nodeName(u, "script") || !m(u)) n.appendChild(u), typeof u.getElementsByTagName != "undefined" && (g = v.grep(v.merge([], u.getElementsByTagName("script")), m), b.splice.apply(b, [s + 1, 0].concat(g)), s += g.length) } return b }, cleanData: function (e, t) { var n, r, i, s, o = 0, u = v.expando, a = v.cache, f = v.support.deleteExpando, l = v.event.special; for (; (i = e[o]) != null; o++)if (t || v.acceptData(i)) { r = i[u], n = r && a[r]; if (n) { if (n.events) for (s in n.events) l[s] ? v.event.remove(i, s) : v.removeEvent(i, s, n.handle); a[r] && (delete a[r], f ? delete i[u] : i.removeAttribute ? i.removeAttribute(u) : i[u] = null, v.deletedIds.push(r)) } } } }), function () { var e, t; v.uaMatch = function (e) { e = e.toLowerCase(); var t = /(chrome)[ \/]([\w.]+)/.exec(e) || /(webkit)[ \/]([\w.]+)/.exec(e) || /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(e) || /(msie) ([\w.]+)/.exec(e) || e.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(e) || []; return { browser: t[1] || "", version: t[2] || "0" } }, e = v.uaMatch(o.userAgent), t = {}, e.browser && (t[e.browser] = !0, t.version = e.version), t.chrome ? t.webkit = !0 : t.webkit && (t.safari = !0), v.browser = t, v.sub = function () { function e (t, n) { return new e.fn.init(t, n) } v.extend(!0, e, this), e.superclass = this, e.fn = e.prototype = this(), e.fn.constructor = e, e.sub = this.sub, e.fn.init = function (r, i) { return i && i instanceof v && !(i instanceof e) && (i = e(i)), v.fn.init.call(this, r, i, t) }, e.fn.init.prototype = e.fn; var t = e(i); return e } }(); var Dt, Pt, Ht, Bt = /alpha\([^)]*\)/i, jt = /opacity=([^)]*)/, Ft = /^(top|right|bottom|left)$/, It = /^(none|table(?!-c[ea]).+)/, qt = /^margin/, Rt = new RegExp("^(" + m + ")(.*)$", "i"), Ut = new RegExp("^(" + m + ")(?!px)[a-z%]+$", "i"), zt = new RegExp("^([-+])=(" + m + ")", "i"), Wt = { BODY: "block" }, Xt = { position: "absolute", visibility: "hidden", display: "block" }, Vt = { letterSpacing: 0, fontWeight: 400 }, $t = ["Top", "Right", "Bottom", "Left"], Jt = ["Webkit", "O", "Moz", "ms"], Kt = v.fn.toggle; v.fn.extend({ css: function (e, n) { return v.access(this, function (e, n, r) { return r !== t ? v.style(e, n, r) : v.css(e, n) }, e, n, arguments.length > 1) }, show: function () { return Yt(this, !0) }, hide: function () { return Yt(this) }, toggle: function (e, t) { var n = typeof e == "boolean"; return v.isFunction(e) && v.isFunction(t) ? Kt.apply(this, arguments) : this.each(function () { (n ? e : Gt(this)) ? v(this).show() : v(this).hide() }) } }), v.extend({ cssHooks: { opacity: { get: function (e, t) { if (t) { var n = Dt(e, "opacity"); return n === "" ? "1" : n } } } }, cssNumber: { fillOpacity: !0, fontWeight: !0, lineHeight: !0, opacity: !0, orphans: !0, widows: !0, zIndex: !0, zoom: !0 }, cssProps: { "float": v.support.cssFloat ? "cssFloat" : "styleFloat" }, style: function (e, n, r, i) { if (!e || e.nodeType === 3 || e.nodeType === 8 || !e.style) return; var s, o, u, a = v.camelCase(n), f = e.style; n = v.cssProps[a] || (v.cssProps[a] = Qt(f, a)), u = v.cssHooks[n] || v.cssHooks[a]; if (r === t) return u && "get" in u && (s = u.get(e, !1, i)) !== t ? s : f[n]; o = typeof r, o === "string" && (s = zt.exec(r)) && (r = (s[1] + 1) * s[2] + parseFloat(v.css(e, n)), o = "number"); if (r == null || o === "number" && isNaN(r)) return; o === "number" && !v.cssNumber[a] && (r += "px"); if (!u || !("set" in u) || (r = u.set(e, r, i)) !== t) try { f[n] = r } catch (l) { } }, css: function (e, n, r, i) { var s, o, u, a = v.camelCase(n); return n = v.cssProps[a] || (v.cssProps[a] = Qt(e.style, a)), u = v.cssHooks[n] || v.cssHooks[a], u && "get" in u && (s = u.get(e, !0, i)), s === t && (s = Dt(e, n)), s === "normal" && n in Vt && (s = Vt[n]), r || i !== t ? (o = parseFloat(s), r || v.isNumeric(o) ? o || 0 : s) : s }, swap: function (e, t, n) { var r, i, s = {}; for (i in t) s[i] = e.style[i], e.style[i] = t[i]; r = n.call(e); for (i in t) e.style[i] = s[i]; return r } }), e.getComputedStyle ? Dt = function (t, n) { var r, i, s, o, u = e.getComputedStyle(t, null), a = t.style; return u && (r = u.getPropertyValue(n) || u[n], r === "" && !v.contains(t.ownerDocument, t) && (r = v.style(t, n)), Ut.test(r) && qt.test(n) && (i = a.width, s = a.minWidth, o = a.maxWidth, a.minWidth = a.maxWidth = a.width = r, r = u.width, a.width = i, a.minWidth = s, a.maxWidth = o)), r } : i.documentElement.currentStyle && (Dt = function (e, t) { var n, r, i = e.currentStyle && e.currentStyle[t], s = e.style; return i == null && s && s[t] && (i = s[t]), Ut.test(i) && !Ft.test(t) && (n = s.left, r = e.runtimeStyle && e.runtimeStyle.left, r && (e.runtimeStyle.left = e.currentStyle.left), s.left = t === "fontSize" ? "1em" : i, i = s.pixelLeft + "px", s.left = n, r && (e.runtimeStyle.left = r)), i === "" ? "auto" : i }), v.each(["height", "width"], function (e, t) { v.cssHooks[t] = { get: function (e, n, r) { if (n) return e.offsetWidth === 0 && It.test(Dt(e, "display")) ? v.swap(e, Xt, function () { return tn(e, t, r) }) : tn(e, t, r) }, set: function (e, n, r) { return Zt(e, n, r ? en(e, t, r, v.support.boxSizing && v.css(e, "boxSizing") === "border-box") : 0) } } }), v.support.opacity || (v.cssHooks.opacity = { get: function (e, t) { return jt.test((t && e.currentStyle ? e.currentStyle.filter : e.style.filter) || "") ? .01 * parseFloat(RegExp.$1) + "" : t ? "1" : "" }, set: function (e, t) { var n = e.style, r = e.currentStyle, i = v.isNumeric(t) ? "alpha(opacity=" + t * 100 + ")" : "", s = r && r.filter || n.filter || ""; n.zoom = 1; if (t >= 1 && v.trim(s.replace(Bt, "")) === "" && n.removeAttribute) { n.removeAttribute("filter"); if (r && !r.filter) return } n.filter = Bt.test(s) ? s.replace(Bt, i) : s + " " + i } }), v(function () { v.support.reliableMarginRight || (v.cssHooks.marginRight = { get: function (e, t) { return v.swap(e, { display: "inline-block" }, function () { if (t) return Dt(e, "marginRight") }) } }), !v.support.pixelPosition && v.fn.position && v.each(["top", "left"], function (e, t) { v.cssHooks[t] = { get: function (e, n) { if (n) { var r = Dt(e, t); return Ut.test(r) ? v(e).position()[t] + "px" : r } } } }) }), v.expr && v.expr.filters && (v.expr.filters.hidden = function (e) { return e.offsetWidth === 0 && e.offsetHeight === 0 || !v.support.reliableHiddenOffsets && (e.style && e.style.display || Dt(e, "display")) === "none" }, v.expr.filters.visible = function (e) { return !v.expr.filters.hidden(e) }), v.each({ margin: "", padding: "", border: "Width" }, function (e, t) { v.cssHooks[e + t] = { expand: function (n) { var r, i = typeof n == "string" ? n.split(" ") : [n], s = {}; for (r = 0; r < 4; r++)s[e + $t[r] + t] = i[r] || i[r - 2] || i[0]; return s } }, qt.test(e) || (v.cssHooks[e + t].set = Zt) }); var rn = /%20/g, sn = /\[\]$/, on = /\r?\n/g, un = /^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i, an = /^(?:select|textarea)/i; v.fn.extend({ serialize: function () { return v.param(this.serializeArray()) }, serializeArray: function () { return this.map(function () { return this.elements ? v.makeArray(this.elements) : this }).filter(function () { return this.name && !this.disabled && (this.checked || an.test(this.nodeName) || un.test(this.type)) }).map(function (e, t) { var n = v(this).val(); return n == null ? null : v.isArray(n) ? v.map(n, function (e, n) { return { name: t.name, value: e.replace(on, "\r\n") } }) : { name: t.name, value: n.replace(on, "\r\n") } }).get() } }), v.param = function (e, n) { var r, i = [], s = function (e, t) { t = v.isFunction(t) ? t() : t == null ? "" : t, i[i.length] = encodeURIComponent(e) + "=" + encodeURIComponent(t) }; n === t && (n = v.ajaxSettings && v.ajaxSettings.traditional); if (v.isArray(e) || e.jquery && !v.isPlainObject(e)) v.each(e, function () { s(this.name, this.value) }); else for (r in e) fn(r, e[r], n, s); return i.join("&").replace(rn, "+") }; var ln, cn, hn = /#.*$/, pn = /^(.*?):[ \t]*([^\r\n]*)\r?$/mg, dn = /^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/, vn = /^(?:GET|HEAD)$/, mn = /^\/\//, gn = /\?/, yn = /)<[^<]*)*<\/script>/gi, bn = /([?&])_=[^&]*/, wn = /^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/, En = v.fn.load, Sn = {}, xn = {}, Tn = ["*/"] + ["*"]; try { cn = s.href } catch (Nn) { cn = i.createElement("a"), cn.href = "", cn = cn.href } ln = wn.exec(cn.toLowerCase()) || [], v.fn.load = function (e, n, r) { if (typeof e != "string" && En) return En.apply(this, arguments); if (!this.length) return this; var i, s, o, u = this, a = e.indexOf(" "); return a >= 0 && (i = e.slice(a, e.length), e = e.slice(0, a)), v.isFunction(n) ? (r = n, n = t) : n && typeof n == "object" && (s = "POST"), v.ajax({ url: e, type: s, dataType: "html", data: n, complete: function (e, t) { r && u.each(r, o || [e.responseText, t, e]) } }).done(function (e) { o = arguments, u.html(i ? v("
    ").append(e.replace(yn, "")).find(i) : e) }), this }, v.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "), function (e, t) { v.fn[t] = function (e) { return this.on(t, e) } }), v.each(["get", "post"], function (e, n) { v[n] = function (e, r, i, s) { return v.isFunction(r) && (s = s || i, i = r, r = t), v.ajax({ type: n, url: e, data: r, success: i, dataType: s }) } }), v.extend({ getScript: function (e, n) { return v.get(e, t, n, "script") }, getJSON: function (e, t, n) { return v.get(e, t, n, "json") }, ajaxSetup: function (e, t) { return t ? Ln(e, v.ajaxSettings) : (t = e, e = v.ajaxSettings), Ln(e, t), e }, ajaxSettings: { url: cn, isLocal: dn.test(ln[1]), global: !0, type: "GET", contentType: "application/x-www-form-urlencoded; charset=UTF-8", processData: !0, async: !0, accepts: { xml: "application/xml, text/xml", html: "text/html", text: "text/plain", json: "application/json, text/javascript", "*": Tn }, contents: { xml: /xml/, html: /html/, json: /json/ }, responseFields: { xml: "responseXML", text: "responseText" }, converters: { "* text": e.String, "text html": !0, "text json": v.parseJSON, "text xml": v.parseXML }, flatOptions: { context: !0, url: !0 } }, ajaxPrefilter: Cn(Sn), ajaxTransport: Cn(xn), ajax: function (e, n) { function T (e, n, s, a) { var l, y, b, w, S, T = n; if (E === 2) return; E = 2, u && clearTimeout(u), o = t, i = a || "", x.readyState = e > 0 ? 4 : 0, s && (w = An(c, x, s)); if (e >= 200 && e < 300 || e === 304) c.ifModified && (S = x.getResponseHeader("Last-Modified"), S && (v.lastModified[r] = S), S = x.getResponseHeader("Etag"), S && (v.etag[r] = S)), e === 304 ? (T = "notmodified", l = !0) : (l = On(c, w), T = l.state, y = l.data, b = l.error, l = !b); else { b = T; if (!T || e) T = "error", e < 0 && (e = 0) } x.status = e, x.statusText = (n || T) + "", l ? d.resolveWith(h, [y, T, x]) : d.rejectWith(h, [x, T, b]), x.statusCode(g), g = t, f && p.trigger("ajax" + (l ? "Success" : "Error"), [x, c, l ? y : b]), m.fireWith(h, [x, T]), f && (p.trigger("ajaxComplete", [x, c]), --v.active || v.event.trigger("ajaxStop")) } typeof e == "object" && (n = e, e = t), n = n || {}; var r, i, s, o, u, a, f, l, c = v.ajaxSetup({}, n), h = c.context || c, p = h !== c && (h.nodeType || h instanceof v) ? v(h) : v.event, d = v.Deferred(), m = v.Callbacks("once memory"), g = c.statusCode || {}, b = {}, w = {}, E = 0, S = "canceled", x = { readyState: 0, setRequestHeader: function (e, t) { if (!E) { var n = e.toLowerCase(); e = w[n] = w[n] || e, b[e] = t } return this }, getAllResponseHeaders: function () { return E === 2 ? i : null }, getResponseHeader: function (e) { var n; if (E === 2) { if (!s) { s = {}; while (n = pn.exec(i)) s[n[1].toLowerCase()] = n[2] } n = s[e.toLowerCase()] } return n === t ? null : n }, overrideMimeType: function (e) { return E || (c.mimeType = e), this }, abort: function (e) { return e = e || S, o && o.abort(e), T(0, e), this } }; d.promise(x), x.success = x.done, x.error = x.fail, x.complete = m.add, x.statusCode = function (e) { if (e) { var t; if (E < 2) for (t in e) g[t] = [g[t], e[t]]; else t = e[x.status], x.always(t) } return this }, c.url = ((e || c.url) + "").replace(hn, "").replace(mn, ln[1] + "//"), c.dataTypes = v.trim(c.dataType || "*").toLowerCase().split(y), c.crossDomain == null && (a = wn.exec(c.url.toLowerCase()), c.crossDomain = !(!a || a[1] === ln[1] && a[2] === ln[2] && (a[3] || (a[1] === "http:" ? 80 : 443)) == (ln[3] || (ln[1] === "http:" ? 80 : 443)))), c.data && c.processData && typeof c.data != "string" && (c.data = v.param(c.data, c.traditional)), kn(Sn, c, n, x); if (E === 2) return x; f = c.global, c.type = c.type.toUpperCase(), c.hasContent = !vn.test(c.type), f && v.active++ === 0 && v.event.trigger("ajaxStart"); if (!c.hasContent) { c.data && (c.url += (gn.test(c.url) ? "&" : "?") + c.data, delete c.data), r = c.url; if (c.cache === !1) { var N = v.now(), C = c.url.replace(bn, "$1_=" + N); c.url = C + (C === c.url ? (gn.test(c.url) ? "&" : "?") + "_=" + N : "") } } (c.data && c.hasContent && c.contentType !== !1 || n.contentType) && x.setRequestHeader("Content-Type", c.contentType), c.ifModified && (r = r || c.url, v.lastModified[r] && x.setRequestHeader("If-Modified-Since", v.lastModified[r]), v.etag[r] && x.setRequestHeader("If-None-Match", v.etag[r])), x.setRequestHeader("Accept", c.dataTypes[0] && c.accepts[c.dataTypes[0]] ? c.accepts[c.dataTypes[0]] + (c.dataTypes[0] !== "*" ? ", " + Tn + "; q=0.01" : "") : c.accepts["*"]); for (l in c.headers) x.setRequestHeader(l, c.headers[l]); if (!c.beforeSend || c.beforeSend.call(h, x, c) !== !1 && E !== 2) { S = "abort"; for (l in { success: 1, error: 1, complete: 1 }) x[l](c[l]); o = kn(xn, c, n, x); if (!o) T(-1, "No Transport"); else { x.readyState = 1, f && p.trigger("ajaxSend", [x, c]), c.async && c.timeout > 0 && (u = setTimeout(function () { x.abort("timeout") }, c.timeout)); try { E = 1, o.send(b, T) } catch (k) { if (!(E < 2)) throw k; T(-1, k) } } return x } return x.abort() }, active: 0, lastModified: {}, etag: {} }); var Mn = [], _n = /\?/, Dn = /(=)\?(?=&|$)|\?\?/, Pn = v.now(); v.ajaxSetup({ jsonp: "callback", jsonpCallback: function () { var e = Mn.pop() || v.expando + "_" + Pn++; return this[e] = !0, e } }), v.ajaxPrefilter("json jsonp", function (n, r, i) { var s, o, u, a = n.data, f = n.url, l = n.jsonp !== !1, c = l && Dn.test(f), h = l && !c && typeof a == "string" && !(n.contentType || "").indexOf("application/x-www-form-urlencoded") && Dn.test(a); if (n.dataTypes[0] === "jsonp" || c || h) return s = n.jsonpCallback = v.isFunction(n.jsonpCallback) ? n.jsonpCallback() : n.jsonpCallback, o = e[s], c ? n.url = f.replace(Dn, "$1" + s) : h ? n.data = a.replace(Dn, "$1" + s) : l && (n.url += (_n.test(f) ? "&" : "?") + n.jsonp + "=" + s), n.converters["script json"] = function () { return u || v.error(s + " was not called"), u[0] }, n.dataTypes[0] = "json", e[s] = function () { u = arguments }, i.always(function () { e[s] = o, n[s] && (n.jsonpCallback = r.jsonpCallback, Mn.push(s)), u && v.isFunction(o) && o(u[0]), u = o = t }), "script" }), v.ajaxSetup({ accepts: { script: "text/javascript, application/javascript, application/ecmascript, application/x-ecmascript" }, contents: { script: /javascript|ecmascript/ }, converters: { "text script": function (e) { return v.globalEval(e), e } } }), v.ajaxPrefilter("script", function (e) { e.cache === t && (e.cache = !1), e.crossDomain && (e.type = "GET", e.global = !1) }), v.ajaxTransport("script", function (e) { if (e.crossDomain) { var n, r = i.head || i.getElementsByTagName("head")[0] || i.documentElement; return { send: function (s, o) { n = i.createElement("script"), n.async = "async", e.scriptCharset && (n.charset = e.scriptCharset), n.src = e.url, n.onload = n.onreadystatechange = function (e, i) { if (i || !n.readyState || /loaded|complete/.test(n.readyState)) n.onload = n.onreadystatechange = null, r && n.parentNode && r.removeChild(n), n = t, i || o(200, "success") }, r.insertBefore(n, r.firstChild) }, abort: function () { n && n.onload(0, 1) } } } }); var Hn, Bn = e.ActiveXObject ? function () { for (var e in Hn) Hn[e](0, 1) } : !1, jn = 0; v.ajaxSettings.xhr = e.ActiveXObject ? function () { return !this.isLocal && Fn() || In() } : Fn, function (e) { v.extend(v.support, { ajax: !!e, cors: !!e && "withCredentials" in e }) }(v.ajaxSettings.xhr()), v.support.ajax && v.ajaxTransport(function (n) { if (!n.crossDomain || v.support.cors) { var r; return { send: function (i, s) { var o, u, a = n.xhr(); n.username ? a.open(n.type, n.url, n.async, n.username, n.password) : a.open(n.type, n.url, n.async); if (n.xhrFields) for (u in n.xhrFields) a[u] = n.xhrFields[u]; n.mimeType && a.overrideMimeType && a.overrideMimeType(n.mimeType), !n.crossDomain && !i["X-Requested-With"] && (i["X-Requested-With"] = "XMLHttpRequest"); try { for (u in i) a.setRequestHeader(u, i[u]) } catch (f) { } a.send(n.hasContent && n.data || null), r = function (e, i) { var u, f, l, c, h; try { if (r && (i || a.readyState === 4)) { r = t, o && (a.onreadystatechange = v.noop, Bn && delete Hn[o]); if (i) a.readyState !== 4 && a.abort(); else { u = a.status, l = a.getAllResponseHeaders(), c = {}, h = a.responseXML, h && h.documentElement && (c.xml = h); try { c.text = a.responseText } catch (p) { } try { f = a.statusText } catch (p) { f = "" } !u && n.isLocal && !n.crossDomain ? u = c.text ? 200 : 404 : u === 1223 && (u = 204) } } } catch (d) { i || s(-1, d) } c && s(u, f, c, l) }, n.async ? a.readyState === 4 ? setTimeout(r, 0) : (o = ++jn, Bn && (Hn || (Hn = {}, v(e).unload(Bn)), Hn[o] = r), a.onreadystatechange = r) : r() }, abort: function () { r && r(0, 1) } } } }); var qn, Rn, Un = /^(?:toggle|show|hide)$/, zn = new RegExp("^(?:([-+])=|)(" + m + ")([a-z%]*)$", "i"), Wn = /queueHooks$/, Xn = [Gn], Vn = { "*": [function (e, t) { var n, r, i = this.createTween(e, t), s = zn.exec(t), o = i.cur(), u = +o || 0, a = 1, f = 20; if (s) { n = +s[2], r = s[3] || (v.cssNumber[e] ? "" : "px"); if (r !== "px" && u) { u = v.css(i.elem, e, !0) || n || 1; do a = a || ".5", u /= a, v.style(i.elem, e, u + r); while (a !== (a = i.cur() / o) && a !== 1 && --f) } i.unit = r, i.start = u, i.end = s[1] ? u + (s[1] + 1) * n : n } return i }] }; v.Animation = v.extend(Kn, { tweener: function (e, t) { v.isFunction(e) ? (t = e, e = ["*"]) : e = e.split(" "); var n, r = 0, i = e.length; for (; r < i; r++)n = e[r], Vn[n] = Vn[n] || [], Vn[n].unshift(t) }, prefilter: function (e, t) { t ? Xn.unshift(e) : Xn.push(e) } }), v.Tween = Yn, Yn.prototype = { constructor: Yn, init: function (e, t, n, r, i, s) { this.elem = e, this.prop = n, this.easing = i || "swing", this.options = t, this.start = this.now = this.cur(), this.end = r, this.unit = s || (v.cssNumber[n] ? "" : "px") }, cur: function () { var e = Yn.propHooks[this.prop]; return e && e.get ? e.get(this) : Yn.propHooks._default.get(this) }, run: function (e) { var t, n = Yn.propHooks[this.prop]; return this.options.duration ? this.pos = t = v.easing[this.easing](e, this.options.duration * e, 0, 1, this.options.duration) : this.pos = t = e, this.now = (this.end - this.start) * t + this.start, this.options.step && this.options.step.call(this.elem, this.now, this), n && n.set ? n.set(this) : Yn.propHooks._default.set(this), this } }, Yn.prototype.init.prototype = Yn.prototype, Yn.propHooks = { _default: { get: function (e) { var t; return e.elem[e.prop] == null || !!e.elem.style && e.elem.style[e.prop] != null ? (t = v.css(e.elem, e.prop, !1, ""), !t || t === "auto" ? 0 : t) : e.elem[e.prop] }, set: function (e) { v.fx.step[e.prop] ? v.fx.step[e.prop](e) : e.elem.style && (e.elem.style[v.cssProps[e.prop]] != null || v.cssHooks[e.prop]) ? v.style(e.elem, e.prop, e.now + e.unit) : e.elem[e.prop] = e.now } } }, Yn.propHooks.scrollTop = Yn.propHooks.scrollLeft = { set: function (e) { e.elem.nodeType && e.elem.parentNode && (e.elem[e.prop] = e.now) } }, v.each(["toggle", "show", "hide"], function (e, t) { var n = v.fn[t]; v.fn[t] = function (r, i, s) { return r == null || typeof r == "boolean" || !e && v.isFunction(r) && v.isFunction(i) ? n.apply(this, arguments) : this.animate(Zn(t, !0), r, i, s) } }), v.fn.extend({ fadeTo: function (e, t, n, r) { return this.filter(Gt).css("opacity", 0).show().end().animate({ opacity: t }, e, n, r) }, animate: function (e, t, n, r) { var i = v.isEmptyObject(e), s = v.speed(t, n, r), o = function () { var t = Kn(this, v.extend({}, e), s); i && t.stop(!0) }; return i || s.queue === !1 ? this.each(o) : this.queue(s.queue, o) }, stop: function (e, n, r) { var i = function (e) { var t = e.stop; delete e.stop, t(r) }; return typeof e != "string" && (r = n, n = e, e = t), n && e !== !1 && this.queue(e || "fx", []), this.each(function () { var t = !0, n = e != null && e + "queueHooks", s = v.timers, o = v._data(this); if (n) o[n] && o[n].stop && i(o[n]); else for (n in o) o[n] && o[n].stop && Wn.test(n) && i(o[n]); for (n = s.length; n--;)s[n].elem === this && (e == null || s[n].queue === e) && (s[n].anim.stop(r), t = !1, s.splice(n, 1)); (t || !r) && v.dequeue(this, e) }) } }), v.each({ slideDown: Zn("show"), slideUp: Zn("hide"), slideToggle: Zn("toggle"), fadeIn: { opacity: "show" }, fadeOut: { opacity: "hide" }, fadeToggle: { opacity: "toggle" } }, function (e, t) { v.fn[e] = function (e, n, r) { return this.animate(t, e, n, r) } }), v.speed = function (e, t, n) { var r = e && typeof e == "object" ? v.extend({}, e) : { complete: n || !n && t || v.isFunction(e) && e, duration: e, easing: n && t || t && !v.isFunction(t) && t }; r.duration = v.fx.off ? 0 : typeof r.duration == "number" ? r.duration : r.duration in v.fx.speeds ? v.fx.speeds[r.duration] : v.fx.speeds._default; if (r.queue == null || r.queue === !0) r.queue = "fx"; return r.old = r.complete, r.complete = function () { v.isFunction(r.old) && r.old.call(this), r.queue && v.dequeue(this, r.queue) }, r }, v.easing = { linear: function (e) { return e }, swing: function (e) { return .5 - Math.cos(e * Math.PI) / 2 } }, v.timers = [], v.fx = Yn.prototype.init, v.fx.tick = function () { var e, n = v.timers, r = 0; qn = v.now(); for (; r < n.length; r++)e = n[r], !e() && n[r] === e && n.splice(r--, 1); n.length || v.fx.stop(), qn = t }, v.fx.timer = function (e) { e() && v.timers.push(e) && !Rn && (Rn = setInterval(v.fx.tick, v.fx.interval)) }, v.fx.interval = 13, v.fx.stop = function () { clearInterval(Rn), Rn = null }, v.fx.speeds = { slow: 600, fast: 200, _default: 400 }, v.fx.step = {}, v.expr && v.expr.filters && (v.expr.filters.animated = function (e) { return v.grep(v.timers, function (t) { return e === t.elem }).length }); var er = /^(?:body|html)$/i; v.fn.offset = function (e) { if (arguments.length) return e === t ? this : this.each(function (t) { v.offset.setOffset(this, e, t) }); var n, r, i, s, o, u, a, f = { top: 0, left: 0 }, l = this[0], c = l && l.ownerDocument; if (!c) return; return (r = c.body) === l ? v.offset.bodyOffset(l) : (n = c.documentElement, v.contains(n, l) ? (typeof l.getBoundingClientRect != "undefined" && (f = l.getBoundingClientRect()), i = tr(c), s = n.clientTop || r.clientTop || 0, o = n.clientLeft || r.clientLeft || 0, u = i.pageYOffset || n.scrollTop, a = i.pageXOffset || n.scrollLeft, { top: f.top + u - s, left: f.left + a - o }) : f) }, v.offset = { bodyOffset: function (e) { var t = e.offsetTop, n = e.offsetLeft; return v.support.doesNotIncludeMarginInBodyOffset && (t += parseFloat(v.css(e, "marginTop")) || 0, n += parseFloat(v.css(e, "marginLeft")) || 0), { top: t, left: n } }, setOffset: function (e, t, n) { var r = v.css(e, "position"); r === "static" && (e.style.position = "relative"); var i = v(e), s = i.offset(), o = v.css(e, "top"), u = v.css(e, "left"), a = (r === "absolute" || r === "fixed") && v.inArray("auto", [o, u]) > -1, f = {}, l = {}, c, h; a ? (l = i.position(), c = l.top, h = l.left) : (c = parseFloat(o) || 0, h = parseFloat(u) || 0), v.isFunction(t) && (t = t.call(e, n, s)), t.top != null && (f.top = t.top - s.top + c), t.left != null && (f.left = t.left - s.left + h), "using" in t ? t.using.call(e, f) : i.css(f) } }, v.fn.extend({ position: function () { if (!this[0]) return; var e = this[0], t = this.offsetParent(), n = this.offset(), r = er.test(t[0].nodeName) ? { top: 0, left: 0 } : t.offset(); return n.top -= parseFloat(v.css(e, "marginTop")) || 0, n.left -= parseFloat(v.css(e, "marginLeft")) || 0, r.top += parseFloat(v.css(t[0], "borderTopWidth")) || 0, r.left += parseFloat(v.css(t[0], "borderLeftWidth")) || 0, { top: n.top - r.top, left: n.left - r.left } }, offsetParent: function () { return this.map(function () { var e = this.offsetParent || i.body; while (e && !er.test(e.nodeName) && v.css(e, "position") === "static") e = e.offsetParent; return e || i.body }) } }), v.each({ scrollLeft: "pageXOffset", scrollTop: "pageYOffset" }, function (e, n) { var r = /Y/.test(n); v.fn[e] = function (i) { return v.access(this, function (e, i, s) { var o = tr(e); if (s === t) return o ? n in o ? o[n] : o.document.documentElement[i] : e[i]; o ? o.scrollTo(r ? v(o).scrollLeft() : s, r ? s : v(o).scrollTop()) : e[i] = s }, e, i, arguments.length, null) } }), v.each({ Height: "height", Width: "width" }, function (e, n) { v.each({ padding: "inner" + e, content: n, "": "outer" + e }, function (r, i) { v.fn[i] = function (i, s) { var o = arguments.length && (r || typeof i != "boolean"), u = r || (i === !0 || s === !0 ? "margin" : "border"); return v.access(this, function (n, r, i) { var s; return v.isWindow(n) ? n.document.documentElement["client" + e] : n.nodeType === 9 ? (s = n.documentElement, Math.max(n.body["scroll" + e], s["scroll" + e], n.body["offset" + e], s["offset" + e], s["client" + e])) : i === t ? v.css(n, r, i, u) : v.style(n, r, i, u) }, n, o ? i : t, o, null) } }) }), e.jQuery = e.$ = v, typeof define == "function" && define.amd && define.amd.jQuery && define("jquery", [], function () { return v }) })(window); \ No newline at end of file diff --git "a/web/117 \344\270\212\346\265\267\345\270\202\345\233\276\344\271\246\351\246\206\345\244\247\345\261\217\347\234\213\346\235\277/static/jquery.min.js" "b/web/117 \344\270\212\346\265\267\345\270\202\345\233\276\344\271\246\351\246\206\345\244\247\345\261\217\347\234\213\346\235\277/static/jquery.min.js" new file mode 100644 index 00000000..e6a051d0 --- /dev/null +++ "b/web/117 \344\270\212\346\265\267\345\270\202\345\233\276\344\271\246\351\246\206\345\244\247\345\261\217\347\234\213\346\235\277/static/jquery.min.js" @@ -0,0 +1,4 @@ +/*! jQuery v1.11.2 | (c) 2005, 2014 jQuery Foundation, Inc. | jquery.org/license */ +!function(a,b){"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){var c=[],d=c.slice,e=c.concat,f=c.push,g=c.indexOf,h={},i=h.toString,j=h.hasOwnProperty,k={},l="1.11.2",m=function(a,b){return new m.fn.init(a,b)},n=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,o=/^-ms-/,p=/-([\da-z])/gi,q=function(a,b){return b.toUpperCase()};m.fn=m.prototype={jquery:l,constructor:m,selector:"",length:0,toArray:function(){return d.call(this)},get:function(a){return null!=a?0>a?this[a+this.length]:this[a]:d.call(this)},pushStack:function(a){var b=m.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a,b){return m.each(this,a,b)},map:function(a){return this.pushStack(m.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(d.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor(null)},push:f,sort:c.sort,splice:c.splice},m.extend=m.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||m.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(e=arguments[h]))for(d in e)a=g[d],c=e[d],g!==c&&(j&&c&&(m.isPlainObject(c)||(b=m.isArray(c)))?(b?(b=!1,f=a&&m.isArray(a)?a:[]):f=a&&m.isPlainObject(a)?a:{},g[d]=m.extend(j,f,c)):void 0!==c&&(g[d]=c));return g},m.extend({expando:"jQuery"+(l+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===m.type(a)},isArray:Array.isArray||function(a){return"array"===m.type(a)},isWindow:function(a){return null!=a&&a==a.window},isNumeric:function(a){return!m.isArray(a)&&a-parseFloat(a)+1>=0},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},isPlainObject:function(a){var b;if(!a||"object"!==m.type(a)||a.nodeType||m.isWindow(a))return!1;try{if(a.constructor&&!j.call(a,"constructor")&&!j.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}if(k.ownLast)for(b in a)return j.call(a,b);for(b in a);return void 0===b||j.call(a,b)},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?h[i.call(a)]||"object":typeof a},globalEval:function(b){b&&m.trim(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(o,"ms-").replace(p,q)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b,c){var d,e=0,f=a.length,g=r(a);if(c){if(g){for(;f>e;e++)if(d=b.apply(a[e],c),d===!1)break}else for(e in a)if(d=b.apply(a[e],c),d===!1)break}else if(g){for(;f>e;e++)if(d=b.call(a[e],e,a[e]),d===!1)break}else for(e in a)if(d=b.call(a[e],e,a[e]),d===!1)break;return a},trim:function(a){return null==a?"":(a+"").replace(n,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(r(Object(a))?m.merge(c,"string"==typeof a?[a]:a):f.call(c,a)),c},inArray:function(a,b,c){var d;if(b){if(g)return g.call(b,a,c);for(d=b.length,c=c?0>c?Math.max(0,d+c):c:0;d>c;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,b){var c=+b.length,d=0,e=a.length;while(c>d)a[e++]=b[d++];if(c!==c)while(void 0!==b[d])a[e++]=b[d++];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,f=0,g=a.length,h=r(a),i=[];if(h)for(;g>f;f++)d=b(a[f],f,c),null!=d&&i.push(d);else for(f in a)d=b(a[f],f,c),null!=d&&i.push(d);return e.apply([],i)},guid:1,proxy:function(a,b){var c,e,f;return"string"==typeof b&&(f=a[b],b=a,a=f),m.isFunction(a)?(c=d.call(arguments,2),e=function(){return a.apply(b||this,c.concat(d.call(arguments)))},e.guid=a.guid=a.guid||m.guid++,e):void 0},now:function(){return+new Date},support:k}),m.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(a,b){h["[object "+b+"]"]=b.toLowerCase()});function r(a){var b=a.length,c=m.type(a);return"function"===c||m.isWindow(a)?!1:1===a.nodeType&&b?!0:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var s=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+1*new Date,v=a.document,w=0,x=0,y=hb(),z=hb(),A=hb(),B=function(a,b){return a===b&&(l=!0),0},C=1<<31,D={}.hasOwnProperty,E=[],F=E.pop,G=E.push,H=E.push,I=E.slice,J=function(a,b){for(var c=0,d=a.length;d>c;c++)if(a[c]===b)return c;return-1},K="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",L="[\\x20\\t\\r\\n\\f]",M="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",N=M.replace("w","w#"),O="\\["+L+"*("+M+")(?:"+L+"*([*^$|!~]?=)"+L+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+N+"))|)"+L+"*\\]",P=":("+M+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+O+")*)|.*)\\)|)",Q=new RegExp(L+"+","g"),R=new RegExp("^"+L+"+|((?:^|[^\\\\])(?:\\\\.)*)"+L+"+$","g"),S=new RegExp("^"+L+"*,"+L+"*"),T=new RegExp("^"+L+"*([>+~]|"+L+")"+L+"*"),U=new RegExp("="+L+"*([^\\]'\"]*?)"+L+"*\\]","g"),V=new RegExp(P),W=new RegExp("^"+N+"$"),X={ID:new RegExp("^#("+M+")"),CLASS:new RegExp("^\\.("+M+")"),TAG:new RegExp("^("+M.replace("w","w*")+")"),ATTR:new RegExp("^"+O),PSEUDO:new RegExp("^"+P),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+L+"*(even|odd|(([+-]|)(\\d*)n|)"+L+"*(?:([+-]|)"+L+"*(\\d+)|))"+L+"*\\)|)","i"),bool:new RegExp("^(?:"+K+")$","i"),needsContext:new RegExp("^"+L+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+L+"*((?:-\\d)?\\d*)"+L+"*\\)|)(?=[^-]|$)","i")},Y=/^(?:input|select|textarea|button)$/i,Z=/^h\d$/i,$=/^[^{]+\{\s*\[native \w/,_=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ab=/[+~]/,bb=/'|\\/g,cb=new RegExp("\\\\([\\da-f]{1,6}"+L+"?|("+L+")|.)","ig"),db=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:0>d?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)},eb=function(){m()};try{H.apply(E=I.call(v.childNodes),v.childNodes),E[v.childNodes.length].nodeType}catch(fb){H={apply:E.length?function(a,b){G.apply(a,I.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function gb(a,b,d,e){var f,h,j,k,l,o,r,s,w,x;if((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,d=d||[],k=b.nodeType,"string"!=typeof a||!a||1!==k&&9!==k&&11!==k)return d;if(!e&&p){if(11!==k&&(f=_.exec(a)))if(j=f[1]){if(9===k){if(h=b.getElementById(j),!h||!h.parentNode)return d;if(h.id===j)return d.push(h),d}else if(b.ownerDocument&&(h=b.ownerDocument.getElementById(j))&&t(b,h)&&h.id===j)return d.push(h),d}else{if(f[2])return H.apply(d,b.getElementsByTagName(a)),d;if((j=f[3])&&c.getElementsByClassName)return H.apply(d,b.getElementsByClassName(j)),d}if(c.qsa&&(!q||!q.test(a))){if(s=r=u,w=b,x=1!==k&&a,1===k&&"object"!==b.nodeName.toLowerCase()){o=g(a),(r=b.getAttribute("id"))?s=r.replace(bb,"\\$&"):b.setAttribute("id",s),s="[id='"+s+"'] ",l=o.length;while(l--)o[l]=s+rb(o[l]);w=ab.test(a)&&pb(b.parentNode)||b,x=o.join(",")}if(x)try{return H.apply(d,w.querySelectorAll(x)),d}catch(y){}finally{r||b.removeAttribute("id")}}}return i(a.replace(R,"$1"),b,d,e)}function hb(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function ib(a){return a[u]=!0,a}function jb(a){var b=n.createElement("div");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function kb(a,b){var c=a.split("|"),e=a.length;while(e--)d.attrHandle[c[e]]=b}function lb(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&(~b.sourceIndex||C)-(~a.sourceIndex||C);if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function mb(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function nb(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function ob(a){return ib(function(b){return b=+b,ib(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function pb(a){return a&&"undefined"!=typeof a.getElementsByTagName&&a}c=gb.support={},f=gb.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?"HTML"!==b.nodeName:!1},m=gb.setDocument=function(a){var b,e,g=a?a.ownerDocument||a:v;return g!==n&&9===g.nodeType&&g.documentElement?(n=g,o=g.documentElement,e=g.defaultView,e&&e!==e.top&&(e.addEventListener?e.addEventListener("unload",eb,!1):e.attachEvent&&e.attachEvent("onunload",eb)),p=!f(g),c.attributes=jb(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=jb(function(a){return a.appendChild(g.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=$.test(g.getElementsByClassName),c.getById=jb(function(a){return o.appendChild(a).id=u,!g.getElementsByName||!g.getElementsByName(u).length}),c.getById?(d.find.ID=function(a,b){if("undefined"!=typeof b.getElementById&&p){var c=b.getElementById(a);return c&&c.parentNode?[c]:[]}},d.filter.ID=function(a){var b=a.replace(cb,db);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(cb,db);return function(a){var c="undefined"!=typeof a.getAttributeNode&&a.getAttributeNode("id");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return"undefined"!=typeof b.getElementsByTagName?b.getElementsByTagName(a):c.qsa?b.querySelectorAll(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){return p?b.getElementsByClassName(a):void 0},r=[],q=[],(c.qsa=$.test(g.querySelectorAll))&&(jb(function(a){o.appendChild(a).innerHTML="",a.querySelectorAll("[msallowcapture^='']").length&&q.push("[*^$]="+L+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+L+"*(?:value|"+K+")"),a.querySelectorAll("[id~="+u+"-]").length||q.push("~="),a.querySelectorAll(":checked").length||q.push(":checked"),a.querySelectorAll("a#"+u+"+*").length||q.push(".#.+[+~]")}),jb(function(a){var b=g.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+L+"*[*^$|!~]?="),a.querySelectorAll(":enabled").length||q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=$.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&jb(function(a){c.disconnectedMatch=s.call(a,"div"),s.call(a,"[s!='']:x"),r.push("!=",P)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=$.test(o.compareDocumentPosition),t=b||$.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===g||a.ownerDocument===v&&t(v,a)?-1:b===g||b.ownerDocument===v&&t(v,b)?1:k?J(k,a)-J(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,e=a.parentNode,f=b.parentNode,h=[a],i=[b];if(!e||!f)return a===g?-1:b===g?1:e?-1:f?1:k?J(k,a)-J(k,b):0;if(e===f)return lb(a,b);c=a;while(c=c.parentNode)h.unshift(c);c=b;while(c=c.parentNode)i.unshift(c);while(h[d]===i[d])d++;return d?lb(h[d],i[d]):h[d]===v?-1:i[d]===v?1:0},g):n},gb.matches=function(a,b){return gb(a,null,null,b)},gb.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(U,"='$1']"),!(!c.matchesSelector||!p||r&&r.test(b)||q&&q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return gb(b,n,null,[a]).length>0},gb.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},gb.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&D.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},gb.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},gb.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=gb.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=gb.selectors={cacheLength:50,createPseudo:ib,match:X,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(cb,db),a[3]=(a[3]||a[4]||a[5]||"").replace(cb,db),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||gb.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&gb.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return X.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&V.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(cb,db).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+L+")"+a+"("+L+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||"undefined"!=typeof a.getAttribute&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=gb.attr(d,a);return null==e?"!="===b:b?(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e.replace(Q," ")+" ").indexOf(c)>-1:"|="===b?e===c||e.slice(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h;if(q){if(f){while(p){l=b;while(l=l[p])if(h?l.nodeName.toLowerCase()===r:1===l.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){k=q[u]||(q[u]={}),j=k[a]||[],n=j[0]===w&&j[1],m=j[0]===w&&j[2],l=n&&q.childNodes[n];while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if(1===l.nodeType&&++m&&l===b){k[a]=[w,n,m];break}}else if(s&&(j=(b[u]||(b[u]={}))[a])&&j[0]===w)m=j[1];else while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if((h?l.nodeName.toLowerCase()===r:1===l.nodeType)&&++m&&(s&&((l[u]||(l[u]={}))[a]=[w,m]),l===b))break;return m-=e,m===d||m%d===0&&m/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||gb.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?ib(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=J(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:ib(function(a){var b=[],c=[],d=h(a.replace(R,"$1"));return d[u]?ib(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),b[0]=null,!c.pop()}}),has:ib(function(a){return function(b){return gb(a,b).length>0}}),contains:ib(function(a){return a=a.replace(cb,db),function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:ib(function(a){return W.test(a||"")||gb.error("unsupported lang: "+a),a=a.replace(cb,db).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return Z.test(a.nodeName)},input:function(a){return Y.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:ob(function(){return[0]}),last:ob(function(a,b){return[b-1]}),eq:ob(function(a,b,c){return[0>c?c+b:c]}),even:ob(function(a,b){for(var c=0;b>c;c+=2)a.push(c);return a}),odd:ob(function(a,b){for(var c=1;b>c;c+=2)a.push(c);return a}),lt:ob(function(a,b,c){for(var d=0>c?c+b:c;--d>=0;)a.push(d);return a}),gt:ob(function(a,b,c){for(var d=0>c?c+b:c;++db;b++)d+=a[b].value;return d}function sb(a,b,c){var d=b.dir,e=c&&"parentNode"===d,f=x++;return b.first?function(b,c,f){while(b=b[d])if(1===b.nodeType||e)return a(b,c,f)}:function(b,c,g){var h,i,j=[w,f];if(g){while(b=b[d])if((1===b.nodeType||e)&&a(b,c,g))return!0}else while(b=b[d])if(1===b.nodeType||e){if(i=b[u]||(b[u]={}),(h=i[d])&&h[0]===w&&h[1]===f)return j[2]=h[2];if(i[d]=j,j[2]=a(b,c,g))return!0}}}function tb(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function ub(a,b,c){for(var d=0,e=b.length;e>d;d++)gb(a,b[d],c);return c}function vb(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;i>h;h++)(f=a[h])&&(!c||c(f,d,e))&&(g.push(f),j&&b.push(h));return g}function wb(a,b,c,d,e,f){return d&&!d[u]&&(d=wb(d)),e&&!e[u]&&(e=wb(e,f)),ib(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||ub(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:vb(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=vb(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?J(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=vb(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):H.apply(g,r)})}function xb(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=sb(function(a){return a===b},h,!0),l=sb(function(a){return J(b,a)>-1},h,!0),m=[function(a,c,d){var e=!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d));return b=null,e}];f>i;i++)if(c=d.relative[a[i].type])m=[sb(tb(m),c)];else{if(c=d.filter[a[i].type].apply(null,a[i].matches),c[u]){for(e=++i;f>e;e++)if(d.relative[a[e].type])break;return wb(i>1&&tb(m),i>1&&rb(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(R,"$1"),c,e>i&&xb(a.slice(i,e)),f>e&&xb(a=a.slice(e)),f>e&&rb(a))}m.push(c)}return tb(m)}function yb(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,h,i,k){var l,m,o,p=0,q="0",r=f&&[],s=[],t=j,u=f||e&&d.find.TAG("*",k),v=w+=null==t?1:Math.random()||.1,x=u.length;for(k&&(j=g!==n&&g);q!==x&&null!=(l=u[q]);q++){if(e&&l){m=0;while(o=a[m++])if(o(l,g,h)){i.push(l);break}k&&(w=v)}c&&((l=!o&&l)&&p--,f&&r.push(l))}if(p+=q,c&&q!==p){m=0;while(o=b[m++])o(r,s,g,h);if(f){if(p>0)while(q--)r[q]||s[q]||(s[q]=F.call(i));s=vb(s)}H.apply(i,s),k&&!f&&s.length>0&&p+b.length>1&&gb.uniqueSort(i)}return k&&(w=v,j=t),r};return c?ib(f):f}return h=gb.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=xb(b[c]),f[u]?d.push(f):e.push(f);f=A(a,yb(e,d)),f.selector=a}return f},i=gb.select=function(a,b,e,f){var i,j,k,l,m,n="function"==typeof a&&a,o=!f&&g(a=n.selector||a);if(e=e||[],1===o.length){if(j=o[0]=o[0].slice(0),j.length>2&&"ID"===(k=j[0]).type&&c.getById&&9===b.nodeType&&p&&d.relative[j[1].type]){if(b=(d.find.ID(k.matches[0].replace(cb,db),b)||[])[0],!b)return e;n&&(b=b.parentNode),a=a.slice(j.shift().value.length)}i=X.needsContext.test(a)?0:j.length;while(i--){if(k=j[i],d.relative[l=k.type])break;if((m=d.find[l])&&(f=m(k.matches[0].replace(cb,db),ab.test(j[0].type)&&pb(b.parentNode)||b))){if(j.splice(i,1),a=f.length&&rb(j),!a)return H.apply(e,f),e;break}}}return(n||h(a,o))(f,b,!p,e,ab.test(a)&&pb(b.parentNode)||b),e},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=jb(function(a){return 1&a.compareDocumentPosition(n.createElement("div"))}),jb(function(a){return a.innerHTML="","#"===a.firstChild.getAttribute("href")})||kb("type|href|height|width",function(a,b,c){return c?void 0:a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&jb(function(a){return a.innerHTML="",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||kb("value",function(a,b,c){return c||"input"!==a.nodeName.toLowerCase()?void 0:a.defaultValue}),jb(function(a){return null==a.getAttribute("disabled")})||kb(K,function(a,b,c){var d;return c?void 0:a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),gb}(a);m.find=s,m.expr=s.selectors,m.expr[":"]=m.expr.pseudos,m.unique=s.uniqueSort,m.text=s.getText,m.isXMLDoc=s.isXML,m.contains=s.contains;var t=m.expr.match.needsContext,u=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,v=/^.[^:#\[\.,]*$/;function w(a,b,c){if(m.isFunction(b))return m.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return m.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(v.test(b))return m.filter(b,a,c);b=m.filter(b,a)}return m.grep(a,function(a){return m.inArray(a,b)>=0!==c})}m.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?m.find.matchesSelector(d,a)?[d]:[]:m.find.matches(a,m.grep(b,function(a){return 1===a.nodeType}))},m.fn.extend({find:function(a){var b,c=[],d=this,e=d.length;if("string"!=typeof a)return this.pushStack(m(a).filter(function(){for(b=0;e>b;b++)if(m.contains(d[b],this))return!0}));for(b=0;e>b;b++)m.find(a,d[b],c);return c=this.pushStack(e>1?m.unique(c):c),c.selector=this.selector?this.selector+" "+a:a,c},filter:function(a){return this.pushStack(w(this,a||[],!1))},not:function(a){return this.pushStack(w(this,a||[],!0))},is:function(a){return!!w(this,"string"==typeof a&&t.test(a)?m(a):a||[],!1).length}});var x,y=a.document,z=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,A=m.fn.init=function(a,b){var c,d;if(!a)return this;if("string"==typeof a){if(c="<"===a.charAt(0)&&">"===a.charAt(a.length-1)&&a.length>=3?[null,a,null]:z.exec(a),!c||!c[1]&&b)return!b||b.jquery?(b||x).find(a):this.constructor(b).find(a);if(c[1]){if(b=b instanceof m?b[0]:b,m.merge(this,m.parseHTML(c[1],b&&b.nodeType?b.ownerDocument||b:y,!0)),u.test(c[1])&&m.isPlainObject(b))for(c in b)m.isFunction(this[c])?this[c](b[c]):this.attr(c,b[c]);return this}if(d=y.getElementById(c[2]),d&&d.parentNode){if(d.id!==c[2])return x.find(a);this.length=1,this[0]=d}return this.context=y,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):m.isFunction(a)?"undefined"!=typeof x.ready?x.ready(a):a(m):(void 0!==a.selector&&(this.selector=a.selector,this.context=a.context),m.makeArray(a,this))};A.prototype=m.fn,x=m(y);var B=/^(?:parents|prev(?:Until|All))/,C={children:!0,contents:!0,next:!0,prev:!0};m.extend({dir:function(a,b,c){var d=[],e=a[b];while(e&&9!==e.nodeType&&(void 0===c||1!==e.nodeType||!m(e).is(c)))1===e.nodeType&&d.push(e),e=e[b];return d},sibling:function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c}}),m.fn.extend({has:function(a){var b,c=m(a,this),d=c.length;return this.filter(function(){for(b=0;d>b;b++)if(m.contains(this,c[b]))return!0})},closest:function(a,b){for(var c,d=0,e=this.length,f=[],g=t.test(a)||"string"!=typeof a?m(a,b||this.context):0;e>d;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&m.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?m.unique(f):f)},index:function(a){return a?"string"==typeof a?m.inArray(this[0],m(a)):m.inArray(a.jquery?a[0]:a,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(m.unique(m.merge(this.get(),m(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function D(a,b){do a=a[b];while(a&&1!==a.nodeType);return a}m.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return m.dir(a,"parentNode")},parentsUntil:function(a,b,c){return m.dir(a,"parentNode",c)},next:function(a){return D(a,"nextSibling")},prev:function(a){return D(a,"previousSibling")},nextAll:function(a){return m.dir(a,"nextSibling")},prevAll:function(a){return m.dir(a,"previousSibling")},nextUntil:function(a,b,c){return m.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return m.dir(a,"previousSibling",c)},siblings:function(a){return m.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return m.sibling(a.firstChild)},contents:function(a){return m.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:m.merge([],a.childNodes)}},function(a,b){m.fn[a]=function(c,d){var e=m.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=m.filter(d,e)),this.length>1&&(C[a]||(e=m.unique(e)),B.test(a)&&(e=e.reverse())),this.pushStack(e)}});var E=/\S+/g,F={};function G(a){var b=F[a]={};return m.each(a.match(E)||[],function(a,c){b[c]=!0}),b}m.Callbacks=function(a){a="string"==typeof a?F[a]||G(a):m.extend({},a);var b,c,d,e,f,g,h=[],i=!a.once&&[],j=function(l){for(c=a.memory&&l,d=!0,f=g||0,g=0,e=h.length,b=!0;h&&e>f;f++)if(h[f].apply(l[0],l[1])===!1&&a.stopOnFalse){c=!1;break}b=!1,h&&(i?i.length&&j(i.shift()):c?h=[]:k.disable())},k={add:function(){if(h){var d=h.length;!function f(b){m.each(b,function(b,c){var d=m.type(c);"function"===d?a.unique&&k.has(c)||h.push(c):c&&c.length&&"string"!==d&&f(c)})}(arguments),b?e=h.length:c&&(g=d,j(c))}return this},remove:function(){return h&&m.each(arguments,function(a,c){var d;while((d=m.inArray(c,h,d))>-1)h.splice(d,1),b&&(e>=d&&e--,f>=d&&f--)}),this},has:function(a){return a?m.inArray(a,h)>-1:!(!h||!h.length)},empty:function(){return h=[],e=0,this},disable:function(){return h=i=c=void 0,this},disabled:function(){return!h},lock:function(){return i=void 0,c||k.disable(),this},locked:function(){return!i},fireWith:function(a,c){return!h||d&&!i||(c=c||[],c=[a,c.slice?c.slice():c],b?i.push(c):j(c)),this},fire:function(){return k.fireWith(this,arguments),this},fired:function(){return!!d}};return k},m.extend({Deferred:function(a){var b=[["resolve","done",m.Callbacks("once memory"),"resolved"],["reject","fail",m.Callbacks("once memory"),"rejected"],["notify","progress",m.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return m.Deferred(function(c){m.each(b,function(b,f){var g=m.isFunction(a[b])&&a[b];e[f[1]](function(){var a=g&&g.apply(this,arguments);a&&m.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f[0]+"With"](this===d?c.promise():this,g?[a]:arguments)})}),a=null}).promise()},promise:function(a){return null!=a?m.extend(a,d):d}},e={};return d.pipe=d.then,m.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[1^a][2].disable,b[2][2].lock),e[f[0]]=function(){return e[f[0]+"With"](this===e?d:this,arguments),this},e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=d.call(arguments),e=c.length,f=1!==e||a&&m.isFunction(a.promise)?e:0,g=1===f?a:m.Deferred(),h=function(a,b,c){return function(e){b[a]=this,c[a]=arguments.length>1?d.call(arguments):e,c===i?g.notifyWith(b,c):--f||g.resolveWith(b,c)}},i,j,k;if(e>1)for(i=new Array(e),j=new Array(e),k=new Array(e);e>b;b++)c[b]&&m.isFunction(c[b].promise)?c[b].promise().done(h(b,k,c)).fail(g.reject).progress(h(b,j,i)):--f;return f||g.resolveWith(k,c),g.promise()}});var H;m.fn.ready=function(a){return m.ready.promise().done(a),this},m.extend({isReady:!1,readyWait:1,holdReady:function(a){a?m.readyWait++:m.ready(!0)},ready:function(a){if(a===!0?!--m.readyWait:!m.isReady){if(!y.body)return setTimeout(m.ready);m.isReady=!0,a!==!0&&--m.readyWait>0||(H.resolveWith(y,[m]),m.fn.triggerHandler&&(m(y).triggerHandler("ready"),m(y).off("ready")))}}});function I(){y.addEventListener?(y.removeEventListener("DOMContentLoaded",J,!1),a.removeEventListener("load",J,!1)):(y.detachEvent("onreadystatechange",J),a.detachEvent("onload",J))}function J(){(y.addEventListener||"load"===event.type||"complete"===y.readyState)&&(I(),m.ready())}m.ready.promise=function(b){if(!H)if(H=m.Deferred(),"complete"===y.readyState)setTimeout(m.ready);else if(y.addEventListener)y.addEventListener("DOMContentLoaded",J,!1),a.addEventListener("load",J,!1);else{y.attachEvent("onreadystatechange",J),a.attachEvent("onload",J);var c=!1;try{c=null==a.frameElement&&y.documentElement}catch(d){}c&&c.doScroll&&!function e(){if(!m.isReady){try{c.doScroll("left")}catch(a){return setTimeout(e,50)}I(),m.ready()}}()}return H.promise(b)};var K="undefined",L;for(L in m(k))break;k.ownLast="0"!==L,k.inlineBlockNeedsLayout=!1,m(function(){var a,b,c,d;c=y.getElementsByTagName("body")[0],c&&c.style&&(b=y.createElement("div"),d=y.createElement("div"),d.style.cssText="position:absolute;border:0;width:0;height:0;top:0;left:-9999px",c.appendChild(d).appendChild(b),typeof b.style.zoom!==K&&(b.style.cssText="display:inline;margin:0;border:0;padding:1px;width:1px;zoom:1",k.inlineBlockNeedsLayout=a=3===b.offsetWidth,a&&(c.style.zoom=1)),c.removeChild(d))}),function(){var a=y.createElement("div");if(null==k.deleteExpando){k.deleteExpando=!0;try{delete a.test}catch(b){k.deleteExpando=!1}}a=null}(),m.acceptData=function(a){var b=m.noData[(a.nodeName+" ").toLowerCase()],c=+a.nodeType||1;return 1!==c&&9!==c?!1:!b||b!==!0&&a.getAttribute("classid")===b};var M=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,N=/([A-Z])/g;function O(a,b,c){if(void 0===c&&1===a.nodeType){var d="data-"+b.replace(N,"-$1").toLowerCase();if(c=a.getAttribute(d),"string"==typeof c){try{c="true"===c?!0:"false"===c?!1:"null"===c?null:+c+""===c?+c:M.test(c)?m.parseJSON(c):c}catch(e){}m.data(a,b,c)}else c=void 0}return c}function P(a){var b;for(b in a)if(("data"!==b||!m.isEmptyObject(a[b]))&&"toJSON"!==b)return!1; +return!0}function Q(a,b,d,e){if(m.acceptData(a)){var f,g,h=m.expando,i=a.nodeType,j=i?m.cache:a,k=i?a[h]:a[h]&&h;if(k&&j[k]&&(e||j[k].data)||void 0!==d||"string"!=typeof b)return k||(k=i?a[h]=c.pop()||m.guid++:h),j[k]||(j[k]=i?{}:{toJSON:m.noop}),("object"==typeof b||"function"==typeof b)&&(e?j[k]=m.extend(j[k],b):j[k].data=m.extend(j[k].data,b)),g=j[k],e||(g.data||(g.data={}),g=g.data),void 0!==d&&(g[m.camelCase(b)]=d),"string"==typeof b?(f=g[b],null==f&&(f=g[m.camelCase(b)])):f=g,f}}function R(a,b,c){if(m.acceptData(a)){var d,e,f=a.nodeType,g=f?m.cache:a,h=f?a[m.expando]:m.expando;if(g[h]){if(b&&(d=c?g[h]:g[h].data)){m.isArray(b)?b=b.concat(m.map(b,m.camelCase)):b in d?b=[b]:(b=m.camelCase(b),b=b in d?[b]:b.split(" ")),e=b.length;while(e--)delete d[b[e]];if(c?!P(d):!m.isEmptyObject(d))return}(c||(delete g[h].data,P(g[h])))&&(f?m.cleanData([a],!0):k.deleteExpando||g!=g.window?delete g[h]:g[h]=null)}}}m.extend({cache:{},noData:{"applet ":!0,"embed ":!0,"object ":"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"},hasData:function(a){return a=a.nodeType?m.cache[a[m.expando]]:a[m.expando],!!a&&!P(a)},data:function(a,b,c){return Q(a,b,c)},removeData:function(a,b){return R(a,b)},_data:function(a,b,c){return Q(a,b,c,!0)},_removeData:function(a,b){return R(a,b,!0)}}),m.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=m.data(f),1===f.nodeType&&!m._data(f,"parsedAttrs"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.indexOf("data-")&&(d=m.camelCase(d.slice(5)),O(f,d,e[d])));m._data(f,"parsedAttrs",!0)}return e}return"object"==typeof a?this.each(function(){m.data(this,a)}):arguments.length>1?this.each(function(){m.data(this,a,b)}):f?O(f,a,m.data(f,a)):void 0},removeData:function(a){return this.each(function(){m.removeData(this,a)})}}),m.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=m._data(a,b),c&&(!d||m.isArray(c)?d=m._data(a,b,m.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=m.queue(a,b),d=c.length,e=c.shift(),f=m._queueHooks(a,b),g=function(){m.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return m._data(a,c)||m._data(a,c,{empty:m.Callbacks("once memory").add(function(){m._removeData(a,b+"queue"),m._removeData(a,c)})})}}),m.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.lengthh;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f},W=/^(?:checkbox|radio)$/i;!function(){var a=y.createElement("input"),b=y.createElement("div"),c=y.createDocumentFragment();if(b.innerHTML="
    a",k.leadingWhitespace=3===b.firstChild.nodeType,k.tbody=!b.getElementsByTagName("tbody").length,k.htmlSerialize=!!b.getElementsByTagName("link").length,k.html5Clone="<:nav>"!==y.createElement("nav").cloneNode(!0).outerHTML,a.type="checkbox",a.checked=!0,c.appendChild(a),k.appendChecked=a.checked,b.innerHTML="",k.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue,c.appendChild(b),b.innerHTML="",k.checkClone=b.cloneNode(!0).cloneNode(!0).lastChild.checked,k.noCloneEvent=!0,b.attachEvent&&(b.attachEvent("onclick",function(){k.noCloneEvent=!1}),b.cloneNode(!0).click()),null==k.deleteExpando){k.deleteExpando=!0;try{delete b.test}catch(d){k.deleteExpando=!1}}}(),function(){var b,c,d=y.createElement("div");for(b in{submit:!0,change:!0,focusin:!0})c="on"+b,(k[b+"Bubbles"]=c in a)||(d.setAttribute(c,"t"),k[b+"Bubbles"]=d.attributes[c].expando===!1);d=null}();var X=/^(?:input|select|textarea)$/i,Y=/^key/,Z=/^(?:mouse|pointer|contextmenu)|click/,$=/^(?:focusinfocus|focusoutblur)$/,_=/^([^.]*)(?:\.(.+)|)$/;function ab(){return!0}function bb(){return!1}function cb(){try{return y.activeElement}catch(a){}}m.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,n,o,p,q,r=m._data(a);if(r){c.handler&&(i=c,c=i.handler,e=i.selector),c.guid||(c.guid=m.guid++),(g=r.events)||(g=r.events={}),(k=r.handle)||(k=r.handle=function(a){return typeof m===K||a&&m.event.triggered===a.type?void 0:m.event.dispatch.apply(k.elem,arguments)},k.elem=a),b=(b||"").match(E)||[""],h=b.length;while(h--)f=_.exec(b[h])||[],o=q=f[1],p=(f[2]||"").split(".").sort(),o&&(j=m.event.special[o]||{},o=(e?j.delegateType:j.bindType)||o,j=m.event.special[o]||{},l=m.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&m.expr.match.needsContext.test(e),namespace:p.join(".")},i),(n=g[o])||(n=g[o]=[],n.delegateCount=0,j.setup&&j.setup.call(a,d,p,k)!==!1||(a.addEventListener?a.addEventListener(o,k,!1):a.attachEvent&&a.attachEvent("on"+o,k))),j.add&&(j.add.call(a,l),l.handler.guid||(l.handler.guid=c.guid)),e?n.splice(n.delegateCount++,0,l):n.push(l),m.event.global[o]=!0);a=null}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,n,o,p,q,r=m.hasData(a)&&m._data(a);if(r&&(k=r.events)){b=(b||"").match(E)||[""],j=b.length;while(j--)if(h=_.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o){l=m.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,n=k[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),i=f=n.length;while(f--)g=n[f],!e&&q!==g.origType||c&&c.guid!==g.guid||h&&!h.test(g.namespace)||d&&d!==g.selector&&("**"!==d||!g.selector)||(n.splice(f,1),g.selector&&n.delegateCount--,l.remove&&l.remove.call(a,g));i&&!n.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||m.removeEvent(a,o,r.handle),delete k[o])}else for(o in k)m.event.remove(a,o+b[j],c,d,!0);m.isEmptyObject(k)&&(delete r.handle,m._removeData(a,"events"))}},trigger:function(b,c,d,e){var f,g,h,i,k,l,n,o=[d||y],p=j.call(b,"type")?b.type:b,q=j.call(b,"namespace")?b.namespace.split("."):[];if(h=l=d=d||y,3!==d.nodeType&&8!==d.nodeType&&!$.test(p+m.event.triggered)&&(p.indexOf(".")>=0&&(q=p.split("."),p=q.shift(),q.sort()),g=p.indexOf(":")<0&&"on"+p,b=b[m.expando]?b:new m.Event(p,"object"==typeof b&&b),b.isTrigger=e?2:3,b.namespace=q.join("."),b.namespace_re=b.namespace?new RegExp("(^|\\.)"+q.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=d),c=null==c?[b]:m.makeArray(c,[b]),k=m.event.special[p]||{},e||!k.trigger||k.trigger.apply(d,c)!==!1)){if(!e&&!k.noBubble&&!m.isWindow(d)){for(i=k.delegateType||p,$.test(i+p)||(h=h.parentNode);h;h=h.parentNode)o.push(h),l=h;l===(d.ownerDocument||y)&&o.push(l.defaultView||l.parentWindow||a)}n=0;while((h=o[n++])&&!b.isPropagationStopped())b.type=n>1?i:k.bindType||p,f=(m._data(h,"events")||{})[b.type]&&m._data(h,"handle"),f&&f.apply(h,c),f=g&&h[g],f&&f.apply&&m.acceptData(h)&&(b.result=f.apply(h,c),b.result===!1&&b.preventDefault());if(b.type=p,!e&&!b.isDefaultPrevented()&&(!k._default||k._default.apply(o.pop(),c)===!1)&&m.acceptData(d)&&g&&d[p]&&!m.isWindow(d)){l=d[g],l&&(d[g]=null),m.event.triggered=p;try{d[p]()}catch(r){}m.event.triggered=void 0,l&&(d[g]=l)}return b.result}},dispatch:function(a){a=m.event.fix(a);var b,c,e,f,g,h=[],i=d.call(arguments),j=(m._data(this,"events")||{})[a.type]||[],k=m.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=m.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,g=0;while((e=f.handlers[g++])&&!a.isImmediatePropagationStopped())(!a.namespace_re||a.namespace_re.test(e.namespace))&&(a.handleObj=e,a.data=e.data,c=((m.event.special[e.origType]||{}).handle||e.handler).apply(f.elem,i),void 0!==c&&(a.result=c)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&(!a.button||"click"!==a.type))for(;i!=this;i=i.parentNode||this)if(1===i.nodeType&&(i.disabled!==!0||"click"!==a.type)){for(e=[],f=0;h>f;f++)d=b[f],c=d.selector+" ",void 0===e[c]&&(e[c]=d.needsContext?m(c,this).index(i)>=0:m.find(c,this,null,[i]).length),e[c]&&e.push(d);e.length&&g.push({elem:i,handlers:e})}return h]","i"),hb=/^\s+/,ib=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,jb=/<([\w:]+)/,kb=/\s*$/g,rb={option:[1,""],legend:[1,"
    ","
    "],area:[1,"",""],param:[1,"",""],thead:[1,"","
    "],tr:[2,"","
    "],col:[2,"","
    "],td:[3,"","
    "],_default:k.htmlSerialize?[0,"",""]:[1,"X
    ","
    "]},sb=db(y),tb=sb.appendChild(y.createElement("div"));rb.optgroup=rb.option,rb.tbody=rb.tfoot=rb.colgroup=rb.caption=rb.thead,rb.th=rb.td;function ub(a,b){var c,d,e=0,f=typeof a.getElementsByTagName!==K?a.getElementsByTagName(b||"*"):typeof a.querySelectorAll!==K?a.querySelectorAll(b||"*"):void 0;if(!f)for(f=[],c=a.childNodes||a;null!=(d=c[e]);e++)!b||m.nodeName(d,b)?f.push(d):m.merge(f,ub(d,b));return void 0===b||b&&m.nodeName(a,b)?m.merge([a],f):f}function vb(a){W.test(a.type)&&(a.defaultChecked=a.checked)}function wb(a,b){return m.nodeName(a,"table")&&m.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function xb(a){return a.type=(null!==m.find.attr(a,"type"))+"/"+a.type,a}function yb(a){var b=pb.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function zb(a,b){for(var c,d=0;null!=(c=a[d]);d++)m._data(c,"globalEval",!b||m._data(b[d],"globalEval"))}function Ab(a,b){if(1===b.nodeType&&m.hasData(a)){var c,d,e,f=m._data(a),g=m._data(b,f),h=f.events;if(h){delete g.handle,g.events={};for(c in h)for(d=0,e=h[c].length;e>d;d++)m.event.add(b,c,h[c][d])}g.data&&(g.data=m.extend({},g.data))}}function Bb(a,b){var c,d,e;if(1===b.nodeType){if(c=b.nodeName.toLowerCase(),!k.noCloneEvent&&b[m.expando]){e=m._data(b);for(d in e.events)m.removeEvent(b,d,e.handle);b.removeAttribute(m.expando)}"script"===c&&b.text!==a.text?(xb(b).text=a.text,yb(b)):"object"===c?(b.parentNode&&(b.outerHTML=a.outerHTML),k.html5Clone&&a.innerHTML&&!m.trim(b.innerHTML)&&(b.innerHTML=a.innerHTML)):"input"===c&&W.test(a.type)?(b.defaultChecked=b.checked=a.checked,b.value!==a.value&&(b.value=a.value)):"option"===c?b.defaultSelected=b.selected=a.defaultSelected:("input"===c||"textarea"===c)&&(b.defaultValue=a.defaultValue)}}m.extend({clone:function(a,b,c){var d,e,f,g,h,i=m.contains(a.ownerDocument,a);if(k.html5Clone||m.isXMLDoc(a)||!gb.test("<"+a.nodeName+">")?f=a.cloneNode(!0):(tb.innerHTML=a.outerHTML,tb.removeChild(f=tb.firstChild)),!(k.noCloneEvent&&k.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||m.isXMLDoc(a)))for(d=ub(f),h=ub(a),g=0;null!=(e=h[g]);++g)d[g]&&Bb(e,d[g]);if(b)if(c)for(h=h||ub(a),d=d||ub(f),g=0;null!=(e=h[g]);g++)Ab(e,d[g]);else Ab(a,f);return d=ub(f,"script"),d.length>0&&zb(d,!i&&ub(a,"script")),d=h=e=null,f},buildFragment:function(a,b,c,d){for(var e,f,g,h,i,j,l,n=a.length,o=db(b),p=[],q=0;n>q;q++)if(f=a[q],f||0===f)if("object"===m.type(f))m.merge(p,f.nodeType?[f]:f);else if(lb.test(f)){h=h||o.appendChild(b.createElement("div")),i=(jb.exec(f)||["",""])[1].toLowerCase(),l=rb[i]||rb._default,h.innerHTML=l[1]+f.replace(ib,"<$1>")+l[2],e=l[0];while(e--)h=h.lastChild;if(!k.leadingWhitespace&&hb.test(f)&&p.push(b.createTextNode(hb.exec(f)[0])),!k.tbody){f="table"!==i||kb.test(f)?""!==l[1]||kb.test(f)?0:h:h.firstChild,e=f&&f.childNodes.length;while(e--)m.nodeName(j=f.childNodes[e],"tbody")&&!j.childNodes.length&&f.removeChild(j)}m.merge(p,h.childNodes),h.textContent="";while(h.firstChild)h.removeChild(h.firstChild);h=o.lastChild}else p.push(b.createTextNode(f));h&&o.removeChild(h),k.appendChecked||m.grep(ub(p,"input"),vb),q=0;while(f=p[q++])if((!d||-1===m.inArray(f,d))&&(g=m.contains(f.ownerDocument,f),h=ub(o.appendChild(f),"script"),g&&zb(h),c)){e=0;while(f=h[e++])ob.test(f.type||"")&&c.push(f)}return h=null,o},cleanData:function(a,b){for(var d,e,f,g,h=0,i=m.expando,j=m.cache,l=k.deleteExpando,n=m.event.special;null!=(d=a[h]);h++)if((b||m.acceptData(d))&&(f=d[i],g=f&&j[f])){if(g.events)for(e in g.events)n[e]?m.event.remove(d,e):m.removeEvent(d,e,g.handle);j[f]&&(delete j[f],l?delete d[i]:typeof d.removeAttribute!==K?d.removeAttribute(i):d[i]=null,c.push(f))}}}),m.fn.extend({text:function(a){return V(this,function(a){return void 0===a?m.text(this):this.empty().append((this[0]&&this[0].ownerDocument||y).createTextNode(a))},null,a,arguments.length)},append:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=wb(this,a);b.appendChild(a)}})},prepend:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=wb(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},remove:function(a,b){for(var c,d=a?m.filter(a,this):this,e=0;null!=(c=d[e]);e++)b||1!==c.nodeType||m.cleanData(ub(c)),c.parentNode&&(b&&m.contains(c.ownerDocument,c)&&zb(ub(c,"script")),c.parentNode.removeChild(c));return this},empty:function(){for(var a,b=0;null!=(a=this[b]);b++){1===a.nodeType&&m.cleanData(ub(a,!1));while(a.firstChild)a.removeChild(a.firstChild);a.options&&m.nodeName(a,"select")&&(a.options.length=0)}return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return m.clone(this,a,b)})},html:function(a){return V(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a)return 1===b.nodeType?b.innerHTML.replace(fb,""):void 0;if(!("string"!=typeof a||mb.test(a)||!k.htmlSerialize&&gb.test(a)||!k.leadingWhitespace&&hb.test(a)||rb[(jb.exec(a)||["",""])[1].toLowerCase()])){a=a.replace(ib,"<$1>");try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(m.cleanData(ub(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=arguments[0];return this.domManip(arguments,function(b){a=this.parentNode,m.cleanData(ub(this)),a&&a.replaceChild(b,this)}),a&&(a.length||a.nodeType)?this:this.remove()},detach:function(a){return this.remove(a,!0)},domManip:function(a,b){a=e.apply([],a);var c,d,f,g,h,i,j=0,l=this.length,n=this,o=l-1,p=a[0],q=m.isFunction(p);if(q||l>1&&"string"==typeof p&&!k.checkClone&&nb.test(p))return this.each(function(c){var d=n.eq(c);q&&(a[0]=p.call(this,c,d.html())),d.domManip(a,b)});if(l&&(i=m.buildFragment(a,this[0].ownerDocument,!1,this),c=i.firstChild,1===i.childNodes.length&&(i=c),c)){for(g=m.map(ub(i,"script"),xb),f=g.length;l>j;j++)d=i,j!==o&&(d=m.clone(d,!0,!0),f&&m.merge(g,ub(d,"script"))),b.call(this[j],d,j);if(f)for(h=g[g.length-1].ownerDocument,m.map(g,yb),j=0;f>j;j++)d=g[j],ob.test(d.type||"")&&!m._data(d,"globalEval")&&m.contains(h,d)&&(d.src?m._evalUrl&&m._evalUrl(d.src):m.globalEval((d.text||d.textContent||d.innerHTML||"").replace(qb,"")));i=c=null}return this}}),m.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){m.fn[a]=function(a){for(var c,d=0,e=[],g=m(a),h=g.length-1;h>=d;d++)c=d===h?this:this.clone(!0),m(g[d])[b](c),f.apply(e,c.get());return this.pushStack(e)}});var Cb,Db={};function Eb(b,c){var d,e=m(c.createElement(b)).appendTo(c.body),f=a.getDefaultComputedStyle&&(d=a.getDefaultComputedStyle(e[0]))?d.display:m.css(e[0],"display");return e.detach(),f}function Fb(a){var b=y,c=Db[a];return c||(c=Eb(a,b),"none"!==c&&c||(Cb=(Cb||m(" + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git "a/web/118 \346\227\205\346\270\270\346\231\272\346\205\247\344\270\255\345\277\203/static/car.png" "b/web/118 \346\227\205\346\270\270\346\231\272\346\205\247\344\270\255\345\277\203/static/car.png" new file mode 100644 index 00000000..65ee3607 Binary files /dev/null and "b/web/118 \346\227\205\346\270\270\346\231\272\346\205\247\344\270\255\345\277\203/static/car.png" differ diff --git "a/web/118 \346\227\205\346\270\270\346\231\272\346\205\247\344\270\255\345\277\203/static/car1.png" "b/web/118 \346\227\205\346\270\270\346\231\272\346\205\247\344\270\255\345\277\203/static/car1.png" new file mode 100644 index 00000000..d983775f Binary files /dev/null and "b/web/118 \346\227\205\346\270\270\346\231\272\346\205\247\344\270\255\345\277\203/static/car1.png" differ diff --git "a/web/118 \346\227\205\346\270\270\346\231\272\346\205\247\344\270\255\345\277\203/static/chart.js" "b/web/118 \346\227\205\346\270\270\346\231\272\346\205\247\344\270\255\345\277\203/static/chart.js" new file mode 100644 index 00000000..3852158f --- /dev/null +++ "b/web/118 \346\227\205\346\270\270\346\231\272\346\205\247\344\270\255\345\277\203/static/chart.js" @@ -0,0 +1,998 @@ +function pieChart(data) { + var data = data + var titleArr = [], seriesArr = []; + colors = [['#389af4', '#dfeaff'], ['#ff8c37', '#ffdcc3'], ['#ff0036', '#ffdcc3'], ['#ffc257', '#ffedcc'], ['#fd6f97', '#fed4e0'], ['#a181fc', '#e3d9fe']] + data.forEach(function (item, index) { + titleArr.push( + { + text: item.name, + left: index < 3 ? index * 30 + 17.5 + '%' : (index - 3) * 40 + 17.5 + '%', + top: index < 3 ? '35%' : '87%', + bottom: 10, + textAlign: 'center', + textStyle: { + fontWeight: 'normal', + fontSize: '12', + color: colors[index][0], + textAlign: 'center', + + left: 10 + }, + } + ); + seriesArr.push( + { + name: item.name, + type: 'pie', + clockWise: false, + radius: [17, 22], + itemStyle: { + normal: { + color: colors[index][0], + shadowColor: colors[index][0], + shadowBlur: 0, + label: { + show: false + }, + labelLine: { + show: false + }, + } + }, + hoverAnimation: false, + center: [index < 3 ? index * 30 + 20 + '%' : (index - 3) * 40 + 20 + '%', index < 3 ? '18%' : '70%'], + data: [{ + value: item.value, + label: { + normal: { + formatter: function (params) { + return params.value + '%'; + }, + position: 'center', + show: true, + textStyle: { + fontSize: '12', + fontWeight: 'bold', + color: colors[index][0] + } + } + }, + }, { + value: 100 - item.value, + name: 'invisible', + itemStyle: { + normal: { + color: colors[index][1] + }, + emphasis: { + color: colors[index][1] + } + } + }] + } + ) + }); + return { + title: titleArr, + series: seriesArr + } +} +function barChart(data) { + return { + tooltip: { + trigger: 'axis', + axisPointer: { // 坐标轴指示器,坐标轴触发有效 + type: 'shadow' // 默认为直线,可选为:'line' | 'shadow' + } + }, + grid: { + left: '2%', + right: '4%', + bottom: '0', + top: '18%', + containLabel: true + }, + legend: { + data: data.legend, + right: '2%', + top: '-4%', + textStyle: { + color: "#fff" + }, + itemWidth: 12, + itemHeight: 10, + // itemGap: 35 + }, + xAxis: { + type: 'category', + data: data.xAxis, + axisLine: { + show: false, + lineStyle: { + color: 'white' + + } + }, + axisLabel: { + textStyle: { + fontFamily: 'Microsoft YaHei' + } + }, + }, + + yAxis: { + type: 'value', + axisLine: { + show: false, + lineStyle: { + color: 'white' + } + }, + splitLine: { + show: false, + lineStyle: { + color: 'rgba(255,255,255,0.3)' + } + }, + axisLabel: {} + }, + series: [{ + name: data.legend[0], + type: 'bar', + barWidth: '15%', + itemStyle: { + normal: { + color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{ + offset: 0, + color: '#fccb05' + }, { + offset: 1, + color: '#f5804d' + }]), + barBorderRadius: 12, + }, + }, + data: data.data[0] + }, + { + name: data.legend[1], + type: 'bar', + barWidth: '15%', + itemStyle: { + normal: { + color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{ + offset: 0, + color: '#8bd46e' + }, { + offset: 1, + color: '#09bcb7' + }]), + barBorderRadius: 11, + } + + }, + data: data.data[1] + }] + }; +} +function carSpaceNumChart(data) { + var myColor = ['#d0a00e', '#34da62', '#00e9db', '#00c0e9', '#0096f3']; + return { + grid: { + left: '11%', + top: '12%', + right: '0%', + bottom: '0%', + containLabel: true + }, + xAxis: [{ + show: false, + }], + tooltip: { + trigger: 'axis', + formatter: v => { + console.log(v) + return ` +
    +
    ${v[0].name}车位占比:${v[0].value}%
    +
    + ` + } + }, + yAxis: [{ + axisTick: 'none', + axisLine: 'none', + offset: '17', + axisLabel: { + textStyle: { + color: '#ffffff', + fontSize: '13', + } + }, + data: data.yAxisName + }, { + axisTick: 'none', + axisLine: 'none', + axisLabel: { + textStyle: { + color: '#ffffff', + fontSize: '13', + } + }, + data: data.yAxisData + }, { + name: '车位占比:%', + nameGap: '50', + nameTextStyle: { + color: '#ffffff', + fontSize: '13', + }, + axisLine: { + lineStyle: { + color: 'rgba(0,0,0,0)' + } + }, + data: [], + }], + series: [{ + type: 'bar', + yAxisIndex: 0, + data: data.data, + label: { + normal: { + show: true, + position: 'right', + formatter: function (param) { + return param.value + '%'; + }, + textStyle: { + color: '#ffffff', + fontSize: '13', + } + } + }, + barWidth: 5, + itemStyle: { + normal: { + color: function (params) { + var num = myColor.length; + return myColor[params.dataIndex % num] + }, + } + }, + z: 2 + }, { + type: 'bar', + yAxisIndex: 1, + barGap: '-100%', + data: [99.5, 99.5, 99.5, 99.5, 99.5], + barWidth: 10, + itemStyle: { + normal: { + color: '#0e2147', + barBorderRadius: 5, + } + }, + z: 1 + }, { + type: 'bar', + yAxisIndex: 2, + barGap: '-100%', + data: [100, 100, 100, 100, 100], + barWidth: 14, + itemStyle: { + normal: { + color: function (params) { + var num = myColor.length; + return myColor[params.dataIndex % num] + }, + barBorderRadius: 5, + } + }, + z: 0 + }, + { + type: 'scatter', + hoverAnimation: false, + data: [0, 0, 0, 0, 0], + yAxisIndex: 2, + symbolSize: 18, + itemStyle: { + normal: { + color: function (params) { + var num = myColor.length; + return myColor[params.dataIndex % num] + }, + opacity: 1, + } + }, + z: 2 + }] + }; +} +function consumptionChart(data) { + var scale = 1; + var echartData = data + var rich = { + yellow: { + color: "#ffc72b", + fontSize: 30 * scale, + padding: [5, 4], + align: 'center' + }, + total: { + color: "#ffc72b", + fontSize: 40 * scale, + align: 'center' + }, + white: { + color: "#fff", + align: 'center', + fontSize: 14 * scale, + padding: [21, 0] + }, + blue: { + color: '#49dff0', + fontSize: 16 * scale, + align: 'center' + }, + hr: { + borderColor: '#0b5263', + width: '100%', + borderWidth: 1, + height: 0, + } + } + var color = ['#c487ee', '#deb140', '#49dff0', '#034079', '#6f81da', '#00ffb4'] + return { + tooltip: { + trigger: 'item', + + }, + legend: { + selectedMode: false, + formatter: function (name) { + // var total = 0; + // var averagePercent; + // echartData.forEach(function(value, index, array) { + // total += value.value; + // }); + // return '{total|' + total + '}'; + }, + data: [echartData[0].name], + left: 'center', + top: 'center', + icon: 'none', + align: 'center', + textStyle: { + color: "#fff", + fontSize: 13, + rich: rich + }, + }, + series: [{ + name: '总消费', + type: 'pie', + radius: ['42%', '50%'], + hoverAnimation: false, + color: ['#c487ee', '#deb140', '#49dff0', '#034079', '#6f81da', '#00ffb4'], + label: { + normal: { + formatter: function (params, ticket, callback) { + var total = 0; + var percent = 0; //消费占比 + echartData.forEach(function (value, index, array) { + total += value.value; + }); + percent = ((params.value / total) * 100).toFixed(1); + return '{white|' + params.name + '}\n{blue|' + percent + '%}'; + }, + rich: rich + }, + textStyle: { + lineHeight: 0 + } + }, + labelLine: { + normal: { + length: 14, + length2: 3, + lineStyle: { + color: '#fff' + } + } + }, + data: echartData + }] + }; +} +function lineChart(data) { + var xData = function () { + var data = []; + for (var i = 1; i < 24; i++) { + data.push(i + "时"); + } + return data; + }(); + + return { + tooltip: { + show: true, + trigger: 'item' + }, + grid: { + borderWidth: 0, + top: '10%', + bottom: '30%', + textStyle: { + color: "#fff" + } + }, + legend: { + x: '46%', + top: '0%', + textStyle: { + color: '#90979c', + }, + data: data.legend + }, + + + calculable: true, + xAxis: [{ + type: "category", + axisLine: { + lineStyle: { + color: "rgba(204,187,225,0.5)", + } + }, + splitLine: { + show: false + }, + axisTick: { + show: false + }, + data: xData, + }], + + yAxis: [{ + type: "value", + splitLine: { + show: false + }, + axisLine: { + lineStyle: { + color: "rgba(204,187,225,0.5)", + } + }, + + }], + dataZoom: [{ + show: true, + height: 10, + xAxisIndex: [0], + bottom: '10%', + + "start": 0, + "end": 70, + handleIcon: 'path://M306.1,413c0,2.2-1.8,4-4,4h-59.8c-2.2,0-4-1.8-4-4V200.8c0-2.2,1.8-4,4-4h59.8c2.2,0,4,1.8,4,4V413z', + handleSize: '110%', + handleStyle: { + color: "#5B3AAE", + }, + textStyle: { + color: "rgba(204,187,225,0.5)", + }, + fillerColor: "rgba(67,55,160,0.4)", + borderColor: "rgba(204,187,225,0.5)", + + }, { + type: "inside", + show: true, + height: 10, + start: 1, + end: 35 + }], + series: [{ + name: data.legend[0], + type: "line", + symbolSize: 5, + symbol: 'circle', + itemStyle: { + color: "#6f7de3", + }, + lineStyle: { + normal: { + width: 1 + } + }, + markPoint: { + label: { + normal: { + textStyle: { + color: '#fff' + } + } + } + + }, + data: data.data[0], + }, { + name: data.legend[1], + type: "line", + symbolSize: 5, + symbol: 'circle', + itemStyle: { + color: "#c257F6", + }, + lineStyle: { + normal: { + width: 1 + } + }, + markPoint: { + label: { + normal: { + textStyle: { + color: '#fff' + } + } + } + + }, + data: data.data[1] + },] + } +} +function pieChart1() { + var scaleData = [{ + 'name': '2018年男生', + 'value': 38 + }, + { + 'name': '2017年男生', + 'value': 31 + }, + { + 'name': '2016年男生', + 'value': 29 + }, + { + 'name': '2016年女生', + 'value': 12 + }, + { + 'name': '2017年女生', + 'value': 34 + }, + { + 'name': '2018年女生', + 'value': 39 + }, + + ]; + var rich = { + white: { + color: '#ddd', + align: 'center', + padding: [3, 0] + } + }; + var placeHolderStyle = { + normal: { + label: { + show: false + }, + labelLine: { + show: false + }, + color: 'rgba(0, 0, 0, 0)', + borderWidth: 0 + } + }; + var data = []; + var color = ['red', 'yellow', 'black', '#ffe000', '#ffa800', '#ff5b00', '#ff3000'] + for (var i = 0; i < scaleData.length; i++) { + data.push({ + value: scaleData[i].value, + name: scaleData[i].name, + itemStyle: { + normal: { + borderWidth: 4, + shadowBlur: 200, + borderColor: color[i], + shadowColor: color[i] + } + } + }, { + value: 2, + name: '', + itemStyle: placeHolderStyle + }); + } + var seriesObj = [{ + name: '', + type: 'pie', + clockWise: false, + radius: [100, 200], + hoverAnimation: false, + itemStyle: { + normal: { + label: { + show: true, + position: 'outside', + color: '#ddd', + formatter: function (params) { + var percent = 0; + var total = 0; + for (var i = 0; i < scaleData.length; i++) { + total += scaleData[i].value; + } + percent = ((params.value / total) * 100).toFixed(0); + if (params.name !== '') { + return params.name + params.value + '人' + '\n{white|' + '占比' + percent + '%}'; + } else { + return ''; + } + }, + rich: rich + }, + labelLine: { + length: 30, + length2: 100, + show: true, + color: '#00ffff' + } + } + }, + data: data + }]; + option = { + tooltip: { + show: false + }, + legend: { + show: false + }, + toolbox: { + show: false + }, + series: seriesObj + } +} +function touristsFlowChart(data) { + // mock + let dataArr = data + + // 排序 + let dataArray = dataArr.sort((a, b) => a.NUM - b.NUM) + + // 计算总数 + let total = dataArray.reduce((data, v) => { return data + +v.NUM }, 0) + + // color + let color = { 0: '#ff5676', 1: '#ffd83e', 2: '#fbff94', 3: '#7daeff' } + + // x轴 + let xdataName = dataArray.map(v => v.NAME) + + // y轴 + let dataNum = dataArray.map((v, i) => ({ + value: +v.NUM, + itemStyle: { + color: { + type: 'linear', x: 1, y: 0, x2: 0, y2: 0, colorStops: [{ + offset: 0, + color: dataArray.length - i - 1 < 3 ? '#ffdae1' : '#ecf3ff' // 0% 处的颜色 + }, { + offset: 0.07, + color: dataArray.length - i - 1 < 3 ? color[dataArray.length - i - 1] : color['3'] // 93% 处的颜色 + }, { + offset: 1, + color: dataArray.length - i - 1 < 3 ? 'rgba(255, 86, 118, .1)' : 'rgba(125,174,255, .1)' // 100% 处的颜色 + } + ] + }, + } + })) + + // 背景色值数据,比最大值多200即可 + let bgData = dataNum.map(v => (+dataNum[dataNum.length - 1].value + 200)) + + // tooltip + let tooltip = { + trigger: 'axis', + // formatter: v => { + // return ` + //
    + //
    ${v[0].name}:${v[0].value}
    + //
    + // ` + // } + } + + // grid + let grid = { top: '10%', left: '20%', right: '14%', bottom: 0 } + + // xAxis + let xAxis = { + splitLine: { show: false }, + axisLine: { show: false }, + axisLabel: { show: false }, + axisTick: { show: false } + } + + // yAxis + let yAxis = [{ + type: "category", + inverse: false, + data: xdataName, + axisLabel: { + formatter: (params, index) => { + return `{a|${params}}` + }, + rich: { + a: { + width: 160, + fontSize: 12, + color: '#fff', + padding: [5, 4, 5, 0], + align: 'right', + } + } + }, + // 把坐标轴、刻度、坐标线统统不要 + axisLine: { show: false }, + axisTick: { show: false }, + splitLine: { show: false }, + }, { + type: 'category', + data: dataNum, + axisLabel: { + formatter: (params, index) => { + console.log(params) + return params + }, + textStyle: { + color: '#4fc8d0' + }, + // align: 'right', + rich: { + a: { fontSize: 24, color: '#98bfff', verticalAlign: 'bottom' }, + a1: { fontSize: 28, color: '#ff7f97', verticalAlign: 'bottom' }, + a2: { fontSize: 24, color: '#ffce64', verticalAlign: 'bottom' }, + a3: { fontSize: 24, color: '#e8ed66', verticalAlign: 'bottom' }, + + b: { fontSize: 12, color: '#98bfff', verticalAlign: 'bottom' }, + b1: { fontSize: 12, color: '#ff7f97', verticalAlign: 'bottom' }, + b2: { fontSize: 12, color: '#ffce64', verticalAlign: 'bottom' }, + b3: { fontSize: 12, color: '#e8ed66', verticalAlign: 'bottom' }, + } + }, + // 把坐标轴、刻度、坐标线统统不要 + axisLine: { show: false }, + axisTick: { show: false }, + splitLine: { show: false }, + } + ] + + // series + let series = [{ + // 背景 + z: 6, + type: 'bar', + barWidth: 10, + itemStyle: { + color: 'rgba(255,255,255,.1)', + barBorderRadius: [0, 20, 20, 0] + }, + data: bgData + }, { + type: 'bar', + barWidth: 10, + barGap: '-100%', + itemStyle: { + color: { + type: 'linear', x: 1, y: 0, x2: 0, y2: 0, colorStops: [{ + offset: 0, + color: 'rgba(255, 218, 220)' // 0% 处的颜色 + }, { + offset: 0.07, + color: 'rgba(255, 86, 118)' // 93% 处的颜色 + }, + { + offset: 1, + color: 'rgba(255, 86, 118, 0)' // 100% 处的颜色 + } + ], + global: false // 缺省为 false + }, + barBorderRadius: [0, 20, 20, 0], + }, + textStyle: { + fontFamily: 'Microsoft YaHei', + fontSize: 14 + }, + data: dataNum + } + ] + + // 渲染 + return { tooltip, grid, xAxis, yAxis, series } + +} +function helpCellChart(datas) { + var names = ['咨询', '投诉', '其他']; +var values = [300, 200, 50]; +var colorList = ['#03acd1', '#fce348', '#fc2d8a']; +var data1 = []; +var data2 = []; +for (var i = 0; i < names.length; i++) { + data1.push({ + name: names[i], + value: datas[0][i] + }) +} + for (var i = 0; i < names.length; i++) { + data2.push({ + name: names[i], + value: datas[1][i] + }) +} + data1.reverse(); + data2.reverse(); +// 公用调整 +var itemStyle = { + normal: { + borderWidth: 5, + color: function(params) { + return colorList[params.dataIndex] + } + } +} +var leftCenter = ['25%', '50%'], + rightCenter = ['75%', '50%'], + radius1 = ['50%', '55%'], // 饼图 + radius3 = ['70%', '71%'] // 线圈 + // 公用调整-end + + return { + tooltip: { + trigger: 'item', + }, + title: [{ + text: '呼入', + x: '20.7%', + y: '42%', + textStyle: { + color: '#559dbd', + fontSize: 14 + } + }, + { + text: '呼出', + x: '70.3%', + y: '42%', + textStyle: { + color: '#559dbd', + fontSize: 14 + } + } + ], + series: [ + // 左饼图 + { + // 饼图圈 + type: 'pie', + zlevel: 3, + radius: radius1, + center: leftCenter, + itemStyle: itemStyle, + labelLine: { + show: false, + normal: { + length: 5, + length2: 0, + lineStyle: { + color: 'transparent' + } + } + }, + label: { + normal: { + formatter: params => { + return ''; + } + } + }, + data: data1, + }, + { + // 最外圆圈 + type: 'pie', + zlevel: 1, + silent: true, //取消高亮 + radius: radius3, + center: leftCenter, + itemStyle: { + normal: { + color: function(params) { + return colorList[params.dataIndex] + } + } + }, + labelLine: { + show: false, + normal: { + length: 10, + length2: 0, + lineStyle: { + color: 'transparent' + } + } + }, + label: { + show: true + }, + data: data1, + }, + + // 右饼图 + { + // 饼图圈 + type: 'pie', + zlevel: 3, + radius: radius1, + center: rightCenter, + itemStyle: itemStyle, + labelLine: { + show: false, + normal: { + length: 5, + length2: 0, + lineStyle: { + color: 'transparent' + } + } + }, + label: { + normal: { + formatter: params => { + return ''; + } + } + }, + data: data2, + }, + { + // 线圆圈 + type: 'pie', + zlevel: 1, + silent: true, //取消高亮 + radius: radius3, + center: rightCenter, + itemStyle: { + normal: { + color: function(params) { + return colorList[params.dataIndex] + } + } + }, + labelLine: { + show: false, + normal: { + length: 10, + length2: 0, + lineStyle: { + color: 'transparent' + } + } + }, + label: { + show: true + }, + data: data2, + }, + ] + }; +} \ No newline at end of file diff --git "a/web/118 \346\227\205\346\270\270\346\231\272\346\205\247\344\270\255\345\277\203/static/common.css" "b/web/118 \346\227\205\346\270\270\346\231\272\346\205\247\344\270\255\345\277\203/static/common.css" new file mode 100644 index 00000000..756e83eb --- /dev/null +++ "b/web/118 \346\227\205\346\270\270\346\231\272\346\205\247\344\270\255\345\277\203/static/common.css" @@ -0,0 +1,55 @@ +* { + margin: 0; + padding: 0; + box-sizing: border-box; + font-family: 'Arial', 'Microsoft YaHei'; +} +html { + background: rgba(255, 255, 255, .95); +} +li { + list-style: none; +} +a { + text-decoration: none; +} +button, input { + outline: none; +} +.h1, .h2, .h3, h1, h2, h3 { + margin-top: 20px; + margin-bottom: 10px; +} +.h4, .h5, .h6, h4, h5, h6 { + margin-top: 10px; + margin-bottom: 10px; +} +.h1, .h2, .h3, .h4, .h5, .h6, h1, h2, h3, h4, h5, h6 { + font-weight: 500; + line-height: 1.1; + color: inherit; +} +.h1, +h1 { + font-size: 36px; +} +.h2, +h2 { + font-size: 30px; +} +.h3, +h3 { + font-size: 24px; +} +.h4, +h4 { + font-size: 18px; +} +.h5, +h5 { + font-size: 14px; +} +.h6, +h6 { + font-size: 12px; +} \ No newline at end of file diff --git "a/web/118 \346\227\205\346\270\270\346\231\272\346\205\247\344\270\255\345\277\203/static/css/index.css" "b/web/118 \346\227\205\346\270\270\346\231\272\346\205\247\344\270\255\345\277\203/static/css/index.css" new file mode 100644 index 00000000..39733aac --- /dev/null +++ "b/web/118 \346\227\205\346\270\270\346\231\272\346\205\247\344\270\255\345\277\203/static/css/index.css" @@ -0,0 +1,1275 @@ +@charset "utf-8"; +/*常用css*/ +.fl { + float: left; + _display: inline; +} +.fr { + float: right; + _display: inline; +} +/*常用字体*/ +.yh { + font-family: 'Microsoft YaHei'; +} +.st { + font-family: 'SimSun'; +} +.ar { + font-family: 'Arial'; +} +.roman { + font-family: "Times New Roman"; +} +.tn { + display: block; + font-size: 0; + text-indent: -99999em; + color: transparent; +} +.tt a:hover { + text-decoration: underline; +} +.xie { + font-style: italic; +} +.ddd { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} +a { + color: #666; +} +a:hover { + text-decoration: none; + color: #6b0018; +} +.btn { + cursor: pointer; +} +body { + font-size: 12px; + color: #666; + line-height: 24px; + min-width: 1200px; + font-family: 'Microsoft YaHei'; +} +.l { + color: #6b0018 !important; +} +.w { + width: 1200px; + min-width: 1200px; + margin: 0 auto; +} +/*header*/ +* { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +body { + min-width: 320px; + background: #000; +} +#wrap { + width: 2414px; + height: 1080px; + margin: 0 auto; + background: url(../images/bg.png) center no-repeat #0D1A35; + position: relative; +} +#wrap.auto { + position: fixed; + overflow: hidden; + left: 50%; + top: 50%; + z-index: 100; + -webkit-transition: 0.3s; + -moz-transition: 0.3s; + -ms-transition: 0.3s; + -o-transition: 0.3s; + transition: 0.3s; + -webkit-transform: translate(-50%, -50%); + -moz-transform: translate(-50%, -50%); + -ms-transform: translate(-50%, -50%); + -o-transform: translate(-50%, -50%); + transform: translate(-50%, -50%); + -webkit-transform-origin: left top; + -moz-transform: left top; + -ms-transform: left top; + -o-transform-origin: left top; + transform-origin: left top; +} +.header { + position: absolute; + left: 0; + top: 0; + width: 100%; + z-index: 100; + background: url(../images/headbg.png) no-repeat; + height: 140px; +} +.logo { + width: 740px; + height: 112px; + float: left; + text-indent: -9999px; + background: url(../images/logo.png) center no-repeat; +} +.head-r { + position: absolute; + right: 29px; + top: 0; + font-size: 30px; + color: #fff; + line-height: 112px; +} +.head-r .date-time, +.head-r .date-year { + padding-left: 29px; +} +.head-r .city { + font-size: 34px; + padding-right: 20px; +} +.head-r .tianqi-tep { + font-size: 20px; + padding-right: 12px; +} +.head-r .tianqi-icon img { + vertical-align: middle; + position: relative; + top: -4px; + height: 40px; +} +.mainbox { + position: absolute; + left: 0; + top: 0; + width: 100%; + z-index: 5; +} +.box { + border: 2px solid #164B7A; + background: rgba(10, 21, 39, 0.5); + position: absolute; + -webkit-box-shadow: inset 0 0 24px rgba(33, 159, 240, 0.4); + -moz-box-shadow: inset 0 0 24px rgba(33, 159, 240, 0.4); + box-shadow: inset 0 0 24px rgba(33, 159, 240, 0.4); + width: 497px; + height: 293px; +} +.box:before { + content: ""; + display: block; + background: url(../images/k.png) no-repeat; + width: 20px; + height: 20px; + position: absolute; + top: -2px; + left: -2px; +} +.box:after { + content: ""; + display: block; + background: url(../images/k.png) right top no-repeat; + width: 20px; + height: 20px; + position: absolute; + top: -2px; + right: -2px; +} +.box .box-inner:before { + content: ""; + display: block; + background: url(../images/k.png) left bottom no-repeat; + width: 20px; + height: 20px; + position: absolute; + bottom: -2px; + left: -2px; +} +.box .box-inner:after { + content: ""; + display: block; + background: url(../images/k.png) right bottom no-repeat; + width: 20px; + height: 20px; + position: absolute; + bottom: -2px; + right: -2px; +} +.box-title { + padding-left: 45px; + position: absolute; + left: 0; + top: 20px; + line-height: 20px; +} +.box-title h3 { + font-size: 15px; + color: #fff; + position: relative; +} +.box-title h3:after { + content: ""; + display: block; + width: 7px; + height: 14px; + background: #3F89FF; + position: absolute; + left: -16px; + top: 50%; + margin-top: -7px; +} +.box1 { + left: 31px; + top: 136px; +} +.box2 { + left: 31px; + top: 444px; +} +.box3 { + left: 31px; + top: 754px; +} +.box-r-1 { + right: 31px; + top: 136px; + height: 245px; +} +.box-r-2 { + right: 31px; + top: 400px; + height: 340px; +} +.box-r-3 { + right: 31px; + top: 754px; +} +.box-map { + position: absolute; + background: url(../images/map.png) no-repeat; + width: 1322px; + height: 601px; + left: 546px; + top: 137px; +} +.box-map .item { + position: absolute; + cursor: pointer; + text-indent: -9999px; +} +.box-map-info { + top: 755px; + left: 546px; + width: 1323px; +} +.building-table { + margin: 0 27px; + position: relative; + top: 47px; +} +.building-table .hd { + border-bottom: 1px solid #172843; + font-size: 15px; + color: #587199; + height: auto; + overflow: hidden; + text-align: center; + line-height: 42px; + margin-bottom: 15px; +} +.building-table li { + height: 27px; + line-height: 27px; +} +.building-table .col1 { + float: left; + width: 182px; +} +.building-table .col2 { + float: left; + width: 140px; + text-align: center; +} +.building-table .col3 { + float: right; + width: 110px; + text-align: center; +} +.building-table .bd { + font-size: 13px; + font-weight: 400; + color: #587199; + line-height: 27px; + height: 162px; +} +.building-table .bd .col1 { + text-indent: 2em; +} +.arrange-table { + margin: 0 20px; + position: relative; + top: 58px; +} +.arrange-table .hd { + margin-bottom: 24px; +} +.arrange-table .hd a { + display: inline-block; + width: 109px; + height: 52px; + text-align: center; + position: relative; +} +.arrange-table .hd a:before { + content: ""; + display: inline-block; + background: url(../images/tab-bg1.png) no-repeat; + width: 109px; + height: 52px; + position: absolute; + left: 0; + top: 0; +} +.arrange-table .hd a h4, +.arrange-table .hd a p { + font-size: 13px; + color: #587199; + text-align: center; + position: relative; +} +.arrange-table .hd a h4 { + padding-top: 10px; + line-height: 1.1em; +} +.arrange-table .hd a p { + color: #FFBA00; +} +.arrange-table .hd a.on:before { + height: 59px; + background-image: url(../images/tab-bg2.png); +} +.arrange-table .hd a.on h4 { + color: #00F519; +} +.arrange-table .item { + display: none; +} +.arrange-list { + height: 144px; + position: relative; + overflow: hidden; +} +.arrange-list li { + line-height: 36px; + position: relative; + overflow: hidden; + font-size: 14px; + height: 36px; + color: #587199; +} +.arrange-list li:after { + content: ""; + display: block; + width: 100%; + height: 1px; + line-height: 1px; + background: #172843; +} +.arrange-list .col1 { + float: left; + width: 52px; +} +.arrange-list .col2 { + width: 328px; + float: left; +} +.arrange-list .col3 { + float: right; +} +.arrange-list .btn-sg { + display: inline-block; + padding-left: 27px; + color: #587199; + background: url(../images/Arrange.png) 0 center no-repeat; +} +.arrange-list .btn-sg:hover { + color: #1D7CBF; +} +.total-number { + position: absolute; + left: 28px; + top: 82px; + width: 100px; +} +.total-number .label { + width: 98px; + height: 49px; + background: linear-gradient(0deg, #0E2A46, #0A1527); + border: 2px solid #216092; + border-radius: 10px; + text-align: center; + margin-bottom: 10px; +} +.total-number .label h4, +.total-number .label p { + font-size: 13px; + color: #fff; + line-height: 1.4em; +} +.total-number .label h4 { + padding-top: 7px; +} +.total-number .label p { + opacity: 0.5; +} +.total-echart { + position: absolute; + left: 130px; + right: 0; + top: 0; + height: 100%; +} +.total-num { + position: absolute; + width: 130px; + text-align: center; + color: #fff; + font-size: 14px; + right: 83px; + line-height: 24px; + top: 50%; + margin-top: -24px; +} +.box-map-info-tables { + padding: 60px 27px 0; + font-size: 13px; + color: #CCDFFD; +} +.box-map-info-tables th { + text-align: right; + font-size: 13px; + color: #587199; + font-weight: normal; +} +.box-map-info-tables th, +.box-map-info-tables td { + line-height: 27px; + vertical-align: top; +} +.box-map-info-tables .name { + position: relative; + height: 27px; +} +.box-map-info-tables .name strong { + position: absolute; + left: 0; + bottom: 0; + font-size: 41px; + color: #fff; + font-weight: bold; + display: block; + width: 100%; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + line-height: 1.5em; +} +.line-row { + margin: 15px 0; + border-top: 1px solid #152640; +} +.project-schedule { + padding-top: 62px; + height: auto; + overflow: hidden; +} +.project-schedule .col { + float: left; + width: 33.3%; + text-align: center; +} +.project-schedule p { + font-size: 13px; + color: #fff; + line-height: 2em; +} +.pop-jksp-content video { + width: 100%; + display: block; + background: #000; +} +.monitor-items { + width: 450px; + margin: 0 auto; + position: relative; + top: 67px; +} +.monitor-items:after { + content: ""; + display: table; + clear: both; +} +.monitor-box1 { + width: 327px; + height: 243px; + position: relative; +} +.monitor-box1 img { + display: block; + width: 100%; + height: 100%; +} +.monitor-box1 a { + display: block; + position: absolute; + width: 100%; + height: 100%; + left: 0; + top: 0; +} +.monitor-box2 { + width: 119px; + height: 78px; + position: absolute; + right: 0; + top: 0; +} +.monitor-box2 img { + display: block; + width: 100%; + height: 100%; +} +.monitor-box2 a { + display: block; + position: absolute; + width: 100%; + height: 100%; + left: 0; + top: 0; +} +.monitor-box3 { + width: 119px; + height: 78px; + position: absolute; + right: 0; + top: 82px; +} +.monitor-box3 img { + display: block; + width: 100%; + height: 100%; +} +.monitor-box3 a { + display: block; + position: absolute; + width: 100%; + height: 100%; + left: 0; + top: 0; +} +.monitor-box4 { + width: 119px; + height: 79px; + position: absolute; + right: 0; + top: 164px; +} +.monitor-box4 img { + display: block; + width: 100%; + height: 100%; +} +.monitor-box4 a { + display: block; + position: absolute; + width: 100%; + height: 100%; + left: 0; + top: 0; +} +.assurance-box { + margin: 0 25px; + padding-top: 57px; +} +.assurance-box .hd { + display: table; + width: 100%; + table-layout: fixed; + border-bottom: 1px solid #172843; +} +.assurance-box .hd a { + display: table-cell; + vertical-align: middle; + height: 48px; + line-height: 48px; + position: relative; + text-align: center; +} +.assurance-box .hd a span { + font-size: 13px; + color: #fff; +} +.assurance-box .hd a.on:after { + content: ""; + display: inline-block; + left: 15px; + right: 15px; + height: 4px; + background: #2952B2; + position: absolute; + line-height: 4px; + bottom: 0; +} +.assurance-box .item { + display: none; +} +.assurance-box .item ul { + padding-top: 26px; + display: table; + clear: both; + width: 100%; + table-layout: fixed; +} +.assurance-box .item li { + display: table-cell; + text-align: center; +} +.assurance-box .item a { + display: block; +} +.assurance-box .item .icon { + display: block; + margin: 0 auto 12px; + width: 94px; + height: 94px; + background: linear-gradient(90deg, #0E2A46, #0A1527); + border: 3px solid #377BBA; + border-radius: 25px; + position: relative; +} +.assurance-box .item .icon i { + position: absolute; + width: 100%; + height: 100%; + display: block; + background: url(../images/sitemap1.png) center no-repeat; +} +.assurance-box .item .small { + width: 65px; + height: 65px; +} +.assurance-box .item .small i { + -webkit-background-size: auto 60%; + background-size: auto 60%; +} +.assurance-box .item .btn-qqzb .icon i { + background-image: url(../images/plane2.png); +} +.assurance-box .item a:hover .icon, +.assurance-box .item a.on .icon { + border-color: #6CFF4A; + background: linear-gradient(90deg, #034105, #0A1527); + -webkit-box-shadow: 0 0 21px rgba(28, 154, 66, 0.78); + -moz-box-shadow: 0 0 21px rgba(28, 154, 66, 0.78); + box-shadow: 0 0 21px rgba(28, 154, 66, 0.78); +} +.assurance-box .item .btn-gltx:hover .icon i, +.assurance-box .item .btn-gltx.on .icon i { + background-image: url(../images/sitemap1-hover.png); +} +.assurance-box .item .btn-qqzb:hover .icon i, +.assurance-box .item .btn-qqzb.on .icon i { + background-image: url(../images/plane2-hover.png); +} +.assurance-box .item .btn-sg .icon i { + background-image: url(../images/sg.png); +} +.assurance-box .item .btn-sg:hover .icon i, +.assurance-box .item .btn-sg.on .icon i { + background-image: url(../images/sg-hover.png); +} +.assurance-box .item .btn-cel .icon i { + background-image: url(../images/cel.png); +} +.assurance-box .item .btn-cel:hover .icon i, +.assurance-box .item .btn-cel.on .icon i { + background-image: url(../images/cel-hover.png); +} +.assurance-box .item .btn-sy .icon i { + background-image: url(../images/sy.png); +} +.assurance-box .item .btn-sy:hover .icon i, +.assurance-box .item .btn-sy.on .icon i { + background-image: url(../images/sy-hover.png); +} +.assurance-box .item .btn-zj .icon i { + background-image: url(../images/zj.png); +} +.assurance-box .item .btn-zj:hover .icon i, +.assurance-box .item .btn-zj.on .icon i { + background-image: url(../images/zj-hover.png); +} +.assurance-box .item .btn-cl .icon i { + background-image: url(../images/cl.png); +} +.assurance-box .item .btn-cl:hover .icon i, +.assurance-box .item .btn-cl.on .icon i { + background-image: url(../images/cl-hover.png); +} +.assurance-box .item .btn-tj .icon i { + background-image: url(../images/tj.png); +} +.assurance-box .item .btn-tj:hover .icon i, +.assurance-box .item .btn-tj.on .icon i { + background-image: url(../images/tj-hover.png); +} +.assurance-box .item .btn-cpjy .icon i { + background-image: url(../images/cpjy.png); +} +.assurance-box .item .btn-cpjy:hover .icon i, +.assurance-box .item .btn-cpjy.on .icon i { + background-image: url(../images/cpjy-hover.png); +} +.assurance-box .item .btn-dw .icon i { + background-image: url(../images/dw.png); +} +.assurance-box .item .btn-dw:hover .icon i, +.assurance-box .item .btn-dw.on .icon i { + background-image: url(../images/dw-hover.png); +} +.assurance-box .item .btn-xmjjg .icon i { + background-image: url(../images/xmjjg.png); +} +.assurance-box .item .btn-xmjjg:hover .icon i, +.assurance-box .item .btn-xmjjg.on .icon i { + background-image: url(../images/xmjjg-hover.png); +} +.assurance-box .item p { + color: #fff; + font-size: 13px; + line-height: 25px; +} +[onclick], +a { + cursor: pointer; +} +.pop-mask { + position: fixed; + width: 100%; + left: 0; + height: 100%; + z-index: 90; + background: #000; + opacity: 0.5; + filter: alpha(opacity=50); +} +.pop-wrap { + display: none; +} +.pop-content-box { + position: absolute; + z-index: 91; + width: 600px; + border: 4px solid #3575AD; + border-radius: 25px; + padding: 0 34px 35px; + background: #12213A; + top: 250px; + left: 50%; + margin-left: -300px; + background: #0A1527; +} +.pop-ygxx-wrap .pop-content-box { + top: 150px; +} +.pop-title { + padding-left: 20px; + height: 76px; + line-height: 76px; + position: relative; +} +.pop-title:before { + content: ""; + display: block; + width: 7px; + height: 17px; + background: #3575AD; + left: 0; + position: absolute; + top: 50%; + margin-top: -9px; +} +.pop-title h2 { + color: #fff; +} +.pop-title .btn-x { + color: #3575AD; + position: absolute; + right: 0; + top: 0; + font-size: 40px; + font-weight: bold; +} +.pop-content { + background: #12213A; + border-radius: 25px; +} +.pop-gltx-content { + padding-bottom: 52px; +} +.pop-gltx-content ul { + height: auto; + overflow: hidden; + padding-left: 27px; + padding-top: 5px; + padding-bottom: 5px; +} +.pop-gltx-content li { + float: left; + width: 240px; + padding-top: 20px; + padding-bottom: 20px; + line-height: 60px; +} +.pop-gltx-content a { + display: block; + width: 100%; + display: -webkit-flex; + -webkit-flex-flow: row; + -webkit-align-items: center; + -webkit-justify-content: space-between; + display: flex; + flex-flow: row; + align-items: center; + justify-content: space-between; +} +.pop-gltx-content a span { + color: #fff; + font-size: 15px; + padding-left: 1em; + flex: 1; + line-height: 1.2em; +} +.pop-gltx-content .icon { + float: left; + width: 60px; + height: 60px; + background: url(../images/icon-group.png) center no-repeat #3575AD; + border-radius: 15px; +} +.pop-gltx-content .icon-people { + background-image: url(../images/icon-group.png); +} +.pop-gltx-content .icon-industry { + background-image: url(../images/icon-wenjian.png); +} +.pop-gltx-content .icon-file { + background-image: url(../images/icon-file.png); +} +.pop-gltx-content .icon-qqzb-1 { + background-image: url(../images/icon-qqzb-1.png); +} +.pop-gltx-content .icon-qqzb-2 { + background-image: url(../images/icon-qqzb-2.png); +} +.pop-gltx-content .icon-qqzb-3 { + background-image: url(../images/icon-qqzb-3.png); +} +.pop-gltx-content .icon-qqzb-4 { + background-image: url(../images/icon-qqzb-4.png); +} +.pop-gltx-content .icon-qqzb-5 { + background-image: url(../images/icon-qqzb-5.png); +} +.pop-gltx-content .icon-sg-1 { + background-image: url(../images/icon-sg-1.png); +} +.pop-gltx-content .icon-sg-2 { + background-image: url(../images/icon-sg-2.png); +} +.pop-gltx-content .icon-cel-1 { + background-image: url(../images/icon-cel-1.png); +} +.pop-gltx-content .icon-cel-2 { + background-image: url(../images/icon-cel-2.png); +} +.pop-gltx-content .icon-sy-1 { + background-image: url(../images/icon-sy-1.png); +} +.pop-gltx-content .icon-sy-2 { + background-image: url(../images/icon-sy-2.png); +} +.pop-gltx-content .icon-sy-3 { + background-image: url(../images/icon-sy-3.png); +} +.pop-gltx-content .icon-sy-4 { + background-image: url(../images/icon-sy-4.png); +} +.pop-gltx-content .icon-zj-1 { + background-image: url(../images/icon-zj-1.png); +} +.pop-gltx-content .icon-zj-2 { + background-image: url(../images/icon-zj-2.png); +} +.pop-gltx-content .icon-cl-1 { + background-image: url(../images/icon-cl-1.png); +} +.pop-gltx-content .icon-cl-2 { + background-image: url(../images/icon-cl-2.png); +} +.pop-gltx-content .icon-cl-3 { + background-image: url(../images/icon-cl-3.png); +} +.pop-gltx-content .icon-cl-4 { + background-image: url(../images/icon-cl-4.png); +} +.pop-gltx-content .icon-cl-5 { + background-image: url(../images/icon-cl-5.png); +} +.pop-gltx-content .icon-tj-1 { + background-image: url(../images/icon-tj-1.png); +} +.pop-gltx-content .icon-tj-2 { + background-image: url(../images/icon-tj-2.png); +} +.search-box { + width: 240px; + height: 36px; + border: 4px solid #243249; + border-radius: 50px; + position: absolute; + left: 171px; + top: 20px; + line-height: 28px; +} +.search-box input { + height: 28px; + background: none; + padding-left: 15px; + width: 190px; + line-height: 26px; + font-size: 15px; + color: #7186AA; +} +.search-box .btn-so { + width: 38px; + height: 28px; + text-indent: -9999px; + display: block; + background: url(../images/Search.png) center no-repeat; + position: absolute; + right: 0; + top: 0; +} +.pop-gr-content { + background: none; + border-radius: 0; +} +.pop-gr-content .hd { + height: auto; + overflow: hidden; + line-height: 43px; + background: #15253F; + font-size: 16px; + color: #8598BA; + text-align: center; +} +.pop-gr-content .col1 { + float: left; + width: 100px; + text-align: center; +} +.pop-gr-content .col2 { + float: left; + width: 100px; + text-align: center; +} +.pop-gr-content .col3 { + float: left; + margin-right: 10px; + width: 218px; + text-align: center; +} +.pop-gr-content .col3 p { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} +.pop-gr-content .col4 { + float: left; + width: 94px; + text-align: left; +} +.pop-gr-content .bd { + line-height: 43px; + font-size: 14px; + color: #8598BA; + overflow: hidden; + position: relative; +} +.pop-gr-content .bd li { + float: left; + width: 100%; +} +.pop-gr-content .bd ul { + height: auto; + overflow: hidden; + position: relative; + max-height: 430px; + overflow-y: auto; + width: 105%; +} +.pop-gr-content .bd li:nth-of-type(2n) { + background: #15253F; +} +.pop-ygxx-content { + height: 722px; + position: relative; +} +.pop-ygxx-content iframe { + border: 0; + position: absolute; + left: 0; + top: 0; + width: 100%; + height: 100%; + border-radius: 25px; + background: transparent; +} +.btn-pop-user { + cursor: pointer; +} +.userInfoBox { + width: 524px; + background: #12213A; +} +.user-head { + padding: 15px 20px; + height: auto; + overflow: hidden; + position: relative; +} +.user-head .avator { + width: 100px; + height: 100px; + position: absolute; + left: 20px; + top: 50%; + margin-top: -50px; + overflow: hidden; + border-radius: 100px; +} +.user-head .avator img { + display: block; + width: 100%; + height: 100%; + border-radius: 100px; +} +.user-head .txt { + font-size: 15px; + padding-left: 113px; + color: #fff; +} +.user-head .txt h2 { + font-size: 23px; + margin-bottom: 8px; +} +.user-head .labels { + margin-top: 5px; +} +.user-head .labels label { + display: inline-block; + height: 32px; + line-height: 32px; + border-radius: 50px; + padding: 0 14px; + font-size: 15px; + color: #fff; + background: #2952B2; +} +.user-tab-hd ul { + text-align: center; + display: table; + width: 100%; + table-layout: fixed; + border-bottom: 1px solid #21324F; +} +.user-tab-hd li { + display: table-cell; + vertical-align: middle; + line-height: 38px; +} +.user-tab-hd li a { + display: inline-block; + padding: 0 13px; + font-size: 13px; + color: #fff; + line-height: 38px; + position: relative; +} +.user-tab-hd li.on a:after { + content: ""; + display: inline-block; + width: 100%; + left: 0; + bottom: 0; + height: 4px; + position: absolute; + background: #2952B2; +} +.user-tab-bd { + height: 560px; +} +.user-tab-bd .item { + display: none; +} +.look-inner { + padding-top: 120px; +} +.look-inner .btn-look { + display: block; + width: 190px; + height: 190px; + margin: 0 auto; + background: url(../images/file.png) center 35px #162642 no-repeat; + border-radius: 100px; +} +.look-inner .btn-look p { + color: #fff; + text-align: center; + padding-top: 140px; + font-size: 13px; +} +.user-tab-bd .tips-row { + text-align: center; + padding-top: 25px; + padding-bottom: 20px; +} +.user-tab-bd .tips-row label { + display: inline-block; + position: relative; + font-size: 15px; + color: #fff; + margin: 0 33px; +} +.user-tab-bd .tips-row label:before { + content: ""; + display: inline-block; + width: 15px; + height: 15px; + border-radius: 50px; + position: relative; + top: 2px; + margin-right: 5px; +} +.user-tab-bd .tips-row .label-green:before { + background: #00D205; +} +.user-tab-bd .tips-row .label-blue:before { + background: #4068FF; +} +.user-tab-bd .tips-row .label-orange:before { + background: #FF3F2A; +} +.calendar-header { + display: none!important; +} +.calendar-table { + width: 100%; + table-layout: fixed; + text-align: center; + color: #fff; +} +.calendar-table th, +.calendar-table td { + text-align: center; +} +.calendar-table td { + padding-top: 15px; + padding-bottom: 15px; + vertical-align: middle; + position: relative; +} +.calendar-table .calendar-column-header { + font-size: 15px; +} +.calendar-table .calendar-value { + font-size: 25px; + color: #BDC1C8; + line-height: 1.2em; +} +.calendar-table .value { + color: #5C6778; + font-size: 13px; + line-height: 1.2em; +} +.calendar-table .calendar-work { + text-indent: -9999px; + width: 15px; + height: 15px; + background: #00D205; + border-radius: 50px; + position: absolute; + left: 50%; + margin-left: -8px; + top: 0; +} +.calendar-table .calendar-work-late { + text-indent: -9999px; + width: 15px; + height: 15px; + background: #4068FF; + border-radius: 50px; + position: absolute; + left: 50%; + margin-left: -8px; + top: 0; +} +.calendar-table .calendar-work-nosign { + text-indent: -9999px; + width: 15px; + height: 15px; + background: #FF3F2A; + border-radius: 50px; + position: absolute; + left: 50%; + margin-left: -8px; + top: 0; +} +.calendar-table .calendar-today:before { + content: ""; + display: inline-block; + position: absolute; + left: 15px; + top: 10px; + right: 15px; + bottom: 10px; + background: #A5ABB4; + border-radius: 8px; +} +.calendar-table .calendar-today .calendar-date { + position: relative; +} +.calendar-table .calendar-today .calendar-value { + color: #12213A; +} +.calendar-table .calendar-today .value { + color: #12213A; +} +.calendar-table .calendar-last-month-cell, +.calendar-table .calendar-next-month-cell { + opacity: 0.3; + filter: alpha(opacity=30); +} +.pop-jksp-wrap .pop-content-box { + width: 1104px; + top: 154px; + margin-left: -557px; +} +/*footer*/ diff --git "a/web/118 \346\227\205\346\270\270\346\231\272\346\205\247\344\270\255\345\277\203/static/css/reset.css" "b/web/118 \346\227\205\346\270\270\346\231\272\346\205\247\344\270\255\345\277\203/static/css/reset.css" new file mode 100644 index 00000000..1c24a1e6 --- /dev/null +++ "b/web/118 \346\227\205\346\270\270\346\231\272\346\205\247\344\270\255\345\277\203/static/css/reset.css" @@ -0,0 +1,112 @@ +@charset "utf-8"; +/* CSS Document */ +/*------- reset -------*/ +/* +author: web63.cn +Date:2015/01/01; +Version:1.0; +*/ +html, body, div, span, applet, object, iframe, +h1, h2, h3, h4, h5, h6, p, pre, +a, abbr, acronym, address, big, cite, code, +del, dfn, em, img, ins, kbd, q, s, samp, +small, strike, strong, sub, sup, tt, var, +b, u, i, center, +dl, dt, dd, ol, ul, li, +fieldset, form, label, legend, +table, caption, tbody, tfoot, thead, tr, th, td, +article, aside, canvas, details, embed, +figure, figcaption, footer, header, hgroup, +menu, nav, output, ruby, section, summary, +time, mark, audio, video { margin: 0; padding: 0; border: 0; font-size: 100%; font: inherit; vertical-align: baseline; + } + +/* HTML5标签初始化 +--------------------------------------------------*/ +article, aside, details, figcaption, figure, footer, header, hgroup, menu, nav, section { display: block; } + +/* 标签初始化 +--------------------------------------------------*/ +body { line-height: 1; color:#333;font:14px/1.5 Arial, Helvetica, Verdana, sans-serif} +ol, ul,li{ list-style: none; } +blockquote, q { + quotes: none; + border-left: solid 4px #39c; + margin-left: 10px; + padding-left: 10px; + background: whitesmoke; + margin: 10px auto; + padding: 6px 10px; + color: #666; + font-size: 20px; +} +i,em{ + font-style:normal; + font-weight:100; +} +blockquote:before, blockquote:after, +q:before, q:after { content: ''; content: none; } +table { border-collapse: collapse; border-spacing: 0; } +a img{ border:0; } +h1{ font-size:24px; font-weight: normal;} +h2{ font-size:20px; font-weight: normal;} +h3{ font-size:18px; font-weight: normal; } +h4{ font-size:14px; font-weight: normal;} +h5, h6{ font-size:12px; font-weight: normal;} +a,a:hover{ text-decoration:none; } +div{display:block;} +.tl{text-align: left;} +.tc{text-align: center;} +.tr{text-align: right;} + +table{ border-collapse: separate;border-spacing: 0;}th, td {text-align: left; font-weight: normal;} img, iframe {border: none; text-decoration:none;}input, textarea, select, button {font-size: 100%;font-family: inherit;margin:0;padding:0;}select {margin: inherit;} hr {margin: 0;padding: 0;border: 0;color: #000;background-color: #000;height: 1px} +strong,b{font-weight:100;} +input,button{border: 0;outline:none;} +/* 解决Google浏览器字体不小于12px的问题 +--------------------------------------------------*/ +html{ -webkit-text-size-adjust:none;} +a{color: #39c; + text-decoration: none;} +a:hover{ text-decoration: underline;} +a{outline: none;} +a:active{*star: expression(this.onFocus=this.blur());} +a:focus{*outline: 0; } + +/*清除浮动*/ +.clearfix:before,.clearfix:after {content:"";display:table;} +.clearfix:after{ clear:both; }/* For IE 6/7 (trigger hasLayout) */ +.clearfix{ zoom:1;} +.clear{clear:both;height:0px;overflow:hidden;} +.clear{clear:both;height:0px;overflow:hidden;} + +/*常用样式*/ +.pr{ position:relative} +.fb,strong{ font-weight:700;} +.fb0{ font-weight:100;} +.hid{overflow:hidden;} +.f12{ font-size:12px;} +.f14{ font-size:14px;} +.f16{ font-size:16px;} +.f18{ font-size:18px;} +.f20{ font-size:20px;} +.db{display: block;} +.imglink{display: block;text-align: center;} + +/*input 框提示文字 html5*/ +.placeholder{ + color:#7186AA; +} +input::-webkit-input-placeholder{ + color: #7186AA; +} +input::-moz-placeholder{ + color: #7186AA; +} +textarea::-webkit-input-placeholder{ + color: #7186AA; +} +textarea::-moz-placeholder{ + color: #7186AA; +} + +.hide{display: none;} diff --git "a/web/118 \346\227\205\346\270\270\346\231\272\346\205\247\344\270\255\345\277\203/static/date.js" "b/web/118 \346\227\205\346\270\270\346\231\272\346\205\247\344\270\255\345\277\203/static/date.js" new file mode 100644 index 00000000..61c5732a --- /dev/null +++ "b/web/118 \346\227\205\346\270\270\346\231\272\346\205\247\344\270\255\345\277\203/static/date.js" @@ -0,0 +1,40 @@ +class CurrentDate { + constructor() { + + } + getDate() { + var date = new Date() // 获取时间 + var year = date.getFullYear() // 获取年 + var month = date.getMonth() + 1 // 获取月 + var strDate = date.getDate() // 获取日 + // var day = date.getDate() // + var day = '日一二三四五六'.charAt(new Date().getDay()) // 周一返回的是1,周六是6,但是周日是0 + var hour = date.getHours() // 获取小时 + var minute = date.getMinutes() // 获取分钟 + var second = date.getSeconds() // 获取秒 + // 由于部分业务处理 是需要月份日份前面有0 故新增一个函数 + // this.getNum() + $('.week').html('星期' + day) + $('.date').html(year + + '-' + + this.getNum(month) + + '-' + + this.getNum(strDate) + + ' ' + + this.getNum(hour) + + ':' + + this.getNum(minute) + + ':' + + this.getNum(second)) + } + getNum(i) { + return i < 10 ? '0' + i : i + } + // 再加一个定时器每秒获取 + getTime() { + this.getDate() + setInterval(() => { + this.getDate() + }, 1000) + } +} \ No newline at end of file diff --git "a/web/118 \346\227\205\346\270\270\346\231\272\346\205\247\344\270\255\345\277\203/static/echarts.min.js" "b/web/118 \346\227\205\346\270\270\346\231\272\346\205\247\344\270\255\345\277\203/static/echarts.min.js" new file mode 100644 index 00000000..4beb85ac --- /dev/null +++ "b/web/118 \346\227\205\346\270\270\346\231\272\346\205\247\344\270\255\345\277\203/static/echarts.min.js" @@ -0,0 +1,45 @@ + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).echarts={})}(this,(function(t){"use strict"; +/*! ***************************************************************************** + Copyright (c) Microsoft Corporation. + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH + REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, + INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + PERFORMANCE OF THIS SOFTWARE. + ***************************************************************************** */var e=function(t,n){return(e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,e){t.__proto__=e}||function(t,e){for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t[n]=e[n])})(t,n)};function n(t,n){function i(){this.constructor=t}e(t,n),t.prototype=null===n?Object.create(n):(i.prototype=n.prototype,new i)}var i=function(){return(i=Object.assign||function(t){for(var e,n=1,i=arguments.length;n18);a&&(n.weChat=!0);e.canvasSupported=!!document.createElement("canvas").getContext,e.svgSupported="undefined"!=typeof SVGRect,e.touchEventsSupported="ontouchstart"in window&&!n.ie&&!n.edge,e.pointerEventsSupported="onpointerdown"in window&&(n.edge||n.ie&&+n.version>=11),e.domSupported="undefined"!=typeof document}(navigator.userAgent,a);var s={"[object Function]":!0,"[object RegExp]":!0,"[object Date]":!0,"[object Error]":!0,"[object CanvasGradient]":!0,"[object CanvasPattern]":!0,"[object Image]":!0,"[object Canvas]":!0},l={"[object Int8Array]":!0,"[object Uint8Array]":!0,"[object Uint8ClampedArray]":!0,"[object Int16Array]":!0,"[object Uint16Array]":!0,"[object Int32Array]":!0,"[object Uint32Array]":!0,"[object Float32Array]":!0,"[object Float64Array]":!0},u=Object.prototype.toString,h=Array.prototype,c=h.forEach,p=h.filter,d=h.slice,f=h.map,g=function(){}.constructor,y=g?g.prototype:null,v={};function m(t,e){v[t]=e}var _=2311;function x(){return _++}function b(){for(var t=[],e=0;e>1)%2;a.style.cssText=["position: absolute","visibility: hidden","padding: 0","margin: 0","border-width: 0","user-select: none","width:0","height:0",i[s]+":0",r[l]+":0",i[1-s]+":auto",r[1-l]+":auto",""].join("!important;"),t.appendChild(a),n.push(a)}return n}(e,o),o,r);if(s)return s(t,n,i),!0}return!1}function Ut(t){return"CANVAS"===t.nodeName.toUpperCase()}var Zt="undefined"!=typeof window&&!!window.addEventListener,jt=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,qt=[];function Kt(t,e,n,i){return n=n||{},i||!a.canvasSupported?$t(t,e,n):a.browser.firefox&&null!=e.layerX&&e.layerX!==e.offsetX?(n.zrX=e.layerX,n.zrY=e.layerY):null!=e.offsetX?(n.zrX=e.offsetX,n.zrY=e.offsetY):$t(t,e,n),n}function $t(t,e,n){if(a.domSupported&&t.getBoundingClientRect){var i=e.clientX,r=e.clientY;if(Ut(t)){var o=t.getBoundingClientRect();return n.zrX=i-o.left,void(n.zrY=r-o.top)}if(Xt(qt,t,i,r))return n.zrX=qt[0],void(n.zrY=qt[1])}n.zrX=n.zrY=0}function Jt(t){return t||window.event}function Qt(t,e,n){if(null!=(e=Jt(e)).zrX)return e;var i=e.type;if(i&&i.indexOf("touch")>=0){var r="touchend"!==i?e.targetTouches[0]:e.changedTouches[0];r&&Kt(t,r,e,n)}else{Kt(t,e,e,n);var o=function(t){var e=t.wheelDelta;if(e)return e;var n=t.deltaX,i=t.deltaY;if(null==n||null==i)return e;return 3*(0!==i?Math.abs(i):Math.abs(n))*(i>0?-1:i<0?1:n>0?-1:1)}(e);e.zrDelta=o?o/120:-(e.detail||0)/3}var a=e.button;return null==e.which&&void 0!==a&&jt.test(e.type)&&(e.which=1&a?1:2&a?3:4&a?2:0),e}function te(t,e,n,i){Zt?t.addEventListener(e,n,i):t.attachEvent("on"+e,n)}var ee=Zt?function(t){t.preventDefault(),t.stopPropagation(),t.cancelBubble=!0}:function(t){t.returnValue=!1,t.cancelBubble=!0};function ne(t){return 2===t.which||3===t.which}var ie=function(){function t(){this._track=[]}return t.prototype.recognize=function(t,e,n){return this._doTrack(t,e,n),this._recognize(t)},t.prototype.clear=function(){return this._track.length=0,this},t.prototype._doTrack=function(t,e,n){var i=t.touches;if(i){for(var r={points:[],touches:[],target:e,event:t},o=0,a=i.length;o1&&r&&r.length>1){var a=re(r)/re(o);!isFinite(a)&&(a=1),e.pinchScale=a;var s=[((i=r)[0][0]+i[1][0])/2,(i[0][1]+i[1][1])/2];return e.pinchX=s[0],e.pinchY=s[1],{type:"pinch",target:t[0].target,event:e}}}}},ae="silent";function se(){ee(this.event)}var le=function(t){function e(){var e=null!==t&&t.apply(this,arguments)||this;return e.handler=null,e}return n(e,t),e.prototype.dispose=function(){},e.prototype.setCursor=function(){},e}(Ft),ue=function(t,e){this.x=t,this.y=e},he=["click","dblclick","mousewheel","mouseout","mouseup","mousedown","mousemove","contextmenu"],ce=function(t){function e(e,n,i,r){var o=t.call(this)||this;return o._hovered=new ue(0,0),o.storage=e,o.painter=n,o.painterRoot=r,i=i||new le,o.proxy=null,o.setHandlerProxy(i),o._draggingMgr=new Vt(o),o}return n(e,t),e.prototype.setHandlerProxy=function(t){this.proxy&&this.proxy.dispose(),t&&(P(he,(function(e){t.on&&t.on(e,this[e],this)}),this),t.handler=this),this.proxy=t},e.prototype.mousemove=function(t){var e=t.zrX,n=t.zrY,i=de(this,e,n),r=this._hovered,o=r.target;o&&!o.__zr&&(o=(r=this.findHover(r.x,r.y)).target);var a=this._hovered=i?new ue(e,n):this.findHover(e,n),s=a.target,l=this.proxy;l.setCursor&&l.setCursor(s?s.cursor:"default"),o&&s!==o&&this.dispatchToElement(r,"mouseout",t),this.dispatchToElement(a,"mousemove",t),s&&s!==o&&this.dispatchToElement(a,"mouseover",t)},e.prototype.mouseout=function(t){var e=t.zrEventControl;"only_globalout"!==e&&this.dispatchToElement(this._hovered,"mouseout",t),"no_globalout"!==e&&this.trigger("globalout",{type:"globalout",event:t})},e.prototype.resize=function(){this._hovered=new ue(0,0)},e.prototype.dispatch=function(t,e){var n=this[t];n&&n.call(this,e)},e.prototype.dispose=function(){this.proxy.dispose(),this.storage=null,this.proxy=null,this.painter=null},e.prototype.setCursorStyle=function(t){var e=this.proxy;e.setCursor&&e.setCursor(t)},e.prototype.dispatchToElement=function(t,e,n){var i=(t=t||{}).target;if(!i||!i.silent){for(var r="on"+e,o=function(t,e,n){return{type:t,event:n,target:e.target,topTarget:e.topTarget,cancelBubble:!1,offsetX:n.zrX,offsetY:n.zrY,gestureEvent:n.gestureEvent,pinchX:n.pinchX,pinchY:n.pinchY,pinchScale:n.pinchScale,wheelDelta:n.zrDelta,zrByTouch:n.zrByTouch,which:n.which,stop:se}}(e,t,n);i&&(i[r]&&(o.cancelBubble=!!i[r].call(i,o)),i.trigger(e,o),i=i.__hostTarget?i.__hostTarget:i.parent,!o.cancelBubble););o.cancelBubble||(this.trigger(e,o),this.painter&&this.painter.eachOtherLayer&&this.painter.eachOtherLayer((function(t){"function"==typeof t[r]&&t[r].call(t,o),t.trigger&&t.trigger(e,o)})))}},e.prototype.findHover=function(t,e,n){for(var i=this.storage.getDisplayList(),r=new ue(t,e),o=i.length-1;o>=0;o--){var a=void 0;if(i[o]!==n&&!i[o].ignore&&(a=pe(i[o],t,e))&&(!r.topTarget&&(r.topTarget=i[o]),a!==ae)){r.target=i[o];break}}return r},e.prototype.processGesture=function(t,e){this._gestureMgr||(this._gestureMgr=new ie);var n=this._gestureMgr;"start"===e&&n.clear();var i=n.recognize(t,this.findHover(t.zrX,t.zrY,null).target,this.proxy.dom);if("end"===e&&n.clear(),i){var r=i.type;t.gestureEvent=r;var o=new ue;o.target=i.target,this.dispatchToElement(o,r,i.event)}},e}(Ft);function pe(t,e,n){if(t[t.rectHover?"rectContain":"contain"](e,n)){for(var i=t,r=void 0,o=!1;i;){if(i.ignoreClip&&(o=!0),!o){var a=i.getClipPath();if(a&&!a.contain(e,n))return!1;i.silent&&(r=!0)}var s=i.__hostTarget;i=s||i.parent}return!r||ae}return!1}function de(t,e,n){var i=t.painter;return e<0||e>i.getWidth()||n<0||n>i.getHeight()}function fe(){return[1,0,0,1,0,0]}function ge(t){return t[0]=1,t[1]=0,t[2]=0,t[3]=1,t[4]=0,t[5]=0,t}function ye(t,e){return t[0]=e[0],t[1]=e[1],t[2]=e[2],t[3]=e[3],t[4]=e[4],t[5]=e[5],t}function ve(t,e,n){var i=e[0]*n[0]+e[2]*n[1],r=e[1]*n[0]+e[3]*n[1],o=e[0]*n[2]+e[2]*n[3],a=e[1]*n[2]+e[3]*n[3],s=e[0]*n[4]+e[2]*n[5]+e[4],l=e[1]*n[4]+e[3]*n[5]+e[5];return t[0]=i,t[1]=r,t[2]=o,t[3]=a,t[4]=s,t[5]=l,t}function me(t,e,n){return t[0]=e[0],t[1]=e[1],t[2]=e[2],t[3]=e[3],t[4]=e[4]+n[0],t[5]=e[5]+n[1],t}function _e(t,e,n){var i=e[0],r=e[2],o=e[4],a=e[1],s=e[3],l=e[5],u=Math.sin(n),h=Math.cos(n);return t[0]=i*h+a*u,t[1]=-i*u+a*h,t[2]=r*h+s*u,t[3]=-r*u+h*s,t[4]=h*o+u*l,t[5]=h*l-u*o,t}function xe(t,e,n){var i=n[0],r=n[1];return t[0]=e[0]*i,t[1]=e[1]*r,t[2]=e[2]*i,t[3]=e[3]*r,t[4]=e[4]*i,t[5]=e[5]*r,t}function be(t,e){var n=e[0],i=e[2],r=e[4],o=e[1],a=e[3],s=e[5],l=n*a-o*i;return l?(l=1/l,t[0]=a*l,t[1]=-o*l,t[2]=-i*l,t[3]=n*l,t[4]=(i*s-a*r)*l,t[5]=(o*r-n*s)*l,t):null}function we(t){var e=[1,0,0,1,0,0];return ye(e,t),e}P(["click","mousedown","mouseup","mousewheel","dblclick","contextmenu"],(function(t){ce.prototype[t]=function(e){var n,i,r=e.zrX,o=e.zrY,a=de(this,r,o);if("mouseup"===t&&a||(i=(n=this.findHover(r,o)).target),"mousedown"===t)this._downEl=i,this._downPoint=[e.zrX,e.zrY],this._upEl=i;else if("mouseup"===t)this._upEl=i;else if("click"===t){if(this._downEl!==this._upEl||!this._downPoint||Lt(this._downPoint,[e.zrX,e.zrY])>4)return;this._downPoint=null}this.dispatchToElement(n,t,e)}}));var Se=Object.freeze({__proto__:null,create:fe,identity:ge,copy:ye,mul:ve,translate:me,rotate:_e,scale:xe,invert:be,clone:we}),Me=ge,Ie=5e-5;function Te(t){return t>Ie||t<-5e-5}var Ce=[],Ae=[],De=[1,0,0,1,0,0],Le=Math.abs,ke=function(){function t(){}return t.prototype.setPosition=function(t){this.x=t[0],this.y=t[1]},t.prototype.setScale=function(t){this.scaleX=t[0],this.scaleY=t[1]},t.prototype.setOrigin=function(t){this.originX=t[0],this.originY=t[1]},t.prototype.needLocalTransform=function(){return Te(this.rotation)||Te(this.x)||Te(this.y)||Te(this.scaleX-1)||Te(this.scaleY-1)},t.prototype.updateTransform=function(){var t=this.parent,e=t&&t.transform,n=this.needLocalTransform(),i=this.transform;n||e?(i=i||[1,0,0,1,0,0],n?this.getLocalTransform(i):Me(i),e&&(n?ve(i,t.transform,i):ye(i,t.transform)),this.transform=i,this._resolveGlobalScaleRatio(i)):i&&Me(i)},t.prototype._resolveGlobalScaleRatio=function(t){var e=this.globalScaleRatio;if(null!=e&&1!==e){this.getGlobalScale(Ce);var n=Ce[0]<0?-1:1,i=Ce[1]<0?-1:1,r=((Ce[0]-n)*e+n)/Ce[0]||0,o=((Ce[1]-i)*e+i)/Ce[1]||0;t[0]*=r,t[1]*=r,t[2]*=o,t[3]*=o}this.invTransform=this.invTransform||[1,0,0,1,0,0],be(this.invTransform,t)},t.prototype.getLocalTransform=function(e){return t.getLocalTransform(this,e)},t.prototype.getComputedTransform=function(){for(var t=this,e=[];t;)e.push(t),t=t.parent;for(;t=e.pop();)t.updateTransform();return this.transform},t.prototype.setLocalTransform=function(t){if(t){var e=t[0]*t[0]+t[1]*t[1],n=t[2]*t[2]+t[3]*t[3];Te(e-1)&&(e=Math.sqrt(e)),Te(n-1)&&(n=Math.sqrt(n)),t[0]<0&&(e=-e),t[3]<0&&(n=-n),this.rotation=Math.atan2(-t[1]/n,t[0]/e),e<0&&n<0&&(this.rotation+=Math.PI,e=-e,n=-n),this.x=t[4],this.y=t[5],this.scaleX=e,this.scaleY=n}},t.prototype.decomposeTransform=function(){if(this.transform){var t=this.parent,e=this.transform;t&&t.transform&&(ve(Ae,t.invTransform,e),e=Ae);var n=this.originX,i=this.originY;(n||i)&&(De[4]=n,De[5]=i,ve(Ae,e,De),Ae[4]-=n,Ae[5]-=i,e=Ae),this.setLocalTransform(e)}},t.prototype.getGlobalScale=function(t){var e=this.transform;return t=t||[],e?(t[0]=Math.sqrt(e[0]*e[0]+e[1]*e[1]),t[1]=Math.sqrt(e[2]*e[2]+e[3]*e[3]),e[0]<0&&(t[0]=-t[0]),e[3]<0&&(t[1]=-t[1]),t):(t[0]=1,t[1]=1,t)},t.prototype.transformCoordToLocal=function(t,e){var n=[t,e],i=this.invTransform;return i&&Rt(n,n,i),n},t.prototype.transformCoordToGlobal=function(t,e){var n=[t,e],i=this.transform;return i&&Rt(n,n,i),n},t.prototype.getLineScale=function(){var t=this.transform;return t&&Le(t[0]-1)>1e-10&&Le(t[3]-1)>1e-10?Math.sqrt(Le(t[0]*t[3]-t[2]*t[1])):1},t.getLocalTransform=function(t,e){Me(e=e||[]);var n=t.originX||0,i=t.originY||0,r=t.scaleX,o=t.scaleY,a=t.rotation||0,s=t.x,l=t.y;return e[4]-=n,e[5]-=i,e[0]*=r,e[1]*=o,e[2]*=r,e[3]*=o,e[4]*=r,e[5]*=o,a&&_e(e,e,a),e[4]+=n,e[5]+=i,e[4]+=s,e[5]+=l,e},t.initDefaultProps=function(){var e=t.prototype;e.x=0,e.y=0,e.scaleX=1,e.scaleY=1,e.originX=0,e.originY=0,e.rotation=0,e.globalScaleRatio=1}(),t}(),Pe={linear:function(t){return t},quadraticIn:function(t){return t*t},quadraticOut:function(t){return t*(2-t)},quadraticInOut:function(t){return(t*=2)<1?.5*t*t:-.5*(--t*(t-2)-1)},cubicIn:function(t){return t*t*t},cubicOut:function(t){return--t*t*t+1},cubicInOut:function(t){return(t*=2)<1?.5*t*t*t:.5*((t-=2)*t*t+2)},quarticIn:function(t){return t*t*t*t},quarticOut:function(t){return 1- --t*t*t*t},quarticInOut:function(t){return(t*=2)<1?.5*t*t*t*t:-.5*((t-=2)*t*t*t-2)},quinticIn:function(t){return t*t*t*t*t},quinticOut:function(t){return--t*t*t*t*t+1},quinticInOut:function(t){return(t*=2)<1?.5*t*t*t*t*t:.5*((t-=2)*t*t*t*t+2)},sinusoidalIn:function(t){return 1-Math.cos(t*Math.PI/2)},sinusoidalOut:function(t){return Math.sin(t*Math.PI/2)},sinusoidalInOut:function(t){return.5*(1-Math.cos(Math.PI*t))},exponentialIn:function(t){return 0===t?0:Math.pow(1024,t-1)},exponentialOut:function(t){return 1===t?1:1-Math.pow(2,-10*t)},exponentialInOut:function(t){return 0===t?0:1===t?1:(t*=2)<1?.5*Math.pow(1024,t-1):.5*(2-Math.pow(2,-10*(t-1)))},circularIn:function(t){return 1-Math.sqrt(1-t*t)},circularOut:function(t){return Math.sqrt(1- --t*t)},circularInOut:function(t){return(t*=2)<1?-.5*(Math.sqrt(1-t*t)-1):.5*(Math.sqrt(1-(t-=2)*t)+1)},elasticIn:function(t){var e,n=.1;return 0===t?0:1===t?1:(!n||n<1?(n=1,e=.1):e=.4*Math.asin(1/n)/(2*Math.PI),-n*Math.pow(2,10*(t-=1))*Math.sin((t-e)*(2*Math.PI)/.4))},elasticOut:function(t){var e,n=.1;return 0===t?0:1===t?1:(!n||n<1?(n=1,e=.1):e=.4*Math.asin(1/n)/(2*Math.PI),n*Math.pow(2,-10*t)*Math.sin((t-e)*(2*Math.PI)/.4)+1)},elasticInOut:function(t){var e,n=.1,i=.4;return 0===t?0:1===t?1:(!n||n<1?(n=1,e=.1):e=i*Math.asin(1/n)/(2*Math.PI),(t*=2)<1?n*Math.pow(2,10*(t-=1))*Math.sin((t-e)*(2*Math.PI)/i)*-.5:n*Math.pow(2,-10*(t-=1))*Math.sin((t-e)*(2*Math.PI)/i)*.5+1)},backIn:function(t){var e=1.70158;return t*t*((e+1)*t-e)},backOut:function(t){var e=1.70158;return--t*t*((e+1)*t+e)+1},backInOut:function(t){var e=2.5949095;return(t*=2)<1?t*t*((e+1)*t-e)*.5:.5*((t-=2)*t*((e+1)*t+e)+2)},bounceIn:function(t){return 1-Pe.bounceOut(1-t)},bounceOut:function(t){return t<1/2.75?7.5625*t*t:t<2/2.75?7.5625*(t-=1.5/2.75)*t+.75:t<2.5/2.75?7.5625*(t-=2.25/2.75)*t+.9375:7.5625*(t-=2.625/2.75)*t+.984375},bounceInOut:function(t){return t<.5?.5*Pe.bounceIn(2*t):.5*Pe.bounceOut(2*t-1)+.5}},Oe=function(){function t(t){this._initialized=!1,this._startTime=0,this._pausedTime=0,this._paused=!1,this._life=t.life||1e3,this._delay=t.delay||0,this.loop=null!=t.loop&&t.loop,this.gap=t.gap||0,this.easing=t.easing||"linear",this.onframe=t.onframe,this.ondestroy=t.ondestroy,this.onrestart=t.onrestart}return t.prototype.step=function(t,e){if(this._initialized||(this._startTime=t+this._delay,this._initialized=!0),!this._paused){var n=(t-this._startTime-this._pausedTime)/this._life;n<0&&(n=0),n=Math.min(n,1);var i=this.easing,r="string"==typeof i?Pe[i]:i,o="function"==typeof r?r(n):n;if(this.onframe&&this.onframe(o),1===n){if(!this.loop)return!0;this._restart(t),this.onrestart&&this.onrestart()}return!1}this._pausedTime+=e},t.prototype._restart=function(t){var e=(t-this._startTime-this._pausedTime)%this._life;this._startTime=t-e+this.gap,this._pausedTime=0},t.prototype.pause=function(){this._paused=!0},t.prototype.resume=function(){this._paused=!1},t}(),Re=function(t){this.value=t},Ne=function(){function t(){this._len=0}return t.prototype.insert=function(t){var e=new Re(t);return this.insertEntry(e),e},t.prototype.insertEntry=function(t){this.head?(this.tail.next=t,t.prev=this.tail,t.next=null,this.tail=t):this.head=this.tail=t,this._len++},t.prototype.remove=function(t){var e=t.prev,n=t.next;e?e.next=n:this.head=n,n?n.prev=e:this.tail=e,t.next=t.prev=null,this._len--},t.prototype.len=function(){return this._len},t.prototype.clear=function(){this.head=this.tail=null,this._len=0},t}(),Ee=function(){function t(t){this._list=new Ne,this._maxSize=10,this._map={},this._maxSize=t}return t.prototype.put=function(t,e){var n=this._list,i=this._map,r=null;if(null==i[t]){var o=n.len(),a=this._lastRemovedEntry;if(o>=this._maxSize&&o>0){var s=n.head;n.remove(s),delete i[s.key],r=s.value,this._lastRemovedEntry=s}a?a.value=e:a=new Re(e),a.key=t,n.insertEntry(a),i[t]=a}return r},t.prototype.get=function(t){var e=this._map[t],n=this._list;if(null!=e)return e!==n.tail&&(n.remove(e),n.insertEntry(e)),e.value},t.prototype.clear=function(){this._list.clear(),this._map={}},t.prototype.len=function(){return this._list.len()},t}(),ze={transparent:[0,0,0,0],aliceblue:[240,248,255,1],antiquewhite:[250,235,215,1],aqua:[0,255,255,1],aquamarine:[127,255,212,1],azure:[240,255,255,1],beige:[245,245,220,1],bisque:[255,228,196,1],black:[0,0,0,1],blanchedalmond:[255,235,205,1],blue:[0,0,255,1],blueviolet:[138,43,226,1],brown:[165,42,42,1],burlywood:[222,184,135,1],cadetblue:[95,158,160,1],chartreuse:[127,255,0,1],chocolate:[210,105,30,1],coral:[255,127,80,1],cornflowerblue:[100,149,237,1],cornsilk:[255,248,220,1],crimson:[220,20,60,1],cyan:[0,255,255,1],darkblue:[0,0,139,1],darkcyan:[0,139,139,1],darkgoldenrod:[184,134,11,1],darkgray:[169,169,169,1],darkgreen:[0,100,0,1],darkgrey:[169,169,169,1],darkkhaki:[189,183,107,1],darkmagenta:[139,0,139,1],darkolivegreen:[85,107,47,1],darkorange:[255,140,0,1],darkorchid:[153,50,204,1],darkred:[139,0,0,1],darksalmon:[233,150,122,1],darkseagreen:[143,188,143,1],darkslateblue:[72,61,139,1],darkslategray:[47,79,79,1],darkslategrey:[47,79,79,1],darkturquoise:[0,206,209,1],darkviolet:[148,0,211,1],deeppink:[255,20,147,1],deepskyblue:[0,191,255,1],dimgray:[105,105,105,1],dimgrey:[105,105,105,1],dodgerblue:[30,144,255,1],firebrick:[178,34,34,1],floralwhite:[255,250,240,1],forestgreen:[34,139,34,1],fuchsia:[255,0,255,1],gainsboro:[220,220,220,1],ghostwhite:[248,248,255,1],gold:[255,215,0,1],goldenrod:[218,165,32,1],gray:[128,128,128,1],green:[0,128,0,1],greenyellow:[173,255,47,1],grey:[128,128,128,1],honeydew:[240,255,240,1],hotpink:[255,105,180,1],indianred:[205,92,92,1],indigo:[75,0,130,1],ivory:[255,255,240,1],khaki:[240,230,140,1],lavender:[230,230,250,1],lavenderblush:[255,240,245,1],lawngreen:[124,252,0,1],lemonchiffon:[255,250,205,1],lightblue:[173,216,230,1],lightcoral:[240,128,128,1],lightcyan:[224,255,255,1],lightgoldenrodyellow:[250,250,210,1],lightgray:[211,211,211,1],lightgreen:[144,238,144,1],lightgrey:[211,211,211,1],lightpink:[255,182,193,1],lightsalmon:[255,160,122,1],lightseagreen:[32,178,170,1],lightskyblue:[135,206,250,1],lightslategray:[119,136,153,1],lightslategrey:[119,136,153,1],lightsteelblue:[176,196,222,1],lightyellow:[255,255,224,1],lime:[0,255,0,1],limegreen:[50,205,50,1],linen:[250,240,230,1],magenta:[255,0,255,1],maroon:[128,0,0,1],mediumaquamarine:[102,205,170,1],mediumblue:[0,0,205,1],mediumorchid:[186,85,211,1],mediumpurple:[147,112,219,1],mediumseagreen:[60,179,113,1],mediumslateblue:[123,104,238,1],mediumspringgreen:[0,250,154,1],mediumturquoise:[72,209,204,1],mediumvioletred:[199,21,133,1],midnightblue:[25,25,112,1],mintcream:[245,255,250,1],mistyrose:[255,228,225,1],moccasin:[255,228,181,1],navajowhite:[255,222,173,1],navy:[0,0,128,1],oldlace:[253,245,230,1],olive:[128,128,0,1],olivedrab:[107,142,35,1],orange:[255,165,0,1],orangered:[255,69,0,1],orchid:[218,112,214,1],palegoldenrod:[238,232,170,1],palegreen:[152,251,152,1],paleturquoise:[175,238,238,1],palevioletred:[219,112,147,1],papayawhip:[255,239,213,1],peachpuff:[255,218,185,1],peru:[205,133,63,1],pink:[255,192,203,1],plum:[221,160,221,1],powderblue:[176,224,230,1],purple:[128,0,128,1],red:[255,0,0,1],rosybrown:[188,143,143,1],royalblue:[65,105,225,1],saddlebrown:[139,69,19,1],salmon:[250,128,114,1],sandybrown:[244,164,96,1],seagreen:[46,139,87,1],seashell:[255,245,238,1],sienna:[160,82,45,1],silver:[192,192,192,1],skyblue:[135,206,235,1],slateblue:[106,90,205,1],slategray:[112,128,144,1],slategrey:[112,128,144,1],snow:[255,250,250,1],springgreen:[0,255,127,1],steelblue:[70,130,180,1],tan:[210,180,140,1],teal:[0,128,128,1],thistle:[216,191,216,1],tomato:[255,99,71,1],turquoise:[64,224,208,1],violet:[238,130,238,1],wheat:[245,222,179,1],white:[255,255,255,1],whitesmoke:[245,245,245,1],yellow:[255,255,0,1],yellowgreen:[154,205,50,1]};function Be(t){return(t=Math.round(t))<0?0:t>255?255:t}function Ve(t){return t<0?0:t>1?1:t}function Fe(t){var e=t;return e.length&&"%"===e.charAt(e.length-1)?Be(parseFloat(e)/100*255):Be(parseInt(e,10))}function Ge(t){var e=t;return e.length&&"%"===e.charAt(e.length-1)?Ve(parseFloat(e)/100):Ve(parseFloat(e))}function He(t,e,n){return n<0?n+=1:n>1&&(n-=1),6*n<1?t+(e-t)*n*6:2*n<1?e:3*n<2?t+(e-t)*(2/3-n)*6:t}function We(t,e,n){return t+(e-t)*n}function Ye(t,e,n,i,r){return t[0]=e,t[1]=n,t[2]=i,t[3]=r,t}function Xe(t,e){return t[0]=e[0],t[1]=e[1],t[2]=e[2],t[3]=e[3],t}var Ue=new Ee(20),Ze=null;function je(t,e){Ze&&Xe(Ze,e),Ze=Ue.put(t,Ze||e.slice())}function qe(t,e){if(t){e=e||[];var n=Ue.get(t);if(n)return Xe(e,n);var i=(t+="").replace(/ /g,"").toLowerCase();if(i in ze)return Xe(e,ze[i]),je(t,e),e;var r,o=i.length;if("#"===i.charAt(0))return 4===o||5===o?(r=parseInt(i.slice(1,4),16))>=0&&r<=4095?(Ye(e,(3840&r)>>4|(3840&r)>>8,240&r|(240&r)>>4,15&r|(15&r)<<4,5===o?parseInt(i.slice(4),16)/15:1),je(t,e),e):void Ye(e,0,0,0,1):7===o||9===o?(r=parseInt(i.slice(1,7),16))>=0&&r<=16777215?(Ye(e,(16711680&r)>>16,(65280&r)>>8,255&r,9===o?parseInt(i.slice(7),16)/255:1),je(t,e),e):void Ye(e,0,0,0,1):void 0;var a=i.indexOf("("),s=i.indexOf(")");if(-1!==a&&s+1===o){var l=i.substr(0,a),u=i.substr(a+1,s-(a+1)).split(","),h=1;switch(l){case"rgba":if(4!==u.length)return 3===u.length?Ye(e,+u[0],+u[1],+u[2],1):Ye(e,0,0,0,1);h=Ge(u.pop());case"rgb":return 3!==u.length?void Ye(e,0,0,0,1):(Ye(e,Fe(u[0]),Fe(u[1]),Fe(u[2]),h),je(t,e),e);case"hsla":return 4!==u.length?void Ye(e,0,0,0,1):(u[3]=Ge(u[3]),Ke(u,e),je(t,e),e);case"hsl":return 3!==u.length?void Ye(e,0,0,0,1):(Ke(u,e),je(t,e),e);default:return}}Ye(e,0,0,0,1)}}function Ke(t,e){var n=(parseFloat(t[0])%360+360)%360/360,i=Ge(t[1]),r=Ge(t[2]),o=r<=.5?r*(i+1):r+i-r*i,a=2*r-o;return Ye(e=e||[],Be(255*He(a,o,n+1/3)),Be(255*He(a,o,n)),Be(255*He(a,o,n-1/3)),1),4===t.length&&(e[3]=t[3]),e}function $e(t,e){var n=qe(t);if(n){for(var i=0;i<3;i++)n[i]=e<0?n[i]*(1-e)|0:(255-n[i])*e+n[i]|0,n[i]>255?n[i]=255:n[i]<0&&(n[i]=0);return an(n,4===n.length?"rgba":"rgb")}}function Je(t){var e=qe(t);if(e)return((1<<24)+(e[0]<<16)+(e[1]<<8)+ +e[2]).toString(16).slice(1)}function Qe(t,e,n){if(e&&e.length&&t>=0&&t<=1){n=n||[];var i=t*(e.length-1),r=Math.floor(i),o=Math.ceil(i),a=e[r],s=e[o],l=i-r;return n[0]=Be(We(a[0],s[0],l)),n[1]=Be(We(a[1],s[1],l)),n[2]=Be(We(a[2],s[2],l)),n[3]=Ve(We(a[3],s[3],l)),n}}var tn=Qe;function en(t,e,n){if(e&&e.length&&t>=0&&t<=1){var i=t*(e.length-1),r=Math.floor(i),o=Math.ceil(i),a=qe(e[r]),s=qe(e[o]),l=i-r,u=an([Be(We(a[0],s[0],l)),Be(We(a[1],s[1],l)),Be(We(a[2],s[2],l)),Ve(We(a[3],s[3],l))],"rgba");return n?{color:u,leftIndex:r,rightIndex:o,value:i}:u}}var nn=en;function rn(t,e,n,i){var r=qe(t);if(t)return r=function(t){if(t){var e,n,i=t[0]/255,r=t[1]/255,o=t[2]/255,a=Math.min(i,r,o),s=Math.max(i,r,o),l=s-a,u=(s+a)/2;if(0===l)e=0,n=0;else{n=u<.5?l/(s+a):l/(2-s-a);var h=((s-i)/6+l/2)/l,c=((s-r)/6+l/2)/l,p=((s-o)/6+l/2)/l;i===s?e=p-c:r===s?e=1/3+h-p:o===s&&(e=2/3+c-h),e<0&&(e+=1),e>1&&(e-=1)}var d=[360*e,n,u];return null!=t[3]&&d.push(t[3]),d}}(r),null!=e&&(r[0]=function(t){return(t=Math.round(t))<0?0:t>360?360:t}(e)),null!=n&&(r[1]=Ge(n)),null!=i&&(r[2]=Ge(i)),an(Ke(r),"rgba")}function on(t,e){var n=qe(t);if(n&&null!=e)return n[3]=Ve(e),an(n,"rgba")}function an(t,e){if(t&&t.length){var n=t[0]+","+t[1]+","+t[2];return"rgba"!==e&&"hsva"!==e&&"hsla"!==e||(n+=","+t[3]),e+"("+n+")"}}function sn(t,e){var n=qe(t);return n?(.299*n[0]+.587*n[1]+.114*n[2])*n[3]/255+(1-n[3])*e:0}var ln=Object.freeze({__proto__:null,parse:qe,lift:$e,toHex:Je,fastLerp:Qe,fastMapToColor:tn,lerp:en,mapToColor:nn,modifyHSL:rn,modifyAlpha:on,stringify:an,lum:sn,random:function(){return"rgb("+Math.round(255*Math.random())+","+Math.round(255*Math.random())+","+Math.round(255*Math.random())+")"}}),un=Array.prototype.slice;function hn(t,e,n){return(e-t)*n+t}function cn(t,e,n,i){for(var r=e.length,o=0;oa)i.length=a;else for(var s=o;s=2&&this.interpolable},t.prototype.getAdditiveTrack=function(){return this._additiveTrack},t.prototype.addKeyframe=function(t,e){t>=this.maxTime?this.maxTime=t:this._needsSort=!0;var n=this.keyframes,i=n.length;if(this.interpolable)if(k(e)){var r=function(t){return k(t&&t[0])?2:1}(e);if(i>0&&this.arrDim!==r)return void(this.interpolable=!1);if(1===r&&"number"!=typeof e[0]||2===r&&"number"!=typeof e[0][0])return void(this.interpolable=!1);if(i>0){var o=n[i-1];this._isAllValueEqual&&(1===r&&gn(e,o.value)||(this._isAllValueEqual=!1))}this.arrDim=r}else{if(this.arrDim>0)return void(this.interpolable=!1);if("string"==typeof e){var a=qe(e);a?(e=a,this.isValueColor=!0):this.interpolable=!1}else if("number"!=typeof e)return void(this.interpolable=!1);if(this._isAllValueEqual&&i>0){o=n[i-1];(this.isValueColor&&!gn(o.value,e)||o.value!==e)&&(this._isAllValueEqual=!1)}}var s={time:t,value:e,percent:0};return this.keyframes.push(s),s},t.prototype.prepare=function(t){var e=this.keyframes;this._needsSort&&e.sort((function(t,e){return t.time-e.time}));for(var n=this.arrDim,i=e.length,r=e[i-1],o=0;o0&&o!==i-1&&fn(e[o].value,r.value,n);if(t&&this.needsAnimate()&&t.needsAnimate()&&n===t.arrDim&&this.isValueColor===t.isValueColor&&!t._finished){this._additiveTrack=t;var a=e[0].value;for(o=0;o=0&&!(o[n].percent<=e);n--);n=Math.min(n,a-2)}else{for(n=this._lastFrame;ne);n++);n=Math.min(n-1,a-2)}var h=o[n+1],c=o[n];if(c&&h){this._lastFrame=n,this._lastFramePercent=e;var p=h.percent-c.percent;if(0!==p){var d=(e-c.percent)/p,f=i?this._additiveValue:u?wn:t[s];if((l>0||u)&&!f&&(f=this._additiveValue=[]),this.useSpline){var g=o[n][r],y=o[0===n?n:n-1][r],v=o[n>a-2?a-1:n+1][r],m=o[n>a-3?a-1:n+2][r];if(l>0)1===l?vn(f,y,g,v,m,d,d*d,d*d*d):function(t,e,n,i,r,o,a,s){for(var l=e.length,u=e[0].length,h=0;h0)1===l?cn(f,c[r],h[r],d):function(t,e,n,i){for(var r=e.length,o=r&&e[0].length,a=0;a.5?e:t}(c[r],h[r],d),i?this._additiveValue=_:t[s]=_}i&&this._addToTarget(t)}}}},t.prototype._addToTarget=function(t){var e=this.arrDim,n=this.propName,i=this._additiveValue;0===e?this.isValueColor?(qe(t[n],wn),pn(wn,wn,i,1),t[n]=_n(wn)):t[n]=t[n]+i:1===e?pn(t[n],t[n],i,1):2===e&&dn(t[n],t[n],i,1)},t}(),Mn=function(){function t(t,e,n){this._tracks={},this._trackKeys=[],this._delay=0,this._maxTime=0,this._paused=!1,this._started=0,this._clip=null,this._target=t,this._loop=e,e&&n?b("Can' use additive animation on looped animation."):this._additiveAnimators=n}return t.prototype.getTarget=function(){return this._target},t.prototype.changeTarget=function(t){this._target=t},t.prototype.when=function(t,e){return this.whenWithKeys(t,e,z(e))},t.prototype.whenWithKeys=function(t,e,n){for(var i=this._tracks,r=0;r0)){this._started=1;for(var n=this,i=[],r=0;r1){var a=o.pop();r.addKeyframe(a.time,t[i]),r.prepare(r.getAdditiveTrack())}}}},t}(),In=function(){function t(t,e){this.x=t||0,this.y=e||0}return t.prototype.copy=function(t){return this.x=t.x,this.y=t.y,this},t.prototype.clone=function(){return new t(this.x,this.y)},t.prototype.set=function(t,e){return this.x=t,this.y=e,this},t.prototype.equal=function(t){return t.x===this.x&&t.y===this.y},t.prototype.add=function(t){return this.x+=t.x,this.y+=t.y,this},t.prototype.scale=function(t){this.x*=t,this.y*=t},t.prototype.scaleAndAdd=function(t,e){this.x+=t.x*e,this.y+=t.y*e},t.prototype.sub=function(t){return this.x-=t.x,this.y-=t.y,this},t.prototype.dot=function(t){return this.x*t.x+this.y*t.y},t.prototype.len=function(){return Math.sqrt(this.x*this.x+this.y*this.y)},t.prototype.lenSquare=function(){return this.x*this.x+this.y*this.y},t.prototype.normalize=function(){var t=this.len();return this.x/=t,this.y/=t,this},t.prototype.distance=function(t){var e=this.x-t.x,n=this.y-t.y;return Math.sqrt(e*e+n*n)},t.prototype.distanceSquare=function(t){var e=this.x-t.x,n=this.y-t.y;return e*e+n*n},t.prototype.negate=function(){return this.x=-this.x,this.y=-this.y,this},t.prototype.transform=function(t){if(t){var e=this.x,n=this.y;return this.x=t[0]*e+t[2]*n+t[4],this.y=t[1]*e+t[3]*n+t[5],this}},t.prototype.toArray=function(t){return t[0]=this.x,t[1]=this.y,t},t.prototype.fromArray=function(t){this.x=t[0],this.y=t[1]},t.set=function(t,e,n){t.x=e,t.y=n},t.copy=function(t,e){t.x=e.x,t.y=e.y},t.len=function(t){return Math.sqrt(t.x*t.x+t.y*t.y)},t.lenSquare=function(t){return t.x*t.x+t.y*t.y},t.dot=function(t,e){return t.x*e.x+t.y*e.y},t.add=function(t,e,n){t.x=e.x+n.x,t.y=e.y+n.y},t.sub=function(t,e,n){t.x=e.x-n.x,t.y=e.y-n.y},t.scale=function(t,e,n){t.x=e.x*n,t.y=e.y*n},t.scaleAndAdd=function(t,e,n,i){t.x=e.x+n.x*i,t.y=e.y+n.y*i},t.lerp=function(t,e,n,i){var r=1-i;t.x=r*e.x+i*n.x,t.y=r*e.y+i*n.y},t}(),Tn=Math.min,Cn=Math.max,An=new In,Dn=new In,Ln=new In,kn=new In,Pn=new In,On=new In,Rn=function(){function t(t,e,n,i){n<0&&isFinite(n)&&(t+=n,n=-n),i<0&&isFinite(i)&&(e+=i,i=-i),this.x=t,this.y=e,this.width=n,this.height=i}return t.prototype.union=function(t){var e=Tn(t.x,this.x),n=Tn(t.y,this.y);isFinite(this.x)&&isFinite(this.width)?this.width=Cn(t.x+t.width,this.x+this.width)-e:this.width=t.width,isFinite(this.y)&&isFinite(this.height)?this.height=Cn(t.y+t.height,this.y+this.height)-n:this.height=t.height,this.x=e,this.y=n},t.prototype.applyTransform=function(e){t.applyTransform(this,this,e)},t.prototype.calculateTransform=function(t){var e=this,n=t.width/e.width,i=t.height/e.height,r=[1,0,0,1,0,0];return me(r,r,[-e.x,-e.y]),xe(r,r,[n,i]),me(r,r,[t.x,t.y]),r},t.prototype.intersect=function(e,n){if(!e)return!1;e instanceof t||(e=t.create(e));var i=this,r=i.x,o=i.x+i.width,a=i.y,s=i.y+i.height,l=e.x,u=e.x+e.width,h=e.y,c=e.y+e.height,p=!(of&&(f=_,gf&&(f=x,v=n.x&&t<=n.x+n.width&&e>=n.y&&e<=n.y+n.height},t.prototype.clone=function(){return new t(this.x,this.y,this.width,this.height)},t.prototype.copy=function(e){t.copy(this,e)},t.prototype.plain=function(){return{x:this.x,y:this.y,width:this.width,height:this.height}},t.prototype.isFinite=function(){return isFinite(this.x)&&isFinite(this.y)&&isFinite(this.width)&&isFinite(this.height)},t.prototype.isZero=function(){return 0===this.width||0===this.height},t.create=function(e){return new t(e.x,e.y,e.width,e.height)},t.copy=function(t,e){t.x=e.x,t.y=e.y,t.width=e.width,t.height=e.height},t.applyTransform=function(e,n,i){if(i){if(i[1]<1e-5&&i[1]>-1e-5&&i[2]<1e-5&&i[2]>-1e-5){var r=i[0],o=i[3],a=i[4],s=i[5];return e.x=n.x*r+a,e.y=n.y*o+s,e.width=n.width*r,e.height=n.height*o,e.width<0&&(e.x+=e.width,e.width=-e.width),void(e.height<0&&(e.y+=e.height,e.height=-e.height))}An.x=Ln.x=n.x,An.y=kn.y=n.y,Dn.x=kn.x=n.x+n.width,Dn.y=Ln.y=n.y+n.height,An.transform(i),kn.transform(i),Dn.transform(i),Ln.transform(i),e.x=Tn(An.x,Dn.x,Ln.x,kn.x),e.y=Tn(An.y,Dn.y,Ln.y,kn.y);var l=Cn(An.x,Dn.x,Ln.x,kn.x),u=Cn(An.y,Dn.y,Ln.y,kn.y);e.width=l-e.x,e.height=u-e.y}else e!==n&&t.copy(e,n)},t}(),Nn={},En="12px sans-serif";var zn={measureText:function(t,e){return xn||(xn=C().getContext("2d")),bn!==e&&(bn=xn.font=e||En),xn.measureText(t)}};function Bn(t,e){var n=Nn[e=e||En];n||(n=Nn[e]=new Ee(500));var i=n.get(t);return null==i&&(i=zn.measureText(t,e).width,n.put(t,i)),i}function Vn(t,e,n,i){var r=Bn(t,e),o=Wn(e),a=Gn(0,r,n),s=Hn(0,o,i);return new Rn(a,s,r,o)}function Fn(t,e,n,i){var r=((t||"")+"").split("\n");if(1===r.length)return Vn(r[0],e,n,i);for(var o=new Rn(0,0,0,0),a=0;a=0?parseFloat(t)/100*e:parseFloat(t):t}function Xn(t,e,n){var i=e.position||"inside",r=null!=e.distance?e.distance:5,o=n.height,a=n.width,s=o/2,l=n.x,u=n.y,h="left",c="top";if(i instanceof Array)l+=Yn(i[0],n.width),u+=Yn(i[1],n.height),h=null,c=null;else switch(i){case"left":l-=r,u+=s,h="right",c="middle";break;case"right":l+=r+a,u+=s,c="middle";break;case"top":l+=a/2,u-=r,h="center",c="bottom";break;case"bottom":l+=a/2,u+=o+r,h="center";break;case"inside":l+=a/2,u+=s,h="center",c="middle";break;case"insideLeft":l+=r,u+=s,c="middle";break;case"insideRight":l+=a-r,u+=s,h="right",c="middle";break;case"insideTop":l+=a/2,u+=r,h="center";break;case"insideBottom":l+=a/2,u+=o-r,h="center",c="bottom";break;case"insideTopLeft":l+=r,u+=r;break;case"insideTopRight":l+=a-r,u+=r,h="right";break;case"insideBottomLeft":l+=r,u+=o-r,c="bottom";break;case"insideBottomRight":l+=a-r,u+=o-r,h="right",c="bottom"}return(t=t||{}).x=l,t.y=u,t.align=h,t.verticalAlign=c,t}var Un=1;"undefined"!=typeof window&&(Un=Math.max(window.devicePixelRatio||window.screen&&window.screen.deviceXDPI/window.screen.logicalXDPI||1,1));var Zn=Un,jn="#333",qn="#ccc",Kn="__zr_normal__",$n=["x","y","scaleX","scaleY","originX","originY","rotation","ignore"],Jn={x:!0,y:!0,scaleX:!0,scaleY:!0,originX:!0,originY:!0,rotation:!0,ignore:!1},Qn={},ti=new Rn(0,0,0,0),ei=function(){function t(t){this.id=x(),this.animators=[],this.currentStates=[],this.states={},this._init(t)}return t.prototype._init=function(t){this.attr(t)},t.prototype.drift=function(t,e,n){switch(this.draggable){case"horizontal":e=0;break;case"vertical":t=0}var i=this.transform;i||(i=this.transform=[1,0,0,1,0,0]),i[4]+=t,i[5]+=e,this.decomposeTransform(),this.markRedraw()},t.prototype.beforeUpdate=function(){},t.prototype.afterUpdate=function(){},t.prototype.update=function(){this.updateTransform(),this.__dirty&&this.updateInnerText()},t.prototype.updateInnerText=function(t){var e=this._textContent;if(e&&(!e.ignore||t)){this.textConfig||(this.textConfig={});var n=this.textConfig,i=n.local,r=e.attachedTransform,o=void 0,a=void 0,s=!1;r.parent=i?this:null;var l=!1;if(r.x=e.x,r.y=e.y,r.originX=e.originX,r.originY=e.originY,r.rotation=e.rotation,r.scaleX=e.scaleX,r.scaleY=e.scaleY,null!=n.position){var u=ti;n.layoutRect?u.copy(n.layoutRect):u.copy(this.getBoundingRect()),i||u.applyTransform(this.transform),this.calculateTextPosition?this.calculateTextPosition(Qn,n,u):Xn(Qn,n,u),r.x=Qn.x,r.y=Qn.y,o=Qn.align,a=Qn.verticalAlign;var h=n.origin;if(h&&null!=n.rotation){var c=void 0,p=void 0;"center"===h?(c=.5*u.width,p=.5*u.height):(c=Yn(h[0],u.width),p=Yn(h[1],u.height)),l=!0,r.originX=-r.x+c+(i?0:u.x),r.originY=-r.y+p+(i?0:u.y)}}null!=n.rotation&&(r.rotation=n.rotation);var d=n.offset;d&&(r.x+=d[0],r.y+=d[1],l||(r.originX=-d[0],r.originY=-d[1]));var f=null==n.inside?"string"==typeof n.position&&n.position.indexOf("inside")>=0:n.inside,g=this._innerTextDefaultStyle||(this._innerTextDefaultStyle={}),y=void 0,v=void 0,m=void 0;f&&this.canBeInsideText()?(y=n.insideFill,v=n.insideStroke,null!=y&&"auto"!==y||(y=this.getInsideTextFill()),null!=v&&"auto"!==v||(v=this.getInsideTextStroke(y),m=!0)):(y=n.outsideFill,v=n.outsideStroke,null!=y&&"auto"!==y||(y=this.getOutsideFill()),null!=v&&"auto"!==v||(v=this.getOutsideStroke(y),m=!0)),(y=y||"#000")===g.fill&&v===g.stroke&&m===g.autoStroke&&o===g.align&&a===g.verticalAlign||(s=!0,g.fill=y,g.stroke=v,g.autoStroke=m,g.align=o,g.verticalAlign=a,e.setDefaultTextStyle(g)),s&&e.dirtyStyle(),e.markRedraw()}},t.prototype.canBeInsideText=function(){return!0},t.prototype.getInsideTextFill=function(){return"#fff"},t.prototype.getInsideTextStroke=function(t){return"#000"},t.prototype.getOutsideFill=function(){return this.__zr&&this.__zr.isDarkMode()?qn:jn},t.prototype.getOutsideStroke=function(t){var e=this.__zr&&this.__zr.getBackgroundColor(),n="string"==typeof e&&qe(e);n||(n=[255,255,255,1]);for(var i=n[3],r=this.__zr.isDarkMode(),o=0;o<3;o++)n[o]=n[o]*i+(r?0:255)*(1-i);return n[3]=1,an(n,"rgba")},t.prototype.traverse=function(t,e){},t.prototype.attrKV=function(t,e){"textConfig"===t?this.setTextConfig(e):"textContent"===t?this.setTextContent(e):"clipPath"===t?this.setClipPath(e):"extra"===t?(this.extra=this.extra||{},I(this.extra,e)):this[t]=e},t.prototype.hide=function(){this.ignore=!0,this.markRedraw()},t.prototype.show=function(){this.ignore=!1,this.markRedraw()},t.prototype.attr=function(t,e){if("string"==typeof t)this.attrKV(t,e);else if(X(t))for(var n=z(t),i=0;i0},t.prototype.getState=function(t){return this.states[t]},t.prototype.ensureState=function(t){var e=this.states;return e[t]||(e[t]={}),e[t]},t.prototype.clearStates=function(t){this.useState(Kn,!1,t)},t.prototype.useState=function(e,n,i){var r=e===Kn;if(this.hasState()||!r){var o=this.currentStates,a=this.stateTransition;if(!(A(o,e)>=0)||!n&&1!==o.length){var s;if(this.stateProxy&&!r&&(s=this.stateProxy(e)),s||(s=this.states&&this.states[e]),s||r){r||this.saveCurrentToNormalState(s);var l=!(!s||!s.hoverLayer);return l&&this._toggleHoverLayerFlag(!0),this._applyStateObj(e,s,this._normalState,n,!i&&!this.__inHover&&a&&a.duration>0,a),this._textContent&&this._textContent.useState(e,n),this._textGuide&&this._textGuide.useState(e,n),r?(this.currentStates=[],this._normalState={}):n?this.currentStates.push(e):this.currentStates=[e],this._updateAnimationTargets(),this.markRedraw(),!l&&this.__inHover&&(this._toggleHoverLayerFlag(!1),this.__dirty&=~t.REDARAW_BIT),s}b("State "+e+" not exists.")}}},t.prototype.useStates=function(e,n){if(e.length){var i=[],r=this.currentStates,o=e.length,a=o===r.length;if(a)for(var s=0;s0,p),this._textContent&&this._textContent.useStates(e),this._textGuide&&this._textGuide.useStates(e),this._updateAnimationTargets(),this.currentStates=e.slice(),this.markRedraw(),!h&&this.__inHover&&(this._toggleHoverLayerFlag(!1),this.__dirty&=~t.REDARAW_BIT)}else this.clearStates()},t.prototype._updateAnimationTargets=function(){for(var t=0;t=0){var n=this.currentStates.slice();n.splice(e,1),this.useStates(n)}},t.prototype.replaceState=function(t,e,n){var i=this.currentStates.slice(),r=A(i,t),o=A(i,e)>=0;r>=0?o?i.splice(r,1):i[r]=e:n&&!o&&i.push(e),this.useStates(i)},t.prototype.toggleState=function(t,e){e?this.useState(t,!0):this.removeState(t)},t.prototype._mergeStates=function(t){for(var e,n={},i=0;i=0&&e.splice(n,1)})),this.animators.push(t),n&&n.animation.addAnimator(t),n&&n.wakeUp()},t.prototype.updateDuringAnimation=function(t){this.markRedraw()},t.prototype.stopAnimation=function(t,e){for(var n=this.animators,i=n.length,r=[],o=0;o8)&&(r("position","_legacyPos","x","y"),r("scale","_legacyScale","scaleX","scaleY"),r("origin","_legacyOrigin","originX","originY"))}(),t}();function ni(t,e,n,i,r){var o=[];oi(t,"",t,e,n=n||{},i,o,r);var a=o.length,s=!1,l=n.done,u=n.aborted,h=function(){s=!0,--a<=0&&(s?l&&l():u&&u())},c=function(){--a<=0&&(s?l&&l():u&&u())};a||l&&l(),o.length>0&&n.during&&o[0].during((function(t,e){n.during(e)}));for(var p=0;p0||r.force&&!a.length){for(var m=t.animators,_=[],x=0;x=0;)r++;return r-e}function si(t,e,n,i,r){for(i===e&&i++;i>>1])<0?l=o:s=o+1;var u=i-s;switch(u){case 3:t[s+3]=t[s+2];case 2:t[s+2]=t[s+1];case 1:t[s+1]=t[s];break;default:for(;u>0;)t[s+u]=t[s+u-1],u--}t[s]=a}}function li(t,e,n,i,r,o){var a=0,s=0,l=1;if(o(t,e[n+r])>0){for(s=i-r;l0;)a=l,(l=1+(l<<1))<=0&&(l=s);l>s&&(l=s),a+=r,l+=r}else{for(s=r+1;ls&&(l=s);var u=a;a=r-l,l=r-u}for(a++;a>>1);o(t,e[n+h])>0?a=h+1:l=h}return l}function ui(t,e,n,i,r,o){var a=0,s=0,l=1;if(o(t,e[n+r])<0){for(s=r+1;ls&&(l=s);var u=a;a=r-l,l=r-u}else{for(s=i-r;l=0;)a=l,(l=1+(l<<1))<=0&&(l=s);l>s&&(l=s),a+=r,l+=r}for(a++;a>>1);o(t,e[n+h])<0?l=h:a=h+1}return l}function hi(t,e){var n,i,r=7,o=0;t.length;var a=[];function s(s){var l=n[s],u=i[s],h=n[s+1],c=i[s+1];i[s]=u+c,s===o-3&&(n[s+1]=n[s+2],i[s+1]=i[s+2]),o--;var p=ui(t[h],t,l,u,0,e);l+=p,0!==(u-=p)&&0!==(c=li(t[l+u-1],t,h,c,c-1,e))&&(u<=c?function(n,i,o,s){var l=0;for(l=0;l=7||d>=7);if(f)break;g<0&&(g=0),g+=2}if((r=g)<1&&(r=1),1===i){for(l=0;l=0;l--)t[d+l]=t[p+l];return void(t[c]=a[h])}var f=r;for(;;){var g=0,y=0,v=!1;do{if(e(a[h],t[u])<0){if(t[c--]=t[u--],g++,y=0,0==--i){v=!0;break}}else if(t[c--]=a[h--],y++,g=0,1==--s){v=!0;break}}while((g|y)=0;l--)t[d+l]=t[p+l];if(0===i){v=!0;break}}if(t[c--]=a[h--],1==--s){v=!0;break}if(0!==(y=s-li(t[u],a,0,s,s-1,e))){for(s-=y,d=(c-=y)+1,p=(h-=y)+1,l=0;l=7||y>=7);if(v)break;f<0&&(f=0),f+=2}(r=f)<1&&(r=1);if(1===s){for(d=(c-=i)+1,p=(u-=i)+1,l=i-1;l>=0;l--)t[d+l]=t[p+l];t[c]=a[h]}else{if(0===s)throw new Error;for(p=c-(s-1),l=0;l1;){var t=o-2;if(t>=1&&i[t-1]<=i[t]+i[t+1]||t>=2&&i[t-2]<=i[t]+i[t-1])i[t-1]i[t+1])break;s(t)}},forceMergeRuns:function(){for(;o>1;){var t=o-2;t>0&&i[t-1]=32;)e|=1&t,t>>=1;return t+e}(r);do{if((o=ai(t,n,i,e))s&&(l=s),si(t,n,n+l,n+o,e),o=l}a.pushRun(n,o),a.mergeRuns(),r-=o,n+=o}while(0!==r);a.forceMergeRuns()}}}var pi=!1;function di(){pi||(pi=!0,console.warn("z / z2 / zlevel of displayable is invalid, which may cause unexpected errors"))}function fi(t,e){return t.zlevel===e.zlevel?t.z===e.z?t.z2-e.z2:t.z-e.z:t.zlevel-e.zlevel}var gi,yi,vi=function(){function t(){this._roots=[],this._displayList=[],this._displayListLen=0,this.displayableSortFunc=fi}return t.prototype.traverse=function(t,e){for(var n=0;n0&&(u.__clipPaths=[]),isNaN(u.z)&&(di(),u.z=0),isNaN(u.z2)&&(di(),u.z2=0),isNaN(u.zlevel)&&(di(),u.zlevel=0),this._displayList[this._displayListLen++]=u}var h=t.getDecalElement&&t.getDecalElement();h&&this._updateAndAddDisplayable(h,e,n);var c=t.getTextGuideLine();c&&this._updateAndAddDisplayable(c,e,n);var p=t.getTextContent();p&&this._updateAndAddDisplayable(p,e,n)}},t.prototype.addRoot=function(t){t.__zr&&t.__zr.storage===this||this._roots.push(t)},t.prototype.delRoot=function(t){if(t instanceof Array)for(var e=0,n=t.length;e=0&&this._roots.splice(i,1)}},t.prototype.delAllRoots=function(){this._roots=[],this._displayList=[],this._displayListLen=0},t.prototype.getRoots=function(){return this._roots},t.prototype.dispose=function(){this._displayList=null,this._roots=null},t}(),mi="undefined"!=typeof window&&(window.requestAnimationFrame&&window.requestAnimationFrame.bind(window)||window.msRequestAnimationFrame&&window.msRequestAnimationFrame.bind(window)||window.mozRequestAnimationFrame||window.webkitRequestAnimationFrame)||function(t){return setTimeout(t,16)},_i=function(t){function e(e){var n=t.call(this)||this;return n._running=!1,n._time=0,n._pausedTime=0,n._pauseStart=0,n._paused=!1,e=e||{},n.stage=e.stage||{},n.onframe=e.onframe||function(){},n}return n(e,t),e.prototype.addClip=function(t){t.animation&&this.removeClip(t),this._clipsHead?(this._clipsTail.next=t,t.prev=this._clipsTail,t.next=null,this._clipsTail=t):this._clipsHead=this._clipsTail=t,t.animation=this},e.prototype.addAnimator=function(t){t.animation=this;var e=t.getClip();e&&this.addClip(e)},e.prototype.removeClip=function(t){if(t.animation){var e=t.prev,n=t.next;e?e.next=n:this._clipsHead=n,n?n.prev=e:this._clipsTail=e,t.next=t.prev=t.animation=null}},e.prototype.removeAnimator=function(t){var e=t.getClip();e&&this.removeClip(e),t.animation=null},e.prototype.update=function(t){for(var e=(new Date).getTime()-this._pausedTime,n=e-this._time,i=this._clipsHead;i;){var r=i.next;i.step(e,n)?(i.ondestroy&&i.ondestroy(),this.removeClip(i),i=r):i=r}this._time=e,t||(this.onframe(n),this.trigger("frame",n),this.stage.update&&this.stage.update())},e.prototype._startLoop=function(){var t=this;this._running=!0,mi((function e(){t._running&&(mi(e),!t._paused&&t.update())}))},e.prototype.start=function(){this._running||(this._time=(new Date).getTime(),this._pausedTime=0,this._startLoop())},e.prototype.stop=function(){this._running=!1},e.prototype.pause=function(){this._paused||(this._pauseStart=(new Date).getTime(),this._paused=!0)},e.prototype.resume=function(){this._paused&&(this._pausedTime+=(new Date).getTime()-this._pauseStart,this._paused=!1)},e.prototype.clear=function(){for(var t=this._clipsHead;t;){var e=t.next;t.prev=t.next=t.animation=null,t=e}this._clipsHead=this._clipsTail=null},e.prototype.isFinished=function(){return null==this._clipsHead},e.prototype.animate=function(t,e){e=e||{},this.start();var n=new Mn(t,e.loop);return this.addAnimator(n),n},e}(Ft),xi=a.domSupported,bi=(yi={pointerdown:1,pointerup:1,pointermove:1,pointerout:1},{mouse:gi=["click","dblclick","mousewheel","wheel","mouseout","mouseup","mousedown","mousemove","contextmenu"],touch:["touchstart","touchend","touchmove"],pointer:O(gi,(function(t){var e=t.replace("mouse","pointer");return yi.hasOwnProperty(e)?e:t}))}),wi=["mousemove","mouseup"],Si=["pointermove","pointerup"],Mi=!1;function Ii(t){var e=t.pointerType;return"pen"===e||"touch"===e}function Ti(t){t&&(t.zrByTouch=!0)}function Ci(t,e){for(var n=e,i=!1;n&&9!==n.nodeType&&!(i=n.domBelongToZr||n!==e&&n===t.painterRoot);)n=n.parentNode;return i}var Ai=function(t,e){this.stopPropagation=ft,this.stopImmediatePropagation=ft,this.preventDefault=ft,this.type=e.type,this.target=this.currentTarget=t.dom,this.pointerType=e.pointerType,this.clientX=e.clientX,this.clientY=e.clientY},Di={mousedown:function(t){t=Qt(this.dom,t),this.__mayPointerCapture=[t.zrX,t.zrY],this.trigger("mousedown",t)},mousemove:function(t){t=Qt(this.dom,t);var e=this.__mayPointerCapture;!e||t.zrX===e[0]&&t.zrY===e[1]||this.__togglePointerCapture(!0),this.trigger("mousemove",t)},mouseup:function(t){t=Qt(this.dom,t),this.__togglePointerCapture(!1),this.trigger("mouseup",t)},mouseout:function(t){Ci(this,(t=Qt(this.dom,t)).toElement||t.relatedTarget)||(this.__pointerCapturing&&(t.zrEventControl="no_globalout"),this.trigger("mouseout",t))},wheel:function(t){Mi=!0,t=Qt(this.dom,t),this.trigger("mousewheel",t)},mousewheel:function(t){Mi||(t=Qt(this.dom,t),this.trigger("mousewheel",t))},touchstart:function(t){Ti(t=Qt(this.dom,t)),this.__lastTouchMoment=new Date,this.handler.processGesture(t,"start"),Di.mousemove.call(this,t),Di.mousedown.call(this,t)},touchmove:function(t){Ti(t=Qt(this.dom,t)),this.handler.processGesture(t,"change"),Di.mousemove.call(this,t)},touchend:function(t){Ti(t=Qt(this.dom,t)),this.handler.processGesture(t,"end"),Di.mouseup.call(this,t),+new Date-+this.__lastTouchMoment<300&&Di.click.call(this,t)},pointerdown:function(t){Di.mousedown.call(this,t)},pointermove:function(t){Ii(t)||Di.mousemove.call(this,t)},pointerup:function(t){Di.mouseup.call(this,t)},pointerout:function(t){Ii(t)||Di.mouseout.call(this,t)}};P(["click","dblclick","contextmenu"],(function(t){Di[t]=function(e){e=Qt(this.dom,e),this.trigger(t,e)}}));var Li={pointermove:function(t){Ii(t)||Li.mousemove.call(this,t)},pointerup:function(t){Li.mouseup.call(this,t)},mousemove:function(t){this.trigger("mousemove",t)},mouseup:function(t){var e=this.__pointerCapturing;this.__togglePointerCapture(!1),this.trigger("mouseup",t),e&&(t.zrEventControl="only_globalout",this.trigger("mouseout",t))}};function ki(t,e){var n=e.domHandlers;a.pointerEventsSupported?P(bi.pointer,(function(i){Oi(e,i,(function(e){n[i].call(t,e)}))})):(a.touchEventsSupported&&P(bi.touch,(function(i){Oi(e,i,(function(r){n[i].call(t,r),function(t){t.touching=!0,null!=t.touchTimer&&(clearTimeout(t.touchTimer),t.touchTimer=null),t.touchTimer=setTimeout((function(){t.touching=!1,t.touchTimer=null}),700)}(e)}))})),P(bi.mouse,(function(i){Oi(e,i,(function(r){r=Jt(r),e.touching||n[i].call(t,r)}))})))}function Pi(t,e){function n(n){Oi(e,n,(function(i){i=Jt(i),Ci(t,i.target)||(i=function(t,e){return Qt(t.dom,new Ai(t,e),!0)}(t,i),e.domHandlers[n].call(t,i))}),{capture:!0})}a.pointerEventsSupported?P(Si,n):a.touchEventsSupported||P(wi,n)}function Oi(t,e,n,i){t.mounted[e]=n,t.listenerOpts[e]=i,te(t.domTarget,e,n,i)}function Ri(t){var e,n,i,r,o=t.mounted;for(var a in o)o.hasOwnProperty(a)&&(e=t.domTarget,n=a,i=o[a],r=t.listenerOpts[a],Zt?e.removeEventListener(n,i,r):e.detachEvent("on"+n,i));t.mounted={}}var Ni=function(t,e){this.mounted={},this.listenerOpts={},this.touching=!1,this.domTarget=t,this.domHandlers=e},Ei=function(t){function e(e,n){var i=t.call(this)||this;return i.__pointerCapturing=!1,i.dom=e,i.painterRoot=n,i._localHandlerScope=new Ni(e,Di),xi&&(i._globalHandlerScope=new Ni(document,Li)),ki(i,i._localHandlerScope),i}return n(e,t),e.prototype.dispose=function(){Ri(this._localHandlerScope),xi&&Ri(this._globalHandlerScope)},e.prototype.setCursor=function(t){this.dom.style&&(this.dom.style.cursor=t||"default")},e.prototype.__togglePointerCapture=function(t){if(this.__mayPointerCapture=null,xi&&+this.__pointerCapturing^+t){this.__pointerCapturing=t;var e=this._globalHandlerScope;t?Pi(this,e):Ri(e)}},e}(Ft),zi=function(t){function e(e){var n=t.call(this)||this;return n.isGroup=!0,n._children=[],n.attr(e),n}return n(e,t),e.prototype.childrenRef=function(){return this._children},e.prototype.children=function(){return this._children.slice()},e.prototype.childAt=function(t){return this._children[t]},e.prototype.childOfName=function(t){for(var e=this._children,n=0;n=0&&(n.splice(i,0,t),this._doAdd(t))}return this},e.prototype.replaceAt=function(t,e){var n=this._children,i=n[e];if(t&&t!==this&&t.parent!==this&&t!==i){n[e]=t,i.parent=null;var r=this.__zr;r&&i.removeSelfFromZr(r),this._doAdd(t)}return this},e.prototype._doAdd=function(t){t.parent&&t.parent.remove(t),t.parent=this;var e=this.__zr;e&&e!==t.__zr&&t.addSelfToZr(e),e&&e.refresh()},e.prototype.remove=function(t){var e=this.__zr,n=this._children,i=A(n,t);return i<0||(n.splice(i,1),t.parent=null,e&&t.removeSelfFromZr(e),e&&e.refresh()),this},e.prototype.removeAll=function(){for(var t=this._children,e=this.__zr,n=0;n0&&(this._stillFrameAccum++,this._stillFrameAccum>this._sleepAfterStill&&this.animation.stop())},t.prototype.setSleepAfterStill=function(t){this._sleepAfterStill=t},t.prototype.wakeUp=function(){this.animation.start(),this._stillFrameAccum=0},t.prototype.addHover=function(t){},t.prototype.removeHover=function(t){},t.prototype.clearHover=function(){},t.prototype.refreshHover=function(){this._needsRefreshHover=!0},t.prototype.refreshHoverImmediately=function(){this._needsRefreshHover=!1,this.painter.refreshHover&&"canvas"===this.painter.getType()&&this.painter.refreshHover()},t.prototype.resize=function(t){t=t||{},this.painter.resize(t.width,t.height),this.handler.resize()},t.prototype.clearAnimation=function(){this.animation.clear()},t.prototype.getWidth=function(){return this.painter.getWidth()},t.prototype.getHeight=function(){return this.painter.getHeight()},t.prototype.pathToImage=function(t,e){if(this.painter.pathToImage)return this.painter.pathToImage(t,e)},t.prototype.setCursorStyle=function(t){this.handler.setCursorStyle(t)},t.prototype.findHover=function(t,e){return this.handler.findHover(t,e)},t.prototype.on=function(t,e,n){return this.handler.on(t,e,n),this},t.prototype.off=function(t,e){this.handler.off(t,e)},t.prototype.trigger=function(t,e){this.handler.trigger(t,e)},t.prototype.clear=function(){for(var t=this.storage.getRoots(),e=0;e0){if(t<=e[0])return n[0];if(t>=e[1])return n[1]}else{if(t>=e[0])return n[0];if(t<=e[1])return n[1]}else{if(t===e[0])return n[0];if(t===e[1])return n[1]}return(t-e[0])/r*o+n[0]}function Zi(t,e){switch(t){case"center":case"middle":t="50%";break;case"left":case"top":t="0%";break;case"right":case"bottom":t="100%"}return"string"==typeof t?(n=t,n.replace(/^\s+|\s+$/g,"")).match(/%$/)?parseFloat(t)/100*e:parseFloat(t):null==t?NaN:+t;var n}function ji(t,e,n){return null==e&&(e=10),e=Math.min(Math.max(0,e),20),t=(+t).toFixed(e),n?t:+t}function qi(t){return t.sort((function(t,e){return t-e})),t}function Ki(t){if(t=+t,isNaN(t))return 0;for(var e=1,n=0;Math.round(t*e)/e!==t;)e*=10,n++;return n}function $i(t){var e=t.toString(),n=e.indexOf("e");if(n>0){var i=+e.slice(n+1);return i<0?-i:0}var r=e.indexOf(".");return r<0?0:e.length-1-r}function Ji(t,e){var n=Math.log,i=Math.LN10,r=Math.floor(n(t[1]-t[0])/i),o=Math.round(n(Math.abs(e[1]-e[0]))/i),a=Math.min(Math.max(-r+o,0),20);return isFinite(a)?a:20}function Qi(t,e,n){if(!t[e])return 0;var i=R(t,(function(t,e){return t+(isNaN(e)?0:e)}),0);if(0===i)return 0;for(var r=Math.pow(10,n),o=O(t,(function(t){return(isNaN(t)?0:t)/i*r*100})),a=100*r,s=O(o,(function(t){return Math.floor(t)})),l=R(s,(function(t,e){return t+e}),0),u=O(o,(function(t,e){return t-s[e]}));lh&&(h=u[p],c=p);++s[c],u[c]=0,++l}return s[e]/r}var tr=9007199254740991;function er(t){var e=2*Math.PI;return(t%e+e)%e}function nr(t){return t>-1e-4&&t=10&&e++,e}function sr(t,e){var n=ar(t),i=Math.pow(10,n),r=t/i;return t=(e?r<1.5?1:r<2.5?2:r<4?3:r<7?5:10:r<1?1:r<2?2:r<3?3:r<5?5:10)*i,n>=-20?+t.toFixed(n<0?-n:0):t}function lr(t,e){var n=(t.length-1)*e+1,i=Math.floor(n),r=+t[i-1],o=n-i;return o?r+o*(t[i]-r):r}function ur(t){t.sort((function(t,e){return s(t,e,0)?-1:1}));for(var e=-1/0,n=1,i=0;i=0||r&&A(r,s)<0)){var l=n.getShallow(s,e);null!=l&&(o[t[a][0]]=l)}}return o}}var Kr=qr([["fill","color"],["shadowBlur"],["shadowOffsetX"],["shadowOffsetY"],["opacity"],["shadowColor"]]),$r=function(){function t(){}return t.prototype.getAreaStyle=function(t,e){return Kr(this,t,e)},t}(),Jr=new Ee(50);function Qr(t){if("string"==typeof t){var e=Jr.get(t);return e&&e.image}return t}function to(t,e,n,i,r){if(t){if("string"==typeof t){if(e&&e.__zrImageSrc===t||!n)return e;var o=Jr.get(t),a={hostEl:n,cb:i,cbPayload:r};return o?!no(e=o.image)&&o.pending.push(a):((e=new Image).onload=e.onerror=eo,Jr.put(t,e.__cachedImgObj={image:e,pending:[a]}),e.src=e.__zrImageSrc=t),e}return t}return e}function eo(){var t=this.__cachedImgObj;this.onload=this.onerror=this.__cachedImgObj=null;for(var e=0;e=a;l++)s-=a;var u=Bn(n,e);return u>s&&(n="",u=0),s=t-u,r.ellipsis=n,r.ellipsisWidth=u,r.contentWidth=s,r.containerWidth=t,r}function ao(t,e){var n=e.containerWidth,i=e.font,r=e.contentWidth;if(!n)return"";var o=Bn(t,i);if(o<=n)return t;for(var a=0;;a++){if(o<=r||a>=e.maxIterations){t+=e.ellipsis;break}var s=0===a?so(t,r,e.ascCharWidth,e.cnCharWidth):o>0?Math.floor(t.length*r/o):0;o=Bn(t=t.substr(0,s),i)}return""===t&&(t=e.placeholder),t}function so(t,e,n,i){for(var r=0,o=0,a=t.length;o=0?parseFloat(t)/100*e:parseFloat(t);return t}(l.width,i.width)+d;u.length>0&&f+i.accumWidth>i.width&&(o=e.split("\n"),c=!0),i.accumWidth=f}else{var g=go(e,h,i.width,i.breakAll,i.accumWidth);i.accumWidth=g.accumWidth+d,a=g.linesWidths,o=g.lines}}else o=e.split("\n");for(var y=0;y=33&&e<=255}(t)||!!po[t]}function go(t,e,n,i,r){for(var o=[],a=[],s="",l="",u=0,h=0,c=0;cn:r+h+d>n)?h?(s||l)&&(f?(s||(s=l,l="",h=u=0),o.push(s),a.push(h-u),l+=p,s="",h=u+=d):(l&&(s+=l,h+=u,l="",u=0),o.push(s),a.push(h),s=p,h=d)):f?(o.push(l),a.push(u),l=p,u=d):(o.push(p),a.push(d)):(h+=d,f?(l+=p,u+=d):(l&&(s+=l,l="",u=0),s+=p))}else l&&(s+=l,h+=u),o.push(s),a.push(h),s="",l="",u=0,h=0}return o.length||s||(s=t,l="",u=0),l&&(s+=l),s&&(o.push(s),a.push(h)),1===o.length&&(h+=r),{accumWidth:h,lines:o,linesWidths:a}}var yo="__zr_style_"+Math.round(10*Math.random()),vo={shadowBlur:0,shadowOffsetX:0,shadowOffsetY:0,shadowColor:"#000",opacity:1,blend:"source-over"},mo={style:{shadowBlur:!0,shadowOffsetX:!0,shadowOffsetY:!0,shadowColor:!0,opacity:!0}};vo[yo]=!0;var _o=["z","z2","invisible"],xo=function(t){function e(e){return t.call(this,e)||this}var i;return n(e,t),e.prototype._init=function(e){for(var n=z(e),i=0;i-1e-8&&tIo||t<-1e-8}function Ro(t,e,n,i,r){var o=1-r;return o*o*(o*t+3*r*e)+r*r*(r*i+3*o*n)}function No(t,e,n,i,r){var o=1-r;return 3*(((e-t)*o+2*(n-e)*r)*o+(i-n)*r*r)}function Eo(t,e,n,i,r,o){var a=i+3*(e-n)-t,s=3*(n-2*e+t),l=3*(e-t),u=t-r,h=s*s-3*a*l,c=s*l-9*a*u,p=l*l-3*s*u,d=0;if(Po(h)&&Po(c)){if(Po(s))o[0]=0;else(M=-l/s)>=0&&M<=1&&(o[d++]=M)}else{var f=c*c-4*h*p;if(Po(f)){var g=c/h,y=-g/2;(M=-s/a+g)>=0&&M<=1&&(o[d++]=M),y>=0&&y<=1&&(o[d++]=y)}else if(f>0){var v=Mo(f),m=h*s+1.5*a*(-c+v),_=h*s+1.5*a*(-c-v);(M=(-s-((m=m<0?-So(-m,Ao):So(m,Ao))+(_=_<0?-So(-_,Ao):So(_,Ao))))/(3*a))>=0&&M<=1&&(o[d++]=M)}else{var x=(2*h*s-3*a*c)/(2*Mo(h*h*h)),b=Math.acos(x)/3,w=Mo(h),S=Math.cos(b),M=(-s-2*w*S)/(3*a),I=(y=(-s+w*(S+Co*Math.sin(b)))/(3*a),(-s+w*(S-Co*Math.sin(b)))/(3*a));M>=0&&M<=1&&(o[d++]=M),y>=0&&y<=1&&(o[d++]=y),I>=0&&I<=1&&(o[d++]=I)}}return d}function zo(t,e,n,i,r){var o=6*n-12*e+6*t,a=9*e+3*i-3*t-9*n,s=3*e-3*t,l=0;if(Po(a)){if(Oo(o))(h=-s/o)>=0&&h<=1&&(r[l++]=h)}else{var u=o*o-4*a*s;if(Po(u))r[0]=-o/(2*a);else if(u>0){var h,c=Mo(u),p=(-o-c)/(2*a);(h=(-o+c)/(2*a))>=0&&h<=1&&(r[l++]=h),p>=0&&p<=1&&(r[l++]=p)}}return l}function Bo(t,e,n,i,r,o){var a=(e-t)*r+t,s=(n-e)*r+e,l=(i-n)*r+n,u=(s-a)*r+a,h=(l-s)*r+s,c=(h-u)*r+u;o[0]=t,o[1]=a,o[2]=u,o[3]=c,o[4]=c,o[5]=h,o[6]=l,o[7]=i}function Vo(t,e,n,i,r,o,a,s,l,u,h){var c,p,d,f,g,y=.005,v=1/0;Do[0]=l,Do[1]=u;for(var m=0;m<1;m+=.05)Lo[0]=Ro(t,n,r,a,m),Lo[1]=Ro(e,i,o,s,m),(f=Pt(Do,Lo))=0&&f=0&&y1e-4)return s[0]=t-n,s[1]=e-i,l[0]=t+n,void(l[1]=e+i);if(Jo[0]=Ko(r)*n+t,Jo[1]=qo(r)*i+e,Qo[0]=Ko(o)*n+t,Qo[1]=qo(o)*i+e,u(s,Jo,Qo),h(l,Jo,Qo),(r%=$o)<0&&(r+=$o),(o%=$o)<0&&(o+=$o),r>o&&!a?o+=$o:rr&&(ta[0]=Ko(d)*n+t,ta[1]=qo(d)*i+e,u(s,ta,s),h(l,ta,l))}var la={M:1,L:2,C:3,Q:4,A:5,Z:6,R:7},ua=[],ha=[],ca=[],pa=[],da=[],fa=[],ga=Math.min,ya=Math.max,va=Math.cos,ma=Math.sin,_a=Math.sqrt,xa=Math.abs,ba=Math.PI,wa=2*ba,Sa="undefined"!=typeof Float32Array,Ma=[];function Ia(t){return Math.round(t/ba*1e8)/1e8%2*ba}function Ta(t,e){var n=Ia(t[0]);n<0&&(n+=wa);var i=n-t[0],r=t[1];r+=i,!e&&r-n>=wa?r=n+wa:e&&n-r>=wa?r=n-wa:!e&&n>r?r=n+(wa-Ia(n-r)):e&&n0&&(this._ux=xa(n/Zn/t)||0,this._uy=xa(n/Zn/e)||0)},t.prototype.setDPR=function(t){this.dpr=t},t.prototype.setContext=function(t){this._ctx=t},t.prototype.getContext=function(){return this._ctx},t.prototype.beginPath=function(){return this._ctx&&this._ctx.beginPath(),this.reset(),this},t.prototype.reset=function(){this._saveData&&(this._len=0),this._lineDash&&(this._lineDash=null,this._dashOffset=0),this._pathSegLen&&(this._pathSegLen=null,this._pathLen=0),this._version++},t.prototype.moveTo=function(t,e){return this.addData(la.M,t,e),this._ctx&&this._ctx.moveTo(t,e),this._x0=t,this._y0=e,this._xi=t,this._yi=e,this},t.prototype.lineTo=function(t,e){var n=xa(t-this._xi)>this._ux||xa(e-this._yi)>this._uy||this._len<5;return this.addData(la.L,t,e),this._ctx&&n&&(this._needsDash?this._dashedLineTo(t,e):this._ctx.lineTo(t,e)),n&&(this._xi=t,this._yi=e),this},t.prototype.bezierCurveTo=function(t,e,n,i,r,o){return this.addData(la.C,t,e,n,i,r,o),this._ctx&&(this._needsDash?this._dashedBezierTo(t,e,n,i,r,o):this._ctx.bezierCurveTo(t,e,n,i,r,o)),this._xi=r,this._yi=o,this},t.prototype.quadraticCurveTo=function(t,e,n,i){return this.addData(la.Q,t,e,n,i),this._ctx&&(this._needsDash?this._dashedQuadraticTo(t,e,n,i):this._ctx.quadraticCurveTo(t,e,n,i)),this._xi=n,this._yi=i,this},t.prototype.arc=function(t,e,n,i,r,o){Ma[0]=i,Ma[1]=r,Ta(Ma,o),i=Ma[0];var a=(r=Ma[1])-i;return this.addData(la.A,t,e,n,n,i,a,0,o?0:1),this._ctx&&this._ctx.arc(t,e,n,i,r,o),this._xi=va(r)*n+t,this._yi=ma(r)*n+e,this},t.prototype.arcTo=function(t,e,n,i,r){return this._ctx&&this._ctx.arcTo(t,e,n,i,r),this},t.prototype.rect=function(t,e,n,i){return this._ctx&&this._ctx.rect(t,e,n,i),this.addData(la.R,t,e,n,i),this},t.prototype.closePath=function(){this.addData(la.Z);var t=this._ctx,e=this._x0,n=this._y0;return t&&(this._needsDash&&this._dashedLineTo(e,n),t.closePath()),this._xi=e,this._yi=n,this},t.prototype.fill=function(t){t&&t.fill(),this.toStatic()},t.prototype.stroke=function(t){t&&t.stroke(),this.toStatic()},t.prototype.setLineDash=function(t){if(t instanceof Array){this._lineDash=t,this._dashIdx=0;for(var e=0,n=0;nu.length&&(this._expandData(),u=this.data);for(var h=0;h0&&d<=t||h<0&&d>=t||0===h&&(c>0&&f<=e||c<0&&f>=e);)d+=h*(n=o[i=this._dashIdx]),f+=c*n,this._dashIdx=(i+1)%g,h>0&&dl||c>0&&fu||a[i%2?"moveTo":"lineTo"](h>=0?ga(d,t):ya(d,t),c>=0?ga(f,e):ya(f,e));h=d-t,c=f-e,this._dashOffset=-_a(h*h+c*c)},t.prototype._dashedBezierTo=function(t,e,n,i,r,o){var a,s,l,u,h,c=this._ctx,p=this._dashSum,d=this._dashOffset,f=this._lineDash,g=this._xi,y=this._yi,v=0,m=this._dashIdx,_=f.length,x=0;for(d<0&&(d=p+d),d%=p,a=0;a<1;a+=.1)s=Ro(g,t,n,r,a+.1)-Ro(g,t,n,r,a),l=Ro(y,e,i,o,a+.1)-Ro(y,e,i,o,a),v+=_a(s*s+l*l);for(;m<_&&!((x+=f[m])>d);m++);for(a=(x-d)/v;a<=1;)u=Ro(g,t,n,r,a),h=Ro(y,e,i,o,a),m%2?c.moveTo(u,h):c.lineTo(u,h),a+=f[m]/v,m=(m+1)%_;m%2!=0&&c.lineTo(r,o),s=r-u,l=o-h,this._dashOffset=-_a(s*s+l*l)},t.prototype._dashedQuadraticTo=function(t,e,n,i){var r=n,o=i;n=(n+2*t)/3,i=(i+2*e)/3,t=(this._xi+2*t)/3,e=(this._yi+2*e)/3,this._dashedBezierTo(t,e,n,i,r,o)},t.prototype.toStatic=function(){if(this._saveData){var t=this.data;t instanceof Array&&(t.length=this._len,Sa&&this._len>11&&(this.data=new Float32Array(t)))}},t.prototype.getBoundingRect=function(){ca[0]=ca[1]=da[0]=da[1]=Number.MAX_VALUE,pa[0]=pa[1]=fa[0]=fa[1]=-Number.MAX_VALUE;var t,e=this.data,n=0,i=0,r=0,o=0;for(t=0;tn||xa(y)>i||c===e-1)&&(f=Math.sqrt(D*D+y*y),r=g,o=_);break;case la.C:var v=t[c++],m=t[c++],_=(g=t[c++],t[c++]),x=t[c++],b=t[c++];f=Fo(r,o,v,m,g,_,x,b,10),r=x,o=b;break;case la.Q:f=Uo(r,o,v=t[c++],m=t[c++],g=t[c++],_=t[c++],10),r=g,o=_;break;case la.A:var w=t[c++],S=t[c++],M=t[c++],I=t[c++],T=t[c++],C=t[c++],A=C+T;c+=1;t[c++];d&&(a=va(T)*M+w,s=ma(T)*I+S),f=ya(M,I)*ga(wa,Math.abs(C)),r=va(A)*M+w,o=ma(A)*I+S;break;case la.R:a=r=t[c++],s=o=t[c++],f=2*t[c++]+2*t[c++];break;case la.Z:var D=a-r;y=s-o;f=Math.sqrt(D*D+y*y),r=a,o=s}f>=0&&(l[h++]=f,u+=f)}return this._pathLen=u,u},t.prototype.rebuildPath=function(t,e){var n,i,r,o,a,s,l,u,h=this.data,c=this._ux,p=this._uy,d=this._len,f=e<1,g=0,y=0;if(!f||(this._pathSegLen||this._calculateLength(),l=this._pathSegLen,u=e*this._pathLen))t:for(var v=0;vc||xa(s-o)>p||v===d-1){if(f){if(g+(H=l[y++])>u){var x=(u-g)/H;t.lineTo(r*(1-x)+a*x,o*(1-x)+s*x);break t}g+=H}t.lineTo(a,s),r=a,o=s}break;case la.C:var b=h[v++],w=h[v++],S=h[v++],M=h[v++],I=h[v++],T=h[v++];if(f){if(g+(H=l[y++])>u){Bo(r,b,S,I,x=(u-g)/H,ua),Bo(o,w,M,T,x,ha),t.bezierCurveTo(ua[1],ha[1],ua[2],ha[2],ua[3],ha[3]);break t}g+=H}t.bezierCurveTo(b,w,S,M,I,T),r=I,o=T;break;case la.Q:b=h[v++],w=h[v++],S=h[v++],M=h[v++];if(f){if(g+(H=l[y++])>u){Yo(r,b,S,x=(u-g)/H,ua),Yo(o,w,M,x,ha),t.quadraticCurveTo(ua[1],ha[1],ua[2],ha[2]);break t}g+=H}t.quadraticCurveTo(b,w,S,M),r=S,o=M;break;case la.A:var C=h[v++],A=h[v++],D=h[v++],L=h[v++],k=h[v++],P=h[v++],O=h[v++],R=!h[v++],N=D>L?D:L,E=xa(D-L)>.001,z=k+P,B=!1;if(f)g+(H=l[y++])>u&&(z=k+P*(u-g)/H,B=!0),g+=H;if(E&&t.ellipse?t.ellipse(C,A,D,L,O,k,z,R):t.arc(C,A,N,k,z,R),B)break t;_&&(n=va(k)*D+C,i=ma(k)*L+A),r=va(z)*D+C,o=ma(z)*L+A;break;case la.R:n=r=h[v],i=o=h[v+1],a=h[v++],s=h[v++];var V=h[v++],F=h[v++];if(f){if(g+(H=l[y++])>u){var G=u-g;t.moveTo(a,s),t.lineTo(a+ga(G,V),s),(G-=V)>0&&t.lineTo(a+V,s+ga(G,F)),(G-=F)>0&&t.lineTo(a+ya(V-G,0),s+F),(G-=V)>0&&t.lineTo(a,s+ya(F-G,0));break t}g+=H}t.rect(a,s,V,F);break;case la.Z:if(f){var H;if(g+(H=l[y++])>u){x=(u-g)/H;t.lineTo(r*(1-x)+n*x,o*(1-x)+i*x);break t}g+=H}t.closePath(),r=n,o=i}}},t.CMD=la,t.initDefaultProps=function(){var e=t.prototype;e._saveData=!0,e._needsDash=!1,e._dashOffset=0,e._dashIdx=0,e._dashSum=0,e._ux=0,e._uy=0}(),t}();function Aa(t,e,n,i,r,o,a){if(0===r)return!1;var s=r,l=0;if(a>e+s&&a>i+s||at+s&&o>n+s||oe+c&&h>i+c&&h>o+c&&h>s+c||ht+c&&u>n+c&&u>r+c&&u>a+c||ue+u&&l>i+u&&l>o+u||lt+u&&s>n+u&&s>r+u||sn||h+ur&&(r+=Oa);var p=Math.atan2(l,s);return p<0&&(p+=Oa),p>=i&&p<=r||p+Oa>=i&&p+Oa<=r}function Na(t,e,n,i,r,o){if(o>e&&o>i||or?s:0}var Ea=Ca.CMD,za=2*Math.PI;var Ba=[-1,-1,-1],Va=[-1,-1];function Fa(t,e,n,i,r,o,a,s,l,u){if(u>e&&u>i&&u>o&&u>s||u1&&(h=void 0,h=Va[0],Va[0]=Va[1],Va[1]=h),f=Ro(e,i,o,s,Va[0]),d>1&&(g=Ro(e,i,o,s,Va[1]))),2===d?ve&&s>i&&s>o||s=0&&h<=1&&(r[l++]=h);else{var u=a*a-4*o*s;if(Po(u))(h=-a/(2*o))>=0&&h<=1&&(r[l++]=h);else if(u>0){var h,c=Mo(u),p=(-a-c)/(2*o);(h=(-a+c)/(2*o))>=0&&h<=1&&(r[l++]=h),p>=0&&p<=1&&(r[l++]=p)}}return l}(e,i,o,s,Ba);if(0===l)return 0;var u=Wo(e,i,o);if(u>=0&&u<=1){for(var h=0,c=Go(e,i,o,u),p=0;pn||s<-n)return 0;var l=Math.sqrt(n*n-s*s);Ba[0]=-l,Ba[1]=l;var u=Math.abs(i-r);if(u<1e-4)return 0;if(u>=za-1e-4){i=0,r=za;var h=o?1:-1;return a>=Ba[0]+t&&a<=Ba[1]+t?h:0}if(i>r){var c=i;i=r,r=c}i<0&&(i+=za,r+=za);for(var p=0,d=0;d<2;d++){var f=Ba[d];if(f+t>a){var g=Math.atan2(s,f);h=o?1:-1;g<0&&(g=za+g),(g>=i&&g<=r||g+za>=i&&g+za<=r)&&(g>Math.PI/2&&g<1.5*Math.PI&&(h=-h),p+=h)}}return p}function Wa(t,e,n,i,r){for(var o,a,s,l,u=t.data,h=t.len(),c=0,p=0,d=0,f=0,g=0,y=0;y1&&(n||(c+=Na(p,d,f,g,i,r))),m&&(f=p=u[y],g=d=u[y+1]),v){case Ea.M:p=f=u[y++],d=g=u[y++];break;case Ea.L:if(n){if(Aa(p,d,u[y],u[y+1],e,i,r))return!0}else c+=Na(p,d,u[y],u[y+1],i,r)||0;p=u[y++],d=u[y++];break;case Ea.C:if(n){if(Da(p,d,u[y++],u[y++],u[y++],u[y++],u[y],u[y+1],e,i,r))return!0}else c+=Fa(p,d,u[y++],u[y++],u[y++],u[y++],u[y],u[y+1],i,r)||0;p=u[y++],d=u[y++];break;case Ea.Q:if(n){if(La(p,d,u[y++],u[y++],u[y],u[y+1],e,i,r))return!0}else c+=Ga(p,d,u[y++],u[y++],u[y],u[y+1],i,r)||0;p=u[y++],d=u[y++];break;case Ea.A:var _=u[y++],x=u[y++],b=u[y++],w=u[y++],S=u[y++],M=u[y++];y+=1;var I=!!(1-u[y++]);o=Math.cos(S)*b+_,a=Math.sin(S)*w+x,m?(f=o,g=a):c+=Na(p,d,o,a,i,r);var T=(i-_)*w/b+_;if(n){if(Ra(_,x,w,S,S+M,I,e,T,r))return!0}else c+=Ha(_,x,w,S,S+M,I,T,r);p=Math.cos(S+M)*b+_,d=Math.sin(S+M)*w+x;break;case Ea.R:if(f=p=u[y++],g=d=u[y++],o=f+u[y++],a=g+u[y++],n){if(Aa(f,g,o,g,e,i,r)||Aa(o,g,o,a,e,i,r)||Aa(o,a,f,a,e,i,r)||Aa(f,a,f,g,e,i,r))return!0}else c+=Na(o,g,o,a,i,r),c+=Na(f,a,f,g,i,r);break;case Ea.Z:if(n){if(Aa(p,d,f,g,e,i,r))return!0}else c+=Na(p,d,f,g,i,r);p=f,d=g}}return n||(s=d,l=g,Math.abs(s-l)<1e-4)||(c+=Na(p,d,f,g,i,r)||0),0!==c}var Ya=T({fill:"#000",stroke:null,strokePercent:1,fillOpacity:1,strokeOpacity:1,lineDashOffset:0,lineWidth:1,lineCap:"butt",miterLimit:10,strokeNoScale:!1,strokeFirst:!1},vo),Xa={style:T({fill:!0,stroke:!0,strokePercent:!0,fillOpacity:!0,strokeOpacity:!0,lineDashOffset:!0,lineWidth:!0,miterLimit:!0},mo.style)},Ua=["x","y","rotation","scaleX","scaleY","originX","originY","invisible","culling","z","z2","zlevel","parent"],Za=function(t){function e(e){return t.call(this,e)||this}var i;return n(e,t),e.prototype.update=function(){var n=this;t.prototype.update.call(this);var i=this.style;if(i.decal){var r=this._decalEl=this._decalEl||new e;r.buildPath===e.prototype.buildPath&&(r.buildPath=function(t){n.buildPath(t,n.shape)}),r.silent=!0;var o=r.style;for(var a in i)o[a]!==i[a]&&(o[a]=i[a]);o.fill=i.fill?i.decal:null,o.decal=null,o.shadowColor=null,i.strokeFirst&&(o.stroke=null);for(var s=0;s.5?jn:e>.2?"#eee":qn}if(t)return qn}return jn},e.prototype.getInsideTextStroke=function(t){var e=this.style.fill;if(H(e)){var n=this.__zr;if(!(!n||!n.isDarkMode())===sn(t,0)<.4)return e}},e.prototype.buildPath=function(t,e,n){},e.prototype.pathUpdated=function(){this.__dirty&=~e.SHAPE_CHANGED_BIT},e.prototype.createPathProxy=function(){this.path=new Ca(!1)},e.prototype.hasStroke=function(){var t=this.style,e=t.stroke;return!(null==e||"none"===e||!(t.lineWidth>0))},e.prototype.hasFill=function(){var t=this.style.fill;return null!=t&&"none"!==t},e.prototype.getBoundingRect=function(){var t=this._rect,n=this.style,i=!t;if(i){var r=!1;this.path||(r=!0,this.createPathProxy());var o=this.path;(r||this.__dirty&e.SHAPE_CHANGED_BIT)&&(o.beginPath(),this.buildPath(o,this.shape,!1),this.pathUpdated()),t=o.getBoundingRect()}if(this._rect=t,this.hasStroke()&&this.path&&this.path.len()>0){var a=this._rectWithStroke||(this._rectWithStroke=t.clone());if(this.__dirty||i){a.copy(t);var s=n.strokeNoScale?this.getLineScale():1,l=n.lineWidth;if(!this.hasFill()){var u=this.strokeContainThreshold;l=Math.max(l,null==u?4:u)}s>1e-10&&(a.width+=l/s,a.height+=l/s,a.x-=l/s/2,a.y-=l/s/2)}return a}return t},e.prototype.contain=function(t,e){var n=this.transformCoordToLocal(t,e),i=this.getBoundingRect(),r=this.style;if(t=n[0],e=n[1],i.contain(t,e)){var o=this.path;if(this.hasStroke()){var a=r.lineWidth,s=r.strokeNoScale?this.getLineScale():1;if(s>1e-10&&(this.hasFill()||(a=Math.max(a,this.strokeContainThreshold)),function(t,e,n,i){return Wa(t,e,!0,n,i)}(o,a/s,t,e)))return!0}if(this.hasFill())return function(t,e,n){return Wa(t,0,!1,e,n)}(o,t,e)}return!1},e.prototype.dirtyShape=function(){this.__dirty|=e.SHAPE_CHANGED_BIT,this._rect&&(this._rect=null),this._decalEl&&this._decalEl.dirtyShape(),this.markRedraw()},e.prototype.dirty=function(){this.dirtyStyle(),this.dirtyShape()},e.prototype.animateShape=function(t){return this.animate("shape",t)},e.prototype.updateDuringAnimation=function(t){"style"===t?this.dirtyStyle():"shape"===t?this.dirtyShape():this.markRedraw()},e.prototype.attrKV=function(e,n){"shape"===e?this.setShape(n):t.prototype.attrKV.call(this,e,n)},e.prototype.setShape=function(t,e){var n=this.shape;return n||(n=this.shape={}),"string"==typeof t?n[t]=e:I(n,t),this.dirtyShape(),this},e.prototype.shapeChanged=function(){return!!(this.__dirty&e.SHAPE_CHANGED_BIT)},e.prototype.createStyle=function(t){return pt(Ya,t)},e.prototype._innerSaveToNormal=function(e){t.prototype._innerSaveToNormal.call(this,e);var n=this._normalState;e.shape&&!n.shape&&(n.shape=I({},this.shape))},e.prototype._applyStateObj=function(e,n,i,r,o,a){t.prototype._applyStateObj.call(this,e,n,i,r,o,a);var s,l=!(n&&r);if(n&&n.shape?o?r?s=n.shape:(s=I({},i.shape),I(s,n.shape)):(s=I({},r?this.shape:i.shape),I(s,n.shape)):l&&(s=i.shape),s)if(o){this.shape=I({},this.shape);for(var u={},h=z(s),c=0;c0},e.prototype.hasFill=function(){var t=this.style.fill;return null!=t&&"none"!==t},e.prototype.createStyle=function(t){return pt(ja,t)},e.prototype.setBoundingRect=function(t){this._rect=t},e.prototype.getBoundingRect=function(){var t=this.style;if(!this._rect){var e=t.text;null!=e?e+="":e="";var n=Fn(e,t.font,t.textAlign,t.textBaseline);if(n.x+=t.x||0,n.y+=t.y||0,this.hasStroke()){var i=t.lineWidth;n.x-=i/2,n.y-=i/2,n.width+=i,n.height+=i}this._rect=n}return this._rect},e.initDefaultProps=void(e.prototype.dirtyRectTolerance=10),e}(xo);qa.prototype.type="tspan";var Ka=T({x:0,y:0},vo),$a={style:T({x:!0,y:!0,width:!0,height:!0,sx:!0,sy:!0,sWidth:!0,sHeight:!0},mo.style)};var Ja=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return n(e,t),e.prototype.createStyle=function(t){return pt(Ka,t)},e.prototype._getSize=function(t){var e=this.style,n=e[t];if(null!=n)return n;var i,r=(i=e.image)&&"string"!=typeof i&&i.width&&i.height?e.image:this.__image;if(!r)return 0;var o="width"===t?"height":"width",a=e[o];return null==a?r[t]:r[t]/r[o]*a},e.prototype.getWidth=function(){return this._getSize("width")},e.prototype.getHeight=function(){return this._getSize("height")},e.prototype.getAnimationStyleProps=function(){return $a},e.prototype.getBoundingRect=function(){var t=this.style;return this._rect||(this._rect=new Rn(t.x||0,t.y||0,this.getWidth(),this.getHeight())),this._rect},e}(xo);Ja.prototype.type="image";var Qa=Math.round;function ts(t,e,n){if(e){var i=e.x1,r=e.x2,o=e.y1,a=e.y2;t.x1=i,t.x2=r,t.y1=o,t.y2=a;var s=n&&n.lineWidth;return s?(Qa(2*i)===Qa(2*r)&&(t.x1=t.x2=ns(i,s,!0)),Qa(2*o)===Qa(2*a)&&(t.y1=t.y2=ns(o,s,!0)),t):t}}function es(t,e,n){if(e){var i=e.x,r=e.y,o=e.width,a=e.height;t.x=i,t.y=r,t.width=o,t.height=a;var s=n&&n.lineWidth;return s?(t.x=ns(i,s,!0),t.y=ns(r,s,!0),t.width=Math.max(ns(i+o,s,!1)-t.x,0===o?0:1),t.height=Math.max(ns(r+a,s,!1)-t.y,0===a?0:1),t):t}}function ns(t,e,n){if(!e)return t;var i=Qa(2*t);return(i+Qa(e))%2==0?i/2:(i+(n?1:-1))/2}var is=function(){this.x=0,this.y=0,this.width=0,this.height=0},rs={},os=function(t){function e(e){return t.call(this,e)||this}return n(e,t),e.prototype.getDefaultShape=function(){return new is},e.prototype.buildPath=function(t,e){var n,i,r,o;if(this.subPixelOptimize){var a=es(rs,e,this.style);n=a.x,i=a.y,r=a.width,o=a.height,a.r=e.r,e=a}else n=e.x,i=e.y,r=e.width,o=e.height;e.r?function(t,e){var n,i,r,o,a,s=e.x,l=e.y,u=e.width,h=e.height,c=e.r;u<0&&(s+=u,u=-u),h<0&&(l+=h,h=-h),"number"==typeof c?n=i=r=o=c:c instanceof Array?1===c.length?n=i=r=o=c[0]:2===c.length?(n=r=c[0],i=o=c[1]):3===c.length?(n=c[0],i=o=c[1],r=c[2]):(n=c[0],i=c[1],r=c[2],o=c[3]):n=i=r=o=0,n+i>u&&(n*=u/(a=n+i),i*=u/a),r+o>u&&(r*=u/(a=r+o),o*=u/a),i+r>h&&(i*=h/(a=i+r),r*=h/a),n+o>h&&(n*=h/(a=n+o),o*=h/a),t.moveTo(s+n,l),t.lineTo(s+u-i,l),0!==i&&t.arc(s+u-i,l+i,i,-Math.PI/2,0),t.lineTo(s+u,l+h-r),0!==r&&t.arc(s+u-r,l+h-r,r,0,Math.PI/2),t.lineTo(s+o,l+h),0!==o&&t.arc(s+o,l+h-o,o,Math.PI/2,Math.PI),t.lineTo(s,l+n),0!==n&&t.arc(s+n,l+n,n,Math.PI,1.5*Math.PI)}(t,e):t.rect(n,i,r,o)},e.prototype.isZeroArea=function(){return!this.shape.width||!this.shape.height},e}(Za);os.prototype.type="rect";var as={fill:"#000"},ss={style:T({fill:!0,stroke:!0,fillOpacity:!0,strokeOpacity:!0,lineWidth:!0,fontSize:!0,lineHeight:!0,width:!0,height:!0,textShadowColor:!0,textShadowBlur:!0,textShadowOffsetX:!0,textShadowOffsetY:!0,backgroundColor:!0,padding:!0,borderColor:!0,borderWidth:!0,borderRadius:!0},mo.style)},ls=function(t){function e(e){var n=t.call(this)||this;return n.type="text",n._children=[],n._defaultStyle=as,n.attr(e),n}return n(e,t),e.prototype.childrenRef=function(){return this._children},e.prototype.update=function(){this.styleChanged()&&this._updateSubTexts();for(var e=0;ep&&u){var d=Math.floor(p/l);n=n.slice(0,d)}var f=p,g=h;if(r&&(f+=r[0]+r[2],null!=g&&(g+=r[1]+r[3])),t&&a&&null!=g)for(var y=oo(h,o,e.ellipsis,{minChar:e.truncateMinChar,placeholder:e.placeholder}),v=0;v0,I=null!=t.width&&("truncate"===t.overflow||"break"===t.overflow||"breakAll"===t.overflow),T=i.calculatedLineHeight,C=0;Cl&&co(n,t.substring(l,u),e,s),co(n,i[2],e,s,i[1]),l=io.lastIndex}lo){b>0?(m.tokens=m.tokens.slice(0,b),y(m,x,_),n.lines=n.lines.slice(0,v+1)):n.lines=n.lines.slice(0,v);break t}var C=w.width,A=null==C||"auto"===C;if("string"==typeof C&&"%"===C.charAt(C.length-1))P.percentWidth=C,h.push(P),P.contentWidth=Bn(P.text,I);else{if(A){var D=w.backgroundColor,L=D&&D.image;L&&no(L=Qr(L))&&(P.width=Math.max(P.width,L.width*T/L.height))}var k=f&&null!=r?r-x:null;null!=k&&k=0&&"right"===(C=_[T]).align;)this._placeToken(C,t,b,f,I,"right",y),w-=C.width,I-=C.width,T--;for(M+=(n-(M-d)-(g-I)-w)/2;S<=T;)C=_[S],this._placeToken(C,t,b,f,M+C.width/2,"center",y),M+=C.width,S++;f+=b}},e.prototype._placeToken=function(t,e,n,i,r,o,a){var s=e.rich[t.styleName]||{};s.text=t.text;var l=t.verticalAlign,u=i+n/2;"top"===l?u=i+t.height/2:"bottom"===l&&(u=i+n-t.height/2),!t.isLineHolder&&gs(s)&&this._renderBackground(s,e,"right"===o?r-t.width:"center"===o?r-t.width/2:r,u-t.height/2,t.width,t.height);var h=!!s.backgroundColor,c=t.textPadding;c&&(r=ds(r,o,c),u-=t.height/2-c[0]-t.innerHeight/2);var p=this._getOrCreateChild(qa),d=p.createStyle();p.useStyle(d);var f=this._defaultStyle,g=!1,y=0,v=ps("fill"in s?s.fill:"fill"in e?e.fill:(g=!0,f.fill)),m=ps("stroke"in s?s.stroke:"stroke"in e?e.stroke:h||a||f.autoStroke&&!g?null:(y=2,f.stroke)),_=s.textShadowBlur>0||e.textShadowBlur>0;d.text=t.text,d.x=r,d.y=u,_&&(d.shadowBlur=s.textShadowBlur||e.textShadowBlur||0,d.shadowColor=s.textShadowColor||e.textShadowColor||"transparent",d.shadowOffsetX=s.textShadowOffsetX||e.textShadowOffsetX||0,d.shadowOffsetY=s.textShadowOffsetY||e.textShadowOffsetY||0),d.textAlign=o,d.textBaseline="middle",d.font=t.font||En,d.opacity=et(s.opacity,e.opacity,1),m&&(d.lineWidth=et(s.lineWidth,e.lineWidth,y),d.lineDash=tt(s.lineDash,e.lineDash),d.lineDashOffset=e.lineDashOffset||0,d.stroke=m),v&&(d.fill=v);var x=t.contentWidth,b=t.contentHeight;p.setBoundingRect(new Rn(Gn(d.x,x,d.textAlign),Hn(d.y,b,d.textBaseline),x,b))},e.prototype._renderBackground=function(t,e,n,i,r,o){var a,s,l,u=t.backgroundColor,h=t.borderWidth,c=t.borderColor,p=H(u),d=t.borderRadius,f=this;if(p||h&&c){(a=this._getOrCreateChild(os)).useStyle(a.createStyle()),a.style.fill=null;var g=a.shape;g.x=n,g.y=i,g.width=r,g.height=o,g.r=d,a.dirtyShape()}if(p)(l=a.style).fill=u||null,l.fillOpacity=tt(t.fillOpacity,1);else if(u&&u.image){(s=this._getOrCreateChild(Ja)).onload=function(){f.dirtyStyle()};var y=s.style;y.image=u.image,y.x=n,y.y=i,y.width=r,y.height=o}h&&c&&((l=a.style).lineWidth=h,l.stroke=c,l.strokeOpacity=tt(t.strokeOpacity,1),l.lineDash=t.borderDash,l.lineDashOffset=t.borderDashOffset||0,a.strokeContainThreshold=0,a.hasFill()&&a.hasStroke()&&(l.strokeFirst=!0,l.lineWidth*=2));var v=(a||s).style;v.shadowBlur=t.shadowBlur||0,v.shadowColor=t.shadowColor||"transparent",v.shadowOffsetX=t.shadowOffsetX||0,v.shadowOffsetY=t.shadowOffsetY||0,v.opacity=et(t.opacity,e.opacity,1)},e.makeFont=function(t){var e="";if(t.fontSize||t.fontFamily||t.fontWeight){var n="";n="string"!=typeof t.fontSize||-1===t.fontSize.indexOf("px")&&-1===t.fontSize.indexOf("rem")&&-1===t.fontSize.indexOf("em")?isNaN(+t.fontSize)?"12px":t.fontSize+"px":t.fontSize,e=[t.fontStyle,t.fontWeight,n,t.fontFamily||"sans-serif"].join(" ")}return e&&ot(e)||t.textFont||t.font},e}(xo),us={left:!0,right:1,center:1},hs={top:1,bottom:1,middle:1};function cs(t){if(t){t.font=ls.makeFont(t);var e=t.align;"middle"===e&&(e="center"),t.align=null==e||us[e]?e:"left";var n=t.verticalAlign;"center"===n&&(n="middle"),t.verticalAlign=null==n||hs[n]?n:"top",t.padding&&(t.padding=it(t.padding))}}function ps(t,e){return null==t||e<=0||"transparent"===t||"none"===t?null:t.image||t.colorStops?"#000":t}function ds(t,e,n){return"right"===e?t-n[1]:"center"===e?t+n[3]/2-n[1]/2:t+n[3]}function fs(t){var e=t.text;return null!=e&&(e+=""),e}function gs(t){return!!(t.backgroundColor||t.borderWidth&&t.borderColor)}var ys=Lr(),vs=1,ms={},_s=Lr(),xs=["emphasis","blur","select"],bs=["normal","emphasis","blur","select"],ws="highlight",Ss="downplay",Ms="select",Is="unselect",Ts="toggleSelect";function Cs(t){return null!=t&&"none"!==t}var As=new Ee(100);function Ds(t){if("string"!=typeof t)return t;var e=As.get(t);return e||(e=$e(t,-.1),As.put(t,e)),e}function Ls(t,e,n){t.onHoverStateChange&&(t.hoverState||0)!==n&&t.onHoverStateChange(e),t.hoverState=n}function ks(t){Ls(t,"emphasis",2)}function Ps(t){2===t.hoverState&&Ls(t,"normal",0)}function Os(t){Ls(t,"blur",1)}function Rs(t){1===t.hoverState&&Ls(t,"normal",0)}function Ns(t){t.selected=!0}function Es(t){t.selected=!1}function zs(t,e,n){e(t,n)}function Bs(t,e,n){zs(t,e,n),t.isGroup&&t.traverse((function(t){zs(t,e,n)}))}function Vs(t,e){switch(e){case"emphasis":t.hoverState=2;break;case"normal":t.hoverState=0;break;case"blur":t.hoverState=1;break;case"select":t.selected=!0}}function Fs(t,e){var n=this.states[t];if(this.style){if("emphasis"===t)return function(t,e,n,i){var r=n&&A(n,"select")>=0,o=!1;if(t instanceof Za){var a=_s(t),s=r&&a.selectFill||a.normalFill,l=r&&a.selectStroke||a.normalStroke;if(Cs(s)||Cs(l)){var u=(i=i||{}).style||{};!Cs(u.fill)&&Cs(s)?(o=!0,i=I({},i),(u=I({},u)).fill=Ds(s)):!Cs(u.stroke)&&Cs(l)&&(o||(i=I({},i),u=I({},u)),u.stroke=Ds(l)),i.style=u}}if(i&&null==i.z2){o||(i=I({},i));var h=t.z2EmphasisLift;i.z2=t.z2+(null!=h?h:10)}return i}(this,0,e,n);if("blur"===t)return function(t,e,n){var i=A(t.currentStates,e)>=0,r=t.style.opacity,o=i?null:function(t,e,n,i){for(var r=t.style,o={},a=0;a0){var o={dataIndex:r,seriesIndex:t.seriesIndex};null!=i&&(o.dataType=i),e.push(o)}}))})),e}function Js(t,e,n){il(t,!0),Bs(t,Gs),Qs(t,e,n)}function Qs(t,e,n){var i=ys(t);null!=e?(i.focus=e,i.blurScope=n):i.focus&&(i.focus=null)}var tl=["emphasis","blur","select"],el={itemStyle:"getItemStyle",lineStyle:"getLineStyle",areaStyle:"getAreaStyle"};function nl(t,e,n,i){n=n||"itemStyle";for(var r=0;r1&&(a*=cl(f),s*=cl(f));var g=(r===o?-1:1)*cl((a*a*(s*s)-a*a*(d*d)-s*s*(p*p))/(a*a*(d*d)+s*s*(p*p)))||0,y=g*a*d/s,v=g*-s*p/a,m=(t+n)/2+dl(c)*y-pl(c)*v,_=(e+i)/2+pl(c)*y+dl(c)*v,x=vl([1,0],[(p-y)/a,(d-v)/s]),b=[(p-y)/a,(d-v)/s],w=[(-1*p-y)/a,(-1*d-v)/s],S=vl(b,w);if(yl(b,w)<=-1&&(S=fl),yl(b,w)>=1&&(S=0),S<0){var M=Math.round(S/fl*1e6)/1e6;S=2*fl+M%2*fl}h.addData(u,m,_,a,s,x,S,c,o)}var _l=/([mlvhzcqtsa])([^mlvhzcqtsa]*)/gi,xl=/-?([0-9]*\.)?[0-9]+([eE]-?[0-9]+)?/g;var bl=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return n(e,t),e.prototype.applyTransform=function(t){},e}(Za);function wl(t){return null!=t.setData}function Sl(t,e){var n=function(t){var e=new Ca;if(!t)return e;var n,i=0,r=0,o=i,a=r,s=Ca.CMD,l=t.match(_l);if(!l)return e;for(var u=0;uL*L+k*k&&(M=T,I=C),{cx:M,cy:I,x01:-h,y01:-c,x11:M*(r/b-1),y11:I*(r/b-1)}}function Gl(t,e){var n=zl(e.r,0),i=zl(e.r0||0,0),r=n>0;if(r||i>0){if(r||(n=i,i=0),i>n){var o=n;n=i,i=o}var a,s=!!e.clockwise,l=e.startAngle,u=e.endAngle;if(l===u)a=0;else{var h=[l,u];Ta(h,!s),a=Nl(h[0]-h[1])}var c=e.cx,p=e.cy,d=e.cornerRadius||0,f=e.innerCornerRadius||0;if(n>Vl)if(a>Ll-Vl)t.moveTo(c+n*Pl(l),p+n*kl(l)),t.arc(c,p,n,l,u,!s),i>Vl&&(t.moveTo(c+i*Pl(u),p+i*kl(u)),t.arc(c,p,i,u,l,s));else{var g=Nl(n-i)/2,y=Bl(g,d),v=Bl(g,f),m=v,_=y,x=n*Pl(l),b=n*kl(l),w=i*Pl(u),S=i*kl(u),M=void 0,I=void 0,T=void 0,C=void 0;if((y>Vl||v>Vl)&&(M=n*Pl(u),I=n*kl(u),T=i*Pl(l),C=i*kl(l),aVl)if(_>Vl){var N=Fl(T,C,x,b,n,_,s),E=Fl(M,I,w,S,n,_,s);t.moveTo(c+N.cx+N.x01,p+N.cy+N.y01),_Vl&&a>Vl)if(m>Vl){N=Fl(w,S,M,I,i,-m,s),E=Fl(x,b,T,C,i,-m,s);t.lineTo(c+N.cx+N.x01,p+N.cy+N.y01),m=2){if(i&&"spline"!==i){var o=function(t,e,n,i){var r,o,a,s,l=[],u=[],h=[],c=[];if(i){a=[1/0,1/0],s=[-1/0,-1/0];for(var p=0,d=t.length;pn-2?n-1:l+1],d=t[l>n-3?n-1:l+2]);var f=u*u,g=u*f;i.push([Ul(h[0],c[0],p[0],d[0],u,f,g),Ul(h[1],c[1],p[1],d[1],u,f,g)])}return i}(r,n)),t.moveTo(r[0][0],r[0][1]);s=1;for(var c=r.length;spu[1]){if(a=!1,r)return a;var u=Math.abs(pu[0]-cu[1]),h=Math.abs(cu[0]-pu[1]);Math.min(u,h)>i.len()&&(u0?l?e.animateFrom(n,{duration:f,delay:y||0,easing:g,done:o,force:!!o||!!a,scope:t,during:a}):e.animateTo(n,{duration:f,delay:y||0,easing:g,done:o,force:!!o||!!a,setToFinal:!0,scope:t,during:a}):(e.stopAnimation(),!l&&e.attr(n),o&&o())}else e.stopAnimation(),!l&&e.attr(n),a&&a(1),o&&o()}function Ou(t,e,n,i,r,o){Pu("update",t,e,n,i,r,o)}function Ru(t,e,n,i,r,o){Pu("init",t,e,n,i,r,o)}function Nu(t,e,n,i,r,o){Bu(t)||Pu("remove",t,e,n,i,r,o)}function Eu(t,e,n,i){t.removeTextContent(),t.removeTextGuideLine(),Nu(t,{style:{opacity:0}},e,n,i)}function zu(t,e,n){function i(){t.parent&&t.parent.remove(t)}t.isGroup?t.traverse((function(t){t.isGroup||Eu(t,e,n,i)})):Eu(t,e,n,i)}function Bu(t){if(!t.__zr)return!0;for(var e=0;eMath.abs(o[1])?o[0]>0?"right":"left":o[1]>0?"bottom":"top"}function Hu(t){return!t.isGroup}function Wu(t,e,n){if(t&&e){var i,r=(i={},t.traverse((function(t){Hu(t)&&t.anid&&(i[t.anid]=t)})),i);e.traverse((function(t){if(Hu(t)&&t.anid){var e=r[t.anid];if(e){var i=o(t);t.attr(o(e)),Ou(t,i,n,ys(t).dataIndex)}}}))}function o(t){var e={x:t.x,y:t.y,rotation:t.rotation};return function(t){return null!=t.shape}(t)&&(e.shape=I({},t.shape)),e}}function Yu(t,e){return O(t,(function(t){var n=t[0];n=mu(n,e.x),n=_u(n,e.x+e.width);var i=t[1];return i=mu(i,e.y),[n,i=_u(i,e.y+e.height)]}))}function Xu(t,e){var n=mu(t.x,e.x),i=_u(t.x+t.width,e.x+e.width),r=mu(t.y,e.y),o=_u(t.y+t.height,e.y+e.height);if(i>=n&&o>=r)return{x:n,y:r,width:i-n,height:o-r}}function Uu(t,e,n){var i=I({rectHover:!0},e),r=i.style={strokeNoScale:!0};if(n=n||{x:-1,y:-1,width:2,height:2},t)return 0===t.indexOf("image://")?(r.image=t.slice(8),T(r,n),new Ja(i)):Tu(t.replace("path://",""),i,n,"center")}function Zu(t,e,n,i,r){for(var o=0,a=r[r.length-1];o=-1e-6)return!1;var f=t-r,g=e-o,y=qu(f,g,u,h)/d;if(y<0||y>1)return!1;var v=qu(f,g,c,p)/d;return!(v<0||v>1)}function qu(t,e,n,i){return t*i-n*e}Mu("circle",Tl),Mu("ellipse",Al),Mu("sector",Wl),Mu("ring",Xl),Mu("polygon",ql),Mu("polyline",$l),Mu("rect",os),Mu("line",tu),Mu("bezierCurve",ru),Mu("arc",au);var Ku=Object.freeze({__proto__:null,extendShape:bu,extendPath:Su,registerShape:Mu,getShapeClass:Iu,makePath:Tu,makeImage:Cu,mergePath:Du,resizePath:Lu,subPixelOptimizeLine:function(t){return ts(t.shape,t.shape,t.style),t},subPixelOptimizeRect:function(t){return es(t.shape,t.shape,t.style),t},subPixelOptimize:ku,updateProps:Ou,initProps:Ru,removeElement:Nu,removeElementWithFadeOut:zu,isElementRemoved:Bu,getTransform:Vu,applyTransform:Fu,transformDirection:Gu,groupTransition:Wu,clipPointsByRect:Yu,clipRectByRect:Xu,createIcon:Uu,linePolygonIntersect:Zu,lineLineIntersect:ju,Group:zi,Image:Ja,Text:ls,Circle:Tl,Ellipse:Al,Sector:Wl,Ring:Xl,Polygon:ql,Polyline:$l,Rect:os,Line:tu,BezierCurve:ru,Arc:au,IncrementalDisplayable:vu,CompoundPath:su,LinearGradient:uu,RadialGradient:hu,BoundingRect:Rn,OrientedBoundingRect:gu,Point:In,Path:Za}),$u={};function Ju(t,e){for(var n=0;n-1?Ch:Dh;function Oh(t,e){t=t.toUpperCase(),kh[t]=new Sh(e),Lh[t]=e}Oh(Ah,{time:{month:["January","February","March","April","May","June","July","August","September","October","November","December"],monthAbbr:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],dayOfWeek:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],dayOfWeekAbbr:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"]},legend:{selector:{all:"All",inverse:"Inv"}},toolbox:{brush:{title:{rect:"Box Select",polygon:"Lasso Select",lineX:"Horizontally Select",lineY:"Vertically Select",keep:"Keep Selections",clear:"Clear Selections"}},dataView:{title:"Data View",lang:["Data View","Close","Refresh"]},dataZoom:{title:{zoom:"Zoom",back:"Zoom Reset"}},magicType:{title:{line:"Switch to Line Chart",bar:"Switch to Bar Chart",stack:"Stack",tiled:"Tile"}},restore:{title:"Restore"},saveAsImage:{title:"Save as Image",lang:["Right Click to Save Image"]}},series:{typeNames:{pie:"Pie chart",bar:"Bar chart",line:"Line chart",scatter:"Scatter plot",effectScatter:"Ripple scatter plot",radar:"Radar chart",tree:"Tree",treemap:"Treemap",boxplot:"Boxplot",candlestick:"Candlestick",k:"K line chart",heatmap:"Heat map",map:"Map",parallel:"Parallel coordinate map",lines:"Line graph",graph:"Relationship graph",sankey:"Sankey diagram",funnel:"Funnel chart",gauge:"Guage",pictorialBar:"Pictorial bar",themeRiver:"Theme River Map",sunburst:"Sunburst"}},aria:{general:{withTitle:'This is a chart about "{title}"',withoutTitle:"This is a chart"},series:{single:{prefix:"",withName:" with type {seriesType} named {seriesName}.",withoutName:" with type {seriesType}."},multiple:{prefix:". It consists of {seriesCount} series count.",withName:" The {seriesId} series is a {seriesType} representing {seriesName}.",withoutName:" The {seriesId} series is a {seriesType}.",separator:{middle:"",end:""}}},data:{allData:"The data is as follows: ",partialData:"The first {displayCnt} items are: ",withName:"the data for {name} is {value}",withoutName:"{value}",separator:{middle:", ",end:". "}}}}),Oh(Ch,{time:{month:["一月","二月","三月","四月","五月","六月","七月","八月","九月","十月","十一月","十二月"],monthAbbr:["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"],dayOfWeek:["星期日","星期一","星期二","星期三","星期四","星期五","星期六"],dayOfWeekAbbr:["日","一","二","三","四","五","六"]},legend:{selector:{all:"全选",inverse:"反选"}},toolbox:{brush:{title:{rect:"矩形选择",polygon:"圈选",lineX:"横向选择",lineY:"纵向选择",keep:"保持选择",clear:"清除选择"}},dataView:{title:"数据视图",lang:["数据视图","关闭","刷新"]},dataZoom:{title:{zoom:"区域缩放",back:"区域缩放还原"}},magicType:{title:{line:"切换为折线图",bar:"切换为柱状图",stack:"切换为堆叠",tiled:"切换为平铺"}},restore:{title:"还原"},saveAsImage:{title:"保存为图片",lang:["右键另存为图片"]}},series:{typeNames:{pie:"饼图",bar:"柱状图",line:"折线图",scatter:"散点图",effectScatter:"涟漪散点图",radar:"雷达图",tree:"树图",treemap:"矩形树图",boxplot:"箱型图",candlestick:"K线图",k:"K线图",heatmap:"热力图",map:"地图",parallel:"平行坐标图",lines:"线图",graph:"关系图",sankey:"桑基图",funnel:"漏斗图",gauge:"仪表盘图",pictorialBar:"象形柱图",themeRiver:"主题河流图",sunburst:"旭日图"}},aria:{general:{withTitle:"这是一个关于“{title}”的图表。",withoutTitle:"这是一个图表,"},series:{single:{prefix:"",withName:"图表类型是{seriesType},表示{seriesName}。",withoutName:"图表类型是{seriesType}。"},multiple:{prefix:"它由{seriesCount}个图表系列组成。",withName:"第{seriesId}个系列是一个表示{seriesName}的{seriesType},",withoutName:"第{seriesId}个系列是一个{seriesType},",separator:{middle:";",end:"。"}}},data:{allData:"其数据是——",partialData:"其中,前{displayCnt}项是——",withName:"{name}的数据是{value}",withoutName:"{value}",separator:{middle:",",end:""}}}});var Rh=1e3,Nh=6e4,Eh=36e5,zh=864e5,Bh=31536e6,Vh={year:"{yyyy}",month:"{MMM}",day:"{d}",hour:"{HH}:{mm}",minute:"{HH}:{mm}",second:"{HH}:{mm}:{ss}",millisecond:"{hh}:{mm}:{ss} {SSS}",none:"{yyyy}-{MM}-{dd} {hh}:{mm}:{ss} {SSS}"},Fh="{yyyy}-{MM}-{dd}",Gh={year:"{yyyy}",month:"{yyyy}-{MM}",day:Fh,hour:"{yyyy}-{MM}-{dd} "+Vh.hour,minute:"{yyyy}-{MM}-{dd} "+Vh.minute,second:"{yyyy}-{MM}-{dd} "+Vh.second,millisecond:Vh.none},Hh=["year","month","day","hour","minute","second","millisecond"],Wh=["year","half-year","quarter","month","week","half-week","day","half-day","quarter-day","hour","minute","second","millisecond"];function Yh(t,e){return"0000".substr(0,e-(t+="").length)+t}function Xh(t){switch(t){case"half-year":case"quarter":return"month";case"week":case"half-week":return"day";case"half-day":case"quarter-day":return"hour";default:return t}}function Uh(t){return t===Xh(t)}function Zh(t,e,n,i){var r=rr(t),o=r[Kh(n)](),a=r[$h(n)]()+1,s=Math.floor((a-1)/4)+1,l=r[Jh(n)](),u=r["get"+(n?"UTC":"")+"Day"](),h=r[Qh(n)](),c=(h-1)%12+1,p=r[tc(n)](),d=r[ec(n)](),f=r[nc(n)](),g=(i instanceof Sh?i:function(t){return kh[t]}(i||Ph)||kh.EN).getModel("time"),y=g.get("month"),v=g.get("monthAbbr"),m=g.get("dayOfWeek"),_=g.get("dayOfWeekAbbr");return(e||"").replace(/{yyyy}/g,o+"").replace(/{yy}/g,o%100+"").replace(/{Q}/g,s+"").replace(/{MMMM}/g,y[a-1]).replace(/{MMM}/g,v[a-1]).replace(/{MM}/g,Yh(a,2)).replace(/{M}/g,a+"").replace(/{dd}/g,Yh(l,2)).replace(/{d}/g,l+"").replace(/{eeee}/g,m[u]).replace(/{ee}/g,_[u]).replace(/{e}/g,u+"").replace(/{HH}/g,Yh(h,2)).replace(/{H}/g,h+"").replace(/{hh}/g,Yh(c+"",2)).replace(/{h}/g,c+"").replace(/{mm}/g,Yh(p,2)).replace(/{m}/g,p+"").replace(/{ss}/g,Yh(d,2)).replace(/{s}/g,d+"").replace(/{SSS}/g,Yh(f,3)).replace(/{S}/g,f+"")}function jh(t,e){var n=rr(t),i=n[$h(e)]()+1,r=n[Jh(e)](),o=n[Qh(e)](),a=n[tc(e)](),s=n[ec(e)](),l=0===n[nc(e)](),u=l&&0===s,h=u&&0===a,c=h&&0===o,p=c&&1===r;return p&&1===i?"year":p?"month":c?"day":h?"hour":u?"minute":l?"second":"millisecond"}function qh(t,e,n){var i="number"==typeof t?rr(t):t;switch(e=e||jh(t,n)){case"year":return i[Kh(n)]();case"half-year":return i[$h(n)]()>=6?1:0;case"quarter":return Math.floor((i[$h(n)]()+1)/4);case"month":return i[$h(n)]();case"day":return i[Jh(n)]();case"half-day":return i[Qh(n)]()/24;case"hour":return i[Qh(n)]();case"minute":return i[tc(n)]();case"second":return i[ec(n)]();case"millisecond":return i[nc(n)]()}}function Kh(t){return t?"getUTCFullYear":"getFullYear"}function $h(t){return t?"getUTCMonth":"getMonth"}function Jh(t){return t?"getUTCDate":"getDate"}function Qh(t){return t?"getUTCHours":"getHours"}function tc(t){return t?"getUTCMinutes":"getMinutes"}function ec(t){return t?"getUTCSeconds":"getSeconds"}function nc(t){return t?"getUTCSeconds":"getSeconds"}function ic(t){return t?"setUTCFullYear":"setFullYear"}function rc(t){return t?"setUTCMonth":"setMonth"}function oc(t){return t?"setUTCDate":"setDate"}function ac(t){return t?"setUTCHours":"setHours"}function sc(t){return t?"setUTCMinutes":"setMinutes"}function lc(t){return t?"setUTCSeconds":"setSeconds"}function uc(t){return t?"setUTCSeconds":"setSeconds"}function hc(t){if(!cr(t))return H(t)?t:"-";var e=(t+"").split(".");return e[0].replace(/(\d{1,3})(?=(?:\d{3})+(?!\d))/g,"$1,")+(e.length>1?"."+e[1]:"")}function cc(t,e){return t=(t||"").toLowerCase().replace(/-(.)/g,(function(t,e){return e.toUpperCase()})),e&&t&&(t=t.charAt(0).toUpperCase()+t.slice(1)),t}var pc=it,dc=/([&<>"'])/g,fc={"&":"&","<":"<",">":">",'"':""","'":"'"};function gc(t){return null==t?"":(t+"").replace(dc,(function(t,e){return fc[e]}))}function yc(t,e,n){function i(t){return t&&ot(t)?t:"-"}function r(t){return!(null==t||isNaN(t)||!isFinite(t))}var o="time"===e,a=t instanceof Date;if(o||a){var s=o?rr(t):t;if(!isNaN(+s))return Zh(s,"yyyy-MM-dd hh:mm:ss",n);if(a)return"-"}if("ordinal"===e)return W(t)?i(t):Y(t)&&r(t)?t+"":"-";var l=hr(t);return r(l)?hc(l):W(t)?i(t):"-"}var vc=["a","b","c","d","e","f","g"],mc=function(t,e){return"{"+t+(null==e?"":e)+"}"};function _c(t,e,n){F(e)||(e=[e]);var i=e.length;if(!i)return"";for(var r=e[0].$vars||[],o=0;o':'':{renderMode:o,content:"{"+(n.markerId||"markerX")+"|} ",style:"subItem"===r?{width:4,height:4,borderRadius:2,backgroundColor:i}:{width:10,height:10,borderRadius:5,backgroundColor:i}}:""}function bc(t,e){return e=e||"transparent",H(t)?t:X(t)&&t.colorStops&&(t.colorStops[0]||{}).color||e}function wc(t,e){if("_blank"===e||"blank"===e){var n=window.open();n.opener=null,n.location.href=t}else window.open(t,e)}var Sc=P,Mc=["left","right","top","bottom","width","height"],Ic=[["width","left","right"],["height","top","bottom"]];function Tc(t,e,n,i,r){var o=0,a=0;null==i&&(i=1/0),null==r&&(r=1/0);var s=0;e.eachChild((function(l,u){var h,c,p=l.getBoundingRect(),d=e.childAt(u+1),f=d&&d.getBoundingRect();if("horizontal"===t){var g=p.width+(f?-f.x+p.x:0);(h=o+g)>i||l.newline?(o=0,h=g,a+=s+n,s=p.height):s=Math.max(s,p.height)}else{var y=p.height+(f?-f.y+p.y:0);(c=a+y)>r||l.newline?(o+=s+n,a=0,c=y,s=p.width):s=Math.max(s,p.width)}l.newline||(l.x=o,l.y=a,l.markRedraw(),"horizontal"===t?o=h+n:a=c+n)}))}var Cc=Tc;V(Tc,"vertical"),V(Tc,"horizontal");function Ac(t,e,n){n=pc(n||0);var i=e.width,r=e.height,o=Zi(t.left,i),a=Zi(t.top,r),s=Zi(t.right,i),l=Zi(t.bottom,r),u=Zi(t.width,i),h=Zi(t.height,r),c=n[2]+n[0],p=n[1]+n[3],d=t.aspect;switch(isNaN(u)&&(u=i-s-p-o),isNaN(h)&&(h=r-l-c-a),null!=d&&(isNaN(u)&&isNaN(h)&&(d>i/r?u=.8*i:h=.8*r),isNaN(u)&&(u=d*h),isNaN(h)&&(h=u/d)),isNaN(o)&&(o=i-s-u-p),isNaN(a)&&(a=r-l-h-c),t.left||t.right){case"center":o=i/2-u/2-n[3];break;case"right":o=i-u-p}switch(t.top||t.bottom){case"middle":case"center":a=r/2-h/2-n[0];break;case"bottom":a=r-h-c}o=o||0,a=a||0,isNaN(u)&&(u=i-p-o-(s||0)),isNaN(h)&&(h=r-c-a-(l||0));var f=new Rn(o+n[3],a+n[0],u,h);return f.margin=n,f}function Dc(t,e,n,i,r){var o=!r||!r.hv||r.hv[0],a=!r||!r.hv||r.hv[1],s=r&&r.boundingMode||"all";if(o||a){var l;if("raw"===s)l="group"===t.type?new Rn(0,0,+e.width||0,+e.height||0):t.getBoundingRect();else if(l=t.getBoundingRect(),t.needLocalTransform()){var u=t.getLocalTransform();(l=l.clone()).applyTransform(u)}var h=Ac(T({width:l.width,height:l.height},e),n,i),c=o?h.x-l.x:0,p=a?h.y-l.y:0;"raw"===s?(t.x=c,t.y=p):(t.x+=c,t.y+=p),t.markRedraw()}}function Lc(t){var e=t.layoutMode||t.constructor.layoutMode;return X(e)?e:e?{type:e}:null}function kc(t,e,n){var i=n&&n.ignoreSize;!F(i)&&(i=[i,i]);var r=a(Ic[0],0),o=a(Ic[1],1);function a(n,r){var o={},a=0,u={},h=0;if(Sc(n,(function(e){u[e]=t[e]})),Sc(n,(function(t){s(e,t)&&(o[t]=u[t]=e[t]),l(o,t)&&a++,l(u,t)&&h++})),i[r])return l(e,n[1])?u[n[2]]=null:l(e,n[2])&&(u[n[1]]=null),u;if(2!==h&&a){if(a>=2)return o;for(var c=0;c=0;a--)o=S(o,n[a],!0);e.defaultOption=o}return e.defaultOption},e.prototype.getReferringComponents=function(t,e){var n=t+"Index",i=t+"Id";return Nr(this.ecModel,t,{index:this.get(n,!0),id:this.get(i,!0)},e)},e.prototype.getBoxLayoutParams=function(){var t=this;return{left:t.get("left"),top:t.get("top"),right:t.get("right"),bottom:t.get("bottom"),width:t.get("width"),height:t.get("height")}},e.protoInitialize=function(){var t=e.prototype;t.type="component",t.id="",t.name="",t.mainType="",t.subType="",t.componentIndex=0}(),e}(Sh);Yr(Nc,Sh),jr(Nc),function(t){var e={};t.registerSubTypeDefaulter=function(t,n){var i=Gr(t);e[i.main]=n},t.determineSubType=function(n,i){var r=i.type;if(!r){var o=Gr(n).main;t.hasSubTypes(n)&&e[o]&&(r=e[o](i))}return r}}(Nc),function(t,e){function n(t,e){return t[e]||(t[e]={predecessor:[],successor:[]}),t[e]}t.topologicalTravel=function(t,i,r,o){if(t.length){var a=function(t){var i={},r=[];return P(t,(function(o){var a=n(i,o),s=function(t,e){var n=[];return P(t,(function(t){A(e,t)>=0&&n.push(t)})),n}(a.originalDeps=e(o),t);a.entryCount=s.length,0===a.entryCount&&r.push(o),P(s,(function(t){A(a.predecessor,t)<0&&a.predecessor.push(t);var e=n(i,t);A(e.successor,t)<0&&e.successor.push(o)}))})),{graph:i,noEntryList:r}}(i),s=a.graph,l=a.noEntryList,u={};for(P(t,(function(t){u[t]=!0}));l.length;){var h=l.pop(),c=s[h],p=!!u[h];p&&(r.call(o,h,c.originalDeps.slice()),delete u[h]),P(c.successor,p?f:d)}P(u,(function(){var t="";throw new Error(t)}))}function d(t){s[t].entryCount--,0===s[t].entryCount&&l.push(t)}function f(t){u[t]=!0,d(t)}}}(Nc,(function(t){var e=[];P(Nc.getClassesByMainType(t),(function(t){e=e.concat(t.dependencies||t.prototype.dependencies||[])})),e=O(e,(function(t){return Gr(t).main})),"dataset"!==t&&A(e,"dataset")<=0&&e.unshift("dataset");return e}));var Ec="";"undefined"!=typeof navigator&&(Ec=navigator.platform||"");var zc="rgba(0, 0, 0, 0.2)",Bc={darkMode:"auto",color:["#5470c6","#91cc75","#fac858","#ee6666","#73c0de","#3ba272","#fc8452","#9a60b4","#ea7ccc"],gradientColor:["#f6efa6","#d88273","#bf444c"],aria:{decal:{decals:[{color:zc,dashArrayX:[1,0],dashArrayY:[2,5],symbolSize:1,rotation:Math.PI/6},{color:zc,symbol:"circle",dashArrayX:[[8,8],[0,8,8,0]],dashArrayY:[6,0],symbolSize:.8},{color:zc,dashArrayX:[1,0],dashArrayY:[4,3],rotation:-Math.PI/4},{color:zc,dashArrayX:[[6,6],[0,6,6,0]],dashArrayY:[6,0]},{color:zc,dashArrayX:[[1,0],[1,6]],dashArrayY:[1,0,6,0],rotation:Math.PI/4},{color:zc,symbol:"triangle",dashArrayX:[[9,9],[0,9,9,0]],dashArrayY:[7,2],symbolSize:.75}]}},textStyle:{fontFamily:Ec.match(/^Win/)?"Microsoft YaHei":"sans-serif",fontSize:12,fontStyle:"normal",fontWeight:"normal"},blendMode:null,stateAnimation:{duration:300,easing:"cubicOut"},animation:"auto",animationDuration:1e3,animationDurationUpdate:500,animationEasing:"cubicInOut",animationEasingUpdate:"cubicInOut",animationThreshold:2e3,progressiveThreshold:3e3,progressive:400,hoverLayerThreshold:3e3,useUTC:!1},Vc=ht(["tooltip","label","itemName","itemId","seriesName"]),Fc="original",Gc="arrayRows",Hc="objectRows",Wc="keyedColumns",Yc="typedArray",Xc="unknown",Uc="column",Zc="row",jc=1,qc=2,Kc=3,$c=Lr();function Jc(t,e,n){var i={},r=tp(e);if(!r||!t)return i;var o,a,s=[],l=[],u=e.ecModel,h=$c(u).datasetMap,c=r.uid+"_"+n.seriesLayoutBy;P(t=t.slice(),(function(e,n){var r=X(e)?e:t[n]={name:e};"ordinal"===r.type&&null==o&&(o=n,a=f(r)),i[r.name]=[]}));var p=h.get(c)||h.set(c,{categoryWayDim:a,valueWayDim:0});function d(t,e,n){for(var i=0;ie)return t[i];return t[n-1]}(i,a):n;if((h=h||n)&&h.length){var c=h[l];return r&&(u[r]=c),s.paletteIdx=(l+1)%h.length,c}}var pp=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return n(e,t),e.prototype.init=function(t,e,n,i,r,o){i=i||{},this.option=null,this._theme=new Sh(i),this._locale=new Sh(r),this._optionManager=o},e.prototype.setOption=function(t,e,n){var i=gp(e);this._optionManager.setOption(t,n,i),this._resetOption(null,i)},e.prototype.resetOption=function(t,e){return this._resetOption(t,gp(e))},e.prototype._resetOption=function(t,e){var n=!1,i=this._optionManager;if(!t||"recreate"===t){var r=i.mountOption("recreate"===t);this.option&&"recreate"!==t?(this.restoreData(),this._mergeOption(r,e)):ap(this,r),n=!0}if("timeline"!==t&&"media"!==t||this.restoreData(),!t||"recreate"===t||"timeline"===t){var o=i.getTimelineOption(this);o&&(n=!0,this._mergeOption(o,e))}if(!t||"recreate"===t||"media"===t){var a=i.getMediaOption(this);a.length&&P(a,(function(t){n=!0,this._mergeOption(t,e)}),this)}return n},e.prototype.mergeOption=function(t){this._mergeOption(t,null)},e.prototype._mergeOption=function(t,e){var n=this.option,i=this._componentsMap,r=this._componentsCount,o=[],a=ht(),s=e&&e.replaceMergeMainTypeMap;$c(this).datasetMap=ht(),P(t,(function(t,e){null!=t&&(Nc.hasClass(e)?e&&(o.push(e),a.set(e,!0)):n[e]=null==n[e]?w(t):S(n[e],t,!0))})),s&&s.each((function(t,e){Nc.hasClass(e)&&!a.get(e)&&(o.push(e),a.set(e,!0))})),Nc.topologicalTravel(o,Nc.getAllClassMainTypes(),(function(e){var o=function(t,e,n){var i=ip.get(e);if(!i)return n;var r=i(t);return r?n.concat(r):n}(this,e,_r(t[e])),a=i.get(e),l=a?s&&s.get(e)?"replaceMerge":"normalMerge":"replaceAll",u=Sr(a,o,l);(function(t,e,n){P(t,(function(t){var i=t.newOption;X(i)&&(t.keyInfo.mainType=e,t.keyInfo.subType=function(t,e,n,i){return e.type?e.type:n?n.subType:i.determineSubType(t,e)}(e,i,t.existing,n))}))})(u,e,Nc),n[e]=null,i.set(e,null),r.set(e,0);var h=[],c=[],p=0;P(u,(function(t,n){var i=t.existing,r=t.newOption;if(r){var o=Nc.getClass(e,t.keyInfo.subType,!0);if(i&&i.constructor===o)i.name=t.keyInfo.name,i.mergeOption(r,this),i.optionUpdated(r,!1);else{var a=I({componentIndex:n},t.keyInfo);I(i=new o(r,this,this,a),a),t.brandNew&&(i.__requireNewView=!0),i.init(r,this,this),i.optionUpdated(null,!0)}}else i&&(i.mergeOption({},this),i.optionUpdated({},!1));i?(h.push(i.option),c.push(i),p++):(h.push(void 0),c.push(void 0))}),this),n[e]=h,i.set(e,c),r.set(e,p),"series"===e&&rp(this)}),this),this._seriesIndices||rp(this)},e.prototype.getOption=function(){var t=w(this.option);return P(t,(function(e,n){if(Nc.hasClass(n)){for(var i=_r(e),r=i.length,o=!1,a=r-1;a>=0;a--)i[a]&&!Ar(i[a])?o=!0:(i[a]=null,!o&&r--);i.length=r,t[n]=i}})),delete t["\0_ec_inner"],t},e.prototype.getTheme=function(){return this._theme},e.prototype.getLocaleModel=function(){return this._locale},e.prototype.getLocale=function(t){return this.getLocaleModel().get(t)},e.prototype.setUpdatePayload=function(t){this._payload=t},e.prototype.getUpdatePayload=function(){return this._payload},e.prototype.getComponent=function(t,e){var n=this._componentsMap.get(t);if(n){var i=n[e||0];if(i)return i;if(null==e)for(var r=0;r=e:"max"===n?t<=e:t===e})(i[a],t,o)||(r=!1)}})),r}var Sp=P,Mp=X,Ip=["areaStyle","lineStyle","nodeStyle","linkStyle","chordStyle","label","labelLine"];function Tp(t){var e=t&&t.itemStyle;if(e)for(var n=0,i=Ip.length;n=0;f--){var g=t[f];if(s||(c=g.data.rawIndexOf(g.stackedByDimension,h)),c>=0){var y=g.data.getByRawIndex(g.stackResultDimension,c);if(p>=0&&y>0||p<=0&&y<0){p+=y,d=y;break}}}return i[0]=p,i[1]=d,i}));a.hostModel.setData(l),e.data=l}))}var Yp,Xp,Up,Zp,jp,qp=function(t){this.data=t.data||(t.sourceFormat===Wc?{}:[]),this.sourceFormat=t.sourceFormat||Xc,this.seriesLayoutBy=t.seriesLayoutBy||Uc,this.startIndex=t.startIndex||0,this.dimensionsDefine=t.dimensionsDefine,this.dimensionsDetectedCount=t.dimensionsDetectedCount,this.encodeDefine=t.encodeDefine,this.metaRawOption=t.metaRawOption};function Kp(t){return t instanceof qp}function $p(t,e,n,i){n=n||td(t);var r=e.seriesLayoutBy,o=function(t,e,n,i,r){var o,a;if(!t)return{dimensionsDefine:ed(r),startIndex:a,dimensionsDetectedCount:o};if(e===Gc){var s=t;"auto"===i||null==i?nd((function(t){null!=t&&"-"!==t&&(H(t)?null==a&&(a=1):a=0)}),n,s,10):a=Y(i)?i:i?1:0,r||1!==a||(r=[],nd((function(t,e){r[e]=null!=t?t+"":""}),n,s,1/0)),o=r?r.length:n===Zc?s.length:s[0]?s[0].length:null}else if(e===Hc)r||(r=function(t){var e,n=0;for(;nu&&(u=d)}s[0]=l,s[1]=u}},i=function(){return this._data?this._data.length/this._dimSize:0};function r(t){for(var e=0;e=1)&&(t=1),t}a===l&&s===u||(e="reset"),(this._dirty||"reset"===e)&&(this._dirty=!1,o=this._doReset(i)),this._modBy=l,this._modDataCount=u;var c=t&&t.step;if(this._dueEnd=n?n._outputDueEnd:this._count?this._count(this.context):1/0,this._progress){var p=this._dueIndex,d=Math.min(null!=c?this._dueIndex+c:1/0,this._dueEnd);if(!i&&(o||p1&&i>0?s:a}};return o;function a(){return e=t?null:oe},gte:function(t,e){return t>=e}},Id=function(){function t(t,e){if("number"!=typeof e){var n="";0,yr(n)}this._opFn=Md[t],this._rvalFloat=hr(e)}return t.prototype.evaluate=function(t){return"number"==typeof t?this._opFn(t,this._rvalFloat):this._opFn(hr(t),this._rvalFloat)},t}(),Td=function(){function t(t,e){var n="desc"===t;this._resultLT=n?1:-1,null==e&&(e=n?"min":"max"),this._incomparable="min"===e?-1/0:1/0}return t.prototype.evaluate=function(t,e){var n=typeof t,i=typeof e,r="number"===n?t:hr(t),o="number"===i?e:hr(e),a=isNaN(r),s=isNaN(o);if(a&&(r=this._incomparable),s&&(o=this._incomparable),a&&s){var l="string"===n,u="string"===i;l&&(r=u?t:0),u&&(o=l?e:0)}return ro?-this._resultLT:0},t}(),Cd=function(){function t(t,e){this._rval=e,this._isEQ=t,this._rvalTypeof=typeof e,this._rvalFloat=hr(e)}return t.prototype.evaluate=function(t){var e=t===this._rval;if(!e){var n=typeof t;n===this._rvalTypeof||"number"!==n&&"number"!==this._rvalTypeof||(e=hr(t)===this._rvalFloat)}return this._isEQ?e:!e},t}();function Ad(t,e){return"eq"===t||"ne"===t?new Cd("eq"===t,e):dt(Md,t)?new Id(t,e):null}var Dd=function(){function t(){}return t.prototype.getRawData=function(){throw new Error("not supported")},t.prototype.getRawDataItem=function(t){throw new Error("not supported")},t.prototype.cloneRawData=function(){},t.prototype.getDimensionInfo=function(t){},t.prototype.cloneAllDimensionInfo=function(){},t.prototype.count=function(){},t.prototype.retrieveValue=function(t,e){},t.prototype.retrieveValueFromItem=function(t,e){},t.prototype.convertValue=function(t,e){return bd(t,e)},t}();function Ld(t){var e=t.sourceFormat;if(!Ed(e)){var n="";0,yr(n)}return t.data}function kd(t){var e=t.sourceFormat,n=t.data;if(!Ed(e)){var i="";0,yr(i)}if(e===Gc){for(var r=[],o=0,a=n.length;o9e10&&(this._versionSignBase=0)},t.prototype._getVersionSign=function(){return this._sourceHost.uid+"_"+this._versionSignBase},t.prototype.prepareSource=function(){this._isDirty()&&this._createSource()},t.prototype._createSource=function(){this._setLocalSource([],[]);var t,e,n=this._sourceHost,i=this._getUpstreamSourceManagers(),r=!!i.length;if(Vd(n)){var o=n,a=void 0,s=void 0,l=void 0;if(r){var u=i[0];u.prepareSource(),a=(l=u.getSource()).data,s=l.sourceFormat,e=[u._getVersionSign()]}else s=Z(a=o.get("data",!0))?Yc:Fc,e=[];var h=this._getSourceMetaRawOption(),c=l?l.metaRawOption:null;t=[$p(a,{seriesLayoutBy:tt(h.seriesLayoutBy,c?c.seriesLayoutBy:null),sourceHeader:tt(h.sourceHeader,c?c.sourceHeader:null),dimensions:tt(h.dimensions,c?c.dimensions:null)},s,o.get("encode",!0))]}else{var p=n;if(r){var d=this._applyTransform(i);t=d.sourceList,e=d.upstreamSignList}else{t=[$p(p.get("source",!0),this._getSourceMetaRawOption(),null,null)],e=[]}}this._setLocalSource(t,e)},t.prototype._applyTransform=function(t){var e,n=this._sourceHost,i=n.get("transform",!0),r=n.get("fromTransformResult",!0);if(null!=r){var o="";1!==t.length&&Fd(o)}var a,s=[],l=[];return P(t,(function(t){t.prepareSource();var e=t.getSource(r||0),n="";null==r||e||Fd(n),s.push(e),l.push(t._getVersionSign())})),i?e=function(t,e,n){var i=_r(t),r=i.length,o="";r||yr(o);for(var a=0,s=r;a1||e>0&&!t.noHeader,i=0;P(t.blocks,(function(t){Xd(t).planLayout(t);var e=t.__gapLevelBetweenSubBlocks;e>=i&&(i=e+(!n||e&&("section"!==t.type||t.noHeader)?0:1))})),t.__gapLevelBetweenSubBlocks=i},build:function(t,e,n,i){var r=e.noHeader,o=jd(e),a=function(t,e,n,i){var r=[],o=e.blocks||[];rt(!o||F(o)),o=o||[];var a=t.orderMode;if(e.sortBlocks&&a){o=o.slice();var s={valueAsc:"asc",valueDesc:"desc"};if(dt(s,a)){var l=new Td(s[a],null);o.sort((function(t,e){return l.evaluate(t.sortParam,e.sortParam)}))}else"seriesDesc"===a&&o.reverse()}var u=jd(e);if(P(o,(function(e,n){var o=Xd(e).build(t,e,n>0?u.html:0,i);null!=o&&r.push(o)})),!r.length)return;return"richText"===t.renderMode?r.join(u.richText):qd(r.join(""),n)}(t,e,r?n:o.html,i);if(r)return a;var s=yc(e.header,"ordinal",t.useUTC),l=Gd(i,t.renderMode).nameStyle;return"richText"===t.renderMode?Kd(t,s,l)+o.richText+a:qd('
    '+gc(s)+"
    "+a,n)}},nameValue:{planLayout:function(t){t.__gapLevelBetweenSubBlocks=0},build:function(t,e,n,i){var r=t.renderMode,o=e.noName,a=e.noValue,s=!e.markerType,l=e.name,u=e.value,h=t.useUTC;if(!o||!a){var c=s?"":t.markupStyleCreator.makeTooltipMarker(e.markerType,e.markerColor||"#333",r),p=o?"":yc(l,"ordinal",h),d=e.valueType,f=a?[]:F(u)?O(u,(function(t,e){return yc(t,F(d)?d[e]:d,h)})):[yc(u,F(d)?d[0]:d,h)],g=!s||!o,y=!s&&o,v=Gd(i,r),m=v.nameStyle,_=v.valueStyle;return"richText"===r?(s?"":c)+(o?"":Kd(t,p,m))+(a?"":function(t,e,n,i,r){var o=[r],a=i?10:20;return n&&o.push({padding:[0,0,0,a],align:"right"}),t.markupStyleCreator.wrapRichTextStyle(e.join(" "),o)}(t,f,g,y,_)):qd((s?"":c)+(o?"":function(t,e,n){return''+gc(t)+""}(p,!s,m))+(a?"":function(t,e,n,i){var r=n?"10px":"20px";return''+O(t,(function(t){return gc(t)})).join("  ")+""}(f,g,y,_)),n)}}}};function Zd(t,e,n,i,r,o){if(t){var a=Xd(t);a.planLayout(t);var s={useUTC:r,renderMode:n,orderMode:i,markupStyleCreator:e};return a.build(s,t,0,o)}}function jd(t){var e=t.__gapLevelBetweenSubBlocks;return{html:Hd[e],richText:Wd[e]}}function qd(t,e){return'
    '+t+'
    '}function Kd(t,e,n){return t.markupStyleCreator.wrapRichTextStyle(e,n)}function $d(t,e){return bc(t.getData().getItemVisual(e,"style")[t.visualDrawType])}function Jd(t,e){var n=t.get("padding");return null!=n?n:"richText"===e?[8,10]:10}var Qd=function(){function t(){this.richTextStyles={},this._nextStyleNameId=pr()}return t.prototype._generateStyleName=function(){return"__EC_aUTo_"+this._nextStyleNameId++},t.prototype.makeTooltipMarker=function(t,e,n){var i="richText"===n?this._generateStyleName():null,r=xc({color:e,type:t,renderMode:n,markerId:i});return H(r)?r:(this.richTextStyles[i]=r.style,r.content)},t.prototype.wrapRichTextStyle=function(t,e){var n={};F(e)?P(e,(function(t){return I(n,t)})):I(n,e);var i=this._generateStyleName();return this.richTextStyles[i]=n,"{"+i+"|"+t+"}"},t}();function tf(t){var e,n,i,r,o=t.series,a=t.dataIndex,s=t.multipleSeries,l=o.getData(),u=l.mapDimensionsAll("defaultedTooltip"),h=u.length,c=o.getRawValue(a),p=F(c),d=$d(o,a);if(h>1||p&&!h){var f=function(t,e,n,i,r){var o=e.getData(),a=R(t,(function(t,e,n){var i=o.getDimensionInfo(n);return t||i&&!1!==i.tooltip&&null!=i.displayName}),!1),s=[],l=[],u=[];function h(t,e){var n=o.getDimensionInfo(e);n&&!1!==n.otherDims.tooltip&&(a?u.push(Yd("nameValue",{markerType:"subItem",markerColor:r,name:n.displayName,value:t,valueType:n.type})):(s.push(t),l.push(n.type)))}return i.length?P(i,(function(t){h(fd(o,n,t),t)})):P(t,h),{inlineValues:s,inlineValueTypes:l,blocks:u}}(c,o,a,u,d);e=f.inlineValues,n=f.inlineValueTypes,i=f.blocks,r=f.inlineValues[0]}else if(h){var g=l.getDimensionInfo(u[0]);r=e=fd(l,a,u[0]),n=g.type}else r=e=p?c[0]:c;var y=Cr(o),v=y&&o.name||"",m=l.getName(a),_=s?v:m;return Yd("section",{header:v,noHeader:s||!y,sortParam:r,blocks:[Yd("nameValue",{markerType:"item",markerColor:d,name:_,noName:!ot(_),value:e,valueType:n})].concat(i||[])})}var ef=Lr();function nf(t,e){return t.getName(e)||t.getId(e)}var rf=function(t){function e(){var e=null!==t&&t.apply(this,arguments)||this;return e._selectedDataIndicesMap={},e}return n(e,t),e.prototype.init=function(t,e,n){this.seriesIndex=this.componentIndex,this.dataTask=md({count:af,reset:sf}),this.dataTask.context={model:this},this.mergeDefaultAndTheme(t,n),(ef(this).sourceManager=new zd(this)).prepareSource();var i=this.getInitialData(t,n);uf(i,this),this.dataTask.context.data=i,ef(this).dataBeforeProcessed=i,of(this),this._initSelectedMapFromData(i)},e.prototype.mergeDefaultAndTheme=function(t,e){var n=Lc(this),i=n?Pc(t):{},r=this.subType;Nc.hasClass(r)&&(r+="Series"),S(t,e.getTheme().get(this.subType)),S(t,this.getDefaultOption()),xr(t,"label",["show"]),this.fillDataTextStyle(t.data),n&&kc(t,i,n)},e.prototype.mergeOption=function(t,e){t=S(this.option,t,!0),this.fillDataTextStyle(t.data);var n=Lc(this);n&&kc(this.option,t,n);var i=ef(this).sourceManager;i.dirty(),i.prepareSource();var r=this.getInitialData(t,e);uf(r,this),this.dataTask.dirty(),this.dataTask.context.data=r,ef(this).dataBeforeProcessed=r,of(this),this._initSelectedMapFromData(r)},e.prototype.fillDataTextStyle=function(t){if(t&&!Z(t))for(var e=["show"],n=0;nthis.getShallow("animationThreshold")&&(t=!1),!!t},e.prototype.restoreData=function(){this.dataTask.dirty()},e.prototype.getColorFromPalette=function(t,e,n){var i=this.ecModel,r=up.prototype.getColorFromPalette.call(this,t,e,n);return r||(r=i.getColorFromPalette(t,e,n)),r},e.prototype.coordDimToDataDim=function(t){return this.getRawData().mapDimensionsAll(t)},e.prototype.getProgressive=function(){return this.get("progressive")},e.prototype.getProgressiveThreshold=function(){return this.get("progressiveThreshold")},e.prototype.select=function(t,e){this._innerSelect(this.getData(e),t)},e.prototype.unselect=function(t,e){var n=this.option.selectedMap;if(n)for(var i=this.getData(e),r=0;r=0&&n.push(r)}return n},e.prototype.isSelected=function(t,e){var n=this.option.selectedMap;return n&&n[nf(this.getData(e),t)]||!1},e.prototype._innerSelect=function(t,e){var n,i,r=this.option.selectedMode,o=e.length;if(r&&o)if("multiple"===r)for(var a=this.option.selectedMap||(this.option.selectedMap={}),s=0;s0&&this._innerSelect(t,e)}},e.registerClass=function(t){return Nc.registerClass(t)},e.protoInitialize=function(){var t=e.prototype;t.type="series.__base__",t.seriesIndex=0,t.useColorPaletteOnData=!1,t.ignoreStyleOnData=!1,t.hasSymbolVisual=!1,t.defaultSymbol="circle",t.visualStyleAccessPath="itemStyle",t.visualDrawType="fill"}(),e}(Nc);function of(t){var e=t.name;Cr(t)||(t.name=function(t){var e=t.getRawData(),n=e.mapDimensionsAll("seriesName"),i=[];return P(n,(function(t){var n=e.getDimensionInfo(t);n.displayName&&i.push(n.displayName)})),i.join(" ")}(t)||e)}function af(t){return t.model.getRawData().count()}function sf(t){var e=t.model;return e.setData(e.getRawData().cloneShallow()),lf}function lf(t,e){e.outputData&&t.end>e.outputData.count()&&e.model.getRawData().cloneShallow(e.outputData)}function uf(t,e){P(r(t.CHANGABLE_METHODS,t.DOWNSAMPLE_METHODS),(function(n){t.wrapMethod(n,V(hf,e))}))}function hf(t,e){var n=cf(t);return n&&n.setOutputEnd((e||this).count()),e}function cf(t){var e=(t.ecModel||{}).scheduler,n=e&&e.getPipeline(t.uid);if(n){var i=n.currentTask;if(i){var r=i.agentStubMap;r&&(i=r.get(t.uid))}return i}}L(rf,yd),L(rf,up),Yr(rf,Nc);var pf=function(){function t(){this.group=new zi,this.uid=Ih("viewComponent")}return t.prototype.init=function(t,e){},t.prototype.render=function(t,e,n,i){},t.prototype.dispose=function(t,e){},t.prototype.updateView=function(t,e,n,i){},t.prototype.updateLayout=function(t,e,n,i){},t.prototype.updateVisual=function(t,e,n,i){},t.prototype.blurSeries=function(t,e){},t}();function df(){var t=Lr();return function(e){var n=t(e),i=e.pipelineContext,r=!!n.large,o=!!n.progressiveRender,a=n.large=!(!i||!i.large),s=n.progressiveRender=!(!i||!i.progressiveRender);return!(r===a&&o===s)&&"reset"}}Hr(pf),jr(pf);var ff=Lr(),gf=df(),yf=function(){function t(){this.group=new zi,this.uid=Ih("viewChart"),this.renderTask=md({plan:_f,reset:xf}),this.renderTask.context={view:this}}return t.prototype.init=function(t,e){},t.prototype.render=function(t,e,n,i){},t.prototype.highlight=function(t,e,n,i){mf(t.getData(),i,"emphasis")},t.prototype.downplay=function(t,e,n,i){mf(t.getData(),i,"normal")},t.prototype.remove=function(t,e){this.group.removeAll()},t.prototype.dispose=function(t,e){},t.prototype.updateView=function(t,e,n,i){this.render(t,e,n,i)},t.prototype.updateLayout=function(t,e,n,i){this.render(t,e,n,i)},t.prototype.updateVisual=function(t,e,n,i){this.render(t,e,n,i)},t.markUpdateMethod=function(t,e){ff(t).updateMethod=e},t.protoInitialize=void(t.prototype.type="chart"),t}();function vf(t,e,n){t&&("emphasis"===e?Hs:Ws)(t,n)}function mf(t,e,n){var i=Dr(t,e),r=e&&null!=e.highlightKey?function(t){var e=ms[t];return null==e&&vs<=32&&(e=ms[t]=vs++),e}(e.highlightKey):null;null!=i?P(_r(i),(function(e){vf(t.getItemGraphicEl(e),n,r)})):t.eachItemGraphicEl((function(t){vf(t,n,r)}))}function _f(t){return gf(t.model)}function xf(t){var e=t.model,n=t.ecModel,i=t.api,r=t.payload,o=e.pipelineContext.progressiveRender,a=t.view,s=r&&ff(r).updateMethod,l=o?"incrementalPrepareRender":s&&a[s]?s:"render";return"render"!==l&&a[l](e,n,i,r),bf[l]}Hr(yf),jr(yf);var bf={incrementalPrepareRender:{progress:function(t,e){e.view.incrementalRender(t,e.model,e.ecModel,e.api,e.payload)}},render:{forceFirstProgress:!0,progress:function(t,e){e.view.render(e.model,e.ecModel,e.api,e.payload)}}},wf="\0__throttleOriginMethod",Sf="\0__throttleRate",Mf="\0__throttleType";function If(t,e,n){var i,r,o,a,s,l=0,u=0,h=null;function c(){u=(new Date).getTime(),h=null,t.apply(o,a||[])}e=e||0;var p=function(){for(var t=[],p=0;p=0?c():h=setTimeout(c,-r),l=i};return p.clear=function(){h&&(clearTimeout(h),h=null)},p.debounceNextCall=function(t){s=t},p}function Tf(t,e,n,i){var r=t[e];if(r){var o=r[wf]||r,a=r[Mf];if(r[Sf]!==n||a!==i){if(null==n||!i)return t[e]=o;(r=t[e]=If(o,n,"debounce"===i))[wf]=o,r[Mf]=i,r[Sf]=n}return r}}var Cf=Lr(),Af={itemStyle:qr(xh,!0),lineStyle:qr(vh,!0)},Df={lineStyle:"stroke",itemStyle:"fill"};function Lf(t,e){var n=t.visualStyleMapper||Af[e];return n||(console.warn("Unkown style type '"+e+"'."),Af.itemStyle)}function kf(t,e){var n=t.visualDrawType||Df[e];return n||(console.warn("Unkown style type '"+e+"'."),"fill")}var Pf={createOnAllSeries:!0,performRawSeries:!0,reset:function(t,e){var n=t.getData(),i=t.visualStyleAccessPath||"itemStyle",r=t.getModel(i),o=Lf(t,i)(r),a=r.getShallow("decal");a&&(n.setVisual("decal",a),a.dirty=!0);var s=kf(t,i),l=o[s],u=G(l)?l:null;if(o[s]&&!u||(o[s]=t.getColorFromPalette(t.name,null,e.getSeriesCount()),n.setVisual("colorFromPalette",!0)),n.setVisual("style",o),n.setVisual("drawType",s),!e.isSeriesFiltered(t)&&u)return n.setVisual("colorFromPalette",!1),{dataEach:function(e,n){var i=t.getDataParams(n),r=I({},o);r[s]=u(i),e.setItemVisual(n,"style",r)}}}},Of=new Sh,Rf={createOnAllSeries:!0,performRawSeries:!0,reset:function(t,e){if(!t.ignoreStyleOnData&&!e.isSeriesFiltered(t)){var n=t.getData(),i=t.visualStyleAccessPath||"itemStyle",r=Lf(t,i),o=n.getVisual("drawType");return{dataEach:n.hasItemOption?function(t,e){var n=t.getRawDataItem(e);if(n&&n[i]){Of.option=n[i];var a=r(Of);I(t.ensureUniqueItemVisual(e,"style"),a),Of.option.decal&&(t.setItemVisual(e,"decal",Of.option.decal),Of.option.decal.dirty=!0),o in a&&t.setItemVisual(e,"colorFromPalette",!1)}}:null}}}},Nf={performRawSeries:!0,overallReset:function(t){var e=ht();t.eachSeries((function(t){if(t.useColorPaletteOnData){var n=e.get(t.type);n||(n={},e.set(t.type,n)),Cf(t).scope=n}})),t.eachSeries((function(e){if(e.useColorPaletteOnData&&!t.isSeriesFiltered(e)){var n=e.getRawData(),i={},r=e.getData(),o=Cf(e).scope,a=e.visualStyleAccessPath||"itemStyle",s=kf(e,a);r.each((function(t){var e=r.getRawIndex(t);i[e]=t})),n.each((function(t){var a=i[t];if(r.getItemVisual(a,"colorFromPalette")){var l=r.ensureUniqueItemVisual(a,"style"),u=n.getName(t)||t+"",h=n.count();l[s]=e.getColorFromPalette(u,o,h)}}))}}))}},Ef=Math.PI;var zf=function(){function t(t,e,n,i){this._stageTaskMap=ht(),this.ecInstance=t,this.api=e,n=this._dataProcessorHandlers=n.slice(),i=this._visualHandlers=i.slice(),this._allHandlers=n.concat(i)}return t.prototype.restoreData=function(t,e){t.restoreData(e),this._stageTaskMap.each((function(t){var e=t.overallTask;e&&e.dirty()}))},t.prototype.getPerformArgs=function(t,e){if(t.__pipeline){var n=this._pipelineMap.get(t.__pipeline.id),i=n.context,r=!e&&n.progressiveEnabled&&(!i||i.progressiveRender)&&t.__idxInPipeline>n.blockIndex?n.step:null,o=i&&i.modDataCount;return{step:r,modBy:null!=o?Math.ceil(o/r):null,modDataCount:o}}},t.prototype.getPipeline=function(t){return this._pipelineMap.get(t)},t.prototype.updateStreamModes=function(t,e){var n=this._pipelineMap.get(t.uid),i=t.getData().count(),r=n.progressiveEnabled&&e.incrementalPrepareRender&&i>=n.threshold,o=t.get("large")&&i>=t.get("largeThreshold"),a="mod"===t.get("progressiveChunkMode")?i:null;t.pipelineContext=n.context={progressiveRender:r,modDataCount:a,large:o}},t.prototype.restorePipelines=function(t){var e=this,n=e._pipelineMap=ht();t.eachSeries((function(t){var i=t.getProgressive(),r=t.uid;n.set(r,{id:r,head:null,tail:null,threshold:t.getProgressiveThreshold(),progressiveEnabled:i&&!(t.preventIncremental&&t.preventIncremental()),blockIndex:-1,step:Math.round(i||700),count:0}),e._pipe(t,t.dataTask)}))},t.prototype.prepareStageTasks=function(){var t=this._stageTaskMap,e=this.api.getModel(),n=this.api;P(this._allHandlers,(function(i){var r=t.get(i.uid)||t.set(i.uid,{}),o="";rt(!(i.reset&&i.overallReset),o),i.reset&&this._createSeriesStageTask(i,r,e,n),i.overallReset&&this._createOverallStageTask(i,r,e,n)}),this)},t.prototype.prepareView=function(t,e,n,i){var r=t.renderTask,o=r.context;o.model=e,o.ecModel=n,o.api=i,r.__block=!t.incrementalPrepareRender,this._pipe(e,r)},t.prototype.performDataProcessorTasks=function(t,e){this._performStageTasks(this._dataProcessorHandlers,t,e,{block:!0})},t.prototype.performVisualTasks=function(t,e,n){this._performStageTasks(this._visualHandlers,t,e,n)},t.prototype._performStageTasks=function(t,e,n,i){i=i||{};var r=!1,o=this;function a(t,e){return t.setDirty&&(!t.dirtyMap||t.dirtyMap.get(e.__pipeline.id))}P(t,(function(t,s){if(!i.visualType||i.visualType===t.visualType){var l=o._stageTaskMap.get(t.uid),u=l.seriesTaskMap,h=l.overallTask;if(h){var c,p=h.agentStubMap;p.each((function(t){a(i,t)&&(t.dirty(),c=!0)})),c&&h.dirty(),o.updatePayload(h,n);var d=o.getPerformArgs(h,i.block);p.each((function(t){t.perform(d)})),h.perform(d)&&(r=!0)}else u&&u.each((function(s,l){a(i,s)&&s.dirty();var u=o.getPerformArgs(s,i.block);u.skip=!t.performRawSeries&&e.isSeriesFiltered(s.context.model),o.updatePayload(s,n),s.perform(u)&&(r=!0)}))}})),this.unfinished=r||this.unfinished},t.prototype.performSeriesTasks=function(t){var e;t.eachSeries((function(t){e=t.dataTask.perform()||e})),this.unfinished=e||this.unfinished},t.prototype.plan=function(){this._pipelineMap.each((function(t){var e=t.tail;do{if(e.__block){t.blockIndex=e.__idxInPipeline;break}e=e.getUpstream()}while(e)}))},t.prototype.updatePayload=function(t,e){"remain"!==e&&(t.context.payload=e)},t.prototype._createSeriesStageTask=function(t,e,n,i){var r=this,o=e.seriesTaskMap,a=e.seriesTaskMap=ht(),s=t.seriesType,l=t.getTargetSeries;function u(e){var s=e.uid,l=a.set(s,o&&o.get(s)||md({plan:Hf,reset:Wf,count:Uf}));l.context={model:e,ecModel:n,api:i,useClearVisual:t.isVisual&&!t.isLayout,plan:t.plan,reset:t.reset,scheduler:r},r._pipe(e,l)}t.createOnAllSeries?n.eachRawSeries(u):s?n.eachRawSeriesByType(s,u):l&&l(n,i).each(u)},t.prototype._createOverallStageTask=function(t,e,n,i){var r=this,o=e.overallTask=e.overallTask||md({reset:Bf});o.context={ecModel:n,api:i,overallReset:t.overallReset,scheduler:r};var a=o.agentStubMap,s=o.agentStubMap=ht(),l=t.seriesType,u=t.getTargetSeries,h=!0,c=!1,p="";function d(t){var e=t.uid,n=s.set(e,a&&a.get(e)||(c=!0,md({reset:Vf,onDirty:Gf})));n.context={model:t,overallProgress:h},n.agent=o,n.__block=h,r._pipe(t,n)}rt(!t.createOnAllSeries,p),l?n.eachRawSeriesByType(l,d):u?u(n,i).each(d):(h=!1,P(n.getSeries(),d)),c&&o.dirty()},t.prototype._pipe=function(t,e){var n=t.uid,i=this._pipelineMap.get(n);!i.head&&(i.head=e),i.tail&&i.tail.pipe(e),i.tail=e,e.__idxInPipeline=i.count++,e.__pipeline=i},t.wrapStageHandler=function(t,e){return G(t)&&(t={overallReset:t,seriesType:Zf(t)}),t.uid=Ih("stageHandler"),e&&(t.visualType=e),t},t}();function Bf(t){t.overallReset(t.ecModel,t.api,t.payload)}function Vf(t){return t.overallProgress&&Ff}function Ff(){this.agent.dirty(),this.getDownstream().dirty()}function Gf(){this.agent&&this.agent.dirty()}function Hf(t){return t.plan?t.plan(t.model,t.ecModel,t.api,t.payload):null}function Wf(t){t.useClearVisual&&t.data.clearAllVisual();var e=t.resetDefines=_r(t.reset(t.model,t.ecModel,t.api,t.payload));return e.length>1?O(e,(function(t,e){return Xf(e)})):Yf}var Yf=Xf(0);function Xf(t){return function(e,n){var i=n.data,r=n.resetDefines[t];if(r&&r.dataEach)for(var o=e.start;o0&&h===r.length-u.length){var c=r.slice(0,h);"data"!==c&&(e.mainType=c,e[u.toLowerCase()]=t,s=!0)}}a.hasOwnProperty(r)&&(n[r]=t,s=!0),s||(i[r]=t)}))}return{cptQuery:e,dataQuery:n,otherQuery:i}},t.prototype.filter=function(t,e){var n=this.eventInfo;if(!n)return!0;var i=n.targetEl,r=n.packedEvent,o=n.model,a=n.view;if(!o||!a)return!0;var s=e.cptQuery,l=e.dataQuery;return u(s,o,"mainType")&&u(s,o,"subType")&&u(s,o,"index","componentIndex")&&u(s,o,"name")&&u(s,o,"id")&&u(l,r,"name")&&u(l,r,"dataIndex")&&u(l,r,"dataType")&&(!a.filterForExposedEvent||a.filterForExposedEvent(t,e.otherQuery,i,r));function u(t,e,n,i){return null==t[n]||e[i||n]===t[n]}},t.prototype.afterTrigger=function(){this.eventInfo=null},t}(),cg={createOnAllSeries:!0,performRawSeries:!0,reset:function(t,e){var n=t.getData();if(t.legendSymbol&&n.setVisual("legendSymbol",t.legendSymbol),t.hasSymbolVisual){var i=t.get("symbol"),r=t.get("symbolSize"),o=t.get("symbolKeepAspect"),a=t.get("symbolRotate"),s=G(i),l=G(r),u=G(a),h=s||l||u,c=!s&&i?i:t.defaultSymbol,p=l?null:r,d=u?null:a;if(n.setVisual({legendSymbol:t.legendSymbol||c,symbol:c,symbolSize:p,symbolKeepAspect:o,symbolRotate:d}),!e.isSeriesFiltered(t))return{dataEach:h?function(e,n){var o=t.getRawValue(n),h=t.getDataParams(n);s&&e.setItemVisual(n,"symbol",i(o,h)),l&&e.setItemVisual(n,"symbolSize",r(o,h)),u&&e.setItemVisual(n,"symbolRotate",a(o,h))}:null}}}};function pg(t,e,n){switch(n){case"color":return t.getItemVisual(e,"style")[t.getVisual("drawType")];case"opacity":return t.getItemVisual(e,"style").opacity;case"symbol":case"symbolSize":case"liftZ":return t.getItemVisual(e,n);default:0}}function dg(t,e){switch(e){case"color":return t.getVisual("style")[t.getVisual("drawType")];case"opacity":return t.getVisual("style").opacity;case"symbol":case"symbolSize":case"liftZ":return t.getVisual(e);default:0}}function fg(t,e,n,i){switch(n){case"color":t.ensureUniqueItemVisual(e,"style")[t.getVisual("drawType")]=i,t.setItemVisual(e,"colorFromPalette",!1);break;case"opacity":t.ensureUniqueItemVisual(e,"style").opacity=i;break;case"symbol":case"symbolSize":case"liftZ":t.setItemVisual(e,n,i);break;default:0}}var gg=2*Math.PI,yg=Ca.CMD,vg=["top","right","bottom","left"];function mg(t,e,n,i,r){var o=n.width,a=n.height;switch(t){case"top":i.set(n.x+o/2,n.y-e),r.set(0,-1);break;case"bottom":i.set(n.x+o/2,n.y+a+e),r.set(0,1);break;case"left":i.set(n.x-e,n.y+a/2),r.set(-1,0);break;case"right":i.set(n.x+o+e,n.y+a/2),r.set(1,0)}}function _g(t,e,n,i,r,o,a,s,l){a-=t,s-=e;var u=Math.sqrt(a*a+s*s),h=(a/=u)*n+t,c=(s/=u)*n+e;if(Math.abs(i-r)%gg<1e-4)return l[0]=h,l[1]=c,u-n;if(o){var p=i;i=Pa(r),r=Pa(p)}else i=Pa(i),r=Pa(r);i>r&&(r+=gg);var d=Math.atan2(s,a);if(d<0&&(d+=gg),d>=i&&d<=r||d+gg>=i&&d+gg<=r)return l[0]=h,l[1]=c,u-n;var f=n*Math.cos(i)+t,g=n*Math.sin(i)+e,y=n*Math.cos(r)+t,v=n*Math.sin(r)+e,m=(f-a)*(f-a)+(g-s)*(g-s),_=(y-a)*(y-a)+(v-s)*(v-s);return m<_?(l[0]=f,l[1]=g,Math.sqrt(m)):(l[0]=y,l[1]=v,Math.sqrt(_))}function xg(t,e,n,i,r,o,a,s){var l=r-t,u=o-e,h=n-t,c=i-e,p=Math.sqrt(h*h+c*c),d=(l*(h/=p)+u*(c/=p))/p;s&&(d=Math.min(Math.max(d,0),1)),d*=p;var f=a[0]=t+d*h,g=a[1]=e+d*c;return Math.sqrt((f-r)*(f-r)+(g-o)*(g-o))}function bg(t,e,n,i,r,o,a){n<0&&(t+=n,n=-n),i<0&&(e+=i,i=-i);var s=t+n,l=e+i,u=a[0]=Math.min(Math.max(r,t),s),h=a[1]=Math.min(Math.max(o,e),l);return Math.sqrt((u-r)*(u-r)+(h-o)*(h-o))}var wg=[];function Sg(t,e,n){var i=bg(e.x,e.y,e.width,e.height,t.x,t.y,wg);return n.set(wg[0],wg[1]),i}function Mg(t,e,n){for(var i,r,o=0,a=0,s=0,l=0,u=1/0,h=e.data,c=t.x,p=t.y,d=0;d0){e=e/180*Math.PI,Ig.fromArray(t[0]),Tg.fromArray(t[1]),Cg.fromArray(t[2]),In.sub(Ag,Ig,Tg),In.sub(Dg,Cg,Tg);var n=Ag.len(),i=Dg.len();if(!(n<.001||i<.001)){Ag.scale(1/n),Dg.scale(1/i);var r=Ag.dot(Dg);if(Math.cos(e)1&&In.copy(Pg,Cg),Pg.toArray(t[1])}}}}function Rg(t,e,n){if(n<=180&&n>0){n=n/180*Math.PI,Ig.fromArray(t[0]),Tg.fromArray(t[1]),Cg.fromArray(t[2]),In.sub(Ag,Tg,Ig),In.sub(Dg,Cg,Tg);var i=Ag.len(),r=Dg.len();if(!(i<.001||r<.001))if(Ag.scale(1/i),Dg.scale(1/r),Ag.dot(e)=a)In.copy(Pg,Cg);else{Pg.scaleAndAdd(Dg,o/Math.tan(Math.PI/2-s));var l=Cg.x!==Tg.x?(Pg.x-Tg.x)/(Cg.x-Tg.x):(Pg.y-Tg.y)/(Cg.y-Tg.y);if(isNaN(l))return;l<0?In.copy(Pg,Tg):l>1&&In.copy(Pg,Cg)}Pg.toArray(t[1])}}}function Ng(t,e,n,i){var r="normal"===n,o=r?t:t.ensureState(n);o.ignore=e;var a=i.get("smooth");a&&!0===a&&(a=.3),o.shape=o.shape||{},a>0&&(o.shape.smooth=a);var s=i.getModel("lineStyle").getLineStyle();r?t.useStyle(s):o.style=s}function Eg(t,e){var n=e.smooth,i=e.points;if(i)if(t.moveTo(i[0][0],i[0][1]),n>0&&i.length>=3){var r=Lt(i[0],i[1]),o=Lt(i[1],i[2]);if(!r||!o)return t.lineTo(i[1][0],i[1][1]),void t.lineTo(i[2][0],i[2][1]);var a=Math.min(r,o)*n,s=Ot([],i[1],i[0],a/r),l=Ot([],i[1],i[2],a/o),u=Ot([],s,l,.5);t.bezierCurveTo(s[0],s[1],s[0],s[1],u[0],u[1]),t.bezierCurveTo(l[0],l[1],l[0],l[1],i[2][0],i[2][1])}else for(var h=1;h0&&o&&x(-h/a,0,a);var f,g,y=t[0],v=t[a-1];return m(),f<0&&b(-f,.8),g<0&&b(g,.8),m(),_(f,g,1),_(g,f,-1),m(),f<0&&w(-f),g<0&&w(g),u}function m(){f=y.rect[e]-i,g=r-v.rect[e]-v.rect[n]}function _(t,e,n){if(t<0){var i=Math.min(e,-t);if(i>0){x(i*n,0,a);var r=i+t;r<0&&b(-r*n,1)}else b(-t*n,1)}}function x(n,i,r){0!==n&&(u=!0);for(var o=i;o0)for(l=0;l0;l--){x(-(o[l-1]*c),l,a)}}}function w(t){var e=t<0?-1:1;t=Math.abs(t);for(var n=Math.ceil(t/(a-1)),i=0;i0?x(n,0,i+1):x(-n,a-i-1,a),(t-=n)<=0)return}}function Fg(t,e,n,i){return Vg(t,"y","height",e,n,i)}function Gg(t){if(t){for(var e=[],n=0;n=0&&n.attr(d.oldLayoutSelect),A(u,"emphasis")>=0&&n.attr(d.oldLayoutEmphasis)),Ou(n,s,e,a)}else if(n.attr(s),!uh(n).valueAnimation){var h=tt(n.style.opacity,1);n.style.opacity=0,Ru(n,{style:{opacity:h}},e,a)}if(d.oldLayout=s,n.states.select){var c=d.oldLayoutSelect={};Zg(c,s,jg),Zg(c,n.states.select,jg)}if(n.states.emphasis){var p=d.oldLayoutEmphasis={};Zg(p,s,jg),Zg(p,n.states.emphasis,jg)}ch(n,a,l,e,e)}if(i&&!i.ignore&&!i.invisible){r=(d=Ug(i)).oldLayout;var d,f={points:i.shape.points};r?(i.attr({shape:r}),Ou(i,{shape:f},e)):(i.setShape(f),i.style.strokePercent=0,Ru(i,{style:{strokePercent:1}},e)),d.oldLayout=f}},t}();function Kg(t,e){function n(e,n){var i=[];return e.eachComponent({mainType:"series",subType:t,query:n},(function(t){i.push(t.seriesIndex)})),i}P([[t+"ToggleSelect","toggleSelect"],[t+"Select","select"],[t+"UnSelect","unselect"]],(function(t){e(t[0],(function(e,i,r){e=I({},e),r.dispatchAction(I(e,{type:t[1],seriesIndex:n(i,e)}))}))}))}function $g(t,e,n,i,r){var o=t+e;n.isSilent(o)||i.eachComponent({mainType:"series",subType:"pie"},(function(t){for(var e=t.seriesIndex,i=r.selected,a=0;a0?(e=e||1,"dashed"===t?[4*e,2*e]:"dotted"===t?[e]:Y(t)?[t]:F(t)?t:null):null}var dy=new Ca(!0);function fy(t){var e=t.stroke;return!(null==e||"none"===e||!(t.lineWidth>0))}function gy(t){var e=t.fill;return null!=e&&"none"!==e}function yy(t,e){if(null!=e.fillOpacity&&1!==e.fillOpacity){var n=t.globalAlpha;t.globalAlpha=e.fillOpacity*e.opacity,t.fill(),t.globalAlpha=n}else t.fill()}function vy(t,e){if(null!=e.strokeOpacity&&1!==e.strokeOpacity){var n=t.globalAlpha;t.globalAlpha=e.strokeOpacity*e.opacity,t.stroke(),t.globalAlpha=n}else t.stroke()}function my(t,e,n){var i=to(e.image,e.__image,n);if(no(i)){var r=t.createPattern(i,e.repeat||"repeat");if("function"==typeof DOMMatrix){var o=new DOMMatrix;o.rotateSelf(0,0,(e.rotation||0)/Math.PI*180),o.scaleSelf(e.scaleX||1,e.scaleY||1),o.translateSelf(e.x||0,e.y||0),r.setTransform(o)}return r}}var _y=["shadowBlur","shadowOffsetX","shadowOffsetY"],xy=[["lineCap","butt"],["lineJoin","miter"],["miterLimit",10]];function by(t,e,n,i,r){var o=!1;if(!i&&e===(n=n||{}))return!1;(i||e.opacity!==n.opacity)&&(o||(My(t,r),o=!0),t.globalAlpha=null==e.opacity?vo.opacity:e.opacity),(i||e.blend!==n.blend)&&(o||(My(t,r),o=!0),t.globalCompositeOperation=e.blend||vo.blend);for(var a=0;a<_y.length;a++){var s=_y[a];(i||e[s]!==n[s])&&(o||(My(t,r),o=!0),t[s]=t.dpr*(e[s]||0))}return(i||e.shadowColor!==n.shadowColor)&&(o||(My(t,r),o=!0),t.shadowColor=e.shadowColor||vo.shadowColor),o}function wy(t,e,n,i,r){var o=Iy(e,r.inHover),a=i?null:n&&Iy(n,r.inHover)||{};if(o===a)return!1;var s=by(t,o,a,i,r);if((i||o.fill!==a.fill)&&(s||(My(t,r),s=!0),t.fillStyle=o.fill),(i||o.stroke!==a.stroke)&&(s||(My(t,r),s=!0),t.strokeStyle=o.stroke),(i||o.opacity!==a.opacity)&&(s||(My(t,r),s=!0),t.globalAlpha=null==o.opacity?1:o.opacity),e.hasStroke()){var l=o.lineWidth/(o.strokeNoScale&&e&&e.getLineScale?e.getLineScale():1);t.lineWidth!==l&&(s||(My(t,r),s=!0),t.lineWidth=l)}for(var u=0;u0&&py(n.lineDash,n.lineWidth),w=n.lineDashOffset,S=!!t.setLineDash,M=e.getGlobalScale();if(u.setScale(M[0],M[1],e.segmentIgnoreThreshold),b){var I=n.strokeNoScale&&e.getLineScale?e.getLineScale():1;I&&1!==I&&(b=O(b,(function(t){return t/I})),w/=I)}var T=!0;(l||e.__dirty&Za.SHAPE_CHANGED_BIT||b&&!S&&r)&&(u.setDPR(t.dpr),s?u.setContext(null):(u.setContext(t),T=!1),u.reset(),b&&!S&&(u.setLineDash(b),u.setLineDashOffset(w)),e.buildPath(u,e.shape,i),u.toStatic(),e.pathUpdated()),T&&u.rebuildPath(t,s?a:1),b&&S&&(t.setLineDash(b),t.lineDashOffset=w),i||(n.strokeFirst?(r&&vy(t,n),o&&yy(t,n)):(o&&yy(t,n),r&&vy(t,n))),b&&S&&t.setLineDash([])}(t,e,d,p),p&&(n.batchFill=d.fill||"",n.batchStroke=d.stroke||"")):e instanceof qa?(3!==n.lastDrawType&&(l=!0,n.lastDrawType=3),wy(t,e,u,l,n),function(t,e,n){var i=n.text;if(null!=i&&(i+=""),i){t.font=n.font||En,t.textAlign=n.textAlign,t.textBaseline=n.textBaseline;var r=void 0;if(t.setLineDash){var o=n.lineDash&&n.lineWidth>0&&py(n.lineDash,n.lineWidth),a=n.lineDashOffset;if(o){var s=n.strokeNoScale&&e.getLineScale?e.getLineScale():1;s&&1!==s&&(o=O(o,(function(t){return t/s})),a/=s),t.setLineDash(o),t.lineDashOffset=a,r=!0}}n.strokeFirst?(fy(n)&&t.strokeText(i,n.x,n.y),gy(n)&&t.fillText(i,n.x,n.y)):(gy(n)&&t.fillText(i,n.x,n.y),fy(n)&&t.strokeText(i,n.x,n.y)),r&&t.setLineDash([])}}(t,e,d)):e instanceof Ja?(2!==n.lastDrawType&&(l=!0,n.lastDrawType=2),function(t,e,n,i,r){by(t,Iy(e,r.inHover),n&&Iy(n,r.inHover),i,r)}(t,e,u,l,n),function(t,e,n){var i=e.__image=to(n.image,e.__image,e,e.onload);if(i&&no(i)){var r=n.x||0,o=n.y||0,a=e.getWidth(),s=e.getHeight(),l=i.width/i.height;if(null==a&&null!=s?a=s*l:null==s&&null!=a?s=a/l:null==a&&null==s&&(a=i.width,s=i.height),n.sWidth&&n.sHeight){var u=n.sx||0,h=n.sy||0;t.drawImage(i,u,h,n.sWidth,n.sHeight,r,o,a,s)}else if(n.sx&&n.sy){var c=a-(u=n.sx),p=s-(h=n.sy);t.drawImage(i,u,h,c,p,r,o,a,s)}else t.drawImage(i,r,o,a,s)}}(t,e,d)):e instanceof vu&&(4!==n.lastDrawType&&(l=!0,n.lastDrawType=4),function(t,e,n){var i=e.getDisplayables(),r=e.getTemporalDisplayables();t.save();var o,a,s={prevElClipPaths:null,prevEl:null,allClipped:!1,viewWidth:n.viewWidth,viewHeight:n.viewHeight,inHover:n.inHover};for(o=e.getCursor(),a=i.length;o0&&t.unfinished);t.unfinished||this._zr.flush()}}},e.prototype.getDom=function(){return this._dom},e.prototype.getId=function(){return this.id},e.prototype.getZr=function(){return this._zr},e.prototype.setOption=function(t,e,n){if(this._disposed)bv(this.id);else{var i,r,o;if(By(e)&&(n=e.lazyUpdate,i=e.silent,r=e.replaceMerge,o=e.transition,e=e.notMerge),this.__flagInMainProcess=!0,!this._model||e){var a=new bp(this._api),s=this._theme,l=this._model=new pp;l.scheduler=this._scheduler,l.init(null,null,null,s,this._locale,a)}this._model.setOption(t,{replaceMerge:r},Iv),dv(this,o),n?(this.__optionUpdated={silent:i},this.__flagInMainProcess=!1,this.getZr().wakeUp()):(qy(this),Jy.update.call(this),this._zr.flush(),this.__optionUpdated=!1,this.__flagInMainProcess=!1,nv.call(this,i),iv.call(this,i))}},e.prototype.setTheme=function(){console.error("ECharts#setTheme() is DEPRECATED in ECharts 3.0")},e.prototype.getModel=function(){return this._model},e.prototype.getOption=function(){return this._model&&this._model.getOption()},e.prototype.getWidth=function(){return this._zr.getWidth()},e.prototype.getHeight=function(){return this._zr.getHeight()},e.prototype.getDevicePixelRatio=function(){return this._zr.painter.dpr||Fy&&window.devicePixelRatio||1},e.prototype.getRenderedCanvas=function(t){if(a.canvasSupported)return(t=I({},t||{})).pixelRatio=t.pixelRatio||this.getDevicePixelRatio(),t.backgroundColor=t.backgroundColor||this._model.get("backgroundColor"),this._zr.painter.getRenderedCanvas(t)},e.prototype.getSvgDataURL=function(){if(a.svgSupported){var t=this._zr;return P(t.storage.getDisplayList(),(function(t){t.stopAnimation(null,!0)})),t.painter.toDataURL()}},e.prototype.getDataURL=function(t){if(!this._disposed){var e=(t=t||{}).excludeComponents,n=this._model,i=[],r=this;Ey(e,(function(t){n.eachComponent({mainType:t},(function(t){var e=r._componentsMap[t.__viewId];e.group.ignore||(i.push(e),e.group.ignore=!0)}))}));var o="svg"===this._zr.painter.getType()?this.getSvgDataURL():this.getRenderedCanvas(t).toDataURL("image/"+(t&&t.type||"png"));return Ey(i,(function(t){t.group.ignore=!1})),o}bv(this.id)},e.prototype.getConnectedDataURL=function(t){if(this._disposed)bv(this.id);else if(a.canvasSupported){var e="svg"===t.type,n=this.group,i=Math.min,r=Math.max,o=1/0;if(Pv[n]){var s=o,l=o,u=-1/0,h=-1/0,c=[],p=t&&t.pixelRatio||this.getDevicePixelRatio();P(kv,(function(o,a){if(o.group===n){var p=e?o.getZr().painter.getSvgDom().innerHTML:o.getRenderedCanvas(w(t)),d=o.getDom().getBoundingClientRect();s=i(d.left,s),l=i(d.top,l),u=r(d.right,u),h=r(d.bottom,h),c.push({dom:p,left:d.left,top:d.top})}}));var d=(u*=p)-(s*=p),f=(h*=p)-(l*=p),g=C(),y=Hi(g,{renderer:e?"svg":"canvas"});if(y.resize({width:d,height:f}),e){var v="";return Ey(c,(function(t){var e=t.left-s,n=t.top-l;v+=''+t.dom+""})),y.painter.getSvgRoot().innerHTML=v,t.connectedBackgroundColor&&y.painter.setBackgroundColor(t.connectedBackgroundColor),y.refreshImmediately(),y.painter.toDataURL()}return t.connectedBackgroundColor&&y.add(new os({shape:{x:0,y:0,width:d,height:f},style:{fill:t.connectedBackgroundColor}})),Ey(c,(function(t){var e=new Ja({style:{x:t.left*p-s,y:t.top*p-l,image:t.dom}});y.add(e)})),y.refreshImmediately(),g.toDataURL("image/"+(t&&t.type||"png"))}return this.getDataURL(t)}},e.prototype.convertToPixel=function(t,e){return Qy(this,"convertToPixel",t,e)},e.prototype.convertFromPixel=function(t,e){return Qy(this,"convertFromPixel",t,e)},e.prototype.containPixel=function(t,e){var n;if(!this._disposed)return P(Pr(this._model,t),(function(t,i){i.indexOf("Models")>=0&&P(t,(function(t){var r=t.coordinateSystem;if(r&&r.containPoint)n=n||!!r.containPoint(e);else if("seriesModels"===i){var o=this._chartsMap[t.__viewId];o&&o.containPoint&&(n=n||o.containPoint(e,t))}else 0}),this)}),this),!!n;bv(this.id)},e.prototype.getVisual=function(t,e){var n=Pr(this._model,t,{defaultMainType:"series"}),i=n.seriesModel;var r=i.getData(),o=n.hasOwnProperty("dataIndexInside")?n.dataIndexInside:n.hasOwnProperty("dataIndex")?r.indexOfRawIndex(n.dataIndex):null;return null!=o?pg(r,o,e):dg(r,e)},e.prototype.getViewOfComponentModel=function(t){return this._componentsMap[t.__viewId]},e.prototype.getViewOfSeriesModel=function(t){return this._chartsMap[t.__viewId]},e.prototype._initEvents=function(){var t,e,n,i=this;Ey(xv,(function(t){var e=function(e){var n,r=i.getModel(),o=e.target,a="globalout"===t;if(a?n={}:o&&Jg(o,(function(t){var e=ys(t);if(e&&null!=e.dataIndex){var i=e.dataModel||r.getSeriesByIndex(e.seriesIndex);return n=i&&i.getDataParams(e.dataIndex,e.dataType)||{},!0}if(e.eventData)return n=I({},e.eventData),!0}),!0),n){var s=n.componentType,l=n.componentIndex;"markLine"!==s&&"markPoint"!==s&&"markArea"!==s||(s="series",l=n.seriesIndex);var u=s&&null!=l&&r.getComponent(s,l),h=u&&i["series"===u.mainType?"_chartsMap":"_componentsMap"][u.__viewId];0,n.event=e,n.type=t,i._$eventProcessor.eventInfo={targetEl:o,packedEvent:n,model:u,view:h},i.trigger(t,n)}};e.zrEventfulCallAtLast=!0,i._zr.on(t,e,i)})),Ey(Sv,(function(t,e){i._messageCenter.on(e,(function(t){this.trigger(e,t)}),i)})),Ey(["selectchanged"],(function(t){i._messageCenter.on(t,(function(e){this.trigger(t,e)}),i)})),t=this._messageCenter,e=this,n=this._api,t.on("selectchanged",(function(t){var i=n.getModel();t.isFromClick?($g("map","selectchanged",e,i,t),$g("pie","selectchanged",e,i,t)):"select"===t.fromAction?($g("map","selected",e,i,t),$g("pie","selected",e,i,t)):"unselect"===t.fromAction&&($g("map","unselected",e,i,t),$g("pie","unselected",e,i,t))}))},e.prototype.isDisposed=function(){return this._disposed},e.prototype.clear=function(){this._disposed?bv(this.id):this.setOption({series:[]},!0)},e.prototype.dispose=function(){if(this._disposed)bv(this.id);else{this._disposed=!0,Er(this.getDom(),Nv,"");var t=this._api,e=this._model;Ey(this._componentsViews,(function(n){n.dispose(e,t)})),Ey(this._chartsViews,(function(n){n.dispose(e,t)})),this._zr.dispose(),delete kv[this.id]}},e.prototype.resize=function(t){if(this._disposed)bv(this.id);else{this._zr.resize(t);var e=this._model;if(this._loadingFX&&this._loadingFX.resize(),e){var n=e.resetOption("media"),i=t&&t.silent;this.__flagInMainProcess=!0,n&&qy(this),Jy.update.call(this,{type:"resize",animation:{duration:0}}),this.__flagInMainProcess=!1,nv.call(this,i),iv.call(this,i)}}},e.prototype.showLoading=function(t,e){if(this._disposed)bv(this.id);else if(By(t)&&(e=t,t=""),t=t||"default",this.hideLoading(),Lv[t]){var n=Lv[t](this._api,e),i=this._zr;this._loadingFX=n,i.add(n)}},e.prototype.hideLoading=function(){this._disposed?bv(this.id):(this._loadingFX&&this._zr.remove(this._loadingFX),this._loadingFX=null)},e.prototype.makeActionFromEvent=function(t){var e=I({},t);return e.type=Sv[t.type],e},e.prototype.dispatchAction=function(t,e){if(this._disposed)bv(this.id);else if(By(e)||(e={silent:!!e}),wv[t.type]&&this._model)if(this.__flagInMainProcess)this._pendingActions.push(t);else{var n=e.silent;ev.call(this,t,n);var i=e.flush;i?this._zr.flush():!1!==i&&a.browser.weChat&&this._throttledZrFlush(),nv.call(this,n),iv.call(this,n)}},e.prototype.updateLabelLayout=function(){var t=this._labelManager;t.updateLayoutConfig(this._api),t.layout(this._api),t.processLabelsOverall()},e.prototype.appendData=function(t){if(this._disposed)bv(this.id);else{var e=t.seriesIndex,n=this.getModel().getSeriesByIndex(e);0,n.appendData(t),this._scheduler.unfinished=!0,this.getZr().wakeUp()}},e.internalField=function(){function t(t){for(var e=[],n=t.currentStates,i=0;i0?{duration:o,delay:i.get("delay"),easing:i.get("easing")}:null;n.group.traverse((function(e){if(e.states&&e.states.emphasis){if(Bu(e))return;if(e instanceof Za&&function(t){var e=_s(t);e.normalFill=t.style.fill,e.normalStroke=t.style.stroke;var n=t.states.select||{};e.selectFill=n.style&&n.style.fill||null,e.selectStroke=n.style&&n.style.stroke||null}(e),e.__dirty){var n=e.prevStates;n&&e.useStates(n)}if(r){e.stateTransition=a;var i=e.getTextContent(),o=e.getTextGuideLine();i&&(i.stateTransition=a),o&&(o.stateTransition=a)}e.__dirty&&t(e)}}))}qy=function(t){var e=t._scheduler;e.restorePipelines(t._model),e.prepareStageTasks(),Ky(t,!0),Ky(t,!1),e.plan()},Ky=function(t,e){for(var n=t._model,i=t._scheduler,r=e?t._componentsViews:t._chartsViews,o=e?t._componentsMap:t._chartsMap,a=t._zr,s=t._api,l=0;le.get("hoverLayerThreshold")&&!a.node&&!a.worker&&e.eachSeries((function(e){if(!e.preventUsingHoverLayer){var n=t._chartsMap[e.__viewId];n.__alive&&n.group.traverse((function(t){t.states.emphasis&&(t.states.emphasis.hoverLayer=!0)}))}}))}(t,n)},hv=function(t,e){Ey(Cv,(function(n){n(t,e)}))},fv=function(t){t.__needsUpdateStatus=!0,t.getZr().wakeUp()},gv=function(e){e.__needsUpdateStatus&&(e.getZr().storage.traverse((function(e){Bu(e)||t(e)})),e.__needsUpdateStatus=!1)},cv=function(t){return new(function(e){function i(){return null!==e&&e.apply(this,arguments)||this}return n(i,e),i.prototype.getCoordinateSystems=function(){return t._coordSysMgr.getCoordinateSystems()},i.prototype.getComponentByElement=function(e){for(;e;){var n=e.__ecComponentInfo;if(null!=n)return t._model.getComponent(n.mainType,n.index);e=e.parent}},i.prototype.enterEmphasis=function(e,n){Hs(e,n),fv(t)},i.prototype.leaveEmphasis=function(e,n){Ws(e,n),fv(t)},i.prototype.enterBlur=function(e){Ys(e),fv(t)},i.prototype.leaveBlur=function(e){Xs(e),fv(t)},i.prototype.enterSelect=function(e){Us(e),fv(t)},i.prototype.leaveSelect=function(e){Zs(e),fv(t)},i.prototype.getModel=function(){return t.getModel()},i.prototype.getViewOfComponentModel=function(e){return t.getViewOfComponentModel(e)},i.prototype.getViewOfSeriesModel=function(e){return t.getViewOfSeriesModel(e)},i}(vp))(t)},pv=function(t){function e(t,e){for(var n=0;n=0)){jv.push(n);var o=zf.wrapStageHandler(n,r);o.__prio=e,o.__raw=n,t.push(o)}}function Kv(t,e){Lv[t]=e}function $v(t,e,n){sg(t,e,n)}var Jv=function(t){var e=(t=w(t)).type,n="";e||yr(n);var i=e.split(":");2!==i.length&&yr(n);var r=!1;"echarts"===i[0]&&(e=i[1],r=!0),t.__isBuiltIn=r,Rd.set(e,t)};Zv(Gy,Pf),Zv(Hy,Rf),Zv(Hy,Nf),Zv(Gy,cg),Zv(Hy,{createOnAllSeries:!0,performRawSeries:!0,reset:function(t,e){if(t.hasSymbolVisual&&!e.isSeriesFiltered(t))return{dataEach:t.getData().hasItemOption?function(t,e){var n=t.getItemModel(e),i=n.getShallow("symbol",!0),r=n.getShallow("symbolSize",!0),o=n.getShallow("symbolRotate",!0),a=n.getShallow("symbolKeepAspect",!0);null!=i&&t.setItemVisual(e,"symbol",i),null!=r&&t.setItemVisual(e,"symbolSize",r),null!=o&&t.setItemVisual(e,"symbolRotate",o),null!=a&&t.setItemVisual(e,"symbolKeepAspect",a)}:null}}}),Zv(7e3,(function(t,e){t.eachRawSeries((function(n){if(!t.isSeriesFiltered(n)){var i=n.getData();i.hasItemVisual()&&i.each((function(t){var n=i.getItemVisual(t,"decal");n&&(i.ensureUniqueItemVisual(t,"style").decal=ky(n,e))}));var r=i.getVisual("decal");if(r)i.getVisual("style").decal=ky(r,e)}}))})),Fv(Hp),Gv(900,(function(t){var e=ht();t.eachSeries((function(t){var n=t.get("stack");if(n){var i=e.get(n)||e.set(n,[]),r=t.getData(),o={stackResultDimension:r.getCalculationInfo("stackResultDimension"),stackedOverDimension:r.getCalculationInfo("stackedOverDimension"),stackedDimension:r.getCalculationInfo("stackedDimension"),stackedByDimension:r.getCalculationInfo("stackedByDimension"),isStackedByIndex:r.getCalculationInfo("isStackedByIndex"),data:r,seriesModel:t};if(!o.stackedDimension||!o.isStackedByIndex&&!o.stackedByDimension)return;i.length&&r.setCalculationInfo("stackedOnSeries",i[i.length-1].seriesModel),i.push(o)}})),e.each(Wp)})),Kv("default",(function(t,e){T(e=e||{},{text:"loading",textColor:"#000",fontSize:12,fontWeight:"normal",fontStyle:"normal",fontFamily:"sans-serif",maskColor:"rgba(255, 255, 255, 0.8)",showSpinner:!0,color:"#5470c6",spinnerRadius:10,lineWidth:5,zlevel:0});var n=new zi,i=new os({style:{fill:e.maskColor},zlevel:e.zlevel,z:1e4});n.add(i);var r,o=new ls({style:{text:e.text,fill:e.textColor,fontSize:e.fontSize,fontWeight:e.fontWeight,fontStyle:e.fontStyle,fontFamily:e.fontFamily}}),a=new os({style:{fill:"none"},textContent:o,textConfig:{position:"right",distance:10},zlevel:e.zlevel,z:10001});return n.add(a),e.showSpinner&&((r=new au({shape:{startAngle:-Ef/2,endAngle:-Ef/2+.1,r:e.spinnerRadius},style:{stroke:e.color,lineCap:"round",lineWidth:e.lineWidth},zlevel:e.zlevel,z:10001})).animateShape(!0).when(1e3,{endAngle:3*Ef/2}).start("circularInOut"),r.animateShape(!0).when(1e3,{startAngle:3*Ef/2}).delay(300).start("circularInOut"),n.add(r)),n.resize=function(){var n=o.getBoundingRect().width,s=e.showSpinner?e.spinnerRadius:0,l=(t.getWidth()-2*s-(e.showSpinner&&n?10:0)-n)/2-(e.showSpinner&&n?0:5+n/2)+(e.showSpinner?0:n/2)+(n?0:s),u=t.getHeight()/2;e.showSpinner&&r.setShape({cx:l,cy:u}),a.setShape({x:l-s,y:u-s,width:2*s,height:2*s}),i.setShape({x:0,y:0,width:t.getWidth(),height:t.getHeight()})},n.resize(),n})),Yv({type:ws,event:ws,update:ws},ft),Yv({type:Ss,event:Ss,update:Ss},ft),Yv({type:Ms,event:Ms,update:Ms},ft),Yv({type:Is,event:Is,update:Is},ft),Yv({type:Ts,event:Ts,update:Ts},ft),Vv("light",Qf),Vv("dark",rg);var Qv=[],tm={registerPreprocessor:Fv,registerProcessor:Gv,registerPostInit:Hv,registerPostUpdate:Wv,registerAction:Yv,registerCoordinateSystem:Xv,registerLayout:Uv,registerVisual:Zv,registerTransform:Jv,registerLoading:Kv,registerMap:$v,PRIORITY:Wy,ComponentModel:Nc,ComponentView:pf,SeriesModel:rf,ChartView:yf,registerComponentModel:function(t){Nc.registerClass(t)},registerComponentView:function(t){pf.registerClass(t)},registerSeriesModel:function(t){rf.registerClass(t)},registerChartView:function(t){yf.registerClass(t)},registerSubTypeDefaulter:function(t,e){Nc.registerSubTypeDefaulter(t,e)},registerPainter:function(t,e){Wi(t,e)}};function em(t){F(t)?P(t,(function(t){em(t)})):A(Qv,t)>=0||(Qv.push(t),G(t)&&(t={install:t}),t.install(tm))}function nm(t){return null==t?0:t.length||1}function im(t){return t}var rm=function(){function t(t,e,n,i,r,o){this._old=t,this._new=e,this._oldKeyGetter=n||im,this._newKeyGetter=i||im,this.context=r,this._diffModeMultiple="multiple"===o}return t.prototype.add=function(t){return this._add=t,this},t.prototype.update=function(t){return this._update=t,this},t.prototype.updateManyToOne=function(t){return this._updateManyToOne=t,this},t.prototype.updateOneToMany=function(t){return this._updateOneToMany=t,this},t.prototype.remove=function(t){return this._remove=t,this},t.prototype.execute=function(){this[this._diffModeMultiple?"_executeMultiple":"_executeOneToOne"]()},t.prototype._executeOneToOne=function(){var t=this._old,e=this._new,n={},i=new Array(t.length),r=new Array(e.length);this._initIndexMap(t,null,i,"_oldKeyGetter"),this._initIndexMap(e,n,r,"_newKeyGetter");for(var o=0;o1){var u=s.shift();1===s.length&&(n[a]=s[0]),this._update&&this._update(u,o)}else 1===l?(n[a]=null,this._update&&this._update(s,o)):this._remove&&this._remove(o)}this._performRestAdd(r,n)},t.prototype._executeMultiple=function(){var t=this._old,e=this._new,n={},i={},r=[],o=[];this._initIndexMap(t,n,r,"_oldKeyGetter"),this._initIndexMap(e,i,o,"_newKeyGetter");for(var a=0;a1&&1===c)this._updateManyToOne&&this._updateManyToOne(u,l),i[s]=null;else if(1===h&&c>1)this._updateOneToMany&&this._updateOneToMany(u,l),i[s]=null;else if(1===h&&1===c)this._update&&this._update(u,l),i[s]=null;else if(h>1)for(var p=0;p1)for(var a=0;av[1]&&(v[1]=y)}e&&(this._nameList[d]=e[f],this._dontMakeIdFromName||gm(this,d))}this._rawCount=this._count=s,this._extent={},lm(this)},t.prototype._initDataFromProvider=function(t,e,n){if(!(t>=e)){for(var i=this._rawData,r=this._storage,o=this.dimensions,a=o.length,s=this._dimensionInfos,l=this._nameList,u=this._idList,h=this._rawExtent,c=i.getSource().sourceFormat===Fc,p=0;pb[1]&&(b[1]=x)}if(c&&!i.pure&&y){var w=y.name;null==l[v]&&null!=w&&(l[v]=Tr(w,null));var S=y.id;null==u[v]&&null!=S&&(u[v]=Tr(S,null))}this._dontMakeIdFromName||gm(this,v)}!i.persistent&&i.clean&&i.clean(),this._rawCount=this._count=e,this._extent={},lm(this)}},t.prototype.count=function(){return this._count},t.prototype.getIndices=function(){var t,e=this._indices;if(e){var n=e.constructor,i=this._count;if(n===Array){t=new n(i);for(var r=0;r=0&&e=0&&e=0&&ea&&(a=l)}return i=[o,a],this._extent[t]=i,i},t.prototype.getApproximateExtent=function(t){return t=this.getDimension(t),this._approximateExtent[t]||this.getDataExtent(t)},t.prototype.setApproximateExtent=function(t,e){e=this.getDimension(e),this._approximateExtent[e]=t.slice()},t.prototype.getCalculationInfo=function(t){return this._calculationInfo[t]},t.prototype.setCalculationInfo=function(t,e){Sm(t)?I(this._calculationInfo,t):this._calculationInfo[t]=e},t.prototype.getSum=function(t){var e=0;if(this._storage[t])for(var n=0,i=this.count();n=this._rawCount||t<0)return-1;if(!this._indices)return t;var e=this._indices,n=e[t];if(null!=n&&nt))return o;r=o-1}}return-1},t.prototype.indicesOfNearest=function(t,e,n){var i=this._storage[t],r=[];if(!i)return r;null==n&&(n=1/0);for(var o=1/0,a=-1,s=0,l=0,u=this.count();l=0&&a<0)&&(o=c,a=h,s=0),h===a&&(r[s++]=l))}return r.length=s,r},t.prototype.getRawDataItem=function(t){if(this._rawData.persistent)return this._rawData.getItem(this.getRawIndex(t));for(var e=[],n=0;n=c&&b<=p||isNaN(b))&&(s[l++]=g),g++}f=!0}else if(2===o){y=d[h[0]];var m=d[h[1]],_=t[i[1]][0],x=t[i[1]][1];for(v=0;v=c&&b<=p||isNaN(b))&&(w>=_&&w<=x||isNaN(w))&&(s[l++]=g),g++}f=!0}}if(!f)if(1===o)for(v=0;v=c&&b<=p||isNaN(b))&&(s[l++]=S)}else for(v=0;vt[T][1])&&(M=!1)}M&&(s[l++]=this.getRawIndex(v))}return lx[1]&&(x[1]=_)}}}return a},t.prototype.downSample=function(t,e,n,i){for(var r=vm(this,[t]),o=r._storage,a=[],s=wm(1/e),l=o[t],u=this.count(),h=r._rawExtent[t],c=new(um(this))(u),p=0,d=0;du-d&&(s=u-d,a.length=s);for(var f=0;fh[1]&&(h[1]=y),c[p++]=v}return r._count=p,r._indices=c,r.getRawIndex=pm,r},t.prototype.lttbDownSample=function(t,e){var n,i,r,o=vm(this,[]),a=o._storage[t],s=this.count(),l=new(um(this))(s),u=0,h=wm(1/e),c=this.getRawIndex(0);l[u++]=c;for(var p=1;pn&&(n=i,r=S)}l[u++]=r,c=r}return l[u++]=this.getRawIndex(s-1),o._count=u,o._indices=l,o.getRawIndex=pm,o},t.prototype.getItemModel=function(t){var e=this.hostModel,n=this.getRawDataItem(t);return new Sh(n,e,e&&e.ecModel)},t.prototype.diff=function(t){var e=this;return new rm(t?t.getIndices():[],this.getIndices(),(function(e){return dm(t,e)}),(function(t){return dm(e,t)}))},t.prototype.getVisual=function(t){var e=this._visual;return e&&e[t]},t.prototype.setVisual=function(t,e){this._visual=this._visual||{},Sm(t)?I(this._visual,t):this._visual[t]=e},t.prototype.getItemVisual=function(t,e){var n=this._itemVisuals[t],i=n&&n[e];return null==i?this.getVisual(e):i},t.prototype.hasItemVisual=function(){return this._itemVisuals.length>0},t.prototype.ensureUniqueItemVisual=function(t,e){var n=this._itemVisuals,i=n[t];i||(i=n[t]={});var r=i[e];return null==r&&(F(r=this.getVisual(e))?r=r.slice():Sm(r)&&(r=I({},r)),i[e]=r),r},t.prototype.setItemVisual=function(t,e,n){var i=this._itemVisuals[t]||{};this._itemVisuals[t]=i,Sm(e)?I(i,e):i[e]=n},t.prototype.clearAllVisual=function(){this._visual={},this._itemVisuals=[]},t.prototype.setLayout=function(t,e){if(Sm(t))for(var n in t)t.hasOwnProperty(n)&&this.setLayout(n,t[n]);else this._layout[t]=e},t.prototype.getLayout=function(t){return this._layout[t]},t.prototype.getItemLayout=function(t){return this._itemLayouts[t]},t.prototype.setItemLayout=function(t,e,n){this._itemLayouts[t]=n?I(this._itemLayouts[t]||{},e):e},t.prototype.clearItemLayouts=function(){this._itemLayouts.length=0},t.prototype.setItemGraphicEl=function(t,e){var n=this.hostModel;if(e){var i=ys(e);i.dataIndex=t,i.dataType=this.dataType,i.seriesIndex=n&&n.seriesIndex,"group"===e.type&&e.traverse(_m,e)}this._graphicEls[t]=e},t.prototype.getItemGraphicEl=function(t){return this._graphicEls[t]},t.prototype.eachItemGraphicEl=function(t,e){P(this._graphicEls,(function(n,i){n&&t&&t.call(e,n,i)}))},t.prototype.cloneShallow=function(e){e||(e=new t(Mm(this.dimensions,this.getDimensionInfo,this),this.hostModel));if(e._storage=this._storage,e._storageArr=this._storageArr,xm(e,this),this._indices){var n=this._indices.constructor;if(n===Array){var i=this._indices.length;e._indices=new n(i);for(var r=0;r65535?Cm:Dm},hm=function(t,e,n,i){var r=Tm[e.type],o=e.name;if(i){var a=t[o],s=a&&a.length;if(s!==n){for(var l=new r(n),u=0;u=0?this._indices[t]:-1},dm=function(t,e){var n=t._idList[e];return null==n&&null!=t._idDimIdx&&(n=fm(t,t._idDimIdx,t._idOrdinalMeta,e)),null==n&&(n="e\0\0"+e),n},ym=function(t){return F(t)||(t=null!=t?[t]:[]),t},function(t,e){for(var n=0;n=0?(s[c]=(o=l[c],a=void 0,(a=o.constructor)===Array?o.slice():new a(o)),r._rawExtent[c]=mm(),r._extent[c]=null):s[c]=l[c],u.push(s[c]))}return r},mm=function(){return[1/0,-1/0]},_m=function(t){var e=ys(t),n=ys(this);e.seriesIndex=n.seriesIndex,e.dataIndex=n.dataIndex,e.dataType=n.dataType},xm=function(t,e){P(Lm.concat(e.__wrappedMethods||[]),(function(n){e.hasOwnProperty(n)&&(t[n]=e[n])})),t.__wrappedMethods=e.__wrappedMethods,P(km,(function(n){t[n]=w(e[n])})),t._calculationInfo=I({},e._calculationInfo)},gm=function(t,e){var n=t._nameList,i=t._idList,r=t._nameDimIdx,o=t._idDimIdx,a=n[e],s=i[e];if(null==a&&null!=r&&(n[e]=a=fm(t,r,t._nameOrdinalMeta,e)),null==s&&null!=o&&(i[e]=s=fm(t,o,t._idOrdinalMeta,e)),null==s&&null!=a){var l=t._nameRepeatCount,u=l[a]=(l[a]||0)+1;s=a,u>1&&(s+="__ec__"+u),i[e]=s}}}(),t}();function Om(t,e,n){Kp(e)||(e=Jp(e)),n=n||{},t=(t||[]).slice();for(var i=(n.dimsDef||[]).slice(),r=ht(),o=ht(),a=[],s=function(t,e,n,i){var r=Math.max(t.dimensionsDetectedCount||1,e.length,n.length,i||0);return P(e,(function(t){var e;X(t)&&(e=t.dimsDef)&&(r=Math.max(r,e.length))})),r}(e,t,i,n.dimCount),l=0;le[1]&&(e[1]=t[1])},t.prototype.unionExtentFromData=function(t,e){this.unionExtent(t.getApproximateExtent(e))},t.prototype.getExtent=function(){return this._extent.slice()},t.prototype.setExtent=function(t,e){var n=this._extent;isNaN(t)||(n[0]=t),isNaN(e)||(n[1]=e)},t.prototype.isInExtentRange=function(t){return this._extent[0]<=t&&this._extent[1]>=t},t.prototype.isBlank=function(){return this._isBlank},t.prototype.setBlank=function(t){this._isBlank=t},t}();jr(Wm);var Ym=function(){function t(t){this.categories=t.categories||[],this._needCollect=t.needCollect,this._deduplication=t.deduplication}return t.createByAxisModel=function(e){var n=e.option,i=n.data,r=i&&O(i,Xm);return new t({categories:r,needCollect:!r,deduplication:!1!==n.dedplication})},t.prototype.getOrdinal=function(t){return this._getOrCreateMap().get(t)},t.prototype.parseAndCollect=function(t){var e,n=this._needCollect;if("string"!=typeof t&&!n)return t;if(n&&!this._deduplication)return e=this.categories.length,this.categories[e]=t,e;var i=this._getOrCreateMap();return null==(e=i.get(t))&&(n?(e=this.categories.length,this.categories[e]=t,i.set(t,e)):e=NaN),e},t.prototype._getOrCreateMap=function(){return this._map||(this._map=ht(this.categories))},t}();function Xm(t){return X(t)&&null!=t.value?t.value:t+""}var Um=ji;function Zm(t,e,n,i){var r={},o=t[1]-t[0],a=r.interval=sr(o/e,!0);null!=n&&ai&&(a=r.interval=i);var s=r.intervalPrecision=jm(a);return function(t,e){!isFinite(t[0])&&(t[0]=e[0]),!isFinite(t[1])&&(t[1]=e[1]),qm(t,0,e),qm(t,1,e),t[0]>t[1]&&(t[0]=t[1])}(r.niceTickExtent=[Um(Math.ceil(t[0]/a)*a,s),Um(Math.floor(t[1]/a)*a,s)],t),r}function jm(t){return $i(t)+2}function qm(t,e,n){t[e]=Math.max(Math.min(t[e],n[1]),n[0])}function Km(t,e){return t>=e[0]&&t<=e[1]}function $m(t,e){return e[1]===e[0]?.5:(t-e[0])/(e[1]-e[0])}function Jm(t,e){return t*(e[1]-e[0])+e[0]}var Qm=function(t){function e(e){var n=t.call(this,e)||this;n.type="ordinal";var i=n.getSetting("ordinalMeta");return i||(i=new Ym({})),F(i)&&(i=new Ym({categories:O(i,(function(t){return X(t)?t.value:t}))})),n._ordinalMeta=i,n._extent=n.getSetting("extent")||[0,i.categories.length-1],n}return n(e,t),e.prototype.parse=function(t){return"string"==typeof t?this._ordinalMeta.getOrdinal(t):Math.round(t)},e.prototype.contain=function(t){return Km(t=this.parse(t),this._extent)&&null!=this._ordinalMeta.categories[t]},e.prototype.normalize=function(t){return $m(t=this._getTickNumber(this.parse(t)),this._extent)},e.prototype.scale=function(t){return t=Math.round(Jm(t,this._extent)),this.getRawOrdinalNumber(t)},e.prototype.getTicks=function(){for(var t=[],e=this._extent,n=e[0];n<=e[1];)t.push({value:n}),n++;return t},e.prototype.getMinorTicks=function(t){},e.prototype.setSortInfo=function(t){if(null!=t){for(var e=t.ordinalNumbers,n=this._ordinalNumbersByTick=[],i=this._ticksByOrdinalNumber=[],r=0,o=this._ordinalMeta.categories.length,a=Math.min(o,e.length);r=0&&t=0&&t=t},e.prototype.getOrdinalMeta=function(){return this._ordinalMeta},e.prototype.niceTicks=function(){},e.prototype.niceExtent=function(){},e.type="ordinal",e}(Wm);Wm.registerClass(Qm);var t_=ji,e_=function(t){function e(){var e=null!==t&&t.apply(this,arguments)||this;return e.type="interval",e._interval=0,e._intervalPrecision=2,e}return n(e,t),e.prototype.parse=function(t){return t},e.prototype.contain=function(t){return Km(t,this._extent)},e.prototype.normalize=function(t){return $m(t,this._extent)},e.prototype.scale=function(t){return Jm(t,this._extent)},e.prototype.setExtent=function(t,e){var n=this._extent;isNaN(t)||(n[0]=parseFloat(t)),isNaN(e)||(n[1]=parseFloat(e))},e.prototype.unionExtent=function(t){var e=this._extent;t[0]e[1]&&(e[1]=t[1]),this.setExtent(e[0],e[1])},e.prototype.getInterval=function(){return this._interval},e.prototype.setInterval=function(t){this._interval=t,this._niceExtent=this._extent.slice(),this._intervalPrecision=jm(t)},e.prototype.getTicks=function(t){var e=this._interval,n=this._extent,i=this._niceExtent,r=this._intervalPrecision,o=[];if(!e)return o;n[0]1e4)return[];var s=o.length?o[o.length-1].value:i[1];return n[1]>s&&(t?o.push({value:t_(s+e,r)}):o.push({value:n[1]})),o},e.prototype.getMinorTicks=function(t){for(var e=this.getTicks(!0),n=[],i=this.getExtent(),r=1;ri[0]&&h0&&(o=null===o?s:Math.min(o,s))}n[i]=o}}return n}(t),n=[];return P(t,(function(t){var i,r=t.coordinateSystem.getBaseAxis(),o=r.getExtent();if("category"===r.type)i=r.getBandWidth();else if("value"===r.type||"time"===r.type){var a=r.dim+"_"+r.index,s=e[a],l=Math.abs(o[1]-o[0]),u=r.scale.getExtent(),h=Math.abs(u[1]-u[0]);i=s?l/h*s:l}else{var c=t.getData();i=Math.abs(o[1]-o[0])/c.count()}var p=Zi(t.get("barWidth"),i),d=Zi(t.get("barMaxWidth"),i),f=Zi(t.get("barMinWidth")||1,i),g=t.get("barGap"),y=t.get("barCategoryGap");n.push({bandWidth:i,barWidth:p,barMaxWidth:d,barMinWidth:f,barGap:g,barCategoryGap:y,axisKey:o_(r),stackId:r_(t)})})),l_(n)}function l_(t){var e={};P(t,(function(t,n){var i=t.axisKey,r=t.bandWidth,o=e[i]||{bandWidth:r,remainedWidth:r,autoWidthCount:0,categoryGap:null,gap:"20%",stacks:{}},a=o.stacks;e[i]=o;var s=t.stackId;a[s]||o.autoWidthCount++,a[s]=a[s]||{width:0,maxWidth:0};var l=t.barWidth;l&&!a[s].width&&(a[s].width=l,l=Math.min(o.remainedWidth,l),o.remainedWidth-=l);var u=t.barMaxWidth;u&&(a[s].maxWidth=u);var h=t.barMinWidth;h&&(a[s].minWidth=h);var c=t.barGap;null!=c&&(o.gap=c);var p=t.barCategoryGap;null!=p&&(o.categoryGap=p)}));var n={};return P(e,(function(t,e){n[e]={};var i=t.stacks,r=t.bandWidth,o=t.categoryGap;if(null==o){var a=z(i).length;o=Math.max(35-4*a,15)+"%"}var s=Zi(o,r),l=Zi(t.gap,1),u=t.remainedWidth,h=t.autoWidthCount,c=(u-s)/(h+(h-1)*l);c=Math.max(c,0),P(i,(function(t){var e=t.maxWidth,n=t.minWidth;if(t.width){i=t.width;e&&(i=Math.min(i,e)),n&&(i=Math.max(i,n)),t.width=i,u-=i+l*i,h--}else{var i=c;e&&ei&&(i=n),i!==c&&(t.width=i,u-=i+l*i,h--)}})),c=(u-s)/(h+(h-1)*l),c=Math.max(c,0);var p,d=0;P(i,(function(t,e){t.width||(t.width=c),p=t,d+=t.width*(1+l)})),p&&(d-=p.width*l);var f=-d/2;P(i,(function(t,i){n[e][i]=n[e][i]||{bandWidth:r,offset:f,width:t.width},f+=t.width*(1+l)}))})),n}function u_(t,e,n){if(t&&e){var i=t[o_(e)];return null!=i&&null!=n?i[r_(n)]:i}}function h_(t,e){var n=a_(t,e),i=s_(n),r={};P(n,(function(t){var e=t.getData(),n=t.coordinateSystem,o=n.getBaseAxis(),a=r_(t),s=i[o_(o)][a],l=s.offset,u=s.width,h=n.getOtherAxis(o),c=t.get("barMinHeight")||0;r[a]=r[a]||[],e.setLayout({bandWidth:s.bandWidth,offset:l,size:u});for(var p=e.mapDimension(h.dim),d=e.mapDimension(o.dim),f=Fm(e,p),g=h.isHorizontal(),y=f_(o,h),v=0,m=e.count();v=0?"p":"n",w=y;f&&(r[a][x]||(r[a][x]={p:y,n:y}),w=r[a][x][b]);var S,M=void 0,I=void 0,T=void 0,C=void 0;if(g)M=w,I=(S=n.dataToPoint([_,x]))[1]+l,T=S[0]-y,C=u,Math.abs(T).5||(h=.5),{progress:function(t,e){for(var c,p=t.count,d=new i_(2*p),f=new i_(2*p),g=new i_(p),y=[],v=[],m=0,_=0;null!=(c=t.next());)v[u]=e.get(a,c),v[1-u]=e.get(s,c),y=n.dataToPoint(v,null,y),f[m]=l?i.x+i.width:y[0],d[m++]=y[0],f[m]=l?y[1]:i.y+i.height,d[m++]=y[1],g[_++]=c;e.setLayout({largePoints:d,largeDataIndices:g,largeBackgroundPoints:f,barWidth:h,valueAxisStart:f_(r,o),backgroundStart:l?i.x:i.y,valueAxisHorizontal:l})}}}}};function p_(t){return t.coordinateSystem&&"cartesian2d"===t.coordinateSystem.type}function d_(t){return t.pipelineContext&&t.pipelineContext.large}function f_(t,e,n){return e.toGlobalCoord(e.dataToCoord("log"===e.type?1:0))}var g_=function(t){function e(e){var n=t.call(this,e)||this;return n.type="time",n}return n(e,t),e.prototype.getLabel=function(t){var e=this.getSetting("useUTC");return Zh(t.value,Gh[function(t){switch(t){case"year":case"month":return"day";case"millisecond":return"millisecond";default:return"second"}}(Xh(this._minLevelUnit))]||Gh.second,e,this.getSetting("locale"))},e.prototype.getFormattedLabel=function(t,e,n){var i=this.getSetting("useUTC");return function(t,e,n,i,r){var o=null;if("string"==typeof n)o=n;else if("function"==typeof n)o=n(t.value,e,{level:t.level});else{var a=I({},Vh);if(t.level>0)for(var s=0;s=0;--s)if(l[u]){o=l[u];break}o=o||a.none}if(F(o)){var h=null==t.level?0:t.level>=0?t.level:o.length+t.level;o=o[h=Math.min(h,o.length-1)]}}return Zh(new Date(t.value),o,r,i)}(t,e,n,this.getSetting("locale"),i)},e.prototype.getTicks=function(t){var e=this._interval,n=this._extent,i=[];if(!e)return i;i.push({value:n[0],level:0});var r=this.getSetting("useUTC"),o=function(t,e,n,i){var r=1e4,o=Wh,a=0;function s(t,e,n,r,o,a,s){for(var l=new Date(e),u=e,h=l[r]();u1&&0===u&&o.unshift({value:o[0].value-p})}}for(u=0;u=i[0]&&v<=i[1]&&c++)}var m=(i[1]-i[0])/e;if(c>1.5*m&&p>m/1.5)break;if(u.push(g),c>m||t===o[d])break}h=[]}}0;var _=N(O(u,(function(t){return N(t,(function(t){return t.value>=i[0]&&t.value<=i[1]&&!t.notAdd}))})),(function(t){return t.length>0})),x=[],b=_.length-1;for(d=0;d<_.length;++d)for(var w=_[d],S=0;Sn&&(this._approxInterval=n);var o=y_.length,a=Math.min(function(t,e,n,i){for(;n>>1;t[r][1]16?16:t>7.5?7:t>3.5?4:t>1.5?2:1}function m_(t){return(t/=2592e6)>6?6:t>3?3:t>2?2:1}function __(t){return(t/=Eh)>12?12:t>6?6:t>3.5?4:t>2?2:1}function x_(t,e){return(t/=e?Nh:Rh)>30?30:t>20?20:t>15?15:t>10?10:t>5?5:t>2?2:1}function b_(t){return sr(t,!0)}function w_(t,e,n){var i=new Date(t);switch(Xh(e)){case"year":case"month":i[rc(n)](0);case"day":i[oc(n)](1);case"hour":i[ac(n)](0);case"minute":i[sc(n)](0);case"second":i[lc(n)](0),i[uc(n)](0)}return i.getTime()}Wm.registerClass(g_);var S_=Wm.prototype,M_=e_.prototype,I_=$i,T_=ji,C_=Math.floor,A_=Math.ceil,D_=Math.pow,L_=Math.log,k_=function(t){function e(){var e=null!==t&&t.apply(this,arguments)||this;return e.type="log",e.base=10,e._originalScale=new e_,e._interval=0,e}return n(e,t),e.prototype.getTicks=function(t){var e=this._originalScale,n=this._extent,i=e.getExtent();return O(M_.getTicks.call(this,t),(function(t){var e=t.value,r=ji(D_(this.base,e));return r=e===n[0]&&this._fixMin?O_(r,i[0]):r,{value:r=e===n[1]&&this._fixMax?O_(r,i[1]):r}}),this)},e.prototype.setExtent=function(t,e){var n=this.base;t=L_(t)/L_(n),e=L_(e)/L_(n),M_.setExtent.call(this,t,e)},e.prototype.getExtent=function(){var t=this.base,e=S_.getExtent.call(this);e[0]=D_(t,e[0]),e[1]=D_(t,e[1]);var n=this._originalScale.getExtent();return this._fixMin&&(e[0]=O_(e[0],n[0])),this._fixMax&&(e[1]=O_(e[1],n[1])),e},e.prototype.unionExtent=function(t){this._originalScale.unionExtent(t);var e=this.base;t[0]=L_(t[0])/L_(e),t[1]=L_(t[1])/L_(e),S_.unionExtent.call(this,t)},e.prototype.unionExtentFromData=function(t,e){this.unionExtent(t.getApproximateExtent(e))},e.prototype.niceTicks=function(t){t=t||10;var e=this._extent,n=e[1]-e[0];if(!(n===1/0||n<=0)){var i=or(n);for(t/n*i<=.5&&(i*=10);!isNaN(i)&&Math.abs(i)<1&&Math.abs(i)>0;)i*=10;var r=[ji(A_(e[0]/i)*i),ji(C_(e[1]/i)*i)];this._interval=i,this._niceExtent=r}},e.prototype.niceExtent=function(t){M_.niceExtent.call(this,t),this._fixMin=t.fixMin,this._fixMax=t.fixMax},e.prototype.parse=function(t){return t},e.prototype.contain=function(t){return Km(t=L_(t)/L_(this.base),this._extent)},e.prototype.normalize=function(t){return $m(t=L_(t)/L_(this.base),this._extent)},e.prototype.scale=function(t){return t=Jm(t,this._extent),D_(this.base,t)},e.type="log",e}(Wm),P_=k_.prototype;function O_(t,e){return T_(t,I_(e))}P_.getMinorTicks=M_.getMinorTicks,P_.getLabel=M_.getLabel,Wm.registerClass(k_);var R_=function(){function t(t,e,n){this._prepareParams(t,e,n)}return t.prototype._prepareParams=function(t,e,n){n[1]s&&(a=NaN,s=NaN);var h=J(a)||J(s)||t&&!i;this._needCrossZero&&(a>0&&s>0&&!l&&(a=0),a<0&&s<0&&!u&&(s=0));var c=this._determinedMin,p=this._determinedMax;return null!=c&&(a=c,l=!0),null!=p&&(s=p,u=!0),{min:a,max:s,minFixed:l,maxFixed:u,isBlank:h}},t.prototype.modifyDataMinMax=function(t,e){this[E_[t]]=e},t.prototype.setDeterminedMinMax=function(t,e){var n=N_[t];this[n]=e},t.prototype.freeze=function(){this.frozen=!0},t}(),N_={min:"_determinedMin",max:"_determinedMax"},E_={min:"_dataMin",max:"_dataMax"};function z_(t,e,n){var i=t.rawExtentInfo;return i||(i=new R_(t,e,n),t.rawExtentInfo=i,i)}function B_(t,e){return null==e?null:J(e)?NaN:t.parse(e)}function V_(t,e){var n=t.type,i=z_(t,e,t.getExtent()).calculate();t.setBlank(i.isBlank);var r=i.min,o=i.max,a=e.ecModel;if(a&&"time"===n){var s=a_("bar",a),l=!1;if(P(s,(function(t){l=l||t.getBaseAxis()===e.axis})),l){var u=s_(s),h=function(t,e,n,i){var r=n.axis.getExtent(),o=r[1]-r[0],a=u_(i,n.axis);if(void 0===a)return{min:t,max:e};var s=1/0;P(a,(function(t){s=Math.min(t.offset,s)}));var l=-1/0;P(a,(function(t){l=Math.max(t.offset+t.width,l)})),s=Math.abs(s),l=Math.abs(l);var u=s+l,h=e-t,c=h/(1-(s+l)/o)-h;return{min:t-=c*(s/u),max:e+=c*(l/u)}}(r,o,e,u);r=h.min,o=h.max}}return{extent:[r,o],fixMin:i.minFixed,fixMax:i.maxFixed}}function F_(t,e){var n=V_(t,e),i=n.extent,r=e.get("splitNumber");t instanceof k_&&(t.base=e.get("logBase"));var o=t.type;t.setExtent(i[0],i[1]),t.niceExtent({splitNumber:r,fixMin:n.fixMin,fixMax:n.fixMax,minInterval:"interval"===o||"time"===o?e.get("minInterval"):null,maxInterval:"interval"===o||"time"===o?e.get("maxInterval"):null});var a=e.get("interval");null!=a&&t.setInterval&&t.setInterval(a)}function G_(t,e){if(e=e||t.get("type"))switch(e){case"category":return new Qm({ordinalMeta:t.getOrdinalMeta?t.getOrdinalMeta():t.getCategories(),extent:[1/0,-1/0]});case"time":return new g_({locale:t.ecModel.getLocaleModel(),useUTC:t.ecModel.get("useUTC")});default:return new(Wm.getClass(e)||e_)}}function H_(t){var e,n,i=t.getLabelModel().get("formatter"),r="category"===t.type?t.scale.getExtent()[0]:null;return"time"===t.scale.type?(n=i,function(e,i){return t.scale.getFormattedLabel(e,i,n)}):"string"==typeof i?function(e){return function(n){var i=t.scale.getLabel(n);return e.replace("{value}",null!=i?i:"")}}(i):"function"==typeof i?(e=i,function(n,i){return null!=r&&(i=n.value-r),e(W_(t,n),i,null!=n.level?{level:n.level}:null)}):function(e){return t.scale.getLabel(e)}}function W_(t,e){return"category"===t.type?t.scale.getLabel(e):e.value}function Y_(t,e){var n=e*Math.PI/180,i=t.width,r=t.height,o=i*Math.abs(Math.cos(n))+Math.abs(r*Math.sin(n)),a=i*Math.abs(Math.sin(n))+Math.abs(r*Math.cos(n));return new Rn(t.x,t.y,o,a)}function X_(t){var e=t.get("interval");return null==e?"auto":e}function U_(t){return"category"===t.type&&0===X_(t.getLabelModel())}function Z_(t,e){var n={};return P(t.mapDimensionsAll(e),(function(e){n[Gm(t,e)]=!0})),z(n)}var j_=function(){function t(){}return t.prototype.getNeedCrossZero=function(){return!this.option.scale},t.prototype.getCoordSysModel=function(){},t}();var q_={isDimensionStacked:Fm,enableDataStack:Vm,getStackedDimension:Gm};var K_=Object.freeze({__proto__:null,createList:function(t){return Hm(t.getSource(),t)},getLayoutRect:Ac,dataStack:q_,createScale:function(t,e){var n=e;e instanceof Sh||(n=new Sh(e));var i=G_(n);return i.setExtent(t[0],t[1]),F_(i,n),i},mixinAxisModelCommonMethods:function(t){L(t,j_)},getECData:ys,createTextStyle:function(t,e){return nh(t,null,null,"normal"!==(e=e||{}).state)},createDimensions:Nm,createSymbol:uy,enableHoverEmphasis:Js});function $_(t,e){return Math.abs(t-e)<1e-8}function J_(t,e,n){var i=0,r=t[0];if(!r)return!1;for(var o=1;o>1^-(1&s),l=l>>1^-(1&l),r=s+=r,o=l+=o,i.push([s/n,l/n])}return i}function ex(t,e){return O(N((t=function(t){if(!t.UTF8Encoding)return t;var e=t,n=e.UTF8Scale;null==n&&(n=1024);for(var i=e.features,r=0;r0})),(function(t){var n=t.properties,i=t.geometry,r=[];if("Polygon"===i.type){var o=i.coordinates;r.push({type:"polygon",exterior:o[0],interiors:o.slice(1)})}"MultiPolygon"===i.type&&P(o=i.coordinates,(function(t){t[0]&&r.push({type:"polygon",exterior:t[0],interiors:t.slice(1)})}));var a=new Q_(n[e||"name"],r,n.cp);return a.properties=n,a}))}var nx=Object.freeze({__proto__:null,linearMap:Ui,round:ji,asc:qi,getPrecision:Ki,getPrecisionSafe:$i,getPixelPrecision:Ji,getPercentWithPrecision:Qi,MAX_SAFE_INTEGER:tr,remRadian:er,isRadianAroundZero:nr,parseDate:rr,quantity:or,quantityExponent:ar,nice:sr,quantile:lr,reformIntervals:ur,isNumeric:cr,numericToNumber:hr}),ix=Object.freeze({__proto__:null,parse:rr,format:Zh}),rx=Object.freeze({__proto__:null,extendShape:bu,extendPath:Su,makePath:Tu,makeImage:Cu,mergePath:Du,resizePath:Lu,createIcon:Uu,updateProps:Ou,initProps:Ru,getTransform:Vu,clipPointsByRect:Yu,clipRectByRect:Xu,registerShape:Mu,getShapeClass:Iu,Group:zi,Image:Ja,Text:ls,Circle:Tl,Ellipse:Al,Sector:Wl,Ring:Xl,Polygon:ql,Polyline:$l,Rect:os,Line:tu,BezierCurve:ru,Arc:au,IncrementalDisplayable:vu,CompoundPath:su,LinearGradient:uu,RadialGradient:hu,BoundingRect:Rn}),ox=Object.freeze({__proto__:null,addCommas:hc,toCamelCase:cc,normalizeCssArray:pc,encodeHTML:gc,formatTpl:_c,getTooltipMarker:xc,formatTime:function(t,e,n){"week"!==t&&"month"!==t&&"quarter"!==t&&"half-year"!==t&&"year"!==t||(t="MM-dd\nyyyy");var i=rr(e),r=n?"UTC":"",o=i["get"+r+"FullYear"](),a=i["get"+r+"Month"]()+1,s=i["get"+r+"Date"](),l=i["get"+r+"Hours"](),u=i["get"+r+"Minutes"](),h=i["get"+r+"Seconds"](),c=i["get"+r+"Milliseconds"]();return t=t.replace("MM",Yh(a,2)).replace("M",a).replace("yyyy",o).replace("yy",o%100+"").replace("dd",Yh(s,2)).replace("d",s).replace("hh",Yh(l,2)).replace("h",l).replace("mm",Yh(u,2)).replace("m",u).replace("ss",Yh(h,2)).replace("s",h).replace("SSS",Yh(c,3))},capitalFirst:function(t){return t?t.charAt(0).toUpperCase()+t.substr(1):t},truncateText:ro,getTextRect:function(t,e,n,i,r,o,a,s){return gr(),new ls({style:{text:t,font:e,align:n,verticalAlign:i,padding:r,rich:o,overflow:a?"truncate":null,lineHeight:s}}).getBoundingRect()}}),ax=Object.freeze({__proto__:null,map:O,each:P,indexOf:A,inherits:D,reduce:R,filter:N,bind:B,curry:V,isArray:F,isString:H,isObject:X,isFunction:G,extend:I,defaults:T,clone:w,merge:S}),sx=Lr();function lx(t){return"category"===t.type?function(t){var e=t.getLabelModel(),n=hx(t,e);return!e.get("show")||t.scale.isBlank()?{labels:[],labelCategoryInterval:n.labelCategoryInterval}:n}(t):function(t){var e=t.scale.getTicks(),n=H_(t);return{labels:O(e,(function(e,i){return{formattedLabel:n(e,i),rawLabel:t.scale.getLabel(e),tickValue:e.value}}))}}(t)}function ux(t,e){return"category"===t.type?function(t,e){var n,i,r=cx(t,"ticks"),o=X_(e),a=px(r,o);if(a)return a;e.get("show")&&!t.scale.isBlank()||(n=[]);if(G(o))n=gx(t,o,!0);else if("auto"===o){var s=hx(t,t.getLabelModel());i=s.labelCategoryInterval,n=O(s.labels,(function(t){return t.tickValue}))}else n=fx(t,i=o,!0);return dx(r,o,{ticks:n,tickCategoryInterval:i})}(t,e):{ticks:O(t.scale.getTicks(),(function(t){return t.value}))}}function hx(t,e){var n,i,r=cx(t,"labels"),o=X_(e),a=px(r,o);return a||(G(o)?n=gx(t,o):(i="auto"===o?function(t){var e=sx(t).autoInterval;return null!=e?e:sx(t).autoInterval=t.calculateCategoryInterval()}(t):o,n=fx(t,i)),dx(r,o,{labels:n,labelCategoryInterval:i}))}function cx(t,e){return sx(t)[e]||(sx(t)[e]=[])}function px(t,e){for(var n=0;n1&&h/l>2&&(u=Math.round(Math.ceil(u/l)*l));var c=U_(t),p=a.get("showMinLabel")||c,d=a.get("showMaxLabel")||c;p&&u!==o[0]&&g(o[0]);for(var f=u;f<=o[1];f+=l)g(f);function g(t){var e={value:t};s.push(n?t:{formattedLabel:i(e),rawLabel:r.getLabel(e),tickValue:t})}return d&&f-l!==o[1]&&g(o[1]),s}function gx(t,e,n){var i=t.scale,r=H_(t),o=[];return P(i.getTicks(),(function(t){var a=i.getLabel(t),s=t.value;e(t.value,a)&&o.push(n?s:{formattedLabel:r(t),rawLabel:a,tickValue:s})})),o}var yx=[0,1],vx=function(){function t(t,e,n){this.onBand=!1,this.inverse=!1,this.dim=t,this.scale=e,this._extent=n||[0,0]}return t.prototype.contain=function(t){var e=this._extent,n=Math.min(e[0],e[1]),i=Math.max(e[0],e[1]);return t>=n&&t<=i},t.prototype.containData=function(t){return this.scale.contain(t)},t.prototype.getExtent=function(){return this._extent.slice()},t.prototype.getPixelPrecision=function(t){return Ji(t||this.scale.getExtent(),this._extent)},t.prototype.setExtent=function(t,e){var n=this._extent;n[0]=t,n[1]=e},t.prototype.dataToCoord=function(t,e){var n=this._extent,i=this.scale;return t=i.normalize(t),this.onBand&&"ordinal"===i.type&&mx(n=n.slice(),i.count()),Ui(t,yx,n,e)},t.prototype.coordToData=function(t,e){var n=this._extent,i=this.scale;this.onBand&&"ordinal"===i.type&&mx(n=n.slice(),i.count());var r=Ui(t,n,yx,e);return this.scale.scale(r)},t.prototype.pointToData=function(t,e){},t.prototype.getTicksCoords=function(t){var e=(t=t||{}).tickModel||this.getTickModel(),n=O(ux(this,e).ticks,(function(t){return{coord:this.dataToCoord("ordinal"===this.scale.type?this.scale.getRawOrdinalNumber(t):t),tickValue:t}}),this);return function(t,e,n,i){var r=e.length;if(!t.onBand||n||!r)return;var o,a,s=t.getExtent();if(1===r)e[0].coord=s[0],o=e[1]={coord:s[0]};else{var l=e[r-1].tickValue-e[0].tickValue,u=(e[r-1].coord-e[0].coord)/l;P(e,(function(t){t.coord-=u/2})),a=1+t.scale.getExtent()[1]-e[r-1].tickValue,o={coord:e[r-1].coord+u*a},e.push(o)}var h=s[0]>s[1];c(e[0].coord,s[0])&&(i?e[0].coord=s[0]:e.shift());i&&c(s[0],e[0].coord)&&e.unshift({coord:s[0]});c(s[1],o.coord)&&(i?o.coord=s[1]:e.pop());i&&c(o.coord,s[1])&&e.push({coord:s[1]});function c(t,e){return t=ji(t),e=ji(e),h?t>e:t0&&t<100||(t=5),O(this.scale.getMinorTicks(t),(function(t){return O(t,(function(t){return{coord:this.dataToCoord(t),tickValue:t}}),this)}),this)},t.prototype.getViewLabels=function(){return lx(this).labels},t.prototype.getLabelModel=function(){return this.model.getModel("axisLabel")},t.prototype.getTickModel=function(){return this.model.getModel("axisTick")},t.prototype.getBandWidth=function(){var t=this._extent,e=this.scale.getExtent(),n=e[1]-e[0]+(this.onBand?1:0);0===n&&(n=1);var i=Math.abs(t[1]-t[0]);return Math.abs(i)/n},t.prototype.calculateCategoryInterval=function(){return function(t){var e=function(t){var e=t.getLabelModel();return{axisRotate:t.getRotate?t.getRotate():t.isHorizontal&&!t.isHorizontal()?90:0,labelRotate:e.get("rotate")||0,font:e.getFont()}}(t),n=H_(t),i=(e.axisRotate-e.labelRotate)/180*Math.PI,r=t.scale,o=r.getExtent(),a=r.count();if(o[1]-o[0]<1)return 0;var s=1;a>40&&(s=Math.max(1,Math.floor(a/40)));for(var l=o[0],u=t.dataToCoord(l+1)-t.dataToCoord(l),h=Math.abs(u*Math.cos(i)),c=Math.abs(u*Math.sin(i)),p=0,d=0;l<=o[1];l+=s){var f,g,y=Fn(n({value:l}),e.font,"center","top");f=1.3*y.width,g=1.3*y.height,p=Math.max(p,f,7),d=Math.max(d,g,7)}var v=p/h,m=d/c;isNaN(v)&&(v=1/0),isNaN(m)&&(m=1/0);var _=Math.max(0,Math.floor(Math.min(v,m))),x=sx(t.model),b=t.getExtent(),w=x.lastAutoInterval,S=x.lastTickCount;return null!=w&&null!=S&&Math.abs(w-_)<=1&&Math.abs(S-a)<=1&&w>_&&x.axisExtent0===b[0]&&x.axisExtent1===b[1]?_=w:(x.lastTickCount=a,x.lastAutoInterval=_,x.axisExtent0=b[0],x.axisExtent1=b[1]),_}(this)},t}();function mx(t,e){var n=(t[1]-t[0])/e/2;t[0]+=n,t[1]-=n}function _x(t){return document.createElementNS("http://www.w3.org/2000/svg",t)}function xx(t,e,n,i,r){for(var o=e.length,a=n.length,s=t.newPos,l=s-i,u=0;s+1=i&&l+1>=r){for(var u=[],h=0;h=i&&c+1>=r)return Sx(l.components);s[a]=l}else s[a]=void 0}var f;o++}for(;o<=a;){var p=c();if(p)return p}}(t,e,n)}var Ix="none",Tx=Math.round,Cx=Math.sin,Ax=Math.cos,Dx=Math.PI,Lx=2*Math.PI,kx=180/Dx,Px=1e-4;function Ox(t){return Tx(1e3*t)/1e3}function Rx(t){return Tx(1e4*t)/1e4}function Nx(t){return t-1e-4}function Ex(t,e){e&&zx(t,"transform","matrix("+Ox(e[0])+","+Ox(e[1])+","+Ox(e[2])+","+Ox(e[3])+","+Rx(e[4])+","+Rx(e[5])+")")}function zx(t,e,n){(!n||"linear"!==n.type&&"radial"!==n.type)&&t.setAttribute(e,n)}function Bx(t,e,n){var i=null==e.opacity?1:e.opacity;if(n instanceof Ja)t.style.opacity=i+"";else{if(function(t){var e=t.fill;return null!=e&&e!==Ix}(e)){var r=e.fill;zx(t,"fill",r="transparent"===r?Ix:r),zx(t,"fill-opacity",(null!=e.fillOpacity?e.fillOpacity*i:i)+"")}else zx(t,"fill",Ix);if(function(t){var e=t.stroke;return null!=e&&e!==Ix}(e)){var o=e.stroke;zx(t,"stroke",o="transparent"===o?Ix:o);var a=e.lineWidth,s=e.strokeNoScale?n.getLineScale():1;zx(t,"stroke-width",(s?a/s:0)+""),zx(t,"paint-order",e.strokeFirst?"stroke":"fill"),zx(t,"stroke-opacity",(null!=e.strokeOpacity?e.strokeOpacity*i:i)+"");var l=e.lineDash&&a>0&&py(e.lineDash,a);if(l){var u=e.lineDashOffset;s&&1!==s&&(l=O(l,(function(t){return t/s})),u&&(u=Tx(u/=s))),zx(t,"stroke-dasharray",l.join(",")),zx(t,"stroke-dashoffset",(u||0)+"")}else zx(t,"stroke-dasharray","");e.lineCap&&zx(t,"stroke-linecap",e.lineCap),e.lineJoin&&zx(t,"stroke-linejoin",e.lineJoin),e.miterLimit&&zx(t,"stroke-miterlimit",e.miterLimit+"")}else zx(t,"stroke",Ix)}}var Vx=function(){function t(){}return t.prototype.reset=function(){this._d=[],this._str=""},t.prototype.moveTo=function(t,e){this._add("M",t,e)},t.prototype.lineTo=function(t,e){this._add("L",t,e)},t.prototype.bezierCurveTo=function(t,e,n,i,r,o){this._add("C",t,e,n,i,r,o)},t.prototype.quadraticCurveTo=function(t,e,n,i){this._add("Q",t,e,n,i)},t.prototype.arc=function(t,e,n,i,r,o){this.ellipse(t,e,n,n,0,i,r,o)},t.prototype.ellipse=function(t,e,n,i,r,o,a,s){var l=0===this._d.length,u=a-o,h=!s,c=Math.abs(u),p=Nx(c-Lx)||(h?u>=Lx:-u>=Lx),d=u>0?u%Lx:u%Lx+Lx,f=!1;f=!!p||!Nx(c)&&d>=Dx==!!h;var g=Rx(t+n*Ax(o)),y=Rx(e+i*Cx(o));p&&(u=h?Lx-1e-4:1e-4-Lx,f=!0,l&&this._d.push("M",g,y));var v=Rx(t+n*Ax(o+u)),m=Rx(e+i*Cx(o+u));if(isNaN(g)||isNaN(y)||isNaN(n)||isNaN(i)||isNaN(r)||isNaN(kx)||isNaN(v)||isNaN(m))return"";this._d.push("A",Rx(n),Rx(i),Tx(r*kx),+f,+h,v,m)},t.prototype.rect=function(t,e,n,i){this._add("M",t,e),this._add("L",t+n,e),this._add("L",t+n,e+i),this._add("L",t,e+i),this._add("L",t,e)},t.prototype.closePath=function(){this._d.length>0&&this._add("Z")},t.prototype._add=function(t,e,n,i,r,o,a,s,l){this._d.push(t);for(var u=1;u=0;--n)if(e[n]===t)return!0;return!1}),i}return null}return n[0]},t.prototype.doUpdate=function(t,e){if(t){var n=this.getDefs(!1);if(t[this._domName]&&n.contains(t[this._domName]))"function"==typeof e&&e(t);else{var i=this.add(t);i&&(t[this._domName]=i)}}},t.prototype.add=function(t){return null},t.prototype.addDom=function(t){var e=this.getDefs(!0);t.parentNode!==e&&e.appendChild(t)},t.prototype.removeDom=function(t){var e=this.getDefs(!1);e&&t[this._domName]&&(e.removeChild(t[this._domName]),t[this._domName]=null)},t.prototype.getDoms=function(){var t=this.getDefs(!1);if(!t)return[];var e=[];return P(this._tagNames,(function(n){for(var i=t.getElementsByTagName(n),r=0;r-1){var s=qe(a)[3],l=Je(a);o.setAttribute("stop-color","#"+l),o.setAttribute("stop-opacity",s+"")}else o.setAttribute("stop-color",n[i].color);e.appendChild(o)}t.__dom=e},e.prototype.markUsed=function(e){if(e.style){var n=e.style.fill;n&&n.__dom&&t.prototype.markDomUsed.call(this,n.__dom),(n=e.style.stroke)&&n.__dom&&t.prototype.markDomUsed.call(this,n.__dom)}},e}(Yx);function qx(t){return t&&(!!t.image||!!t.svgElement)}var Kx=new ty,$x=function(t){function e(e,n){return t.call(this,e,n,["pattern"],"__pattern_in_use__")||this}return n(e,t),e.prototype.addWithoutUpdate=function(t,e){if(e&&e.style){var n=this;P(["fill","stroke"],(function(i){var r=e.style[i];if(qx(r)){var o=n.getDefs(!0),a=Kx.get(r);a?o.contains(a)||n.addDom(a):a=n.add(r),n.markUsed(e);var s=a.getAttribute("id");t.setAttribute(i,"url(#"+s+")")}}))}},e.prototype.add=function(t){if(qx(t)){var e=this.createElement("pattern");return t.id=null==t.id?this.nextId++:t.id,e.setAttribute("id","zr"+this._zrId+"-pattern-"+t.id),e.setAttribute("x","0"),e.setAttribute("y","0"),e.setAttribute("patternUnits","userSpaceOnUse"),this.updateDom(t,e),this.addDom(e),e}},e.prototype.update=function(t){if(qx(t)){var e=this;this.doUpdate(t,(function(){var n=Kx.get(t);e.updateDom(t,n)}))}},e.prototype.updateDom=function(t,e){var n=t.svgElement;if(n instanceof SVGElement)n.parentNode!==e&&(e.innerHTML="",e.appendChild(n),e.setAttribute("width",t.svgWidth+""),e.setAttribute("height",t.svgHeight+""));else{var i=void 0,r=e.getElementsByTagName("image");if(r.length){if(!t.image)return void e.removeChild(r[0]);i=r[0]}else t.image&&(i=this.createElement("image"));if(i){var o=void 0;if("string"==typeof t.image?o=t.image:t.image instanceof HTMLImageElement?o=t.image.src:t.image instanceof HTMLCanvasElement&&(o=t.image.toDataURL()),o){i.setAttribute("href",o),i.setAttribute("x","0"),i.setAttribute("y","0");var a=to(o,i,{dirty:function(){}},(function(t){e.setAttribute("width",t.width+""),e.setAttribute("height",t.height+"")}));a&&a.width&&a.height&&(e.setAttribute("width",a.width+""),e.setAttribute("height",a.height+"")),e.appendChild(i)}}}var s="translate("+(t.x||0)+", "+(t.y||0)+") rotate("+(t.rotation||0)/Math.PI*180+") scale("+(t.scaleX||1)+", "+(t.scaleY||1)+")";e.setAttribute("patternTransform",s),Kx.set(t,e)},e.prototype.markUsed=function(e){e.style&&(qx(e.style.fill)&&t.prototype.markDomUsed.call(this,Kx.get(e.style.fill)),qx(e.style.stroke)&&t.prototype.markDomUsed.call(this,Kx.get(e.style.stroke)))},e}(Yx);function Jx(t){var e=t.__clipPaths;return e&&e.length>0}var Qx=function(t){function e(e,n){var i=t.call(this,e,n,"clipPath","__clippath_in_use__")||this;return i._refGroups={},i._keyDuplicateCount={},i}return n(e,t),e.prototype.markAllUnused=function(){for(var e in t.prototype.markAllUnused.call(this),this._refGroups)this.markDomUnused(this._refGroups[e]);this._keyDuplicateCount={}},e.prototype._getClipPathGroup=function(t,e){if(Jx(t)){var n=t.__clipPaths,i=this._keyDuplicateCount,r=function(t){var e=[];if(t)for(var n=0;n0){var n=this.getDefs(!0),i=e[0],r=void 0,o=void 0;i._dom?(o=i._dom.getAttribute("id"),r=i._dom,n.contains(r)||n.appendChild(r)):(o="zr"+this._zrId+"-clip-"+this.nextId,++this.nextId,(r=this.createElement("clipPath")).setAttribute("id",o),n.appendChild(r),i._dom=r),this.getSvgProxy(i).brush(i);var a=this.getSvgElement(i);r.innerHTML="",r.appendChild(a),t.setAttribute("clip-path","url(#"+o+")"),e.length>1&&this.updateDom(r,e.slice(1))}else t&&t.setAttribute("clip-path","none")},e.prototype.markUsed=function(e){var n=this;e.__clipPaths&&P(e.__clipPaths,(function(e){e._dom&&t.prototype.markDomUsed.call(n,e._dom)}))},e.prototype.removeUnused=function(){t.prototype.removeUnused.call(this);var e={};for(var n in this._refGroups){var i=this._refGroups[n];this.isDomUnused(i)?i.parentNode&&i.parentNode.removeChild(i):e[n]=i}this._refGroups=e},e}(Yx),tb=function(t){function e(e,n){var i=t.call(this,e,n,["filter"],"__filter_in_use__","_shadowDom")||this;return i._shadowDomMap={},i._shadowDomPool=[],i}return n(e,t),e.prototype._getFromPool=function(){var t=this._shadowDomPool.pop();if(!t){(t=this.createElement("filter")).setAttribute("id","zr"+this._zrId+"-shadow-"+this.nextId++);var e=this.createElement("feDropShadow");t.appendChild(e),this.addDom(t)}return t},e.prototype.update=function(t,e){if(function(t){return t&&(t.shadowBlur||t.shadowOffsetX||t.shadowOffsetY)}(e.style)){var n=function(t){var e=t.style,n=t.getGlobalScale();return[e.shadowColor,(e.shadowBlur||0).toFixed(2),(e.shadowOffsetX||0).toFixed(2),(e.shadowOffsetY||0).toFixed(2),n[0],n[1]].join(",")}(e),i=e._shadowDom=this._shadowDomMap[n];i||(i=this._getFromPool(),this._shadowDomMap[n]=i),this.updateDom(t,e,i)}else this.remove(t,e)},e.prototype.remove=function(t,e){null!=e._shadowDom&&(e._shadowDom=null,t.style.filter="")},e.prototype.updateDom=function(t,e,n){var i=n.children[0],r=e.style,o=e.getGlobalScale(),a=o[0],s=o[1];if(a&&s){var l=r.shadowOffsetX||0,u=r.shadowOffsetY||0,h=r.shadowBlur,c=r.shadowColor;i.setAttribute("dx",l/a+""),i.setAttribute("dy",u/s+""),i.setAttribute("flood-color",c);var p=h/2/a+" "+h/2/s;i.setAttribute("stdDeviation",p),n.setAttribute("x","-100%"),n.setAttribute("y","-100%"),n.setAttribute("width","300%"),n.setAttribute("height","300%"),e._shadowDom=n;var d=n.getAttribute("id");t.style.filter="url(#"+d+")"}},e.prototype.removeUnused=function(){if(this.getDefs(!1)){var t=this._shadowDomPool;for(var e in this._shadowDomMap){var n=this._shadowDomMap[e];t.push(n)}this._shadowDomMap={}}},e}(Yx);function eb(t){return parseInt(t,10)}function nb(t){return t instanceof Za?Fx:t instanceof Ja?Gx:t instanceof qa?Wx:Fx}function ib(t,e){return e&&t&&e.parentNode!==t}function rb(t,e,n){if(ib(t,e)&&n){var i=n.nextSibling;i?t.insertBefore(e,i):t.appendChild(e)}}function ob(t,e){if(ib(t,e)){var n=t.firstChild;n?t.insertBefore(e,n):t.appendChild(e)}}function ab(t,e){e&&t&&e.parentNode===t&&t.removeChild(e)}function sb(t){return t.__svgEl}var lb=function(){function t(t,e,n,i){this.type="svg",this.refreshHover=ub("refreshHover"),this.pathToImage=ub("pathToImage"),this.configLayer=ub("configLayer"),this.root=t,this.storage=e,this._opts=n=I({},n||{});var r=_x("svg");r.setAttributeNS("http://www.w3.org/2000/xmlns/","xmlns","http://www.w3.org/2000/svg"),r.setAttributeNS("http://www.w3.org/2000/xmlns/","xmlns:xlink","http://www.w3.org/1999/xlink"),r.setAttribute("version","1.1"),r.setAttribute("baseProfile","full"),r.style.cssText="user-select:none;position:absolute;left:0;top:0;";var o=_x("g");r.appendChild(o);var a=_x("g");r.appendChild(a),this._gradientManager=new jx(i,a),this._patternManager=new $x(i,a),this._clipPathManager=new Qx(i,a),this._shadowManager=new tb(i,a);var s=document.createElement("div");s.style.cssText="overflow:hidden;position:relative",this._svgDom=r,this._svgRoot=a,this._backgroundRoot=o,this._viewport=s,t.appendChild(s),s.appendChild(r),this.resize(n.width,n.height),this._visibleList=[]}return t.prototype.getType=function(){return"svg"},t.prototype.getViewportRoot=function(){return this._viewport},t.prototype.getSvgDom=function(){return this._svgDom},t.prototype.getSvgRoot=function(){return this._svgRoot},t.prototype.getViewportRootOffset=function(){var t=this.getViewportRoot();if(t)return{offsetLeft:t.offsetLeft||0,offsetTop:t.offsetTop||0}},t.prototype.refresh=function(){var t=this.storage.getDisplayList(!0);this._paintList(t)},t.prototype.setBackgroundColor=function(t){this._backgroundRoot&&this._backgroundNode&&this._backgroundRoot.removeChild(this._backgroundNode);var e=_x("rect");e.setAttribute("width",this.getWidth()),e.setAttribute("height",this.getHeight()),e.setAttribute("x",0),e.setAttribute("y",0),e.setAttribute("id",0),e.style.fill=t,this._backgroundRoot.appendChild(e),this._backgroundNode=e},t.prototype.createSVGElement=function(t){return _x(t)},t.prototype.paintOne=function(t){var e=nb(t);return e&&e.brush(t),sb(t)},t.prototype._paintList=function(t){var e=this._gradientManager,n=this._patternManager,i=this._clipPathManager,r=this._shadowManager;e.markAllUnused(),n.markAllUnused(),i.markAllUnused(),r.markAllUnused();for(var o=this._svgRoot,a=this._visibleList,s=t.length,l=[],u=0;u=0;--n)if(e[n]===t)return!0;return!1}),i}return null}return n[0]},t.prototype.resize=function(t,e){var n=this._viewport;n.style.display="none";var i=this._opts;if(null!=t&&(i.width=t),null!=e&&(i.height=e),t=this._getSize(0),e=this._getSize(1),n.style.display="",this._width!==t||this._height!==e){this._width=t,this._height=e;var r=n.style;r.width=t+"px",r.height=e+"px";var o=this._svgDom;o.setAttribute("width",t+""),o.setAttribute("height",e+"")}this._backgroundNode&&(this._backgroundNode.setAttribute("width",t),this._backgroundNode.setAttribute("height",e))},t.prototype.getWidth=function(){return this._width},t.prototype.getHeight=function(){return this._height},t.prototype._getSize=function(t){var e=this._opts,n=["width","height"][t],i=["clientWidth","clientHeight"][t],r=["paddingLeft","paddingTop"][t],o=["paddingRight","paddingBottom"][t];if(null!=e[n]&&"auto"!==e[n])return parseFloat(e[n]);var a=this.root,s=document.defaultView.getComputedStyle(a);return(a[i]||eb(s[n])||eb(a.style[n]))-(eb(s[r])||0)-(eb(s[o])||0)|0},t.prototype.dispose=function(){this.root.innerHTML="",this._svgRoot=this._backgroundRoot=this._svgDom=this._backgroundNode=this._viewport=this.storage=null},t.prototype.clear=function(){var t=this._viewport;t&&t.parentNode&&t.parentNode.removeChild(t)},t.prototype.toDataURL=function(){this.refresh();var t=this._svgDom,e=t.outerHTML||(t.parentNode&&t.parentNode).innerHTML;return"data:image/svg+xml;charset=UTF-8,"+encodeURIComponent(e.replace(/>\n\r<"))},t}();function ub(t){return function(){b('In SVG mode painter not support method "'+t+'"')}}function hb(){return!1}function cb(t,e,n){var i=C(),r=e.getWidth(),o=e.getHeight(),a=i.style;return a&&(a.position="absolute",a.left="0",a.top="0",a.width=r+"px",a.height=o+"px",i.setAttribute("data-zr-dom-id",t)),i.width=r*n,i.height=o*n,i}var pb=function(t){function e(e,n,i){var r,o=t.call(this)||this;o.motionBlur=!1,o.lastFrameAlpha=.7,o.dpr=1,o.virtual=!1,o.config={},o.incremental=!1,o.zlevel=0,o.maxRepaintRectCount=5,o.__dirty=!0,o.__firstTimePaint=!0,o.__used=!1,o.__drawIndex=0,o.__startIndex=0,o.__endIndex=0,o.__prevStartIndex=null,o.__prevEndIndex=null,i=i||Zn,"string"==typeof e?r=cb(e,n,i):X(e)&&(e=(r=e).id),o.id=e,o.dom=r;var a=r.style;return a&&(r.onselectstart=hb,a.webkitUserSelect="none",a.userSelect="none",a.webkitTapHighlightColor="rgba(0,0,0,0)",a["-webkit-touch-callout"]="none",a.padding="0",a.margin="0",a.borderWidth="0"),o.domBack=null,o.ctxBack=null,o.painter=n,o.config=null,o.dpr=i,o}return n(e,t),e.prototype.getElementCount=function(){return this.__endIndex-this.__startIndex},e.prototype.afterBrush=function(){this.__prevStartIndex=this.__startIndex,this.__prevEndIndex=this.__endIndex},e.prototype.initContext=function(){this.ctx=this.dom.getContext("2d"),this.ctx.dpr=this.dpr},e.prototype.setUnpainted=function(){this.__firstTimePaint=!0},e.prototype.createBackBuffer=function(){var t=this.dpr;this.domBack=cb("back-"+this.id,this.painter,t),this.ctxBack=this.domBack.getContext("2d"),1!==t&&this.ctxBack.scale(t,t)},e.prototype.createRepaintRects=function(t,e,n,i){if(this.__firstTimePaint)return this.__firstTimePaint=!1,null;var r,o=[],a=this.maxRepaintRectCount,s=!1,l=new Rn(0,0,0,0);function u(t){if(t.isFinite()&&!t.isZero())if(0===o.length){(e=new Rn(0,0,0,0)).copy(t),o.push(e)}else{for(var e,n=!1,i=1/0,r=0,u=0;u=a)}}for(var h=this.__startIndex;h15)break}n.prevElClipPaths&&l.restore()};if(u)if(0===u.length)p=s.__endIndex;else for(var x=d.dpr,b=0;b0&&t>i[0]){for(s=0;st);s++);a=n[i[s]]}if(i.splice(s+1,0,t),n[t]=e,!e.virtual)if(a){var l=a.dom;l.nextSibling?o.insertBefore(e.dom,l.nextSibling):o.appendChild(e.dom)}else o.firstChild?o.insertBefore(e.dom,o.firstChild):o.appendChild(e.dom);e.__painter=this}else b("Layer of zlevel "+t+" is not valid")},t.prototype.eachLayer=function(t,e){for(var n=this._zlevelList,i=0;i0?gb:0),this._needsManuallyCompositing),u.__builtin__||b("ZLevel "+l+" has been used by unkown layer "+u.id),u!==o&&(u.__used=!0,u.__startIndex!==r&&(u.__dirty=!0),u.__startIndex=r,u.incremental?u.__drawIndex=-1:u.__drawIndex=r,e(r),o=u),s.__dirty&ei.REDARAW_BIT&&!s.__inHover&&(u.__dirty=!0,u.incremental&&u.__drawIndex<0&&(u.__drawIndex=r))}e(r),this.eachBuiltinLayer((function(t,e){!t.__used&&t.getElementCount()>0&&(t.__dirty=!0,t.__startIndex=t.__endIndex=t.__drawIndex=0),t.__dirty&&t.__drawIndex<0&&(t.__drawIndex=t.__startIndex)}))},t.prototype.clear=function(){return this.eachBuiltinLayer(this._clearLayer),this},t.prototype._clearLayer=function(t){t.clear()},t.prototype.setBackgroundColor=function(t){this._backgroundColor=t,P(this._layers,(function(t){t.setUnpainted()}))},t.prototype.configLayer=function(t,e){if(e){var n=this._layerConfig;n[t]?S(n[t],e,!0):n[t]=e;for(var i=0;i0?n=i[0]:i[1]<0&&(n=i[1]);return n}(r,n),a=i.dim,s=r.dim,l=e.mapDimension(s),u=e.mapDimension(a),h="x"===s||"radius"===s?1:0,c=O(t.dimensions,(function(t){return e.mapDimension(t)})),p=!1,d=e.getCalculationInfo("stackResultDimension");return Fm(e,c[0])&&(p=!0,c[0]=d),Fm(e,c[1])&&(p=!0,c[1]=d),{dataDimsForPoint:c,valueStart:o,valueAxisDim:s,baseAxisDim:a,stacked:!!p,valueDim:l,baseDim:u,baseDataOffset:h,stackedOverDimension:e.getCalculationInfo("stackedOverDimension")}}function Ab(t,e,n,i){var r=NaN;t.stacked&&(r=n.get(n.getCalculationInfo("stackedOverDimension"),i)),isNaN(r)&&(r=t.valueStart);var o=t.baseDataOffset,a=[];return a[o]=n.get(t.baseDim,i),a[1-o]=r,e.dataToPoint(a)}var Db="undefined"!=typeof Float32Array,Lb=Db?Float32Array:Array;function kb(t){return F(t)?Db?new Float32Array(t):t:new Lb(t)}var Pb=Math.min,Ob=Math.max;function Rb(t,e){return isNaN(t)||isNaN(e)}function Nb(t,e,n,i,r,o,a,s,l){for(var u,h,c,p,d,f,g=n,y=0;y=r||g<0)break;if(Rb(v,m)){if(l){g+=o;continue}break}if(g===n)t[o>0?"moveTo":"lineTo"](v,m),c=v,p=m;else{var _=v-u,x=m-h;if(_*_+x*x<.5){g+=o;continue}if(a>0){var b=g+o,w=e[2*b],S=e[2*b+1],M=y+1;if(l)for(;Rb(w,S)&&M=i||Rb(w,S))d=v,f=m;else{T=w-u,C=S-h;var L=v-u,k=w-v,P=m-h,O=S-m,R=void 0,N=void 0;"x"===s?(R=Math.abs(L),N=Math.abs(k),d=v-R*a,f=m,A=v+R*a,D=m):"y"===s?(R=Math.abs(P),N=Math.abs(O),d=v,f=m-R*a,A=v,D=m+R*a):(R=Math.sqrt(L*L+P*P),d=v-T*a*(1-(I=(N=Math.sqrt(k*k+O*O))/(N+R))),f=m-C*a*(1-I),D=m+C*a*I,A=Pb(A=v+T*a*I,Ob(w,v)),D=Pb(D,Ob(S,m)),A=Ob(A,Pb(w,v)),f=m-(C=(D=Ob(D,Pb(S,m)))-m)*R/N,d=Pb(d=v-(T=A-v)*R/N,Ob(u,v)),f=Pb(f,Ob(h,m)),A=v+(T=v-(d=Ob(d,Pb(u,v))))*N/R,D=m+(C=m-(f=Ob(f,Pb(h,m))))*N/R)}t.bezierCurveTo(c,p,d,f,v,m),c=A,p=D}else t.lineTo(v,m)}u=v,h=m,g+=o}return y}var Eb=function(){this.smooth=0,this.smoothConstraint=!0},zb=function(t){function e(e){var n=t.call(this,e)||this;return n.type="ec-polyline",n}return n(e,t),e.prototype.getDefaultStyle=function(){return{stroke:"#000",fill:null}},e.prototype.getDefaultShape=function(){return new Eb},e.prototype.buildPath=function(t,e){var n=e.points,i=0,r=n.length/2;if(e.connectNulls){for(;r>0&&Rb(n[2*r-2],n[2*r-1]);r--);for(;i=0){var y=a?(h-i)*g+i:(u-n)*g+n;return a?[t,y]:[y,t]}n=u,i=h;break;case o.C:u=r[l++],h=r[l++],c=r[l++],p=r[l++],d=r[l++],f=r[l++];var v=a?Eo(n,u,c,d,t,s):Eo(i,h,p,f,t,s);if(v>0)for(var m=0;m=0){y=a?Ro(i,h,p,f,_):Ro(n,u,c,d,_);return a?[t,y]:[y,t]}}n=d,i=f}}},e}(Za),Bb=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return n(e,t),e}(Eb),Vb=function(t){function e(e){var n=t.call(this,e)||this;return n.type="ec-polygon",n}return n(e,t),e.prototype.getDefaultShape=function(){return new Bb},e.prototype.buildPath=function(t,e){var n=e.points,i=e.stackedOnPoints,r=0,o=n.length/2,a=e.smoothMonotone;if(e.connectNulls){for(;o>0&&Rb(n[2*o-2],n[2*o-1]);o--);for(;ri)return!1;return!0}(o,e))){var a=e.mapDimension(o.dim),s={};return P(o.getViewLabels(),(function(t){var e=o.scale.getRawOrdinalNumber(t.tickValue);s[e]=1})),function(t){return!s.hasOwnProperty(e.get(a,t))}}}}function Kb(t,e){return[t[2*e],t[2*e+1]]}function $b(t,e,n,i){if(Wb(e,"cartesian2d")){var r=i.getModel("endLabel"),o=r.get("show"),a=r.get("valueAnimation"),s=i.getData(),l={lastFrameIndex:0},u=o?function(n,i){t._endLabelOnDuring(n,i,s,l,a,r,e)}:null,h=e.getBaseAxis().isHorizontal(),c=Fb(e,n,i,(function(){var e=t._endLabel;e&&n&&null!=l.originalX&&e.attr({x:l.originalX,y:l.originalY})}),u);if(!i.get("clip",!0)){var p=c.shape,d=Math.max(p.width,p.height);h?(p.y-=d,p.height+=2*d):(p.x-=d,p.width+=2*d)}return u&&u(1,c),c}return Gb(e,n,i)}var Jb=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return n(e,t),e.prototype.init=function(){var t=new zi,e=new Tb;this.group.add(e.group),this._symbolDraw=e,this._lineGroup=t},e.prototype.render=function(t,e,n){var i=this,r=t.coordinateSystem,o=this.group,a=t.getData(),s=t.getModel("lineStyle"),l=t.getModel("areaStyle"),u=a.getLayout("points")||[],h="polar"===r.type,c=this._coordSys,p=this._symbolDraw,d=this._polyline,f=this._polygon,g=this._lineGroup,y=t.get("animation"),v=!l.isEmpty(),m=l.get("origin"),_=Cb(r,a,m),x=v&&function(t,e,n){if(!n.valueDim)return[];for(var i=e.count(),r=kb(2*i),o=0;o=0;o--){var a=n[o].dimension,s=t.dimensions[a],l=t.getDimensionInfo(s);if("x"===(i=l&&l.coordDim)||"y"===i){r=n[o];break}}if(r){var u=e.getAxis(i),h=O(r.stops,(function(t){return{offset:0,coord:u.toGlobalCoord(u.dataToCoord(t.value)),color:t.color}})),c=h.length,p=r.outerColors.slice();c&&h[0].coord>h[c-1].coord&&(h.reverse(),p.reverse());var d=h[0].coord-10,f=h[c-1].coord+10,g=f-d;if(g<.001)return"transparent";P(h,(function(t){t.offset=(t.coord-d)/g})),h.push({offset:c?h[c-1].offset:.5,color:p[1]||"transparent"}),h.unshift({offset:c?h[0].offset:.5,color:p[0]||"transparent"});var y=new uu(0,0,0,0,h,!0);return y[i]=d,y[i+"2"]=f,y}}}(a,r)||a.getVisual("style")[a.getVisual("drawType")];d&&c.type===r.type&&I===this._step?(v&&!f?f=this._newPolygon(u,x):f&&!v&&(g.remove(f),f=this._polygon=null),h||this._initOrUpdateEndLabel(t,r,bc(C)),g.setClipPath($b(this,r,!1,t)),b&&p.updateData(a,{isIgnore:w,clipShape:M,disableAnimation:!0,getSymbolPoint:function(t){return[u[2*t],u[2*t+1]]}}),Yb(this._stackedOnPoints,x)&&Yb(this._points,u)||(y?this._doUpdateAnimation(a,x,r,n,I,m):(I&&(u=jb(u,r,I),x&&(x=jb(x,r,I))),d.setShape({points:u}),f&&f.setShape({points:u,stackedOnPoints:x})))):(b&&p.updateData(a,{isIgnore:w,clipShape:M,disableAnimation:!0,getSymbolPoint:function(t){return[u[2*t],u[2*t+1]]}}),y&&this._initSymbolLabelAnimation(a,r,M),I&&(u=jb(u,r,I),x&&(x=jb(x,r,I))),d=this._newPolyline(u),v&&(f=this._newPolygon(u,x)),h||this._initOrUpdateEndLabel(t,r,bc(C)),g.setClipPath($b(this,r,!0,t)));var A=t.get(["emphasis","focus"]),D=t.get(["emphasis","blurScope"]);(d.useStyle(T(s.getLineStyle(),{fill:"none",stroke:C,lineJoin:"bevel"})),nl(d,t,"lineStyle"),d.style.lineWidth>0&&"bolder"===t.get(["emphasis","lineStyle","width"]))&&(d.getState("emphasis").style.lineWidth=d.style.lineWidth+1);ys(d).seriesIndex=t.seriesIndex,Js(d,A,D);var L=Zb(t.get("smooth")),k=t.get("smoothMonotone"),R=t.get("connectNulls");if(d.setShape({smooth:L,smoothMonotone:k,connectNulls:R}),f){var N=a.getCalculationInfo("stackedOnSeries"),E=0;f.useStyle(T(l.getAreaStyle(),{fill:C,opacity:.7,lineJoin:"bevel",decal:a.getVisual("style").decal})),N&&(E=Zb(N.get("smooth"))),f.setShape({smooth:L,stackedOnSmooth:E,smoothMonotone:k,connectNulls:R}),nl(f,t,"areaStyle"),ys(f).seriesIndex=t.seriesIndex,Js(f,A,D)}var z=function(t){i._changePolyState(t)};a.eachItemGraphicEl((function(t){t&&(t.onHoverStateChange=z)})),this._polyline.onHoverStateChange=z,this._data=a,this._coordSys=r,this._stackedOnPoints=x,this._points=u,this._step=I,this._valueOrigin=m},e.prototype.dispose=function(){},e.prototype.highlight=function(t,e,n,i){var r=t.getData(),o=Dr(r,i);if(this._changePolyState("emphasis"),!(o instanceof Array)&&null!=o&&o>=0){var a=r.getLayout("points"),s=r.getItemGraphicEl(o);if(!s){var l=a[2*o],u=a[2*o+1];if(isNaN(l)||isNaN(u))return;if(this._clipShapeForSymbol&&!this._clipShapeForSymbol.contain(l,u))return;(s=new bb(r,o)).x=l,s.y=u,s.setZ(t.get("zlevel"),t.get("z")),s.__temp=!0,r.setItemGraphicEl(o,s),s.stopSymbolAnimation(!0),this.group.add(s)}s.highlight()}else yf.prototype.highlight.call(this,t,e,n,i)},e.prototype.downplay=function(t,e,n,i){var r=t.getData(),o=Dr(r,i);if(this._changePolyState("normal"),null!=o&&o>=0){var a=r.getItemGraphicEl(o);a&&(a.__temp?(r.setItemGraphicEl(o,null),this.group.remove(a)):a.downplay())}else yf.prototype.downplay.call(this,t,e,n,i)},e.prototype._changePolyState=function(t){var e=this._polygon;Vs(this._polyline,t),e&&Vs(e,t)},e.prototype._newPolyline=function(t){var e=this._polyline;return e&&this._lineGroup.remove(e),e=new zb({shape:{points:t},segmentIgnoreThreshold:2,z2:10}),this._lineGroup.add(e),this._polyline=e,e},e.prototype._newPolygon=function(t,e){var n=this._polygon;return n&&this._lineGroup.remove(n),n=new Vb({shape:{points:t,stackedOnPoints:e},segmentIgnoreThreshold:2}),this._lineGroup.add(n),this._polygon=n,n},e.prototype._initSymbolLabelAnimation=function(t,e,n){var i,r,o=e.getBaseAxis(),a=o.inverse;"cartesian2d"===e.type?(i=o.isHorizontal(),r=!1):"polar"===e.type&&(i="angle"===o.dim,r=!0);var s=t.hostModel,l=s.get("animationDuration");"function"==typeof l&&(l=l(null));var u=s.get("animationDelay")||0,h="function"==typeof u?u(null):u;t.eachItemGraphicEl((function(t,o){var s=t;if(s){var c=[t.x,t.y],p=void 0,d=void 0,f=void 0;if(r){var g=n,y=e.pointToCoord(c);i?(p=g.startAngle,d=g.endAngle,f=-y[1]/180*Math.PI):(p=g.r0,d=g.r,f=y[0])}else{var v=n;i?(p=v.x,d=v.x+v.width,f=t.x):(p=v.y+v.height,d=v.y,f=t.y)}var m=d===p?0:(f-p)/(d-p);a&&(m=1-m);var _="function"==typeof u?u(o):l*m+h,x=s.getSymbolPath(),b=x.getTextContent();s.attr({scaleX:0,scaleY:0}),s.animateTo({scaleX:1,scaleY:1},{duration:200,delay:_}),b&&b.animateFrom({style:{opacity:0}},{duration:300,delay:_}),x.disableLabelAnimation=!0}}))},e.prototype._initOrUpdateEndLabel=function(t,e,n){var i=t.getModel("endLabel");if(i.get("show")){var r=t.getData(),o=this._polyline,a=this._endLabel;a||((a=this._endLabel=new ls({z2:200})).ignoreClip=!0,o.setTextContent(this._endLabel),o.disableLabelAnimation=!0);var s=function(t){for(var e,n,i=t.length/2;i>0&&(e=t[2*i-2],n=t[2*i-1],isNaN(e)||isNaN(n));i--);return i-1}(r.getLayout("points"));s>=0&&(th(o,eh(t,"endLabel"),{inheritColor:n,labelFetcher:t,labelDataIndex:s,defaultText:function(t,e,n){return null!=n?xb(r,n):_b(r,t)},enableTextSetter:!0},function(t,e){var n=e.getBaseAxis(),i=n.isHorizontal(),r=n.inverse,o=i?r?"right":"left":"center",a=i?"middle":r?"top":"bottom";return{normal:{align:t.get("align")||o,verticalAlign:t.get("verticalAlign")||a}}}(i,e)),o.textConfig.position=null)}else this._endLabel&&(this._polyline.removeTextContent(),this._endLabel=null)},e.prototype._endLabelOnDuring=function(t,e,n,i,r,o,a){var s=this._endLabel,l=this._polyline;if(s){t<1&&null==i.originalX&&(i.originalX=s.x,i.originalY=s.y);var u=n.getLayout("points"),h=n.hostModel,c=h.get("connectNulls"),p=o.get("precision"),d=o.get("distance")||0,f=a.getBaseAxis(),g=f.isHorizontal(),y=f.inverse,v=e.shape,m=y?g?v.x:v.y+v.height:g?v.x+v.width:v.y,_=(g?d:0)*(y?-1:1),x=(g?0:-d)*(y?-1:1),b=g?"x":"y",w=function(t,e,n){for(var i,r,o=t.length/2,a="x"===n?0:1,s=0,l=-1,u=0;u=e||i>=e&&r<=e){l=u;break}s=u,i=r}else i=r;return{range:[s,l],t:(e-i)/(r-i)}}(u,m,b),S=w.range,M=S[1]-S[0],I=void 0;if(M>=1){if(M>1&&!c){var T=Kb(u,S[0]);s.attr({x:T[0]+_,y:T[1]+x}),r&&(I=h.getRawValue(S[0]))}else{(T=l.getPointOn(m,b))&&s.attr({x:T[0]+_,y:T[1]+x});var C=h.getRawValue(S[0]),A=h.getRawValue(S[1]);r&&(I=Br(n,p,C,A,w.t))}i.lastFrameIndex=S[0]}else{var D=1===t||i.lastFrameIndex>0?S[0]:0;T=Kb(u,D);r&&(I=h.getRawValue(D)),s.attr({x:T[0]+_,y:T[1]+x})}r&&uh(s).setLabelText(I)}},e.prototype._doUpdateAnimation=function(t,e,n,i,r,o){var a=this._polyline,s=this._polygon,l=t.hostModel,u=function(t,e,n,i,r,o,a,s){for(var l=function(t,e){var n=[];return e.diff(t).add((function(t){n.push({cmd:"+",idx:t})})).update((function(t,e){n.push({cmd:"=",idx:e,idx1:t})})).remove((function(t){n.push({cmd:"-",idx:t})})).execute(),n}(t,e),u=[],h=[],c=[],p=[],d=[],f=[],g=[],y=Cb(r,e,a),v=Cb(o,t,s),m=t.getLayout("points")||[],_=e.getLayout("points")||[],x=0;x3e3||s&&Ub(c,d)>3e3)return a.setShape({points:p}),void(s&&s.setShape({points:p,stackedOnPoints:d}));a.shape.__points=u.current,a.shape.points=h;var f={shape:{points:p}};u.current!==h&&(f.shape.__points=u.next),a.stopAnimation(),Ou(a,f,l),s&&(s.setShape({points:h,stackedOnPoints:c}),s.stopAnimation(),Ou(s,{shape:{stackedOnPoints:d}},l),a.shape.points!==s.shape.points&&(s.shape.points=a.shape.points));for(var g=[],y=u.status,v=0;ve&&(e=t[n]);return isFinite(e)?e:NaN},min:function(t){for(var e=1/0,n=0;n10&&"cartesian2d"===o.type&&r){var s=o.getBaseAxis(),l=o.getOtherAxis(s),u=s.getExtent(),h=n.getDevicePixelRatio(),c=Math.abs(u[1]-u[0])*(h||1),p=Math.round(a/c);if(p>1){"lttb"===r&&t.setData(i.lttbDownSample(i.mapDimension(l.dim),1/p));var d=void 0;"string"==typeof r?d=tw[r]:"function"==typeof r&&(d=r),d&&t.setData(i.downSample(i.mapDimension(l.dim),1/p,d,ew))}}}}}var iw=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n}return n(e,t),e.prototype.getInitialData=function(t,e){return Hm(this.getSource(),this,{useEncodeDefaulter:!0})},e.prototype.getMarkerPosition=function(t){var e=this.coordinateSystem;if(e){var n=e.dataToPoint(e.clampData(t)),i=this.getData(),r=i.getLayout("offset"),o=i.getLayout("size");return n[e.getBaseAxis().isHorizontal()?0:1]+=r+o/2,n}return[NaN,NaN]},e.type="series.__base_bar__",e.defaultOption={zlevel:0,z:2,coordinateSystem:"cartesian2d",legendHoverLink:!0,barMinHeight:0,barMinAngle:0,large:!1,largeThreshold:400,progressive:3e3,progressiveChunkMode:"mod"},e}(rf);rf.registerClass(iw);var rw=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n}return n(e,t),e.prototype.getInitialData=function(){return Hm(this.getSource(),this,{useEncodeDefaulter:!0,createInvertedIndices:!!this.get("realtimeSort",!0)||null})},e.prototype.getProgressive=function(){return!!this.get("large")&&this.get("progressive")},e.prototype.getProgressiveThreshold=function(){var t=this.get("progressiveThreshold"),e=this.get("largeThreshold");return e>t&&(t=e),t},e.prototype.brushSelector=function(t,e,n){return n.rect(e.getItemLayout(t))},e.type="series.bar",e.dependencies=["grid","polar"],e.defaultOption=Th(iw.defaultOption,{clip:!0,roundCap:!1,showBackground:!1,backgroundStyle:{color:"rgba(180, 180, 180, 0.2)",borderColor:null,borderWidth:0,borderType:"solid",borderRadius:0,shadowBlur:0,shadowColor:null,shadowOffsetX:0,shadowOffsetY:0,opacity:1},select:{itemStyle:{borderColor:"#212121"}},realtimeSort:!1}),e}(iw),ow=function(){this.cx=0,this.cy=0,this.r0=0,this.r=0,this.startAngle=0,this.endAngle=2*Math.PI,this.clockwise=!0},aw=function(t){function e(e){var n=t.call(this,e)||this;return n.type="sausage",n}return n(e,t),e.prototype.getDefaultShape=function(){return new ow},e.prototype.buildPath=function(t,e){var n=e.cx,i=e.cy,r=Math.max(e.r0||0,0),o=Math.max(e.r,0),a=.5*(o-r),s=r+a,l=e.startAngle,u=e.endAngle,h=e.clockwise,c=Math.cos(l),p=Math.sin(l),d=Math.cos(u),f=Math.sin(u);(h?u-l<2*Math.PI:l-u<2*Math.PI)&&(t.moveTo(c*r+n,p*r+i),t.arc(c*s+n,p*s+i,a,-Math.PI+l,l,!h)),t.arc(n,i,o,l,u,!h),t.moveTo(d*o+n,f*o+i),t.arc(d*s+n,f*s+i,a,u-2*Math.PI,u-Math.PI,!h),0!==r&&(t.arc(n,i,r,u,l,h),t.moveTo(c*r+n,f*r+i)),t.closePath()},e}(Za),sw=["itemStyle","borderWidth"],lw=["itemStyle","borderRadius"],uw=[0,0],hw=Math.max,cw=Math.min;var pw=function(t){function e(){var n=t.call(this)||this;return n.type=e.type,n._isFirstFrame=!0,n}return n(e,t),e.prototype.render=function(t,e,n,i){this._model=t,this._removeOnRenderedListener(n),this._updateDrawMode(t);var r=t.get("coordinateSystem");("cartesian2d"===r||"polar"===r)&&(this._isLargeDraw?this._renderLarge(t,e,n):this._renderNormal(t,e,n,i))},e.prototype.incrementalPrepareRender=function(t){this._clear(),this._updateDrawMode(t),this._updateLargeClip(t)},e.prototype.incrementalRender=function(t,e){this._incrementalRenderLarge(t,e)},e.prototype._updateDrawMode=function(t){var e=t.pipelineContext.large;null!=this._isLargeDraw&&e===this._isLargeDraw||(this._isLargeDraw=e,this._clear())},e.prototype._renderNormal=function(t,e,n,i){var r,o=this.group,a=t.getData(),s=this._data,l=t.coordinateSystem,u=l.getBaseAxis();"cartesian2d"===l.type?r=u.isHorizontal():"polar"===l.type&&(r="angle"===u.dim);var h=t.isAnimationEnabled()?t:null,c=function(t,e){var n=t.get("realtimeSort",!0),i=e.getBaseAxis();0;if(n&&"category"===i.type&&"cartesian2d"===e.type)return{baseAxis:i,otherAxis:e.getOtherAxis(i)}}(t,l);c&&this._enableRealtimeSort(c,a,n);var p=t.get("clip",!0)||c,d=function(t,e){var n=t.getArea&&t.getArea();if(Wb(t,"cartesian2d")){var i=t.getBaseAxis();if("category"!==i.type||!i.onBand){var r=e.getLayout("bandWidth");i.isHorizontal()?(n.x-=r,n.width+=2*r):(n.y-=r,n.height+=2*r)}}return n}(l,a);o.removeClipPath();var f=t.get("roundCap",!0),g=t.get("showBackground",!0),y=t.getModel("backgroundStyle"),v=y.get("borderRadius")||0,m=[],_=this._backgroundEls,x=i&&i.isInitSort,b=i&&"changeAxisOrder"===i.type;function w(t){var e=yw[l.type](a,t),n=function(t,e,n){return new("polar"===t.type?Wl:os)({shape:ww(e,n,t),silent:!0,z2:0})}(l,r,e);return n.useStyle(y.getItemStyle()),"cartesian2d"===l.type&&n.setShape("r",v),m[t]=n,n}a.diff(s).add((function(e){var n=a.getItemModel(e),i=yw[l.type](a,e,n);if(g&&w(e),a.hasValue(e)){var s=!1;p&&(s=dw[l.type](d,i));var y=fw[l.type](t,a,e,i,r,h,u.model,!1,f);vw(y,a,e,n,i,t,r,"polar"===l.type),x?y.attr({shape:i}):c?gw(c,h,y,i,e,r,!1,!1):Ru(y,{shape:i},t,e),a.setItemGraphicEl(e,y),o.add(y),y.ignore=s}})).update((function(e,n){var i=a.getItemModel(e),S=yw[l.type](a,e,i);if(g){var M=void 0;0===_.length?M=w(n):((M=_[n]).useStyle(y.getItemStyle()),"cartesian2d"===l.type&&M.setShape("r",v),m[e]=M);var I=yw[l.type](a,e);Ou(M,{shape:ww(r,I,l)},h,e)}var T=s.getItemGraphicEl(n);if(!a.hasValue(e))return o.remove(T),void(T=null);var C=!1;p&&(C=dw[l.type](d,S))&&o.remove(T),T||(T=fw[l.type](t,a,e,S,r,h,u.model,!!T,f)),b||vw(T,a,e,i,S,t,r,"polar"===l.type),x?T.attr({shape:S}):c?gw(c,h,T,S,e,r,!0,b):Ou(T,{shape:S},t,e,null),a.setItemGraphicEl(e,T),T.ignore=C,o.add(T)})).remove((function(e){var n=s.getItemGraphicEl(e);n&&zu(n,t,e)})).execute();var S=this._backgroundGroup||(this._backgroundGroup=new zi);S.removeAll();for(var M=0;Mo)return!0;o=u}return!1},e.prototype._isOrderDifferentInView=function(t,e){for(var n=e.scale,i=n.getExtent(),r=Math.max(0,i[0]),o=Math.min(i[1],n.getOrdinalMeta().categories.length-1);r<=o;++r)if(t.ordinalNumbers[r]!==n.getRawOrdinalNumber(r))return!0},e.prototype._updateSortWithinSameData=function(t,e,n,i){if(this._isOrderChangedWithinSameData(t,e,n)){var r=this._dataSort(t,n,e);this._isOrderDifferentInView(r,n)&&(this._removeOnRenderedListener(i),i.dispatchAction({type:"changeAxisOrder",componentType:n.dim+"Axis",axisId:n.index,sortInfo:r}))}},e.prototype._dispatchInitSort=function(t,e,n){var i=e.baseAxis,r=this._dataSort(t,i,(function(n){return t.get(t.mapDimension(e.otherAxis.dim),n)}));n.dispatchAction({type:"changeAxisOrder",componentType:i.dim+"Axis",isInitSort:!0,axisId:i.index,sortInfo:r,animation:{duration:0}})},e.prototype.remove=function(t,e){this._clear(this._model),this._removeOnRenderedListener(e)},e.prototype.dispose=function(t,e){this._removeOnRenderedListener(e)},e.prototype._removeOnRenderedListener=function(t){this._onRendered&&(t.getZr().off("rendered",this._onRendered),this._onRendered=null)},e.prototype._clear=function(t){var e=this.group,n=this._data;t&&t.isAnimationEnabled()&&n&&!this._isLargeDraw?(this._removeBackground(),this._backgroundEls=[],n.eachItemGraphicEl((function(e){zu(e,t,ys(e).dataIndex)}))):e.removeAll(),this._data=null,this._isFirstFrame=!0},e.prototype._removeBackground=function(){this.group.remove(this._backgroundGroup),this._backgroundGroup=null},e.type="bar",e}(yf),dw={cartesian2d:function(t,e){var n=e.width<0?-1:1,i=e.height<0?-1:1;n<0&&(e.x+=e.width,e.width=-e.width),i<0&&(e.y+=e.height,e.height=-e.height);var r=t.x+t.width,o=t.y+t.height,a=hw(e.x,t.x),s=cw(e.x+e.width,r),l=hw(e.y,t.y),u=cw(e.y+e.height,o),h=sr?s:a,e.y=c&&l>o?u:l,e.width=h?0:s-a,e.height=c?0:u-l,n<0&&(e.x+=e.width,e.width=-e.width),i<0&&(e.y+=e.height,e.height=-e.height),h||c},polar:function(t,e){var n=e.r0<=e.r?1:-1;if(n<0){var i=e.r;e.r=e.r0,e.r0=i}var r=cw(e.r,t.r),o=hw(e.r0,t.r0);e.r=r,e.r0=o;var a=r-o<0;if(n<0){i=e.r;e.r=e.r0,e.r0=i}return a}},fw={cartesian2d:function(t,e,n,i,r,o,a,s,l){var u=new os({shape:I({},i),z2:1});(u.__dataIndex=n,u.name="item",o)&&(u.shape[r?"height":"width"]=0);return u},polar:function(t,e,n,i,r,o,a,s,l){var u=i.startAngle0?1:-1,a=i.height>0?1:-1;return{x:i.x+o*r/2,y:i.y+a*r/2,width:i.width-o*r,height:i.height-a*r}},polar:function(t,e,n){var i=t.getItemLayout(e);return{cx:i.cx,cy:i.cy,r0:i.r0,r:i.r,startAngle:i.startAngle,endAngle:i.endAngle}}};function vw(t,e,n,i,r,o,a,s){var l=e.getItemVisual(n,"style");s||t.setShape("r",i.get(lw)||0),t.useStyle(l);var u=i.getShallow("cursor");if(u&&t.attr("cursor",u),!s){var h=a?r.height>0?"bottom":"top":r.width>0?"left":"right",c=eh(i);th(t,c,{labelFetcher:o,labelDataIndex:n,defaultText:_b(o.getData(),n),inheritColor:l.fill,defaultOpacity:l.opacity,defaultOutsidePosition:h}),hh(t.getTextContent(),c,o.getRawValue(n),(function(t){return xb(e,t)}))}var p=i.getModel(["emphasis"]);Js(t,p.get("focus"),p.get("blurScope")),nl(t,i),function(t){return null!=t.startAngle&&null!=t.endAngle&&t.startAngle===t.endAngle}(r)&&(t.style.fill="none",t.style.stroke="none",P(t.states,(function(t){t.style&&(t.style.fill=t.style.stroke="none")})))}var mw=function(){},_w=function(t){function e(e){var n=t.call(this,e)||this;return n.type="largeBar",n}return n(e,t),e.prototype.getDefaultShape=function(){return new mw},e.prototype.buildPath=function(t,e){for(var n=e.points,i=this.__startPoint,r=this.__baseDimIdx,o=0;o=c&&y<=p&&(l<=v?h>=l&&h<=v:h>=v&&h<=l))return a[d]}return-1}(this,t.offsetX,t.offsetY);ys(this).dataIndex=e>=0?e:null}),30,!1);function ww(t,e,n){if(Wb(n,"cartesian2d")){var i=e,r=n.getArea();return{x:t?i.x:r.x,y:t?r.y:i.y,width:t?i.width:r.width,height:t?r.height:i.height}}var o=e;return{cx:(r=n.getArea()).cx,cy:r.cy,r0:t?r.r0:o.r0,r:t?r.r:o.r,startAngle:t?o.startAngle:0,endAngle:t?o.endAngle:2*Math.PI}}var Sw=2*Math.PI,Mw=Math.PI/180;function Iw(t,e,n){e.eachSeriesByType(t,(function(t){var e=t.getData(),i=e.mapDimension("value"),r=function(t,e){return Ac(t.getBoxLayoutParams(),{width:e.getWidth(),height:e.getHeight()})}(t,n),o=t.get("center"),a=t.get("radius");F(a)||(a=[0,a]),F(o)||(o=[o,o]);var s=Zi(r.width,n.getWidth()),l=Zi(r.height,n.getHeight()),u=Math.min(s,l),h=Zi(o[0],s)+r.x,c=Zi(o[1],l)+r.y,p=Zi(a[0],u/2),d=Zi(a[1],u/2),f=-t.get("startAngle")*Mw,g=t.get("minAngle")*Mw,y=0;e.each(i,(function(t){!isNaN(t)&&y++}));var v=e.getSum(i),m=Math.PI/(v||y)*2,_=t.get("clockwise"),x=t.get("roseType"),b=t.get("stillShowZeroSum"),w=e.getDataExtent(i);w[0]=0;var S=Sw,M=0,I=f,T=_?1:-1;if(e.setLayout({viewRect:r,r:d}),e.each(i,(function(t,n){var i;if(isNaN(t))e.setItemLayout(n,{angle:NaN,startAngle:NaN,endAngle:NaN,clockwise:_,cx:h,cy:c,r0:p,r:x?NaN:d});else{(i="area"!==x?0===v&&b?m:t*m:Sw/y)n?a:o,h=Math.abs(l.label.y-n);if(h>u.maxY){var c=l.label.x-e-l.len2*r,p=i+l.len,f=Math.abs(c)0?"right":"left":L>0?"left":"right"}var F=y.get("rotate");if(O="number"==typeof F?F*(Math.PI/180):F?L<0?-D+Math.PI:-D:0,o=!!O,p.x=I,p.y=T,p.rotation=O,p.setStyle({verticalAlign:"middle"}),R){p.setStyle({align:A});var G=p.states.select;G&&(G.x+=p.x,G.y+=p.y)}else{var H=p.getBoundingRect().clone();H.applyTransform(p.getComputedTransform());var W=(p.style.margin||0)+2.1;H.y-=W/2,H.height+=W,r.push({label:p,labelLine:f,position:v,len:S,len2:M,minTurnAngle:w.get("minTurnAngle"),maxSurfaceAngle:w.get("maxSurfaceAngle"),surfaceNormal:new In(L,k),linePoints:C,textAlign:A,labelDistance:m,labelAlignTo:_,edgeDistance:x,bleedMargin:b,rect:H})}s.setTextConfig({inside:R})}})),!o&&t.get("avoidLabelOverlap")&&function(t,e,n,i,r,o,a,s){for(var l=[],u=[],h=Number.MAX_VALUE,c=-Number.MAX_VALUE,p=0;p0){for(var l=o.getItemLayout(0),u=1;isNaN(l&&l.startAngle)&&u=n.r0}},e.type="pie",e}(yf);function Rw(t,e,n){e=F(e)&&{coordDimensions:e}||I({},e);var i=t.getSource(),r=Nm(i,e),o=new Pm(r,t);return o.initData(i,n),o}var Nw=function(){function t(t,e){this._getDataWithEncodedVisual=t,this._getRawData=e}return t.prototype.getAllNames=function(){var t=this._getRawData();return t.mapArray(t.getName)},t.prototype.containName=function(t){return this._getRawData().indexOfName(t)>=0},t.prototype.indexOfName=function(t){return this._getDataWithEncodedVisual().indexOfName(t)},t.prototype.getItemVisual=function(t,e){return this._getDataWithEncodedVisual().getItemVisual(t,e)},t}(),Ew=function(t){function e(){var e=null!==t&&t.apply(this,arguments)||this;return e.useColorPaletteOnData=!0,e}return n(e,t),e.prototype.init=function(e){t.prototype.init.apply(this,arguments),this.legendVisualProvider=new Nw(B(this.getData,this),B(this.getRawData,this)),this._defaultLabelLine(e)},e.prototype.mergeOption=function(){t.prototype.mergeOption.apply(this,arguments)},e.prototype.getInitialData=function(){return Rw(this,{coordDimensions:["value"],encodeDefaulter:V(Qc,this)})},e.prototype.getDataParams=function(e){var n=this.getData(),i=t.prototype.getDataParams.call(this,e),r=[];return n.each(n.mapDimension("value"),(function(t){r.push(t)})),i.percent=Qi(r,e,n.hostModel.get("percentPrecision")),i.$vars.push("percent"),i},e.prototype._defaultLabelLine=function(t){xr(t,"labelLine",["show"]);var e=t.labelLine,n=t.emphasis.labelLine;e.show=e.show&&t.label.show,n.show=n.show&&t.emphasis.label.show},e.type="series.pie",e.defaultOption={zlevel:0,z:2,legendHoverLink:!0,center:["50%","50%"],radius:[0,"75%"],clockwise:!0,startAngle:90,minAngle:0,minShowLabelAngle:0,selectedOffset:10,percentPrecision:2,stillShowZeroSum:!0,left:0,top:0,right:0,bottom:0,width:null,height:null,label:{rotate:0,show:!0,overflow:"truncate",position:"outer",alignTo:"none",edgeDistance:"25%",bleedMargin:10,distanceToLabelLine:5},labelLine:{show:!0,length:15,length2:15,smooth:!1,minTurnAngle:90,maxSurfaceAngle:90,lineStyle:{width:1,type:"solid"}},itemStyle:{borderWidth:1},labelLayout:{hideOverlap:!0},emphasis:{scale:!0,scaleSize:5},avoidLabelOverlap:!0,animationType:"expansion",animationDuration:1e3,animationTypeUpdate:"transition",animationEasingUpdate:"cubicInOut",animationDurationUpdate:500,animationEasing:"cubicInOut"},e}(rf);var zw=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n.hasSymbolVisual=!0,n}return n(e,t),e.prototype.getInitialData=function(t,e){return Hm(this.getSource(),this,{useEncodeDefaulter:!0})},e.prototype.getProgressive=function(){var t=this.option.progressive;return null==t?this.option.large?5e3:this.get("progressive"):t},e.prototype.getProgressiveThreshold=function(){var t=this.option.progressiveThreshold;return null==t?this.option.large?1e4:this.get("progressiveThreshold"):t},e.prototype.brushSelector=function(t,e,n){return n.point(e.getItemLayout(t))},e.type="series.scatter",e.dependencies=["grid","polar","geo","singleAxis","calendar"],e.defaultOption={coordinateSystem:"cartesian2d",zlevel:0,z:2,legendHoverLink:!0,symbolSize:10,large:!1,largeThreshold:2e3,itemStyle:{opacity:.8},emphasis:{scale:!0},clip:!0,select:{itemStyle:{borderColor:"#212121"}}},e}(rf),Bw=function(){},Vw=function(t){function e(e){return t.call(this,e)||this}return n(e,t),e.prototype.getDefaultShape=function(){return new Bw},e.prototype.buildPath=function(t,e){var n=e.points,i=e.size,r=this.symbolProxy,o=r.shape,a=t.getContext?t.getContext():t;if(a&&i[0]<4)this._ctx=a;else{this._ctx=null;for(var s=0;s=0;s--){var l=2*s,u=i[l]-o/2,h=i[l+1]-a/2;if(t>=u&&e>=h&&t<=u+o&&e<=h+a)return s}return-1},e}(Za),Fw=function(){function t(){this.group=new zi}return t.prototype.isPersistent=function(){return!this._incremental},t.prototype.updateData=function(t,e){this.group.removeAll();var n=new Vw({rectHover:!0,cursor:"default"});n.setShape({points:t.getLayout("points")}),this._setCommon(n,t,!1,e),this.group.add(n),this._incremental=null},t.prototype.updateLayout=function(t){if(!this._incremental){var e=t.getLayout("points");this.group.eachChild((function(t){if(null!=t.startIndex){var n=2*(t.endIndex-t.startIndex),i=4*t.startIndex*2;e=new Float32Array(e.buffer,i,n)}t.setShape("points",e)}))}},t.prototype.incrementalPrepareUpdate=function(t){this.group.removeAll(),this._clearIncremental(),t.count()>2e6?(this._incremental||(this._incremental=new vu({silent:!0})),this.group.add(this._incremental)):this._incremental=null},t.prototype.incrementalUpdate=function(t,e,n){var i;this._incremental?(i=new Vw,this._incremental.addDisplayable(i,!0)):((i=new Vw({rectHover:!0,cursor:"default",startIndex:t.start,endIndex:t.end})).incremental=!0,this.group.add(i)),i.setShape({points:e.getLayout("points")}),this._setCommon(i,e,!!this._incremental,n)},t.prototype._setCommon=function(t,e,n,i){var r=e.hostModel;i=i||{};var o=e.getVisual("symbolSize");t.setShape("size",o instanceof Array?o:[o,o]),t.softClipShape=i.clipShape||null,t.symbolProxy=uy(e.getVisual("symbol"),0,0,0,0),t.setColor=t.symbolProxy.setColor;var a=t.shape.size[0]<4;t.useStyle(r.getModel("itemStyle").getItemStyle(a?["color","shadowBlur","shadowColor"]:["color"]));var s=e.getVisual("style"),l=s&&s.fill;if(l&&t.setColor(l),!n){var u=ys(t);u.seriesIndex=r.seriesIndex,t.on("mousemove",(function(e){u.dataIndex=null;var n=t.findDataIndex(e.offsetX,e.offsetY);n>=0&&(u.dataIndex=n+(t.startIndex||0))}))}},t.prototype.remove=function(){this._clearIncremental(),this._incremental=null,this.group.removeAll()},t.prototype._clearIncremental=function(){var t=this._incremental;t&&t.clearDisplaybles()},t}(),Gw=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n}return n(e,t),e.prototype.render=function(t,e,n){var i=t.getData();this._updateSymbolDraw(i,t).updateData(i,{clipShape:this._getClipShape(t)}),this._finished=!0},e.prototype.incrementalPrepareRender=function(t,e,n){var i=t.getData();this._updateSymbolDraw(i,t).incrementalPrepareUpdate(i),this._finished=!1},e.prototype.incrementalRender=function(t,e,n){this._symbolDraw.incrementalUpdate(t,e.getData(),{clipShape:this._getClipShape(e)}),this._finished=t.end===e.getData().count()},e.prototype.updateTransform=function(t,e,n){var i=t.getData();if(this.group.dirty(),!this._finished||i.count()>1e4||!this._symbolDraw.isPersistent())return{update:!0};var r=Qb("").reset(t,e,n);r.progress&&r.progress({start:0,end:i.count(),count:i.count()},i),this._symbolDraw.updateLayout(i)},e.prototype._getClipShape=function(t){var e=t.coordinateSystem,n=e&&e.getArea&&e.getArea();return t.get("clip",!0)?n:null},e.prototype._updateSymbolDraw=function(t,e){var n=this._symbolDraw,i=e.pipelineContext.large;return n&&i===this._isLargeDraw||(n&&n.remove(),n=this._symbolDraw=i?new Fw:new Tb,this._isLargeDraw=i,this.group.removeAll()),this.group.add(n.group),n},e.prototype.remove=function(t,e){this._symbolDraw&&this._symbolDraw.remove(!0),this._symbolDraw=null},e.prototype.dispose=function(){},e.type="scatter",e}(yf),Hw=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return n(e,t),e.type="grid",e.dependencies=["xAxis","yAxis"],e.layoutMode="box",e.defaultOption={show:!1,zlevel:0,z:0,left:"10%",top:60,right:"10%",bottom:70,containLabel:!1,backgroundColor:"rgba(0,0,0,0)",borderWidth:1,borderColor:"#ccc"},e}(Nc),Ww=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return n(e,t),e.prototype.getCoordSysModel=function(){return this.getReferringComponents("grid",Or).models[0]},e.type="cartesian2dAxis",e}(Nc);L(Ww,j_);var Yw={show:!0,zlevel:0,z:0,inverse:!1,name:"",nameLocation:"end",nameRotate:null,nameTruncate:{maxWidth:null,ellipsis:"...",placeholder:"."},nameTextStyle:{},nameGap:15,silent:!1,triggerEvent:!1,tooltip:{show:!1},axisPointer:{},axisLine:{show:!0,onZero:!0,onZeroAxisIndex:null,lineStyle:{color:"#6E7079",width:1,type:"solid"},symbol:["none","none"],symbolSize:[10,15]},axisTick:{show:!0,inside:!1,length:5,lineStyle:{width:1}},axisLabel:{show:!0,inside:!1,rotate:0,showMinLabel:null,showMaxLabel:null,margin:8,fontSize:12},splitLine:{show:!0,lineStyle:{color:["#E0E6F1"],width:1,type:"solid"}},splitArea:{show:!1,areaStyle:{color:["rgba(250,250,250,0.2)","rgba(210,219,238,0.2)"]}}},Xw=S({boundaryGap:!0,deduplication:null,splitLine:{show:!1},axisTick:{alignWithLabel:!1,interval:"auto"},axisLabel:{interval:"auto"}},Yw),Uw=S({boundaryGap:[0,0],axisLine:{show:"auto"},axisTick:{show:"auto"},splitNumber:5,minorTick:{show:!1,splitNumber:5,length:3,lineStyle:{}},minorSplitLine:{show:!1,lineStyle:{color:"#F4F7FD",width:1}}},Yw),Zw={category:Xw,value:Uw,time:S({scale:!0,splitNumber:6,axisLabel:{showMinLabel:!1,showMaxLabel:!1,rich:{primary:{fontWeight:"bold"}}},splitLine:{show:!1}},Uw),log:T({scale:!0,logBase:10},Uw)},jw={value:1,category:1,time:1,log:1};function qw(t,e,i,r){P(jw,(function(o,a){var s=S(S({},Zw[a],!0),r,!0),l=function(t){function i(){for(var n=[],i=0;ie[1]&&e.reverse(),e},e.prototype.pointToData=function(t,e){return this.coordToData(this.toLocalCoord(t["x"===this.dim?0:1]),e)},e.prototype.setCategorySortInfo=function(t){if("category"!==this.type)return!1;this.model.option.categorySortInfo=t,this.scale.setSortInfo(t)},e}(vx);function nS(t,e,n){n=n||{};var i=t.coordinateSystem,r=e.axis,o={},a=r.getAxesOnZeroOf()[0],s=r.position,l=a?"onZero":s,u=r.dim,h=i.getRect(),c=[h.x,h.x+h.width,h.y,h.y+h.height],p={left:0,right:1,top:0,bottom:1,onZero:2},d=e.get("offset")||0,f="x"===u?[c[2]-d,c[3]+d]:[c[0]-d,c[1]+d];if(a){var g=a.toGlobalCoord(a.dataToCoord(0));f[p.onZero]=Math.max(Math.min(g,f[1]),f[0])}o.position=["y"===u?f[p[l]]:c[0],"x"===u?f[p[l]]:c[3]],o.rotation=Math.PI/2*("x"===u?0:1);o.labelDirection=o.tickDirection=o.nameDirection={top:-1,bottom:1,left:-1,right:1}[s],o.labelOffset=a?f[p[s]]-f[p.onZero]:0,e.get(["axisTick","inside"])&&(o.tickDirection=-o.tickDirection),Q(n.labelInside,e.get(["axisLabel","inside"]))&&(o.labelDirection=-o.labelDirection);var y=e.get(["axisLabel","rotate"]);return o.labelRotate="top"===l?-y:y,o.z2=1,o}function iS(t){return"cartesian2d"===t.get("coordinateSystem")}function rS(t){var e={xAxisModel:null,yAxisModel:null};return P(e,(function(n,i){var r=i.replace(/Model$/,""),o=t.getReferringComponents(r,Or).models[0];e[i]=o})),e}var oS=function(){function t(t,e,n){this.type="grid",this._coordsMap={},this._coordsList=[],this._axesMap={},this._axesList=[],this.axisPointerEnabled=!0,this.dimensions=Jw,this._initCartesian(t,e,n),this.model=t}return t.prototype.getRect=function(){return this._rect},t.prototype.update=function(t,e){var n=this._axesMap;this._updateScale(t,this.model),P(n.x,(function(t){F_(t.scale,t.model)})),P(n.y,(function(t){F_(t.scale,t.model)}));var i={};P(n.x,(function(t){sS(n,"y",t,i)})),P(n.y,(function(t){sS(n,"x",t,i)})),this.resize(this.model,e)},t.prototype.resize=function(t,e,n){var i=t.getBoxLayoutParams(),r=!n&&t.get("containLabel"),o=Ac(i,{width:e.getWidth(),height:e.getHeight()});this._rect=o;var a=this._axesList;function s(){P(a,(function(t){var e=t.isHorizontal(),n=e?[0,o.width]:[0,o.height],i=t.inverse?1:0;t.setExtent(n[i],n[1-i]),function(t,e){var n=t.getExtent(),i=n[0]+n[1];t.toGlobalCoord="x"===t.dim?function(t){return t+e}:function(t){return i-t+e},t.toLocalCoord="x"===t.dim?function(t){return t-e}:function(t){return i-t+e}}(t,e?o.x:o.y)}))}s(),r&&(P(a,(function(t){if(!t.model.get(["axisLabel","inside"])){var e=function(t){var e=t.model,n=t.scale;if(e.get(["axisLabel","show"])&&!n.isBlank()){var i,r,o=n.getExtent();r=n instanceof Qm?n.count():(i=n.getTicks()).length;var a,s=t.getLabelModel(),l=H_(t),u=1;r>40&&(u=Math.ceil(r/40));for(var h=0;h0&&i>0||n<0&&i<0)}(t)}var uS=Math.PI,hS=function(){function t(t,e){this.group=new zi,this.opt=e,this.axisModel=t,T(e,{labelOffset:0,nameDirection:1,tickDirection:1,labelDirection:1,silent:!0,handleAutoShown:function(){return!0}});var n=new zi({x:e.position[0],y:e.position[1],rotation:e.rotation});n.updateTransform(),this._transformGroup=n}return t.prototype.hasBuilder=function(t){return!!cS[t]},t.prototype.add=function(t){cS[t](this.opt,this.axisModel,this.group,this._transformGroup)},t.prototype.getGroup=function(){return this.group},t.innerTextLayout=function(t,e,n){var i,r,o=er(e-t);return nr(o)?(r=n>0?"top":"bottom",i="center"):nr(o-uS)?(r=n>0?"bottom":"top",i="center"):(r="middle",i=o>0&&o0?"right":"left":n>0?"left":"right"),{rotation:o,textAlign:i,textVerticalAlign:r}},t.makeAxisEventDataBase=function(t){var e={componentType:t.mainType,componentIndex:t.componentIndex};return e[t.mainType+"Index"]=t.componentIndex,e},t.isLabelSilent=function(t){var e=t.get("tooltip");return t.get("silent")||!(t.get("triggerEvent")||e&&e.show)},t}(),cS={axisLine:function(t,e,n,i){var r=e.get(["axisLine","show"]);if("auto"===r&&t.handleAutoShown&&(r=t.handleAutoShown("axisLine")),r){var o=e.axis.getExtent(),a=i.transform,s=[o[0],0],l=[o[1],0];a&&(Rt(s,s,a),Rt(l,l,a));var u=I({lineCap:"round"},e.getModel(["axisLine","lineStyle"]).getLineStyle()),h=new tu({subPixelOptimize:!0,shape:{x1:s[0],y1:s[1],x2:l[0],y2:l[1]},style:u,strokeContainThreshold:t.strokeContainThreshold||5,silent:!0,z2:1});h.anid="line",n.add(h);var c=e.get(["axisLine","symbol"]),p=e.get(["axisLine","symbolSize"]),d=e.get(["axisLine","symbolOffset"])||0;if("number"==typeof d&&(d=[d,d]),null!=c){"string"==typeof c&&(c=[c,c]),"string"!=typeof p&&"number"!=typeof p||(p=[p,p]);var f=p[0],g=p[1];P([{rotate:t.rotation+Math.PI/2,offset:d[0],r:0},{rotate:t.rotation-Math.PI/2,offset:d[1],r:Math.sqrt((s[0]-l[0])*(s[0]-l[0])+(s[1]-l[1])*(s[1]-l[1]))}],(function(e,i){if("none"!==c[i]&&null!=c[i]){var r=uy(c[i],-f/2,-g/2,f,g,u.stroke,!0),o=e.r+e.offset;r.attr({rotation:e.rotate,x:s[0]+o*Math.cos(t.rotation),y:s[1]-o*Math.sin(t.rotation),silent:!0,z2:11}),n.add(r)}}))}}},axisTickLabel:function(t,e,n,i){var r=function(t,e,n,i){var r=n.axis,o=n.getModel("axisTick"),a=o.get("show");"auto"===a&&i.handleAutoShown&&(a=i.handleAutoShown("axisTick"));if(!a||r.scale.isBlank())return;for(var s=o.getModel("lineStyle"),l=i.tickDirection*o.get("length"),u=gS(r.getTicksCoords(),e.transform,l,T(s.getLineStyle(),{stroke:n.get(["axisLine","lineStyle","color"])}),"ticks"),h=0;hc[1]?-1:1,d=["start"===s?c[0]-p*h:"end"===s?c[1]+p*h:(c[0]+c[1])/2,fS(s)?t.labelOffset+l*h:0],f=e.get("nameRotate");null!=f&&(f=f*uS/180),fS(s)?o=hS.innerTextLayout(t.rotation,null!=f?f:t.rotation,l):(o=function(t,e,n,i){var r,o,a=er(n-t),s=i[0]>i[1],l="start"===e&&!s||"start"!==e&&s;nr(a-uS/2)?(o=l?"bottom":"top",r="center"):nr(a-1.5*uS)?(o=l?"top":"bottom",r="center"):(o="middle",r=a<1.5*uS&&a>uS/2?l?"left":"right":l?"right":"left");return{rotation:a,textAlign:r,textVerticalAlign:o}}(t.rotation,s,f||0,c),null!=(a=t.axisNameAvailableWidth)&&(a=Math.abs(a/Math.sin(o.rotation)),!isFinite(a)&&(a=null)));var g=u.getFont(),y=e.get("nameTruncate",!0)||{},v=y.ellipsis,m=Q(t.nameTruncateMaxWidth,y.maxWidth,a),_=e.get("tooltip",!0),x=e.mainType,b={componentType:x,name:r,$vars:["name"]};b[x+"Index"]=e.componentIndex;var w=new ls({x:d[0],y:d[1],rotation:o.rotation,silent:hS.isLabelSilent(e),style:nh(u,{text:r,font:g,overflow:"truncate",width:m,ellipsis:v,fill:u.getTextColor()||e.get(["axisLine","lineStyle","color"]),align:u.get("align")||o.textAlign,verticalAlign:u.get("verticalAlign")||o.textVerticalAlign}),z2:1});if(w.tooltip=_&&_.show?I({content:r,formatter:function(){return r},formatterParams:b},_):null,w.__fullText=r,w.anid="name",e.get("triggerEvent")){var S=hS.makeAxisEventDataBase(e);S.targetType="axisName",S.name=r,ys(w).eventData=S}i.add(w),w.updateTransform(),n.add(w),w.decomposeTransform()}}};function pS(t){t&&(t.ignore=!0)}function dS(t,e){var n=t&&t.getBoundingRect().clone(),i=e&&e.getBoundingRect().clone();if(n&&i){var r=ge([]);return _e(r,r,-t.rotation),n.applyTransform(ve([],r,t.getLocalTransform())),i.applyTransform(ve([],r,e.getLocalTransform())),n.intersect(i)}}function fS(t){return"middle"===t||"center"===t}function gS(t,e,n,i,r){for(var o=[],a=[],s=[],l=0;l=0||t===e}function mS(t){var e=_S(t);if(e){var n=e.axisPointerModel,i=e.axis.scale,r=n.option,o=n.get("status"),a=n.get("value");null!=a&&(a=i.parse(a));var s=xS(n);null==o&&(r.status=s?"show":"hide");var l=i.getExtent().slice();l[0]>l[1]&&l.reverse(),(null==a||a>l[1])&&(a=l[1]),a0&&!c.min?c.min=0:null!=c.min&&c.min<0&&!c.max&&(c.max=0);var p=a;null!=c.color&&(p=T({color:c.color},a));var d=S(w(c),{boundaryGap:t,splitNumber:e,scale:n,axisLine:i,axisTick:r,axisLabel:o,name:c.text,nameLocation:"end",nameGap:u,nameTextStyle:p,triggerEvent:h},!1);if(s||(d.name=""),"string"==typeof l){var f=d.name;d.name=l.replace("{value}",null!=f?f:"")}else"function"==typeof l&&(d.name=l(d.name,d));var g=new Sh(d,null,this.ecModel);return L(g,j_.prototype),g.mainType="radar",g.componentIndex=this.componentIndex,g}),this);this._indicatorModels=c},e.prototype.getIndicatorModels=function(){return this._indicatorModels},e.type="radar",e.defaultOption={zlevel:0,z:0,center:["50%","50%"],radius:"75%",startAngle:90,axisName:{show:!0},boundaryGap:[0,0],splitNumber:5,axisNameGap:15,scale:!1,shape:"polygon",axisLine:S({lineStyle:{color:"#bbb"}},HS.axisLine),axisLabel:WS(HS.axisLabel,!1),axisTick:WS(HS.axisTick,!1),splitLine:WS(HS.splitLine,!0),splitArea:WS(HS.splitArea,!0),indicator:[]},e}(Nc),XS=["axisLine","axisTickLabel","axisName"],US=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n}return n(e,t),e.prototype.render=function(t,e,n){this.group.removeAll(),this._buildAxes(t),this._buildSplitLineAndArea(t)},e.prototype._buildAxes=function(t){var e=t.coordinateSystem;P(O(e.getIndicatorAxes(),(function(t){return new hS(t.model,{position:[e.cx,e.cy],rotation:t.angle,labelDirection:-1,tickDirection:-1,nameDirection:1})})),(function(t){P(XS,t.add,t),this.group.add(t.getGroup())}),this)},e.prototype._buildSplitLineAndArea=function(t){var e=t.coordinateSystem,n=e.getIndicatorAxes();if(n.length){var i=t.get("shape"),r=t.getModel("splitLine"),o=t.getModel("splitArea"),a=r.getModel("lineStyle"),s=o.getModel("areaStyle"),l=r.get("show"),u=o.get("show"),h=a.get("color"),c=s.get("color"),p=F(h)?h:[h],d=F(c)?c:[c],f=[],g=[];if("circle"===i)for(var y=n[0].getTicksCoords(),v=e.cx,m=e.cy,_=0;_n[0]&&isFinite(c)&&isFinite(n[0]))}else{a.getTicks().length-1>r&&(u=o(u));c=ji((h=Math.ceil(n[1]/u)*u)-u*r);a.setExtent(c,h),a.setInterval(u)}}))},t.prototype.convertToPixel=function(t,e,n){return console.warn("Not implemented."),null},t.prototype.convertFromPixel=function(t,e,n){return console.warn("Not implemented."),null},t.prototype.containPoint=function(t){return console.warn("Not implemented."),!1},t.create=function(e,n){var i=[];return e.eachComponent("radar",(function(r){var o=new t(r,e,n);i.push(o),r.coordinateSystem=o})),e.eachSeriesByType("radar",(function(t){"radar"===t.get("coordinateSystem")&&(t.coordinateSystem=i[t.get("radarIndex")||0])})),i},t.dimensions=[],t}();function qS(t){t.registerCoordinateSystem("radar",jS),t.registerComponentModel(YS),t.registerComponentView(US)}var KS="\0_ec_interaction_mutex";function $S(t,e){return!!JS(t)[e]}function JS(t){return t[KS]||(t[KS]={})}Yv({type:"takeGlobalCursor",event:"globalCursorTaken",update:"update"},(function(){}));var QS=function(t){function e(e){var n=t.call(this)||this;n._zr=e;var i=B(n._mousedownHandler,n),r=B(n._mousemoveHandler,n),o=B(n._mouseupHandler,n),a=B(n._mousewheelHandler,n),s=B(n._pinchHandler,n);return n.enable=function(t,n){this.disable(),this._opt=T(w(n)||{},{zoomOnMouseWheel:!0,moveOnMouseMove:!0,moveOnMouseWheel:!1,preventDefaultMouseMove:!0}),null==t&&(t=!0),!0!==t&&"move"!==t&&"pan"!==t||(e.on("mousedown",i),e.on("mousemove",r),e.on("mouseup",o)),!0!==t&&"scale"!==t&&"zoom"!==t||(e.on("mousewheel",a),e.on("pinch",s))},n.disable=function(){e.off("mousedown",i),e.off("mousemove",r),e.off("mouseup",o),e.off("mousewheel",a),e.off("pinch",s)},n}return n(e,t),e.prototype.isDragging=function(){return this._dragging},e.prototype.isPinching=function(){return this._pinching},e.prototype.setPointerChecker=function(t){this.pointerChecker=t},e.prototype.dispose=function(){this.disable()},e.prototype._mousedownHandler=function(t){if(!(ne(t)||t.target&&t.target.draggable)){var e=t.offsetX,n=t.offsetY;this.pointerChecker&&this.pointerChecker(t,e,n)&&(this._x=e,this._y=n,this._dragging=!0)}},e.prototype._mousemoveHandler=function(t){if(this._dragging&&nM("moveOnMouseMove",t,this._opt)&&"pinch"!==t.gestureEvent&&!$S(this._zr,"globalPan")){var e=t.offsetX,n=t.offsetY,i=this._x,r=this._y,o=e-i,a=n-r;this._x=e,this._y=n,this._opt.preventDefaultMouseMove&&ee(t.event),eM(this,"pan","moveOnMouseMove",t,{dx:o,dy:a,oldX:i,oldY:r,newX:e,newY:n,isAvailableBehavior:null})}},e.prototype._mouseupHandler=function(t){ne(t)||(this._dragging=!1)},e.prototype._mousewheelHandler=function(t){var e=nM("zoomOnMouseWheel",t,this._opt),n=nM("moveOnMouseWheel",t,this._opt),i=t.wheelDelta,r=Math.abs(i),o=t.offsetX,a=t.offsetY;if(0!==i&&(e||n)){if(e){var s=r>3?1.4:r>1?1.2:1.1;tM(this,"zoom","zoomOnMouseWheel",t,{scale:i>0?s:1/s,originX:o,originY:a,isAvailableBehavior:null})}if(n){var l=Math.abs(i);tM(this,"scrollMove","moveOnMouseWheel",t,{scrollDelta:(i>0?1:-1)*(l>3?.4:l>1?.15:.05),originX:o,originY:a,isAvailableBehavior:null})}}},e.prototype._pinchHandler=function(t){$S(this._zr,"globalPan")||tM(this,"zoom",null,t,{scale:t.pinchScale>1?1.1:1/1.1,originX:t.pinchX,originY:t.pinchY,isAvailableBehavior:null})},e}(Ft);function tM(t,e,n,i,r){t.pointerChecker&&t.pointerChecker(i,r.originX,r.originY)&&(ee(i.event),eM(t,e,n,i,r))}function eM(t,e,n,i,r){r.isAvailableBehavior=B(nM,null,n,i),t.trigger(e,r)}function nM(t,e,n){var i=n[t];return!t||i&&(!H(i)||e.event[i+"Key"])}function iM(t,e,n){var i=t.target;i.x+=e,i.y+=n,i.dirty()}function rM(t,e,n,i){var r=t.target,o=t.zoomLimit,a=t.zoom=t.zoom||1;if(a*=e,o){var s=o.min||0,l=o.max||1/0;a=Math.max(Math.min(l,a),s)}var u=a/t.zoom;t.zoom=a,r.x-=(n-r.x)*(u-1),r.y-=(i-r.y)*(u-1),r.scaleX*=u,r.scaleY*=u,r.dirty()}var oM={axisPointer:1,tooltip:1,brush:1};function aM(t,e,n){var i=e.getComponentByElement(t.topTarget),r=i&&i.coordinateSystem;return i&&i!==n&&!oM.hasOwnProperty(i.mainType)&&r&&r.model!==n}for(var sM=[126,25],lM=[[[0,3.5],[7,11.2],[15,11.9],[30,7],[42,.7],[52,.7],[56,7.7],[59,.7],[64,.7],[64,0],[5,0],[0,3.5]],[[13,16.1],[19,14.7],[16,21.7],[11,23.1],[13,16.1]],[[12,32.2],[14,38.5],[15,38.5],[13,32.2],[12,32.2]],[[16,47.6],[12,53.2],[13,53.2],[18,47.6],[16,47.6]],[[6,64.4],[8,70],[9,70],[8,64.4],[6,64.4]],[[23,82.6],[29,79.8],[30,79.8],[25,82.6],[23,82.6]],[[37,70.7],[43,62.3],[44,62.3],[39,70.7],[37,70.7]],[[48,51.1],[51,45.5],[53,45.5],[50,51.1],[48,51.1]],[[51,35],[51,28.7],[53,28.7],[53,35],[51,35]],[[52,22.4],[55,17.5],[56,17.5],[53,22.4],[52,22.4]],[[58,12.6],[62,7],[63,7],[60,12.6],[58,12.6]],[[0,3.5],[0,93.1],[64,93.1],[64,0],[63,0],[63,92.4],[1,92.4],[1,3.5],[0,3.5]]],uM=0;uM=4&&(s={x:parseFloat(h[0]||0),y:parseFloat(h[1]||0),width:parseFloat(h[2]),height:parseFloat(h[3])})}if(s&&null!=o&&null!=a&&(l=DM(s,o,a),!e.ignoreViewBox)){var c=i;(i=new zi).add(c),c.scaleX=c.scaleY=l.scale,c.x=l.x,c.y=l.y}return e.ignoreRootClip||null==o||null==a||i.setClipPath(new os({shape:{x:0,y:0,width:o,height:a}})),{root:i,width:o,height:a,viewBoxRect:s,viewBoxTransform:l}},t.prototype._parseNode=function(t,e){var n,i,r=t.nodeName.toLowerCase();if("defs"===r?this._isDefine=!0:"text"===r&&(this._isText=!0),this._isDefine){if(i=xM[r]){var o=i.call(this,t),a=t.getAttribute("id");a&&(this._defs[a]=o)}}else(i=vM[r])&&(n=i.call(this,t,e),e.add(n));if(n)for(var s=t.firstChild;s;)1===s.nodeType&&this._parseNode(s,n),3===s.nodeType&&this._isText&&this._parseText(s,n),s=s.nextSibling;"defs"===r?this._isDefine=!1:"text"===r&&(this._isText=!1)},t.prototype._parseText=function(t,e){if(1===t.nodeType){var n=t.getAttribute("dx")||0,i=t.getAttribute("dy")||0;this._textX+=parseFloat(n),this._textY+=parseFloat(i)}var r=new qa({style:{text:t.textContent},x:this._textX||0,y:this._textY||0});bM(e,r),MM(t,r,this._defs);var o=r.style,a=o.fontSize;a&&a<9&&(o.fontSize=9,r.scaleX*=a/9,r.scaleY*=a/9);var s=(o.fontSize||o.fontFamily)&&[o.fontStyle,o.fontWeight,(o.fontSize||12)+"px",o.fontFamily||"sans-serif"].join(" ");o.font=s;var l=r.getBoundingRect();return this._textX+=l.width,e.add(r),r},t.internalField=void(vM={g:function(t,e){var n=new zi;return bM(e,n),MM(t,n,this._defs),n},rect:function(t,e){var n=new os;return bM(e,n),MM(t,n,this._defs),n.setShape({x:parseFloat(t.getAttribute("x")||"0"),y:parseFloat(t.getAttribute("y")||"0"),width:parseFloat(t.getAttribute("width")||"0"),height:parseFloat(t.getAttribute("height")||"0")}),n},circle:function(t,e){var n=new Tl;return bM(e,n),MM(t,n,this._defs),n.setShape({cx:parseFloat(t.getAttribute("cx")||"0"),cy:parseFloat(t.getAttribute("cy")||"0"),r:parseFloat(t.getAttribute("r")||"0")}),n},line:function(t,e){var n=new tu;return bM(e,n),MM(t,n,this._defs),n.setShape({x1:parseFloat(t.getAttribute("x1")||"0"),y1:parseFloat(t.getAttribute("y1")||"0"),x2:parseFloat(t.getAttribute("x2")||"0"),y2:parseFloat(t.getAttribute("y2")||"0")}),n},ellipse:function(t,e){var n=new Al;return bM(e,n),MM(t,n,this._defs),n.setShape({cx:parseFloat(t.getAttribute("cx")||"0"),cy:parseFloat(t.getAttribute("cy")||"0"),rx:parseFloat(t.getAttribute("rx")||"0"),ry:parseFloat(t.getAttribute("ry")||"0")}),n},polygon:function(t,e){var n,i=t.getAttribute("points");i&&(n=wM(i));var r=new ql({shape:{points:n||[]}});return bM(e,r),MM(t,r,this._defs),r},polyline:function(t,e){var n=new Za;bM(e,n),MM(t,n,this._defs);var i,r=t.getAttribute("points");return r&&(i=wM(r)),new $l({shape:{points:i||[]}})},image:function(t,e){var n=new Ja;return bM(e,n),MM(t,n,this._defs),n.setStyle({image:t.getAttribute("xlink:href"),x:+t.getAttribute("x"),y:+t.getAttribute("y"),width:+t.getAttribute("width"),height:+t.getAttribute("height")}),n},text:function(t,e){var n=t.getAttribute("x")||"0",i=t.getAttribute("y")||"0",r=t.getAttribute("dx")||"0",o=t.getAttribute("dy")||"0";this._textX=parseFloat(n)+parseFloat(r),this._textY=parseFloat(i)+parseFloat(o);var a=new zi;return bM(e,a),MM(t,a,this._defs),a},tspan:function(t,e){var n=t.getAttribute("x"),i=t.getAttribute("y");null!=n&&(this._textX=parseFloat(n)),null!=i&&(this._textY=parseFloat(i));var r=t.getAttribute("dx")||0,o=t.getAttribute("dy")||0,a=new zi;return bM(e,a),MM(t,a,this._defs),this._textX+=r,this._textY+=o,a},path:function(t,e){var n=Ml(t.getAttribute("d")||"");return bM(e,n),MM(t,n,this._defs),n}}),t}(),xM={lineargradient:function(t){var e=parseInt(t.getAttribute("x1")||"0",10),n=parseInt(t.getAttribute("y1")||"0",10),i=parseInt(t.getAttribute("x2")||"10",10),r=parseInt(t.getAttribute("y2")||"0",10),o=new uu(e,n,i,r);return function(t,e){var n=t.firstChild;for(;n;){if(1===n.nodeType){var i=n.getAttribute("offset"),r=void 0;r=i.indexOf("%")>0?parseInt(i,10)/100:i?parseFloat(i):0;var o=n.getAttribute("stop-color")||"#000000";e.colorStops.push({offset:r,color:o})}n=n.nextSibling}}(t,o),o}};function bM(t,e){t&&t.__inheritedStyle&&(e.__inheritedStyle||(e.__inheritedStyle={}),T(e.__inheritedStyle,t.__inheritedStyle))}function wM(t){for(var e=ot(t).split(mM),n=[],i=0;i0;o-=2){var a=i[o],s=void 0;switch(r=r||[1,0,0,1,0,0],i[o-1]){case"translate":s=ot(a).split(mM),me(r,r,[parseFloat(s[0]),parseFloat(s[1]||"0")]);break;case"scale":s=ot(a).split(mM),xe(r,r,[parseFloat(s[0]),parseFloat(s[1]||s[0])]);break;case"rotate":s=ot(a).split(mM),_e(r,r,parseFloat(s[0]));break;case"skew":s=ot(a).split(mM),console.warn("Skew transform is not supported yet");break;case"matrix":s=ot(a).split(mM),r[0]=parseFloat(s[0]),r[1]=parseFloat(s[1]),r[2]=parseFloat(s[2]),r[3]=parseFloat(s[3]),r[4]=parseFloat(s[4]),r[5]=parseFloat(s[5])}}e.setLocalTransform(r)}}(t,e),I(o,function(t){var e=t.getAttribute("style"),n={};if(!e)return n;var i,r={};AM.lastIndex=0;for(;null!=(i=AM.exec(e));)r[i[1]]=i[2];for(var o in SM)SM.hasOwnProperty(o)&&null!=r[o]&&(n[SM[o]]=r[o]);return n}(t)),!i))for(var a in SM)if(SM.hasOwnProperty(a)){var s=t.getAttribute(a);null!=s&&(o[SM[a]]=s)}r.style=r.style||{},null!=o.fill&&(r.style.fill=TM(o.fill,n)),null!=o.stroke&&(r.style.stroke=TM(o.stroke,n)),P(["lineWidth","opacity","fillOpacity","strokeOpacity","miterLimit","fontSize"],(function(t){null!=o[t]&&(r.style[t]=parseFloat(o[t]))})),o.textBaseline&&"auto"!==o.textBaseline||(o.textBaseline="alphabetic"),"alphabetic"===o.textBaseline&&(o.textBaseline="bottom"),"start"===o.textAlign&&(o.textAlign="left"),"end"===o.textAlign&&(o.textAlign="right"),P(["lineDashOffset","lineCap","lineJoin","fontWeight","fontFamily","fontStyle","textAlign","textBaseline"],(function(t){null!=o[t]&&(r.style[t]=o[t])})),o.lineDash&&(r.style.lineDash=O(ot(o.lineDash).split(mM),(function(t){return parseFloat(t)}))),r.__inheritedStyle=o}var IM=/url\(\s*#(.*?)\)/;function TM(t,e){var n=e&&t&&t.match(IM);return n?e[ot(n[1])]:t}var CM=/(translate|scale|rotate|skewX|skewY|matrix)\(([\-\s0-9\.e,]*)\)/g;var AM=/([^\s:;]+)\s*:\s*([^:;]+)/g;function DM(t,e,n){var i=e/t.width,r=n/t.height,o=Math.min(i,r);return{scale:o,x:-(t.x+t.width/2)*o+e/2,y:-(t.y+t.height/2)*o+n/2}}var LM=Lr();function kM(t,e){var n,i,r,o,a=t.svgXML;try{rt(null!=(i=(n=a&&(r=a,o={ignoreViewBox:!0,ignoreRootClip:!0},(new _M).parse(r,o))||{}).root))}catch(t){throw new Error("Invalid svg format\n"+t.message)}var s=n.width,l=n.height,u=n.viewBoxRect;if(e||(e=null==s||null==l?i.getBoundingRect():new Rn(0,0,0,0),null!=s&&(e.width=s),null!=l&&(e.height=l)),u){var h=DM(u,e.width,e.height),c=i;(i=new zi).add(c),c.scaleX=c.scaleY=h.scale,c.x=h.x,c.y=h.y}return i.setClipPath(new os({shape:e.plain()})),{root:i,boundingRect:e}}var PM={geoJSON:gM,svg:{load:function(t,e){var n=LM(e).originRoot;if(n)return{root:n,boundingRect:LM(e).boundingRect};var i=kM(e);return LM(e).originRoot=i.root,LM(e).boundingRect=i.boundingRect,i},makeGraphic:function(t,e,n){var i=LM(e),r=i.rootMap||(i.rootMap=ht()),o=r.get(n);if(o)return o;var a=i.originRoot,s=i.boundingRect;return i.originRootHostKey?o=kM(e,s).root:(i.originRootHostKey=n,o=a),r.set(n,o)},removeGraphic:function(t,e,n){var i=LM(e),r=i.rootMap;r&&r.removeKey(n),n===i.originRootHostKey&&(i.originRootHostKey=null)}}},OM=function(t,e,n){var i,r=[],o=ht(),a=ht();return P(EM(t),(function(s){var l=PM[s.type].load(t,s,n);P(l.regions,(function(t){var n=t.name;e&&e.hasOwnProperty(n)&&(t=t.cloneShallow(n=e[n])),r.push(t),o.set(n,t),a.set(n,t.center)}));var u=l.boundingRect;u&&(i?i.union(u):i=u.clone())})),{regions:r,regionsMap:o,nameCoordMap:a,boundingRect:i||new Rn(0,0,0,0)}},RM=function(t,e){var n=EM(t),i=[];return P(n,(function(n){var r=PM[n.type].makeGraphic;r&&i.push(r(t,n,e))})),i},NM=function(t,e){P(EM(t),(function(n){var i=PM[n.type].makeGraphic;i&&i(t,n,e)}))};function EM(t){var e=lg(t)||[];return e}function zM(t){var e=t.getItemStyle(),n=t.get("areaColor");return null!=n&&(e.fill=n),e}var BM=function(){function t(t){var e=new zi;this.uid=Ih("ec_map_draw"),this._controller=new QS(t.getZr()),this._controllerHost={target:e},this.group=e,e.add(this._regionsGroup=new zi),e.add(this._backgroundGroup=new zi)}return t.prototype.draw=function(t,e,n,i,r){var o="geo"===t.mainType,a=t.getData&&t.getData();o&&e.eachComponent({mainType:"series",subType:"map"},(function(e){a||e.getHostGeoModel()!==t||(a=e.getData())}));var s=t.coordinateSystem;this._updateBackground(s);var l,u,h=this._regionsGroup,c=this.group,p=s.getTransformInfo(),d=!h.childAt(0)||r;if(d)c.transform=p.roamTransform,c.decomposeTransform(),c.dirty();else{var f=new ke;f.transform=p.roamTransform,f.decomposeTransform();var g={scaleX:f.scaleX,scaleY:f.scaleY,x:f.x,y:f.y};l=f.scaleX,u=f.scaleY,Ou(c,g,t)}h.removeAll();var y=ht(),v=a&&a.getVisual("visualMeta")&&a.getVisual("visualMeta").length>0;P(s.regions,(function(e){var i=y.get(e.name)||y.set(e.name,new zi),r=new su({segmentIgnoreThreshold:1,shape:{paths:[]}});i.add(r);var s,f=t.getRegionModel(e.name)||t,g=f.getModel("itemStyle"),m=f.getModel("emphasis"),_=m.getModel("itemStyle"),x=f.getModel(["blur","itemStyle"]),b=f.getModel(["select","itemStyle"]),w=zM(g),S=zM(_),M=zM(x),I=zM(b);if(a){s=a.indexOfName(e.name);var T=a.getItemVisual(s,"style"),C=a.getItemVisual(s,"decal");v&&T.fill&&(w.fill=T.fill),C&&(w.decal=ky(C,n))}var A=p.rawScaleX,D=p.rawScaleY,L=p.rawX,k=p.rawY,O=function(t){return[t[0]*A+L,t[1]*D+k]};P(e.geometries,(function(t){if("polygon"===t.type){for(var e=[],n=0;n=0)&&(F=t);var G=O(e.center),H=new ls({x:G[0],y:G[1],scaleX:1/c.scaleX,scaleY:1/c.scaleY,z2:10,silent:!0});th(H,eh(f),{labelFetcher:F,labelDataIndex:V,defaultText:e.name},{normal:{align:"center",verticalAlign:"middle"}}),r.setTextContent(H),r.setTextConfig({local:!0}),r.disableLabelAnimation=!0,d||Ou(H,{scaleX:1/l,scaleY:1/u},t)}if(a)a.setItemGraphicEl(s,i);else{var W=t.getRegionModel(e.name);ys(r).eventData={componentType:"geo",componentIndex:t.componentIndex,geoIndex:t.componentIndex,name:e.name,region:W&&W.option||{}}}(i.__regions||(i.__regions=[])).push(e),i.highDownSilentOnTouch=!!t.get("selectedMode"),Js(i,m.get("focus"),m.get("blurScope")),h.add(i)})),this._updateController(t,e,n),this._updateMapSelectHandler(t,h,n,i)},t.prototype.remove=function(){this._regionsGroup.removeAll(),this._backgroundGroup.removeAll(),this._controller.dispose(),this._mapName&&NM(this._mapName,this.uid),this._mapName=null,this._controllerHost=null},t.prototype._updateBackground=function(t){var e=t.map;this._mapName!==e&&P(RM(e,this.uid),(function(t){this._backgroundGroup.add(t)}),this),this._mapName=e},t.prototype._updateController=function(t,e,n){var i=t.coordinateSystem,r=this._controller,o=this._controllerHost;o.zoomLimit=t.get("scaleLimit"),o.zoom=i.getZoom(),r.enable(t.get("roam")||!1);var a=t.mainType;function s(){var e={type:"geoRoam",componentType:a};return e[a+"Id"]=t.id,e}r.off("pan").on("pan",(function(t){this._mouseDownFlag=!1,iM(o,t.dx,t.dy),n.dispatchAction(I(s(),{dx:t.dx,dy:t.dy}))}),this),r.off("zoom").on("zoom",(function(t){this._mouseDownFlag=!1,rM(o,t.scale,t.originX,t.originY),n.dispatchAction(I(s(),{zoom:t.scale,originX:t.originX,originY:t.originY}));var e=this.group;this._regionsGroup.traverse((function(t){var n=t.getTextContent();n&&(n.scaleX=1/e.scaleX,n.scaleY=1/e.scaleY,n.markRedraw())}))}),this),r.setPointerChecker((function(e,r,o){return i.getViewRectAfterRoam().contain(r,o)&&!aM(e,n,t)}))},t.prototype._updateMapSelectHandler=function(t,e,n,i){var r=this;e.off("mousedown"),t.get("selectedMode")&&(e.on("mousedown",(function(){r._mouseDownFlag=!0})),e.on("click",(function(t){r._mouseDownFlag&&(r._mouseDownFlag=!1)})))},t}(),VM=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n}return n(e,t),e.prototype.render=function(t,e,n,i){if(!i||"mapToggleSelect"!==i.type||i.from!==this.uid){var r=this.group;if(r.removeAll(),!t.getHostGeoModel()){if(i&&"geoRoam"===i.type&&"series"===i.componentType&&i.seriesId===t.id)(o=this._mapDraw)&&r.add(o.group);else if(t.needsDrawMap){var o=this._mapDraw||new BM(n);r.add(o.group),o.draw(t,e,n,this,i),this._mapDraw=o}else this._mapDraw&&this._mapDraw.remove(),this._mapDraw=null;t.get("showLegendSymbol")&&e.getComponent("legend")&&this._renderSymbols(t,e,n)}}},e.prototype.remove=function(){this._mapDraw&&this._mapDraw.remove(),this._mapDraw=null,this.group.removeAll()},e.prototype.dispose=function(){this._mapDraw&&this._mapDraw.remove(),this._mapDraw=null},e.prototype._renderSymbols=function(t,e,n){var i=t.originalData,r=this.group;i.each(i.mapDimension("value"),(function(e,n){if(!isNaN(e)){var o=i.getItemLayout(n);if(o&&o.point){var a=o.point,s=o.offset,l=new Tl({style:{fill:t.getData().getVisual("style").fill},shape:{cx:a[0]+9*s,cy:a[1],r:3},silent:!0,z2:8+(s?0:11)});if(!s){var u=t.mainSeries.getData(),h=i.getName(n),c=u.indexOfName(h),p=i.getItemModel(n),d=p.getModel("label"),f=u.getItemGraphicEl(c);th(l,eh(p),{labelFetcher:{getFormattedLabel:function(e,n){return t.getFormattedLabel(c,n)}}}),l.disableLabelAnimation=!0,d.get("position")||l.setTextConfig({position:"bottom"}),f.onHoverStateChange=function(t){l.useState(t)}}r.add(l)}}}))},e.type="map",e}(yf),FM=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n.needsDrawMap=!1,n.seriesGroup=[],n.getTooltipPosition=function(t){if(null!=t){var e=this.getData().getName(t),n=this.coordinateSystem,i=n.getRegion(e);return i&&n.dataToPoint(i.center)}},n}return n(e,t),e.prototype.getInitialData=function(t){for(var e=Rw(this,{coordDimensions:["value"],encodeDefaulter:V(Qc,this)}),n=ht(),i=[],r=0,o=e.count();r1?(s.width=a,s.height=a/d):(s.height=a,s.width=a*d),s.y=o[1]-s.height/2,s.x=o[0]-s.width/2;else{var g=t.getBoxLayoutParams();g.aspect=d,s=Ac(g,{width:c,height:p})}this.setViewRect(s.x,s.y,s.width,s.height),this.setCenter(t.get("center")),this.setZoom(t.get("zoom"))}L(UM,YM);var qM=new(function(){function t(){this.dimensions=UM.prototype.dimensions}return t.prototype.create=function(t,e){var n=[];t.eachComponent("geo",(function(t,i){var r=t.get("map"),o=t.get("aspectScale"),a=!0,s=lg(r);s&&s[0]&&"svg"===s[0].type?(null==o&&(o=1),a=!1):null==o&&(o=.75);var l=new UM(r+i,r,t.get("nameMap"),a);l.aspectScale=o,l.zoomLimit=t.get("scaleLimit"),n.push(l),t.coordinateSystem=l,l.model=t,l.resize=jM,l.resize(t,e)})),t.eachSeries((function(t){if("geo"===t.get("coordinateSystem")){var e=t.get("geoIndex")||0;t.coordinateSystem=n[e]}}));var i={};return t.eachSeriesByType("map",(function(t){if(!t.getHostGeoModel()){var e=t.getMapType();i[e]=i[e]||[],i[e].push(t)}})),P(i,(function(t,i){var r=O(t,(function(t){return t.get("nameMap")})),o=new UM(i,i,M(r));o.zoomLimit=Q.apply(null,O(t,(function(t){return t.get("scaleLimit")}))),n.push(o),o.resize=jM,o.aspectScale=t[0].get("aspectScale"),o.resize(t[0],e),P(t,(function(t){t.coordinateSystem=o,function(t,e){P(e.get("geoCoord"),(function(e,n){t.addGeoCoord(n,e)}))}(o,t)}))})),n},t.prototype.getFilledRegions=function(t,e,n){for(var i=(t||[]).slice(),r=ht(),o=0;o=0;){var o=e[n];o.hierNode.prelim+=i,o.hierNode.modifier+=i,r+=o.hierNode.change,i+=o.hierNode.shift+r}}(t);var o=(n[0].hierNode.prelim+n[n.length-1].hierNode.prelim)/2;r?(t.hierNode.prelim=r.hierNode.prelim+e(t,r),t.hierNode.modifier=t.hierNode.prelim-o):t.hierNode.prelim=o}else r&&(t.hierNode.prelim=r.hierNode.prelim+e(t,r));t.parentNode.hierNode.defaultAncestor=function(t,e,n,i){if(e){for(var r=t,o=t,a=o.parentNode.children[0],s=e,l=r.hierNode.modifier,u=o.hierNode.modifier,h=a.hierNode.modifier,c=s.hierNode.modifier;s=rI(s),o=oI(o),s&&o;){r=rI(r),a=oI(a),r.hierNode.ancestor=t;var p=s.hierNode.prelim+c-o.hierNode.prelim-u+i(s,o);p>0&&(sI(aI(s,t,n),t,p),u+=p,l+=p),c+=s.hierNode.modifier,u+=o.hierNode.modifier,l+=r.hierNode.modifier,h+=a.hierNode.modifier}s&&!rI(r)&&(r.hierNode.thread=s,r.hierNode.modifier+=c-l),o&&!oI(a)&&(a.hierNode.thread=o,a.hierNode.modifier+=u-h,n=t)}return n}(t,r,t.parentNode.hierNode.defaultAncestor||i[0],e)}function eI(t){var e=t.hierNode.prelim+t.parentNode.hierNode.modifier;t.setLayout({x:e},!0),t.hierNode.modifier+=t.parentNode.hierNode.modifier}function nI(t){return arguments.length?t:lI}function iI(t,e){return t-=Math.PI/2,{x:e*Math.cos(t),y:e*Math.sin(t)}}function rI(t){var e=t.children;return e.length&&t.isExpand?e[e.length-1]:t.hierNode.thread}function oI(t){var e=t.children;return e.length&&t.isExpand?e[0]:t.hierNode.thread}function aI(t,e,n){return t.hierNode.ancestor.parentNode===e.parentNode?t.hierNode.ancestor:n}function sI(t,e,n){var i=n/(e.hierNode.i-t.hierNode.i);e.hierNode.change-=i,e.hierNode.shift+=n,e.hierNode.modifier+=n,e.hierNode.prelim+=n,t.hierNode.change+=i}function lI(t,e){return t.parentNode===e.parentNode?1:2}var uI=function(){this.parentPoint=[],this.childPoints=[]},hI=function(t){function e(e){return t.call(this,e)||this}return n(e,t),e.prototype.getDefaultStyle=function(){return{stroke:"#000",fill:null}},e.prototype.getDefaultShape=function(){return new uI},e.prototype.buildPath=function(t,e){var n=e.childPoints,i=n.length,r=e.parentPoint,o=n[0],a=n[i-1];if(1===i)return t.moveTo(r[0],r[1]),void t.lineTo(o[0],o[1]);var s=e.orient,l="TB"===s||"BT"===s?0:1,u=1-l,h=Zi(e.forkPosition,1),c=[];c[l]=r[l],c[u]=r[u]+(a[u]-r[u])*h,t.moveTo(r[0],r[1]),t.lineTo(c[0],c[1]),t.moveTo(o[0],o[1]),c[l]=o[l],t.lineTo(c[0],c[1]),c[l]=a[l],t.lineTo(c[0],c[1]),t.lineTo(a[0],a[1]);for(var p=1;pm.x)||(x-=Math.PI);var S=b?"left":"right",M=s.getModel("label"),I=M.get("rotate"),C=I*(Math.PI/180),A=y.getTextContent();A&&(y.setTextConfig({position:M.get("position")||S,rotation:null==I?-x:C,origin:"center"}),A.setStyle("verticalAlign","middle"))}var D=s.get(["emphasis","focus"]),L="ancestor"===D?a.getAncestorsIndices():"descendant"===D?a.getDescendantIndices():null;L&&(ys(n).focus=L),function(t,e,n,i,r,o,a,s){var l=e.getModel(),u=t.get("edgeShape"),h=t.get("layout"),c=t.getOrient(),p=t.get(["lineStyle","curveness"]),d=t.get("edgeForkPosition"),f=l.getModel("lineStyle").getLineStyle(),g=i.__edge;if("curve"===u)e.parentNode&&e.parentNode!==n&&(g||(g=i.__edge=new ru({shape:gI(h,c,p,r,r)})),Ou(g,{shape:gI(h,c,p,o,a)},t));else if("polyline"===u)if("orthogonal"===h){if(e!==n&&e.children&&0!==e.children.length&&!0===e.isExpand){for(var y=e.children,v=[],m=0;me&&(e=i.height)}this.height=e+1},t.prototype.getNodeById=function(t){if(this.getId()===t)return this;for(var e=0,n=this.children,i=n.length;e=0&&this.hostTree.data.setItemLayout(this.dataIndex,t,e)},t.prototype.getLayout=function(){return this.hostTree.data.getItemLayout(this.dataIndex)},t.prototype.getModel=function(t){if(!(this.dataIndex<0))return this.hostTree.data.getItemModel(this.dataIndex).getModel(t)},t.prototype.getLevelModel=function(){return(this.hostTree.levelModels||[])[this.depth]},t.prototype.setVisual=function(t,e){this.dataIndex>=0&&this.hostTree.data.setItemVisual(this.dataIndex,t,e)},t.prototype.getVisual=function(t){return this.hostTree.data.getItemVisual(this.dataIndex,t)},t.prototype.getRawIndex=function(){return this.hostTree.data.getRawIndex(this.dataIndex)},t.prototype.getId=function(){return this.hostTree.data.getId(this.dataIndex)},t.prototype.isAncestorOf=function(t){for(var e=t.parentNode;e;){if(e===this)return!0;e=e.parentNode}return!1},t.prototype.isDescendantOf=function(t){return t!==this&&t.isAncestorOf(this)},t}(),TI=function(){function t(t){this.type="tree",this._nodes=[],this.hostModel=t}return t.prototype.eachNode=function(t,e,n){this.root.eachNode(t,e,n)},t.prototype.getNodeByDataIndex=function(t){var e=this.data.getRawIndex(t);return this._nodes[e]},t.prototype.getNodeById=function(t){return this.root.getNodeById(t)},t.prototype.update=function(){for(var t=this.data,e=this._nodes,n=0,i=e.length;no&&(o=t.depth)}));var a=t.expandAndCollapse&&t.initialTreeDepth>=0?t.initialTreeDepth:o;return r.root.eachNode("preorder",(function(t){var e=t.hostTree.data.getRawDataItem(t.dataIndex);t.isExpand=e&&null!=e.collapsed?!e.collapsed:t.depth<=a})),r.data},e.prototype.getOrient=function(){var t=this.get("orient");return"horizontal"===t?t="LR":"vertical"===t&&(t="TB"),t},e.prototype.setZoom=function(t){this.option.zoom=t},e.prototype.setCenter=function(t){this.option.center=t},e.prototype.formatTooltip=function(t,e,n){for(var i=this.getData().tree,r=i.root.children[0],o=i.getNodeByDataIndex(t),a=o.getValue(),s=o.name;o&&o!==r;)s=o.parentNode.name+"."+s,o=o.parentNode;return Yd("nameValue",{name:s,value:a,noValue:isNaN(a)||null==a})},e.type="series.tree",e.layoutMode="box",e.defaultOption={zlevel:0,z:2,coordinateSystem:"view",left:"12%",top:"12%",right:"12%",bottom:"12%",layout:"orthogonal",edgeShape:"curve",edgeForkPosition:"50%",roam:!1,nodeScaleRatio:.4,center:null,zoom:1,orient:"LR",symbol:"emptyCircle",symbolSize:7,expandAndCollapse:!0,initialTreeDepth:2,lineStyle:{color:"#ccc",width:1.5,curveness:.5},itemStyle:{color:"lightsteelblue",borderColor:"#c23531",borderWidth:1.5},label:{show:!0},animationEasing:"linear",animationDuration:700,animationDurationUpdate:500},e}(rf);function AI(t,e){for(var n,i=[t];n=i.pop();)if(e(n),n.isExpand){var r=n.children;if(r.length)for(var o=r.length-1;o>=0;o--)i.push(r[o])}}function DI(t,e){t.eachSeriesByType("tree",(function(t){!function(t,e){var n=function(t,e){return Ac(t.getBoxLayoutParams(),{width:e.getWidth(),height:e.getHeight()})}(t,e);t.layoutInfo=n;var i=t.get("layout"),r=0,o=0,a=null;"radial"===i?(r=2*Math.PI,o=Math.min(n.height,n.width)/2,a=nI((function(t,e){return(t.parentNode===e.parentNode?1:2)/t.depth}))):(r=n.width,o=n.height,a=nI());var s=t.getData().tree.root,l=s.children[0];if(l){!function(t){var e=t;e.hierNode={defaultAncestor:null,ancestor:e,prelim:0,modifier:0,change:0,shift:0,i:0,thread:null};for(var n,i,r=[e];n=r.pop();)if(i=n.children,n.isExpand&&i.length)for(var o=i.length-1;o>=0;o--){var a=i[o];a.hierNode={defaultAncestor:null,ancestor:a,prelim:0,modifier:0,change:0,shift:0,i:o,thread:null},r.push(a)}}(s),function(t,e,n){for(var i,r=[t],o=[];i=r.pop();)if(o.push(i),i.isExpand){var a=i.children;if(a.length)for(var s=0;sh.getLayout().x&&(h=t),t.depth>c.depth&&(c=t)}));var p=u===h?1:a(u,h)/2,d=p-u.getLayout().x,f=0,g=0,y=0,v=0;if("radial"===i)f=r/(h.getLayout().x+p+d),g=o/(c.depth-1||1),AI(l,(function(t){y=(t.getLayout().x+d)*f,v=(t.depth-1)*g;var e=iI(y,v);t.setLayout({x:e.x,y:e.y,rawX:y,rawY:v},!0)}));else{var m=t.getOrient();"RL"===m||"LR"===m?(g=o/(h.getLayout().x+p+d),f=r/(c.depth-1||1),AI(l,(function(t){v=(t.getLayout().x+d)*g,y="LR"===m?(t.depth-1)*f:r-(t.depth-1)*f,t.setLayout({x:y,y:v},!0)}))):"TB"!==m&&"BT"!==m||(f=r/(h.getLayout().x+p+d),g=o/(c.depth-1||1),AI(l,(function(t){y=(t.getLayout().x+d)*f,v="TB"===m?(t.depth-1)*g:o-(t.depth-1)*g,t.setLayout({x:y,y:v},!0)})))}}}(t,e)}))}function LI(t){t.eachSeriesByType("tree",(function(t){var e=t.getData();e.tree.eachNode((function(t){var n=t.getModel().getModel("itemStyle").getItemStyle();I(e.ensureUniqueItemVisual(t.dataIndex,"style"),n)}))}))}function kI(t,e,n){if(t&&A(e,t.type)>=0){var i=n.getData().tree.root,r=t.targetNode;if("string"==typeof r&&(r=i.getNodeById(r)),r&&i.contains(r))return{node:r};var o=t.targetNodeId;if(null!=o&&(r=i.getNodeById(o)))return{node:r}}}function PI(t){for(var e=[];t;)(t=t.parentNode)&&e.push(t);return e.reverse()}function OI(t,e){return A(PI(t),e)>=0}function RI(t,e){for(var n=[];t;){var i=t.dataIndex;n.push({name:t.name,dataIndex:i,value:e.getRawValue(i)}),t=t.parentNode}return n.reverse(),n}var NI=function(){},EI=["treemapZoomToNode","treemapRender","treemapMove"];function zI(t){var e=t.getData().tree,n={};e.eachNode((function(e){for(var i=e;i&&i.depth>1;)i=i.parentNode;var r=hp(t.ecModel,i.name||i.dataIndex+"",n);e.setVisual("decal",r)}))}var BI=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n.preventUsingHoverLayer=!0,n}return n(e,t),e.prototype.getInitialData=function(t,e){var n={name:t.name,children:t.data};VI(n);var i=t.levels||[],r=this.designatedVisualItemStyle={},o=new Sh({itemStyle:r},this,e),a=O((i=t.levels=function(t,e){var n,i,r=_r(e.get("color")),o=_r(e.get(["aria","decal","decals"]));if(!r)return;P(t=t||[],(function(t){var e=new Sh(t),r=e.get("color"),o=e.get("decal");(e.get(["itemStyle","color"])||r&&"none"!==r)&&(n=!0),(e.get(["itemStyle","decal"])||o&&"none"!==o)&&(i=!0)}));var a=t[0]||(t[0]={});n||(a.color=r.slice());!i&&o&&(a.decal=o.slice());return t}(i,e))||[],(function(t){return new Sh(t,o,e)}),this),s=TI.createTree(n,this,(function(t){t.wrapMethod("getItemModel",(function(t,e){var n=s.getNodeByDataIndex(e),i=a[n.depth];return t.parentModel=i||o,t}))}));return s.data},e.prototype.optionUpdated=function(){this.resetViewRoot()},e.prototype.formatTooltip=function(t,e,n){var i=this.getData(),r=this.getRawValue(t);return Yd("nameValue",{name:i.getName(t),value:r})},e.prototype.getDataParams=function(e){var n=t.prototype.getDataParams.apply(this,arguments),i=this.getData().tree.getNodeByDataIndex(e);return n.treePathInfo=RI(i,this),n},e.prototype.setLayoutInfo=function(t){this.layoutInfo=this.layoutInfo||{},I(this.layoutInfo,t)},e.prototype.mapIdToIndex=function(t){var e=this._idIndexMap;e||(e=this._idIndexMap=ht(),this._idIndexMapCount=0);var n=e.get(t);return null==n&&e.set(t,n=this._idIndexMapCount++),n},e.prototype.getViewRoot=function(){return this._viewRoot},e.prototype.resetViewRoot=function(t){t?this._viewRoot=t:t=this._viewRoot;var e=this.getRawData().tree.root;t&&(t===e||e.contains(t))||(this._viewRoot=e)},e.prototype.enableAriaDecal=function(){zI(this)},e.type="series.treemap",e.layoutMode="box",e.defaultOption={progressive:0,left:"center",top:"middle",width:"80%",height:"80%",sort:!0,clipWindow:"origin",squareRatio:.5*(1+Math.sqrt(5)),leafDepth:null,drillDownIcon:"▶",zoomToNodeRatio:.1024,roam:!0,nodeClick:"zoomToNode",animation:!0,animationDurationUpdate:900,animationEasing:"quinticInOut",breadcrumb:{show:!0,height:22,left:"center",top:"bottom",emptyItemWidth:25,itemStyle:{color:"rgba(0,0,0,0.7)",textStyle:{color:"#fff"}}},label:{show:!0,distance:0,padding:5,position:"inside",color:"#fff",overflow:"truncate"},upperLabel:{show:!1,position:[0,"50%"],height:20,overflow:"truncate",verticalAlign:"middle"},itemStyle:{color:null,colorAlpha:null,colorSaturation:null,borderWidth:0,gapWidth:0,borderColor:"#fff",borderColorSaturation:null},emphasis:{upperLabel:{show:!0,position:[0,"50%"],ellipsis:!0,verticalAlign:"middle"}},visualDimension:0,visualMin:null,visualMax:null,color:[],colorAlpha:null,colorSaturation:null,colorMappingBy:"index",visibleMin:10,childrenVisibleMin:null,levels:[]},e}(rf);function VI(t){var e=0;P(t.children,(function(t){VI(t);var n=t.value;F(n)&&(n=n[0]),e+=n}));var n=t.value;F(n)&&(n=n[0]),(null==n||isNaN(n))&&(n=e),n<0&&(n=0),F(t.value)?t.value[0]=n:t.value=n}var FI=function(){function t(t){this.group=new zi,t.add(this.group)}return t.prototype.render=function(t,e,n,i){var r=t.getModel("breadcrumb"),o=this.group;if(o.removeAll(),r.get("show")&&n){var a=r.getModel("itemStyle"),s=a.getModel("textStyle"),l={pos:{left:r.get("left"),right:r.get("right"),top:r.get("top"),bottom:r.get("bottom")},box:{width:e.getWidth(),height:e.getHeight()},emptyItemWidth:r.get("emptyItemWidth"),totalWidth:0,renderList:[]};this._prepare(n,l,s),this._renderContent(t,l,a,s,i),Dc(o,l.pos,l.box)}},t.prototype._prepare=function(t,e,n){for(var i=t;i;i=i.parentNode){var r=Tr(i.getModel().get("name"),""),o=n.getTextRect(r),a=Math.max(o.width+16,e.emptyItemWidth);e.totalWidth+=a+8,e.renderList.push({node:i,text:r,width:a})}},t.prototype._renderContent=function(t,e,n,i,r){for(var o,a,s,l,u,h,c,p,d,f=0,g=e.emptyItemWidth,y=t.get(["breadcrumb","height"]),v=(o=e.pos,a=e.box,l=a.width,u=a.height,h=Zi(o.left,l),c=Zi(o.top,u),p=Zi(o.right,l),d=Zi(o.bottom,u),(isNaN(h)||isNaN(parseFloat(o.left)))&&(h=0),(isNaN(p)||isNaN(parseFloat(o.right)))&&(p=l),(isNaN(c)||isNaN(parseFloat(o.top)))&&(c=0),(isNaN(d)||isNaN(parseFloat(o.bottom)))&&(d=u),s=pc(s||0),{width:Math.max(p-h-s[1]-s[3],0),height:Math.max(d-c-s[0]-s[2],0)}),m=e.totalWidth,_=e.renderList,x=_.length-1;x>=0;x--){var b=_[x],w=b.node,S=b.width,M=b.text;m>v.width&&(m-=S-g,S=g,M=null);var I=new ql({shape:{points:GI(f,0,S,y,x===_.length-1,0===x)},style:T(n.getItemStyle(),{lineJoin:"bevel"}),textContent:new ls({style:{text:M,fill:i.getTextColor(),font:i.getFont()}}),textConfig:{position:"inside"},z:10,onclick:V(r,w)});I.disableLabelAnimation=!0,this.group.add(I),HI(I,t,w),f+=S+8}},t.prototype.remove=function(){this.group.removeAll()},t}();function GI(t,e,n,i,r,o){var a=[[r?t:t-5,e],[t+n,e],[t+n,e+i],[r?t:t-5,e+i]];return!o&&a.splice(2,0,[t+n+5,e+i/2]),!r&&a.push([t,e+i/2]),a}function HI(t,e,n){ys(t).eventData={componentType:"series",componentSubType:"treemap",componentIndex:e.componentIndex,seriesIndex:e.componentIndex,seriesName:e.name,seriesType:"treemap",selfType:"breadcrumb",nodeData:{dataIndex:n&&n.dataIndex,name:n&&n.name},treePathInfo:n&&RI(n,e)}}var WI=function(){function t(){this._storage=[],this._elExistsMap={}}return t.prototype.add=function(t,e,n,i,r){return!this._elExistsMap[t.id]&&(this._elExistsMap[t.id]=!0,this._storage.push({el:t,target:e,duration:n,delay:i,easing:r}),!0)},t.prototype.finished=function(t){return this._finishedCallback=t,this},t.prototype.start=function(){for(var t=this,e=this._storage.length,n=function(){--e<=0&&(t._storage.length=0,t._elExistsMap={},t._finishedCallback&&t._finishedCallback())},i=0,r=this._storage.length;i3||Math.abs(t.dy)>3)){var e=this.seriesModel.getData().tree.root;if(!e)return;var n=e.getLayout();if(!n)return;this.api.dispatchAction({type:"treemapMove",from:this.uid,seriesId:this.seriesModel.id,rootRect:{x:n.x+t.dx,y:n.y+t.dy,width:n.width,height:n.height}})}},e.prototype._onZoom=function(t){var e=t.originX,n=t.originY;if("animating"!==this._state){var i=this.seriesModel.getData().tree.root;if(!i)return;var r=i.getLayout();if(!r)return;var o=new Rn(r.x,r.y,r.width,r.height),a=this.seriesModel.layoutInfo,s=[1,0,0,1,0,0];me(s,s,[-(e-=a.x),-(n-=a.y)]),xe(s,s,[t.scale,t.scale]),me(s,s,[e,n]),o.applyTransform(s),this.api.dispatchAction({type:"treemapRender",from:this.uid,seriesId:this.seriesModel.id,rootRect:{x:o.x,y:o.y,width:o.width,height:o.height}})}},e.prototype._initEvents=function(t){var e=this;t.on("click",(function(t){if("ready"===e._state){var n=e.seriesModel.get("nodeClick",!0);if(n){var i=e.findTarget(t.offsetX,t.offsetY);if(i){var r=i.node;if(r.getLayout().isLeafRoot)e._rootToNode(i);else if("zoomToNode"===n)e._zoomToNode(i);else if("link"===n){var o=r.hostTree.data.getItemModel(r.dataIndex),a=o.get("link",!0),s=o.get("target",!0)||"blank";a&&wc(a,s)}}}}}),this)},e.prototype._renderBreadcrumb=function(t,e,n){var i=this;n||(n=null!=t.get("leafDepth",!0)?{node:t.getViewRoot()}:this.findTarget(e.getWidth()/2,e.getHeight()/2))||(n={node:t.getData().tree.root}),(this._breadcrumb||(this._breadcrumb=new FI(this.group))).render(t,e,n.node,(function(e){"animating"!==i._state&&(OI(t.getViewRoot(),e)?i._rootToNode({node:e}):i._zoomToNode({node:e}))}))},e.prototype.remove=function(){this._clearController(),this._containerGroup&&this._containerGroup.removeAll(),this._storage={nodeGroup:[],background:[],content:[]},this._state="ready",this._breadcrumb&&this._breadcrumb.remove()},e.prototype.dispose=function(){this._clearController()},e.prototype._zoomToNode=function(t){this.api.dispatchAction({type:"treemapZoomToNode",from:this.uid,seriesId:this.seriesModel.id,targetNode:t.node})},e.prototype._rootToNode=function(t){this.api.dispatchAction({type:"treemapRootToNode",from:this.uid,seriesId:this.seriesModel.id,targetNode:t.node})},e.prototype.findTarget=function(t,e){var n;return this.seriesModel.getViewRoot().eachNode({attr:"viewChildren",order:"preorder"},(function(i){var r=this._storage.background[i.getRawIndex()];if(r){var o=r.transformCoordToLocal(t,e),a=r.shape;if(!(a.x<=o[0]&&o[0]<=a.x+a.width&&a.y<=o[1]&&o[1]<=a.y+a.height))return!1;n={node:i,offsetX:o[0],offsetY:o[1]}}}),this),n},e.type="treemap",e}(yf);var JI=P,QI=X,tT=-1,eT=function(){function t(e){var n=e.mappingMethod,i=e.type,r=this.option=w(e);this.type=i,this.mappingMethod=n,this._normalizeData=cT[n];var o=t.visualHandlers[i];this.applyVisual=o.applyVisual,this.getColorMapper=o.getColorMapper,this._normalizedToVisual=o._normalizedToVisual[n],"piecewise"===n?(nT(r),function(t){var e=t.pieceList;t.hasSpecialVisual=!1,P(e,(function(e,n){e.originIndex=n,null!=e.visual&&(t.hasSpecialVisual=!0)}))}(r)):"category"===n?r.categories?function(t){var e=t.categories,n=t.categoryMap={},i=t.visual;if(JI(e,(function(t,e){n[t]=e})),!F(i)){var r=[];X(i)?JI(i,(function(t,e){var i=n[e];r[null!=i?i:tT]=t})):r[-1]=i,i=hT(t,r)}for(var o=e.length-1;o>=0;o--)null==i[o]&&(delete n[e[o]],e.pop())}(r):nT(r,!0):(rt("linear"!==n||r.dataExtent),nT(r))}return t.prototype.mapValueToVisual=function(t){var e=this._normalizeData(t);return this._normalizedToVisual(e,t)},t.prototype.getNormalizer=function(){return B(this._normalizeData,this)},t.listVisualTypes=function(){return z(t.visualHandlers)},t.isValidType=function(e){return t.visualHandlers.hasOwnProperty(e)},t.eachVisual=function(t,e,n){X(t)?P(t,e,n):e.call(n,t)},t.mapVisual=function(e,n,i){var r,o=F(e)?[]:X(e)?{}:(r=!0,null);return t.eachVisual(e,(function(t,e){var a=n.call(i,t,e);r?o=a:o[e]=a})),o},t.retrieveVisuals=function(e){var n,i={};return e&&JI(t.visualHandlers,(function(t,r){e.hasOwnProperty(r)&&(i[r]=e[r],n=!0)})),n?i:null},t.prepareVisualTypes=function(t){if(F(t))t=t.slice();else{if(!QI(t))return[];var e=[];JI(t,(function(t,n){e.push(n)})),t=e}return t.sort((function(t,e){return"color"===e&&"color"!==t&&0===t.indexOf("color")?1:-1})),t},t.dependsOn=function(t,e){return"color"===e?!(!t||0!==t.indexOf(e)):t===e},t.findPieceIndex=function(t,e,n){for(var i,r=1/0,o=0,a=e.length;ou[1]&&(u[1]=l);var h=e.get("colorMappingBy"),c={type:a.name,dataExtent:u,visual:a.range};"color"!==c.type||"index"!==h&&"id"!==h?c.mappingMethod="linear":(c.mappingMethod="category",c.loop=!0);var p=new eT(c);return dT(p).drColorMappingBy=h,p}(0,r,o,0,u,d);P(d,(function(t,e){if(t.depth>=n.length||t===n[t.depth]){var o=function(t,e,n,i,r,o){var a=I({},e);if(r){var s=r.type,l="color"===s&&dT(r).drColorMappingBy,u="index"===l?i:"id"===l?o.mapIdToIndex(n.getId()):n.getValue(t.get("visualDimension"));a[s]=r.mapValueToVisual(u)}return a}(r,u,t,e,f,i);gT(t,o,n,i)}}))}else s=yT(u),h.fill=s}}function yT(t){var e=vT(t,"color");if(e){var n=vT(t,"colorAlpha"),i=vT(t,"colorSaturation");return i&&(e=rn(e,null,null,i)),n&&(e=on(e,n)),e}}function vT(t,e){var n=t[e];if(null!=n&&"none"!==n)return n}function mT(t,e){var n=t.get(e);return F(n)&&n.length?{name:e,range:n}:null}var _T=Math.max,xT=Math.min,bT=Q,wT=P,ST=["itemStyle","borderWidth"],MT=["itemStyle","gapWidth"],IT=["upperLabel","show"],TT=["upperLabel","height"],CT={seriesType:"treemap",reset:function(t,e,n,i){var r=n.getWidth(),o=n.getHeight(),a=t.option,s=Ac(t.getBoxLayoutParams(),{width:n.getWidth(),height:n.getHeight()}),l=a.size||[],u=Zi(bT(s.width,l[0]),r),h=Zi(bT(s.height,l[1]),o),c=i&&i.type,p=kI(i,["treemapZoomToNode","treemapRootToNode"],t),d="treemapRender"===c||"treemapMove"===c?i.rootRect:null,f=t.getViewRoot(),g=PI(f);if("treemapMove"!==c){var y="treemapZoomToNode"===c?function(t,e,n,i,r){var o,a=(e||{}).node,s=[i,r];if(!a||a===n)return s;var l=i*r,u=l*t.option.zoomToNodeRatio;for(;o=a.parentNode;){for(var h=0,c=o.children,p=0,d=c.length;ptr&&(u=tr),a=o}ua[1]&&(a[1]=e)}))):a=[NaN,NaN];return{sum:i,dataExtent:a}}(e,a,s);if(0===u.sum)return t.viewChildren=[];if(u.sum=function(t,e,n,i,r){if(!i)return n;for(var o=t.get("visibleMin"),a=r.length,s=a,l=a-1;l>=0;l--){var u=r["asc"===i?a-l-1:l].getValue();u/n*ei&&(i=a));var l=t.area*t.area,u=e*e*n;return l?_T(u*i/l,l/(u*r)):1/0}function LT(t,e,n,i,r){var o=e===n.width?0:1,a=1-o,s=["x","y"],l=["width","height"],u=n[s[o]],h=e?t.area/e:0;(r||h>n[l[a]])&&(h=n[l[a]]);for(var c=0,p=t.length;ci&&(i=e);var o=i%2?i+2:i+3;r=[];for(var a=0;a0&&(m[0]=-m[0],m[1]=-m[1]);var x=v[0]<0?-1:1;if("start"!==i.__position&&"end"!==i.__position){var b=-Math.atan2(v[1],v[0]);u[0].8?"left":h[0]<-.8?"right":"center",p=h[1]>.8?"top":h[1]<-.8?"bottom":"middle";break;case"start":i.x=-h[0]*f+l[0],i.y=-h[1]*g+l[1],c=h[0]>.8?"right":h[0]<-.8?"left":"center",p=h[1]>.8?"bottom":h[1]<-.8?"top":"middle";break;case"insideStartTop":case"insideStart":case"insideStartBottom":i.x=f*x+l[0],i.y=l[1]+w,c=v[0]<0?"right":"left",i.originX=-f*x,i.originY=-w;break;case"insideMiddleTop":case"insideMiddle":case"insideMiddleBottom":case"middle":i.x=_[0],i.y=_[1]+w,c="center",i.originY=-w;break;case"insideEndTop":case"insideEnd":case"insideEndBottom":i.x=-f*x+u[0],i.y=u[1]+w,c=v[0]>=0?"right":"left",i.originX=f*x,i.originY=-w}i.scaleX=i.scaleY=r,i.setStyle({verticalAlign:i.__verticalAlign||p,align:i.__align||c})}}}function S(t,e){var n=t.__specifiedRotation;if(null==n){var i=a.tangentAt(e);t.attr("rotation",(1===e?-1:1)*Math.PI/2-Math.atan2(i[1],i[0]))}else t.attr("rotation",n)}},e}(zi),dC=function(){function t(t){this.group=new zi,this._LineCtor=t||pC}return t.prototype.isPersistent=function(){return!0},t.prototype.updateData=function(t){var e=this,n=this,i=n.group,r=n._lineData;n._lineData=t,r||i.removeAll();var o=fC(t);t.diff(r).add((function(n){e._doAdd(t,n,o)})).update((function(n,i){e._doUpdate(r,t,i,n,o)})).remove((function(t){i.remove(r.getItemGraphicEl(t))})).execute()},t.prototype.updateLayout=function(){var t=this._lineData;t&&t.eachItemGraphicEl((function(e,n){e.updateLayout(t,n)}),this)},t.prototype.incrementalPrepareUpdate=function(t){this._seriesScope=fC(t),this._lineData=null,this.group.removeAll()},t.prototype.incrementalUpdate=function(t,e){function n(t){t.isGroup||function(t){return t.animators&&t.animators.length>0}(t)||(t.incremental=!0,t.ensureState("emphasis").hoverLayer=!0)}for(var i=t.start;i=0?i+=u:i-=u:f>=0?i-=u:i+=u}return i}function MC(t,e){var n=[],i=Yo,r=[[],[],[]],o=[[],[]],a=[];e/=2,t.eachEdge((function(t,s){var l=t.getLayout(),u=t.getVisual("fromSymbol"),h=t.getVisual("toSymbol");l.__original||(l.__original=[mt(l[0]),mt(l[1])],l[2]&&l.__original.push(mt(l[2])));var c=l.__original;if(null!=l[2]){if(vt(r[0],c[0]),vt(r[1],c[2]),vt(r[2],c[1]),u&&"none"!==u){var p=jT(t.node1),d=SC(r,c[0],p*e);i(r[0][0],r[1][0],r[2][0],d,n),r[0][0]=n[3],r[1][0]=n[4],i(r[0][1],r[1][1],r[2][1],d,n),r[0][1]=n[3],r[1][1]=n[4]}if(h&&"none"!==h){p=jT(t.node2),d=SC(r,c[1],p*e);i(r[0][0],r[1][0],r[2][0],d,n),r[1][0]=n[1],r[2][0]=n[2],i(r[0][1],r[1][1],r[2][1],d,n),r[1][1]=n[1],r[2][1]=n[2]}vt(l[0],r[0]),vt(l[1],r[2]),vt(l[2],r[1])}else{if(vt(o[0],c[0]),vt(o[1],c[1]),wt(a,o[1],o[0]),At(a,a),u&&"none"!==u){p=jT(t.node1);bt(o[0],o[0],a,p*e)}if(h&&"none"!==h){p=jT(t.node2);bt(o[1],o[1],a,-p*e)}vt(l[0],o[0]),vt(l[1],o[1])}}))}function IC(t){return"view"===t.type}var TC=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n}return n(e,t),e.prototype.init=function(t,e){var n=new Tb,i=new dC,r=this.group;this._controller=new QS(e.getZr()),this._controllerHost={target:r},r.add(n.group),r.add(i.group),this._symbolDraw=n,this._lineDraw=i,this._firstRender=!0},e.prototype.render=function(t,e,n){var i=this,r=t.coordinateSystem;this._model=t;var o=this._symbolDraw,a=this._lineDraw,s=this.group;if(IC(r)){var l={x:r.x,y:r.y,scaleX:r.scaleX,scaleY:r.scaleY};this._firstRender?s.attr(l):Ou(s,l,t)}MC(t.getGraph(),ZT(t));var u=t.getData();o.updateData(u);var h=t.getEdgeData();a.updateData(h),this._updateNodeAndLinkScale(),this._updateController(t,e,n),clearTimeout(this._layoutTimeout);var c=t.forceLayout,p=t.get(["force","layoutAnimation"]);c&&this._startForceLayoutIteration(c,p),u.graph.eachNode((function(t){var e=t.dataIndex,n=t.getGraphicEl(),r=t.getModel();n.off("drag").off("dragend");var o=r.get("draggable");o&&n.on("drag",(function(){c&&(c.warmUp(),!i._layouting&&i._startForceLayoutIteration(c,p),c.setFixed(e),u.setItemLayout(e,[n.x,n.y]))})).on("dragend",(function(){c&&c.setUnfixed(e)})),n.setDraggable(o&&!!c),"adjacency"===r.get(["emphasis","focus"])&&(ys(n).focus=t.getAdjacentDataIndices())})),u.graph.eachEdge((function(t){var e=t.getGraphicEl();"adjacency"===t.getModel().get(["emphasis","focus"])&&(ys(e).focus={edge:[t.dataIndex],node:[t.node1.dataIndex,t.node2.dataIndex]})}));var d="circular"===t.get("layout")&&t.get(["circular","rotateLabel"]),f=u.getLayout("cx"),g=u.getLayout("cy");u.eachItemGraphicEl((function(t,e){var n=u.getItemModel(e).get(["label","rotate"])||0,i=t.getSymbolPath();if(d){var r=u.getItemLayout(e),o=Math.atan2(r[1]-g,r[0]-f);o<0&&(o=2*Math.PI+o);var a=r[0]=0&&t.call(e,n[r],r)},t.prototype.eachEdge=function(t,e){for(var n=this.edges,i=n.length,r=0;r=0&&n[r].node1.dataIndex>=0&&n[r].node2.dataIndex>=0&&t.call(e,n[r],r)},t.prototype.breadthFirstTraverse=function(t,e,n,i){if(e instanceof DC||(e=this._nodesMap[CC(e)]),e){for(var r="out"===n?"outEdges":"in"===n?"inEdges":"edges",o=0;o=0&&n.node2.dataIndex>=0}));for(r=0,o=i.length;r=0&&this[t][e].setItemVisual(this.dataIndex,n,i)},getVisual:function(n){return this[t][e].getItemVisual(this.dataIndex,n)},setLayout:function(n,i){this.dataIndex>=0&&this[t][e].setItemLayout(this.dataIndex,n,i)},getLayout:function(){return this[t][e].getItemLayout(this.dataIndex)},getGraphicEl:function(){return this[t][e].getItemGraphicEl(this.dataIndex)},getRawIndex:function(){return this[t][e].getRawIndex(this.dataIndex)}}}function PC(t,e,n,i,r){for(var o=new AC(i),a=0;a "+p)),u++)}var d,f=n.get("coordinateSystem");if("cartesian2d"===f||"polar"===f)d=Hm(t,n);else{var g=_p.get(f),y=g&&g.dimensions||[];A(y,"value")<0&&y.concat(["value"]);var v=Nm(t,{coordDimensions:y});(d=new Pm(v,n)).initData(t)}var m=new Pm(["value"],n);return m.initData(l,s),r&&r(d,m),vI({mainData:d,struct:o,structAttr:"graph",datas:{node:d,edge:m},datasAttr:{node:"data",edge:"edgeData"}}),o.update(),o}L(DC,kC("hostGraph","data")),L(LC,kC("hostGraph","edgeData"));var OC=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n.hasSymbolVisual=!0,n}return n(e,t),e.prototype.init=function(e){t.prototype.init.apply(this,arguments);var n=this;function i(){return n._categoriesData}this.legendVisualProvider=new Nw(i,i),this.fillDataTextStyle(e.edges||e.links),this._updateCategoriesData()},e.prototype.mergeOption=function(e){t.prototype.mergeOption.apply(this,arguments),this.fillDataTextStyle(e.edges||e.links),this._updateCategoriesData()},e.prototype.mergeDefaultAndTheme=function(e){t.prototype.mergeDefaultAndTheme.apply(this,arguments),xr(e,"edgeLabel",["show"])},e.prototype.getInitialData=function(t,e){var n,i=t.edges||t.links||[],r=t.data||t.nodes||[],o=this;if(r&&i){BT(n=this)&&(n.__curvenessList=[],n.__edgeMap={},VT(n));var a=PC(r,i,this,!0,(function(t,e){t.wrapMethod("getItemModel",(function(t){var e=o._categoriesModels[t.getShallow("category")];return e&&(e.parentModel=t.parentModel,t.parentModel=e),t}));var n=Sh.prototype.getModel;function i(t,e){var i=n.call(this,t,e);return i.resolveParentPath=r,i}function r(t){if(t&&("label"===t[0]||"label"===t[1])){var e=t.slice();return"label"===t[0]?e[0]="edgeLabel":"label"===t[1]&&(e[1]="edgeLabel"),e}return t}e.wrapMethod("getItemModel",(function(t){return t.resolveParentPath=r,t.getModel=i,t}))}));return P(a.edges,(function(t){!function(t,e,n,i){if(BT(n)){var r=FT(t,e,n),o=n.__edgeMap,a=o[GT(r)];o[r]&&!a?o[r].isForward=!0:a&&o[r]&&(a.isForward=!0,o[r].isForward=!1),o[r]=o[r]||[],o[r].push(i)}}(t.node1,t.node2,this,t.dataIndex)}),this),a.data}},e.prototype.getGraph=function(){return this.getData().graph},e.prototype.getEdgeData=function(){return this.getGraph().edgeData},e.prototype.getCategoriesData=function(){return this._categoriesData},e.prototype.formatTooltip=function(t,e,n){if("edge"===n){var i=this.getData(),r=this.getDataParams(t,n),o=i.graph.getEdgeByIndex(t),a=i.getName(o.node1.dataIndex),s=i.getName(o.node2.dataIndex),l=[];return null!=a&&l.push(a),null!=s&&l.push(s),Yd("nameValue",{name:l.join(" > "),value:r.value,noValue:null==r.value})}return tf({series:this,dataIndex:t,multipleSeries:e})},e.prototype._updateCategoriesData=function(){var t=O(this.option.categories||[],(function(t){return null!=t.value?t:I({value:0},t)})),e=new Pm(["value"],this);e.initData(t),this._categoriesData=e,this._categoriesModels=e.mapArray((function(t){return e.getItemModel(t)}))},e.prototype.setZoom=function(t){this.option.zoom=t},e.prototype.setCenter=function(t){this.option.center=t},e.prototype.isAnimationEnabled=function(){return t.prototype.isAnimationEnabled.call(this)&&!("force"===this.get("layout")&&this.get(["force","layoutAnimation"]))},e.type="series.graph",e.dependencies=["grid","polar","geo","singleAxis","calendar"],e.defaultOption={zlevel:0,z:2,coordinateSystem:"view",legendHoverLink:!0,layout:null,circular:{rotateLabel:!1},force:{initLayout:null,repulsion:[0,50],gravity:.1,friction:.6,edgeLength:30,layoutAnimation:!0},left:"center",top:"center",symbol:"circle",symbolSize:10,edgeSymbol:["none","none"],edgeSymbolSize:10,edgeLabel:{position:"middle",distance:5},draggable:!1,roam:!1,center:null,zoom:1,nodeScaleRatio:.6,label:{show:!1,formatter:"{b}"},itemStyle:{},lineStyle:{color:"#aaa",width:1,opacity:.5},emphasis:{scale:!0,label:{show:!0}},select:{itemStyle:{borderColor:"#212121"}}},e}(rf),RC={type:"graphRoam",event:"graphRoam",update:"none"};var NC=function(){this.angle=0,this.width=10,this.r=10,this.x=0,this.y=0},EC=function(t){function e(e){var n=t.call(this,e)||this;return n.type="pointer",n}return n(e,t),e.prototype.getDefaultShape=function(){return new NC},e.prototype.buildPath=function(t,e){var n=Math.cos,i=Math.sin,r=e.r,o=e.width,a=e.angle,s=e.x-n(a)*o*(o>=r/3?1:2),l=e.y-i(a)*o*(o>=r/3?1:2);a=e.angle-Math.PI/2,t.moveTo(s,l),t.lineTo(e.x+n(a)*o,e.y+i(a)*o),t.lineTo(e.x+n(e.angle)*r,e.y+i(e.angle)*r),t.lineTo(e.x-n(a)*o,e.y-i(a)*o),t.lineTo(s,l)},e}(Za);function zC(t,e){var n=null==t?"":t+"";return e&&("string"==typeof e?n=e.replace("{value}",n):"function"==typeof e&&(n=e(t))),n}var BC=2*Math.PI,VC=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n}return n(e,t),e.prototype.render=function(t,e,n){this.group.removeAll();var i=t.get(["axisLine","lineStyle","color"]),r=function(t,e){var n=t.get("center"),i=e.getWidth(),r=e.getHeight(),o=Math.min(i,r);return{cx:Zi(n[0],e.getWidth()),cy:Zi(n[1],e.getHeight()),r:Zi(t.get("radius"),o/2)}}(t,n);this._renderMain(t,e,n,i,r),this._data=t.getData()},e.prototype.dispose=function(){},e.prototype._renderMain=function(t,e,n,i,r){for(var o=this.group,a=t.get("clockwise"),s=-t.get("startAngle")/180*Math.PI,l=-t.get("endAngle")/180*Math.PI,u=t.getModel("axisLine"),h=u.get("roundCap")?aw:Wl,c=u.get("show"),p=u.getModel("lineStyle"),d=p.get("width"),f=(l-s)%BC||l===s?(l-s)%BC:BC,g=s,y=0;c&&y=t&&(0===e?0:i[e-1][0]).8?"bottom":"middle",align:u<-.4?"left":u>.4?"right":"center"},{inheritColor:R}),silent:!0}))}if(m.get("show")&&L!==x){P=(P=m.get("distance"))?P+l:l;for(var N=0;N<=b;N++){u=Math.cos(M),h=Math.sin(M);var E=new tu({shape:{x1:u*(f-P)+p,y1:h*(f-P)+d,x2:u*(f-S-P)+p,y2:h*(f-S-P)+d},silent:!0,style:A});"auto"===A.stroke&&E.setStyle({stroke:i((L+N/b)/x)}),c.add(E),M+=T}M-=T}else M+=I}},e.prototype._renderPointer=function(t,e,n,i,r,o,a,s,l){var u=this.group,h=this._data,c=this._progressEls,p=[],d=t.get(["pointer","show"]),f=t.getModel("progress"),g=f.get("show"),y=t.getData(),v=y.mapDimension("value"),m=+t.get("min"),_=+t.get("max"),x=[m,_],b=[o,a];function w(e,n){var i,o=y.getItemModel(e).getModel("pointer"),a=Zi(o.get("width"),r.r),s=Zi(o.get("length"),r.r),l=t.get(["pointer","icon"]),u=o.get("offsetCenter"),h=Zi(u[0],r.r),c=Zi(u[1],r.r),p=o.get("keepAspect");return(i=l?uy(l,h-a/2,c-s,a,s,null,p):new EC({shape:{angle:-Math.PI/2,width:a,r:s,x:h,y:c}})).rotation=-(n+Math.PI/2),i.x=r.cx,i.y=r.cy,i}function S(t,e){var n=f.get("roundCap")?aw:Wl,i=f.get("overlap"),a=i?f.get("width"):l/y.count(),u=i?r.r-a:r.r-(t+1)*a,h=i?r.r:r.r-t*a,c=new n({shape:{startAngle:o,endAngle:e,cx:r.cx,cy:r.cy,clockwise:s,r0:u,r:h}});return i&&(c.z2=_-y.get(v,t)%_),c}(g||d)&&(y.diff(h).add((function(e){if(d){var n=w(e,o);Ru(n,{rotation:-(Ui(y.get(v,e),x,b,!0)+Math.PI/2)},t),u.add(n),y.setItemGraphicEl(e,n)}if(g){var i=S(e,o),r=f.get("clip");Ru(i,{shape:{endAngle:Ui(y.get(v,e),x,b,r)}},t),u.add(i),p[e]=i}})).update((function(e,n){if(d){var i=h.getItemGraphicEl(n),r=i?i.rotation:o,a=w(e,r);a.rotation=r,Ou(a,{rotation:-(Ui(y.get(v,e),x,b,!0)+Math.PI/2)},t),u.add(a),y.setItemGraphicEl(e,a)}if(g){var s=c[n],l=S(e,s?s.shape.endAngle:o),m=f.get("clip");Ou(l,{shape:{endAngle:Ui(y.get(v,e),x,b,m)}},t),u.add(l),p[e]=l}})).execute(),y.each((function(t){var e=y.getItemModel(t),n=e.getModel("emphasis");if(d){var r=y.getItemGraphicEl(t);r.useStyle(y.getItemVisual(t,"style")),r.setStyle(e.getModel(["pointer","itemStyle"]).getItemStyle()),"auto"===r.style.fill&&r.setStyle("fill",i(Ui(y.get(v,t),x,[0,1],!0))),r.z2EmphasisLift=0,nl(r,e),Js(r,n.get("focus"),n.get("blurScope"))}if(g){var o=p[t];o.useStyle(y.getItemVisual(t,"style")),o.setStyle(e.getModel(["progress","itemStyle"]).getItemStyle()),o.z2EmphasisLift=0,nl(o,e),Js(o,n.get("focus"),n.get("blurScope"))}})),this._progressEls=p)},e.prototype._renderAnchor=function(t,e){var n=t.getModel("anchor");if(n.get("show")){var i=n.get("size"),r=n.get("icon"),o=n.get("offsetCenter"),a=n.get("keepAspect"),s=uy(r,e.cx-i/2+Zi(o[0],e.r),e.cy-i/2+Zi(o[1],e.r),i,i,null,a);s.z2=n.get("showAbove")?1:0,s.setStyle(n.getModel("itemStyle").getItemStyle()),this.group.add(s)}},e.prototype._renderTitleAndDetail=function(t,e,n,i,r){var o=this,a=t.getData(),s=a.mapDimension("value"),l=+t.get("min"),u=+t.get("max"),h=new zi,c=[],p=[],d=t.isAnimationEnabled();a.diff(this._data).add((function(t){c[t]=new ls({silent:!0}),p[t]=new ls({silent:!0})})).update((function(t,e){c[t]=o._titleEls[e],p[t]=o._detailEls[e]})).execute(),a.each((function(e){var n=a.getItemModel(e),o=a.get(s,e),f=new zi,g=i(Ui(o,[l,u],[0,1],!0)),y=n.getModel("title");if(y.get("show")){var v=y.get("offsetCenter"),m=r.cx+Zi(v[0],r.r),_=r.cy+Zi(v[1],r.r);(C=c[e]).attr({style:nh(y,{x:m,y:_,text:a.getName(e),align:"center",verticalAlign:"middle"},{inheritColor:g})}),f.add(C)}var x=n.getModel("detail");if(x.get("show")){var b=x.get("offsetCenter"),w=r.cx+Zi(b[0],r.r),S=r.cy+Zi(b[1],r.r),M=Zi(x.get("width"),r.r),I=Zi(x.get("height"),r.r),T=t.get(["progress","show"])?a.getItemVisual(e,"style").fill:g,C=p[e],A=x.get("formatter");C.attr({style:nh(x,{x:w,y:S,text:zC(o,A),width:isNaN(M)?null:M,height:isNaN(I)?null:I,align:"center",verticalAlign:"middle"},{inheritColor:T})}),hh(C,{normal:x},o,(function(t){return zC(t,A)})),d&&ch(C,e,a,t,{getFormattedLabel:function(t,e,n,i,r,a){return zC(a?a.interpolatedValue:o,A)}}),f.add(C)}h.add(f)})),this.group.add(h),this._titleEls=c,this._detailEls=p},e.type="gauge",e}(yf),FC=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n.visualStyleAccessPath="itemStyle",n.useColorPaletteOnData=!0,n}return n(e,t),e.prototype.getInitialData=function(t,e){return Rw(this,["value"])},e.type="series.gauge",e.defaultOption={zlevel:0,z:2,center:["50%","50%"],legendHoverLink:!0,radius:"75%",startAngle:225,endAngle:-45,clockwise:!0,min:0,max:100,splitNumber:10,axisLine:{show:!0,roundCap:!1,lineStyle:{color:[[1,"#E6EBF8"]],width:10}},progress:{show:!1,overlap:!0,width:10,roundCap:!1,clip:!0},splitLine:{show:!0,length:10,distance:10,lineStyle:{color:"#63677A",width:3,type:"solid"}},axisTick:{show:!0,splitNumber:5,length:6,distance:10,lineStyle:{color:"#63677A",width:1,type:"solid"}},axisLabel:{show:!0,distance:15,color:"#464646",fontSize:12},pointer:{icon:null,offsetCenter:[0,0],show:!0,length:"60%",width:6,keepAspect:!1},anchor:{show:!1,showAbove:!1,size:6,icon:"circle",offsetCenter:[0,0],keepAspect:!1,itemStyle:{color:"#fff",borderWidth:0,borderColor:"#5470c6"}},title:{show:!0,offsetCenter:[0,"20%"],color:"#464646",fontSize:16,valueAnimation:!1},detail:{show:!0,backgroundColor:"rgba(0,0,0,0)",borderWidth:0,borderColor:"#ccc",width:100,height:null,padding:[5,10],offsetCenter:[0,"40%"],color:"#464646",fontSize:30,fontWeight:"bold",lineHeight:30,valueAnimation:!1}},e}(rf);var GC=["itemStyle","opacity"],HC=function(t){function e(e,n){var i=t.call(this)||this,r=i,o=new $l,a=new ls;return r.setTextContent(a),i.setTextGuideLine(o),i.updateData(e,n,!0),i}return n(e,t),e.prototype.updateData=function(t,e,n){var i=this,r=t.hostModel,o=t.getItemModel(e),a=t.getItemLayout(e),s=o.getModel("emphasis"),l=o.get(GC);l=null==l?1:l,i.useStyle(t.getItemVisual(e,"style")),i.style.lineJoin="round",n?(i.setShape({points:a.points}),i.style.opacity=0,Ru(i,{style:{opacity:l}},r,e)):Ou(i,{style:{opacity:l},shape:{points:a.points}},r,e),nl(i,o),this._updateLabel(t,e),Js(this,s.get("focus"),s.get("blurScope"))},e.prototype._updateLabel=function(t,e){var n=this,i=this.getTextGuideLine(),r=n.getTextContent(),o=t.hostModel,a=t.getItemModel(e),s=t.getItemLayout(e).label,l=t.getItemVisual(e,"style"),u=l.fill;th(r,eh(a),{labelFetcher:t.hostModel,labelDataIndex:e,defaultOpacity:l.opacity,defaultText:t.getName(e)},{normal:{align:s.textAlign,verticalAlign:s.verticalAlign}}),n.setTextConfig({local:!0,inside:!!s.inside,insideStroke:u,outsideFill:u});var h=s.linePoints;i.setShape({points:h}),n.textGuideLineConfig={anchor:h?new In(h[0][0],h[0][1]):null},Ou(r,{style:{x:s.x,y:s.y}},o,e),r.attr({rotation:s.rotation,originX:s.x,originY:s.y,z2:10}),zg(n,Bg(a),{stroke:u})},e}(ql),WC=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n.ignoreLabelLineUpdate=!0,n}return n(e,t),e.prototype.render=function(t,e,n){var i=t.getData(),r=this._data,o=this.group;i.diff(r).add((function(t){var e=new HC(i,t);i.setItemGraphicEl(t,e),o.add(e)})).update((function(t,e){var n=r.getItemGraphicEl(e);n.updateData(i,t),o.add(n),i.setItemGraphicEl(t,n)})).remove((function(e){zu(r.getItemGraphicEl(e),t,e)})).execute(),this._data=i},e.prototype.remove=function(){this.group.removeAll(),this._data=null},e.prototype.dispose=function(){},e.type="funnel",e}(yf),YC=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n.useColorPaletteOnData=!0,n}return n(e,t),e.prototype.init=function(e){t.prototype.init.apply(this,arguments),this.legendVisualProvider=new Nw(B(this.getData,this),B(this.getRawData,this)),this._defaultLabelLine(e)},e.prototype.getInitialData=function(t,e){return Rw(this,{coordDimensions:["value"],encodeDefaulter:V(Qc,this)})},e.prototype._defaultLabelLine=function(t){xr(t,"labelLine",["show"]);var e=t.labelLine,n=t.emphasis.labelLine;e.show=e.show&&t.label.show,n.show=n.show&&t.emphasis.label.show},e.prototype.getDataParams=function(e){var n=this.getData(),i=t.prototype.getDataParams.call(this,e),r=n.mapDimension("value"),o=n.getSum(r);return i.percent=o?+(n.get(r,e)/o*100).toFixed(2):0,i.$vars.push("percent"),i},e.type="series.funnel",e.defaultOption={zlevel:0,z:2,legendHoverLink:!0,left:80,top:60,right:80,bottom:60,minSize:"0%",maxSize:"100%",sort:"descending",orient:"vertical",gap:0,funnelAlign:"center",label:{show:!0,position:"outer"},labelLine:{show:!0,length:20,lineStyle:{width:1}},itemStyle:{borderColor:"#fff",borderWidth:1},emphasis:{label:{show:!0}},select:{itemStyle:{borderColor:"#212121"}}},e}(rf);function XC(t,e){t.eachSeriesByType("funnel",(function(t){var n=t.getData(),i=n.mapDimension("value"),r=t.get("sort"),o=function(t,e){return Ac(t.getBoxLayoutParams(),{width:e.getWidth(),height:e.getHeight()})}(t,e),a=t.get("orient"),s=o.width,l=o.height,u=function(t,e){for(var n=t.mapDimension("value"),i=t.mapArray(n,(function(t){return t})),r=[],o="ascending"===e,a=0,s=t.count();a5)return;var i=this._model.coordinateSystem.getSlidedAxisExpandWindow([t.offsetX,t.offsetY]);"none"!==i.behavior&&this._dispatchExpand({axisExpandWindow:i.axisExpandWindow})}this._mouseDownPoint=null},mousemove:function(t){if(!this._mouseDownPoint&&rA(this,"mousemove")){var e=this._model,n=e.coordinateSystem.getSlidedAxisExpandWindow([t.offsetX,t.offsetY]),i=n.behavior;"jump"===i&&this._throttledDispatchExpand.debounceNextCall(e.get("axisExpandDebounce")),this._throttledDispatchExpand("none"===i?null:{axisExpandWindow:n.axisExpandWindow,animation:"jump"===i?null:{duration:0}})}}};function rA(t,e){var n=t._model;return n.get("axisExpandable")&&n.get("axisExpandTriggerOn")===e}var oA=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n}return n(e,t),e.prototype.init=function(){t.prototype.init.apply(this,arguments),this.mergeOption({})},e.prototype.mergeOption=function(t){var e=this.option;t&&S(e,t,!0),this._initDimensions()},e.prototype.contains=function(t,e){var n=t.get("parallelIndex");return null!=n&&e.getComponent("parallel",n)===this},e.prototype.setAxisExpand=function(t){P(["axisExpandable","axisExpandCenter","axisExpandCount","axisExpandWidth","axisExpandWindow"],(function(e){t.hasOwnProperty(e)&&(this.option[e]=t[e])}),this)},e.prototype._initDimensions=function(){var t=this.dimensions=[],e=this.parallelAxisIndex=[];P(N(this.ecModel.queryComponents({mainType:"parallelAxis"}),(function(t){return(t.get("parallelIndex")||0)===this.componentIndex}),this),(function(n){t.push("dim"+n.get("dim")),e.push(n.componentIndex)}))},e.type="parallel",e.dependencies=["parallelAxis"],e.layoutMode="box",e.defaultOption={zlevel:0,z:0,left:80,top:60,right:80,bottom:60,layout:"horizontal",axisExpandable:!1,axisExpandCenter:null,axisExpandCount:0,axisExpandWidth:50,axisExpandRate:17,axisExpandDebounce:50,axisExpandSlideTriggerArea:[-.15,.05,.4],axisExpandTriggerOn:"click",parallelAxisDefault:null},e}(Nc),aA=function(t){function e(e,n,i,r,o){var a=t.call(this,e,n,i)||this;return a.type=r||"value",a.axisIndex=o,a}return n(e,t),e.prototype.isHorizontal=function(){return"horizontal"!==this.coordinateSystem.getModel().get("layout")},e}(vx);function sA(t,e,n,i,r,o){t=t||0;var a=n[1]-n[0];if(null!=r&&(r=uA(r,[0,a])),null!=o&&(o=Math.max(o,null!=r?r:0)),"all"===i){var s=Math.abs(e[1]-e[0]);s=uA(s,[0,a]),r=o=uA(s,[r,o]),i=0}e[0]=uA(e[0],n),e[1]=uA(e[1],n);var l=lA(e,i);e[i]+=t;var u,h=r||0,c=n.slice();return l.sign<0?c[0]+=h:c[1]-=h,e[i]=uA(e[i],c),u=lA(e,i),null!=r&&(u.sign!==l.sign||u.spano&&(e[1-i]=e[i]+u.sign*o),e}function lA(t,e){var n=t[e]-t[1-e];return{span:Math.abs(n),sign:n>0?-1:n<0?1:e?-1:1}}function uA(t,e){return Math.min(null!=e[1]?e[1]:1/0,Math.max(null!=e[0]?e[0]:-1/0,t))}var hA=P,cA=Math.min,pA=Math.max,dA=Math.floor,fA=Math.ceil,gA=ji,yA=Math.PI,vA=function(){function t(t,e,n){this.type="parallel",this._axesMap=ht(),this._axesLayout={},this.dimensions=t.dimensions,this._model=t,this._init(t,e,n)}return t.prototype._init=function(t,e,n){var i=t.dimensions,r=t.parallelAxisIndex;hA(i,(function(t,n){var i=r[n],o=e.getComponent("parallelAxis",i),a=this._axesMap.set(t,new aA(t,G_(o),[0,0],o.get("type"),i)),s="category"===a.type;a.onBand=s&&o.get("boundaryGap"),a.inverse=o.get("inverse"),o.axis=a,a.model=o,a.coordinateSystem=o.coordinateSystem=this}),this)},t.prototype.update=function(t,e){this._updateAxesFromSeries(this._model,t)},t.prototype.containPoint=function(t){var e=this._makeLayoutInfo(),n=e.axisBase,i=e.layoutBase,r=e.pixelDimIndex,o=t[1-r],a=t[r];return o>=n&&o<=n+e.axisLength&&a>=i&&a<=i+e.layoutLength},t.prototype.getModel=function(){return this._model},t.prototype._updateAxesFromSeries=function(t,e){e.eachSeries((function(n){if(t.contains(n,e)){var i=n.getData();hA(this.dimensions,(function(t){var e=this._axesMap.get(t);e.scale.unionExtentFromData(i,i.mapDimension(t)),F_(e.scale,e.model)}),this)}}),this)},t.prototype.resize=function(t,e){this._rect=Ac(t.getBoxLayoutParams(),{width:e.getWidth(),height:e.getHeight()}),this._layoutAxes()},t.prototype.getRect=function(){return this._rect},t.prototype._makeLayoutInfo=function(){var t,e=this._model,n=this._rect,i=["x","y"],r=["width","height"],o=e.get("layout"),a="horizontal"===o?0:1,s=n[r[a]],l=[0,s],u=this.dimensions.length,h=mA(e.get("axisExpandWidth"),l),c=mA(e.get("axisExpandCount")||0,[0,u]),p=e.get("axisExpandable")&&u>3&&u>c&&c>1&&h>0&&s>0,d=e.get("axisExpandWindow");d?(t=mA(d[1]-d[0],l),d[1]=d[0]+t):(t=mA(h*(c-1),l),(d=[h*(e.get("axisExpandCenter")||dA(u/2))-t/2])[1]=d[0]+t);var f=(s-t)/(u-c);f<3&&(f=0);var g=[dA(gA(d[0]/h,1))+1,fA(gA(d[1]/h,1))-1],y=f/h*d[0];return{layout:o,pixelDimIndex:a,layoutBase:n[i[a]],layoutLength:s,axisBase:n[i[1-a]],axisLength:n[r[1-a]],axisExpandable:p,axisExpandWidth:h,axisCollapseWidth:f,axisExpandWindow:d,axisCount:u,winInnerIndices:g,axisExpandWindow0Pos:y}},t.prototype._layoutAxes=function(){var t=this._rect,e=this._axesMap,n=this.dimensions,i=this._makeLayoutInfo(),r=i.layout;e.each((function(t){var e=[0,i.axisLength],n=t.inverse?1:0;t.setExtent(e[n],e[1-n])})),hA(n,(function(e,n){var o=(i.axisExpandable?xA:_A)(n,i),a={horizontal:{x:o.position,y:i.axisLength},vertical:{x:0,y:o.position}},s={horizontal:yA/2,vertical:0},l=[a[r].x+t.x,a[r].y+t.y],u=s[r],h=[1,0,0,1,0,0];_e(h,h,u),me(h,h,l),this._axesLayout[e]={position:l,rotation:u,transform:h,axisNameAvailableWidth:o.axisNameAvailableWidth,axisLabelShow:o.axisLabelShow,nameTruncateMaxWidth:o.nameTruncateMaxWidth,tickDirection:1,labelDirection:1}}),this)},t.prototype.getAxis=function(t){return this._axesMap.get(t)},t.prototype.dataToPoint=function(t,e){return this.axisCoordToPoint(this._axesMap.get(e).dataToCoord(t),e)},t.prototype.eachActiveState=function(t,e,n,i){null==n&&(n=0),null==i&&(i=t.count());var r=this._axesMap,o=this.dimensions,a=[],s=[];P(o,(function(e){a.push(t.mapDimension(e)),s.push(r.get(e).model)}));for(var l=this.hasAxisBrushed(),u=n;ur*(1-h[0])?(l="jump",a=s-r*(1-h[2])):(a=s-r*h[1])>=0&&(a=s-r*(1-h[1]))<=0&&(a=0),(a*=e.axisExpandWidth/u)?sA(a,i,o,"all"):l="none";else{var p=i[1]-i[0];(i=[pA(0,o[1]*s/p-p/2)])[1]=cA(o[1],i[0]+p),i[0]=i[1]-p}return{axisExpandWindow:i,behavior:l}},t}();function mA(t,e){return cA(pA(t,e[0]),e[1])}function _A(t,e){var n=e.layoutLength/(e.axisCount-1);return{position:n*t,axisNameAvailableWidth:n,axisLabelShow:!0}}function xA(t,e){var n,i,r=e.layoutLength,o=e.axisExpandWidth,a=e.axisCount,s=e.axisCollapseWidth,l=e.winInnerIndices,u=s,h=!1;return t=0;n--)qi(e[n])},e.prototype.getActiveState=function(t){var e=this.activeIntervals;if(!e.length)return"normal";if(null==t||isNaN(+t))return"inactive";if(1===e.length){var n=e[0];if(n[0]<=t&&t<=n[1])return"active"}else for(var i=0,r=e.length;i6}(t)||o){if(a&&!o){"single"===s.brushMode&&GA(t);var l=w(s);l.brushType=rD(l.brushType,a),l.panelId=a===SA?null:a.panelId,o=t._creatingCover=OA(t,l),t._covers.push(o)}if(o){var u=sD[rD(t._brushType,a)];o.__brushOption.range=u.getCreatingRange(tD(t,o,t._track)),i&&(RA(t,o),u.updateCommon(t,o)),NA(t,o),r={isEnd:i}}}else i&&"single"===s.brushMode&&s.removeOnClick&&VA(t,e,n)&&GA(t)&&(r={isEnd:i,removeOnClick:!0});return r}function rD(t,e){return"auto"===t?e.defaultBrushType:t}var oD={mousedown:function(t){if(this._dragging)aD(this,t);else if(!t.target||!t.target.draggable){eD(t);var e=this.group.transformCoordToLocal(t.offsetX,t.offsetY);this._creatingCover=null,(this._creatingPanel=VA(this,t,e))&&(this._dragging=!0,this._track=[e.slice()])}},mousemove:function(t){var e=t.offsetX,n=t.offsetY,i=this.group.transformCoordToLocal(e,n);if(function(t,e,n){if(t._brushType&&!function(t,e,n){var i=t._zr;return e<0||e>i.getWidth()||n<0||n>i.getHeight()}(t,e.offsetX,e.offsetY)){var i=t._zr,r=t._covers,o=VA(t,e,n);if(!t._dragging)for(var a=0;a=0&&(o[r[a].depth]=new Sh(r[a],this,e));if(i&&n)return PC(i,n,this,!0,(function(t,e){t.wrapMethod("getItemModel",(function(t,e){var n=t.parentModel,i=n.getData().getItemLayout(e);if(i){var r=i.depth,o=n.levelModels[r];o&&(t.parentModel=o)}return t})),e.wrapMethod("getItemModel",(function(t,e){var n=t.parentModel,i=n.getGraph().getEdgeByIndex(e).node1.getLayout();if(i){var r=i.depth,o=n.levelModels[r];o&&(t.parentModel=o)}return t}))})).data},e.prototype.setNodePosition=function(t,e){var n=this.option.data[t];n.localX=e[0],n.localY=e[1]},e.prototype.getGraph=function(){return this.getData().graph},e.prototype.getEdgeData=function(){return this.getGraph().edgeData},e.prototype.formatTooltip=function(t,e,n){function i(t){return isNaN(t)||null==t}if("edge"===n){var r=this.getDataParams(t,n),o=r.data,a=r.value;return Yd("nameValue",{name:o.source+" -- "+o.target,value:a,noValue:i(a)})}var s=this.getGraph().getNodeByIndex(t).getLayout().value,l=this.getDataParams(t,n).data.name;return Yd("nameValue",{name:null!=l?l+"":null,value:s,noValue:i(s)})},e.prototype.optionUpdated=function(){this.option},e.prototype.getDataParams=function(e,n){var i=t.prototype.getDataParams.call(this,e,n);if(null==i.value&&"node"===n){var r=this.getGraph().getNodeByIndex(e).getLayout().value;i.value=r}return i},e.type="series.sankey",e.defaultOption={zlevel:0,z:2,coordinateSystem:"view",left:"5%",top:"5%",right:"20%",bottom:"5%",orient:"horizontal",nodeWidth:20,nodeGap:8,draggable:!0,layoutIterations:32,label:{show:!0,position:"right",fontSize:12},levels:[],nodeAlign:"justify",lineStyle:{color:"#314656",opacity:.2,curveness:.5},emphasis:{label:{show:!0},lineStyle:{opacity:.5}},select:{itemStyle:{borderColor:"#212121"}},animationEasing:"linear",animationDuration:1e3},e}(rf);function wD(t,e){t.eachSeriesByType("sankey",(function(t){var n=t.get("nodeWidth"),i=t.get("nodeGap"),r=function(t,e){return Ac(t.getBoxLayoutParams(),{width:e.getWidth(),height:e.getHeight()})}(t,e);t.layoutInfo=r;var o=r.width,a=r.height,s=t.getGraph(),l=s.nodes,u=s.edges;!function(t){P(t,(function(t){var e=PD(t.outEdges,kD),n=PD(t.inEdges,kD),i=t.getValue()||0,r=Math.max(e,n,i);t.setLayout({value:r},!0)}))}(l),function(t,e,n,i,r,o,a,s,l){(function(t,e,n,i,r,o,a){for(var s=[],l=[],u=[],h=[],c=0,p=0;p=0;v&&y.depth>d&&(d=y.depth),g.setLayout({depth:v?y.depth:c},!0),"vertical"===o?g.setLayout({dy:n},!0):g.setLayout({dx:n},!0);for(var m=0;mc-1?d:c-1;a&&"left"!==a&&function(t,e,n,i){if("right"===e){for(var r=[],o=t,a=0;o.length;){for(var s=0;s0;o--)ID(s,l*=.99,a),MD(s,r,n,i,a),OD(s,l,a),MD(s,r,n,i,a)}(t,e,o,r,i,a,s),function(t,e){var n="vertical"===e?"x":"y";P(t,(function(t){t.outEdges.sort((function(t,e){return t.node2.getLayout()[n]-e.node2.getLayout()[n]})),t.inEdges.sort((function(t,e){return t.node1.getLayout()[n]-e.node1.getLayout()[n]}))})),P(t,(function(t){var e=0,n=0;P(t.outEdges,(function(t){t.setLayout({sy:e},!0),e+=t.getLayout().dy})),P(t.inEdges,(function(t){t.setLayout({ty:n},!0),n+=t.getLayout().dy}))}))}(t,s)}(l,u,n,i,o,a,0!==N(l,(function(t){return 0===t.getLayout().value})).length?0:t.get("layoutIterations"),t.get("orient"),t.get("nodeAlign"))}))}function SD(t){var e=t.hostGraph.data.getRawDataItem(t.dataIndex);return null!=e.depth&&e.depth>=0}function MD(t,e,n,i,r){var o="vertical"===r?"x":"y";P(t,(function(t){var a,s,l;t.sort((function(t,e){return t.getLayout()[o]-e.getLayout()[o]}));for(var u=0,h=t.length,c="vertical"===r?"dx":"dy",p=0;p0&&(a=s.getLayout()[o]+l,"vertical"===r?s.setLayout({x:a},!0):s.setLayout({y:a},!0)),u=s.getLayout()[o]+s.getLayout()[c]+e;if((l=u-e-("vertical"===r?i:n))>0){a=s.getLayout()[o]-l,"vertical"===r?s.setLayout({x:a},!0):s.setLayout({y:a},!0),u=a;for(p=h-2;p>=0;--p)(l=(s=t[p]).getLayout()[o]+s.getLayout()[c]+e-u)>0&&(a=s.getLayout()[o]-l,"vertical"===r?s.setLayout({x:a},!0):s.setLayout({y:a},!0)),u=s.getLayout()[o]}}))}function ID(t,e,n){P(t.slice().reverse(),(function(t){P(t,(function(t){if(t.outEdges.length){var i=PD(t.outEdges,TD,n)/PD(t.outEdges,kD);if(isNaN(i)){var r=t.outEdges.length;i=r?PD(t.outEdges,CD,n)/r:0}if("vertical"===n){var o=t.getLayout().x+(i-LD(t,n))*e;t.setLayout({x:o},!0)}else{var a=t.getLayout().y+(i-LD(t,n))*e;t.setLayout({y:a},!0)}}}))}))}function TD(t,e){return LD(t.node2,e)*t.getValue()}function CD(t,e){return LD(t.node2,e)}function AD(t,e){return LD(t.node1,e)*t.getValue()}function DD(t,e){return LD(t.node1,e)}function LD(t,e){return"vertical"===e?t.getLayout().x+t.getLayout().dx/2:t.getLayout().y+t.getLayout().dy/2}function kD(t){return t.getValue()}function PD(t,e,n){for(var i=0,r=t.length,o=-1;++oi&&(i=e)})),P(e,(function(e){var r=new eT({type:"color",mappingMethod:"linear",dataExtent:[n,i],visual:t.get("color")}).mapValueToVisual(e.getLayout().value),o=e.getModel().get(["itemStyle","color"]);null!=o?(e.setVisual("color",o),e.setVisual("style",{fill:o})):(e.setVisual("color",r),e.setVisual("style",{fill:r}))}))}}))}var ND=function(){function t(){}return t.prototype.getInitialData=function(t,e){var n,i,r=e.getComponent("xAxis",this.get("xAxisIndex")),o=e.getComponent("yAxis",this.get("yAxisIndex")),a=r.get("type"),s=o.get("type");"category"===a?(t.layout="horizontal",n=r.getOrdinalMeta(),i=!0):"category"===s?(t.layout="vertical",n=o.getOrdinalMeta(),i=!0):t.layout=t.layout||"horizontal";var l=["x","y"],u="horizontal"===t.layout?0:1,h=this._baseAxisDim=l[u],c=l[1-u],p=[r,o],d=p[u].get("type"),f=p[1-u].get("type"),g=t.data;if(g&&i){var y=[];P(g,(function(t,e){var n;F(t)?(n=t.slice(),t.unshift(e)):F(t.value)?(n=t.value.slice(),t.value.unshift(e)):n=t,y.push(n)})),t.data=y}var v=this.defaultValueDimensions,m=[{name:h,type:am(d),ordinalMeta:n,otherDims:{tooltip:!1,itemName:0},dimsDef:["base"]},{name:c,type:am(f),dimsDef:v.slice()}];return Rw(this,{coordDimensions:m,dimensionsCount:v.length+1,encodeDefaulter:V(Jc,m,this)})},t.prototype.getBaseAxis=function(){var t=this._baseAxisDim;return this.ecModel.getComponent(t+"Axis",this.get(t+"AxisIndex")).axis},t}(),ED=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n.defaultValueDimensions=[{name:"min",defaultTooltip:!0},{name:"Q1",defaultTooltip:!0},{name:"median",defaultTooltip:!0},{name:"Q3",defaultTooltip:!0},{name:"max",defaultTooltip:!0}],n.visualDrawType="stroke",n}return n(e,t),e.type="series.boxplot",e.dependencies=["xAxis","yAxis","grid"],e.defaultOption={zlevel:0,z:2,coordinateSystem:"cartesian2d",legendHoverLink:!0,layout:null,boxWidth:[7,50],itemStyle:{color:"#fff",borderWidth:1},emphasis:{scale:!0,itemStyle:{borderWidth:2,shadowBlur:5,shadowOffsetX:1,shadowOffsetY:1,shadowColor:"rgba(0,0,0,0.2)"}},animationDuration:800},e}(rf);L(ED,ND,!0);var zD=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n}return n(e,t),e.prototype.render=function(t,e,n){var i=t.getData(),r=this.group,o=this._data;this._data||r.removeAll();var a="horizontal"===t.get("layout")?1:0;i.diff(o).add((function(t){if(i.hasValue(t)){var e=FD(i.getItemLayout(t),i,t,a,!0);i.setItemGraphicEl(t,e),r.add(e)}})).update((function(t,e){var n=o.getItemGraphicEl(e);if(i.hasValue(t)){var s=i.getItemLayout(t);n?GD(s,n,i,t):n=FD(s,i,t,a),r.add(n),i.setItemGraphicEl(t,n)}else r.remove(n)})).remove((function(t){var e=o.getItemGraphicEl(t);e&&r.remove(e)})).execute(),this._data=i},e.prototype.remove=function(t){var e=this.group,n=this._data;this._data=null,n&&n.eachItemGraphicEl((function(t){t&&e.remove(t)}))},e.type="boxplot",e}(yf),BD=function(){},VD=function(t){function e(e){var n=t.call(this,e)||this;return n.type="boxplotBoxPath",n}return n(e,t),e.prototype.getDefaultShape=function(){return new BD},e.prototype.buildPath=function(t,e){var n=e.points,i=0;for(t.moveTo(n[i][0],n[i][1]),i++;i<4;i++)t.lineTo(n[i][0],n[i][1]);for(t.closePath();ig){var x=[v,_];i.push(x)}}}return{boxData:n,outliers:i}}(e.getRawData(),t.config);return[{dimensions:["ItemName","Low","Q1","Q2","Q3","High"],data:i.boxData},{data:i.outliers}]}};var ZD=["color","borderColor"],jD=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n}return n(e,t),e.prototype.render=function(t,e,n){this.group.removeClipPath(),this._updateDrawMode(t),this._isLargeDraw?this._renderLarge(t):this._renderNormal(t)},e.prototype.incrementalPrepareRender=function(t,e,n){this._clear(),this._updateDrawMode(t)},e.prototype.incrementalRender=function(t,e,n,i){this._isLargeDraw?this._incrementalRenderLarge(t,e):this._incrementalRenderNormal(t,e)},e.prototype._updateDrawMode=function(t){var e=t.pipelineContext.large;null!=this._isLargeDraw&&e===this._isLargeDraw||(this._isLargeDraw=e,this._clear())},e.prototype._renderNormal=function(t){var e=t.getData(),n=this._data,i=this.group,r=e.getLayout("isSimpleBox"),o=t.get("clip",!0),a=t.coordinateSystem,s=a.getArea&&a.getArea();this._data||i.removeAll(),e.diff(n).add((function(n){if(e.hasValue(n)){var a=e.getItemLayout(n);if(o&&JD(s,a))return;var l=$D(a,n,!0);Ru(l,{shape:{points:a.ends}},t,n),QD(l,e,n,r),i.add(l),e.setItemGraphicEl(n,l)}})).update((function(a,l){var u=n.getItemGraphicEl(l);if(e.hasValue(a)){var h=e.getItemLayout(a);o&&JD(s,h)?i.remove(u):(u?Ou(u,{shape:{points:h.ends}},t,a):u=$D(h),QD(u,e,a,r),i.add(u),e.setItemGraphicEl(a,u))}else i.remove(u)})).remove((function(t){var e=n.getItemGraphicEl(t);e&&i.remove(e)})).execute(),this._data=e},e.prototype._renderLarge=function(t){this._clear(),iL(t,this.group);var e=t.get("clip",!0)?Hb(t.coordinateSystem,!1,t):null;e?this.group.setClipPath(e):this.group.removeClipPath()},e.prototype._incrementalRenderNormal=function(t,e){for(var n,i=e.getData(),r=i.getLayout("isSimpleBox");null!=(n=t.next());){var o=$D(i.getItemLayout(n));QD(o,i,n,r),o.incremental=!0,this.group.add(o)}},e.prototype._incrementalRenderLarge=function(t,e){iL(e,this.group,!0)},e.prototype.remove=function(t){this._clear()},e.prototype._clear=function(){this.group.removeAll(),this._data=null},e.type="candlestick",e}(yf),qD=function(){},KD=function(t){function e(e){var n=t.call(this,e)||this;return n.type="normalCandlestickBox",n}return n(e,t),e.prototype.getDefaultShape=function(){return new qD},e.prototype.buildPath=function(t,e){var n=e.points;this.__simpleBox?(t.moveTo(n[4][0],n[4][1]),t.lineTo(n[6][0],n[6][1])):(t.moveTo(n[0][0],n[0][1]),t.lineTo(n[1][0],n[1][1]),t.lineTo(n[2][0],n[2][1]),t.lineTo(n[3][0],n[3][1]),t.closePath(),t.moveTo(n[4][0],n[4][1]),t.lineTo(n[5][0],n[5][1]),t.moveTo(n[6][0],n[6][1]),t.lineTo(n[7][0],n[7][1]))},e}(Za);function $D(t,e,n){var i=t.ends;return new KD({shape:{points:n?tL(i,t):i},z2:100})}function JD(t,e){for(var n=!0,i=0;i0?"borderColor":"borderColor0"])||n.get(["itemStyle",t>0?"color":"color0"]),o=n.getModel("itemStyle").getItemStyle(ZD);e.useStyle(o),e.style.fill=null,e.style.stroke=r}var oL=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n.defaultValueDimensions=[{name:"open",defaultTooltip:!0},{name:"close",defaultTooltip:!0},{name:"lowest",defaultTooltip:!0},{name:"highest",defaultTooltip:!0}],n}return n(e,t),e.prototype.getShadowDim=function(){return"open"},e.prototype.brushSelector=function(t,e,n){var i=e.getItemLayout(t);return i&&n.rect(i.brushRect)},e.type="series.candlestick",e.dependencies=["xAxis","yAxis","grid"],e.defaultOption={zlevel:0,z:2,coordinateSystem:"cartesian2d",legendHoverLink:!0,layout:null,clip:!0,itemStyle:{color:"#eb5454",color0:"#47b262",borderColor:"#eb5454",borderColor0:"#47b262",borderWidth:1},emphasis:{scale:!0,itemStyle:{borderWidth:2}},barMaxWidth:null,barMinWidth:null,barWidth:null,large:!0,largeThreshold:600,progressive:3e3,progressiveThreshold:1e4,progressiveChunkMode:"mod",animationEasing:"linear",animationDuration:300},e}(rf);function aL(t){t&&F(t.series)&&P(t.series,(function(t){X(t)&&"k"===t.type&&(t.type="candlestick")}))}L(oL,ND,!0);var sL=["itemStyle","borderColor"],lL=["itemStyle","borderColor0"],uL=["itemStyle","color"],hL=["itemStyle","color0"],cL={seriesType:"candlestick",plan:df(),performRawSeries:!0,reset:function(t,e){function n(t,e){return e.get(t>0?uL:hL)}function i(t,e){return e.get(t>0?sL:lL)}if(t.getData().setVisual("legendSymbol","roundRect"),!e.isSeriesFiltered(t))return!t.pipelineContext.large&&{progress:function(t,e){for(var r;null!=(r=t.next());){var o=e.getItemModel(r),a=e.getItemLayout(r).sign,s=o.getItemStyle();s.fill=n(a,o),s.stroke=i(a,o)||s.fill,I(e.ensureUniqueItemVisual(r,"style"),s)}}}}},pL="undefined"!=typeof Float32Array?Float32Array:Array,dL={seriesType:"candlestick",plan:df(),reset:function(t){var e=t.coordinateSystem,n=t.getData(),i=function(t,e){var n,i=t.getBaseAxis(),r="category"===i.type?i.getBandWidth():(n=i.getExtent(),Math.abs(n[1]-n[0])/e.count()),o=Zi(tt(t.get("barMaxWidth"),r),r),a=Zi(tt(t.get("barMinWidth"),1),r),s=t.get("barWidth");return null!=s?Zi(s,r):Math.max(Math.min(r/2,o),a)}(t,n),r=["x","y"],o=n.mapDimension(r[0]),a=n.mapDimensionsAll(r[1]),s=a[0],l=a[1],u=a[2],h=a[3];if(n.setLayout({candleWidth:i,isSimpleBox:i<=1.3}),!(null==o||a.length<4))return{progress:t.pipelineContext.large?function(t,n){var i,r,a=new pL(4*t.count),c=0,p=[],d=[];for(;null!=(r=t.next());){var f=n.get(o,r),g=n.get(s,r),y=n.get(l,r),v=n.get(u,r),m=n.get(h,r);isNaN(f)||isNaN(v)||isNaN(m)?(a[c++]=NaN,c+=3):(a[c++]=fL(n,r,g,y,l),p[0]=f,p[1]=v,i=e.dataToPoint(p,null,d),a[c++]=i?i[0]:NaN,a[c++]=i?i[1]:NaN,p[1]=m,i=e.dataToPoint(p,null,d),a[c++]=i?i[1]:NaN)}n.setLayout("largePoints",a)}:function(t,n){var r;for(;null!=(r=t.next());){var a=n.get(o,r),c=n.get(s,r),p=n.get(l,r),d=n.get(u,r),f=n.get(h,r),g=Math.min(c,p),y=Math.max(c,p),v=w(g,a),m=w(y,a),_=w(d,a),x=w(f,a),b=[];S(b,m,0),S(b,v,1),b.push(I(x),I(m),I(_),I(v)),n.setItemLayout(r,{sign:fL(n,r,c,p,l),initBaseline:c>p?m[1]:v[1],ends:b,brushRect:M(d,f,a)})}function w(t,n){var i=[];return i[0]=n,i[1]=t,isNaN(n)||isNaN(t)?[NaN,NaN]:e.dataToPoint(i)}function S(t,e,n){var r=e.slice(),o=e.slice();r[0]=ku(r[0]+i/2,1,!1),o[0]=ku(o[0]-i/2,1,!0),n?t.push(r,o):t.push(o,r)}function M(t,e,n){var r=w(t,n),o=w(e,n);return r[0]-=i/2,o[0]-=i/2,{x:r[0],y:r[1],width:i,height:o[1]-r[1]}}function I(t){return t[0]=ku(t[0],1),t}}}}};function fL(t,e,n,i,r){return n>i?-1:n0?t.get(r,e-1)<=i?1:-1:1}function gL(t,e){var n=e.rippleEffectColor||e.color;t.eachChild((function(t){t.attr({z:e.z,zlevel:e.zlevel,style:{stroke:"stroke"===e.brushType?n:null,fill:"fill"===e.brushType?n:null}})}))}var yL=function(t){function e(e,n){var i=t.call(this)||this,r=new bb(e,n),o=new zi;return i.add(r),i.add(o),i.updateData(e,n),i}return n(e,t),e.prototype.stopEffectAnimation=function(){this.childAt(1).removeAll()},e.prototype.startEffectAnimation=function(t){for(var e=t.symbolType,n=t.color,i=this.childAt(1),r=0;r<3;r++){var o=uy(e,-1,-1,2,2,n);o.attr({style:{strokeNoScale:!0},z2:99,silent:!0,scaleX:.5,scaleY:.5});var a=-r/3*t.period+t.effectOffset;o.animate("",!0).when(t.period,{scale:[t.rippleScale/2,t.rippleScale/2]}).delay(a).start(),o.animateStyle(!0).when(t.period,{opacity:0}).delay(a).start(),i.add(o)}gL(i,t)},e.prototype.updateEffectAnimation=function(t){for(var e=this._effectCfg,n=this.childAt(1),i=["symbolType","period","rippleScale"],r=0;r0&&(a=this._getLineLength(i)/l*1e3),(a!==this._period||s!==this._loop)&&(i.stopAnimation(),a>0)){var h=void 0;h="function"==typeof u?u(n):u,i.__t>0&&(h=-a*i.__t),i.__t=0;var c=i.animate("",s).when(a,{__t:1}).delay(h).during((function(){r._updateSymbolPosition(i)}));s||c.done((function(){r.remove(i)})),c.start()}this._period=a,this._loop=s}},e.prototype._getLineLength=function(t){return Lt(t.__p1,t.__cp1)+Lt(t.__cp1,t.__p2)},e.prototype._updateAnimationPoints=function(t,e){t.__p1=e[0],t.__p2=e[1],t.__cp1=e[2]||[(e[0][0]+e[1][0])/2,(e[0][1]+e[1][1])/2]},e.prototype.updateData=function(t,e,n){this.childAt(0).updateData(t,e,n),this._updateEffectSymbol(t,e)},e.prototype._updateSymbolPosition=function(t){var e=t.__p1,n=t.__p2,i=t.__cp1,r=t.__t,o=[t.x,t.y],a=o.slice(),s=Go,l=Ho;o[0]=s(e[0],i[0],n[0],r),o[1]=s(e[1],i[1],n[1],r);var u=l(e[0],i[0],n[0],r),h=l(e[1],i[1],n[1],r);t.rotation=-Math.atan2(h,u)-Math.PI/2,"line"!==this._symbolType&&"rect"!==this._symbolType&&"roundRect"!==this._symbolType||(void 0!==t.__lastT&&t.__lastT=0&&!(i[o]<=e);o--);o=Math.min(o,r-2)}else{for(o=a;oe);o++);o=Math.min(o-1,r-2)}var s=(e-i[o])/(i[o+1]-i[o]),l=n[o],u=n[o+1];t.x=l[0]*(1-s)+s*u[0],t.y=l[1]*(1-s)+s*u[1];var h=u[0]-l[0],c=u[1]-l[1];t.rotation=-Math.atan2(c,h)-Math.PI/2,this._lastFrame=o,this._lastFramePercent=e,t.ignore=!1}},e}(_L),wL=function(){this.polyline=!1,this.curveness=0,this.segs=[]},SL=function(t){function e(e){return t.call(this,e)||this}return n(e,t),e.prototype.getDefaultStyle=function(){return{stroke:"#000",fill:null}},e.prototype.getDefaultShape=function(){return new wL},e.prototype.buildPath=function(t,e){var n=e.segs,i=e.curveness;if(e.polyline)for(var r=0;r0){t.moveTo(n[r++],n[r++]);for(var a=1;a0){var c=(s+u)/2-(l-h)*i,p=(l+h)/2-(u-s)*i;t.quadraticCurveTo(c,p,u,h)}else t.lineTo(u,h)}},e.prototype.findDataIndex=function(t,e){var n=this.shape,i=n.segs,r=n.curveness,o=this.style.lineWidth;if(n.polyline)for(var a=0,s=0;s0)for(var u=i[s++],h=i[s++],c=1;c0){if(La(u,h,(u+p)/2-(h-d)*r,(h+d)/2-(p-u)*r,p,d,o,t,e))return a}else if(Aa(u,h,p,d,o,t,e))return a;a++}return-1},e}(Za),ML=function(){function t(){this.group=new zi}return t.prototype.isPersistent=function(){return!this._incremental},t.prototype.updateData=function(t){this.group.removeAll();var e=new SL({rectHover:!0,cursor:"default"});e.setShape({segs:t.getLayout("linesPoints")}),this._setCommon(e,t),this.group.add(e),this._incremental=null},t.prototype.incrementalPrepareUpdate=function(t){this.group.removeAll(),this._clearIncremental(),t.count()>5e5?(this._incremental||(this._incremental=new vu({silent:!0})),this.group.add(this._incremental)):this._incremental=null},t.prototype.incrementalUpdate=function(t,e){var n=new SL;n.setShape({segs:e.getLayout("linesPoints")}),this._setCommon(n,e,!!this._incremental),this._incremental?this._incremental.addDisplayable(n,!0):(n.rectHover=!0,n.cursor="default",n.__startIndex=t.start,this.group.add(n))},t.prototype.remove=function(){this._clearIncremental(),this._incremental=null,this.group.removeAll()},t.prototype._setCommon=function(t,e,n){var i=e.hostModel;t.setShape({polyline:i.get("polyline"),curveness:i.get(["lineStyle","curveness"])}),t.useStyle(i.getModel("lineStyle").getLineStyle()),t.style.strokeNoScale=!0;var r=e.getVisual("style");if(r&&r.stroke&&t.setStyle("stroke",r.stroke),t.setStyle("fill",null),!n){var o=ys(t);o.seriesIndex=i.seriesIndex,t.on("mousemove",(function(e){o.dataIndex=null;var n=t.findDataIndex(e.offsetX,e.offsetY);n>0&&(o.dataIndex=n+t.__startIndex)}))}},t.prototype._clearIncremental=function(){var t=this._incremental;t&&t.clearDisplaybles()},t}(),IL={seriesType:"lines",plan:df(),reset:function(t){var e=t.coordinateSystem,n=t.get("polyline"),i=t.pipelineContext.large;return{progress:function(r,o){var a=[];if(i){var s=void 0,l=r.end-r.start;if(n){for(var u=0,h=r.start;h ")})},e.prototype.preventIncremental=function(){return!!this.get(["effect","show"])},e.prototype.getProgressive=function(){var t=this.option.progressive;return null==t?this.option.large?1e4:this.get("progressive"):t},e.prototype.getProgressiveThreshold=function(){var t=this.option.progressiveThreshold;return null==t?this.option.large?2e4:this.get("progressiveThreshold"):t},e.type="series.lines",e.dependencies=["grid","polar","geo","calendar"],e.defaultOption={coordinateSystem:"geo",zlevel:0,z:2,legendHoverLink:!0,xAxisIndex:0,yAxisIndex:0,symbol:["none","none"],symbolSize:[10,10],geoIndex:0,effect:{show:!1,period:4,constantSpeed:0,symbol:"circle",symbolSize:3,loop:!0,trailLength:.2},large:!1,largeThreshold:2e3,polyline:!1,clip:!0,label:{show:!1,position:"end"},lineStyle:{opacity:.5}},e}(rf);function kL(t){return t instanceof Array||(t=[t,t]),t}var PL={seriesType:"lines",reset:function(t){var e=kL(t.get("symbol")),n=kL(t.get("symbolSize")),i=t.getData();return i.setVisual("fromSymbol",e&&e[0]),i.setVisual("toSymbol",e&&e[1]),i.setVisual("fromSymbolSize",n&&n[0]),i.setVisual("toSymbolSize",n&&n[1]),{dataEach:i.hasItemOption?function(t,e){var n=t.getItemModel(e),i=kL(n.getShallow("symbol",!0)),r=kL(n.getShallow("symbolSize",!0));i[0]&&t.setItemVisual(e,"fromSymbol",i[0]),i[1]&&t.setItemVisual(e,"toSymbol",i[1]),r[0]&&t.setItemVisual(e,"fromSymbolSize",r[0]),r[1]&&t.setItemVisual(e,"toSymbolSize",r[1])}:null}}};var OL=function(){function t(){this.blurSize=30,this.pointSize=20,this.maxOpacity=1,this.minOpacity=0,this._gradientPixels={inRange:null,outOfRange:null};var t=C();this.canvas=t}return t.prototype.update=function(t,e,n,i,r,o){var a=this._getBrush(),s=this._getGradient(r,"inRange"),l=this._getGradient(r,"outOfRange"),u=this.pointSize+this.blurSize,h=this.canvas,c=h.getContext("2d"),p=t.length;h.width=e,h.height=n;for(var d=0;d0){var I=o(v)?s:l;v>0&&(v=v*S+w),_[x++]=I[M],_[x++]=I[M+1],_[x++]=I[M+2],_[x++]=I[M+3]*v*256}else x+=4}return c.putImageData(m,0,0),h},t.prototype._getBrush=function(){var t=this._brushCanvas||(this._brushCanvas=C()),e=this.pointSize+this.blurSize,n=2*e;t.width=n,t.height=n;var i=t.getContext("2d");return i.clearRect(0,0,n,n),i.shadowOffsetX=n,i.shadowBlur=this.blurSize,i.shadowColor="#000",i.beginPath(),i.arc(-e,e,this.pointSize,0,2*Math.PI,!0),i.closePath(),i.fill(),t},t.prototype._getGradient=function(t,e){for(var n=this._gradientPixels,i=n[e]||(n[e]=new Uint8ClampedArray(1024)),r=[0,0,0,0],o=0,a=0;a<256;a++)t[e](a/255,!0,r),i[o++]=r[0],i[o++]=r[1],i[o++]=r[2],i[o++]=r[3];return i},t}();function RL(t){var e=t.dimensions;return"lng"===e[0]&&"lat"===e[1]}var NL=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n}return n(e,t),e.prototype.render=function(t,e,n){var i;e.eachComponent("visualMap",(function(e){e.eachTargetSeries((function(n){n===t&&(i=e)}))})),this.group.removeAll(),this._incrementalDisplayable=null;var r=t.coordinateSystem;"cartesian2d"===r.type||"calendar"===r.type?this._renderOnCartesianAndCalendar(t,n,0,t.getData().count()):RL(r)&&this._renderOnGeo(r,t,i,n)},e.prototype.incrementalPrepareRender=function(t,e,n){this.group.removeAll()},e.prototype.incrementalRender=function(t,e,n,i){var r=e.coordinateSystem;r&&(RL(r)?this.render(e,n,i):this._renderOnCartesianAndCalendar(e,i,t.start,t.end,!0))},e.prototype._renderOnCartesianAndCalendar=function(t,e,n,i,r){var o,a,s,l,u=t.coordinateSystem;if(Wb(u,"cartesian2d")){var h=u.getAxis("x"),c=u.getAxis("y");0,o=h.getBandWidth(),a=c.getBandWidth(),s=h.scale.getExtent(),l=c.scale.getExtent()}for(var p=this.group,d=t.getData(),f=t.getModel(["emphasis","itemStyle"]).getItemStyle(),g=t.getModel(["blur","itemStyle"]).getItemStyle(),y=t.getModel(["select","itemStyle"]).getItemStyle(),v=eh(t),m=t.get(["emphasis","focus"]),_=t.get(["emphasis","blurScope"]),x=Wb(u,"cartesian2d")?[d.mapDimension("x"),d.mapDimension("y"),d.mapDimension("value")]:[d.mapDimension("time"),d.mapDimension("value")],b=n;bs[1]||Il[1])continue;var T=u.dataToPoint([M,I]);w=new os({shape:{x:Math.floor(Math.round(T[0])-o/2),y:Math.floor(Math.round(T[1])-a/2),width:Math.ceil(o),height:Math.ceil(a)},style:S})}else{if(isNaN(d.get(x[1],b)))continue;w=new os({z2:1,shape:u.dataToRect([d.get(x[0],b)]).contentShape,style:S})}var C=d.getItemModel(b);if(d.hasItemOption){var A=C.getModel("emphasis");f=A.getModel("itemStyle").getItemStyle(),g=C.getModel(["blur","itemStyle"]).getItemStyle(),y=C.getModel(["select","itemStyle"]).getItemStyle(),m=A.get("focus"),_=A.get("blurScope"),v=eh(C)}var D=t.getRawValue(b),L="-";D&&null!=D[2]&&(L=D[2]+""),th(w,v,{labelFetcher:t,labelDataIndex:b,defaultOpacity:S.opacity,defaultText:L}),w.ensureState("emphasis").style=f,w.ensureState("blur").style=g,w.ensureState("select").style=y,Js(w,m,_),w.incremental=r,r&&(w.states.emphasis.hoverLayer=!0),p.add(w),d.setItemGraphicEl(b,w)}},e.prototype._renderOnGeo=function(t,e,n,i){var r=n.targetVisuals.inRange,o=n.targetVisuals.outOfRange,a=e.getData(),s=this._hmLayer||this._hmLayer||new OL;s.blurSize=e.get("blurSize"),s.pointSize=e.get("pointSize"),s.minOpacity=e.get("minOpacity"),s.maxOpacity=e.get("maxOpacity");var l=t.getViewRect().clone(),u=t.getRoamTransform();l.applyTransform(u);var h=Math.max(l.x,0),c=Math.max(l.y,0),p=Math.min(l.width+l.x,i.getWidth()),d=Math.min(l.height+l.y,i.getHeight()),f=p-h,g=d-c,y=[a.mapDimension("lng"),a.mapDimension("lat"),a.mapDimension("value")],v=a.mapArray(y,(function(e,n,i){var r=t.dataToPoint([e,n]);return r[0]-=h,r[1]-=c,r.push(i),r})),m=n.getExtent(),_="visualMap.continuous"===n.type?function(t,e){var n=t[1]-t[0];return e=[(e[0]-t[0])/n,(e[1]-t[0])/n],function(t){return t>=e[0]&&t<=e[1]}}(m,n.option.range):function(t,e,n){var i=t[1]-t[0],r=(e=O(e,(function(e){return{interval:[(e.interval[0]-t[0])/i,(e.interval[1]-t[0])/i]}}))).length,o=0;return function(t){var i;for(i=o;i=0;i--){var a;if((a=e[i].interval)[0]<=t&&t<=a[1]){o=i;break}}return i>=0&&i0?1:o<0?-1:0}(n,o,r,i,c),function(t,e,n,i,r,o,a,s,l,u){var h,c=l.valueDim,p=l.categoryDim,d=Math.abs(n[p.wh]),f=t.getItemVisual(e,"symbolSize");h=F(f)?f.slice():null==f?["100%","100%"]:[f,f];h[p.index]=Zi(h[p.index],d),h[c.index]=Zi(h[c.index],i?d:Math.abs(o)),u.symbolSize=h,(u.symbolScale=[h[0]/s,h[1]/s])[c.index]*=(l.isHorizontal?-1:1)*a}(t,e,r,o,0,c.boundingLength,c.pxSign,u,i,c),function(t,e,n,i,r){var o=t.get(zL)||0;o&&(VL.attr({scaleX:e[0],scaleY:e[1],rotation:n}),VL.updateTransform(),o/=VL.getLineScale(),o*=e[i.valueDim.index]);r.valueLineWidth=o}(n,c.symbolScale,l,i,c);var p=c.symbolSize,d=n.get("symbolOffset");return F(d)&&(d=[Zi(d[0],p[0]),Zi(d[1],p[1])]),function(t,e,n,i,r,o,a,s,l,u,h,c){var p=h.categoryDim,d=h.valueDim,f=c.pxSign,g=Math.max(e[d.index]+s,0),y=g;if(i){var v=Math.abs(l),m=Q(t.get("symbolMargin"),"15%")+"",_=!1;m.lastIndexOf("!")===m.length-1&&(_=!0,m=m.slice(0,m.length-1));var x=Zi(m,e[d.index]),b=Math.max(g+2*x,0),w=_?0:2*x,S=cr(i),M=S?i:ik((v+w)/b);b=g+2*(x=(v-M*g)/2/(_?M:M-1)),w=_?0:2*x,S||"fixed"===i||(M=u?ik((Math.abs(u)+w)/b):0),y=M*b-w,c.repeatTimes=M,c.symbolMargin=x}var T=f*(y/2),C=c.pathPosition=[];C[p.index]=n[p.wh]/2,C[d.index]="start"===a?T:"end"===a?l-T:l/2,o&&(C[0]+=o[0],C[1]+=o[1]);var A=c.bundlePosition=[];A[p.index]=n[p.xy],A[d.index]=n[d.xy];var D=c.barRectShape=I({},n);D[d.wh]=f*Math.max(Math.abs(n[d.wh]),Math.abs(C[d.index]+T)),D[p.wh]=n[p.wh];var L=c.clipShape={};L[p.xy]=-n[p.xy],L[p.wh]=h.ecSize[p.wh],L[d.xy]=0,L[d.wh]=n[d.wh]}(n,p,r,o,0,d,s,c.valueLineWidth,c.boundingLength,c.repeatCutLength,i,c),c}function HL(t,e){return t.toGlobalCoord(t.dataToCoord(t.scale.parse(e)))}function WL(t){var e=t.symbolPatternSize,n=uy(t.symbolType,-e/2,-e/2,e,e);return n.attr({culling:!0}),"image"!==n.type&&n.setStyle({strokeNoScale:!0}),n}function YL(t,e,n,i){var r=t.__pictorialBundle,o=n.symbolSize,a=n.valueLineWidth,s=n.pathPosition,l=e.valueDim,u=n.repeatTimes||0,h=0,c=o[e.valueDim.index]+a+2*n.symbolMargin;for(tk(t,(function(t){t.__pictorialAnimationIndex=h,t.__pictorialRepeatTimes=u,h0:i<0)&&(r=u-1-t),e[l.index]=c*(r-u/2+.5)+s[l.index],{x:e[0],y:e[1],scaleX:n.symbolScale[0],scaleY:n.symbolScale[1],rotation:n.rotation}}}function XL(t,e,n,i){var r=t.__pictorialBundle,o=t.__pictorialMainPath;o?ek(o,null,{x:n.pathPosition[0],y:n.pathPosition[1],scaleX:n.symbolScale[0],scaleY:n.symbolScale[1],rotation:n.rotation},n,i):(o=t.__pictorialMainPath=WL(n),r.add(o),ek(o,{x:n.pathPosition[0],y:n.pathPosition[1],scaleX:0,scaleY:0,rotation:n.rotation},{scaleX:n.symbolScale[0],scaleY:n.symbolScale[1]},n,i))}function UL(t,e,n){var i=I({},e.barRectShape),r=t.__pictorialBarRect;r?ek(r,null,{shape:i},e,n):(r=t.__pictorialBarRect=new os({z2:2,shape:i,silent:!0,style:{stroke:"transparent",fill:"transparent",lineWidth:0}}),t.add(r))}function ZL(t,e,n,i){if(n.symbolClip){var r=t.__pictorialClipPath,o=I({},n.clipShape),a=e.valueDim,s=n.animationModel,l=n.dataIndex;if(r)Ou(r,{shape:o},s,l);else{o[a.wh]=0,r=new os({shape:o}),t.__pictorialBundle.setClipPath(r),t.__pictorialClipPath=r;var u={};u[a.wh]=n.clipShape[a.wh],Ku[i?"updateProps":"initProps"](r,{shape:u},s,l)}}}function jL(t,e){var n=t.getItemModel(e);return n.getAnimationDelayParams=qL,n.isAnimationEnabled=KL,n}function qL(t){return{index:t.__pictorialAnimationIndex,count:t.__pictorialRepeatTimes}}function KL(){return this.parentModel.isAnimationEnabled()&&!!this.getShallow("animation")}function $L(t,e,n,i){var r=new zi,o=new zi;return r.add(o),r.__pictorialBundle=o,o.x=n.bundlePosition[0],o.y=n.bundlePosition[1],n.symbolRepeat?YL(r,e,n):XL(r,0,n),UL(r,n,i),ZL(r,e,n,i),r.__pictorialShapeStr=QL(t,n),r.__pictorialSymbolMeta=n,r}function JL(t,e,n,i){var r=i.__pictorialBarRect;r&&r.removeTextContent();var o=[];tk(i,(function(t){o.push(t)})),i.__pictorialMainPath&&o.push(i.__pictorialMainPath),i.__pictorialClipPath&&(n=null),P(o,(function(t){Nu(t,{scaleX:0,scaleY:0},n,e,(function(){i.parent&&i.parent.remove(i)}))})),t.setItemGraphicEl(e,null)}function QL(t,e){return[t.getItemVisual(e.dataIndex,"symbol")||"none",!!e.symbolRepeat,!!e.symbolClip].join(":")}function tk(t,e,n){P(t.__pictorialBundle.children(),(function(i){i!==t.__pictorialBarRect&&e.call(n,i)}))}function ek(t,e,n,i,r,o){e&&t.attr(e),i.symbolClip&&!r?n&&t.attr(n):n&&Ku[r?"updateProps":"initProps"](t,n,i.animationModel,i.dataIndex,o)}function nk(t,e,n){var i=n.dataIndex,r=n.itemModel,o=r.getModel("emphasis"),a=o.getModel("itemStyle").getItemStyle(),s=r.getModel(["blur","itemStyle"]).getItemStyle(),l=r.getModel(["select","itemStyle"]).getItemStyle(),u=r.getShallow("cursor"),h=o.get("focus"),c=o.get("blurScope"),p=o.get("scale");tk(t,(function(t){if(t instanceof Ja){var e=t.style;t.useStyle(I({image:e.image,x:e.x,y:e.y,width:e.width,height:e.height},n.style))}else t.useStyle(n.style);var i=t.ensureState("emphasis");i.style=a,p&&(i.scaleX=1.1*t.scaleX,i.scaleY=1.1*t.scaleY),t.ensureState("blur").style=s,t.ensureState("select").style=l,u&&(t.cursor=u),t.z2=n.z2}));var d=e.valueDim.posDesc[+(n.boundingLength>0)];th(t.__pictorialBarRect,eh(r),{labelFetcher:e.seriesModel,labelDataIndex:i,defaultText:_b(e.seriesModel.getData(),i),inheritColor:n.style.fill,defaultOpacity:n.style.opacity,defaultOutsidePosition:d}),Js(t,h,c)}function ik(t){var e=Math.round(t);return Math.abs(t-e)<1e-4?e:Math.ceil(t)}var rk=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n.hasSymbolVisual=!0,n.defaultSymbol="roundRect",n}return n(e,t),e.prototype.getInitialData=function(e){return e.stack=null,t.prototype.getInitialData.apply(this,arguments)},e.type="series.pictorialBar",e.dependencies=["grid"],e.defaultOption=Th(iw.defaultOption,{symbol:"circle",symbolSize:null,symbolRotate:null,symbolPosition:null,symbolOffset:null,symbolMargin:null,symbolRepeat:!1,symbolRepeatDirection:"end",symbolClip:!1,symbolBoundingData:null,symbolPatternSize:400,barGap:"-100%",progressive:0,emphasis:{scale:!1},select:{itemStyle:{borderColor:"#212121"}}}),e}(iw);var ok=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n._layers=[],n}return n(e,t),e.prototype.render=function(t,e,n){var i=t.getData(),r=this,o=this.group,a=t.getLayerSeries(),s=i.getLayout("layoutInfo"),l=s.rect,u=s.boundaryGap;function h(t){return t.name}o.x=0,o.y=l.y+u[0];var c=new rm(this._layersSeries||[],a,h,h),p=[];function d(e,n,s){var l=r._layers;if("remove"!==e){for(var u,h,c=[],d=[],f=a[n].indices,g=0;go&&(o=s),i.push(s)}for(var u=0;uo&&(o=c)}return{y0:r,max:o}}(l),h=u.y0,c=n/u.max,p=o.length,d=o[0].indices.length,f=0;fMath.PI/2?"right":"left"):w&&"center"!==w?"left"===w?(v=r.r0+b,a>Math.PI/2&&(w="right")):"right"===w&&(v=r.r-b,a>Math.PI/2&&(w="left")):(v=(r.r+r.r0)/2,w="center"),d.style.align=w,d.style.verticalAlign=f(o,"verticalAlign")||"middle",d.x=v*s+r.cx,d.y=v*l+r.cy;var S=f(o,"rotate"),M=0;"radial"===S?(M=-a)<-Math.PI/2&&(M+=Math.PI):"tangential"===S?(M=Math.PI/2-a)>Math.PI/2?M-=Math.PI:M<-Math.PI/2&&(M+=Math.PI):"number"==typeof S&&(M=S*Math.PI/180),d.rotation=M})),h.dirtyStyle()},e}(Wl),hk="sunburstRootToNode",ck="sunburstHighlight";var pk=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n}return n(e,t),e.prototype.render=function(t,e,n,i){var r=this;this.seriesModel=t,this.api=n,this.ecModel=e;var o=t.getData(),a=o.tree.root,s=t.getViewRoot(),l=this.group,u=t.get("renderLabelForZeroData"),h=[];s.eachNode((function(t){h.push(t)}));var c=this._oldChildren||[];!function(i,r){if(0===i.length&&0===r.length)return;function s(t){return t.getId()}function h(s,h){!function(i,r){u||!i||i.getValue()||(i=null);if(i!==a&&r!==a)if(r&&r.piece)i?(r.piece.updateData(!1,i,t,e,n),o.setItemGraphicEl(i.dataIndex,r.piece)):function(t){if(!t)return;t.piece&&(l.remove(t.piece),t.piece=null)}(r);else if(i){var s=new uk(i,t,e,n);l.add(s),o.setItemGraphicEl(i.dataIndex,s)}}(null==s?null:i[s],null==h?null:r[h])}new rm(r,i,s,s).add(h).update(h).remove(V(h,null)).execute()}(h,c),function(i,o){o.depth>0?(r.virtualPiece?r.virtualPiece.updateData(!1,i,t,e,n):(r.virtualPiece=new uk(i,t,e,n),l.add(r.virtualPiece)),o.piece.off("click"),r.virtualPiece.on("click",(function(t){r._rootToNode(o.parentNode)}))):r.virtualPiece&&(l.remove(r.virtualPiece),r.virtualPiece=null)}(a,s),this._initEvents(),this._oldChildren=h},e.prototype._initEvents=function(){var t=this;this.group.off("click"),this.group.on("click",(function(e){var n=!1;t.seriesModel.getViewRoot().eachNode((function(i){if(!n&&i.piece&&i.piece===e.target){var r=i.getModel().get("nodeClick");if("rootToNode"===r)t._rootToNode(i);else if("link"===r){var o=i.getModel(),a=o.get("link");if(a)wc(a,o.get("target",!0)||"_blank")}n=!0}}))}))},e.prototype._rootToNode=function(t){t!==this.seriesModel.getViewRoot()&&this.api.dispatchAction({type:hk,from:this.uid,seriesId:this.seriesModel.id,targetNode:t})},e.prototype.containPoint=function(t,e){var n=e.getData().getItemLayout(0);if(n){var i=t[0]-n.cx,r=t[1]-n.cy,o=Math.sqrt(i*i+r*r);return o<=n.r&&o>=n.r0}},e.type="sunburst",e}(yf),dk=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n.ignoreStyleOnData=!0,n}return n(e,t),e.prototype.getInitialData=function(t,e){var n={name:t.name,children:t.data};fk(n);var i=O(t.levels||[],(function(t){return new Sh(t,this,e)}),this),r=TI.createTree(n,this,(function(t){t.wrapMethod("getItemModel",(function(t,e){var n=r.getNodeByDataIndex(e),o=i[n.depth];return o&&(t.parentModel=o),t}))}));return r.data},e.prototype.optionUpdated=function(){this.resetViewRoot()},e.prototype.getDataParams=function(e){var n=t.prototype.getDataParams.apply(this,arguments),i=this.getData().tree.getNodeByDataIndex(e);return n.treePathInfo=RI(i,this),n},e.prototype.getViewRoot=function(){return this._viewRoot},e.prototype.resetViewRoot=function(t){t?this._viewRoot=t:t=this._viewRoot;var e=this.getRawData().tree.root;t&&(t===e||e.contains(t))||(this._viewRoot=e)},e.prototype.enableAriaDecal=function(){zI(this)},e.type="series.sunburst",e.defaultOption={zlevel:0,z:2,center:["50%","50%"],radius:[0,"75%"],clockwise:!0,startAngle:90,minAngle:0,stillShowZeroSum:!0,nodeClick:"rootToNode",renderLabelForZeroData:!1,label:{rotate:"radial",show:!0,opacity:1,align:"center",position:"inside",distance:5,silent:!0},itemStyle:{borderWidth:1,borderColor:"white",borderType:"solid",shadowBlur:0,shadowColor:"rgba(0, 0, 0, 0.2)",shadowOffsetX:0,shadowOffsetY:0,opacity:1},emphasis:{focus:"descendant"},blur:{itemStyle:{opacity:.2},label:{opacity:.1}},animationType:"expansion",animationDuration:1e3,animationDurationUpdate:500,data:[],levels:[],sort:"desc"},e}(rf);function fk(t){var e=0;P(t.children,(function(t){fk(t);var n=t.value;F(n)&&(n=n[0]),e+=n}));var n=t.value;F(n)&&(n=n[0]),(null==n||isNaN(n))&&(n=e),n<0&&(n=0),F(t.value)?t.value[0]=n:t.value=n}var gk=Math.PI/180;function yk(t,e,n){e.eachSeriesByType(t,(function(t){var e=t.get("center"),i=t.get("radius");F(i)||(i=[0,i]),F(e)||(e=[e,e]);var r=n.getWidth(),o=n.getHeight(),a=Math.min(r,o),s=Zi(e[0],r),l=Zi(e[1],o),u=Zi(i[0],a/2),h=Zi(i[1],a/2),c=-t.get("startAngle")*gk,p=t.get("minAngle")*gk,d=t.getData().tree.root,f=t.getViewRoot(),g=f.depth,y=t.get("sort");null!=y&&vk(f,y);var v=0;P(f.children,(function(t){!isNaN(t.getValue())&&v++}));var m=f.getValue(),_=Math.PI/(m||v)*2,x=f.depth>0,b=f.height-(x?-1:1),w=(h-u)/(b||1),S=t.get("clockwise"),M=t.get("stillShowZeroSum"),I=S?1:-1,T=function(t,e){if(t){var n=e;if(t!==d){var i=t.getValue(),r=0===m&&M?_:i*_;r1;)r=r.parentNode;var o=n.getColorFromPalette(r.name||r.dataIndex+"",e);return t.depth>1&&"string"==typeof o&&(o=$e(o,(t.depth-1)/(i-1)*.5)),o}(r,t,i.root.height)),I(n.ensureUniqueItemVisual(r.dataIndex,"style"),o)}))}))}function _k(t,e){return e=e||[0,0],O(["x","y"],(function(n,i){var r=this.getAxis(n),o=e[i],a=t[i]/2;return"category"===r.type?r.getBandWidth():Math.abs(r.dataToCoord(o-a)-r.dataToCoord(o+a))}),this)}function xk(t,e){return e=e||[0,0],O([0,1],(function(n){var i=e[n],r=t[n]/2,o=[],a=[];return o[n]=i-r,a[n]=i+r,o[1-n]=a[1-n]=e[1-n],Math.abs(this.dataToPoint(o)[n]-this.dataToPoint(a)[n])}),this)}function bk(t,e){var n=this.getAxis(),i=e instanceof Array?e[0]:e,r=(t instanceof Array?t[0]:t)/2;return"category"===n.type?n.getBandWidth():Math.abs(n.dataToCoord(i-r)-n.dataToCoord(i+r))}function wk(t,e){return e=e||[0,0],O(["Radius","Angle"],(function(n,i){var r=this["get"+n+"Axis"](),o=e[i],a=t[i]/2,s="category"===r.type?r.getBandWidth():Math.abs(r.dataToCoord(o-a)-r.dataToCoord(o+a));return"Angle"===n&&(s=s*Math.PI/180),s}),this)}function Sk(t,e,n,i){return t&&(t.legacy||!1!==t.legacy&&!n&&!i&&"tspan"!==e&&("text"===e||dt(t,"text")))}function Mk(t,e,n){var i,r,o,a=t;if("text"===e)o=a;else{o={},dt(a,"text")&&(o.text=a.text),dt(a,"rich")&&(o.rich=a.rich),dt(a,"textFill")&&(o.fill=a.textFill),dt(a,"textStroke")&&(o.stroke=a.textStroke),r={type:"text",style:o,silent:!0},i={};var s=dt(a,"textPosition");n?i.position=s?a.textPosition:"inside":s&&(i.position=a.textPosition),dt(a,"textPosition")&&(i.position=a.textPosition),dt(a,"textOffset")&&(i.offset=a.textOffset),dt(a,"textRotation")&&(i.rotation=a.textRotation),dt(a,"textDistance")&&(i.distance=a.textDistance)}return Ik(o,t),P(o.rich,(function(t){Ik(t,t)})),{textConfig:i,textContent:r}}function Ik(t,e){e&&(e.font=e.textFont||e.font,dt(e,"textStrokeWidth")&&(t.lineWidth=e.textStrokeWidth),dt(e,"textAlign")&&(t.align=e.textAlign),dt(e,"textVerticalAlign")&&(t.verticalAlign=e.textVerticalAlign),dt(e,"textLineHeight")&&(t.lineHeight=e.textLineHeight),dt(e,"textWidth")&&(t.width=e.textWidth),dt(e,"textHeight")&&(t.height=e.textHeight),dt(e,"textBackgroundColor")&&(t.backgroundColor=e.textBackgroundColor),dt(e,"textPadding")&&(t.padding=e.textPadding),dt(e,"textBorderColor")&&(t.borderColor=e.textBorderColor),dt(e,"textBorderWidth")&&(t.borderWidth=e.textBorderWidth),dt(e,"textBorderRadius")&&(t.borderRadius=e.textBorderRadius),dt(e,"textBoxShadowColor")&&(t.shadowColor=e.textBoxShadowColor),dt(e,"textBoxShadowBlur")&&(t.shadowBlur=e.textBoxShadowBlur),dt(e,"textBoxShadowOffsetX")&&(t.shadowOffsetX=e.textBoxShadowOffsetX),dt(e,"textBoxShadowOffsetY")&&(t.shadowOffsetY=e.textBoxShadowOffsetY))}function Tk(t,e,n){var i=t;i.textPosition=i.textPosition||n.position||"inside",null!=n.offset&&(i.textOffset=n.offset),null!=n.rotation&&(i.textRotation=n.rotation),null!=n.distance&&(i.textDistance=n.distance);var r=i.textPosition.indexOf("inside")>=0,o=t.fill||"#000";Ck(i,e);var a=null==i.textFill;return r?a&&(i.textFill=n.insideFill||"#fff",!i.textStroke&&n.insideStroke&&(i.textStroke=n.insideStroke),!i.textStroke&&(i.textStroke=o),null==i.textStrokeWidth&&(i.textStrokeWidth=2)):(a&&(i.textFill=n.outsideFill||o),!i.textStroke&&n.outsideStroke&&(i.textStroke=n.outsideStroke)),i.text=e.text,i.rich=e.rich,P(e.rich,(function(t){Ck(t,t)})),i}function Ck(t,e){e&&(dt(e,"fill")&&(t.textFill=e.fill),dt(e,"stroke")&&(t.textStroke=e.fill),dt(e,"lineWidth")&&(t.textStrokeWidth=e.lineWidth),dt(e,"font")&&(t.font=e.font),dt(e,"fontStyle")&&(t.fontStyle=e.fontStyle),dt(e,"fontWeight")&&(t.fontWeight=e.fontWeight),dt(e,"fontSize")&&(t.fontSize=e.fontSize),dt(e,"fontFamily")&&(t.fontFamily=e.fontFamily),dt(e,"align")&&(t.textAlign=e.align),dt(e,"verticalAlign")&&(t.textVerticalAlign=e.verticalAlign),dt(e,"lineHeight")&&(t.textLineHeight=e.lineHeight),dt(e,"width")&&(t.textWidth=e.width),dt(e,"height")&&(t.textHeight=e.height),dt(e,"backgroundColor")&&(t.textBackgroundColor=e.backgroundColor),dt(e,"padding")&&(t.textPadding=e.padding),dt(e,"borderColor")&&(t.textBorderColor=e.borderColor),dt(e,"borderWidth")&&(t.textBorderWidth=e.borderWidth),dt(e,"borderRadius")&&(t.textBorderRadius=e.borderRadius),dt(e,"shadowColor")&&(t.textBoxShadowColor=e.shadowColor),dt(e,"shadowBlur")&&(t.textBoxShadowBlur=e.shadowBlur),dt(e,"shadowOffsetX")&&(t.textBoxShadowOffsetX=e.shadowOffsetX),dt(e,"shadowOffsetY")&&(t.textBoxShadowOffsetY=e.shadowOffsetY),dt(e,"textShadowColor")&&(t.textShadowColor=e.textShadowColor),dt(e,"textShadowBlur")&&(t.textShadowBlur=e.textShadowBlur),dt(e,"textShadowOffsetX")&&(t.textShadowOffsetX=e.textShadowOffsetX),dt(e,"textShadowOffsetY")&&(t.textShadowOffsetY=e.textShadowOffsetY))}var Ak=Ca.CMD,Dk=2*Math.PI,Lk=["x","y"],kk=["width","height"],Pk=[];function Ok(t,e){return Math.abs(t-e)<1e-5}function Rk(t){var e,n,i,r,o,a=t.data,s=t.len(),l=[],u=0,h=0,c=0,p=0;function d(t,n){e&&e.length>2&&l.push(e),e=[t,n]}function f(t,n,i,r){Ok(t,i)&&Ok(n,r)||e.push(t,n,i,r,i,r)}function g(t,n,i,r,o,a){var s=Math.abs(n-t),l=4*Math.tan(s/4)/3,u=nM:C2&&l.push(e),l}function Nk(t,e){var n=t.length,i=e.length;if(n===i)return[t,e];for(var r=n0)for(var b=i/n,w=-i/2;w<=i/2;w+=b){var S=Math.sin(w),M=Math.cos(w),I=0;for(_=0;_c.width?1:0,r=kk[i],o=Lk[i],a=c[r]/e,s=c[o],l=0;li[1]&&i.reverse(),{coordSys:{type:"polar",cx:t.cx,cy:t.cy,r:i[1],r0:i[0]},api:{coord:function(i){var r=e.dataToRadius(i[0]),o=n.dataToAngle(i[1]),a=t.coordToPoint([r,o]);return a.push(r,o*Math.PI/180),a},size:B(wk,t)}}},calendar:function(t){var e=t.getRect(),n=t.getRangeInfo();return{coordSys:{type:"calendar",x:e.x,y:e.y,width:e.width,height:e.height,cellWidth:t.getCellWidth(),cellHeight:t.getCellHeight(),rangeInfo:{start:n.start,end:n.end,weeks:n.weeks,dayCount:n.allDay}},api:{coord:function(e,n){return t.dataToPoint(e,n)}}}}},fP=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n}return n(e,t),e.prototype.optionUpdated=function(){this.currentZLevel=this.get("zlevel",!0),this.currentZ=this.get("z",!0)},e.prototype.getInitialData=function(t,e){return Hm(this.getSource(),this)},e.prototype.getDataParams=function(e,n,i){var r=t.prototype.getDataParams.call(this,e,n);return i&&(r.info=Qk(i).info),r},e.type="series.custom",e.dependencies=["grid","polar","geo","singleAxis","calendar"],e.defaultOption={coordinateSystem:"cartesian2d",zlevel:0,z:2,legendHoverLink:!0,clip:!1},e}(rf),gP=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n}return n(e,t),e.prototype.render=function(t,e,n,i){var r=this._data,o=t.getData(),a=this.group,s=NP(t,o,e,n),l=t.__transientTransitionOpt;if(!l||null!=l.from&&null!=l.to){var u=new KP(t,l),h=l?"multiple":"oneToOne";new rm(r?r.getIndices():[],o.getIndices(),yP(r,h,l&&l.from),yP(o,h,l&&l.to),null,h).add((function(e){zP(n,null,e,s(e,i),t,a,o,null)})).remove((function(e){UP(r.getItemGraphicEl(e),t,a)})).update((function(e,l){u.reset("oneToOne");var h=r.getItemGraphicEl(l);u.findAndAddFrom(h),u.hasFrom()&&(qP(h,a),h=null),zP(n,h,e,s(e,i),t,a,o,u),u.applyMorphing()})).updateManyToOne((function(e,l){u.reset("manyToOne");for(var h=0;h=0){!s&&(s=r[t]={});var f=z(l);for(c=0;c=0){var d=t.getAnimationStyleProps(),f=d?d.style:null;if(f){!a&&(a=r.style={});var g=z(i);for(h=0;h=p;d--)UP(e.childAt(d),r,e)}(t,e,n,i,r,s),l>=0?o.replaceAt(e,l):o.add(e),e}function VP(t,e){var n,i=Qk(t),r=e.type,o=e.shape,a=e.style;return null!=r&&r!==i.customGraphicType||"path"===r&&((n=o)&&(dt(n,"pathData")||dt(n,"d")))&&ZP(o)!==i.customPathData||"image"===r&&dt(a,"image")&&a.image!==i.customImagePath}function FP(t,e,n){var i=e?GP(t,e):t,r=e?HP(t,i,iP):t.style,o=t.type,a=i?i.textConfig:null,s=t.textContent,l=s?e?GP(s,e):s:null;if(r&&(n.isLegacy||Sk(r,o,!!a,!!l))){n.isLegacy=!0;var u=Mk(r,o,!e);!a&&u.textConfig&&(a=u.textConfig),!l&&u.textContent&&(l=u.textContent)}if(!e&&l){var h=l;!h.type&&(h.type="text")}var c=e?n[e]:n.normal;c.cfg=a,c.conOpt=l}function GP(t,e){return e?t?t[e]:null:t}function HP(t,e,n){var i=e&&e.style;return null==i&&n===iP&&t&&(i=t.styleEmphasis),i}function WP(t,e){var n=t&&t.name;return null!=n?n:"e\0\0"+e}function YP(t,e){var n=this.context,i=null!=t?n.newChildren[t]:null,r=null!=e?n.oldChildren[e]:null;BP(n.api,r,n.dataIndex,i,n.seriesModel,n.group,0,n.morphPreparation)}function XP(t){var e=this.context;UP(e.oldChildren[t],e.seriesModel,e.group)}function UP(t,e,n){if(t){var i=Qk(t).leaveToProps;i?Ou(t,i,e,{cb:function(){n.remove(t)}}):n.remove(t)}}function ZP(t){return t&&(t.pathData||t.d)}function jP(t){return t&&t instanceof Za}function qP(t,e){t&&e.remove(t)}var KP=function(){function t(t,e){this._fromList=[],this._toList=[],this._toElOptionList=[],this._allPropsFinalList=[],this._toDataIndices=[],this._morphConfigList=[],this._seriesModel=t,this._transOpt=e}return t.prototype.hasFrom=function(){return!!this._fromList.length},t.prototype.findAndAddFrom=function(t){if(t&&(Qk(t).canMorph&&this._fromList.push(t),t.isGroup))for(var e=t.childrenRef(),n=0;n=n?i-a:o;this._manyToOneForSingleTo(r,a>=i?null:a,s)}else if("oneToMany"===t)for(var l=Math.max(1,Math.floor(n/i)),u=0,h=0;u=n?n-u:l;this._oneToManyForSingleFrom(u,c,h>=i?null:h)}},t.prototype._oneToOneForSingleTo=function(t,e){var n,i=this._toList[t],r=this._toElOptionList[t],o=this._toDataIndices[t],a=this._allPropsFinalList[t],s=this._fromList[e],l=this._getOrCreateMorphConfig(o),u=l.duration;if(s&&Yk(s)){if(_P(i,a,r.style),u){var h=Xk([s],i,l,$P);this._processResultIndividuals(h,t,null)}}else{var c=u&&s&&(s!==i||(Wk(n=s)||Yk(n)))?s:null,p={};bP("shape",i,c,r,p,!1),bP("extra",i,c,r,p,!1),SP(i,c,r,p,!1),MP(i,c,r,r.style,p,!1),_P(i,a,r.style),c&&Fk(c,i,l),xP(i,o,r,this._seriesModel,p,!1)}},t.prototype._manyToOneForSingleTo=function(t,e,n){var i=this._toList[t],r=this._toElOptionList[t];_P(i,this._allPropsFinalList[t],r.style);var o=this._getOrCreateMorphConfig(this._toDataIndices[t]);if(o.duration&&null!=e){for(var a=[],s=e;sa)return!0;if(o){var s=_S(t).seriesDataCount,l=i.getExtent();return Math.abs(l[0]-l[1])/s>a}return!1}return!0===n},t.prototype.makeElOption=function(t,e,n,i,r){},t.prototype.createPointerEl=function(t,e,n,i){var r=e.pointer;if(r){var o=JP(t).pointerEl=new Ku[r.type](QP(e.pointer));t.add(o)}},t.prototype.createLabelEl=function(t,e,n,i){if(e.label){var r=JP(t).labelEl=new ls(QP(e.label));t.add(r),rO(r,i)}},t.prototype.updatePointerEl=function(t,e,n){var i=JP(t).pointerEl;i&&e.pointer&&(i.setStyle(e.pointer.style),n(i,{shape:e.pointer.shape}))},t.prototype.updateLabelEl=function(t,e,n,i){var r=JP(t).labelEl;r&&(r.setStyle(e.label.style),n(r,{x:e.label.x,y:e.label.y}),rO(r,i))},t.prototype._renderHandle=function(t){if(!this._dragging&&this.updateHandleTransform){var e,n=this._axisPointerModel,i=this._api.getZr(),r=this._handle,o=n.getModel("handle"),a=n.get("status");if(!o.get("show")||!a||"hide"===a)return r&&i.remove(r),void(this._handle=null);this._handle||(e=!0,r=this._handle=Uu(o.get("icon"),{cursor:"move",draggable:!0,onmousemove:function(t){ee(t.event)},onmousedown:tO(this._onHandleDragMove,this,0,0),drift:tO(this._onHandleDragMove,this),ondragend:tO(this._onHandleDragEnd,this)}),i.add(r)),aO(r,n,!1),r.setStyle(o.getItemStyle(null,["color","borderColor","borderWidth","opacity","shadowColor","shadowBlur","shadowOffsetX","shadowOffsetY"]));var s=o.get("size");F(s)||(s=[s,s]),r.scaleX=s[0]/2,r.scaleY=s[1]/2,Tf(this,"_doDispatchAxisPointer",o.get("throttle")||0,"fixRate"),this._moveHandleToValue(t,e)}},t.prototype._moveHandleToValue=function(t,e){nO(this._axisPointerModel,!e&&this._moveAnimation,this._handle,oO(this.getHandleTransform(t,this._axisModel,this._axisPointerModel)))},t.prototype._onHandleDragMove=function(t,e){var n=this._handle;if(n){this._dragging=!0;var i=this.updateHandleTransform(oO(n),[t,e],this._axisModel,this._axisPointerModel);this._payloadInfo=i,n.stopAnimation(),n.attr(oO(i)),JP(n).lastProp=null,this._doDispatchAxisPointer()}},t.prototype._doDispatchAxisPointer=function(){if(this._handle){var t=this._payloadInfo,e=this._axisModel;this._api.dispatchAction({type:"updateAxisPointer",x:t.cursorPoint[0],y:t.cursorPoint[1],tooltipOption:t.tooltipOption,axesInfo:[{axisDim:e.axis.dim,axisIndex:e.componentIndex}]})}},t.prototype._onHandleDragEnd=function(){if(this._dragging=!1,this._handle){var t=this._axisPointerModel.get("value");this._moveHandleToValue(t),this._api.dispatchAction({type:"hideTip"})}},t.prototype.clear=function(t){this._lastValue=null,this._lastStatus=null;var e=t.getZr(),n=this._group,i=this._handle;e&&n&&(this._lastGraphicKey=null,n&&e.remove(n),i&&e.remove(i),this._group=null,this._handle=null,this._payloadInfo=null)},t.prototype.doClear=function(){},t.prototype.buildLabel=function(t,e,n){return{x:t[n=n||0],y:t[1-n],width:e[n],height:e[1-n]}},t}();function nO(t,e,n,i){iO(JP(n).lastProp,i)||(JP(n).lastProp=i,e?Ou(n,i,t):(n.stopAnimation(),n.attr(i)))}function iO(t,e){if(X(t)&&X(e)){var n=!0;return P(e,(function(e,i){n=n&&iO(t[i],e)})),!!n}return t===e}function rO(t,e){t[e.get(["label","show"])?"show":"hide"]()}function oO(t){return{x:t.x||0,y:t.y||0,rotation:t.rotation||0}}function aO(t,e,n){var i=e.get("z"),r=e.get("zlevel");t&&t.traverse((function(t){"group"!==t.type&&(null!=i&&(t.z=i),null!=r&&(t.zlevel=r),t.silent=n)}))}function sO(t){var e,n=t.get("type"),i=t.getModel(n+"Style");return"line"===n?(e=i.getLineStyle()).fill=null:"shadow"===n&&((e=i.getAreaStyle()).stroke=null),e}function lO(t,e,n,i,r){var o=uO(n.get("value"),e.axis,e.ecModel,n.get("seriesDataIndices"),{precision:n.get(["label","precision"]),formatter:n.get(["label","formatter"])}),a=n.getModel("label"),s=pc(a.get("padding")||0),l=a.getFont(),u=Fn(o,l),h=r.position,c=u.width+s[1]+s[3],p=u.height+s[0]+s[2],d=r.align;"right"===d&&(h[0]-=c),"center"===d&&(h[0]-=c/2);var f=r.verticalAlign;"bottom"===f&&(h[1]-=p),"middle"===f&&(h[1]-=p/2),function(t,e,n,i){var r=i.getWidth(),o=i.getHeight();t[0]=Math.min(t[0]+e,r)-e,t[1]=Math.min(t[1]+n,o)-n,t[0]=Math.max(t[0],0),t[1]=Math.max(t[1],0)}(h,c,p,i);var g=a.get("backgroundColor");g&&"auto"!==g||(g=e.get(["axisLine","lineStyle","color"])),t.label={x:h[0],y:h[1],style:nh(a,{text:o,font:l,fill:a.getTextColor(),padding:s,backgroundColor:g}),z2:10}}function uO(t,e,n,i,r){t=e.scale.parse(t);var o=e.scale.getLabel({value:t},{precision:r.precision}),a=r.formatter;if(a){var s={value:W_(e,{value:t}),axisDimension:e.dim,axisIndex:e.index,seriesData:[]};P(i,(function(t){var e=n.getSeriesByIndex(t.seriesIndex),i=t.dataIndexInside,r=e&&e.getDataParams(i);r&&s.seriesData.push(r)})),H(a)?o=a.replace("{value}",o):G(a)&&(o=a(s))}return o}function hO(t,e,n){var i=[1,0,0,1,0,0];return _e(i,i,n.rotation),me(i,i,n.position),Fu([t.dataToCoord(e),(n.labelOffset||0)+(n.labelDirection||1)*(n.labelMargin||0)],i)}function cO(t,e,n,i,r,o){var a=hS.innerTextLayout(n.rotation,0,n.labelDirection);n.labelMargin=r.get(["label","margin"]),lO(e,i,r,o,{position:hO(i.axis,t,n),align:a.textAlign,verticalAlign:a.textVerticalAlign})}function pO(t,e,n){return{x1:t[n=n||0],y1:t[1-n],x2:e[n],y2:e[1-n]}}function dO(t,e,n){return{x:t[n=n||0],y:t[1-n],width:e[n],height:e[1-n]}}function fO(t,e,n,i,r,o){return{cx:t,cy:e,r0:n,r:i,startAngle:r,endAngle:o,clockwise:!0}}var gO=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return n(e,t),e.prototype.makeElOption=function(t,e,n,i,r){var o=n.axis,a=o.grid,s=i.get("type"),l=yO(a,o).getOtherAxis(o).getGlobalExtent(),u=o.toGlobalCoord(o.dataToCoord(e,!0));if(s&&"none"!==s){var h=sO(i),c=vO[s](o,u,l);c.style=h,t.graphicKey=c.type,t.pointer=c}cO(e,t,nS(a.model,n),n,i,r)},e.prototype.getHandleTransform=function(t,e,n){var i=nS(e.axis.grid.model,e,{labelInside:!1});i.labelMargin=n.get(["handle","margin"]);var r=hO(e.axis,t,i);return{x:r[0],y:r[1],rotation:i.rotation+(i.labelDirection<0?Math.PI:0)}},e.prototype.updateHandleTransform=function(t,e,n,i){var r=n.axis,o=r.grid,a=r.getGlobalExtent(!0),s=yO(o,r).getOtherAxis(r).getGlobalExtent(),l="x"===r.dim?0:1,u=[t.x,t.y];u[l]+=e[l],u[l]=Math.min(a[1],u[l]),u[l]=Math.max(a[0],u[l]);var h=(s[1]+s[0])/2,c=[h,h];c[l]=u[l];return{x:u[0],y:u[1],rotation:t.rotation,cursorPoint:c,tooltipOption:[{verticalAlign:"middle"},{align:"center"}][l]}},e}(eO);function yO(t,e){var n={};return n[e.dim+"AxisIndex"]=e.index,t.getCartesian(n)}var vO={line:function(t,e,n){return{type:"Line",subPixelOptimize:!0,shape:pO([e,n[0]],[e,n[1]],mO(t))}},shadow:function(t,e,n){var i=Math.max(1,t.getBandWidth()),r=n[1]-n[0];return{type:"Rect",shape:dO([e-i/2,n[0]],[i,r],mO(t))}}};function mO(t){return"x"===t.dim?0:1}var _O=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n}return n(e,t),e.type="axisPointer",e.defaultOption={show:"auto",zlevel:0,z:50,type:"line",snap:!1,triggerTooltip:!0,value:null,status:null,link:[],animation:null,animationDurationUpdate:200,lineStyle:{color:"#B9BEC9",width:1,type:"dashed"},shadowStyle:{color:"rgba(210,219,238,0.2)"},label:{show:!0,formatter:null,precision:"auto",margin:3,color:"#fff",padding:[5,7,5,7],backgroundColor:"auto",borderColor:null,borderWidth:0,borderRadius:3},handle:{show:!1,icon:"M10.7,11.9v-1.3H9.3v1.3c-4.9,0.3-8.8,4.4-8.8,9.4c0,5,3.9,9.1,8.8,9.4h1.3c4.9-0.3,8.8-4.4,8.8-9.4C19.5,16.3,15.6,12.2,10.7,11.9z M13.3,24.4H6.7v-1.2h6.6z M13.3,22H6.7v-1.2h6.6z M13.3,19.6H6.7v-1.2h6.6z",size:45,margin:50,color:"#333",shadowBlur:3,shadowColor:"#aaa",shadowOffsetX:0,shadowOffsetY:2,throttle:40}},e}(Nc),xO=Lr(),bO=P;function wO(t,e,n){if(!a.node){var i=e.getZr();xO(i).records||(xO(i).records={}),function(t,e){if(xO(t).initialized)return;function n(n,i){t.on(n,(function(n){var r=function(t){var e={showTip:[],hideTip:[]},n=function(i){var r=e[i.type];r?r.push(i):(i.dispatchAction=n,t.dispatchAction(i))};return{dispatchAction:n,pendings:e}}(e);bO(xO(t).records,(function(t){t&&i(t,n,r.dispatchAction)})),function(t,e){var n,i=t.showTip.length,r=t.hideTip.length;i?n=t.showTip[i-1]:r&&(n=t.hideTip[r-1]);n&&(n.dispatchAction=null,e.dispatchAction(n))}(r.pendings,e)}))}xO(t).initialized=!0,n("click",V(MO,"click")),n("mousemove",V(MO,"mousemove")),n("globalout",SO)}(i,e),(xO(i).records[t]||(xO(i).records[t]={})).handler=n}}function SO(t,e,n){t.handler("leave",null,n)}function MO(t,e,n,i){e.handler(t,n,i)}function IO(t,e){if(!a.node){var n=e.getZr();(xO(n).records||{})[t]&&(xO(n).records[t]=null)}}var TO=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n}return n(e,t),e.prototype.render=function(t,e,n){var i=e.getComponent("tooltip"),r=t.get("triggerOn")||i&&i.get("triggerOn")||"mousemove|click";wO("axisPointer",n,(function(t,e,n){"none"!==r&&("leave"===t||r.indexOf(t)>=0)&&n({type:"updateAxisPointer",currTrigger:t,x:e&&e.offsetX,y:e&&e.offsetY})}))},e.prototype.remove=function(t,e){IO("axisPointer",e)},e.prototype.dispose=function(t,e){IO("axisPointer",e)},e.type="axisPointer",e}(pf);function CO(t,e){var n,i=[],r=t.seriesIndex;if(null==r||!(n=e.getSeriesByIndex(r)))return{point:[]};var o=n.getData(),a=Dr(o,t);if(null==a||a<0||F(a))return{point:[]};var s=o.getItemGraphicEl(a),l=n.coordinateSystem;if(n.getTooltipPosition)i=n.getTooltipPosition(a)||[];else if(l&&l.dataToPoint)if(t.isStacked){var u=l.getBaseAxis(),h=l.getOtherAxis(u).dim,c=u.dim,p="x"===h||"radius"===h?1:0,d=o.mapDimension(c),f=[];f[p]=o.get(d,a),f[1-p]=o.get(o.getCalculationInfo("stackResultDimension"),a),i=l.dataToPoint(f)||[]}else i=l.dataToPoint(o.getValues(O(l.dimensions,(function(t){return o.mapDimension(t)})),a))||[];else if(s){var g=s.getBoundingRect().clone();g.applyTransform(s.transform),i=[g.x+g.width/2,g.y+g.height/2]}return{point:i,el:s}}var AO=Lr();function DO(t,e,n){var i=t.currTrigger,r=[t.x,t.y],o=t,a=t.dispatchAction||B(n.dispatchAction,n),s=e.getComponent("axisPointer").coordSysAxesInfo;if(s){RO(r)&&(r=CO({seriesIndex:o.seriesIndex,dataIndex:o.dataIndex},e).point);var l=RO(r),u=o.axesInfo,h=s.axesInfo,c="leave"===i||RO(r),p={},d={},f={list:[],map:{}},g={showPointer:V(kO,d),showTooltip:V(PO,f)};P(s.coordSysMap,(function(t,e){var n=l||t.containPoint(r);P(s.coordSysAxesInfo[e],(function(t,e){var i=t.axis,o=function(t,e){for(var n=0;n<(t||[]).length;n++){var i=t[n];if(e.axis.dim===i.axisDim&&e.axis.model.componentIndex===i.axisIndex)return i}}(u,t);if(!c&&n&&(!u||o)){var a=o&&o.value;null!=a||l||(a=i.pointToData(r)),null!=a&&LO(t,a,g,!1,p)}}))}));var y={};return P(h,(function(t,e){var n=t.linkGroup;n&&!d[e]&&P(n.axesInfo,(function(e,i){var r=d[i];if(e!==t&&r){var o=r.value;n.mapper&&(o=t.axis.scale.parse(n.mapper(o,OO(e),OO(t)))),y[t.key]=o}}))})),P(y,(function(t,e){LO(h[e],t,g,!0,p)})),function(t,e,n){var i=n.axesInfo=[];P(e,(function(e,n){var r=e.axisPointerModel.option,o=t[n];o?(!e.useHandle&&(r.status="show"),r.value=o.value,r.seriesDataIndices=(o.payloadBatch||[]).slice()):!e.useHandle&&(r.status="hide"),"show"===r.status&&i.push({axisDim:e.axis.dim,axisIndex:e.axis.model.componentIndex,value:r.value})}))}(d,h,p),function(t,e,n,i){if(RO(e)||!t.list.length)return void i({type:"hideTip"});var r=((t.list[0].dataByAxis[0]||{}).seriesDataIndices||[])[0]||{};i({type:"showTip",escapeConnect:!0,x:e[0],y:e[1],tooltipOption:n.tooltipOption,position:n.position,dataIndexInside:r.dataIndexInside,dataIndex:r.dataIndex,seriesIndex:r.seriesIndex,dataByCoordSys:t.list})}(f,r,t,a),function(t,e,n){var i=n.getZr(),r="axisPointerLastHighlights",o=AO(i)[r]||{},a=AO(i)[r]={};P(t,(function(t,e){var n=t.axisPointerModel.option;"show"===n.status&&P(n.seriesDataIndices,(function(t){var e=t.seriesIndex+" | "+t.dataIndex;a[e]=t}))}));var s=[],l=[];P(o,(function(t,e){!a[e]&&l.push(t)})),P(a,(function(t,e){!o[e]&&s.push(t)})),l.length&&n.dispatchAction({type:"downplay",escapeConnect:!0,notBlur:!0,batch:l}),s.length&&n.dispatchAction({type:"highlight",escapeConnect:!0,notBlur:!0,batch:s})}(h,0,n),p}}function LO(t,e,n,i,r){var o=t.axis;if(!o.scale.isBlank()&&o.containData(e))if(t.involveSeries){var a=function(t,e){var n=e.axis,i=n.dim,r=t,o=[],a=Number.MAX_VALUE,s=-1;return P(e.seriesModels,(function(e,l){var u,h,c=e.getData().mapDimensionsAll(i);if(e.getAxisTooltipData){var p=e.getAxisTooltipData(c,t,n);h=p.dataIndices,u=p.nestestValue}else{if(!(h=e.getData().indicesOfNearest(c[0],t,"category"===n.type?.5:null)).length)return;u=e.getData().get(c[0],h[0])}if(null!=u&&isFinite(u)){var d=t-u,f=Math.abs(d);f<=a&&((f=0&&s<0)&&(a=f,s=d,r=u,o.length=0),P(h,(function(t){o.push({seriesIndex:e.seriesIndex,dataIndexInside:t,dataIndex:e.getData().getRawIndex(t)})})))}})),{payloadBatch:o,snapToValue:r}}(e,t),s=a.payloadBatch,l=a.snapToValue;s[0]&&null==r.seriesIndex&&I(r,s[0]),!i&&t.snap&&o.containData(l)&&null!=l&&(e=l),n.showPointer(t,e,s),n.showTooltip(t,a,l)}else n.showPointer(t,e)}function kO(t,e,n,i){t[e.key]={value:n,payloadBatch:i}}function PO(t,e,n,i){var r=n.payloadBatch,o=e.axis,a=o.model,s=e.axisPointerModel;if(e.triggerTooltip&&r.length){var l=e.coordSys.model,u=bS(l),h=t.map[u];h||(h=t.map[u]={coordSysId:l.id,coordSysIndex:l.componentIndex,coordSysType:l.type,coordSysMainType:l.mainType,dataByAxis:[]},t.list.push(h)),h.dataByAxis.push({axisDim:o.dim,axisIndex:a.componentIndex,axisType:a.type,axisId:a.id,value:i,valueLabelOpt:{precision:s.get(["label","precision"]),formatter:s.get(["label","formatter"])},seriesDataIndices:r.slice()})}}function OO(t){var e=t.axis.model,n={},i=n.axisDim=t.axis.dim;return n.axisIndex=n[i+"AxisIndex"]=e.componentIndex,n.axisName=n[i+"AxisName"]=e.name,n.axisId=n[i+"AxisId"]=e.id,n}function RO(t){return!t||null==t[0]||isNaN(t[0])||null==t[1]||isNaN(t[1])}function NO(t){SS.registerAxisPointerClass("CartesianAxisPointer",gO),t.registerComponentModel(_O),t.registerComponentView(TO),t.registerPreprocessor((function(t){if(t){(!t.axisPointer||0===t.axisPointer.length)&&(t.axisPointer={});var e=t.axisPointer.link;e&&!F(e)&&(t.axisPointer.link=[e])}})),t.registerProcessor(t.PRIORITY.PROCESSOR.STATISTIC,(function(t,e){t.getComponent("axisPointer").coordSysAxesInfo=yS(t,e)})),t.registerAction({type:"updateAxisPointer",event:"updateAxisPointer",update:":updateAxisPointer"},DO)}var EO=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return n(e,t),e.prototype.makeElOption=function(t,e,n,i,r){var o=n.axis;"angle"===o.dim&&(this.animationThreshold=Math.PI/18);var a=o.polar,s=a.getOtherAxis(o).getExtent(),l=o.dataToCoord(e),u=i.get("type");if(u&&"none"!==u){var h=sO(i),c=zO[u](o,a,l,s);c.style=h,t.graphicKey=c.type,t.pointer=c}var p=function(t,e,n,i,r){var o=e.axis,a=o.dataToCoord(t),s=i.getAngleAxis().getExtent()[0];s=s/180*Math.PI;var l,u,h,c=i.getRadiusAxis().getExtent();if("radius"===o.dim){var p=[1,0,0,1,0,0];_e(p,p,s),me(p,p,[i.cx,i.cy]),l=Fu([a,-r],p);var d=e.getModel("axisLabel").get("rotate")||0,f=hS.innerTextLayout(s,d*Math.PI/180,-1);u=f.textAlign,h=f.textVerticalAlign}else{var g=c[1];l=i.coordToPoint([g+r,a]);var y=i.cx,v=i.cy;u=Math.abs(l[0]-y)/g<.3?"center":l[0]>y?"left":"right",h=Math.abs(l[1]-v)/g<.3?"middle":l[1]>v?"top":"bottom"}return{position:l,align:u,verticalAlign:h}}(e,n,0,a,i.get(["label","margin"]));lO(t,n,i,r,p)},e}(eO);var zO={line:function(t,e,n,i){return"angle"===t.dim?{type:"Line",shape:pO(e.coordToPoint([i[0],n]),e.coordToPoint([i[1],n]))}:{type:"Circle",shape:{cx:e.cx,cy:e.cy,r:n}}},shadow:function(t,e,n,i){var r=Math.max(1,t.getBandWidth()),o=Math.PI/180;return"angle"===t.dim?{type:"Sector",shape:fO(e.cx,e.cy,i[0],i[1],(-n-r/2)*o,(r/2-n)*o)}:{type:"Sector",shape:fO(e.cx,e.cy,n-r/2,n+r/2,0,2*Math.PI)}}},BO=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n}return n(e,t),e.prototype.findAxisModel=function(t){var e;return this.ecModel.eachComponent(t,(function(t){t.getCoordSysModel()===this&&(e=t)}),this),e},e.type="polar",e.dependencies=["radiusAxis","angleAxis"],e.defaultOption={zlevel:0,z:0,center:["50%","50%"],radius:"80%"},e}(Nc),VO=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return n(e,t),e.prototype.getCoordSysModel=function(){return this.getReferringComponents("polar",Or).models[0]},e.type="polarAxis",e}(Nc);L(VO,j_);var FO=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n}return n(e,t),e.type="angleAxis",e}(VO),GO=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n}return n(e,t),e.type="radiusAxis",e}(VO),HO=function(t){function e(e,n){return t.call(this,"radius",e,n)||this}return n(e,t),e.prototype.pointToData=function(t,e){return this.polar.pointToData(t,e)["radius"===this.dim?0:1]},e}(vx);HO.prototype.dataToRadius=vx.prototype.dataToCoord,HO.prototype.radiusToData=vx.prototype.coordToData;var WO=Lr(),YO=function(t){function e(e,n){return t.call(this,"angle",e,n||[0,360])||this}return n(e,t),e.prototype.pointToData=function(t,e){return this.polar.pointToData(t,e)["radius"===this.dim?0:1]},e.prototype.calculateCategoryInterval=function(){var t=this,e=t.getLabelModel(),n=t.scale,i=n.getExtent(),r=n.count();if(i[1]-i[0]<1)return 0;var o=i[0],a=t.dataToCoord(o+1)-t.dataToCoord(o),s=Math.abs(a),l=Fn(null==o?"":o+"",e.getFont(),"center","top"),u=Math.max(l.height,7)/s;isNaN(u)&&(u=1/0);var h=Math.max(0,Math.floor(u)),c=WO(t.model),p=c.lastAutoInterval,d=c.lastTickCount;return null!=p&&null!=d&&Math.abs(p-h)<=1&&Math.abs(d-r)<=1&&p>h?h=p:(c.lastTickCount=r,c.lastAutoInterval=h),h},e}(vx);YO.prototype.dataToAngle=vx.prototype.dataToCoord,YO.prototype.angleToData=vx.prototype.coordToData;var XO=function(){function t(t){this.dimensions=["radius","angle"],this.type="polar",this.cx=0,this.cy=0,this._radiusAxis=new HO,this._angleAxis=new YO,this.axisPointerEnabled=!0,this.name=t||"",this._radiusAxis.polar=this._angleAxis.polar=this}return t.prototype.containPoint=function(t){var e=this.pointToCoord(t);return this._radiusAxis.contain(e[0])&&this._angleAxis.contain(e[1])},t.prototype.containData=function(t){return this._radiusAxis.containData(t[0])&&this._angleAxis.containData(t[1])},t.prototype.getAxis=function(t){return this["_"+t+"Axis"]},t.prototype.getAxes=function(){return[this._radiusAxis,this._angleAxis]},t.prototype.getAxesByScale=function(t){var e=[],n=this._angleAxis,i=this._radiusAxis;return n.scale.type===t&&e.push(n),i.scale.type===t&&e.push(i),e},t.prototype.getAngleAxis=function(){return this._angleAxis},t.prototype.getRadiusAxis=function(){return this._radiusAxis},t.prototype.getOtherAxis=function(t){var e=this._angleAxis;return t===e?this._radiusAxis:e},t.prototype.getBaseAxis=function(){return this.getAxesByScale("ordinal")[0]||this.getAxesByScale("time")[0]||this.getAngleAxis()},t.prototype.getTooltipAxes=function(t){var e=null!=t&&"auto"!==t?this.getAxis(t):this.getBaseAxis();return{baseAxes:[e],otherAxes:[this.getOtherAxis(e)]}},t.prototype.dataToPoint=function(t,e){return this.coordToPoint([this._radiusAxis.dataToRadius(t[0],e),this._angleAxis.dataToAngle(t[1],e)])},t.prototype.pointToData=function(t,e){var n=this.pointToCoord(t);return[this._radiusAxis.radiusToData(n[0],e),this._angleAxis.angleToData(n[1],e)]},t.prototype.pointToCoord=function(t){var e=t[0]-this.cx,n=t[1]-this.cy,i=this.getAngleAxis(),r=i.getExtent(),o=Math.min(r[0],r[1]),a=Math.max(r[0],r[1]);i.inverse?o=a-360:a=o+360;var s=Math.sqrt(e*e+n*n);e/=s,n/=s;for(var l=Math.atan2(-n,e)/Math.PI*180,u=la;)l+=360*u;return[s,l]},t.prototype.coordToPoint=function(t){var e=t[0],n=t[1]/180*Math.PI;return[Math.cos(n)*e+this.cx,-Math.sin(n)*e+this.cy]},t.prototype.getArea=function(){var t=this.getAngleAxis(),e=this.getRadiusAxis().getExtent().slice();e[0]>e[1]&&e.reverse();var n=t.getExtent(),i=Math.PI/180;return{cx:this.cx,cy:this.cy,r0:e[0],r:e[1],startAngle:-n[0]*i,endAngle:-n[1]*i,clockwise:t.inverse,contain:function(t,e){var n=t-this.cx,i=e-this.cy,r=n*n+i*i,o=this.r,a=this.r0;return r<=o*o&&r>=a*a}}},t.prototype.convertToPixel=function(t,e,n){return UO(e)===this?this.dataToPoint(n):null},t.prototype.convertFromPixel=function(t,e,n){return UO(e)===this?this.pointToData(n):null},t}();function UO(t){var e=t.seriesModel,n=t.polarModel;return n&&n.coordinateSystem||e&&e.coordinateSystem}function ZO(t,e){var n=this,i=n.getAngleAxis(),r=n.getRadiusAxis();if(i.scale.setExtent(1/0,-1/0),r.scale.setExtent(1/0,-1/0),t.eachSeries((function(t){if(t.coordinateSystem===n){var e=t.getData();P(Z_(e,"radius"),(function(t){r.scale.unionExtentFromData(e,t)})),P(Z_(e,"angle"),(function(t){i.scale.unionExtentFromData(e,t)}))}})),F_(i.scale,i.model),F_(r.scale,r.model),"category"===i.type&&!i.onBand){var o=i.getExtent(),a=360/i.scale.count();i.inverse?o[1]+=a:o[1]-=a,i.setExtent(o[0],o[1])}}function jO(t,e){if(t.type=e.get("type"),t.scale=G_(e),t.onBand=e.get("boundaryGap")&&"category"===t.type,t.inverse=e.get("inverse"),function(t){return"angleAxis"===t.mainType}(e)){t.inverse=t.inverse!==e.get("clockwise");var n=e.get("startAngle");t.setExtent(n,n+(t.inverse?-360:360))}e.axis=t,t.model=e}var qO={dimensions:XO.prototype.dimensions,create:function(t,e){var n=[];return t.eachComponent("polar",(function(t,i){var r=new XO(i+"");r.update=ZO;var o=r.getRadiusAxis(),a=r.getAngleAxis(),s=t.findAxisModel("radiusAxis"),l=t.findAxisModel("angleAxis");jO(o,s),jO(a,l),function(t,e,n){var i=e.get("center"),r=n.getWidth(),o=n.getHeight();t.cx=Zi(i[0],r),t.cy=Zi(i[1],o);var a=t.getRadiusAxis(),s=Math.min(r,o)/2,l=e.get("radius");null==l?l=[0,"100%"]:F(l)||(l=[0,l]);var u=[Zi(l[0],s),Zi(l[1],s)];a.inverse?a.setExtent(u[1],u[0]):a.setExtent(u[0],u[1])}(r,t,e),n.push(r),t.coordinateSystem=r,r.model=t})),t.eachSeries((function(t){if("polar"===t.get("coordinateSystem")){var e=t.getReferringComponents("polar",Or).models[0];0,t.coordinateSystem=e.coordinateSystem}})),n}},KO=["axisLine","axisLabel","axisTick","minorTick","splitLine","minorSplitLine","splitArea"];function $O(t,e,n){e[1]>e[0]&&(e=e.slice().reverse());var i=t.coordToPoint([e[0],n]),r=t.coordToPoint([e[1],n]);return{x1:i[0],y1:i[1],x2:r[0],y2:r[1]}}function JO(t){return t.getRadiusAxis().inverse?0:1}function QO(t){var e=t[0],n=t[t.length-1];e&&n&&Math.abs(Math.abs(e.coord-n.coord)-360)<1e-4&&t.pop()}var tR=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n.axisPointerClass="PolarAxisPointer",n}return n(e,t),e.prototype.render=function(t,e){if(this.group.removeAll(),t.get("show")){var n=t.axis,i=n.polar,r=i.getRadiusAxis().getExtent(),o=n.getTicksCoords(),a=n.getMinorTicksCoords(),s=O(n.getViewLabels(),(function(t){t=w(t);var e=n.scale,i="ordinal"===e.type?e.getRawOrdinalNumber(t.tickValue):t.tickValue;return t.coord=n.dataToCoord(i),t}));QO(s),QO(o),P(KO,(function(e){!t.get([e,"show"])||n.scale.isBlank()&&"axisLine"!==e||eR[e](this.group,t,i,o,a,r,s)}),this)}},e.type="angleAxis",e}(SS),eR={axisLine:function(t,e,n,i,r,o){var a,s=e.getModel(["axisLine","lineStyle"]),l=JO(n),u=l?0:1;(a=0===o[u]?new Tl({shape:{cx:n.cx,cy:n.cy,r:o[l]},style:s.getLineStyle(),z2:1,silent:!0}):new Xl({shape:{cx:n.cx,cy:n.cy,r:o[l],r0:o[u]},style:s.getLineStyle(),z2:1,silent:!0})).style.fill=null,t.add(a)},axisTick:function(t,e,n,i,r,o){var a=e.getModel("axisTick"),s=(a.get("inside")?-1:1)*a.get("length"),l=o[JO(n)],u=O(i,(function(t){return new tu({shape:$O(n,[l,l+s],t.coord)})}));t.add(Du(u,{style:T(a.getModel("lineStyle").getLineStyle(),{stroke:e.get(["axisLine","lineStyle","color"])})}))},minorTick:function(t,e,n,i,r,o){if(r.length){for(var a=e.getModel("axisTick"),s=e.getModel("minorTick"),l=(a.get("inside")?-1:1)*s.get("length"),u=o[JO(n)],h=[],c=0;cf?"left":"right",v=Math.abs(d[1]-g)/p<.3?"middle":d[1]>g?"top":"bottom";if(s&&s[c]){var m=s[c];X(m)&&m.textStyle&&(a=new Sh(m.textStyle,l,l.ecModel))}var _=new ls({silent:hS.isLabelSilent(e),style:nh(a,{x:d[0],y:d[1],fill:a.getTextColor()||e.get(["axisLine","lineStyle","color"]),text:i.formattedLabel,align:y,verticalAlign:v})});if(t.add(_),h){var x=hS.makeAxisEventDataBase(e);x.targetType="axisLabel",x.value=i.rawLabel,ys(_).eventData=x}}),this)},splitLine:function(t,e,n,i,r,o){var a=e.getModel("splitLine").getModel("lineStyle"),s=a.get("color"),l=0;s=s instanceof Array?s:[s];for(var u=[],h=0;h=0?"p":"n",T=x;m&&(i[s][M]||(i[s][M]={p:x,n:x}),T=i[s][M][I]);var C=void 0,A=void 0,D=void 0,L=void 0;if("radius"===c.dim){var k=c.dataToCoord(S)-x,P=o.dataToCoord(M);Math.abs(k)=e.y&&t[1]<=e.y+e.height:n.contain(n.toLocalCoord(t[1]))&&t[0]>=e.y&&t[0]<=e.y+e.height},t.prototype.pointToData=function(t){var e=this.getAxis();return[e.coordToData(e.toLocalCoord(t["horizontal"===e.orient?0:1]))]},t.prototype.dataToPoint=function(t){var e=this.getAxis(),n=this.getRect(),i=[],r="horizontal"===e.orient?0:1;return t instanceof Array&&(t=t[0]),i[r]=e.toGlobalCoord(e.dataToCoord(+t)),i[1-r]=0===r?n.y+n.height/2:n.x+n.width/2,i},t.prototype.convertToPixel=function(t,e,n){return xR(e)===this?this.dataToPoint(n):null},t.prototype.convertFromPixel=function(t,e,n){return xR(e)===this?this.pointToData(n):null},t}();function xR(t){var e=t.seriesModel,n=t.singleAxisModel;return n&&n.coordinateSystem||e&&e.coordinateSystem}var bR={create:function(t,e){var n=[];return t.eachComponent("singleAxis",(function(i,r){var o=new _R(i,t,e);o.name="single_"+r,o.resize(i,e),i.coordinateSystem=o,n.push(o)})),t.eachSeries((function(t){if("singleAxis"===t.get("coordinateSystem")){var e=t.getReferringComponents("singleAxis",Or).models[0];t.coordinateSystem=e&&e.coordinateSystem}})),n},dimensions:_R.prototype.dimensions},wR=["x","y"],SR=["width","height"],MR=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return n(e,t),e.prototype.makeElOption=function(t,e,n,i,r){var o=n.axis,a=o.coordinateSystem,s=CR(a,1-TR(o)),l=a.dataToPoint(e)[0],u=i.get("type");if(u&&"none"!==u){var h=sO(i),c=IR[u](o,l,s);c.style=h,t.graphicKey=c.type,t.pointer=c}cO(e,t,pR(n),n,i,r)},e.prototype.getHandleTransform=function(t,e,n){var i=pR(e,{labelInside:!1});i.labelMargin=n.get(["handle","margin"]);var r=hO(e.axis,t,i);return{x:r[0],y:r[1],rotation:i.rotation+(i.labelDirection<0?Math.PI:0)}},e.prototype.updateHandleTransform=function(t,e,n,i){var r=n.axis,o=r.coordinateSystem,a=TR(r),s=CR(o,a),l=[t.x,t.y];l[a]+=e[a],l[a]=Math.min(s[1],l[a]),l[a]=Math.max(s[0],l[a]);var u=CR(o,1-a),h=(u[1]+u[0])/2,c=[h,h];return c[a]=l[a],{x:l[0],y:l[1],rotation:t.rotation,cursorPoint:c,tooltipOption:{verticalAlign:"middle"}}},e}(eO),IR={line:function(t,e,n){return{type:"Line",subPixelOptimize:!0,shape:pO([e,n[0]],[e,n[1]],TR(t))}},shadow:function(t,e,n){var i=t.getBandWidth(),r=n[1]-n[0];return{type:"Rect",shape:dO([e-i/2,n[0]],[i,r],TR(t))}}};function TR(t){return t.isHorizontal()?0:1}function CR(t,e){var n=t.getRect();return[n[wR[e]],n[wR[e]]+n[SR[e]]]}var AR=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n}return n(e,t),e.type="single",e}(pf);var DR=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n}return n(e,t),e.prototype.init=function(e,n,i){var r=Pc(e);t.prototype.init.apply(this,arguments),LR(e,r)},e.prototype.mergeOption=function(e){t.prototype.mergeOption.apply(this,arguments),LR(this.option,e)},e.prototype.getCellSize=function(){return this.option.cellSize},e.type="calendar",e.defaultOption={zlevel:0,z:2,left:80,top:60,cellSize:20,orient:"horizontal",splitLine:{show:!0,lineStyle:{color:"#000",width:1,type:"solid"}},itemStyle:{color:"#fff",borderWidth:1,borderColor:"#ccc"},dayLabel:{show:!0,firstDay:0,position:"start",margin:"50%",nameMap:"en",color:"#000"},monthLabel:{show:!0,position:"start",margin:5,align:"center",nameMap:"en",formatter:null,color:"#000"},yearLabel:{show:!0,position:null,margin:30,formatter:null,color:"#ccc",fontFamily:"sans-serif",fontWeight:"bolder",fontSize:20}},e}(Nc);function LR(t,e){var n,i=t.cellSize;1===(n=F(i)?i:t.cellSize=[i,i]).length&&(n[1]=n[0]);var r=O([0,1],(function(t){return function(t,e){return null!=t[Ic[e][0]]||null!=t[Ic[e][1]]&&null!=t[Ic[e][2]]}(e,t)&&(n[t]="auto"),null!=n[t]&&"auto"!==n[t]}));kc(t,e,{type:"box",ignoreSize:r})}var kR={EN:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],CN:["一月","二月","三月","四月","五月","六月","七月","八月","九月","十月","十一月","十二月"]},PR={EN:["S","M","T","W","T","F","S"],CN:["日","一","二","三","四","五","六"]},OR=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n}return n(e,t),e.prototype.render=function(t,e,n){var i=this.group;i.removeAll();var r=t.coordinateSystem,o=r.getRangeInfo(),a=r.getOrient();this._renderDayRect(t,o,i),this._renderLines(t,o,a,i),this._renderYearText(t,o,a,i),this._renderMonthText(t,a,i),this._renderWeekText(t,o,a,i)},e.prototype._renderDayRect=function(t,e,n){for(var i=t.coordinateSystem,r=t.getModel("itemStyle").getItemStyle(),o=i.getCellWidth(),a=i.getCellHeight(),s=e.start.time;s<=e.end.time;s=i.getNextNDay(s,1).time){var l=i.dataToRect([s],!1).tl,u=new os({shape:{x:l[0],y:l[1],width:o,height:a},cursor:"default",style:r});n.add(u)}},e.prototype._renderLines=function(t,e,n,i){var r=this,o=t.coordinateSystem,a=t.getModel(["splitLine","lineStyle"]).getLineStyle(),s=t.get(["splitLine","show"]),l=a.lineWidth;this._tlpoints=[],this._blpoints=[],this._firstDayOfMonth=[],this._firstDayPoints=[];for(var u=e.start,h=0;u.time<=e.end.time;h++){p(u.formatedDate),0===h&&(u=o.getDateInfo(e.start.y+"-"+e.start.m));var c=u.date;c.setMonth(c.getMonth()+1),u=o.getDateInfo(c)}function p(e){r._firstDayOfMonth.push(o.getDateInfo(e)),r._firstDayPoints.push(o.dataToRect([e],!1).tl);var l=r._getLinePointsOfOneWeek(t,e,n);r._tlpoints.push(l[0]),r._blpoints.push(l[l.length-1]),s&&r._drawSplitline(l,a,i)}p(o.getNextNDay(e.end.time,1).formatedDate),s&&this._drawSplitline(r._getEdgesPoints(r._tlpoints,l,n),a,i),s&&this._drawSplitline(r._getEdgesPoints(r._blpoints,l,n),a,i)},e.prototype._getEdgesPoints=function(t,e,n){var i=[t[0].slice(),t[t.length-1].slice()],r="horizontal"===n?0:1;return i[0][r]=i[0][r]-e/2,i[1][r]=i[1][r]+e/2,i},e.prototype._drawSplitline=function(t,e,n){var i=new $l({z2:20,shape:{points:t},style:e});n.add(i)},e.prototype._getLinePointsOfOneWeek=function(t,e,n){for(var i=t.coordinateSystem,r=i.getDateInfo(e),o=[],a=0;a<7;a++){var s=i.getNextNDay(r.time,a),l=i.dataToRect([s.time],!1);o[2*s.day]=l.tl,o[2*s.day+1]=l["horizontal"===n?"bl":"tr"]}return o},e.prototype._formatterLabel=function(t,e){return"string"==typeof t&&t?(n=t,P(e,(function(t,e){n=n.replace("{"+e+"}",i?gc(t):t)})),n):"function"==typeof t?t(e):e.nameMap;var n,i},e.prototype._yearTextPositionControl=function(t,e,n,i,r){var o=e[0],a=e[1],s=["center","bottom"];"bottom"===i?(a+=r,s=["center","top"]):"left"===i?o-=r:"right"===i?(o+=r,s=["center","top"]):a-=r;var l=0;return"left"!==i&&"right"!==i||(l=Math.PI/2),{rotation:l,x:o,y:a,style:{align:s[0],verticalAlign:s[1]}}},e.prototype._renderYearText=function(t,e,n,i){var r=t.getModel("yearLabel");if(r.get("show")){var o=r.get("margin"),a=r.get("position");a||(a="horizontal"!==n?"top":"left");var s=[this._tlpoints[this._tlpoints.length-1],this._blpoints[0]],l=(s[0][0]+s[1][0])/2,u=(s[0][1]+s[1][1])/2,h="horizontal"===n?0:1,c={top:[l,s[h][1]],bottom:[l,s[1-h][1]],left:[s[1-h][0],u],right:[s[h][0],u]},p=e.start.y;+e.end.y>+e.start.y&&(p=p+"-"+e.end.y);var d=r.get("formatter"),f={start:e.start.y,end:e.end.y,nameMap:p},g=this._formatterLabel(d,f),y=new ls({z2:30,style:nh(r,{text:g})});y.attr(this._yearTextPositionControl(y,c[a],n,a,o)),i.add(y)}},e.prototype._monthTextPositionControl=function(t,e,n,i,r){var o="left",a="top",s=t[0],l=t[1];return"horizontal"===n?(l+=r,e&&(o="center"),"start"===i&&(a="bottom")):(s+=r,e&&(a="middle"),"start"===i&&(o="right")),{x:s,y:l,align:o,verticalAlign:a}},e.prototype._renderMonthText=function(t,e,n){var i=t.getModel("monthLabel");if(i.get("show")){var r=i.get("nameMap"),o=i.get("margin"),a=i.get("position"),s=i.get("align"),l=[this._tlpoints,this._blpoints];H(r)&&(r=kR[r.toUpperCase()]||[]);var u="start"===a?0:1,h="horizontal"===e?0:1;o="start"===a?-o:o;for(var c="center"===s,p=0;p=i.start.time&&n.timea.end.time&&t.reverse(),t},t.prototype._getRangeInfo=function(t){var e,n=[this.getDateInfo(t[0]),this.getDateInfo(t[1])];n[0].time>n[1].time&&(e=!0,n.reverse());var i=Math.floor(n[1].time/RR)-Math.floor(n[0].time/RR)+1,r=new Date(n[0].time),o=r.getDate(),a=n[1].date.getDate();r.setDate(o+i-1);var s=r.getDate();if(s!==a)for(var l=r.getTime()-n[1].time>0?1:-1;(s=r.getDate())!==a&&(r.getTime()-n[1].time)*l>0;)i-=l,r.setDate(s-l);var u=Math.floor((i+n[0].day+6)/7),h=e?1-u:u-1;return e&&n.reverse(),{range:[n[0].formatedDate,n[1].formatedDate],start:n[0],end:n[1],allDay:i,weeks:u,nthWeek:h,fweek:n[0].day,lweek:n[1].day}},t.prototype._getDateByWeeksAndDay=function(t,e,n){var i=this._getRangeInfo(n);if(t>i.weeks||0===t&&ei.lweek)return null;var r=7*(t-1)-i.fweek+e,o=new Date(i.start.time);return o.setDate(+i.start.d+r),this.getDateInfo(o)},t.create=function(e,n){var i=[];return e.eachComponent("calendar",(function(r){var o=new t(r,e,n);i.push(o),r.coordinateSystem=o})),e.eachSeries((function(t){"calendar"===t.get("coordinateSystem")&&(t.coordinateSystem=i[t.get("calendarIndex")||0])})),i},t.dimensions=["time","value"],t}();function ER(t){var e=t.calendarModel,n=t.seriesModel;return e?e.coordinateSystem:n?n.coordinateSystem:null}var zR=Lr(),BR={path:null,compoundPath:null,group:zi,image:Ja,text:ls},VR=function(t){var e=t.graphic;F(e)?e[0]&&e[0].elements?t.graphic=[t.graphic[0]]:t.graphic=[{elements:e}]:e&&!e.elements&&(t.graphic=[{elements:[e]}])},FR=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n}return n(e,t),e.prototype.mergeOption=function(e,n){var i=this.option.elements;this.option.elements=null,t.prototype.mergeOption.call(this,e,n),this.option.elements=i},e.prototype.optionUpdated=function(t,e){var n=this.option,i=(e?n:t).elements,r=n.elements=e?[]:n.elements,o=[];this._flatten(i,o,null);var a=Sr(r,o,"normalMerge"),s=this._elOptionsToUpdate=[];P(a,(function(t,e){var n=t.newOption;n&&(s.push(n),function(t,e){var n=t.existing;if(e.id=t.keyInfo.id,!e.type&&n&&(e.type=n.type),null==e.parentId){var i=e.parentOption;i?e.parentId=i.id:n&&(e.parentId=n.parentId)}e.parentOption=null}(t,n),function(t,e,n){var i=I({},n),r=t[e],o=n.$action||"merge";if("merge"===o){if(r)S(r,i,!0),kc(r,i,{ignoreSize:!0}),Oc(n,r);else t[e]=i}else"replace"===o?t[e]=i:"remove"===o&&r&&(t[e]=null)}(r,e,n),function(t,e){if(!t)return;if(t.hv=e.hv=[YR(e,["left","right"]),YR(e,["top","bottom"])],"group"===t.type){var n=t,i=e;null==n.width&&(n.width=i.width=0),null==n.height&&(n.height=i.height=0)}}(r[e],n))}),this);for(var l=r.length-1;l>=0;l--)null==r[l]?r.splice(l,1):delete r[l].$action},e.prototype._flatten=function(t,e,n){P(t,(function(t){if(t){n&&(t.parentOption=n),e.push(t);var i=t.children;"group"===t.type&&i&&this._flatten(i,e,t),delete t.children}}),this)},e.prototype.useElOptionsToUpdate=function(){var t=this._elOptionsToUpdate;return this._elOptionsToUpdate=null,t},e.type="graphic",e.defaultOption={elements:[]},e}(Nc),GR=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n}return n(e,t),e.prototype.init=function(){this._elMap=ht()},e.prototype.render=function(t,e,n){t!==this._lastGraphicModel&&this._clear(),this._lastGraphicModel=t,this._updateElements(t),this._relocate(t,n)},e.prototype._updateElements=function(t){var e=t.useElOptionsToUpdate();if(e){var n=this._elMap,i=this.group;P(e,(function(e){var r=Tr(e.id,null),o=null!=r?n.get(r):null,a=Tr(e.parentId,null),s=null!=a?n.get(a):i,l=e.type,u=e.style;"text"===l&&u&&e.hv&&e.hv[1]&&(u.textVerticalAlign=u.textBaseline=u.verticalAlign=u.align=null);var h=e.textContent,c=e.textConfig;if(u&&Sk(u,l,!!c,!!h)){var p=Mk(u,l,!0);!c&&p.textConfig&&(c=e.textConfig=p.textConfig),!h&&p.textContent&&(h=p.textContent)}var d=function(t){return t=I({},t),P(["id","parentId","$action","hv","bounding","textContent"].concat(Mc),(function(e){delete t[e]})),t}(e);var f=e.$action||"merge";"merge"===f?o?o.attr(d):HR(r,s,d,n):"replace"===f?(WR(o,n),HR(r,s,d,n)):"remove"===f&&WR(o,n);var g=n.get(r);if(g&&h)if("merge"===f){var y=g.getTextContent();y?y.attr(h):g.setTextContent(new ls(h))}else"replace"===f&&g.setTextContent(new ls(h));if(g){var v=zR(g);v.__ecGraphicWidthOption=e.width,v.__ecGraphicHeightOption=e.height,function(t,e,n){var i=ys(t).eventData;t.silent||t.ignore||i||(i=ys(t).eventData={componentType:"graphic",componentIndex:e.componentIndex,name:t.name});i&&(i.info=n.info)}(g,t,e)}}))}},e.prototype._relocate=function(t,e){for(var n=t.option.elements,i=this.group,r=this._elMap,o=e.getWidth(),a=e.getHeight(),s=0;s=0;s--){var c,p,d;if(d=null!=(p=Tr((c=n[s]).id,null))?r.get(p):null){var f=d.parent;h=zR(f);Dc(d,c,f===i?{width:o,height:a}:{width:h.__ecGraphicWidth,height:h.__ecGraphicHeight},null,{hv:c.hv,boundingMode:c.bounding})}}},e.prototype._clear=function(){var t=this._elMap;t.each((function(e){WR(e,t)})),this._elMap=ht()},e.prototype.dispose=function(){this._clear()},e.type="graphic",e}(pf);function HR(t,e,n,i){var r=n.type;var o=dt(BR,r)?BR[r]:Iu(r);var a=new o(n);e.add(a),i.set(t,a),zR(a).__ecGraphicId=t}function WR(t,e){var n=t&&t.parent;n&&("group"===t.type&&t.traverse((function(t){WR(t,e)})),e.removeKey(zR(t).__ecGraphicId),n.remove(t))}function YR(t,e){var n;return P(e,(function(e){null!=t[e]&&"auto"!==t[e]&&(n=!0)})),n}var XR=["x","y","radius","angle","single"],UR=["cartesian2d","polar","singleAxis"];function ZR(t){return t+"Axis"}function jR(t,e){var n,i=ht(),r=[],o=ht();t.eachComponent({mainType:"dataZoom",query:e},(function(t){o.get(t.uid)||s(t)}));do{n=!1,t.eachComponent("dataZoom",a)}while(n);function a(t){!o.get(t.uid)&&function(t){var e=!1;return t.eachTargetAxis((function(t,n){var r=i.get(t);r&&r[n]&&(e=!0)})),e}(t)&&(s(t),n=!0)}function s(t){o.set(t.uid,!0),r.push(t),t.eachTargetAxis((function(t,e){(i.get(t)||i.set(t,[]))[e]=!0}))}return r}function qR(t){var e=t.ecModel,n={infoList:[],infoMap:ht()};return t.eachTargetAxis((function(t,i){var r=e.getComponent(ZR(t),i);if(r){var o=r.getCoordSysModel();if(o){var a=o.uid,s=n.infoMap.get(a);s||(s={model:o,axisModels:[]},n.infoList.push(s),n.infoMap.set(a,s)),s.axisModels.push(r)}}})),n}var KR=function(){function t(){this.indexList=[],this.indexMap=[]}return t.prototype.add=function(t){this.indexMap[t]||(this.indexList.push(t),this.indexMap[t]=!0)},t}(),$R=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n._autoThrottle=!0,n._noTarget=!0,n._rangePropMode=["percent","percent"],n}return n(e,t),e.prototype.init=function(t,e,n){var i=JR(t);this.settledOption=i,this.mergeDefaultAndTheme(t,n),this._doInit(i)},e.prototype.mergeOption=function(t){var e=JR(t);S(this.option,t,!0),S(this.settledOption,e,!0),this._doInit(e)},e.prototype._doInit=function(t){var e=this.option;this._setDefaultThrottle(t),this._updateRangeUse(t);var n=this.settledOption;P([["start","startValue"],["end","endValue"]],(function(t,i){"value"===this._rangePropMode[i]&&(e[t[0]]=n[t[0]]=null)}),this),this._resetTarget()},e.prototype._resetTarget=function(){var t=this.get("orient",!0),e=this._targetAxisInfoMap=ht();this._fillSpecifiedTargetAxis(e)?this._orient=t||this._makeAutoOrientByTargetAxis():(this._orient=t||"horizontal",this._fillAutoTargetAxisByOrient(e,this._orient)),this._noTarget=!0,e.each((function(t){t.indexList.length&&(this._noTarget=!1)}),this)},e.prototype._fillSpecifiedTargetAxis=function(t){var e=!1;return P(XR,(function(n){var i=this.getReferringComponents(ZR(n),Rr);if(i.specified){e=!0;var r=new KR;P(i.models,(function(t){r.add(t.componentIndex)})),t.set(n,r)}}),this),e},e.prototype._fillAutoTargetAxisByOrient=function(t,e){var n=this.ecModel,i=!0;if(i){var r="vertical"===e?"y":"x";o(n.findComponents({mainType:r+"Axis"}),r)}i&&o(n.findComponents({mainType:"singleAxis",filter:function(t){return t.get("orient",!0)===e}}),"single");function o(e,n){var r=e[0];if(r){var o=new KR;if(o.add(r.componentIndex),t.set(n,o),i=!1,"x"===n||"y"===n){var a=r.getReferringComponents("grid",Or).models[0];a&&P(e,(function(t){r.componentIndex!==t.componentIndex&&a===t.getReferringComponents("grid",Or).models[0]&&o.add(t.componentIndex)}))}}}i&&P(XR,(function(e){if(i){var r=n.findComponents({mainType:ZR(e),filter:function(t){return"category"===t.get("type",!0)}});if(r[0]){var o=new KR;o.add(r[0].componentIndex),t.set(e,o),i=!1}}}),this)},e.prototype._makeAutoOrientByTargetAxis=function(){var t;return this.eachTargetAxis((function(e){!t&&(t=e)}),this),"y"===t?"vertical":"horizontal"},e.prototype._setDefaultThrottle=function(t){if(t.hasOwnProperty("throttle")&&(this._autoThrottle=!1),this._autoThrottle){var e=this.ecModel.option;this.option.throttle=e.animation&&e.animationDurationUpdate>0?100:20}},e.prototype._updateRangeUse=function(t){var e=this._rangePropMode,n=this.get("rangeMode");P([["start","startValue"],["end","endValue"]],(function(i,r){var o=null!=t[i[0]],a=null!=t[i[1]];o&&!a?e[r]="percent":!o&&a?e[r]="value":n?e[r]=n[r]:o&&(e[r]="percent")}))},e.prototype.noTarget=function(){return this._noTarget},e.prototype.getFirstTargetAxisModel=function(){var t;return this.eachTargetAxis((function(e,n){null==t&&(t=this.ecModel.getComponent(ZR(e),n))}),this),t},e.prototype.eachTargetAxis=function(t,e){this._targetAxisInfoMap.each((function(n,i){P(n.indexList,(function(n){t.call(e,i,n)}))}))},e.prototype.getAxisProxy=function(t,e){var n=this.getAxisModel(t,e);if(n)return n.__dzAxisProxy},e.prototype.getAxisModel=function(t,e){var n=this._targetAxisInfoMap.get(t);if(n&&n.indexMap[e])return this.ecModel.getComponent(ZR(t),e)},e.prototype.setRawRange=function(t){var e=this.option,n=this.settledOption;P([["start","startValue"],["end","endValue"]],(function(i){null==t[i[0]]&&null==t[i[1]]||(e[i[0]]=n[i[0]]=t[i[0]],e[i[1]]=n[i[1]]=t[i[1]])}),this),this._updateRangeUse(t)},e.prototype.setCalculatedRange=function(t){var e=this.option;P(["start","startValue","end","endValue"],(function(n){e[n]=t[n]}))},e.prototype.getPercentRange=function(){var t=this.findRepresentativeAxisProxy();if(t)return t.getDataPercentWindow()},e.prototype.getValueRange=function(t,e){if(null!=t||null!=e)return this.getAxisProxy(t,e).getDataValueWindow();var n=this.findRepresentativeAxisProxy();return n?n.getDataValueWindow():void 0},e.prototype.findRepresentativeAxisProxy=function(t){if(t)return t.__dzAxisProxy;for(var e,n=this._targetAxisInfoMap.keys(),i=0;i=0}(e)){var n=ZR(this._dimName),i=e.getReferringComponents(n,Or).models[0];i&&this._axisIndex===i.componentIndex&&t.push(e)}}),this),t},t.prototype.getAxisModel=function(){return this.ecModel.getComponent(this._dimName+"Axis",this._axisIndex)},t.prototype.getMinMaxSpan=function(){return w(this._minMaxSpan)},t.prototype.calculateDataWindow=function(t){var e,n=this._dataExtent,i=this.getAxisModel().axis.scale,r=this._dataZoomModel.getRangePropMode(),o=[0,100],a=[],s=[];nN(["start","end"],(function(l,u){var h=t[l],c=t[l+"Value"];"percent"===r[u]?(null==h&&(h=o[u]),c=i.parse(Ui(h,o,n))):(e=!0,h=Ui(c=null==c?n[u]:i.parse(c),n,o)),s[u]=c,a[u]=h})),iN(s),iN(a);var l=this._minMaxSpan;function u(t,e,n,r,o){var a=o?"Span":"ValueSpan";sA(0,t,n,"all",l["min"+a],l["max"+a]);for(var s=0;s<2;s++)e[s]=Ui(t[s],n,r,!0),o&&(e[s]=i.parse(e[s]))}return e?u(s,a,n,o,!1):u(a,s,o,n,!0),{valueWindow:s,percentWindow:a}},t.prototype.reset=function(t){if(t===this._dataZoomModel){var e=this.getTargetSeriesModels();this._dataExtent=function(t,e,n){var i=[1/0,-1/0];nN(n,(function(t){!function(t,e,n){e&&P(Z_(e,n),(function(n){var i=e.getApproximateExtent(n);i[0]t[1]&&(t[1]=i[1])}))}(i,t.getData(),e)}));var r=t.getAxisModel(),o=z_(r.axis.scale,r,i).calculate();return[o.min,o.max]}(this,this._dimName,e),this._updateMinMaxSpan();var n=this.calculateDataWindow(t.settledOption);this._valueWindow=n.valueWindow,this._percentWindow=n.percentWindow,this._setAxisModel()}},t.prototype.filterData=function(t,e){if(t===this._dataZoomModel){var n=this._dimName,i=this.getTargetSeriesModels(),r=t.get("filterMode"),o=this._valueWindow;"none"!==r&&nN(i,(function(t){var e=t.getData(),i=e.mapDimensionsAll(n);i.length&&("weakFilter"===r?e.filterSelf((function(t){for(var n,r,a,s=0;so[1];if(u&&!h&&!c)return!0;u&&(a=!0),h&&(n=!0),c&&(r=!0)}return a&&n&&r})):nN(i,(function(n){if("empty"===r)t.setData(e=e.map(n,(function(t){return function(t){return t>=o[0]&&t<=o[1]}(t)?t:NaN})));else{var i={};i[n]=o,e.selectRange(i)}})),nN(i,(function(t){e.setApproximateExtent(o,t)})))}))}},t.prototype._updateMinMaxSpan=function(){var t=this._minMaxSpan={},e=this._dataZoomModel,n=this._dataExtent;nN(["min","max"],(function(i){var r=e.get(i+"Span"),o=e.get(i+"ValueSpan");null!=o&&(o=this.getAxisModel().axis.scale.parse(o)),null!=o?r=Ui(n[0]+o,n,[0,100],!0):null!=r&&(o=Ui(r,[0,100],n,!0)-n[0]),t[i+"Span"]=r,t[i+"ValueSpan"]=o}),this)},t.prototype._setAxisModel=function(){var t=this.getAxisModel(),e=this._percentWindow,n=this._valueWindow;if(e){var i=Ji(n,[0,500]);i=Math.min(i,20);var r=t.axis.scale.rawExtentInfo;0!==e[0]&&r.setDeterminedMinMax("min",+n[0].toFixed(i)),100!==e[1]&&r.setDeterminedMinMax("max",+n[1].toFixed(i)),r.freeze()}},t}();var oN={getTargetSeries:function(t){function e(e){t.eachComponent("dataZoom",(function(n){n.eachTargetAxis((function(i,r){var o=t.getComponent(ZR(i),r);e(i,r,o,n)}))}))}e((function(t,e,n,i){n.__dzAxisProxy=null}));var n=[];e((function(e,i,r,o){r.__dzAxisProxy||(r.__dzAxisProxy=new rN(e,i,o,t),n.push(r.__dzAxisProxy))}));var i=ht();return P(n,(function(t){P(t.getTargetSeriesModels(),(function(t){i.set(t.uid,t)}))})),i},overallReset:function(t,e){t.eachComponent("dataZoom",(function(t){t.eachTargetAxis((function(e,n){t.getAxisProxy(e,n).reset(t)})),t.eachTargetAxis((function(n,i){t.getAxisProxy(n,i).filterData(t,e)}))})),t.eachComponent("dataZoom",(function(t){var e=t.findRepresentativeAxisProxy();if(e){var n=e.getDataPercentWindow(),i=e.getDataValueWindow();t.setCalculatedRange({start:n[0],end:n[1],startValue:i[0],endValue:i[1]})}}))}};var aN=!1;function sN(t){aN||(aN=!0,t.registerProcessor(t.PRIORITY.PROCESSOR.FILTER,oN),function(t){t.registerAction("dataZoom",(function(t,e){P(jR(e,t),(function(e){e.setRawRange({start:t.start,end:t.end,startValue:t.startValue,endValue:t.endValue})}))}))}(t),t.registerSubTypeDefaulter("dataZoom",(function(){return"slider"})))}function lN(t){t.registerComponentModel(QR),t.registerComponentView(eN),sN(t)}var uN=function(){},hN={};function cN(t,e){hN[t]=e}function pN(t){return hN[t]}var dN=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n}return n(e,t),e.prototype.optionUpdated=function(){t.prototype.optionUpdated.apply(this,arguments);var e=this.ecModel;P(this.option.feature,(function(t,n){var i=pN(n);i&&(i.getDefaultOption&&(i.defaultOption=i.getDefaultOption(e)),S(t,i.defaultOption))}))},e.type="toolbox",e.layoutMode={type:"box",ignoreSize:!0},e.defaultOption={show:!0,z:6,zlevel:0,orient:"horizontal",left:"right",top:"top",backgroundColor:"transparent",borderColor:"#ccc",borderRadius:0,borderWidth:0,padding:5,itemSize:15,itemGap:8,showTitle:!0,iconStyle:{borderColor:"#666",color:"none"},emphasis:{iconStyle:{borderColor:"#3E98C5"}},tooltip:{show:!1}},e}(Nc);function fN(t,e){var n=pc(e.get("padding")),i=e.getItemStyle(["color","opacity"]);return i.fill=e.get("backgroundColor"),t=new os({shape:{x:t.x-n[3],y:t.y-n[0],width:t.width+n[1]+n[3],height:t.height+n[0]+n[2],r:e.get("borderRadius")},style:i,silent:!0,z2:-1})}var gN=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return n(e,t),e.prototype.render=function(t,e,n,i){var r=this.group;if(r.removeAll(),t.get("show")){var o=+t.get("itemSize"),a=t.get("feature")||{},s=this._features||(this._features={}),l=[];P(a,(function(t,e){l.push(e)})),new rm(this._featureNames||[],l).add(u).update(u).remove(V(u,null)).execute(),this._featureNames=l,function(t,e,n){var i=e.getBoxLayoutParams(),r=e.get("padding"),o={width:n.getWidth(),height:n.getHeight()},a=Ac(i,o,r);Cc(e.get("orient"),t,e.get("itemGap"),a.width,a.height),Dc(t,i,o,r)}(r,t,n),r.add(fN(r.getBoundingRect(),t)),r.eachChild((function(t){var e=t.__title,i=t.ensureState("emphasis"),a=i.textConfig||(i.textConfig={}),s=t.getTextContent(),l=s&&s.states.emphasis;if(l&&!G(l)&&e){var u=l.style||(l.style={}),h=Fn(e,ls.makeFont(u)),c=t.x+r.x,p=!1;t.y+r.y+o+h.height>n.getHeight()&&(a.position="top",p=!0);var d=p?-5-h.height:o+8;c+h.width/2>n.getWidth()?(a.position=["100%",d],u.align="right"):c-h.width/2<0&&(a.position=[0,d],u.align="left")}}))}function u(u,h){var c,p=l[u],d=l[h],f=a[p],g=new Sh(f,t,t.ecModel);if(i&&null!=i.newTitle&&i.featureName===p&&(f.title=i.newTitle),p&&!d){if(function(t){return 0===t.indexOf("my")}(p))c={onclick:g.option.onclick,featureName:p};else{var y=pN(p);if(!y)return;c=new y}s[p]=c}else if(!(c=s[d]))return;if(c.uid=Ih("toolbox-feature"),c.model=g,c.ecModel=e,c.api=n,c instanceof uN){if(!p&&d)return void(c.dispose&&c.dispose(e,n));if(!g.get("show")||c.unusable)return void(c.remove&&c.remove(e,n))}!function(i,a,s){var l,u,h=i.getModel("iconStyle"),c=i.getModel(["emphasis","iconStyle"]),p=a instanceof uN&&a.getIcons?a.getIcons():i.get("icon"),d=i.get("title")||{};"string"==typeof p?(l={})[s]=p:l=p;"string"==typeof d?(u={})[s]=d:u=d;var f=i.iconPaths={};P(l,(function(s,l){var p=Uu(s,{},{x:-o/2,y:-o/2,width:o,height:o});p.setStyle(h.getItemStyle()),p.ensureState("emphasis").style=c.getItemStyle();var d=new ls({style:{text:u[l],align:c.get("textAlign"),borderRadius:c.get("textBorderRadius"),padding:c.get("textPadding"),fill:null},ignore:!0});p.setTextContent(d);var g=t.getModel("tooltip");g&&g.get("show")&&(p.tooltip=I({content:u[l],formatter:g.get("formatter",!0)||function(){return u[l]},formatterParams:{componentType:"toolbox",name:l,title:u[l],$vars:["name","title"]},position:g.get("position",!0)||"bottom"},g.option)),p.__title=u[l],p.on("mouseover",(function(){var e=c.getItemStyle(),n="vertical"===t.get("orient")?null==t.get("right")?"right":"left":null==t.get("bottom")?"bottom":"top";d.setStyle({fill:c.get("textFill")||e.fill||e.stroke||"#000",backgroundColor:c.get("textBackgroundColor")}),p.setTextConfig({position:c.get("textPosition")||n}),d.ignore=!t.get("showTitle"),Hs(this)})).on("mouseout",(function(){"emphasis"!==i.get(["iconStatus",l])&&Ws(this),d.hide()})),("emphasis"===i.get(["iconStatus",l])?Hs:Ws)(p),r.add(p),p.on("click",B(a.onclick,a,e,n,l)),f[l]=p}))}(g,c,p),g.setIconStatus=function(t,e){var n=this.option,i=this.iconPaths;n.iconStatus=n.iconStatus||{},n.iconStatus[t]=e,i[t]&&("emphasis"===e?Hs:Ws)(i[t])},c instanceof uN&&c.render&&c.render(g,e,n,i)}},e.prototype.updateView=function(t,e,n,i){P(this._features,(function(t){t instanceof uN&&t.updateView&&t.updateView(t.model,e,n,i)}))},e.prototype.remove=function(t,e){P(this._features,(function(n){n instanceof uN&&n.remove&&n.remove(t,e)})),this.group.removeAll()},e.prototype.dispose=function(t,e){P(this._features,(function(n){n instanceof uN&&n.dispose&&n.dispose(t,e)}))},e.type="toolbox",e}(pf);var yN=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return n(e,t),e.prototype.onclick=function(t,e){var n=this.model,i=n.get("name")||t.get("title.0.text")||"echarts",r="svg"===e.getZr().painter.getType(),o=r?"svg":n.get("type",!0)||"png",s=e.getConnectedDataURL({type:o,backgroundColor:n.get("backgroundColor",!0)||t.get("backgroundColor")||"#fff",connectedBackgroundColor:n.get("connectedBackgroundColor"),excludeComponents:n.get("excludeComponents"),pixelRatio:n.get("pixelRatio")});if("function"!=typeof MouseEvent||!a.browser.newEdge&&(a.browser.ie||a.browser.edge))if(window.navigator.msSaveOrOpenBlob||r){var l=s.split(","),u=l[0].indexOf("base64")>-1,h=r?decodeURIComponent(l[1]):l[1];u&&(h=atob(h));var c=i+"."+o;if(window.navigator.msSaveOrOpenBlob){for(var p=h.length,d=new Uint8Array(p);p--;)d[p]=h.charCodeAt(p);var f=new Blob([d]);window.navigator.msSaveOrOpenBlob(f,c)}else{var g=document.createElement("iframe");document.body.appendChild(g);var y=g.contentWindow,v=y.document;v.open("image/svg+xml","replace"),v.write(h),v.close(),y.focus(),v.execCommand("SaveAs",!0,c),document.body.removeChild(g)}}else{var m=n.get("lang"),_='',x=window.open();x.document.write(_),x.document.title=i}else{var b=document.createElement("a");b.download=i+"."+o,b.target="_blank",b.href=s;var w=new MouseEvent("click",{view:document.defaultView,bubbles:!0,cancelable:!1});b.dispatchEvent(w)}},e.getDefaultOption=function(t){return{show:!0,icon:"M4.7,22.9L29.3,45.5L54.7,23.4M4.6,43.6L4.6,58L53.8,58L53.8,43.6M29.2,45.1L29.2,0",title:t.getLocale(["toolbox","saveAsImage","title"]),type:"png",connectedBackgroundColor:"#fff",name:"",excludeComponents:["toolbox"],lang:t.getLocale(["toolbox","saveAsImage","lang"])}},e}(uN);yN.prototype.unusable=!a.canvasSupported;var vN="__ec_magicType_stack__",mN=[["line","bar"],["stack"]],_N=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return n(e,t),e.prototype.getIcons=function(){var t=this.model,e=t.get("icon"),n={};return P(t.get("type"),(function(t){e[t]&&(n[t]=e[t])})),n},e.getDefaultOption=function(t){return{show:!0,type:[],icon:{line:"M4.1,28.9h7.1l9.3-22l7.4,38l9.7-19.7l3,12.8h14.9M4.1,58h51.4",bar:"M6.7,22.9h10V48h-10V22.9zM24.9,13h10v35h-10V13zM43.2,2h10v46h-10V2zM3.1,58h53.7",stack:"M8.2,38.4l-8.4,4.1l30.6,15.3L60,42.5l-8.1-4.1l-21.5,11L8.2,38.4z M51.9,30l-8.1,4.2l-13.4,6.9l-13.9-6.9L8.2,30l-8.4,4.2l8.4,4.2l22.2,11l21.5-11l8.1-4.2L51.9,30z M51.9,21.7l-8.1,4.2L35.7,30l-5.3,2.8L24.9,30l-8.4-4.1l-8.3-4.2l-8.4,4.2L8.2,30l8.3,4.2l13.9,6.9l13.4-6.9l8.1-4.2l8.1-4.1L51.9,21.7zM30.4,2.2L-0.2,17.5l8.4,4.1l8.3,4.2l8.4,4.2l5.5,2.7l5.3-2.7l8.1-4.2l8.1-4.2l8.1-4.1L30.4,2.2z"},title:t.getLocale(["toolbox","magicType","title"]),option:{},seriesIndex:{}}},e.prototype.onclick=function(t,e,n){var i=this.model,r=i.get(["seriesIndex",n]);if(xN[n]){var o,a={series:[]};P(mN,(function(t){A(t,n)>=0&&P(t,(function(t){i.setIconStatus(t,"normal")}))})),i.setIconStatus(n,"emphasis"),t.eachComponent({mainType:"series",query:null==r?null:{seriesIndex:r}},(function(t){var e=t.subType,r=t.id,o=xN[n](e,r,t,i);o&&(T(o,t.option),a.series.push(o));var s=t.coordinateSystem;if(s&&"cartesian2d"===s.type&&("line"===n||"bar"===n)){var l=s.getAxesByScale("ordinal")[0];if(l){var u=l.dim+"Axis",h=t.getReferringComponents(u,Or).models[0].componentIndex;a[u]=a[u]||[];for(var c=0;c<=h;c++)a[u][h]=a[u][h]||{};a[u][h].boundaryGap="bar"===n}}})),"stack"===n&&(o=S({stack:i.option.title.tiled,tiled:i.option.title.stack},i.option.title)),e.dispatchAction({type:"changeMagicType",currentType:n,newOption:a,newTitle:o,featureName:"magicType"})}},e}(uN),xN={line:function(t,e,n,i){if("bar"===t)return S({id:e,type:"line",data:n.get("data"),stack:n.get("stack"),markPoint:n.get("markPoint"),markLine:n.get("markLine")},i.get(["option","line"])||{},!0)},bar:function(t,e,n,i){if("line"===t)return S({id:e,type:"bar",data:n.get("data"),stack:n.get("stack"),markPoint:n.get("markPoint"),markLine:n.get("markLine")},i.get(["option","bar"])||{},!0)},stack:function(t,e,n,i){var r=n.get("stack")===vN;if("line"===t||"bar"===t)return i.setIconStatus("stack",r?"normal":"emphasis"),S({id:e,stack:r?"":vN},i.get(["option","stack"])||{},!0)}};Yv({type:"changeMagicType",event:"magicTypeChanged",update:"prepareAndUpdate"},(function(t,e){e.mergeOption(t.newOption)}));var bN=new Array(60).join("-"),wN="\t";function SN(t){return t.replace(/^\s\s*/,"").replace(/\s\s*$/,"")}var MN=new RegExp("[\t]+","g");function IN(t,e){var n=t.split(new RegExp("\n*"+bN+"\n*","g")),i={series:[]};return P(n,(function(t,n){if(function(t){if(t.slice(0,t.indexOf("\n")).indexOf(wN)>=0)return!0}(t)){var r=function(t){for(var e=t.split(/\n+/g),n=[],i=O(SN(e.shift()).split(MN),(function(t){return{name:t,data:[]}})),r=0;r=0)&&t(r,i._targetInfoList)}))}return t.prototype.setOutputRanges=function(t,e){return this.matchOutputRanges(t,e,(function(t,e,n){if((t.coordRanges||(t.coordRanges=[])).push(e),!t.coordRange){t.coordRange=e;var i=FN[t.brushType](0,n,e);t.__rangeOffset={offset:HN[t.brushType](i.values,t.range,[1,1]),xyMinMax:i.xyMinMax}}})),t},t.prototype.matchOutputRanges=function(t,e,n){P(t,(function(t){var i=this.findTargetInfo(t,e);i&&!0!==i&&P(i.coordSyses,(function(i){var r=FN[t.brushType](1,i,t.range);n(t,r.values,i,e)}))}),this)},t.prototype.setInputRanges=function(t,e){P(t,(function(t){var n,i,r,o,a,s=this.findTargetInfo(t,e);if(t.range=t.range||[],s&&!0!==s){t.panelId=s.panelId;var l=FN[t.brushType](0,s.coordSys,t.coordRange),u=t.__rangeOffset;t.range=u?HN[t.brushType](l.values,u.offset,(n=l.xyMinMax,i=u.xyMinMax,r=YN(n),o=YN(i),a=[r[0]/o[0],r[1]/o[1]],isNaN(a[0])&&(a[0]=1),isNaN(a[1])&&(a[1]=1),a)):l.values}}),this)},t.prototype.makePanelOpts=function(t,e){return O(this._targetInfoList,(function(n){var i=n.getPanelRect();return{panelId:n.panelId,defaultBrushType:e?e(n):null,clipPath:uD(i),isTargetByCursor:cD(i,t,n.coordSysModel),getLinearBrushOtherExtent:hD(i)}}))},t.prototype.controlSeries=function(t,e,n){var i=this.findTargetInfo(t,n);return!0===i||i&&A(i.coordSyses,e.coordinateSystem)>=0},t.prototype.findTargetInfo=function(t,e){for(var n=this._targetInfoList,i=EN(e,t),r=0;rt[1]&&t.reverse(),t}function EN(t,e){return Pr(t,e,{includeMainTypes:ON})}var zN={grid:function(t,e){var n=t.xAxisModels,i=t.yAxisModels,r=t.gridModels,o=ht(),a={},s={};(n||i||r)&&(P(n,(function(t){var e=t.axis.grid.model;o.set(e.id,e),a[e.id]=!0})),P(i,(function(t){var e=t.axis.grid.model;o.set(e.id,e),s[e.id]=!0})),P(r,(function(t){o.set(t.id,t),a[t.id]=!0,s[t.id]=!0})),o.each((function(t){var r=t.coordinateSystem,o=[];P(r.getCartesians(),(function(t,e){(A(n,t.getAxis("x").model)>=0||A(i,t.getAxis("y").model)>=0)&&o.push(t)})),e.push({panelId:"grid--"+t.id,gridModel:t,coordSysModel:t,coordSys:o[0],coordSyses:o,getPanelRect:VN.grid,xAxisDeclared:a[t.id],yAxisDeclared:s[t.id]})})))},geo:function(t,e){P(t.geoModels,(function(t){var n=t.coordinateSystem;e.push({panelId:"geo--"+t.id,geoModel:t,coordSysModel:t,coordSys:n,coordSyses:[n],getPanelRect:VN.geo})}))}},BN=[function(t,e){var n=t.xAxisModel,i=t.yAxisModel,r=t.gridModel;return!r&&n&&(r=n.axis.grid.model),!r&&i&&(r=i.axis.grid.model),r&&r===e.gridModel},function(t,e){var n=t.geoModel;return n&&n===e.geoModel}],VN={grid:function(){return this.coordSys.master.getRect().clone()},geo:function(){var t=this.coordSys,e=t.getBoundingRect().clone();return e.applyTransform(Vu(t)),e}},FN={lineX:V(GN,0),lineY:V(GN,1),rect:function(t,e,n){var i=e[PN[t]]([n[0][0],n[1][0]]),r=e[PN[t]]([n[0][1],n[1][1]]),o=[NN([i[0],r[0]]),NN([i[1],r[1]])];return{values:o,xyMinMax:o}},polygon:function(t,e,n){var i=[[1/0,-1/0],[1/0,-1/0]];return{values:O(n,(function(n){var r=e[PN[t]](n);return i[0][0]=Math.min(i[0][0],r[0]),i[1][0]=Math.min(i[1][0],r[1]),i[0][1]=Math.max(i[0][1],r[0]),i[1][1]=Math.max(i[1][1],r[1]),r})),xyMinMax:i}}};function GN(t,e,n,i){var r=n.getAxis(["x","y"][t]),o=NN(O([0,1],(function(t){return e?r.coordToData(r.toLocalCoord(i[t])):r.toGlobalCoord(r.dataToCoord(i[t]))}))),a=[];return a[t]=o,a[1-t]=[NaN,NaN],{values:o,xyMinMax:a}}var HN={lineX:V(WN,0),lineY:V(WN,1),rect:function(t,e,n){return[[t[0][0]-n[0]*e[0][0],t[0][1]-n[0]*e[0][1]],[t[1][0]-n[1]*e[1][0],t[1][1]-n[1]*e[1][1]]]},polygon:function(t,e,n){return O(t,(function(t,i){return[t[0]-n[0]*e[i][0],t[1]-n[1]*e[i][1]]}))}};function WN(t,e,n,i){return[e[0]-i[t]*n[0],e[1]-i[t]*n[1]]}function YN(t){return t?[t[0][1]-t[0][0],t[1][1]-t[1][0]]:[NaN,NaN]}var XN,UN,ZN=P,jN=mr+"toolbox-dataZoom_",qN=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return n(e,t),e.prototype.render=function(t,e,n,i){this._brushController||(this._brushController=new PA(n.getZr()),this._brushController.on("brush",B(this._onBrush,this)).mount()),function(t,e,n,i,r){var o=n._isZoomActive;i&&"takeGlobalCursor"===i.type&&(o="dataZoomSelect"===i.key&&i.dataZoomSelectActive);n._isZoomActive=o,t.setIconStatus("zoom",o?"emphasis":"normal");var a=new RN($N(t),e,{include:["grid"]}).makePanelOpts(r,(function(t){return t.xAxisDeclared&&!t.yAxisDeclared?"lineX":!t.xAxisDeclared&&t.yAxisDeclared?"lineY":"rect"}));n._brushController.setPanels(a).enableBrush(!(!o||!a.length)&&{brushType:"auto",brushStyle:t.getModel("brushStyle").getItemStyle()})}(t,e,this,i,n),function(t,e){t.setIconStatus("back",function(t){return LN(t).length}(e)>1?"emphasis":"normal")}(t,e)},e.prototype.onclick=function(t,e,n){KN[n].call(this)},e.prototype.remove=function(t,e){this._brushController&&this._brushController.unmount()},e.prototype.dispose=function(t,e){this._brushController&&this._brushController.dispose()},e.prototype._onBrush=function(t){var e=t.areas;if(t.isEnd&&e.length){var n={},i=this.ecModel;this._brushController.updateCovers([]),new RN($N(this.model),i,{include:["grid"]}).matchOutputRanges(e,i,(function(t,e,n){if("cartesian2d"===n.type){var i=t.brushType;"rect"===i?(r("x",n,e[0]),r("y",n,e[1])):r({lineX:"x",lineY:"y"}[i],n,e)}})),function(t,e){var n=LN(t);AN(e,(function(e,i){for(var r=n.length-1;r>=0&&!n[r][i];r--);if(r<0){var o=t.queryComponents({mainType:"dataZoom",subType:"select",id:i})[0];if(o){var a=o.getPercentRange();n[0][i]={dataZoomId:i,start:a[0],end:a[1]}}}})),n.push(e)}(i,n),this._dispatchZoomAction(n)}function r(t,e,r){var o=e.getAxis(t),a=o.model,s=function(t,e,n){var i;return n.eachComponent({mainType:"dataZoom",subType:"select"},(function(n){n.getAxisModel(t,e.componentIndex)&&(i=n)})),i}(t,a,i),l=s.findRepresentativeAxisProxy(a).getMinMaxSpan();null==l.minValueSpan&&null==l.maxValueSpan||(r=sA(0,r.slice(),o.scale.getExtent(),0,l.minValueSpan,l.maxValueSpan)),s&&(n[s.id]={dataZoomId:s.id,startValue:r[0],endValue:r[1]})}},e.prototype._dispatchZoomAction=function(t){var e=[];ZN(t,(function(t,n){e.push(w(t))})),e.length&&this.api.dispatchAction({type:"dataZoom",from:this.uid,batch:e})},e.getDefaultOption=function(t){return{show:!0,filterMode:"filter",icon:{zoom:"M0,13.5h26.9 M13.5,26.9V0 M32.1,13.5H58V58H13.5 V32.1",back:"M22,1.4L9.9,13.5l12.3,12.3 M10.3,13.5H54.9v44.6 H10.3v-26"},title:t.getLocale(["toolbox","dataZoom","title"]),brushStyle:{borderWidth:0,color:"rgba(210,219,238,0.2)"}}},e}(uN),KN={zoom:function(){var t=!this._isZoomActive;this.api.dispatchAction({type:"takeGlobalCursor",key:"dataZoomSelect",dataZoomSelectActive:t})},back:function(){this._dispatchZoomAction(function(t){var e=LN(t),n=e[e.length-1];e.length>1&&e.pop();var i={};return AN(n,(function(t,n){for(var r=e.length-1;r>=0;r--)if(t=e[r][n]){i[n]=t;break}})),i}(this.ecModel))}};function $N(t){var e={xAxisIndex:t.get("xAxisIndex",!0),yAxisIndex:t.get("yAxisIndex",!0),xAxisId:t.get("xAxisId",!0),yAxisId:t.get("yAxisId",!0)};return null==e.xAxisIndex&&null==e.xAxisId&&(e.xAxisIndex="all"),null==e.yAxisIndex&&null==e.yAxisId&&(e.yAxisIndex="all"),e}XN="dataZoom",UN=function(t){var e=t.getComponent("toolbox",0);if(e){var n=e.getModel(["feature","dataZoom"]),i=[],r=Pr(t,$N(n));return ZN(r.xAxisModels,(function(t){return o(t,"xAxis","xAxisIndex")})),ZN(r.yAxisModels,(function(t){return o(t,"yAxis","yAxisIndex")})),i}function o(t,e,r){var o=t.componentIndex,a={type:"select",$fromToolbox:!0,filterMode:n.get("filterMode",!0)||"filter",id:jN+e+o};a[r]=o,i.push(a)}},rt(null==ip.get(XN)&&UN),ip.set(XN,UN);var JN=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n}return n(e,t),e.type="tooltip",e.dependencies=["axisPointer"],e.defaultOption={zlevel:0,z:60,show:!0,showContent:!0,trigger:"item",triggerOn:"mousemove|click",alwaysShowContent:!1,displayMode:"single",renderMode:"auto",confine:null,showDelay:0,hideDelay:100,transitionDuration:.4,enterable:!1,backgroundColor:"#fff",shadowBlur:10,shadowColor:"rgba(0, 0, 0, .2)",shadowOffsetX:1,shadowOffsetY:2,borderRadius:4,borderWidth:1,padding:null,extraCssText:"",axisPointer:{type:"line",axis:"auto",animation:"auto",animationDurationUpdate:200,animationEasingUpdate:"exponentialOut",crossStyle:{color:"#999",width:1,type:"dashed",textStyle:{}}},textStyle:{color:"#666",fontSize:14}},e}(Nc);function QN(t){var e=t.get("confine");return null!=e?!!e:"richText"===t.get("renderMode")}var tE=["-ms-","-moz-","-o-","-webkit-",""];function eE(t,e,n){var i=[],r=t.get("transitionDuration"),o=t.get("backgroundColor"),s=t.get("shadowBlur"),l=t.get("shadowColor"),u=t.get("shadowOffsetX"),h=t.get("shadowOffsetY"),c=t.getModel("textStyle"),p=Jd(t,"html"),d=u+"px "+h+"px "+s+"px "+l;return i.push("box-shadow:"+d),e&&r&&i.push(function(t,e){var n="cubic-bezier(0.23, 1, 0.32, 1)",i="opacity "+t/2+"s "+n+",visibility "+t/2+"s "+n;return e||(i+=",left "+t+"s "+n+",top "+t+"s "+n),O(tE,(function(t){return t+"transition:"+i})).join(";")}(r,n)),o&&(a.canvasSupported?i.push("background-Color:"+o):(i.push("background-Color:#"+Je(o)),i.push("filter:alpha(opacity=70)"))),P(["width","color","radius"],(function(e){var n="border-"+e,r=cc(n),o=t.get(r);null!=o&&i.push(n+":"+o+("color"===e?"":"px"))})),i.push(function(t){var e=[],n=t.get("fontSize"),i=t.getTextColor();i&&e.push("color:"+i),e.push("font:"+t.getFont()),n&&e.push("line-height:"+Math.round(3*n/2)+"px");var r=t.get("textShadowColor"),o=t.get("textShadowBlur")||0,a=t.get("textShadowOffsetX")||0,s=t.get("textShadowOffsetY")||0;return r&&o&&e.push("text-shadow:"+a+"px "+s+"px "+o+"px "+r),P(["decoration","align"],(function(n){var i=t.get(n);i&&e.push("text-"+n+":"+i)})),e.join(";")}(c)),null!=p&&i.push("padding:"+pc(p).join("px ")+"px"),i.join(";")+";"}function nE(t,e,n,i,r){var o=e&&e.painter;if(n){var a=o&&o.getViewportRoot();a&&function(t,e,n,i,r){Xt(Yt,e,i,r,!0)&&Xt(t,n,Yt[0],Yt[1])}(t,a,document.body,i,r)}else{t[0]=i,t[1]=r;var s=o&&o.getViewportRootOffset();s&&(t[0]+=s.offsetLeft,t[1]+=s.offsetTop)}t[2]=t[0]/e.getWidth(),t[3]=t[1]/e.getHeight()}var iE=function(){function t(t,e,n){if(this._show=!1,this._styleCoord=[0,0,0,0],this._enterable=!0,this._firstShow=!0,this._longHide=!0,a.wxa)return null;var i=document.createElement("div");i.domBelongToZr=!0,this.el=i;var r=this._zr=e.getZr(),o=this._appendToBody=n&&n.appendToBody;nE(this._styleCoord,r,o,e.getWidth()/2,e.getHeight()/2),o?document.body.appendChild(i):t.appendChild(i),this._container=t;var s=this;i.onmouseenter=function(){s._enterable&&(clearTimeout(s._hideTimeout),s._show=!0),s._inContent=!0},i.onmousemove=function(t){if(t=t||window.event,!s._enterable){var e=r.handler;Qt(r.painter.getViewportRoot(),t,!0),e.dispatch("mousemove",t)}},i.onmouseleave=function(){s._inContent=!1,s._enterable&&s._show&&s.hideLater(s._hideDelay)}}return t.prototype.update=function(t){var e=this._container,n=e.currentStyle||document.defaultView.getComputedStyle(e),i=e.style;"absolute"!==i.position&&"absolute"!==n.position&&(i.position="relative"),t.get("alwaysShowContent")&&this._moveIfResized(),this.el.className=t.get("className")||""},t.prototype.show=function(t,e){clearTimeout(this._hideTimeout),clearTimeout(this._longHideTimeout);var n=this.el,i=this._styleCoord,r=n.offsetHeight/2;e=bc(e),n.style.cssText="position:absolute;display:block;border-style:solid;white-space:nowrap;z-index:9999999;"+eE(t,!this._firstShow,this._longHide)+";left:"+i[0]+"px;top:"+(i[1]-r)+"px;border-color: "+e+";"+(t.get("extraCssText")||""),n.style.display=n.innerHTML?"block":"none",n.style.pointerEvents=this._enterable?"auto":"none",this._show=!0,this._firstShow=!1,this._longHide=!1},t.prototype.setContent=function(t,e,n,i,r){if(null!=t){var o=this.el;if(H(r)&&"item"===n.get("trigger")&&!QN(n)&&(t+=function(t,e,n){if(!H(n)||"inside"===n)return"";e=bc(e);var i,r="left"===(i=n)?"right":"right"===i?"left":"top"===i?"bottom":"top",o="",a="";return A(["left","right"],r)>-1?(o=r+":-6px;top:50%;",a="translateY(-50%) rotate("+("left"===r?-225:-45)+"deg)"):(o=r+":-6px;left:50%;",a="translateX(-50%) rotate("+("top"===r?225:45)+"deg)"),'
    '}(n.get("backgroundColor"),i,r)),H(t))o.innerHTML=t;else if(t){o.innerHTML="",F(t)||(t=[t]);for(var a=0;a=0?this._tryShow(n,i):"leave"===e&&this._hide(i))}),this))},e.prototype._keepShow=function(){var t=this._tooltipModel,e=this._ecModel,n=this._api;if(null!=this._lastX&&null!=this._lastY&&"none"!==t.get("triggerOn")){var i=this;clearTimeout(this._refreshUpdateTimeout),this._refreshUpdateTimeout=setTimeout((function(){!n.isDisposed()&&i.manuallyShowTip(t,e,n,{x:i._lastX,y:i._lastY,dataByCoordSys:i._lastDataByCoordSys})}))}},e.prototype.manuallyShowTip=function(t,e,n,i){if(i.from!==this.uid&&!a.node){var r=fE(i,n);this._ticket="";var o=i.dataByCoordSys;if(i.tooltip&&null!=i.x&&null!=i.y){var s=cE;s.x=i.x,s.y=i.y,s.update(),s.tooltip=i.tooltip,this._tryShow({offsetX:i.x,offsetY:i.y,target:s},r)}else if(o)this._tryShow({offsetX:i.x,offsetY:i.y,position:i.position,dataByCoordSys:o,tooltipOption:i.tooltipOption},r);else if(null!=i.seriesIndex){if(this._manuallyAxisShowTip(t,e,n,i))return;var l=CO(i,e),u=l.point[0],h=l.point[1];null!=u&&null!=h&&this._tryShow({offsetX:u,offsetY:h,position:i.position,target:l.el},r)}else null!=i.x&&null!=i.y&&(n.dispatchAction({type:"updateAxisPointer",x:i.x,y:i.y}),this._tryShow({offsetX:i.x,offsetY:i.y,position:i.position,target:n.getZr().findHover(i.x,i.y).target},r))}},e.prototype.manuallyHideTip=function(t,e,n,i){var r=this._tooltipContent;!this._alwaysShowContent&&this._tooltipModel&&r.hideLater(this._tooltipModel.get("hideDelay")),this._lastX=this._lastY=this._lastDataByCoordSys=null,i.from!==this.uid&&this._hide(fE(i,n))},e.prototype._manuallyAxisShowTip=function(t,e,n,i){var r=i.seriesIndex,o=i.dataIndex,a=e.getComponent("axisPointer").coordSysAxesInfo;if(null!=r&&null!=o&&null!=a){var s=e.getSeriesByIndex(r);if(s)if("axis"===dE([s.getData().getItemModel(o),s,(s.coordinateSystem||{}).model,t]).get("trigger"))return n.dispatchAction({type:"updateAxisPointer",seriesIndex:r,dataIndex:o,position:i.position}),!0}},e.prototype._tryShow=function(t,e){var n=t.target;if(this._tooltipModel){this._lastX=t.offsetX,this._lastY=t.offsetY;var i=t.dataByCoordSys;i&&i.length?this._showAxisTooltip(i,t):n&&Jg(n,(function(t){return null!=ys(t).dataIndex}),!0)?(this._lastDataByCoordSys=null,this._showSeriesItemTooltip(t,n,e)):n&&n.tooltip?(this._lastDataByCoordSys=null,this._showComponentItemTooltip(t,n,e)):(this._lastDataByCoordSys=null,this._hide(e))}},e.prototype._showOrMove=function(t,e){var n=t.get("showDelay");e=B(e,this),clearTimeout(this._showTimout),n>0?this._showTimout=setTimeout(e,n):e()},e.prototype._showAxisTooltip=function(t,e){var n=this._ecModel,i=this._tooltipModel,r=[e.offsetX,e.offsetY],o=dE([e.tooltipOption,i]),a=this._renderMode,s=[],l=Yd("section",{blocks:[],noHeader:!0}),u=[],h=new Qd;uE(t,(function(t){uE(t.dataByAxis,(function(t){var e=n.getComponent(t.axisDim+"Axis",t.axisIndex),i=t.value;if(e&&null!=i){var r=uO(i,e.axis,n,t.seriesDataIndices,t.valueLabelOpt),o=Yd("section",{header:r,noHeader:!ot(r),sortBlocks:!0,blocks:[]});l.blocks.push(o),P(t.seriesDataIndices,(function(l){var c=n.getSeriesByIndex(l.seriesIndex),p=l.dataIndexInside,d=c.getDataParams(p);d.axisDim=t.axisDim,d.axisIndex=t.axisIndex,d.axisType=t.axisType,d.axisId=t.axisId,d.axisValue=W_(e.axis,{value:i}),d.axisValueLabel=r,d.marker=h.makeTooltipMarker("item",bc(d.color),a);var f=vd(c.formatTooltip(p,!0,null));f.markupFragment&&o.blocks.push(f.markupFragment),f.markupText&&u.push(f.markupText),s.push(d)}))}}))})),l.blocks.reverse(),u.reverse();var c=e.position,p=o.get("order"),d=Zd(l,h,a,p,n.get("useUTC"),o.get("textStyle"));d&&u.unshift(d);var f="richText"===a?"\n\n":"
    ",g=u.join(f);this._showOrMove(o,(function(){this._updateContentNotChangedOnAxis(t)?this._updatePosition(o,c,r[0],r[1],this._tooltipContent,s):this._showTooltipContent(o,g,s,Math.random()+"",r[0],r[1],c,null,h)}))},e.prototype._showSeriesItemTooltip=function(t,e,n){var i=Jg(e,(function(t){return null!=ys(t).dataIndex}),!0),r=this._ecModel,o=ys(i),a=o.seriesIndex,s=r.getSeriesByIndex(a),l=o.dataModel||s,u=o.dataIndex,h=o.dataType,c=l.getData(h),p=this._renderMode,d=dE([c.getItemModel(u),l,s&&(s.coordinateSystem||{}).model,this._tooltipModel]),f=d.get("trigger");if(null==f||"item"===f){var g=l.getDataParams(u,h),y=new Qd;g.marker=y.makeTooltipMarker("item",bc(g.color),p);var v=vd(l.formatTooltip(u,!1,h)),m=d.get("order"),_=v.markupFragment?Zd(v.markupFragment,y,p,m,r.get("useUTC"),d.get("textStyle")):v.markupText,x="item_"+l.name+"_"+u;this._showOrMove(d,(function(){this._showTooltipContent(d,_,g,x,t.offsetX,t.offsetY,t.position,t.target,y)})),n({type:"showTip",dataIndexInside:u,dataIndex:c.getRawIndex(u),seriesIndex:a,from:this.uid})}},e.prototype._showComponentItemTooltip=function(t,e,n){var i=e.tooltip;if(H(i)){i={content:i,formatter:i}}var r=new Sh(i,this._tooltipModel,this._ecModel),o=r.get("content"),a=Math.random()+"",s=new Qd;this._showOrMove(r,(function(){this._showTooltipContent(r,o,r.get("formatterParams")||{},a,t.offsetX,t.offsetY,t.position,e,s)})),n({type:"showTip",from:this.uid})},e.prototype._showTooltipContent=function(t,e,n,i,r,o,a,s,l){if(this._ticket="",t.get("showContent")&&t.get("show")){var u=this._tooltipContent,h=t.get("formatter");a=a||t.get("position");var c=e,p=this._getNearestPoint([r,o],n,t.get("trigger"),t.get("borderColor"));if(h&&H(h)){var d=t.ecModel.get("useUTC"),f=F(n)?n[0]:n;c=h,f&&f.axisType&&f.axisType.indexOf("time")>=0&&(c=Zh(f.axisValue,c,d)),c=_c(c,n,!0)}else if(G(h)){var g=lE((function(e,i){e===this._ticket&&(u.setContent(i,l,t,p.color,a),this._updatePosition(t,a,r,o,u,n,s))}),this);this._ticket=i,c=h(n,i,g)}u.setContent(c,l,t,p.color,a),u.show(t,p.color),this._updatePosition(t,a,r,o,u,n,s)}},e.prototype._getNearestPoint=function(t,e,n,i){return"axis"===n||F(e)?{color:i||("html"===this._renderMode?"#fff":"none")}:F(e)?void 0:{color:i||e.color||e.borderColor}},e.prototype._updatePosition=function(t,e,n,i,r,o,a){var s=this._api.getWidth(),l=this._api.getHeight();e=e||t.get("position");var u=r.getSize(),h=t.get("align"),c=t.get("verticalAlign"),p=a&&a.getBoundingRect().clone();if(a&&p.applyTransform(a.transform),G(e)&&(e=e([n,i],o,r.el,p,{viewSize:[s,l],contentSize:u.slice()})),F(e))n=hE(e[0],s),i=hE(e[1],l);else if(X(e)){var d=e;d.width=u[0],d.height=u[1];var f=Ac(d,{width:s,height:l});n=f.x,i=f.y,h=null,c=null}else if(H(e)&&a){var g=function(t,e,n){var i=n[0],r=n[1],o=10,a=5,s=0,l=0,u=e.width,h=e.height;switch(t){case"inside":s=e.x+u/2-i/2,l=e.y+h/2-r/2;break;case"top":s=e.x+u/2-i/2,l=e.y-r-o;break;case"bottom":s=e.x+u/2-i/2,l=e.y+h+o;break;case"left":s=e.x-i-o-a,l=e.y+h/2-r/2;break;case"right":s=e.x+u+o+a,l=e.y+h/2-r/2}return[s,l]}(e,p,u);n=g[0],i=g[1]}else{g=function(t,e,n,i,r,o,a){var s=n.getOuterSize(),l=s.width,u=s.height;null!=o&&(t+l+o+2>i?t-=l+o:t+=o);null!=a&&(e+u+a>r?e-=u+a:e+=a);return[t,e]}(n,i,r,s,l,h?null:20,c?null:20);n=g[0],i=g[1]}if(h&&(n-=gE(h)?u[0]/2:"right"===h?u[0]:0),c&&(i-=gE(c)?u[1]/2:"bottom"===c?u[1]:0),QN(t)){g=function(t,e,n,i,r){var o=n.getOuterSize(),a=o.width,s=o.height;return t=Math.min(t+a,i)-a,e=Math.min(e+s,r)-s,t=Math.max(t,0),e=Math.max(e,0),[t,e]}(n,i,r,s,l);n=g[0],i=g[1]}r.moveTo(n,i)},e.prototype._updateContentNotChangedOnAxis=function(t){var e=this._lastDataByCoordSys,n=!!e&&e.length===t.length;return n&&uE(e,(function(e,i){var r=e.dataByAxis||[],o=(t[i]||{}).dataByAxis||[];(n=n&&r.length===o.length)&&uE(r,(function(t,e){var i=o[e]||{},r=t.seriesDataIndices||[],a=i.seriesDataIndices||[];(n=n&&t.value===i.value&&t.axisType===i.axisType&&t.axisId===i.axisId&&r.length===a.length)&&uE(r,(function(t,e){var i=a[e];n=n&&t.seriesIndex===i.seriesIndex&&t.dataIndex===i.dataIndex}))}))})),this._lastDataByCoordSys=t,!!n},e.prototype._hide=function(t){this._lastDataByCoordSys=null,t({type:"hideTip",from:this.uid})},e.prototype.dispose=function(t,e){a.node||(this._tooltipContent.dispose(),IO("itemTooltip",e))},e.type="tooltip",e}(pf);function dE(t){for(var e=t.pop();t.length;){var n=t.pop();n&&(n instanceof Sh&&(n=n.get("tooltip",!0)),H(n)&&(n={formatter:n}),e=new Sh(n,e,e.ecModel))}return e}function fE(t,e){return t.dispatchAction||B(e.dispatchAction,e)}function gE(t){return"center"===t||"middle"===t}var yE=["rect","polygon","keep","clear"];function vE(t,e){var n=_r(t?t.brush:[]);if(n.length){var i=[];P(n,(function(t){var e=t.hasOwnProperty("toolbox")?t.toolbox:[];e instanceof Array&&(i=i.concat(e))}));var r=t&&t.toolbox;F(r)&&(r=r[0]),r||(r={feature:{}},t.toolbox=[r]);var o=r.feature||(r.feature={}),a=o.brush||(o.brush={}),s=a.type||(a.type=[]);s.push.apply(s,i),function(t){var e={};P(t,(function(t){e[t]=1})),t.length=0,P(e,(function(e,n){t.push(n)}))}(s),e&&!s.length&&s.push.apply(s,yE)}}var mE=P;function _E(t){if(t)for(var e in t)if(t.hasOwnProperty(e))return!0}function xE(t,e,n){var i={};return mE(e,(function(e){var r,o=i[e]=((r=function(){}).prototype.__hidden=r.prototype,new r);mE(t[e],(function(t,i){if(eT.isValidType(i)){var r={type:i,visual:t};n&&n(r,e),o[i]=new eT(r),"opacity"===i&&((r=w(r)).type="colorAlpha",o.__hidden.__alphaForOpacity=new eT(r))}}))})),i}function bE(t,e,n){var i;P(n,(function(t){e.hasOwnProperty(t)&&_E(e[t])&&(i=!0)})),i&&P(n,(function(n){e.hasOwnProperty(n)&&_E(e[n])?t[n]=w(e[n]):delete t[n]}))}var wE={lineX:SE(0),lineY:SE(1),rect:{point:function(t,e,n){return t&&n.boundingRect.contain(t[0],t[1])},rect:function(t,e,n){return t&&n.boundingRect.intersect(t)}},polygon:{point:function(t,e,n){return t&&n.boundingRect.contain(t[0],t[1])&&J_(n.range,t[0],t[1])},rect:function(t,e,n){var i=n.range;if(!t||i.length<=1)return!1;var r=t.x,o=t.y,a=t.width,s=t.height,l=i[0];return!!(J_(i,r,o)||J_(i,r+a,o)||J_(i,r,o+s)||J_(i,r+a,o+s)||Rn.create(t).contain(l[0],l[1])||Zu(r,o,r+a,o,i)||Zu(r,o,r,o+s,i)||Zu(r+a,o,r+a,o+s,i)||Zu(r,o+s,r+a,o+s,i))||void 0}}};function SE(t){var e=["x","y"],n=["width","height"];return{point:function(e,n,i){if(e){var r=i.range;return ME(e[t],r)}},rect:function(i,r,o){if(i){var a=o.range,s=[i[e[t]],i[e[t]]+i[n[t]]];return s[1]e[0][1]&&(e[0][1]=o[0]),o[1]e[1][1]&&(e[1][1]=o[1])}return e&&OE(e)}};function OE(t){return new Rn(t[0][0],t[1][0],t[0][1]-t[0][0],t[1][1]-t[1][0])}var RE=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n}return n(e,t),e.prototype.init=function(t,e){this.ecModel=t,this.api=e,this.model,(this._brushController=new PA(e.getZr())).on("brush",B(this._onBrush,this)).mount()},e.prototype.render=function(t,e,n,i){this.model=t,this._updateController(t,e,n,i)},e.prototype.updateTransform=function(t,e,n,i){AE(e),this._updateController(t,e,n,i)},e.prototype.updateVisual=function(t,e,n,i){this.updateTransform(t,e,n,i)},e.prototype.updateView=function(t,e,n,i){this._updateController(t,e,n,i)},e.prototype._updateController=function(t,e,n,i){(!i||i.$from!==t.id)&&this._brushController.setPanels(t.brushTargetManager.makePanelOpts(n)).enableBrush(t.brushOption).updateCovers(t.areas.slice())},e.prototype.dispose=function(){this._brushController.dispose()},e.prototype._onBrush=function(t){var e=this.model.id,n=this.model.brushTargetManager.setOutputRanges(t.areas,this.ecModel);(!t.isEnd||t.removeOnClick)&&this.api.dispatchAction({type:"brush",brushId:e,areas:w(n),$from:e}),t.isEnd&&this.api.dispatchAction({type:"brushEnd",brushId:e,areas:w(n),$from:e})},e.type="brush",e}(pf),NE=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n.areas=[],n.brushOption={},n}return n(e,t),e.prototype.optionUpdated=function(t,e){var n=this.option;!e&&bE(n,t,["inBrush","outOfBrush"]);var i=n.inBrush=n.inBrush||{};n.outOfBrush=n.outOfBrush||{color:"#ddd"},i.hasOwnProperty("liftZ")||(i.liftZ=5)},e.prototype.setAreas=function(t){t&&(this.areas=O(t,(function(t){return EE(this.option,t)}),this))},e.prototype.setBrushOption=function(t){this.brushOption=EE(this.option,t),this.brushType=this.brushOption.brushType},e.type="brush",e.dependencies=["geo","grid","xAxis","yAxis","parallel","series"],e.defaultOption={seriesIndex:"all",brushType:"rect",brushMode:"single",transformable:!0,brushStyle:{borderWidth:1,color:"rgba(210,219,238,0.3)",borderColor:"#D2DBEE"},throttleType:"fixRate",throttleDelay:0,removeOnClick:!0,z:1e4},e}(Nc);function EE(t,e){return S({brushType:t.brushType,brushMode:t.brushMode,transformable:t.transformable,brushStyle:new Sh(t.brushStyle).getItemStyle(),removeOnClick:t.removeOnClick,z:t.z},e,!0)}var zE=["rect","polygon","lineX","lineY","keep","clear"],BE=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return n(e,t),e.prototype.render=function(t,e,n){var i,r,o;e.eachComponent({mainType:"brush"},(function(t){i=t.brushType,r=t.brushOption.brushMode||"single",o=o||!!t.areas.length})),this._brushType=i,this._brushMode=r,P(t.get("type",!0),(function(e){t.setIconStatus(e,("keep"===e?"multiple"===r:"clear"===e?o:e===i)?"emphasis":"normal")}))},e.prototype.updateView=function(t,e,n){this.render(t,e,n)},e.prototype.getIcons=function(){var t=this.model,e=t.get("icon",!0),n={};return P(t.get("type",!0),(function(t){e[t]&&(n[t]=e[t])})),n},e.prototype.onclick=function(t,e,n){var i=this._brushType,r=this._brushMode;"clear"===n?(e.dispatchAction({type:"axisAreaSelect",intervals:[]}),e.dispatchAction({type:"brush",command:"clear",areas:[]})):e.dispatchAction({type:"takeGlobalCursor",key:"brush",brushOption:{brushType:"keep"===n?i:i!==n&&n,brushMode:"keep"===n?"multiple"===r?"single":"multiple":r}})},e.getDefaultOption=function(t){return{show:!0,type:zE.slice(),icon:{rect:"M7.3,34.7 M0.4,10V-0.2h9.8 M89.6,10V-0.2h-9.8 M0.4,60v10.2h9.8 M89.6,60v10.2h-9.8 M12.3,22.4V10.5h13.1 M33.6,10.5h7.8 M49.1,10.5h7.8 M77.5,22.4V10.5h-13 M12.3,31.1v8.2 M77.7,31.1v8.2 M12.3,47.6v11.9h13.1 M33.6,59.5h7.6 M49.1,59.5 h7.7 M77.5,47.6v11.9h-13",polygon:"M55.2,34.9c1.7,0,3.1,1.4,3.1,3.1s-1.4,3.1-3.1,3.1 s-3.1-1.4-3.1-3.1S53.5,34.9,55.2,34.9z M50.4,51c1.7,0,3.1,1.4,3.1,3.1c0,1.7-1.4,3.1-3.1,3.1c-1.7,0-3.1-1.4-3.1-3.1 C47.3,52.4,48.7,51,50.4,51z M55.6,37.1l1.5-7.8 M60.1,13.5l1.6-8.7l-7.8,4 M59,19l-1,5.3 M24,16.1l6.4,4.9l6.4-3.3 M48.5,11.6 l-5.9,3.1 M19.1,12.8L9.7,5.1l1.1,7.7 M13.4,29.8l1,7.3l6.6,1.6 M11.6,18.4l1,6.1 M32.8,41.9 M26.6,40.4 M27.3,40.2l6.1,1.6 M49.9,52.1l-5.6-7.6l-4.9-1.2",lineX:"M15.2,30 M19.7,15.6V1.9H29 M34.8,1.9H40.4 M55.3,15.6V1.9H45.9 M19.7,44.4V58.1H29 M34.8,58.1H40.4 M55.3,44.4 V58.1H45.9 M12.5,20.3l-9.4,9.6l9.6,9.8 M3.1,29.9h16.5 M62.5,20.3l9.4,9.6L62.3,39.7 M71.9,29.9H55.4",lineY:"M38.8,7.7 M52.7,12h13.2v9 M65.9,26.6V32 M52.7,46.3h13.2v-9 M24.9,12H11.8v9 M11.8,26.6V32 M24.9,46.3H11.8v-9 M48.2,5.1l-9.3-9l-9.4,9.2 M38.9-3.9V12 M48.2,53.3l-9.3,9l-9.4-9.2 M38.9,62.3V46.4",keep:"M4,10.5V1h10.3 M20.7,1h6.1 M33,1h6.1 M55.4,10.5V1H45.2 M4,17.3v6.6 M55.6,17.3v6.6 M4,30.5V40h10.3 M20.7,40 h6.1 M33,40h6.1 M55.4,30.5V40H45.2 M21,18.9h62.9v48.6H21V18.9z",clear:"M22,14.7l30.9,31 M52.9,14.7L22,45.7 M4.7,16.8V4.2h13.1 M26,4.2h7.8 M41.6,4.2h7.8 M70.3,16.8V4.2H57.2 M4.7,25.9v8.6 M70.3,25.9v8.6 M4.7,43.2v12.6h13.1 M26,55.8h7.8 M41.6,55.8h7.8 M70.3,43.2v12.6H57.2"},title:t.getLocale(["toolbox","brush","title"])}},e}(uN);var VE=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n.layoutMode={type:"box",ignoreSize:!0},n}return n(e,t),e.type="title",e.defaultOption={zlevel:0,z:6,show:!0,text:"",target:"blank",subtext:"",subtarget:"blank",left:0,top:0,backgroundColor:"rgba(0,0,0,0)",borderColor:"#ccc",borderWidth:0,padding:5,itemGap:10,textStyle:{fontSize:18,fontWeight:"bold",color:"#464646"},subtextStyle:{fontSize:12,color:"#6E7079"}},e}(Nc),FE=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n}return n(e,t),e.prototype.render=function(t,e,n){if(this.group.removeAll(),t.get("show")){var i=this.group,r=t.getModel("textStyle"),o=t.getModel("subtextStyle"),a=t.get("textAlign"),s=tt(t.get("textBaseline"),t.get("textVerticalAlign")),l=new ls({style:nh(r,{text:t.get("text"),fill:r.getTextColor()},{disableBox:!0}),z2:10}),u=l.getBoundingRect(),h=t.get("subtext"),c=new ls({style:nh(o,{text:h,fill:o.getTextColor(),y:u.height+t.get("itemGap"),verticalAlign:"top"},{disableBox:!0}),z2:10}),p=t.get("link"),d=t.get("sublink"),f=t.get("triggerEvent",!0);l.silent=!p&&!f,c.silent=!d&&!f,p&&l.on("click",(function(){wc(p,"_"+t.get("target"))})),d&&c.on("click",(function(){wc(d,"_"+t.get("subtarget"))})),ys(l).eventData=ys(c).eventData=f?{componentType:"title",componentIndex:t.componentIndex}:null,i.add(l),h&&i.add(c);var g=i.getBoundingRect(),y=t.getBoxLayoutParams();y.width=g.width,y.height=g.height;var v=Ac(y,{width:n.getWidth(),height:n.getHeight()},t.get("padding"));a||("middle"===(a=t.get("left")||t.get("right"))&&(a="center"),"right"===a?v.x+=v.width:"center"===a&&(v.x+=v.width/2)),s||("center"===(s=t.get("top")||t.get("bottom"))&&(s="middle"),"bottom"===s?v.y+=v.height:"middle"===s&&(v.y+=v.height/2),s=s||"top"),i.x=v.x,i.y=v.y,i.markRedraw();var m={align:a,verticalAlign:s};l.setStyle(m),c.setStyle(m),g=i.getBoundingRect();var _=v.margin,x=t.getItemStyle(["color","opacity"]);x.fill=t.get("backgroundColor");var b=new os({shape:{x:g.x-_[3],y:g.y-_[0],width:g.width+_[1]+_[3],height:g.height+_[0]+_[2],r:t.get("borderRadius")},style:x,subPixelOptimize:!0,silent:!0});i.add(b)}},e.type="title",e}(pf);var GE=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n.layoutMode="box",n}return n(e,t),e.prototype.init=function(t,e,n){this.mergeDefaultAndTheme(t,n),this._initData()},e.prototype.mergeOption=function(e){t.prototype.mergeOption.apply(this,arguments),this._initData()},e.prototype.setCurrentIndex=function(t){null==t&&(t=this.option.currentIndex);var e=this._data.count();this.option.loop?t=(t%e+e)%e:(t>=e&&(t=e-1),t<0&&(t=0)),this.option.currentIndex=t},e.prototype.getCurrentIndex=function(){return this.option.currentIndex},e.prototype.isIndexMax=function(){return this.getCurrentIndex()>=this._data.count()-1},e.prototype.setPlayState=function(t){this.option.autoPlay=!!t},e.prototype.getPlayState=function(){return!!this.option.autoPlay},e.prototype._initData=function(){var t,e=this.option,n=e.data||[],i=e.axisType,r=this._names=[];"category"===i?(t=[],P(n,(function(e,n){var i,o=Tr(wr(e),"");X(e)?(i=w(e)).value=n:i=n,t.push(i),r.push(o)}))):t=n;var o={category:"ordinal",time:"time",value:"number"}[i]||"number";(this._data=new Pm([{name:"value",type:o}],this)).initData(t,r)},e.prototype.getData=function(){return this._data},e.prototype.getCategories=function(){if("category"===this.get("axisType"))return this._names.slice()},e.type="timeline",e.defaultOption={zlevel:0,z:4,show:!0,axisType:"time",realtime:!0,left:"20%",top:null,right:"20%",bottom:0,width:null,height:40,padding:5,controlPosition:"left",autoPlay:!1,rewind:!1,loop:!0,playInterval:2e3,currentIndex:0,itemStyle:{},label:{color:"#000"},data:[]},e}(Nc),HE=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n}return n(e,t),e.type="timeline.slider",e.defaultOption=Th(GE.defaultOption,{backgroundColor:"rgba(0,0,0,0)",borderColor:"#ccc",borderWidth:0,orient:"horizontal",inverse:!1,tooltip:{trigger:"item"},symbol:"circle",symbolSize:12,lineStyle:{show:!0,width:2,color:"#DAE1F5"},label:{position:"auto",show:!0,interval:"auto",rotate:0,color:"#A4B1D7"},itemStyle:{color:"#A4B1D7",borderWidth:1},checkpointStyle:{symbol:"circle",symbolSize:15,color:"#316bf3",borderColor:"#fff",borderWidth:2,shadowBlur:2,shadowOffsetX:1,shadowOffsetY:1,shadowColor:"rgba(0, 0, 0, 0.3)",animation:!0,animationDuration:300,animationEasing:"quinticInOut"},controlStyle:{show:!0,showPlayBtn:!0,showPrevBtn:!0,showNextBtn:!0,itemSize:24,itemGap:12,position:"left",playIcon:"path://M31.6,53C17.5,53,6,41.5,6,27.4S17.5,1.8,31.6,1.8C45.7,1.8,57.2,13.3,57.2,27.4S45.7,53,31.6,53z M31.6,3.3 C18.4,3.3,7.5,14.1,7.5,27.4c0,13.3,10.8,24.1,24.1,24.1C44.9,51.5,55.7,40.7,55.7,27.4C55.7,14.1,44.9,3.3,31.6,3.3z M24.9,21.3 c0-2.2,1.6-3.1,3.5-2l10.5,6.1c1.899,1.1,1.899,2.9,0,4l-10.5,6.1c-1.9,1.1-3.5,0.2-3.5-2V21.3z",stopIcon:"path://M30.9,53.2C16.8,53.2,5.3,41.7,5.3,27.6S16.8,2,30.9,2C45,2,56.4,13.5,56.4,27.6S45,53.2,30.9,53.2z M30.9,3.5C17.6,3.5,6.8,14.4,6.8,27.6c0,13.3,10.8,24.1,24.101,24.1C44.2,51.7,55,40.9,55,27.6C54.9,14.4,44.1,3.5,30.9,3.5z M36.9,35.8c0,0.601-0.4,1-0.9,1h-1.3c-0.5,0-0.9-0.399-0.9-1V19.5c0-0.6,0.4-1,0.9-1H36c0.5,0,0.9,0.4,0.9,1V35.8z M27.8,35.8 c0,0.601-0.4,1-0.9,1h-1.3c-0.5,0-0.9-0.399-0.9-1V19.5c0-0.6,0.4-1,0.9-1H27c0.5,0,0.9,0.4,0.9,1L27.8,35.8L27.8,35.8z",nextIcon:"M2,18.5A1.52,1.52,0,0,1,.92,18a1.49,1.49,0,0,1,0-2.12L7.81,9.36,1,3.11A1.5,1.5,0,1,1,3,.89l8,7.34a1.48,1.48,0,0,1,.49,1.09,1.51,1.51,0,0,1-.46,1.1L3,18.08A1.5,1.5,0,0,1,2,18.5Z",prevIcon:"M10,.5A1.52,1.52,0,0,1,11.08,1a1.49,1.49,0,0,1,0,2.12L4.19,9.64,11,15.89a1.5,1.5,0,1,1-2,2.22L1,10.77A1.48,1.48,0,0,1,.5,9.68,1.51,1.51,0,0,1,1,8.58L9,.92A1.5,1.5,0,0,1,10,.5Z",prevBtnSize:18,nextBtnSize:18,color:"#A4B1D7",borderColor:"#A4B1D7",borderWidth:1},emphasis:{label:{show:!0,color:"#6f778d"},itemStyle:{color:"#316BF3"},controlStyle:{color:"#316BF3",borderColor:"#316BF3",borderWidth:2}},progress:{lineStyle:{color:"#316BF3"},itemStyle:{color:"#316BF3"},label:{color:"#6f778d"}},data:[]}),e}(GE);L(HE,yd.prototype);var WE=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n}return n(e,t),e.type="timeline",e}(pf),YE=function(t){function e(e,n,i,r){var o=t.call(this,e,n,i)||this;return o.type=r||"value",o}return n(e,t),e.prototype.getLabelModel=function(){return this.model.getModel("label")},e.prototype.isHorizontal=function(){return"horizontal"===this.model.get("orient")},e}(vx),XE=Math.PI,UE=Lr(),ZE=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n}return n(e,t),e.prototype.init=function(t,e){this.api=e},e.prototype.render=function(t,e,n){if(this.model=t,this.api=n,this.ecModel=e,this.group.removeAll(),t.get("show",!0)){var i=this._layout(t,n),r=this._createGroup("_mainGroup"),o=this._createGroup("_labelGroup"),a=this._axis=this._createAxis(i,t);t.formatTooltip=function(t){return Yd("nameValue",{noName:!0,value:a.scale.getLabel({value:t})})},P(["AxisLine","AxisTick","Control","CurrentPointer"],(function(e){this["_render"+e](i,r,a,t)}),this),this._renderAxisLabel(i,o,a,t),this._position(i,t)}this._doPlayStop(),this._updateTicksStatus()},e.prototype.remove=function(){this._clearTimer(),this.group.removeAll()},e.prototype.dispose=function(){this._clearTimer()},e.prototype._layout=function(t,e){var n,i,r,o,a=t.get(["label","position"]),s=t.get("orient"),l=function(t,e){return Ac(t.getBoxLayoutParams(),{width:e.getWidth(),height:e.getHeight()},t.get("padding"))}(t,e),u={horizontal:"center",vertical:(n=null==a||"auto"===a?"horizontal"===s?l.y+l.height/2=0||"+"===n?"left":"right"},h={horizontal:n>=0||"+"===n?"top":"bottom",vertical:"middle"},c={horizontal:0,vertical:XE/2},p="vertical"===s?l.height:l.width,d=t.getModel("controlStyle"),f=d.get("show",!0),g=f?d.get("itemSize"):0,y=f?d.get("itemGap"):0,v=g+y,m=t.get(["label","rotate"])||0;m=m*XE/180;var _=d.get("position",!0),x=f&&d.get("showPlayBtn",!0),b=f&&d.get("showPrevBtn",!0),w=f&&d.get("showNextBtn",!0),S=0,M=p;"left"===_||"bottom"===_?(x&&(i=[0,0],S+=v),b&&(r=[S,0],S+=v),w&&(o=[M-g,0],M-=v)):(x&&(i=[M-g,0],M-=v),b&&(r=[0,0],S+=v),w&&(o=[M-g,0],M-=v));var I=[S,M];return t.get("inverse")&&I.reverse(),{viewRect:l,mainLength:p,orient:s,rotation:c[s],labelRotation:m,labelPosOpt:n,labelAlign:t.get(["label","align"])||u[s],labelBaseline:t.get(["label","verticalAlign"])||t.get(["label","baseline"])||h[s],playPosition:i,prevBtnPosition:r,nextBtnPosition:o,axisExtent:I,controlSize:g,controlGap:y}},e.prototype._position=function(t,e){var n=this._mainGroup,i=this._labelGroup,r=t.viewRect;if("vertical"===t.orient){var o=[1,0,0,1,0,0],a=r.x,s=r.y+r.height;me(o,o,[-a,-s]),_e(o,o,-XE/2),me(o,o,[a,s]),(r=r.clone()).applyTransform(o)}var l=y(r),u=y(n.getBoundingRect()),h=y(i.getBoundingRect()),c=[n.x,n.y],p=[i.x,i.y];p[0]=c[0]=l[0][0];var d,f=t.labelPosOpt;null==f||H(f)?(v(c,u,l,1,d="+"===f?0:1),v(p,h,l,1,1-d)):(v(c,u,l,1,d=f>=0?0:1),p[1]=c[1]+f);function g(t){t.originX=l[0][0]-t.x,t.originY=l[1][0]-t.y}function y(t){return[[t.x,t.x+t.width],[t.y,t.y+t.height]]}function v(t,e,n,i,r){t[i]+=n[i][r]-e[i][r]}n.setPosition(c),i.setPosition(p),n.rotation=i.rotation=t.rotation,g(n),g(i)},e.prototype._createAxis=function(t,e){var n=e.getData(),i=e.get("axisType"),r=function(t,e){if(e=e||t.get("type"))switch(e){case"category":return new Qm({ordinalMeta:t.getCategories(),extent:[1/0,-1/0]});case"time":return new g_({locale:t.ecModel.getLocaleModel(),useUTC:t.ecModel.get("useUTC")});default:return new e_}}(e,i);r.getTicks=function(){return n.mapArray(["value"],(function(t){return{value:t}}))};var o=n.getDataExtent("value");r.setExtent(o[0],o[1]),r.niceTicks();var a=new YE("value",r,t.axisExtent,i);return a.model=e,a},e.prototype._createGroup=function(t){var e=this[t]=new zi;return this.group.add(e),e},e.prototype._renderAxisLine=function(t,e,n,i){var r=n.getExtent();if(i.get(["lineStyle","show"])){var o=new tu({shape:{x1:r[0],y1:0,x2:r[1],y2:0},style:I({lineCap:"round"},i.getModel("lineStyle").getLineStyle()),silent:!0,z2:1});e.add(o);var a=this._progressLine=new tu({shape:{x1:r[0],x2:this._currentPointer?this._currentPointer.x:r[0],y1:0,y2:0},style:T({lineCap:"round",lineWidth:o.style.lineWidth},i.getModel(["progress","lineStyle"]).getLineStyle()),silent:!0,z2:1});e.add(a)}},e.prototype._renderAxisTick=function(t,e,n,i){var r=this,o=i.getData(),a=n.scale.getTicks();this._tickSymbols=[],P(a,(function(t){var a=n.dataToCoord(t.value),s=o.getItemModel(t.value),l=s.getModel("itemStyle"),u=s.getModel(["emphasis","itemStyle"]),h=s.getModel(["progress","itemStyle"]),c={x:a,y:0,onclick:B(r._changeTimeline,r,t.value)},p=jE(s,l,e,c);p.ensureState("emphasis").style=u.getItemStyle(),p.ensureState("progress").style=h.getItemStyle(),Js(p);var d=ys(p);s.get("tooltip")?(d.dataIndex=t.value,d.dataModel=i):d.dataIndex=d.dataModel=null,r._tickSymbols.push(p)}))},e.prototype._renderAxisLabel=function(t,e,n,i){var r=this;if(n.getLabelModel().get("show")){var o=i.getData(),a=n.getViewLabels();this._tickLabels=[],P(a,(function(i){var a=i.tickValue,s=o.getItemModel(a),l=s.getModel("label"),u=s.getModel(["emphasis","label"]),h=s.getModel(["progress","label"]),c=n.dataToCoord(i.tickValue),p=new ls({x:c,y:0,rotation:t.labelRotation-t.rotation,onclick:B(r._changeTimeline,r,a),silent:!1,style:nh(l,{text:i.formattedLabel,align:t.labelAlign,verticalAlign:t.labelBaseline})});p.ensureState("emphasis").style=nh(u),p.ensureState("progress").style=nh(h),e.add(p),Js(p),UE(p).dataIndex=a,r._tickLabels.push(p)}))}},e.prototype._renderControl=function(t,e,n,i){var r=t.controlSize,o=t.rotation,a=i.getModel("controlStyle").getItemStyle(),s=i.getModel(["emphasis","controlStyle"]).getItemStyle(),l=i.getPlayState(),u=i.get("inverse",!0);function h(t,n,l,u){if(t){var h=Yn(tt(i.get(["controlStyle",n+"BtnSize"]),r),r),c=function(t,e,n,i){var r=i.style,o=Uu(t.get(["controlStyle",e]),i||{},new Rn(n[0],n[1],n[2],n[3]));r&&o.setStyle(r);return o}(i,n+"Icon",[0,-h/2,h,h],{position:t,origin:[r/2,0],rotation:u?-o:0,rectHover:!0,style:a,onclick:l});c.ensureState("emphasis").style=s,e.add(c),Js(c)}}h(t.nextBtnPosition,"next",B(this._changeTimeline,this,u?"-":"+")),h(t.prevBtnPosition,"prev",B(this._changeTimeline,this,u?"+":"-")),h(t.playPosition,l?"stop":"play",B(this._handlePlayClick,this,!l),!0)},e.prototype._renderCurrentPointer=function(t,e,n,i){var r=i.getData(),o=i.getCurrentIndex(),a=r.getItemModel(o).getModel("checkpointStyle"),s=this,l={onCreate:function(t){t.draggable=!0,t.drift=B(s._handlePointerDrag,s),t.ondragend=B(s._handlePointerDragend,s),qE(t,s._progressLine,o,n,i,!0)},onUpdate:function(t){qE(t,s._progressLine,o,n,i)}};this._currentPointer=jE(a,a,this._mainGroup,{},this._currentPointer,l)},e.prototype._handlePlayClick=function(t){this._clearTimer(),this.api.dispatchAction({type:"timelinePlayChange",playState:t,from:this.uid})},e.prototype._handlePointerDrag=function(t,e,n){this._clearTimer(),this._pointerChangeTimeline([n.offsetX,n.offsetY])},e.prototype._handlePointerDragend=function(t){this._pointerChangeTimeline([t.offsetX,t.offsetY],!0)},e.prototype._pointerChangeTimeline=function(t,e){var n=this._toAxisCoord(t)[0],i=qi(this._axis.getExtent().slice());n>i[1]&&(n=i[1]),n=0&&(a[o]=+a[o].toFixed(c)),[a,h]}var rz={min:V(iz,"min"),max:V(iz,"max"),average:V(iz,"average"),median:V(iz,"median")};function oz(t,e){var n=t.getData(),i=t.coordinateSystem;if(e&&!function(t){return!isNaN(parseFloat(t.x))&&!isNaN(parseFloat(t.y))}(e)&&!F(e.coord)&&i){var r=i.dimensions,o=az(e,n,i,t);if((e=w(e)).type&&rz[e.type]&&o.baseAxis&&o.valueAxis){var a=A(r,o.baseAxis.dim),s=A(r,o.valueAxis.dim),l=rz[e.type](n,o.baseDataDim,o.valueDataDim,a,s);e.coord=l[0],e.value=l[1]}else{for(var u=[null!=e.xAxis?e.xAxis:e.radiusAxis,null!=e.yAxis?e.yAxis:e.angleAxis],h=0;h<2;h++)rz[u[h]]&&(u[h]=uz(n,n.mapDimension(r[h]),u[h]));e.coord=u}}return e}function az(t,e,n,i){var r={};return null!=t.valueIndex||null!=t.valueDim?(r.valueDataDim=null!=t.valueIndex?e.getDimension(t.valueIndex):t.valueDim,r.valueAxis=n.getAxis(function(t,e){var n=t.getData(),i=n.dimensions;e=n.getDimension(e);for(var r=0;r=0&&"number"==typeof l&&(l=+l.toFixed(Math.min(f,20))),p.coord[h]=d.coord[h]=l,r=[p,d,{type:a,valueIndex:i.valueIndex,value:l}]}else r=[]}var g=[oz(t,r[0]),oz(t,r[1]),I({},r[2])];return g[2].type=g[2].type||null,S(g[2],g[0]),S(g[2],g[1]),g};function vz(t){return!isNaN(t)&&!isFinite(t)}function mz(t,e,n,i){var r=1-t,o=i.dimensions[t];return vz(e[r])&&vz(n[r])&&e[t]===n[t]&&i.getAxis(o).containData(e[t])}function _z(t,e){if("cartesian2d"===t.type){var n=e[0].coord,i=e[1].coord;if(n&&i&&(mz(1,n,i,t)||mz(0,n,i,t)))return!0}return sz(t,e[0])&&sz(t,e[1])}function xz(t,e,n,i,r){var o,a=i.coordinateSystem,s=t.getItemModel(e),l=Zi(s.get("x"),r.getWidth()),u=Zi(s.get("y"),r.getHeight());if(isNaN(l)||isNaN(u)){if(i.getMarkerPosition)o=i.getMarkerPosition(t.getValues(t.dimensions,e));else{var h=a.dimensions,c=t.get(h[0],e),p=t.get(h[1],e);o=a.dataToPoint([c,p])}if(Wb(a,"cartesian2d")){var d=a.getAxis("x"),f=a.getAxis("y");h=a.dimensions;vz(t.get(h[0],e))?o[0]=d.toGlobalCoord(d.getExtent()[n?0:1]):vz(t.get(h[1],e))&&(o[1]=f.toGlobalCoord(f.getExtent()[n?0:1]))}isNaN(l)||(o[0]=l),isNaN(u)||(o[1]=u)}else o=[l,u];t.setItemLayout(e,o)}var bz=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n}return n(e,t),e.prototype.updateTransform=function(t,e,n){e.eachSeries((function(t){var e=ez.getMarkerModelFromSeries(t,"markLine");if(e){var i=e.getData(),r=gz(e).from,o=gz(e).to;r.each((function(e){xz(r,e,!0,t,n),xz(o,e,!1,t,n)})),i.each((function(t){i.setItemLayout(t,[r.getItemLayout(t),o.getItemLayout(t)])})),this.markerGroupMap.get(t.id).updateLayout()}}),this)},e.prototype.renderSeries=function(t,e,n,i){var r=t.coordinateSystem,o=t.id,a=t.getData(),s=this.markerGroupMap,l=s.get(o)||s.set(o,new dC);this.group.add(l.group);var u=function(t,e,n){var i;i=t?O(t&&t.dimensions,(function(t){return T({name:t},e.getData().getDimensionInfo(e.getData().mapDimension(t))||{})})):[{name:"value",type:"float"}];var r=new Pm(i,n),o=new Pm(i,n),a=new Pm([],n),s=O(n.get("data"),V(yz,e,t,n));t&&(s=N(s,V(_z,t)));var l=t?lz:function(t){return t.value};return r.initData(O(s,(function(t){return t[0]})),null,l),o.initData(O(s,(function(t){return t[1]})),null,l),a.initData(O(s,(function(t){return t[2]}))),a.hasItemOption=!0,{from:r,to:o,line:a}}(r,t,e),h=u.from,c=u.to,p=u.line;gz(e).from=h,gz(e).to=c,e.setData(p);var d=e.get("symbol"),f=e.get("symbolSize");function g(e,n,r){var o=e.getItemModel(n);xz(e,n,r,t,i);var s=o.getModel("itemStyle").getItemStyle();null==s.fill&&(s.fill=dg(a,"color")),e.setItemVisual(n,{symbolRotate:o.get("symbolRotate"),symbolSize:o.get("symbolSize")||f[r?0:1],symbol:o.get("symbol",!0)||d[r?0:1],style:s})}F(d)||(d=[d,d]),F(f)||(f=[f,f]),u.from.each((function(t){g(h,t,!0),g(c,t,!1)})),p.each((function(t){var e=p.getItemModel(t).getModel("lineStyle").getLineStyle();p.setItemLayout(t,[h.getItemLayout(t),c.getItemLayout(t)]),null==e.stroke&&(e.stroke=h.getItemVisual(t,"style").fill),p.setItemVisual(t,{fromSymbolRotate:h.getItemVisual(t,"symbolRotate"),fromSymbolSize:h.getItemVisual(t,"symbolSize"),fromSymbol:h.getItemVisual(t,"symbol"),toSymbolRotate:c.getItemVisual(t,"symbolRotate"),toSymbolSize:c.getItemVisual(t,"symbolSize"),toSymbol:c.getItemVisual(t,"symbol"),style:e})})),l.updateData(p),u.line.eachItemGraphicEl((function(t,n){t.traverse((function(t){ys(t).dataModel=e}))})),this.markKeep(l),l.group.silent=e.get("silent")||t.get("silent")},e.type="markLine",e}(cz);var wz=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n}return n(e,t),e.prototype.createMarkerModelFromSeries=function(t,n,i){return new e(t,n,i)},e.type="markArea",e.defaultOption={zlevel:0,z:1,tooltip:{trigger:"item"},animation:!1,label:{show:!0,position:"top"},itemStyle:{borderWidth:0},emphasis:{label:{show:!0,position:"top"}}},e}(ez),Sz=Lr(),Mz=function(t,e,n,i){var r=oz(t,i[0]),o=oz(t,i[1]),a=r.coord,s=o.coord;a[0]=Q(a[0],-1/0),a[1]=Q(a[1],-1/0),s[0]=Q(s[0],1/0),s[1]=Q(s[1],1/0);var l=M([{},r,o]);return l.coord=[r.coord,o.coord],l.x0=r.x,l.y0=r.y,l.x1=o.x,l.y1=o.y,l};function Iz(t){return!isNaN(t)&&!isFinite(t)}function Tz(t,e,n,i){var r=1-t;return Iz(e[r])&&Iz(n[r])}function Cz(t,e){var n=e.coord[0],i=e.coord[1];return!!(Wb(t,"cartesian2d")&&n&&i&&(Tz(1,n,i)||Tz(0,n,i)))||(sz(t,{coord:n,x:e.x0,y:e.y0})||sz(t,{coord:i,x:e.x1,y:e.y1}))}function Az(t,e,n,i,r){var o,a=i.coordinateSystem,s=t.getItemModel(e),l=Zi(s.get(n[0]),r.getWidth()),u=Zi(s.get(n[1]),r.getHeight());if(isNaN(l)||isNaN(u)){if(i.getMarkerPosition)o=i.getMarkerPosition(t.getValues(n,e));else{var h=[d=t.get(n[0],e),f=t.get(n[1],e)];a.clampData&&a.clampData(h,h),o=a.dataToPoint(h,!0)}if(Wb(a,"cartesian2d")){var c=a.getAxis("x"),p=a.getAxis("y"),d=t.get(n[0],e),f=t.get(n[1],e);Iz(d)?o[0]=c.toGlobalCoord(c.getExtent()["x0"===n[0]?0:1]):Iz(f)&&(o[1]=p.toGlobalCoord(p.getExtent()["y0"===n[1]?0:1]))}isNaN(l)||(o[0]=l),isNaN(u)||(o[1]=u)}else o=[l,u];return o}var Dz=[["x0","y0"],["x1","y0"],["x1","y1"],["x0","y1"]],Lz=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n}return n(e,t),e.prototype.updateTransform=function(t,e,n){e.eachSeries((function(t){var e=ez.getMarkerModelFromSeries(t,"markArea");if(e){var i=e.getData();i.each((function(e){var r=O(Dz,(function(r){return Az(i,e,r,t,n)}));i.setItemLayout(e,r),i.getItemGraphicEl(e).setShape("points",r)}))}}),this)},e.prototype.renderSeries=function(t,e,n,i){var r=t.coordinateSystem,o=t.id,a=t.getData(),s=this.markerGroupMap,l=s.get(o)||s.set(o,{group:new zi});this.group.add(l.group),this.markKeep(l);var u=function(t,e,n){var i,r,o=["x0","y0","x1","y1"];t?(i=O(t&&t.dimensions,(function(t){var n=e.getData();return T({name:t},n.getDimensionInfo(n.mapDimension(t))||{})})),r=new Pm(O(o,(function(t,e){return{name:t,type:i[e%2].type}})),n)):r=new Pm(i=[{name:"value",type:"float"}],n);var a=O(n.get("data"),V(Mz,e,t,n));t&&(a=N(a,V(Cz,t)));var s=t?function(t,e,n,i){return t.coord[Math.floor(i/2)][i%2]}:function(t){return t.value};return r.initData(a,null,s),r.hasItemOption=!0,r}(r,t,e);e.setData(u),u.each((function(e){var n=O(Dz,(function(n){return Az(u,e,n,t,i)})),o=!0;P(Dz,(function(t){if(o){var n=u.get(t[0],e),i=u.get(t[1],e);(Iz(n)||r.getAxis("x").containData(n))&&(Iz(i)||r.getAxis("y").containData(i))&&(o=!1)}})),u.setItemLayout(e,{points:n,allClipped:o});var s=u.getItemModel(e).getModel("itemStyle").getItemStyle(),l=dg(a,"color");s.fill||(s.fill=l,"string"==typeof s.fill&&(s.fill=on(s.fill,.4))),s.stroke||(s.stroke=l),u.setItemVisual(e,"style",s)})),u.diff(Sz(l).data).add((function(t){var e=u.getItemLayout(t);if(!e.allClipped){var n=new ql({shape:{points:e.points}});u.setItemGraphicEl(t,n),l.group.add(n)}})).update((function(t,n){var i=Sz(l).data.getItemGraphicEl(n),r=u.getItemLayout(t);r.allClipped?i&&l.group.remove(i):(i?Ou(i,{shape:{points:r.points}},e,t):i=new ql({shape:{points:r.points}}),u.setItemGraphicEl(t,i),l.group.add(i))})).remove((function(t){var e=Sz(l).data.getItemGraphicEl(t);l.group.remove(e)})).execute(),u.eachItemGraphicEl((function(t,n){var i=u.getItemModel(n),r=u.getItemVisual(n,"style");t.useStyle(u.getItemVisual(n,"style")),th(t,eh(i),{labelFetcher:e,labelDataIndex:n,defaultText:u.getName(n)||"",inheritColor:"string"==typeof r.fill?on(r.fill,1):"#000"}),nl(t,i),Js(t),ys(t).dataModel=e})),Sz(l).data=u,l.group.silent=e.get("silent")||t.get("silent")},e.type="markArea",e}(cz);var kz=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n.layoutMode={type:"box",ignoreSize:!0},n}return n(e,t),e.prototype.init=function(t,e,n){this.mergeDefaultAndTheme(t,n),t.selected=t.selected||{},this._updateSelector(t)},e.prototype.mergeOption=function(e,n){t.prototype.mergeOption.call(this,e,n),this._updateSelector(e)},e.prototype._updateSelector=function(t){var e=t.selector,n=this.ecModel;!0===e&&(e=t.selector=["all","inverse"]),F(e)&&P(e,(function(t,i){H(t)&&(t={type:t}),e[i]=S(t,function(t,e){return"all"===e?{type:"all",title:t.getLocale(["legend","selector","all"])}:"inverse"===e?{type:"inverse",title:t.getLocale(["legend","selector","inverse"])}:void 0}(n,t.type))}))},e.prototype.optionUpdated=function(){this._updateData(this.ecModel);var t=this._data;if(t[0]&&"single"===this.get("selectedMode")){for(var e=!1,n=0;n=0},e.prototype.getOrient=function(){return"vertical"===this.get("orient")?{index:1,name:"vertical"}:{index:0,name:"horizontal"}},e.type="legend.plain",e.dependencies=["series"],e.defaultOption={zlevel:0,z:4,show:!0,orient:"horizontal",left:"center",top:0,align:"auto",backgroundColor:"rgba(0,0,0,0)",borderColor:"#ccc",borderRadius:0,borderWidth:0,padding:5,itemGap:10,itemWidth:25,itemHeight:14,inactiveColor:"#ccc",inactiveBorderColor:"#ccc",itemStyle:{borderWidth:0},textStyle:{color:"#333"},selectedMode:!0,selector:!1,selectorLabel:{show:!0,borderRadius:10,padding:[3,5,3,5],fontSize:12,fontFamily:" sans-serif",color:"#666",borderWidth:1,borderColor:"#666"},emphasis:{selectorLabel:{show:!0,color:"#eee",backgroundColor:"#666"}},selectorPosition:"auto",selectorItemGap:7,selectorButtonGap:10,tooltip:{show:!1}},e}(Nc),Pz=V,Oz=P,Rz=zi,Nz=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n.newlineDisabled=!1,n}return n(e,t),e.prototype.init=function(){this.group.add(this._contentGroup=new Rz),this.group.add(this._selectorGroup=new Rz),this._isFirstRender=!0},e.prototype.getContentGroup=function(){return this._contentGroup},e.prototype.getSelectorGroup=function(){return this._selectorGroup},e.prototype.render=function(t,e,n){var i=this._isFirstRender;if(this._isFirstRender=!1,this.resetInner(),t.get("show",!0)){var r=t.get("align"),o=t.get("orient");r&&"auto"!==r||(r="right"===t.get("left")&&"vertical"===o?"right":"left");var a=t.get("selector",!0),s=t.get("selectorPosition",!0);!a||s&&"auto"!==s||(s="horizontal"===o?"end":"start"),this.renderInner(r,t,e,n,a,o,s);var l=t.getBoxLayoutParams(),u={width:n.getWidth(),height:n.getHeight()},h=t.get("padding"),c=Ac(l,u,h),p=this.layoutInner(t,r,c,i,a,s),d=Ac(T({width:p.width,height:p.height},l),u,h);this.group.x=d.x-p.x,this.group.y=d.y-p.y,this.group.markRedraw(),this.group.add(this._backgroundEl=fN(p,t))}},e.prototype.resetInner=function(){this.getContentGroup().removeAll(),this._backgroundEl&&this.group.remove(this._backgroundEl),this.getSelectorGroup().removeAll()},e.prototype.renderInner=function(t,e,n,i,r,o,a){var s=this.getContentGroup(),l=ht(),u=e.get("selectedMode"),h=[];n.eachRawSeries((function(t){!t.get("legendHoverLink")&&h.push(t.id)})),Oz(e.getData(),(function(r,o){var a=r.get("name");if(!this.newlineDisabled&&(""===a||"\n"===a)){var c=new Rz;return c.newline=!0,void s.add(c)}var p=n.getSeriesByName(a)[0];if(!l.get(a)){if(p){var d=p.getData(),f=d.getVisual("style"),g=f[d.getVisual("drawType")]||f.fill,y=f.stroke,v=f.decal,m=d.getVisual("legendSymbol")||"roundRect",_=d.getVisual("symbol");this._createItem(a,o,r,e,m,_,t,g,y,v,u).on("click",Pz(zz,a,null,i,h)).on("mouseover",Pz(Vz,p.name,null,i,h)).on("mouseout",Pz(Fz,p.name,null,i,h)),l.set(a,!0)}else n.eachRawSeries((function(n){if(!l.get(a)&&n.legendVisualProvider){var s=n.legendVisualProvider;if(!s.containName(a))return;var c=s.indexOfName(a),p=s.getItemVisual(c,"style"),d=p.stroke,f=p.decal,g=p.fill,y=qe(p.fill);y&&0===y[3]&&(y[3]=.2,g=an(y,"rgba"));this._createItem(a,o,r,e,"roundRect",null,t,g,d,f,u).on("click",Pz(zz,null,a,i,h)).on("mouseover",Pz(Vz,null,a,i,h)).on("mouseout",Pz(Fz,null,a,i,h)),l.set(a,!0)}}),this);0}}),this),r&&this._createSelector(r,e,i,o,a)},e.prototype._createSelector=function(t,e,n,i,r){var o=this.getSelectorGroup();Oz(t,(function(t){var i=t.type,r=new ls({style:{x:0,y:0,align:"center",verticalAlign:"middle"},onclick:function(){n.dispatchAction({type:"all"===i?"legendAllSelect":"legendInverseSelect"})}});o.add(r),th(r,{normal:e.getModel("selectorLabel"),emphasis:e.getModel(["emphasis","selectorLabel"])},{defaultText:t.title}),Js(r)}))},e.prototype._createItem=function(t,e,n,i,r,o,a,s,l,u,h){var c=i.get("itemWidth"),p=i.get("itemHeight"),d=i.get("inactiveColor"),f=i.get("inactiveBorderColor"),g=i.get("symbolKeepAspect"),y=i.getModel("itemStyle"),v=i.isSelected(t),m=new Rz,_=n.getModel("textStyle"),x=n.get("icon"),b=n.getModel("tooltip"),w=b.parentModel,S=uy(r=x||r,0,0,c,p,v?s:d,null==g||g);if(m.add(Ez(S,r,y,l,f,u,v)),!x&&o&&(o!==r||"none"===o)){var M=.8*p;"none"===o&&(o="circle");var T=uy(o,(c-M)/2,(p-M)/2,M,M,v?s:d,null==g||g);m.add(Ez(T,o,y,l,f,u,v))}var C="left"===a?c+5:-5,A=a,D=i.get("formatter"),L=t;"string"==typeof D&&D?L=D.replace("{name}",null!=t?t:""):"function"==typeof D&&(L=D(t)),m.add(new ls({style:nh(_,{text:L,x:C,y:p/2,fill:v?_.getTextColor():d,align:A,verticalAlign:"middle"})}));var k=new os({shape:m.getBoundingRect(),invisible:!0});if(b.get("show")){var P={componentType:"legend",legendIndex:i.componentIndex,name:t,$vars:["name"]};k.tooltip=I({content:t,formatter:w.get("formatter",!0)||function(t){return t.name},formatterParams:P},b.option)}return m.add(k),m.eachChild((function(t){t.silent=!0})),k.silent=!h,this.getContentGroup().add(m),Js(m),m.__legendDataIndex=e,m},e.prototype.layoutInner=function(t,e,n,i,r,o){var a=this.getContentGroup(),s=this.getSelectorGroup();Cc(t.get("orient"),a,t.get("itemGap"),n.width,n.height);var l=a.getBoundingRect(),u=[-l.x,-l.y];if(s.markRedraw(),a.markRedraw(),r){Cc("horizontal",s,t.get("selectorItemGap",!0));var h=s.getBoundingRect(),c=[-h.x,-h.y],p=t.get("selectorButtonGap",!0),d=t.getOrient().index,f=0===d?"width":"height",g=0===d?"height":"width",y=0===d?"y":"x";"end"===o?c[d]+=l[f]+p:u[d]+=h[f]+p,c[1-d]+=l[g]/2-h[g]/2,s.x=c[0],s.y=c[1],a.x=u[0],a.y=u[1];var v={x:0,y:0};return v[f]=l[f]+p+h[f],v[g]=Math.max(l[g],h[g]),v[y]=Math.min(0,h[y]+c[1-d]),v}return a.x=u[0],a.y=u[1],this.group.getBoundingRect()},e.prototype.remove=function(){this.getContentGroup().removeAll(),this._isFirstRender=!0},e.type="legend.plain",e}(pf);function Ez(t,e,n,i,r,o,a){var s;return"line"!==e&&e.indexOf("empty")<0?(s=n.getItemStyle(),t.style.stroke=i,t.style.decal=o,a||(s.stroke=r)):s=n.getItemStyle(["borderWidth","borderColor"]),t.setStyle(s),t}function zz(t,e,n,i){Fz(t,e,n,i),n.dispatchAction({type:"legendToggleSelect",name:null!=t?t:e}),Vz(t,e,n,i)}function Bz(t){for(var e,n=t.getZr().storage.getDisplayList(),i=0,r=n.length;in[r],f=[-c.x,-c.y];e||(f[i]=l[s]);var g=[0,0],y=[-p.x,-p.y],v=tt(t.get("pageButtonGap",!0),t.get("itemGap",!0));d&&("end"===t.get("pageButtonPosition",!0)?y[i]+=n[r]-p[r]:g[i]+=p[r]+v);y[1-i]+=c[o]/2-p[o]/2,l.setPosition(f),u.setPosition(g),h.setPosition(y);var m={x:0,y:0};if(m[r]=d?n[r]:c[r],m[o]=Math.max(c[o],p[o]),m[a]=Math.min(0,p[a]+y[1-i]),u.__rectSize=n[r],d){var _={x:0,y:0};_[r]=Math.max(n[r]-p[r]-v,0),_[o]=m[o],u.setClipPath(new os({shape:_})),u.__rectSize=_[r]}else h.eachChild((function(t){t.attr({invisible:!0,silent:!0})}));var x=this._getPageInfo(t);return null!=x.pageIndex&&Ou(l,{x:x.contentPosition[0],y:x.contentPosition[1]},d?t:null),this._updatePageInfoView(t,x),m},e.prototype._pageGo=function(t,e,n){var i=this._getPageInfo(e)[t];null!=i&&n.dispatchAction({type:"legendScroll",scrollDataIndex:i,legendId:e.id})},e.prototype._updatePageInfoView=function(t,e){var n=this._controllerGroup;P(["pagePrev","pageNext"],(function(i){var r=null!=e[i+"DataIndex"],o=n.childOfName(i);o&&(o.setStyle("fill",r?t.get("pageIconColor",!0):t.get("pageIconInactiveColor",!0)),o.cursor=r?"pointer":"default")}));var i=n.childOfName("pageText"),r=t.get("pageFormatter"),o=e.pageIndex,a=null!=o?o+1:0,s=e.pageCount;i&&r&&i.setStyle("text",H(r)?r.replace("{current}",null==a?"":a+"").replace("{total}",null==s?"":s+""):r({current:a,total:s}))},e.prototype._getPageInfo=function(t){var e=t.get("scrollDataIndex",!0),n=this.getContentGroup(),i=this._containerGroup.__rectSize,r=t.getOrient().index,o=Zz[r],a=jz[r],s=this._findTargetItemIndex(e),l=n.children(),u=l[s],h=l.length,c=h?1:0,p={contentPosition:[n.x,n.y],pageCount:c,pageIndex:c-1,pagePrevDataIndex:null,pageNextDataIndex:null};if(!u)return p;var d=m(u);p.contentPosition[r]=-d.s;for(var f=s+1,g=d,y=d,v=null;f<=h;++f)(!(v=m(l[f]))&&y.e>g.s+i||v&&!_(v,g.s))&&(g=y.i>g.i?y:v)&&(null==p.pageNextDataIndex&&(p.pageNextDataIndex=g.i),++p.pageCount),y=v;for(f=s-1,g=d,y=d,v=null;f>=-1;--f)(v=m(l[f]))&&_(y,v.s)||!(g.i=e&&t.s<=e+i}},e.prototype._findTargetItemIndex=function(t){return this._showController?(this.getContentGroup().eachChild((function(i,r){var o=i.__legendDataIndex;null==n&&null!=o&&(n=r),o===t&&(e=r)})),null!=e?e:n):0;var e,n},e.type="legend.scroll",e}(Nz);function Kz(t){em(Wz),t.registerComponentModel(Yz),t.registerComponentView(qz),function(t){t.registerAction("legendScroll","legendscroll",(function(t,e){var n=t.scrollDataIndex;null!=n&&e.eachComponent({mainType:"legend",subType:"scroll",query:t},(function(t){t.setScrollDataIndex(n)}))}))}(t)}var $z=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n}return n(e,t),e.type="dataZoom.inside",e.defaultOption=Th($R.defaultOption,{disabled:!1,zoomLock:!1,zoomOnMouseWheel:!0,moveOnMouseMove:!0,moveOnMouseWheel:!1,preventDefaultMouseMove:!0}),e}($R),Jz=Lr();function Qz(t,e,n){Jz(t).coordSysRecordMap.each((function(t){var i=t.dataZoomInfoMap.get(e.uid);i&&(i.getRange=n)}))}function tB(t,e){if(e){t.removeKey(e.model.uid);var n=e.controller;n&&n.dispose()}}function eB(t,e){t.dispatchAction({type:"dataZoom",animation:{easing:"cubicOut",duration:100},batch:e})}function nB(t,e,n,i){return t.coordinateSystem.containPoint([n,i])}function iB(t){t.registerProcessor(t.PRIORITY.PROCESSOR.FILTER,(function(t,e){var n=Jz(e),i=n.coordSysRecordMap||(n.coordSysRecordMap=ht());i.each((function(t){t.dataZoomInfoMap=null})),t.eachComponent({mainType:"dataZoom",subType:"inside"},(function(t){P(qR(t).infoList,(function(n){var r=n.model.uid,o=i.get(r)||i.set(r,function(t,e){var n={model:e,containsPoint:V(nB,e),dispatchAction:V(eB,t),dataZoomInfoMap:null,controller:null},i=n.controller=new QS(t.getZr());return P(["pan","zoom","scrollMove"],(function(t){i.on(t,(function(e){var i=[];n.dataZoomInfoMap.each((function(r){if(e.isAvailableBehavior(r.model.option)){var o=(r.getRange||{})[t],a=o&&o(r.dzReferCoordSysInfo,n.model.mainType,n.controller,e);!r.model.get("disabled",!0)&&a&&i.push({dataZoomId:r.model.id,start:a[0],end:a[1]})}})),i.length&&n.dispatchAction(i)}))})),n}(e,n.model));(o.dataZoomInfoMap||(o.dataZoomInfoMap=ht())).set(t.uid,{dzReferCoordSysInfo:n,model:t,getRange:null})}))})),i.each((function(t){var e,n=t.controller,r=t.dataZoomInfoMap;if(r){var o=r.keys()[0];null!=o&&(e=r.get(o))}if(e){var a=function(t){var e,n="type_",i={type_true:2,type_move:1,type_false:0,type_undefined:-1},r=!0;return t.each((function(t){var o=t.model,a=!o.get("disabled",!0)&&(!o.get("zoomLock",!0)||"move");i[n+a]>i[n+e]&&(e=a),r=r&&o.get("preventDefaultMouseMove",!0)})),{controlType:e,opt:{zoomOnMouseWheel:!0,moveOnMouseMove:!0,moveOnMouseWheel:!0,preventDefaultMouseMove:!!r}}}(r);n.enable(a.controlType,a.opt),n.setPointerChecker(t.containsPoint),Tf(t,"dispatchAction",e.model.get("throttle",!0),"fixRate")}else tB(i,t)}))}))}var rB=function(t){function e(){var e=null!==t&&t.apply(this,arguments)||this;return e.type="dataZoom.inside",e}return n(e,t),e.prototype.render=function(e,n,i){t.prototype.render.apply(this,arguments),e.noTarget()?this._clear():(this.range=e.getPercentRange(),Qz(i,e,{pan:B(oB.pan,this),zoom:B(oB.zoom,this),scrollMove:B(oB.scrollMove,this)}))},e.prototype.dispose=function(){this._clear(),t.prototype.dispose.apply(this,arguments)},e.prototype._clear=function(){!function(t,e){for(var n=Jz(t).coordSysRecordMap,i=n.keys(),r=0;r0?s.pixelStart+s.pixelLength-s.pixel:s.pixel-s.pixelStart)/s.pixelLength*(o[1]-o[0])+o[0],u=Math.max(1/i.scale,0);o[0]=(o[0]-l)*u+l,o[1]=(o[1]-l)*u+l;var h=this.dataZoomModel.findRepresentativeAxisProxy().getMinMaxSpan();return sA(0,o,[0,100],0,h.minSpan,h.maxSpan),this.range=o,r[0]!==o[0]||r[1]!==o[1]?o:void 0}},pan:aB((function(t,e,n,i,r,o){var a=sB[i]([o.oldX,o.oldY],[o.newX,o.newY],e,r,n);return a.signal*(t[1]-t[0])*a.pixel/a.pixelLength})),scrollMove:aB((function(t,e,n,i,r,o){return sB[i]([0,0],[o.scrollDelta,o.scrollDelta],e,r,n).signal*(t[1]-t[0])*o.scrollDelta}))};function aB(t){return function(e,n,i,r){var o=this.range,a=o.slice(),s=e.axisModels[0];if(s)return sA(t(a,s,e,n,i,r),a,[0,100],"all"),this.range=a,o[0]!==a[0]||o[1]!==a[1]?a:void 0}}var sB={grid:function(t,e,n,i,r){var o=n.axis,a={},s=r.model.coordinateSystem.getRect();return t=t||[0,0],"x"===o.dim?(a.pixel=e[0]-t[0],a.pixelLength=s.width,a.pixelStart=s.x,a.signal=o.inverse?1:-1):(a.pixel=e[1]-t[1],a.pixelLength=s.height,a.pixelStart=s.y,a.signal=o.inverse?-1:1),a},polar:function(t,e,n,i,r){var o=n.axis,a={},s=r.model.coordinateSystem,l=s.getRadiusAxis().getExtent(),u=s.getAngleAxis().getExtent();return t=t?s.pointToCoord(t):[0,0],e=s.pointToCoord(e),"radiusAxis"===n.mainType?(a.pixel=e[0]-t[0],a.pixelLength=l[1]-l[0],a.pixelStart=l[0],a.signal=o.inverse?1:-1):(a.pixel=e[1]-t[1],a.pixelLength=u[1]-u[0],a.pixelStart=u[0],a.signal=o.inverse?-1:1),a},singleAxis:function(t,e,n,i,r){var o=n.axis,a=r.model.coordinateSystem.getRect(),s={};return t=t||[0,0],"horizontal"===o.orient?(s.pixel=e[0]-t[0],s.pixelLength=a.width,s.pixelStart=a.x,s.signal=o.inverse?1:-1):(s.pixel=e[1]-t[1],s.pixelLength=a.height,s.pixelStart=a.y,s.signal=o.inverse?-1:1),s}};function lB(t){sN(t),t.registerComponentModel($z),t.registerComponentView(rB),iB(t)}var uB=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n}return n(e,t),e.type="dataZoom.slider",e.layoutMode="box",e.defaultOption=Th($R.defaultOption,{show:!0,right:"ph",top:"ph",width:"ph",height:"ph",left:null,bottom:null,borderColor:"#d2dbee",borderRadius:3,backgroundColor:"rgba(47,69,84,0)",dataBackground:{lineStyle:{color:"#d2dbee",width:.5},areaStyle:{color:"#d2dbee",opacity:.2}},selectedDataBackground:{lineStyle:{color:"#8fb0f7",width:.5},areaStyle:{color:"#8fb0f7",opacity:.2}},fillerColor:"rgba(135,175,274,0.2)",handleIcon:"path://M-9.35,34.56V42m0-40V9.5m-2,0h4a2,2,0,0,1,2,2v21a2,2,0,0,1-2,2h-4a2,2,0,0,1-2-2v-21A2,2,0,0,1-11.35,9.5Z",handleSize:"100%",handleStyle:{color:"#fff",borderColor:"#ACB8D1"},moveHandleSize:7,moveHandleIcon:"path://M-320.9-50L-320.9-50c18.1,0,27.1,9,27.1,27.1V85.7c0,18.1-9,27.1-27.1,27.1l0,0c-18.1,0-27.1-9-27.1-27.1V-22.9C-348-41-339-50-320.9-50z M-212.3-50L-212.3-50c18.1,0,27.1,9,27.1,27.1V85.7c0,18.1-9,27.1-27.1,27.1l0,0c-18.1,0-27.1-9-27.1-27.1V-22.9C-239.4-41-230.4-50-212.3-50z M-103.7-50L-103.7-50c18.1,0,27.1,9,27.1,27.1V85.7c0,18.1-9,27.1-27.1,27.1l0,0c-18.1,0-27.1-9-27.1-27.1V-22.9C-130.9-41-121.8-50-103.7-50z",moveHandleStyle:{color:"#D2DBEE",opacity:.7},showDetail:!0,showDataShadow:"auto",realtime:!0,zoomLock:!1,textStyle:{color:"#6E7079"},brushSelect:!0,brushStyle:{color:"rgba(135,175,274,0.15)"},emphasis:{handleStyle:{borderColor:"#8FB0F7"},moveHandleStyle:{color:"#8FB0F7"}}}),e}($R),hB=os,cB="horizontal",pB="vertical",dB=["line","bar","candlestick","scatter"],fB={easing:"cubicOut",duration:100},gB=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n._displayables={},n}return n(e,t),e.prototype.init=function(t,e){this.api=e,this._onBrush=B(this._onBrush,this),this._onBrushEnd=B(this._onBrushEnd,this)},e.prototype.render=function(e,n,i,r){if(t.prototype.render.apply(this,arguments),Tf(this,"_dispatchZoomAction",e.get("throttle"),"fixRate"),this._orient=e.getOrient(),!1!==e.get("show")){if(e.noTarget())return this._clear(),void this.group.removeAll();r&&"dataZoom"===r.type&&r.from===this.uid||this._buildView(),this._updateView()}else this.group.removeAll()},e.prototype.dispose=function(){this._clear(),t.prototype.dispose.apply(this,arguments)},e.prototype._clear=function(){var t,e,n;(n=(t=this)[e="_dispatchZoomAction"])&&n[wf]&&(t[e]=n[wf]);var i=this.api.getZr();i.off("mousemove",this._onBrush),i.off("mouseup",this._onBrushEnd)},e.prototype._buildView=function(){var t=this.group;t.removeAll(),this._brushing=!1,this._displayables.brushRect=null,this._resetLocation(),this._resetInterval();var e=this._displayables.sliderGroup=new zi;this._renderBackground(),this._renderHandle(),this._renderDataShadow(),t.add(e),this._positionGroup()},e.prototype._resetLocation=function(){var t=this.dataZoomModel,e=this.api,n=t.get("brushSelect")?7:0,i=this._findCoordRect(),r={width:e.getWidth(),height:e.getHeight()},o=this._orient===cB?{right:r.width-i.x-i.width,top:r.height-30-7-n,width:i.width,height:30}:{right:7,top:i.y,width:30,height:i.height},a=Pc(t.option);P(["right","top","width","height"],(function(t){"ph"===a[t]&&(a[t]=o[t])}));var s=Ac(a,r);this._location={x:s.x,y:s.y},this._size=[s.width,s.height],this._orient===pB&&this._size.reverse()},e.prototype._positionGroup=function(){var t=this.group,e=this._location,n=this._orient,i=this.dataZoomModel.getFirstTargetAxisModel(),r=i&&i.get("inverse"),o=this._displayables.sliderGroup,a=(this._dataShadowInfo||{}).otherAxisInverse;o.attr(n!==cB||r?n===cB&&r?{scaleY:a?1:-1,scaleX:-1}:n!==pB||r?{scaleY:a?-1:1,scaleX:-1,rotation:Math.PI/2}:{scaleY:a?-1:1,scaleX:1,rotation:Math.PI/2}:{scaleY:a?1:-1,scaleX:1});var s=t.getBoundingRect([o]);t.x=e.x-s.x,t.y=e.y-s.y,t.markRedraw()},e.prototype._getViewExtent=function(){return[0,this._size[0]]},e.prototype._renderBackground=function(){var t=this.dataZoomModel,e=this._size,n=this._displayables.sliderGroup,i=t.get("brushSelect");n.add(new hB({silent:!0,shape:{x:0,y:0,width:e[0],height:e[1]},style:{fill:t.get("backgroundColor")},z2:-40}));var r=new hB({shape:{x:0,y:0,width:e[0],height:e[1]},style:{fill:"transparent"},z2:0,onclick:B(this._onClickPanel,this)}),o=this.api.getZr();i?(r.on("mousedown",this._onBrushStart,this),r.cursor="crosshair",o.on("mousemove",this._onBrush),o.on("mouseup",this._onBrushEnd)):(o.off("mousemove",this._onBrush),o.off("mouseup",this._onBrushEnd)),n.add(r)},e.prototype._renderDataShadow=function(){var t=this._dataShadowInfo=this._prepareDataShadowInfo();if(this._displayables.dataShadowSegs=[],t){var e=this._size,n=t.series,i=n.getRawData(),r=n.getShadowDim?n.getShadowDim():t.otherDim;if(null!=r){var o=i.getDataExtent(r),a=.3*(o[1]-o[0]);o=[o[0]-a,o[1]+a];var s,l=[0,e[1]],u=[0,e[0]],h=[[e[0],0],[0,0]],c=[],p=u[1]/(i.count()-1),d=0,f=Math.round(i.count()/e[0]);i.each([r],(function(t,e){if(f>0&&e%f)d+=p;else{var n=null==t||isNaN(t)||""===t,i=n?0:Ui(t,o,l,!0);n&&!s&&e?(h.push([h[h.length-1][0],0]),c.push([c[c.length-1][0],0])):!n&&s&&(h.push([d,0]),c.push([d,0])),h.push([d,i]),c.push([d,i]),d+=p,s=n}}));for(var g=this.dataZoomModel,y=0;y<3;y++){var v=m(1===y);this._displayables.sliderGroup.add(v),this._displayables.dataShadowSegs.push(v)}}}function m(t){var e=g.getModel(t?"selectedDataBackground":"dataBackground"),n=new zi,i=new ql({shape:{points:h},segmentIgnoreThreshold:1,style:e.getModel("areaStyle").getAreaStyle(),silent:!0,z2:-20}),r=new $l({shape:{points:c},segmentIgnoreThreshold:1,style:e.getModel("lineStyle").getLineStyle(),silent:!0,z2:-19});return n.add(i),n.add(r),n}},e.prototype._prepareDataShadowInfo=function(){var t=this.dataZoomModel,e=t.get("showDataShadow");if(!1!==e){var n,i=this.ecModel;return t.eachTargetAxis((function(r,o){P(t.getAxisProxy(r,o).getTargetSeriesModels(),(function(t){if(!(n||!0!==e&&A(dB,t.get("type"))<0)){var a,s=i.getComponent(ZR(r),o).axis,l={x:"y",y:"x",radius:"angle",angle:"radius"}[r],u=t.coordinateSystem;null!=l&&u.getOtherAxis&&(a=u.getOtherAxis(s).inverse),l=t.getData().mapDimension(l),n={thisAxis:s,series:t,thisDim:r,otherDim:l,otherAxisInverse:a}}}),this)}),this),n}},e.prototype._renderHandle=function(){var t=this.group,e=this._displayables,n=e.handles=[null,null],i=e.handleLabels=[null,null],r=this._displayables.sliderGroup,o=this._size,a=this.dataZoomModel,s=this.api,l=a.get("borderRadius")||0,u=a.get("brushSelect"),h=e.filler=new hB({silent:u,style:{fill:a.get("fillerColor")},textConfig:{position:"inside"}});r.add(h),r.add(new hB({silent:!0,subPixelOptimize:!0,shape:{x:0,y:0,width:o[0],height:o[1],r:l},style:{stroke:a.get("dataBackgroundColor")||a.get("borderColor"),lineWidth:1,fill:"rgba(0,0,0,0)"}})),P([0,1],(function(e){var o=a.get("handleIcon");!ay[o]&&o.indexOf("path://")<0&&o.indexOf("image://")<0&&(o="path://"+o);var s=uy(o,-1,0,2,2,null,!0);s.attr({cursor:yB(this._orient),draggable:!0,drift:B(this._onDragMove,this,e),ondragend:B(this._onDragEnd,this),onmouseover:B(this._showDataInfo,this,!0),onmouseout:B(this._showDataInfo,this,!1),z2:5});var l=s.getBoundingRect(),u=a.get("handleSize");this._handleHeight=Zi(u,this._size[1]),this._handleWidth=l.width/l.height*this._handleHeight,s.setStyle(a.getModel("handleStyle").getItemStyle()),s.style.strokeNoScale=!0,s.rectHover=!0,s.ensureState("emphasis").style=a.getModel(["emphasis","handleStyle"]).getItemStyle(),Js(s);var h=a.get("handleColor");null!=h&&(s.style.fill=h),r.add(n[e]=s);var c=a.getModel("textStyle");t.add(i[e]=new ls({silent:!0,invisible:!0,style:{x:0,y:0,text:"",verticalAlign:"middle",align:"center",fill:c.getTextColor(),font:c.getFont()},z2:10}))}),this);var c=h;if(u){var p=Zi(a.get("moveHandleSize"),o[1]),d=e.moveHandle=new os({style:a.getModel("moveHandleStyle").getItemStyle(),silent:!0,shape:{r:[0,0,2,2],y:o[1]-.5,height:p}}),f=.8*p,g=e.moveHandleIcon=uy(a.get("moveHandleIcon"),-f/2,-f/2,f,f,"#fff",!0);g.silent=!0,g.y=o[1]+p/2-.5,d.ensureState("emphasis").style=a.getModel(["emphasis","moveHandleStyle"]).getItemStyle();var y=Math.min(o[1]/2,Math.max(p,10));(c=e.moveZone=new os({invisible:!0,shape:{y:o[1]-y,height:p+y}})).on("mouseover",(function(){s.enterEmphasis(d)})).on("mouseout",(function(){s.leaveEmphasis(d)})),r.add(d),r.add(g),r.add(c)}c.attr({draggable:!0,cursor:yB(this._orient),drift:B(this._onDragMove,this,"all"),ondragstart:B(this._showDataInfo,this,!0),ondragend:B(this._onDragEnd,this),onmouseover:B(this._showDataInfo,this,!0),onmouseout:B(this._showDataInfo,this,!1)})},e.prototype._resetInterval=function(){var t=this._range=this.dataZoomModel.getPercentRange(),e=this._getViewExtent();this._handleEnds=[Ui(t[0],[0,100],e,!0),Ui(t[1],[0,100],e,!0)]},e.prototype._updateInterval=function(t,e){var n=this.dataZoomModel,i=this._handleEnds,r=this._getViewExtent(),o=n.findRepresentativeAxisProxy().getMinMaxSpan(),a=[0,100];sA(e,i,r,n.get("zoomLock")?"all":t,null!=o.minSpan?Ui(o.minSpan,a,r,!0):null,null!=o.maxSpan?Ui(o.maxSpan,a,r,!0):null);var s=this._range,l=this._range=qi([Ui(i[0],r,a,!0),Ui(i[1],r,a,!0)]);return!s||s[0]!==l[0]||s[1]!==l[1]},e.prototype._updateView=function(t){var e=this._displayables,n=this._handleEnds,i=qi(n.slice()),r=this._size;P([0,1],(function(t){var i=e.handles[t],o=this._handleHeight;i.attr({scaleX:o/2,scaleY:o/2,x:n[t]+(t?-1:1),y:r[1]/2-o/2})}),this),e.filler.setShape({x:i[0],y:0,width:i[1]-i[0],height:r[1]});var o={x:i[0],width:i[1]-i[0]};e.moveHandle&&(e.moveHandle.setShape(o),e.moveZone.setShape(o),e.moveZone.getBoundingRect(),e.moveHandleIcon&&e.moveHandleIcon.attr("x",o.x+o.width/2));for(var a=e.dataShadowSegs,s=[0,i[0],i[1],r[0]],l=0;le[0]||n[1]<0||n[1]>e[1])){var i=this._handleEnds,r=(i[0]+i[1])/2,o=this._updateInterval("all",n[0]-r);this._updateView(),o&&this._dispatchZoomAction(!1)}},e.prototype._onBrushStart=function(t){var e=t.offsetX,n=t.offsetY;this._brushStart=new In(e,n),this._brushing=!0,this._brushStartTime=+new Date},e.prototype._onBrushEnd=function(t){if(this._brushing){var e=this._displayables.brushRect;if(this._brushing=!1,e){e.attr("ignore",!0);var n=e.shape;if(!(+new Date-this._brushStartTime<200&&Math.abs(n.width)<5)){var i=this._getViewExtent(),r=[0,100];this._range=qi([Ui(n.x,i,r,!0),Ui(n.x+n.width,i,r,!0)]),this._handleEnds=[n.x,n.x+n.width],this._updateView(),this._dispatchZoomAction(!1)}}}},e.prototype._onBrush=function(t){this._brushing&&(ee(t.event),this._updateBrushRect(t.offsetX,t.offsetY))},e.prototype._updateBrushRect=function(t,e){var n=this._displayables,i=this.dataZoomModel,r=n.brushRect;r||(r=n.brushRect=new hB({silent:!0,style:i.getModel("brushStyle").getItemStyle()}),n.sliderGroup.add(r)),r.attr("ignore",!1);var o=this._brushStart,a=this._displayables.sliderGroup,s=a.transformCoordToLocal(t,e),l=a.transformCoordToLocal(o.x,o.y),u=this._size;s[0]=Math.max(Math.min(u[0],s[0]),0),r.setShape({x:l[0],y:0,width:s[0]-l[0],height:u[1]})},e.prototype._dispatchZoomAction=function(t){var e=this._range;this.api.dispatchAction({type:"dataZoom",from:this.uid,dataZoomId:this.dataZoomModel.id,animation:t?fB:null,start:e[0],end:e[1]})},e.prototype._findCoordRect=function(){var t,e=qR(this.dataZoomModel).infoList;if(!t&&e.length){var n=e[0].model.coordinateSystem;t=n.getRect&&n.getRect()}if(!t){var i=this.api.getWidth(),r=this.api.getHeight();t={x:.2*i,y:.2*r,width:.6*i,height:.6*r}}return t},e.type="dataZoom.slider",e}(tN);function yB(t){return"vertical"===t?"ns-resize":"ew-resize"}function vB(t){t.registerComponentModel(uB),t.registerComponentView(gB),sN(t)}var mB=function(t,e,n){var i=w((_B[t]||{})[e]);return n&&F(i)?i[i.length-1]:i},_B={color:{active:["#006edd","#e0ffff"],inactive:["rgba(0,0,0,0)"]},colorHue:{active:[0,360],inactive:[0,0]},colorSaturation:{active:[.3,1],inactive:[0,0]},colorLightness:{active:[.9,.5],inactive:[0,0]},colorAlpha:{active:[.3,1],inactive:[0,0]},opacity:{active:[.3,1],inactive:[0,0]},symbol:{active:["circle","roundRect","diamond"],inactive:["none"]},symbolSize:{active:[10,50],inactive:[0,0]}},xB=eT.mapVisual,bB=eT.eachVisual,wB=F,SB=P,MB=qi,IB=Ui,TB=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n.stateList=["inRange","outOfRange"],n.replacableOptionKeys=["inRange","outOfRange","target","controller","color"],n.layoutMode={type:"box",ignoreSize:!0},n.dataBound=[-1/0,1/0],n.targetVisuals={},n.controllerVisuals={},n}return n(e,t),e.prototype.init=function(t,e,n){this.mergeDefaultAndTheme(t,n)},e.prototype.optionUpdated=function(t,e){var n=this.option;a.canvasSupported||(n.realtime=!1),!e&&bE(n,t,this.replacableOptionKeys),this.textStyleModel=this.getModel("textStyle"),this.resetItemSize(),this.completeVisualOption()},e.prototype.resetVisual=function(t){var e=this.stateList;t=B(t,this),this.controllerVisuals=xE(this.option.controller,e,t),this.targetVisuals=xE(this.option.target,e,t)},e.prototype.getTargetSeriesIndices=function(){var t=this.option.seriesIndex,e=[];return null==t||"all"===t?this.ecModel.eachSeries((function(t,n){e.push(n)})):e=_r(t),e},e.prototype.eachTargetSeries=function(t,e){P(this.getTargetSeriesIndices(),(function(n){var i=this.ecModel.getSeriesByIndex(n);i&&t.call(e,i)}),this)},e.prototype.isTargetSeries=function(t){var e=!1;return this.eachTargetSeries((function(n){n===t&&(e=!0)})),e},e.prototype.formatValueText=function(t,e,n){var i,r=this.option,o=r.precision,a=this.dataBound,s=r.formatter;n=n||["<",">"],F(t)&&(t=t.slice(),i=!0);var l=e?t:i?[u(t[0]),u(t[1])]:u(t);return H(s)?s.replace("{value}",i?l[0]:l).replace("{value2}",i?l[1]:l):G(s)?i?s(t[0],t[1]):s(t):i?t[0]===a[0]?n[0]+" "+l[1]:t[1]===a[1]?n[1]+" "+l[0]:l[0]+" - "+l[1]:l;function u(t){return t===a[0]?"min":t===a[1]?"max":(+t).toFixed(Math.min(o,20))}},e.prototype.resetExtent=function(){var t=this.option,e=MB([t.min,t.max]);this._dataExtent=e},e.prototype.getDataDimension=function(t){var e=this.option.dimension,n=t.dimensions;if(null!=e||n.length){if(null!=e)return t.getDimension(e);for(var i=t.dimensions,r=i.length-1;r>=0;r--){var o=i[r];if(!t.getDimensionInfo(o).isCalculationCoord)return o}}},e.prototype.getExtent=function(){return this._dataExtent.slice()},e.prototype.completeVisualOption=function(){var t=this.ecModel,e=this.option,n={inRange:e.inRange,outOfRange:e.outOfRange},i=e.target||(e.target={}),r=e.controller||(e.controller={});S(i,n),S(r,n);var o=this.isCategory();function a(n){wB(e.color)&&!n.inRange&&(n.inRange={color:e.color.slice().reverse()}),n.inRange=n.inRange||{color:t.get("gradientColor")}}a.call(this,i),a.call(this,r),function(t,e,n){var i=t[e],r=t[n];i&&!r&&(r=t[n]={},SB(i,(function(t,e){if(eT.isValidType(e)){var n=mB(e,"inactive",o);null!=n&&(r[e]=n,"color"!==e||r.hasOwnProperty("opacity")||r.hasOwnProperty("colorAlpha")||(r.opacity=[0,0]))}})))}.call(this,i,"inRange","outOfRange"),function(t){var e=(t.inRange||{}).symbol||(t.outOfRange||{}).symbol,n=(t.inRange||{}).symbolSize||(t.outOfRange||{}).symbolSize,i=this.get("inactiveColor");SB(this.stateList,(function(r){var a=this.itemSize,s=t[r];s||(s=t[r]={color:o?i:[i]}),null==s.symbol&&(s.symbol=e&&w(e)||(o?"roundRect":["roundRect"])),null==s.symbolSize&&(s.symbolSize=n&&w(n)||(o?a[0]:[a[0],a[0]])),s.symbol=xB(s.symbol,(function(t){return"none"===t||"square"===t?"roundRect":t}));var l=s.symbolSize;if(null!=l){var u=-1/0;bB(l,(function(t){t>u&&(u=t)})),s.symbolSize=xB(l,(function(t){return IB(t,[0,u],[0,a[0]],!0)}))}}),this)}.call(this,r)},e.prototype.resetItemSize=function(){this.itemSize=[parseFloat(this.get("itemWidth")),parseFloat(this.get("itemHeight"))]},e.prototype.isCategory=function(){return!!this.option.categories},e.prototype.setSelected=function(t){},e.prototype.getSelected=function(){return null},e.prototype.getValueState=function(t){return null},e.prototype.getVisualMeta=function(t){return null},e.type="visualMap",e.dependencies=["series"],e.defaultOption={show:!0,zlevel:0,z:4,seriesIndex:"all",min:0,max:200,left:0,right:null,top:null,bottom:0,itemWidth:null,itemHeight:null,inverse:!1,orient:"vertical",backgroundColor:"rgba(0,0,0,0)",borderColor:"#ccc",contentColor:"#5793f3",inactiveColor:"#aaa",borderWidth:0,padding:5,textGap:10,precision:0,textStyle:{color:"#333"}},e}(Nc),CB=[20,140],AB=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n}return n(e,t),e.prototype.optionUpdated=function(e,n){t.prototype.optionUpdated.apply(this,arguments),this.resetExtent(),this.resetVisual((function(t){t.mappingMethod="linear",t.dataExtent=this.getExtent()})),this._resetRange()},e.prototype.resetItemSize=function(){t.prototype.resetItemSize.apply(this,arguments);var e=this.itemSize;(null==e[0]||isNaN(e[0]))&&(e[0]=CB[0]),(null==e[1]||isNaN(e[1]))&&(e[1]=CB[1])},e.prototype._resetRange=function(){var t=this.getExtent(),e=this.option.range;!e||e.auto?(t.auto=1,this.option.range=t):F(e)&&(e[0]>e[1]&&e.reverse(),e[0]=Math.max(e[0],t[0]),e[1]=Math.min(e[1],t[1]))},e.prototype.completeVisualOption=function(){t.prototype.completeVisualOption.apply(this,arguments),P(this.stateList,(function(t){var e=this.option.controller[t].symbolSize;e&&e[0]!==e[1]&&(e[0]=e[1]/3)}),this)},e.prototype.setSelected=function(t){this.option.range=t.slice(),this._resetRange()},e.prototype.getSelected=function(){var t=this.getExtent(),e=qi((this.get("range")||[]).slice());return e[0]>t[1]&&(e[0]=t[1]),e[1]>t[1]&&(e[1]=t[1]),e[0]=n[1]||t<=e[1])?"inRange":"outOfRange"},e.prototype.findTargetDataIndices=function(t){var e=[];return this.eachTargetSeries((function(n){var i=[],r=n.getData();r.each(this.getDataDimension(r),(function(e,n){t[0]<=e&&e<=t[1]&&i.push(n)}),this),e.push({seriesId:n.id,dataIndex:i})}),this),e},e.prototype.getVisualMeta=function(t){var e=DB(this,"outOfRange",this.getExtent()),n=DB(this,"inRange",this.option.range.slice()),i=[];function r(e,n){i.push({value:e,color:t(e,n)})}for(var o=0,a=0,s=n.length,l=e.length;at[1])break;n.push({color:this.getControllerVisual(o,"color",e),offset:r/100})}return n.push({color:this.getControllerVisual(t[1],"color",e),offset:1}),n},e.prototype._createBarPoints=function(t,e){var n=this.visualMapModel.itemSize;return[[n[0]-e[0],t[0]],[n[0],t[0]],[n[0],t[1]],[n[0]-e[1],t[1]]]},e.prototype._createBarGroup=function(t){var e=this._orient,n=this.visualMapModel.get("inverse");return new zi("horizontal"!==e||n?"horizontal"===e&&n?{scaleX:"bottom"===t?-1:1,rotation:-Math.PI/2}:"vertical"!==e||n?{scaleX:"left"===t?1:-1}:{scaleX:"left"===t?1:-1,scaleY:-1}:{scaleX:"bottom"===t?1:-1,rotation:Math.PI/2})},e.prototype._updateHandle=function(t,e){if(this._useHandle){var n=this._shapes,i=this.visualMapModel,r=n.handleThumbs,o=n.handleLabels,a=i.itemSize,s=i.getExtent();NB([0,1],(function(l){var u=r[l];u.setStyle("fill",e.handlesColor[l]),u.y=t[l];var h=RB(t[l],[0,a[1]],s,!0),c=this.getControllerVisual(h,"symbolSize");u.scaleX=u.scaleY=c/a[0],u.x=a[0]-c/2;var p=Fu(n.handleLabelPoints[l],Vu(u,this.group));o[l].setStyle({x:p[0],y:p[1],text:i.formatValueText(this._dataInterval[l]),verticalAlign:"middle",align:"vertical"===this._orient?this._applyTransform("left",n.mainGroup):"center"})}),this)}},e.prototype._showIndicator=function(t,e,n,i){var r=this.visualMapModel,o=r.getExtent(),a=r.itemSize,s=[0,a[1]],l=this._shapes,u=l.indicator;if(u){u.attr("invisible",!1);var h=this.getControllerVisual(t,"color",{convertOpacityToAlpha:!0}),c=this.getControllerVisual(t,"symbolSize"),p=RB(t,o,s,!0),d=a[0]-c/2,f={x:u.x,y:u.y};u.y=p,u.x=d;var g=Fu(l.indicatorLabelPoint,Vu(u,this.group)),y=l.indicatorLabel;y.attr("invisible",!1);var v=this._applyTransform("left",l.mainGroup),m="horizontal"===this._orient;y.setStyle({text:(n||"")+r.formatValueText(e),verticalAlign:m?v:"middle",align:m?"center":v});var _={x:d,y:p,style:{fill:h}},x={style:{x:g[0],y:g[1]}};if(r.ecModel.isAnimationEnabled()&&!this._firstShowIndicator){var b={duration:100,easing:"cubicInOut",additive:!0};u.x=f.x,u.y=f.y,u.animateTo(_,b),y.animateTo(x,b)}else u.attr(_),y.attr(x);this._firstShowIndicator=!1;var w=this._shapes.handleLabels;if(w)for(var S=0;Sr[1]&&(u[1]=1/0),e&&(u[0]===-1/0?this._showIndicator(l,u[1],"< ",a):u[1]===1/0?this._showIndicator(l,u[0],"> ",a):this._showIndicator(l,l,"≈ ",a));var h=this._hoverLinkDataIndices,c=[];(e||FB(n))&&(c=this._hoverLinkDataIndices=n.findTargetDataIndices(u));var p=function(t,e){var n={},i={};return r(t||[],n),r(e||[],i,n),[o(n),o(i)];function r(t,e,n){for(var i=0,r=t.length;i0:t.splitNumber>0)&&!t.calculable?"piecewise":"continuous"})),t.registerAction(HB,WB),P(YB,(function(e){t.registerVisual(t.PRIORITY.VISUAL.COMPONENT,e)})),t.registerPreprocessor(ZB))}function $B(t){t.registerComponentModel(AB),t.registerComponentView(BB),KB(t)}var JB=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n._pieceList=[],n}return n(e,t),e.prototype.optionUpdated=function(e,n){t.prototype.optionUpdated.apply(this,arguments),this.resetExtent();var i=this._mode=this._determineMode();this._pieceList=[],QB[this._mode].call(this,this._pieceList),this._resetSelected(e,n);var r=this.option.categories;this.resetVisual((function(t,e){"categories"===i?(t.mappingMethod="category",t.categories=w(r)):(t.dataExtent=this.getExtent(),t.mappingMethod="piecewise",t.pieceList=O(this._pieceList,(function(t){return t=w(t),"inRange"!==e&&(t.visual=null),t})))}))},e.prototype.completeVisualOption=function(){var e=this.option,n={},i=eT.listVisualTypes(),r=this.isCategory();function o(t,e,n){return t&&t[e]&&t[e].hasOwnProperty(n)}P(e.pieces,(function(t){P(i,(function(e){t.hasOwnProperty(e)&&(n[e]=1)}))})),P(n,(function(t,n){var i=!1;P(this.stateList,(function(t){i=i||o(e,t,n)||o(e.target,t,n)}),this),!i&&P(this.stateList,(function(t){(e[t]||(e[t]={}))[n]=mB(n,"inRange"===t?"active":"inactive",r)}))}),this),t.prototype.completeVisualOption.apply(this,arguments)},e.prototype._resetSelected=function(t,e){var n=this.option,i=this._pieceList,r=(e?n:t).selected||{};if(n.selected=r,P(i,(function(t,e){var n=this.getSelectedMapKey(t);r.hasOwnProperty(n)||(r[n]=!0)}),this),"single"===n.selectedMode){var o=!1;P(i,(function(t,e){var n=this.getSelectedMapKey(t);r[n]&&(o?r[n]=!1:o=!0)}),this)}},e.prototype.getSelectedMapKey=function(t){return"categories"===this._mode?t.value+"":t.index+""},e.prototype.getPieceList=function(){return this._pieceList},e.prototype._determineMode=function(){var t=this.option;return t.pieces&&t.pieces.length>0?"pieces":this.option.categories?"categories":"splitNumber"},e.prototype.setSelected=function(t){this.option.selected=w(t)},e.prototype.getValueState=function(t){var e=eT.findPieceIndex(t,this._pieceList);return null!=e&&this.option.selected[this.getSelectedMapKey(this._pieceList[e])]?"inRange":"outOfRange"},e.prototype.findTargetDataIndices=function(t){var e=[],n=this._pieceList;return this.eachTargetSeries((function(i){var r=[],o=i.getData();o.each(this.getDataDimension(o),(function(e,i){eT.findPieceIndex(e,n)===t&&r.push(i)}),this),e.push({seriesId:i.id,dataIndex:r})}),this),e},e.prototype.getRepresentValue=function(t){var e;if(this.isCategory())e=t.value;else if(null!=t.value)e=t.value;else{var n=t.interval||[];e=n[0]===-1/0&&n[1]===1/0?0:(n[0]+n[1])/2}return e},e.prototype.getVisualMeta=function(t){if(!this.isCategory()){var e=[],n=["",""],i=this,r=this._pieceList.slice();if(r.length){var o=r[0].interval[0];o!==-1/0&&r.unshift({interval:[-1/0,o]}),(o=r[r.length-1].interval[1])!==1/0&&r.push({interval:[o,1/0]})}else r.push({interval:[-1/0,1/0]});var a=-1/0;return P(r,(function(t){var e=t.interval;e&&(e[0]>a&&s([a,e[0]],"outOfRange"),s(e.slice()),a=e[1])}),this),{stops:e,outerColors:n}}function s(r,o){var a=i.getRepresentValue({interval:r});o||(o=i.getValueState(a));var s=t(a,o);r[0]===-1/0?n[0]=s:r[1]===1/0?n[1]=s:e.push({value:r[0],color:s},{value:r[1],color:s})}},e.type="visualMap.piecewise",e.defaultOption=Th(TB.defaultOption,{selected:null,minOpen:!1,maxOpen:!1,align:"auto",itemWidth:20,itemHeight:14,itemSymbol:"roundRect",pieces:null,categories:null,splitNumber:5,selectedMode:"multiple",itemGap:10,hoverLink:!0}),e}(TB),QB={splitNumber:function(t){var e=this.option,n=Math.min(e.precision,20),i=this.getExtent(),r=e.splitNumber;r=Math.max(parseInt(r,10),1),e.splitNumber=r;for(var o=(i[1]-i[0])/r;+o.toFixed(n)!==o&&n<5;)n++;e.precision=n,o=+o.toFixed(n),e.minOpen&&t.push({interval:[-1/0,i[0]],close:[0,0]});for(var a=0,s=i[0];a","≥"][e[0]]];t.text=t.text||this.formatValueText(null!=t.value?t.value:t.interval,!1,n)}),this)}};function tV(t,e){var n=t.inverse;("vertical"===t.orient?!n:n)&&e.reverse()}var eV=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n}return n(e,t),e.prototype.doRender=function(){var t=this.group;t.removeAll();var e=this.visualMapModel,n=e.get("textGap"),i=e.textStyleModel,r=i.getFont(),o=i.getTextColor(),a=this._getItemAlign(),s=e.itemSize,l=this._getViewData(),u=l.endsText,h=Q(e.get("showLabel",!0),!u);u&&this._renderEndsText(t,u[0],s,h,a),P(l.viewPieceList,(function(i){var l=i.piece,u=new zi;u.onclick=B(this._onItemClick,this,l),this._enableHoverLink(u,i.indexInModelPieceList);var c=e.getRepresentValue(l);if(this._createItemSymbol(u,c,[0,0,s[0],s[1]]),h){var p=this.visualMapModel.getValueState(c);u.add(new ls({style:{x:"right"===a?-n:s[0]+n,y:s[1]/2,text:l.text,verticalAlign:"middle",align:a,font:r,fill:o,opacity:"outOfRange"===p?.5:1}}))}t.add(u)}),this),u&&this._renderEndsText(t,u[1],s,h,a),Cc(e.get("orient"),t,e.get("itemGap")),this.renderBackground(t),this.positionGroup(t)},e.prototype._enableHoverLink=function(t,e){var n=this;t.on("mouseover",(function(){return i("highlight")})).on("mouseout",(function(){return i("downplay")}));var i=function(t){var i=n.visualMapModel;i.option.hoverLink&&n.api.dispatchAction({type:t,batch:OB(i.findTargetDataIndices(e),i)})}},e.prototype._getItemAlign=function(){var t=this.visualMapModel,e=t.option;if("vertical"===e.orient)return PB(t,this.api,t.itemSize);var n=e.align;return n&&"auto"!==n||(n="left"),n},e.prototype._renderEndsText=function(t,e,n,i,r){if(e){var o=new zi,a=this.visualMapModel.textStyleModel;o.add(new ls({style:{x:i?"right"===r?n[0]:0:n[0]/2,y:n[1]/2,verticalAlign:"middle",align:i?r:"center",text:e,font:a.getFont(),fill:a.getTextColor()}})),t.add(o)}},e.prototype._getViewData=function(){var t=this.visualMapModel,e=O(t.getPieceList(),(function(t,e){return{piece:t,indexInModelPieceList:e}})),n=t.get("text"),i=t.get("orient"),r=t.get("inverse");return("horizontal"===i?r:!r)?e.reverse():n&&(n=n.slice().reverse()),{viewPieceList:e,endsText:n}},e.prototype._createItemSymbol=function(t,e,n){t.add(uy(this.getControllerVisual(e,"symbol"),n[0],n[1],n[2],n[3],this.getControllerVisual(e,"color")))},e.prototype._onItemClick=function(t){var e=this.visualMapModel,n=e.option,i=w(n.selected),r=e.getSelectedMapKey(t);"single"===n.selectedMode?(i[r]=!0,P(i,(function(t,e){i[e]=e===r}))):i[r]=!i[r],this.api.dispatchAction({type:"selectDataRange",from:this.uid,visualMapId:this.visualMapModel.id,selected:i})},e.type="visualMap.piecewise",e}(LB);function nV(t){t.registerComponentModel(JB),t.registerComponentView(eV),KB(t)}var iV={label:{enabled:!0},decal:{show:!1}},rV=Lr(),oV={};function aV(t,e){var n=t.getModel("aria");if(n.get("enabled")){var i=w(iV);S(i.label,t.getLocaleModel().get("aria"),!1),S(n.option,i,!1),function(){if(n.getModel("decal").get("show")){var e=ht();t.eachSeries((function(t){if(t.useColorPaletteOnData){var n=e.get(t.type);n||(n={},e.set(t.type,n)),rV(t).scope=n}})),t.eachRawSeries((function(e){if(!t.isSeriesFiltered(e))if("function"!=typeof e.enableAriaDecal){var n=e.getData();if(e.useColorPaletteOnData){var i=e.getRawData(),r={},o=rV(e).scope;n.each((function(t){var e=n.getRawIndex(t);r[e]=t}));var a=i.count();i.each((function(t){var s=r[t],l=i.getName(t)||t+"",h=hp(e.ecModel,l,o,a),c=n.getItemVisual(s,"decal");n.setItemVisual(s,"decal",u(c,h))}))}else{var s=hp(e.ecModel,e.name,oV,t.getSeriesCount()),l=n.getVisual("decal");n.setVisual("decal",u(l,s))}}else e.enableAriaDecal();function u(t,e){var n=t?I(I({},e),t):e;return n.dirty=!0,n}}))}}(),function(){var i=t.getLocaleModel().get("aria"),o=n.getModel("label");if(o.option=T(o.option,i),!o.get("enabled"))return;var a=e.getZr().dom;if(o.get("description"))return void a.setAttribute("aria-label",o.get("description"));var s,l=t.getSeriesCount(),u=o.get(["data","maxCount"])||10,h=o.get(["series","maxCount"])||10,c=Math.min(l,h);if(l<1)return;var p=function(){var e=t.get("title");e&&e.length&&(e=e[0]);return e&&e.text}();if(p){var d=o.get(["general","withTitle"]);s=r(d,{title:p})}else s=o.get(["general","withoutTitle"]);var f=[],g=l>1?o.get(["series","multiple","prefix"]):o.get(["series","single","prefix"]);s+=r(g,{seriesCount:l}),t.eachSeries((function(e,n){if(n1?o.get(["series","multiple",a]):o.get(["series","single",a]),{seriesId:e.seriesIndex,seriesName:e.get("name"),seriesType:(_=e.subType,t.getLocaleModel().get(["series","typeNames"])[_]||"自定义图")});var s=e.getData();if(s.count()>u)i+=r(o.get(["data","partialData"]),{displayCnt:u});else i+=o.get(["data","allData"]);for(var h=[],p=0;p":"gt",">=":"gte","=":"eq","!=":"ne","<>":"ne"},uV=function(){function t(t){if(null==(this._condVal=H(t)?new RegExp(t):$(t)?t:null)){var e="";0,yr(e)}}return t.prototype.evaluate=function(t){var e=typeof t;return"string"===e?this._condVal.test(t):"number"===e&&this._condVal.test(t+"")},t}(),hV=function(){function t(){}return t.prototype.evaluate=function(){return this.value},t}(),cV=function(){function t(){}return t.prototype.evaluate=function(){for(var t=this.children,e=0;e + ${item.col1} + ${item.col2} + ${item.col3} + ${item.col4} + ${item.col5} + ${item.col6} + ` + ] + } + + // 12301 呼叫 + var helpCellChartEl = document.getElementById('helpCellChart') + var helpCellChartInit = echarts.init(helpCellChartEl) + var options = helpCellChart(helpCellChartData) + helpCellChartInit.setOption(options) + + window.onresize = function () { + helpCellChartInit.resize(); + ticketsChartInit.resize(); + consumptionChartInit.resize() + touristsFlowChartInit.resize() + totalPeopleChartInit.resize() + carFlowChartInit.resize() + carSpaceNumInit.resize() + } + mapData.map((item, index) => { + if (item.value == 3) { + $('.map_box .city').eq(index).removeClass('orange').addClass('red') + }else if (item.value == 2) { + $('.map_box .city').eq(index).removeClass('red').addClass('orange') + }else if (item.value == 1) { + $('.map_box .city').eq(index).removeClass('red orange') + } + }) +}) \ No newline at end of file diff --git "a/web/118 \346\227\205\346\270\270\346\231\272\346\205\247\344\270\255\345\277\203/static/jquery.js" "b/web/118 \346\227\205\346\270\270\346\231\272\346\205\247\344\270\255\345\277\203/static/jquery.js" new file mode 100644 index 00000000..9b5206bc --- /dev/null +++ "b/web/118 \346\227\205\346\270\270\346\231\272\346\205\247\344\270\255\345\277\203/static/jquery.js" @@ -0,0 +1,10364 @@ +/*! + * jQuery JavaScript Library v3.3.1 + * https://jquery.com/ + * + * Includes Sizzle.js + * https://sizzlejs.com/ + * + * Copyright JS Foundation and other contributors + * Released under the MIT license + * https://jquery.org/license + * + * Date: 2018-01-20T17:24Z + */ +( function( global, factory ) { + + "use strict"; + + if ( typeof module === "object" && typeof module.exports === "object" ) { + + // For CommonJS and CommonJS-like environments where a proper `window` + // is present, execute the factory and get jQuery. + // For environments that do not have a `window` with a `document` + // (such as Node.js), expose a factory as module.exports. + // This accentuates the need for the creation of a real `window`. + // e.g. var jQuery = require("jquery")(window); + // See ticket #14549 for more info. + module.exports = global.document ? + factory( global, true ) : + function( w ) { + if ( !w.document ) { + throw new Error( "jQuery requires a window with a document" ); + } + return factory( w ); + }; + } else { + factory( global ); + } + +// Pass this if window is not defined yet +} )( typeof window !== "undefined" ? window : this, function( window, noGlobal ) { + +// Edge <= 12 - 13+, Firefox <=18 - 45+, IE 10 - 11, Safari 5.1 - 9+, iOS 6 - 9.1 +// throw exceptions when non-strict code (e.g., ASP.NET 4.5) accesses strict mode +// arguments.callee.caller (trac-13335). But as of jQuery 3.0 (2016), strict mode should be common +// enough that all such attempts are guarded in a try block. +"use strict"; + +var arr = []; + +var document = window.document; + +var getProto = Object.getPrototypeOf; + +var slice = arr.slice; + +var concat = arr.concat; + +var push = arr.push; + +var indexOf = arr.indexOf; + +var class2type = {}; + +var toString = class2type.toString; + +var hasOwn = class2type.hasOwnProperty; + +var fnToString = hasOwn.toString; + +var ObjectFunctionString = fnToString.call( Object ); + +var support = {}; + +var isFunction = function isFunction( obj ) { + + // Support: Chrome <=57, Firefox <=52 + // In some browsers, typeof returns "function" for HTML elements + // (i.e., `typeof document.createElement( "object" ) === "function"`). + // We don't want to classify *any* DOM node as a function. + return typeof obj === "function" && typeof obj.nodeType !== "number"; + }; + + +var isWindow = function isWindow( obj ) { + return obj != null && obj === obj.window; + }; + + + + + var preservedScriptAttributes = { + type: true, + src: true, + noModule: true + }; + + function DOMEval( code, doc, node ) { + doc = doc || document; + + var i, + script = doc.createElement( "script" ); + + script.text = code; + if ( node ) { + for ( i in preservedScriptAttributes ) { + if ( node[ i ] ) { + script[ i ] = node[ i ]; + } + } + } + doc.head.appendChild( script ).parentNode.removeChild( script ); + } + + +function toType( obj ) { + if ( obj == null ) { + return obj + ""; + } + + // Support: Android <=2.3 only (functionish RegExp) + return typeof obj === "object" || typeof obj === "function" ? + class2type[ toString.call( obj ) ] || "object" : + typeof obj; +} +/* global Symbol */ +// Defining this global in .eslintrc.json would create a danger of using the global +// unguarded in another place, it seems safer to define global only for this module + + + +var + version = "3.3.1", + + // Define a local copy of jQuery + jQuery = function( selector, context ) { + + // The jQuery object is actually just the init constructor 'enhanced' + // Need init if jQuery is called (just allow error to be thrown if not included) + return new jQuery.fn.init( selector, context ); + }, + + // Support: Android <=4.0 only + // Make sure we trim BOM and NBSP + rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g; + +jQuery.fn = jQuery.prototype = { + + // The current version of jQuery being used + jquery: version, + + constructor: jQuery, + + // The default length of a jQuery object is 0 + length: 0, + + toArray: function() { + return slice.call( this ); + }, + + // Get the Nth element in the matched element set OR + // Get the whole matched element set as a clean array + get: function( num ) { + + // Return all the elements in a clean array + if ( num == null ) { + return slice.call( this ); + } + + // Return just the one element from the set + return num < 0 ? this[ num + this.length ] : this[ num ]; + }, + + // Take an array of elements and push it onto the stack + // (returning the new matched element set) + pushStack: function( elems ) { + + // Build a new jQuery matched element set + var ret = jQuery.merge( this.constructor(), elems ); + + // Add the old object onto the stack (as a reference) + ret.prevObject = this; + + // Return the newly-formed element set + return ret; + }, + + // Execute a callback for every element in the matched set. + each: function( callback ) { + return jQuery.each( this, callback ); + }, + + map: function( callback ) { + return this.pushStack( jQuery.map( this, function( elem, i ) { + return callback.call( elem, i, elem ); + } ) ); + }, + + slice: function() { + return this.pushStack( slice.apply( this, arguments ) ); + }, + + first: function() { + return this.eq( 0 ); + }, + + last: function() { + return this.eq( -1 ); + }, + + eq: function( i ) { + var len = this.length, + j = +i + ( i < 0 ? len : 0 ); + return this.pushStack( j >= 0 && j < len ? [ this[ j ] ] : [] ); + }, + + end: function() { + return this.prevObject || this.constructor(); + }, + + // For internal use only. + // Behaves like an Array's method, not like a jQuery method. + push: push, + sort: arr.sort, + splice: arr.splice +}; + +jQuery.extend = jQuery.fn.extend = function() { + var options, name, src, copy, copyIsArray, clone, + target = arguments[ 0 ] || {}, + i = 1, + length = arguments.length, + deep = false; + + // Handle a deep copy situation + if ( typeof target === "boolean" ) { + deep = target; + + // Skip the boolean and the target + target = arguments[ i ] || {}; + i++; + } + + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target !== "object" && !isFunction( target ) ) { + target = {}; + } + + // Extend jQuery itself if only one argument is passed + if ( i === length ) { + target = this; + i--; + } + + for ( ; i < length; i++ ) { + + // Only deal with non-null/undefined values + if ( ( options = arguments[ i ] ) != null ) { + + // Extend the base object + for ( name in options ) { + src = target[ name ]; + copy = options[ name ]; + + // Prevent never-ending loop + if ( target === copy ) { + continue; + } + + // Recurse if we're merging plain objects or arrays + if ( deep && copy && ( jQuery.isPlainObject( copy ) || + ( copyIsArray = Array.isArray( copy ) ) ) ) { + + if ( copyIsArray ) { + copyIsArray = false; + clone = src && Array.isArray( src ) ? src : []; + + } else { + clone = src && jQuery.isPlainObject( src ) ? src : {}; + } + + // Never move original objects, clone them + target[ name ] = jQuery.extend( deep, clone, copy ); + + // Don't bring in undefined values + } else if ( copy !== undefined ) { + target[ name ] = copy; + } + } + } + } + + // Return the modified object + return target; +}; + +jQuery.extend( { + + // Unique for each copy of jQuery on the page + expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ), + + // Assume jQuery is ready without the ready module + isReady: true, + + error: function( msg ) { + throw new Error( msg ); + }, + + noop: function() {}, + + isPlainObject: function( obj ) { + var proto, Ctor; + + // Detect obvious negatives + // Use toString instead of jQuery.type to catch host objects + if ( !obj || toString.call( obj ) !== "[object Object]" ) { + return false; + } + + proto = getProto( obj ); + + // Objects with no prototype (e.g., `Object.create( null )`) are plain + if ( !proto ) { + return true; + } + + // Objects with prototype are plain iff they were constructed by a global Object function + Ctor = hasOwn.call( proto, "constructor" ) && proto.constructor; + return typeof Ctor === "function" && fnToString.call( Ctor ) === ObjectFunctionString; + }, + + isEmptyObject: function( obj ) { + + /* eslint-disable no-unused-vars */ + // See https://github.com/eslint/eslint/issues/6125 + var name; + + for ( name in obj ) { + return false; + } + return true; + }, + + // Evaluates a script in a global context + globalEval: function( code ) { + DOMEval( code ); + }, + + each: function( obj, callback ) { + var length, i = 0; + + if ( isArrayLike( obj ) ) { + length = obj.length; + for ( ; i < length; i++ ) { + if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { + break; + } + } + } else { + for ( i in obj ) { + if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { + break; + } + } + } + + return obj; + }, + + // Support: Android <=4.0 only + trim: function( text ) { + return text == null ? + "" : + ( text + "" ).replace( rtrim, "" ); + }, + + // results is for internal usage only + makeArray: function( arr, results ) { + var ret = results || []; + + if ( arr != null ) { + if ( isArrayLike( Object( arr ) ) ) { + jQuery.merge( ret, + typeof arr === "string" ? + [ arr ] : arr + ); + } else { + push.call( ret, arr ); + } + } + + return ret; + }, + + inArray: function( elem, arr, i ) { + return arr == null ? -1 : indexOf.call( arr, elem, i ); + }, + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + merge: function( first, second ) { + var len = +second.length, + j = 0, + i = first.length; + + for ( ; j < len; j++ ) { + first[ i++ ] = second[ j ]; + } + + first.length = i; + + return first; + }, + + grep: function( elems, callback, invert ) { + var callbackInverse, + matches = [], + i = 0, + length = elems.length, + callbackExpect = !invert; + + // Go through the array, only saving the items + // that pass the validator function + for ( ; i < length; i++ ) { + callbackInverse = !callback( elems[ i ], i ); + if ( callbackInverse !== callbackExpect ) { + matches.push( elems[ i ] ); + } + } + + return matches; + }, + + // arg is for internal usage only + map: function( elems, callback, arg ) { + var length, value, + i = 0, + ret = []; + + // Go through the array, translating each of the items to their new values + if ( isArrayLike( elems ) ) { + length = elems.length; + for ( ; i < length; i++ ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret.push( value ); + } + } + + // Go through every key on the object, + } else { + for ( i in elems ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret.push( value ); + } + } + } + + // Flatten any nested arrays + return concat.apply( [], ret ); + }, + + // A global GUID counter for objects + guid: 1, + + // jQuery.support is not used in Core but other projects attach their + // properties to it so it needs to exist. + support: support +} ); + +if ( typeof Symbol === "function" ) { + jQuery.fn[ Symbol.iterator ] = arr[ Symbol.iterator ]; +} + +// Populate the class2type map +jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ), +function( i, name ) { + class2type[ "[object " + name + "]" ] = name.toLowerCase(); +} ); + +function isArrayLike( obj ) { + + // Support: real iOS 8.2 only (not reproducible in simulator) + // `in` check used to prevent JIT error (gh-2145) + // hasOwn isn't used here due to false negatives + // regarding Nodelist length in IE + var length = !!obj && "length" in obj && obj.length, + type = toType( obj ); + + if ( isFunction( obj ) || isWindow( obj ) ) { + return false; + } + + return type === "array" || length === 0 || + typeof length === "number" && length > 0 && ( length - 1 ) in obj; +} +var Sizzle = +/*! + * Sizzle CSS Selector Engine v2.3.3 + * https://sizzlejs.com/ + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license + * http://jquery.org/license + * + * Date: 2016-08-08 + */ +(function( window ) { + +var i, + support, + Expr, + getText, + isXML, + tokenize, + compile, + select, + outermostContext, + sortInput, + hasDuplicate, + + // Local document vars + setDocument, + document, + docElem, + documentIsHTML, + rbuggyQSA, + rbuggyMatches, + matches, + contains, + + // Instance-specific data + expando = "sizzle" + 1 * new Date(), + preferredDoc = window.document, + dirruns = 0, + done = 0, + classCache = createCache(), + tokenCache = createCache(), + compilerCache = createCache(), + sortOrder = function( a, b ) { + if ( a === b ) { + hasDuplicate = true; + } + return 0; + }, + + // Instance methods + hasOwn = ({}).hasOwnProperty, + arr = [], + pop = arr.pop, + push_native = arr.push, + push = arr.push, + slice = arr.slice, + // Use a stripped-down indexOf as it's faster than native + // https://jsperf.com/thor-indexof-vs-for/5 + indexOf = function( list, elem ) { + var i = 0, + len = list.length; + for ( ; i < len; i++ ) { + if ( list[i] === elem ) { + return i; + } + } + return -1; + }, + + booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped", + + // Regular expressions + + // http://www.w3.org/TR/css3-selectors/#whitespace + whitespace = "[\\x20\\t\\r\\n\\f]", + + // http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier + identifier = "(?:\\\\.|[\\w-]|[^\0-\\xa0])+", + + // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors + attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace + + // Operator (capture 2) + "*([*^$|!~]?=)" + whitespace + + // "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]" + "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace + + "*\\]", + + pseudos = ":(" + identifier + ")(?:\\((" + + // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments: + // 1. quoted (capture 3; capture 4 or capture 5) + "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" + + // 2. simple (capture 6) + "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" + + // 3. anything else (capture 2) + ".*" + + ")\\)|)", + + // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter + rwhitespace = new RegExp( whitespace + "+", "g" ), + rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ), + + rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), + rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ), + + rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g" ), + + rpseudo = new RegExp( pseudos ), + ridentifier = new RegExp( "^" + identifier + "$" ), + + matchExpr = { + "ID": new RegExp( "^#(" + identifier + ")" ), + "CLASS": new RegExp( "^\\.(" + identifier + ")" ), + "TAG": new RegExp( "^(" + identifier + "|[*])" ), + "ATTR": new RegExp( "^" + attributes ), + "PSEUDO": new RegExp( "^" + pseudos ), + "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace + + "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace + + "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), + "bool": new RegExp( "^(?:" + booleans + ")$", "i" ), + // For use in libraries implementing .is() + // We use this for POS matching in `select` + "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + + whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" ) + }, + + rinputs = /^(?:input|select|textarea|button)$/i, + rheader = /^h\d$/i, + + rnative = /^[^{]+\{\s*\[native \w/, + + // Easily-parseable/retrievable ID or TAG or CLASS selectors + rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, + + rsibling = /[+~]/, + + // CSS escapes + // http://www.w3.org/TR/CSS21/syndata.html#escaped-characters + runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ), + funescape = function( _, escaped, escapedWhitespace ) { + var high = "0x" + escaped - 0x10000; + // NaN means non-codepoint + // Support: Firefox<24 + // Workaround erroneous numeric interpretation of +"0x" + return high !== high || escapedWhitespace ? + escaped : + high < 0 ? + // BMP codepoint + String.fromCharCode( high + 0x10000 ) : + // Supplemental Plane codepoint (surrogate pair) + String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 ); + }, + + // CSS string/identifier serialization + // https://drafts.csswg.org/cssom/#common-serializing-idioms + rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g, + fcssescape = function( ch, asCodePoint ) { + if ( asCodePoint ) { + + // U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER + if ( ch === "\0" ) { + return "\uFFFD"; + } + + // Control characters and (dependent upon position) numbers get escaped as code points + return ch.slice( 0, -1 ) + "\\" + ch.charCodeAt( ch.length - 1 ).toString( 16 ) + " "; + } + + // Other potentially-special ASCII characters get backslash-escaped + return "\\" + ch; + }, + + // Used for iframes + // See setDocument() + // Removing the function wrapper causes a "Permission Denied" + // error in IE + unloadHandler = function() { + setDocument(); + }, + + disabledAncestor = addCombinator( + function( elem ) { + return elem.disabled === true && ("form" in elem || "label" in elem); + }, + { dir: "parentNode", next: "legend" } + ); + +// Optimize for push.apply( _, NodeList ) +try { + push.apply( + (arr = slice.call( preferredDoc.childNodes )), + preferredDoc.childNodes + ); + // Support: Android<4.0 + // Detect silently failing push.apply + arr[ preferredDoc.childNodes.length ].nodeType; +} catch ( e ) { + push = { apply: arr.length ? + + // Leverage slice if possible + function( target, els ) { + push_native.apply( target, slice.call(els) ); + } : + + // Support: IE<9 + // Otherwise append directly + function( target, els ) { + var j = target.length, + i = 0; + // Can't trust NodeList.length + while ( (target[j++] = els[i++]) ) {} + target.length = j - 1; + } + }; +} + +function Sizzle( selector, context, results, seed ) { + var m, i, elem, nid, match, groups, newSelector, + newContext = context && context.ownerDocument, + + // nodeType defaults to 9, since context defaults to document + nodeType = context ? context.nodeType : 9; + + results = results || []; + + // Return early from calls with invalid selector or context + if ( typeof selector !== "string" || !selector || + nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) { + + return results; + } + + // Try to shortcut find operations (as opposed to filters) in HTML documents + if ( !seed ) { + + if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) { + setDocument( context ); + } + context = context || document; + + if ( documentIsHTML ) { + + // If the selector is sufficiently simple, try using a "get*By*" DOM method + // (excepting DocumentFragment context, where the methods don't exist) + if ( nodeType !== 11 && (match = rquickExpr.exec( selector )) ) { + + // ID selector + if ( (m = match[1]) ) { + + // Document context + if ( nodeType === 9 ) { + if ( (elem = context.getElementById( m )) ) { + + // Support: IE, Opera, Webkit + // TODO: identify versions + // getElementById can match elements by name instead of ID + if ( elem.id === m ) { + results.push( elem ); + return results; + } + } else { + return results; + } + + // Element context + } else { + + // Support: IE, Opera, Webkit + // TODO: identify versions + // getElementById can match elements by name instead of ID + if ( newContext && (elem = newContext.getElementById( m )) && + contains( context, elem ) && + elem.id === m ) { + + results.push( elem ); + return results; + } + } + + // Type selector + } else if ( match[2] ) { + push.apply( results, context.getElementsByTagName( selector ) ); + return results; + + // Class selector + } else if ( (m = match[3]) && support.getElementsByClassName && + context.getElementsByClassName ) { + + push.apply( results, context.getElementsByClassName( m ) ); + return results; + } + } + + // Take advantage of querySelectorAll + if ( support.qsa && + !compilerCache[ selector + " " ] && + (!rbuggyQSA || !rbuggyQSA.test( selector )) ) { + + if ( nodeType !== 1 ) { + newContext = context; + newSelector = selector; + + // qSA looks outside Element context, which is not what we want + // Thanks to Andrew Dupont for this workaround technique + // Support: IE <=8 + // Exclude object elements + } else if ( context.nodeName.toLowerCase() !== "object" ) { + + // Capture the context ID, setting it first if necessary + if ( (nid = context.getAttribute( "id" )) ) { + nid = nid.replace( rcssescape, fcssescape ); + } else { + context.setAttribute( "id", (nid = expando) ); + } + + // Prefix every selector in the list + groups = tokenize( selector ); + i = groups.length; + while ( i-- ) { + groups[i] = "#" + nid + " " + toSelector( groups[i] ); + } + newSelector = groups.join( "," ); + + // Expand context for sibling selectors + newContext = rsibling.test( selector ) && testContext( context.parentNode ) || + context; + } + + if ( newSelector ) { + try { + push.apply( results, + newContext.querySelectorAll( newSelector ) + ); + return results; + } catch ( qsaError ) { + } finally { + if ( nid === expando ) { + context.removeAttribute( "id" ); + } + } + } + } + } + } + + // All others + return select( selector.replace( rtrim, "$1" ), context, results, seed ); +} + +/** + * Create key-value caches of limited size + * @returns {function(string, object)} Returns the Object data after storing it on itself with + * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength) + * deleting the oldest entry + */ +function createCache() { + var keys = []; + + function cache( key, value ) { + // Use (key + " ") to avoid collision with native prototype properties (see Issue #157) + if ( keys.push( key + " " ) > Expr.cacheLength ) { + // Only keep the most recent entries + delete cache[ keys.shift() ]; + } + return (cache[ key + " " ] = value); + } + return cache; +} + +/** + * Mark a function for special use by Sizzle + * @param {Function} fn The function to mark + */ +function markFunction( fn ) { + fn[ expando ] = true; + return fn; +} + +/** + * Support testing using an element + * @param {Function} fn Passed the created element and returns a boolean result + */ +function assert( fn ) { + var el = document.createElement("fieldset"); + + try { + return !!fn( el ); + } catch (e) { + return false; + } finally { + // Remove from its parent by default + if ( el.parentNode ) { + el.parentNode.removeChild( el ); + } + // release memory in IE + el = null; + } +} + +/** + * Adds the same handler for all of the specified attrs + * @param {String} attrs Pipe-separated list of attributes + * @param {Function} handler The method that will be applied + */ +function addHandle( attrs, handler ) { + var arr = attrs.split("|"), + i = arr.length; + + while ( i-- ) { + Expr.attrHandle[ arr[i] ] = handler; + } +} + +/** + * Checks document order of two siblings + * @param {Element} a + * @param {Element} b + * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b + */ +function siblingCheck( a, b ) { + var cur = b && a, + diff = cur && a.nodeType === 1 && b.nodeType === 1 && + a.sourceIndex - b.sourceIndex; + + // Use IE sourceIndex if available on both nodes + if ( diff ) { + return diff; + } + + // Check if b follows a + if ( cur ) { + while ( (cur = cur.nextSibling) ) { + if ( cur === b ) { + return -1; + } + } + } + + return a ? 1 : -1; +} + +/** + * Returns a function to use in pseudos for input types + * @param {String} type + */ +function createInputPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for buttons + * @param {String} type + */ +function createButtonPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return (name === "input" || name === "button") && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for :enabled/:disabled + * @param {Boolean} disabled true for :disabled; false for :enabled + */ +function createDisabledPseudo( disabled ) { + + // Known :disabled false positives: fieldset[disabled] > legend:nth-of-type(n+2) :can-disable + return function( elem ) { + + // Only certain elements can match :enabled or :disabled + // https://html.spec.whatwg.org/multipage/scripting.html#selector-enabled + // https://html.spec.whatwg.org/multipage/scripting.html#selector-disabled + if ( "form" in elem ) { + + // Check for inherited disabledness on relevant non-disabled elements: + // * listed form-associated elements in a disabled fieldset + // https://html.spec.whatwg.org/multipage/forms.html#category-listed + // https://html.spec.whatwg.org/multipage/forms.html#concept-fe-disabled + // * option elements in a disabled optgroup + // https://html.spec.whatwg.org/multipage/forms.html#concept-option-disabled + // All such elements have a "form" property. + if ( elem.parentNode && elem.disabled === false ) { + + // Option elements defer to a parent optgroup if present + if ( "label" in elem ) { + if ( "label" in elem.parentNode ) { + return elem.parentNode.disabled === disabled; + } else { + return elem.disabled === disabled; + } + } + + // Support: IE 6 - 11 + // Use the isDisabled shortcut property to check for disabled fieldset ancestors + return elem.isDisabled === disabled || + + // Where there is no isDisabled, check manually + /* jshint -W018 */ + elem.isDisabled !== !disabled && + disabledAncestor( elem ) === disabled; + } + + return elem.disabled === disabled; + + // Try to winnow out elements that can't be disabled before trusting the disabled property. + // Some victims get caught in our net (label, legend, menu, track), but it shouldn't + // even exist on them, let alone have a boolean value. + } else if ( "label" in elem ) { + return elem.disabled === disabled; + } + + // Remaining elements are neither :enabled nor :disabled + return false; + }; +} + +/** + * Returns a function to use in pseudos for positionals + * @param {Function} fn + */ +function createPositionalPseudo( fn ) { + return markFunction(function( argument ) { + argument = +argument; + return markFunction(function( seed, matches ) { + var j, + matchIndexes = fn( [], seed.length, argument ), + i = matchIndexes.length; + + // Match elements found at the specified indexes + while ( i-- ) { + if ( seed[ (j = matchIndexes[i]) ] ) { + seed[j] = !(matches[j] = seed[j]); + } + } + }); + }); +} + +/** + * Checks a node for validity as a Sizzle context + * @param {Element|Object=} context + * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value + */ +function testContext( context ) { + return context && typeof context.getElementsByTagName !== "undefined" && context; +} + +// Expose support vars for convenience +support = Sizzle.support = {}; + +/** + * Detects XML nodes + * @param {Element|Object} elem An element or a document + * @returns {Boolean} True iff elem is a non-HTML XML node + */ +isXML = Sizzle.isXML = function( elem ) { + // documentElement is verified for cases where it doesn't yet exist + // (such as loading iframes in IE - #4833) + var documentElement = elem && (elem.ownerDocument || elem).documentElement; + return documentElement ? documentElement.nodeName !== "HTML" : false; +}; + +/** + * Sets document-related variables once based on the current document + * @param {Element|Object} [doc] An element or document object to use to set the document + * @returns {Object} Returns the current document + */ +setDocument = Sizzle.setDocument = function( node ) { + var hasCompare, subWindow, + doc = node ? node.ownerDocument || node : preferredDoc; + + // Return early if doc is invalid or already selected + if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) { + return document; + } + + // Update global variables + document = doc; + docElem = document.documentElement; + documentIsHTML = !isXML( document ); + + // Support: IE 9-11, Edge + // Accessing iframe documents after unload throws "permission denied" errors (jQuery #13936) + if ( preferredDoc !== document && + (subWindow = document.defaultView) && subWindow.top !== subWindow ) { + + // Support: IE 11, Edge + if ( subWindow.addEventListener ) { + subWindow.addEventListener( "unload", unloadHandler, false ); + + // Support: IE 9 - 10 only + } else if ( subWindow.attachEvent ) { + subWindow.attachEvent( "onunload", unloadHandler ); + } + } + + /* Attributes + ---------------------------------------------------------------------- */ + + // Support: IE<8 + // Verify that getAttribute really returns attributes and not properties + // (excepting IE8 booleans) + support.attributes = assert(function( el ) { + el.className = "i"; + return !el.getAttribute("className"); + }); + + /* getElement(s)By* + ---------------------------------------------------------------------- */ + + // Check if getElementsByTagName("*") returns only elements + support.getElementsByTagName = assert(function( el ) { + el.appendChild( document.createComment("") ); + return !el.getElementsByTagName("*").length; + }); + + // Support: IE<9 + support.getElementsByClassName = rnative.test( document.getElementsByClassName ); + + // Support: IE<10 + // Check if getElementById returns elements by name + // The broken getElementById methods don't pick up programmatically-set names, + // so use a roundabout getElementsByName test + support.getById = assert(function( el ) { + docElem.appendChild( el ).id = expando; + return !document.getElementsByName || !document.getElementsByName( expando ).length; + }); + + // ID filter and find + if ( support.getById ) { + Expr.filter["ID"] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + return elem.getAttribute("id") === attrId; + }; + }; + Expr.find["ID"] = function( id, context ) { + if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { + var elem = context.getElementById( id ); + return elem ? [ elem ] : []; + } + }; + } else { + Expr.filter["ID"] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + var node = typeof elem.getAttributeNode !== "undefined" && + elem.getAttributeNode("id"); + return node && node.value === attrId; + }; + }; + + // Support: IE 6 - 7 only + // getElementById is not reliable as a find shortcut + Expr.find["ID"] = function( id, context ) { + if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { + var node, i, elems, + elem = context.getElementById( id ); + + if ( elem ) { + + // Verify the id attribute + node = elem.getAttributeNode("id"); + if ( node && node.value === id ) { + return [ elem ]; + } + + // Fall back on getElementsByName + elems = context.getElementsByName( id ); + i = 0; + while ( (elem = elems[i++]) ) { + node = elem.getAttributeNode("id"); + if ( node && node.value === id ) { + return [ elem ]; + } + } + } + + return []; + } + }; + } + + // Tag + Expr.find["TAG"] = support.getElementsByTagName ? + function( tag, context ) { + if ( typeof context.getElementsByTagName !== "undefined" ) { + return context.getElementsByTagName( tag ); + + // DocumentFragment nodes don't have gEBTN + } else if ( support.qsa ) { + return context.querySelectorAll( tag ); + } + } : + + function( tag, context ) { + var elem, + tmp = [], + i = 0, + // By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too + results = context.getElementsByTagName( tag ); + + // Filter out possible comments + if ( tag === "*" ) { + while ( (elem = results[i++]) ) { + if ( elem.nodeType === 1 ) { + tmp.push( elem ); + } + } + + return tmp; + } + return results; + }; + + // Class + Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) { + if ( typeof context.getElementsByClassName !== "undefined" && documentIsHTML ) { + return context.getElementsByClassName( className ); + } + }; + + /* QSA/matchesSelector + ---------------------------------------------------------------------- */ + + // QSA and matchesSelector support + + // matchesSelector(:active) reports false when true (IE9/Opera 11.5) + rbuggyMatches = []; + + // qSa(:focus) reports false when true (Chrome 21) + // We allow this because of a bug in IE8/9 that throws an error + // whenever `document.activeElement` is accessed on an iframe + // So, we allow :focus to pass through QSA all the time to avoid the IE error + // See https://bugs.jquery.com/ticket/13378 + rbuggyQSA = []; + + if ( (support.qsa = rnative.test( document.querySelectorAll )) ) { + // Build QSA regex + // Regex strategy adopted from Diego Perini + assert(function( el ) { + // Select is set to empty string on purpose + // This is to test IE's treatment of not explicitly + // setting a boolean content attribute, + // since its presence should be enough + // https://bugs.jquery.com/ticket/12359 + docElem.appendChild( el ).innerHTML = "" + + ""; + + // Support: IE8, Opera 11-12.16 + // Nothing should be selected when empty strings follow ^= or $= or *= + // The test attribute must be unknown in Opera but "safe" for WinRT + // https://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section + if ( el.querySelectorAll("[msallowcapture^='']").length ) { + rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" ); + } + + // Support: IE8 + // Boolean attributes and "value" are not treated correctly + if ( !el.querySelectorAll("[selected]").length ) { + rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" ); + } + + // Support: Chrome<29, Android<4.4, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.8+ + if ( !el.querySelectorAll( "[id~=" + expando + "-]" ).length ) { + rbuggyQSA.push("~="); + } + + // Webkit/Opera - :checked should return selected option elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + // IE8 throws error here and will not see later tests + if ( !el.querySelectorAll(":checked").length ) { + rbuggyQSA.push(":checked"); + } + + // Support: Safari 8+, iOS 8+ + // https://bugs.webkit.org/show_bug.cgi?id=136851 + // In-page `selector#id sibling-combinator selector` fails + if ( !el.querySelectorAll( "a#" + expando + "+*" ).length ) { + rbuggyQSA.push(".#.+[+~]"); + } + }); + + assert(function( el ) { + el.innerHTML = "" + + ""; + + // Support: Windows 8 Native Apps + // The type and name attributes are restricted during .innerHTML assignment + var input = document.createElement("input"); + input.setAttribute( "type", "hidden" ); + el.appendChild( input ).setAttribute( "name", "D" ); + + // Support: IE8 + // Enforce case-sensitivity of name attribute + if ( el.querySelectorAll("[name=d]").length ) { + rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" ); + } + + // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) + // IE8 throws error here and will not see later tests + if ( el.querySelectorAll(":enabled").length !== 2 ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } + + // Support: IE9-11+ + // IE's :disabled selector does not pick up the children of disabled fieldsets + docElem.appendChild( el ).disabled = true; + if ( el.querySelectorAll(":disabled").length !== 2 ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } + + // Opera 10-11 does not throw on post-comma invalid pseudos + el.querySelectorAll("*,:x"); + rbuggyQSA.push(",.*:"); + }); + } + + if ( (support.matchesSelector = rnative.test( (matches = docElem.matches || + docElem.webkitMatchesSelector || + docElem.mozMatchesSelector || + docElem.oMatchesSelector || + docElem.msMatchesSelector) )) ) { + + assert(function( el ) { + // Check to see if it's possible to do matchesSelector + // on a disconnected node (IE 9) + support.disconnectedMatch = matches.call( el, "*" ); + + // This should fail with an exception + // Gecko does not error, returns false instead + matches.call( el, "[s!='']:x" ); + rbuggyMatches.push( "!=", pseudos ); + }); + } + + rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") ); + rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") ); + + /* Contains + ---------------------------------------------------------------------- */ + hasCompare = rnative.test( docElem.compareDocumentPosition ); + + // Element contains another + // Purposefully self-exclusive + // As in, an element does not contain itself + contains = hasCompare || rnative.test( docElem.contains ) ? + function( a, b ) { + var adown = a.nodeType === 9 ? a.documentElement : a, + bup = b && b.parentNode; + return a === bup || !!( bup && bup.nodeType === 1 && ( + adown.contains ? + adown.contains( bup ) : + a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16 + )); + } : + function( a, b ) { + if ( b ) { + while ( (b = b.parentNode) ) { + if ( b === a ) { + return true; + } + } + } + return false; + }; + + /* Sorting + ---------------------------------------------------------------------- */ + + // Document order sorting + sortOrder = hasCompare ? + function( a, b ) { + + // Flag for duplicate removal + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + // Sort on method existence if only one input has compareDocumentPosition + var compare = !a.compareDocumentPosition - !b.compareDocumentPosition; + if ( compare ) { + return compare; + } + + // Calculate position if both inputs belong to the same document + compare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ? + a.compareDocumentPosition( b ) : + + // Otherwise we know they are disconnected + 1; + + // Disconnected nodes + if ( compare & 1 || + (!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) { + + // Choose the first element that is related to our preferred document + if ( a === document || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) { + return -1; + } + if ( b === document || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) { + return 1; + } + + // Maintain original order + return sortInput ? + ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : + 0; + } + + return compare & 4 ? -1 : 1; + } : + function( a, b ) { + // Exit early if the nodes are identical + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + var cur, + i = 0, + aup = a.parentNode, + bup = b.parentNode, + ap = [ a ], + bp = [ b ]; + + // Parentless nodes are either documents or disconnected + if ( !aup || !bup ) { + return a === document ? -1 : + b === document ? 1 : + aup ? -1 : + bup ? 1 : + sortInput ? + ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : + 0; + + // If the nodes are siblings, we can do a quick check + } else if ( aup === bup ) { + return siblingCheck( a, b ); + } + + // Otherwise we need full lists of their ancestors for comparison + cur = a; + while ( (cur = cur.parentNode) ) { + ap.unshift( cur ); + } + cur = b; + while ( (cur = cur.parentNode) ) { + bp.unshift( cur ); + } + + // Walk down the tree looking for a discrepancy + while ( ap[i] === bp[i] ) { + i++; + } + + return i ? + // Do a sibling check if the nodes have a common ancestor + siblingCheck( ap[i], bp[i] ) : + + // Otherwise nodes in our document sort first + ap[i] === preferredDoc ? -1 : + bp[i] === preferredDoc ? 1 : + 0; + }; + + return document; +}; + +Sizzle.matches = function( expr, elements ) { + return Sizzle( expr, null, null, elements ); +}; + +Sizzle.matchesSelector = function( elem, expr ) { + // Set document vars if needed + if ( ( elem.ownerDocument || elem ) !== document ) { + setDocument( elem ); + } + + // Make sure that attribute selectors are quoted + expr = expr.replace( rattributeQuotes, "='$1']" ); + + if ( support.matchesSelector && documentIsHTML && + !compilerCache[ expr + " " ] && + ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) && + ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) { + + try { + var ret = matches.call( elem, expr ); + + // IE 9's matchesSelector returns false on disconnected nodes + if ( ret || support.disconnectedMatch || + // As well, disconnected nodes are said to be in a document + // fragment in IE 9 + elem.document && elem.document.nodeType !== 11 ) { + return ret; + } + } catch (e) {} + } + + return Sizzle( expr, document, null, [ elem ] ).length > 0; +}; + +Sizzle.contains = function( context, elem ) { + // Set document vars if needed + if ( ( context.ownerDocument || context ) !== document ) { + setDocument( context ); + } + return contains( context, elem ); +}; + +Sizzle.attr = function( elem, name ) { + // Set document vars if needed + if ( ( elem.ownerDocument || elem ) !== document ) { + setDocument( elem ); + } + + var fn = Expr.attrHandle[ name.toLowerCase() ], + // Don't get fooled by Object.prototype properties (jQuery #13807) + val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ? + fn( elem, name, !documentIsHTML ) : + undefined; + + return val !== undefined ? + val : + support.attributes || !documentIsHTML ? + elem.getAttribute( name ) : + (val = elem.getAttributeNode(name)) && val.specified ? + val.value : + null; +}; + +Sizzle.escape = function( sel ) { + return (sel + "").replace( rcssescape, fcssescape ); +}; + +Sizzle.error = function( msg ) { + throw new Error( "Syntax error, unrecognized expression: " + msg ); +}; + +/** + * Document sorting and removing duplicates + * @param {ArrayLike} results + */ +Sizzle.uniqueSort = function( results ) { + var elem, + duplicates = [], + j = 0, + i = 0; + + // Unless we *know* we can detect duplicates, assume their presence + hasDuplicate = !support.detectDuplicates; + sortInput = !support.sortStable && results.slice( 0 ); + results.sort( sortOrder ); + + if ( hasDuplicate ) { + while ( (elem = results[i++]) ) { + if ( elem === results[ i ] ) { + j = duplicates.push( i ); + } + } + while ( j-- ) { + results.splice( duplicates[ j ], 1 ); + } + } + + // Clear input after sorting to release objects + // See https://github.com/jquery/sizzle/pull/225 + sortInput = null; + + return results; +}; + +/** + * Utility function for retrieving the text value of an array of DOM nodes + * @param {Array|Element} elem + */ +getText = Sizzle.getText = function( elem ) { + var node, + ret = "", + i = 0, + nodeType = elem.nodeType; + + if ( !nodeType ) { + // If no nodeType, this is expected to be an array + while ( (node = elem[i++]) ) { + // Do not traverse comment nodes + ret += getText( node ); + } + } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { + // Use textContent for elements + // innerText usage removed for consistency of new lines (jQuery #11153) + if ( typeof elem.textContent === "string" ) { + return elem.textContent; + } else { + // Traverse its children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + ret += getText( elem ); + } + } + } else if ( nodeType === 3 || nodeType === 4 ) { + return elem.nodeValue; + } + // Do not include comment or processing instruction nodes + + return ret; +}; + +Expr = Sizzle.selectors = { + + // Can be adjusted by the user + cacheLength: 50, + + createPseudo: markFunction, + + match: matchExpr, + + attrHandle: {}, + + find: {}, + + relative: { + ">": { dir: "parentNode", first: true }, + " ": { dir: "parentNode" }, + "+": { dir: "previousSibling", first: true }, + "~": { dir: "previousSibling" } + }, + + preFilter: { + "ATTR": function( match ) { + match[1] = match[1].replace( runescape, funescape ); + + // Move the given value to match[3] whether quoted or unquoted + match[3] = ( match[3] || match[4] || match[5] || "" ).replace( runescape, funescape ); + + if ( match[2] === "~=" ) { + match[3] = " " + match[3] + " "; + } + + return match.slice( 0, 4 ); + }, + + "CHILD": function( match ) { + /* matches from matchExpr["CHILD"] + 1 type (only|nth|...) + 2 what (child|of-type) + 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...) + 4 xn-component of xn+y argument ([+-]?\d*n|) + 5 sign of xn-component + 6 x of xn-component + 7 sign of y-component + 8 y of y-component + */ + match[1] = match[1].toLowerCase(); + + if ( match[1].slice( 0, 3 ) === "nth" ) { + // nth-* requires argument + if ( !match[3] ) { + Sizzle.error( match[0] ); + } + + // numeric x and y parameters for Expr.filter.CHILD + // remember that false/true cast respectively to 0/1 + match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) ); + match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" ); + + // other types prohibit arguments + } else if ( match[3] ) { + Sizzle.error( match[0] ); + } + + return match; + }, + + "PSEUDO": function( match ) { + var excess, + unquoted = !match[6] && match[2]; + + if ( matchExpr["CHILD"].test( match[0] ) ) { + return null; + } + + // Accept quoted arguments as-is + if ( match[3] ) { + match[2] = match[4] || match[5] || ""; + + // Strip excess characters from unquoted arguments + } else if ( unquoted && rpseudo.test( unquoted ) && + // Get excess from tokenize (recursively) + (excess = tokenize( unquoted, true )) && + // advance to the next closing parenthesis + (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) { + + // excess is a negative index + match[0] = match[0].slice( 0, excess ); + match[2] = unquoted.slice( 0, excess ); + } + + // Return only captures needed by the pseudo filter method (type and argument) + return match.slice( 0, 3 ); + } + }, + + filter: { + + "TAG": function( nodeNameSelector ) { + var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase(); + return nodeNameSelector === "*" ? + function() { return true; } : + function( elem ) { + return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; + }; + }, + + "CLASS": function( className ) { + var pattern = classCache[ className + " " ]; + + return pattern || + (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) && + classCache( className, function( elem ) { + return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== "undefined" && elem.getAttribute("class") || "" ); + }); + }, + + "ATTR": function( name, operator, check ) { + return function( elem ) { + var result = Sizzle.attr( elem, name ); + + if ( result == null ) { + return operator === "!="; + } + if ( !operator ) { + return true; + } + + result += ""; + + return operator === "=" ? result === check : + operator === "!=" ? result !== check : + operator === "^=" ? check && result.indexOf( check ) === 0 : + operator === "*=" ? check && result.indexOf( check ) > -1 : + operator === "$=" ? check && result.slice( -check.length ) === check : + operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 : + operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" : + false; + }; + }, + + "CHILD": function( type, what, argument, first, last ) { + var simple = type.slice( 0, 3 ) !== "nth", + forward = type.slice( -4 ) !== "last", + ofType = what === "of-type"; + + return first === 1 && last === 0 ? + + // Shortcut for :nth-*(n) + function( elem ) { + return !!elem.parentNode; + } : + + function( elem, context, xml ) { + var cache, uniqueCache, outerCache, node, nodeIndex, start, + dir = simple !== forward ? "nextSibling" : "previousSibling", + parent = elem.parentNode, + name = ofType && elem.nodeName.toLowerCase(), + useCache = !xml && !ofType, + diff = false; + + if ( parent ) { + + // :(first|last|only)-(child|of-type) + if ( simple ) { + while ( dir ) { + node = elem; + while ( (node = node[ dir ]) ) { + if ( ofType ? + node.nodeName.toLowerCase() === name : + node.nodeType === 1 ) { + + return false; + } + } + // Reverse direction for :only-* (if we haven't yet done so) + start = dir = type === "only" && !start && "nextSibling"; + } + return true; + } + + start = [ forward ? parent.firstChild : parent.lastChild ]; + + // non-xml :nth-child(...) stores cache data on `parent` + if ( forward && useCache ) { + + // Seek `elem` from a previously-cached index + + // ...in a gzip-friendly way + node = parent; + outerCache = node[ expando ] || (node[ expando ] = {}); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + (outerCache[ node.uniqueID ] = {}); + + cache = uniqueCache[ type ] || []; + nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; + diff = nodeIndex && cache[ 2 ]; + node = nodeIndex && parent.childNodes[ nodeIndex ]; + + while ( (node = ++nodeIndex && node && node[ dir ] || + + // Fallback to seeking `elem` from the start + (diff = nodeIndex = 0) || start.pop()) ) { + + // When found, cache indexes on `parent` and break + if ( node.nodeType === 1 && ++diff && node === elem ) { + uniqueCache[ type ] = [ dirruns, nodeIndex, diff ]; + break; + } + } + + } else { + // Use previously-cached element index if available + if ( useCache ) { + // ...in a gzip-friendly way + node = elem; + outerCache = node[ expando ] || (node[ expando ] = {}); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + (outerCache[ node.uniqueID ] = {}); + + cache = uniqueCache[ type ] || []; + nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; + diff = nodeIndex; + } + + // xml :nth-child(...) + // or :nth-last-child(...) or :nth(-last)?-of-type(...) + if ( diff === false ) { + // Use the same loop as above to seek `elem` from the start + while ( (node = ++nodeIndex && node && node[ dir ] || + (diff = nodeIndex = 0) || start.pop()) ) { + + if ( ( ofType ? + node.nodeName.toLowerCase() === name : + node.nodeType === 1 ) && + ++diff ) { + + // Cache the index of each encountered element + if ( useCache ) { + outerCache = node[ expando ] || (node[ expando ] = {}); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + (outerCache[ node.uniqueID ] = {}); + + uniqueCache[ type ] = [ dirruns, diff ]; + } + + if ( node === elem ) { + break; + } + } + } + } + } + + // Incorporate the offset, then check against cycle size + diff -= last; + return diff === first || ( diff % first === 0 && diff / first >= 0 ); + } + }; + }, + + "PSEUDO": function( pseudo, argument ) { + // pseudo-class names are case-insensitive + // http://www.w3.org/TR/selectors/#pseudo-classes + // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters + // Remember that setFilters inherits from pseudos + var args, + fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] || + Sizzle.error( "unsupported pseudo: " + pseudo ); + + // The user may use createPseudo to indicate that + // arguments are needed to create the filter function + // just as Sizzle does + if ( fn[ expando ] ) { + return fn( argument ); + } + + // But maintain support for old signatures + if ( fn.length > 1 ) { + args = [ pseudo, pseudo, "", argument ]; + return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ? + markFunction(function( seed, matches ) { + var idx, + matched = fn( seed, argument ), + i = matched.length; + while ( i-- ) { + idx = indexOf( seed, matched[i] ); + seed[ idx ] = !( matches[ idx ] = matched[i] ); + } + }) : + function( elem ) { + return fn( elem, 0, args ); + }; + } + + return fn; + } + }, + + pseudos: { + // Potentially complex pseudos + "not": markFunction(function( selector ) { + // Trim the selector passed to compile + // to avoid treating leading and trailing + // spaces as combinators + var input = [], + results = [], + matcher = compile( selector.replace( rtrim, "$1" ) ); + + return matcher[ expando ] ? + markFunction(function( seed, matches, context, xml ) { + var elem, + unmatched = matcher( seed, null, xml, [] ), + i = seed.length; + + // Match elements unmatched by `matcher` + while ( i-- ) { + if ( (elem = unmatched[i]) ) { + seed[i] = !(matches[i] = elem); + } + } + }) : + function( elem, context, xml ) { + input[0] = elem; + matcher( input, null, xml, results ); + // Don't keep the element (issue #299) + input[0] = null; + return !results.pop(); + }; + }), + + "has": markFunction(function( selector ) { + return function( elem ) { + return Sizzle( selector, elem ).length > 0; + }; + }), + + "contains": markFunction(function( text ) { + text = text.replace( runescape, funescape ); + return function( elem ) { + return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1; + }; + }), + + // "Whether an element is represented by a :lang() selector + // is based solely on the element's language value + // being equal to the identifier C, + // or beginning with the identifier C immediately followed by "-". + // The matching of C against the element's language value is performed case-insensitively. + // The identifier C does not have to be a valid language name." + // http://www.w3.org/TR/selectors/#lang-pseudo + "lang": markFunction( function( lang ) { + // lang value must be a valid identifier + if ( !ridentifier.test(lang || "") ) { + Sizzle.error( "unsupported lang: " + lang ); + } + lang = lang.replace( runescape, funescape ).toLowerCase(); + return function( elem ) { + var elemLang; + do { + if ( (elemLang = documentIsHTML ? + elem.lang : + elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) { + + elemLang = elemLang.toLowerCase(); + return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0; + } + } while ( (elem = elem.parentNode) && elem.nodeType === 1 ); + return false; + }; + }), + + // Miscellaneous + "target": function( elem ) { + var hash = window.location && window.location.hash; + return hash && hash.slice( 1 ) === elem.id; + }, + + "root": function( elem ) { + return elem === docElem; + }, + + "focus": function( elem ) { + return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex); + }, + + // Boolean properties + "enabled": createDisabledPseudo( false ), + "disabled": createDisabledPseudo( true ), + + "checked": function( elem ) { + // In CSS3, :checked should return both checked and selected elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + var nodeName = elem.nodeName.toLowerCase(); + return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected); + }, + + "selected": function( elem ) { + // Accessing this property makes selected-by-default + // options in Safari work properly + if ( elem.parentNode ) { + elem.parentNode.selectedIndex; + } + + return elem.selected === true; + }, + + // Contents + "empty": function( elem ) { + // http://www.w3.org/TR/selectors/#empty-pseudo + // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5), + // but not by others (comment: 8; processing instruction: 7; etc.) + // nodeType < 6 works because attributes (2) do not appear as children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + if ( elem.nodeType < 6 ) { + return false; + } + } + return true; + }, + + "parent": function( elem ) { + return !Expr.pseudos["empty"]( elem ); + }, + + // Element/input types + "header": function( elem ) { + return rheader.test( elem.nodeName ); + }, + + "input": function( elem ) { + return rinputs.test( elem.nodeName ); + }, + + "button": function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === "button" || name === "button"; + }, + + "text": function( elem ) { + var attr; + return elem.nodeName.toLowerCase() === "input" && + elem.type === "text" && + + // Support: IE<8 + // New HTML5 attribute values (e.g., "search") appear with elem.type === "text" + ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === "text" ); + }, + + // Position-in-collection + "first": createPositionalPseudo(function() { + return [ 0 ]; + }), + + "last": createPositionalPseudo(function( matchIndexes, length ) { + return [ length - 1 ]; + }), + + "eq": createPositionalPseudo(function( matchIndexes, length, argument ) { + return [ argument < 0 ? argument + length : argument ]; + }), + + "even": createPositionalPseudo(function( matchIndexes, length ) { + var i = 0; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "odd": createPositionalPseudo(function( matchIndexes, length ) { + var i = 1; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "lt": createPositionalPseudo(function( matchIndexes, length, argument ) { + var i = argument < 0 ? argument + length : argument; + for ( ; --i >= 0; ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "gt": createPositionalPseudo(function( matchIndexes, length, argument ) { + var i = argument < 0 ? argument + length : argument; + for ( ; ++i < length; ) { + matchIndexes.push( i ); + } + return matchIndexes; + }) + } +}; + +Expr.pseudos["nth"] = Expr.pseudos["eq"]; + +// Add button/input type pseudos +for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) { + Expr.pseudos[ i ] = createInputPseudo( i ); +} +for ( i in { submit: true, reset: true } ) { + Expr.pseudos[ i ] = createButtonPseudo( i ); +} + +// Easy API for creating new setFilters +function setFilters() {} +setFilters.prototype = Expr.filters = Expr.pseudos; +Expr.setFilters = new setFilters(); + +tokenize = Sizzle.tokenize = function( selector, parseOnly ) { + var matched, match, tokens, type, + soFar, groups, preFilters, + cached = tokenCache[ selector + " " ]; + + if ( cached ) { + return parseOnly ? 0 : cached.slice( 0 ); + } + + soFar = selector; + groups = []; + preFilters = Expr.preFilter; + + while ( soFar ) { + + // Comma and first run + if ( !matched || (match = rcomma.exec( soFar )) ) { + if ( match ) { + // Don't consume trailing commas as valid + soFar = soFar.slice( match[0].length ) || soFar; + } + groups.push( (tokens = []) ); + } + + matched = false; + + // Combinators + if ( (match = rcombinators.exec( soFar )) ) { + matched = match.shift(); + tokens.push({ + value: matched, + // Cast descendant combinators to space + type: match[0].replace( rtrim, " " ) + }); + soFar = soFar.slice( matched.length ); + } + + // Filters + for ( type in Expr.filter ) { + if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] || + (match = preFilters[ type ]( match ))) ) { + matched = match.shift(); + tokens.push({ + value: matched, + type: type, + matches: match + }); + soFar = soFar.slice( matched.length ); + } + } + + if ( !matched ) { + break; + } + } + + // Return the length of the invalid excess + // if we're just parsing + // Otherwise, throw an error or return tokens + return parseOnly ? + soFar.length : + soFar ? + Sizzle.error( selector ) : + // Cache the tokens + tokenCache( selector, groups ).slice( 0 ); +}; + +function toSelector( tokens ) { + var i = 0, + len = tokens.length, + selector = ""; + for ( ; i < len; i++ ) { + selector += tokens[i].value; + } + return selector; +} + +function addCombinator( matcher, combinator, base ) { + var dir = combinator.dir, + skip = combinator.next, + key = skip || dir, + checkNonElements = base && key === "parentNode", + doneName = done++; + + return combinator.first ? + // Check against closest ancestor/preceding element + function( elem, context, xml ) { + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + return matcher( elem, context, xml ); + } + } + return false; + } : + + // Check against all ancestor/preceding elements + function( elem, context, xml ) { + var oldCache, uniqueCache, outerCache, + newCache = [ dirruns, doneName ]; + + // We can't set arbitrary data on XML nodes, so they don't benefit from combinator caching + if ( xml ) { + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + if ( matcher( elem, context, xml ) ) { + return true; + } + } + } + } else { + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + outerCache = elem[ expando ] || (elem[ expando ] = {}); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ elem.uniqueID ] || (outerCache[ elem.uniqueID ] = {}); + + if ( skip && skip === elem.nodeName.toLowerCase() ) { + elem = elem[ dir ] || elem; + } else if ( (oldCache = uniqueCache[ key ]) && + oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) { + + // Assign to newCache so results back-propagate to previous elements + return (newCache[ 2 ] = oldCache[ 2 ]); + } else { + // Reuse newcache so results back-propagate to previous elements + uniqueCache[ key ] = newCache; + + // A match means we're done; a fail means we have to keep checking + if ( (newCache[ 2 ] = matcher( elem, context, xml )) ) { + return true; + } + } + } + } + } + return false; + }; +} + +function elementMatcher( matchers ) { + return matchers.length > 1 ? + function( elem, context, xml ) { + var i = matchers.length; + while ( i-- ) { + if ( !matchers[i]( elem, context, xml ) ) { + return false; + } + } + return true; + } : + matchers[0]; +} + +function multipleContexts( selector, contexts, results ) { + var i = 0, + len = contexts.length; + for ( ; i < len; i++ ) { + Sizzle( selector, contexts[i], results ); + } + return results; +} + +function condense( unmatched, map, filter, context, xml ) { + var elem, + newUnmatched = [], + i = 0, + len = unmatched.length, + mapped = map != null; + + for ( ; i < len; i++ ) { + if ( (elem = unmatched[i]) ) { + if ( !filter || filter( elem, context, xml ) ) { + newUnmatched.push( elem ); + if ( mapped ) { + map.push( i ); + } + } + } + } + + return newUnmatched; +} + +function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) { + if ( postFilter && !postFilter[ expando ] ) { + postFilter = setMatcher( postFilter ); + } + if ( postFinder && !postFinder[ expando ] ) { + postFinder = setMatcher( postFinder, postSelector ); + } + return markFunction(function( seed, results, context, xml ) { + var temp, i, elem, + preMap = [], + postMap = [], + preexisting = results.length, + + // Get initial elements from seed or context + elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ), + + // Prefilter to get matcher input, preserving a map for seed-results synchronization + matcherIn = preFilter && ( seed || !selector ) ? + condense( elems, preMap, preFilter, context, xml ) : + elems, + + matcherOut = matcher ? + // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results, + postFinder || ( seed ? preFilter : preexisting || postFilter ) ? + + // ...intermediate processing is necessary + [] : + + // ...otherwise use results directly + results : + matcherIn; + + // Find primary matches + if ( matcher ) { + matcher( matcherIn, matcherOut, context, xml ); + } + + // Apply postFilter + if ( postFilter ) { + temp = condense( matcherOut, postMap ); + postFilter( temp, [], context, xml ); + + // Un-match failing elements by moving them back to matcherIn + i = temp.length; + while ( i-- ) { + if ( (elem = temp[i]) ) { + matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem); + } + } + } + + if ( seed ) { + if ( postFinder || preFilter ) { + if ( postFinder ) { + // Get the final matcherOut by condensing this intermediate into postFinder contexts + temp = []; + i = matcherOut.length; + while ( i-- ) { + if ( (elem = matcherOut[i]) ) { + // Restore matcherIn since elem is not yet a final match + temp.push( (matcherIn[i] = elem) ); + } + } + postFinder( null, (matcherOut = []), temp, xml ); + } + + // Move matched elements from seed to results to keep them synchronized + i = matcherOut.length; + while ( i-- ) { + if ( (elem = matcherOut[i]) && + (temp = postFinder ? indexOf( seed, elem ) : preMap[i]) > -1 ) { + + seed[temp] = !(results[temp] = elem); + } + } + } + + // Add elements to results, through postFinder if defined + } else { + matcherOut = condense( + matcherOut === results ? + matcherOut.splice( preexisting, matcherOut.length ) : + matcherOut + ); + if ( postFinder ) { + postFinder( null, results, matcherOut, xml ); + } else { + push.apply( results, matcherOut ); + } + } + }); +} + +function matcherFromTokens( tokens ) { + var checkContext, matcher, j, + len = tokens.length, + leadingRelative = Expr.relative[ tokens[0].type ], + implicitRelative = leadingRelative || Expr.relative[" "], + i = leadingRelative ? 1 : 0, + + // The foundational matcher ensures that elements are reachable from top-level context(s) + matchContext = addCombinator( function( elem ) { + return elem === checkContext; + }, implicitRelative, true ), + matchAnyContext = addCombinator( function( elem ) { + return indexOf( checkContext, elem ) > -1; + }, implicitRelative, true ), + matchers = [ function( elem, context, xml ) { + var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || ( + (checkContext = context).nodeType ? + matchContext( elem, context, xml ) : + matchAnyContext( elem, context, xml ) ); + // Avoid hanging onto element (issue #299) + checkContext = null; + return ret; + } ]; + + for ( ; i < len; i++ ) { + if ( (matcher = Expr.relative[ tokens[i].type ]) ) { + matchers = [ addCombinator(elementMatcher( matchers ), matcher) ]; + } else { + matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches ); + + // Return special upon seeing a positional matcher + if ( matcher[ expando ] ) { + // Find the next relative operator (if any) for proper handling + j = ++i; + for ( ; j < len; j++ ) { + if ( Expr.relative[ tokens[j].type ] ) { + break; + } + } + return setMatcher( + i > 1 && elementMatcher( matchers ), + i > 1 && toSelector( + // If the preceding token was a descendant combinator, insert an implicit any-element `*` + tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" }) + ).replace( rtrim, "$1" ), + matcher, + i < j && matcherFromTokens( tokens.slice( i, j ) ), + j < len && matcherFromTokens( (tokens = tokens.slice( j )) ), + j < len && toSelector( tokens ) + ); + } + matchers.push( matcher ); + } + } + + return elementMatcher( matchers ); +} + +function matcherFromGroupMatchers( elementMatchers, setMatchers ) { + var bySet = setMatchers.length > 0, + byElement = elementMatchers.length > 0, + superMatcher = function( seed, context, xml, results, outermost ) { + var elem, j, matcher, + matchedCount = 0, + i = "0", + unmatched = seed && [], + setMatched = [], + contextBackup = outermostContext, + // We must always have either seed elements or outermost context + elems = seed || byElement && Expr.find["TAG"]( "*", outermost ), + // Use integer dirruns iff this is the outermost matcher + dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1), + len = elems.length; + + if ( outermost ) { + outermostContext = context === document || context || outermost; + } + + // Add elements passing elementMatchers directly to results + // Support: IE<9, Safari + // Tolerate NodeList properties (IE: "length"; Safari: ) matching elements by id + for ( ; i !== len && (elem = elems[i]) != null; i++ ) { + if ( byElement && elem ) { + j = 0; + if ( !context && elem.ownerDocument !== document ) { + setDocument( elem ); + xml = !documentIsHTML; + } + while ( (matcher = elementMatchers[j++]) ) { + if ( matcher( elem, context || document, xml) ) { + results.push( elem ); + break; + } + } + if ( outermost ) { + dirruns = dirrunsUnique; + } + } + + // Track unmatched elements for set filters + if ( bySet ) { + // They will have gone through all possible matchers + if ( (elem = !matcher && elem) ) { + matchedCount--; + } + + // Lengthen the array for every element, matched or not + if ( seed ) { + unmatched.push( elem ); + } + } + } + + // `i` is now the count of elements visited above, and adding it to `matchedCount` + // makes the latter nonnegative. + matchedCount += i; + + // Apply set filters to unmatched elements + // NOTE: This can be skipped if there are no unmatched elements (i.e., `matchedCount` + // equals `i`), unless we didn't visit _any_ elements in the above loop because we have + // no element matchers and no seed. + // Incrementing an initially-string "0" `i` allows `i` to remain a string only in that + // case, which will result in a "00" `matchedCount` that differs from `i` but is also + // numerically zero. + if ( bySet && i !== matchedCount ) { + j = 0; + while ( (matcher = setMatchers[j++]) ) { + matcher( unmatched, setMatched, context, xml ); + } + + if ( seed ) { + // Reintegrate element matches to eliminate the need for sorting + if ( matchedCount > 0 ) { + while ( i-- ) { + if ( !(unmatched[i] || setMatched[i]) ) { + setMatched[i] = pop.call( results ); + } + } + } + + // Discard index placeholder values to get only actual matches + setMatched = condense( setMatched ); + } + + // Add matches to results + push.apply( results, setMatched ); + + // Seedless set matches succeeding multiple successful matchers stipulate sorting + if ( outermost && !seed && setMatched.length > 0 && + ( matchedCount + setMatchers.length ) > 1 ) { + + Sizzle.uniqueSort( results ); + } + } + + // Override manipulation of globals by nested matchers + if ( outermost ) { + dirruns = dirrunsUnique; + outermostContext = contextBackup; + } + + return unmatched; + }; + + return bySet ? + markFunction( superMatcher ) : + superMatcher; +} + +compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) { + var i, + setMatchers = [], + elementMatchers = [], + cached = compilerCache[ selector + " " ]; + + if ( !cached ) { + // Generate a function of recursive functions that can be used to check each element + if ( !match ) { + match = tokenize( selector ); + } + i = match.length; + while ( i-- ) { + cached = matcherFromTokens( match[i] ); + if ( cached[ expando ] ) { + setMatchers.push( cached ); + } else { + elementMatchers.push( cached ); + } + } + + // Cache the compiled function + cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) ); + + // Save selector and tokenization + cached.selector = selector; + } + return cached; +}; + +/** + * A low-level selection function that works with Sizzle's compiled + * selector functions + * @param {String|Function} selector A selector or a pre-compiled + * selector function built with Sizzle.compile + * @param {Element} context + * @param {Array} [results] + * @param {Array} [seed] A set of elements to match against + */ +select = Sizzle.select = function( selector, context, results, seed ) { + var i, tokens, token, type, find, + compiled = typeof selector === "function" && selector, + match = !seed && tokenize( (selector = compiled.selector || selector) ); + + results = results || []; + + // Try to minimize operations if there is only one selector in the list and no seed + // (the latter of which guarantees us context) + if ( match.length === 1 ) { + + // Reduce context if the leading compound selector is an ID + tokens = match[0] = match[0].slice( 0 ); + if ( tokens.length > 2 && (token = tokens[0]).type === "ID" && + context.nodeType === 9 && documentIsHTML && Expr.relative[ tokens[1].type ] ) { + + context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0]; + if ( !context ) { + return results; + + // Precompiled matchers will still verify ancestry, so step up a level + } else if ( compiled ) { + context = context.parentNode; + } + + selector = selector.slice( tokens.shift().value.length ); + } + + // Fetch a seed set for right-to-left matching + i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length; + while ( i-- ) { + token = tokens[i]; + + // Abort if we hit a combinator + if ( Expr.relative[ (type = token.type) ] ) { + break; + } + if ( (find = Expr.find[ type ]) ) { + // Search, expanding context for leading sibling combinators + if ( (seed = find( + token.matches[0].replace( runescape, funescape ), + rsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context + )) ) { + + // If seed is empty or no tokens remain, we can return early + tokens.splice( i, 1 ); + selector = seed.length && toSelector( tokens ); + if ( !selector ) { + push.apply( results, seed ); + return results; + } + + break; + } + } + } + } + + // Compile and execute a filtering function if one is not provided + // Provide `match` to avoid retokenization if we modified the selector above + ( compiled || compile( selector, match ) )( + seed, + context, + !documentIsHTML, + results, + !context || rsibling.test( selector ) && testContext( context.parentNode ) || context + ); + return results; +}; + +// One-time assignments + +// Sort stability +support.sortStable = expando.split("").sort( sortOrder ).join("") === expando; + +// Support: Chrome 14-35+ +// Always assume duplicates if they aren't passed to the comparison function +support.detectDuplicates = !!hasDuplicate; + +// Initialize against the default document +setDocument(); + +// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27) +// Detached nodes confoundingly follow *each other* +support.sortDetached = assert(function( el ) { + // Should return 1, but returns 4 (following) + return el.compareDocumentPosition( document.createElement("fieldset") ) & 1; +}); + +// Support: IE<8 +// Prevent attribute/property "interpolation" +// https://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx +if ( !assert(function( el ) { + el.innerHTML = ""; + return el.firstChild.getAttribute("href") === "#" ; +}) ) { + addHandle( "type|href|height|width", function( elem, name, isXML ) { + if ( !isXML ) { + return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 ); + } + }); +} + +// Support: IE<9 +// Use defaultValue in place of getAttribute("value") +if ( !support.attributes || !assert(function( el ) { + el.innerHTML = ""; + el.firstChild.setAttribute( "value", "" ); + return el.firstChild.getAttribute( "value" ) === ""; +}) ) { + addHandle( "value", function( elem, name, isXML ) { + if ( !isXML && elem.nodeName.toLowerCase() === "input" ) { + return elem.defaultValue; + } + }); +} + +// Support: IE<9 +// Use getAttributeNode to fetch booleans when getAttribute lies +if ( !assert(function( el ) { + return el.getAttribute("disabled") == null; +}) ) { + addHandle( booleans, function( elem, name, isXML ) { + var val; + if ( !isXML ) { + return elem[ name ] === true ? name.toLowerCase() : + (val = elem.getAttributeNode( name )) && val.specified ? + val.value : + null; + } + }); +} + +return Sizzle; + +})( window ); + + + +jQuery.find = Sizzle; +jQuery.expr = Sizzle.selectors; + +// Deprecated +jQuery.expr[ ":" ] = jQuery.expr.pseudos; +jQuery.uniqueSort = jQuery.unique = Sizzle.uniqueSort; +jQuery.text = Sizzle.getText; +jQuery.isXMLDoc = Sizzle.isXML; +jQuery.contains = Sizzle.contains; +jQuery.escapeSelector = Sizzle.escape; + + + + +var dir = function( elem, dir, until ) { + var matched = [], + truncate = until !== undefined; + + while ( ( elem = elem[ dir ] ) && elem.nodeType !== 9 ) { + if ( elem.nodeType === 1 ) { + if ( truncate && jQuery( elem ).is( until ) ) { + break; + } + matched.push( elem ); + } + } + return matched; +}; + + +var siblings = function( n, elem ) { + var matched = []; + + for ( ; n; n = n.nextSibling ) { + if ( n.nodeType === 1 && n !== elem ) { + matched.push( n ); + } + } + + return matched; +}; + + +var rneedsContext = jQuery.expr.match.needsContext; + + + +function nodeName( elem, name ) { + + return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); + +}; +var rsingleTag = ( /^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i ); + + + +// Implement the identical functionality for filter and not +function winnow( elements, qualifier, not ) { + if ( isFunction( qualifier ) ) { + return jQuery.grep( elements, function( elem, i ) { + return !!qualifier.call( elem, i, elem ) !== not; + } ); + } + + // Single element + if ( qualifier.nodeType ) { + return jQuery.grep( elements, function( elem ) { + return ( elem === qualifier ) !== not; + } ); + } + + // Arraylike of elements (jQuery, arguments, Array) + if ( typeof qualifier !== "string" ) { + return jQuery.grep( elements, function( elem ) { + return ( indexOf.call( qualifier, elem ) > -1 ) !== not; + } ); + } + + // Filtered directly for both simple and complex selectors + return jQuery.filter( qualifier, elements, not ); +} + +jQuery.filter = function( expr, elems, not ) { + var elem = elems[ 0 ]; + + if ( not ) { + expr = ":not(" + expr + ")"; + } + + if ( elems.length === 1 && elem.nodeType === 1 ) { + return jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : []; + } + + return jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) { + return elem.nodeType === 1; + } ) ); +}; + +jQuery.fn.extend( { + find: function( selector ) { + var i, ret, + len = this.length, + self = this; + + if ( typeof selector !== "string" ) { + return this.pushStack( jQuery( selector ).filter( function() { + for ( i = 0; i < len; i++ ) { + if ( jQuery.contains( self[ i ], this ) ) { + return true; + } + } + } ) ); + } + + ret = this.pushStack( [] ); + + for ( i = 0; i < len; i++ ) { + jQuery.find( selector, self[ i ], ret ); + } + + return len > 1 ? jQuery.uniqueSort( ret ) : ret; + }, + filter: function( selector ) { + return this.pushStack( winnow( this, selector || [], false ) ); + }, + not: function( selector ) { + return this.pushStack( winnow( this, selector || [], true ) ); + }, + is: function( selector ) { + return !!winnow( + this, + + // If this is a positional/relative selector, check membership in the returned set + // so $("p:first").is("p:last") won't return true for a doc with two "p". + typeof selector === "string" && rneedsContext.test( selector ) ? + jQuery( selector ) : + selector || [], + false + ).length; + } +} ); + + +// Initialize a jQuery object + + +// A central reference to the root jQuery(document) +var rootjQuery, + + // A simple way to check for HTML strings + // Prioritize #id over to avoid XSS via location.hash (#9521) + // Strict HTML recognition (#11290: must start with <) + // Shortcut simple #id case for speed + rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/, + + init = jQuery.fn.init = function( selector, context, root ) { + var match, elem; + + // HANDLE: $(""), $(null), $(undefined), $(false) + if ( !selector ) { + return this; + } + + // Method init() accepts an alternate rootjQuery + // so migrate can support jQuery.sub (gh-2101) + root = root || rootjQuery; + + // Handle HTML strings + if ( typeof selector === "string" ) { + if ( selector[ 0 ] === "<" && + selector[ selector.length - 1 ] === ">" && + selector.length >= 3 ) { + + // Assume that strings that start and end with <> are HTML and skip the regex check + match = [ null, selector, null ]; + + } else { + match = rquickExpr.exec( selector ); + } + + // Match html or make sure no context is specified for #id + if ( match && ( match[ 1 ] || !context ) ) { + + // HANDLE: $(html) -> $(array) + if ( match[ 1 ] ) { + context = context instanceof jQuery ? context[ 0 ] : context; + + // Option to run scripts is true for back-compat + // Intentionally let the error be thrown if parseHTML is not present + jQuery.merge( this, jQuery.parseHTML( + match[ 1 ], + context && context.nodeType ? context.ownerDocument || context : document, + true + ) ); + + // HANDLE: $(html, props) + if ( rsingleTag.test( match[ 1 ] ) && jQuery.isPlainObject( context ) ) { + for ( match in context ) { + + // Properties of context are called as methods if possible + if ( isFunction( this[ match ] ) ) { + this[ match ]( context[ match ] ); + + // ...and otherwise set as attributes + } else { + this.attr( match, context[ match ] ); + } + } + } + + return this; + + // HANDLE: $(#id) + } else { + elem = document.getElementById( match[ 2 ] ); + + if ( elem ) { + + // Inject the element directly into the jQuery object + this[ 0 ] = elem; + this.length = 1; + } + return this; + } + + // HANDLE: $(expr, $(...)) + } else if ( !context || context.jquery ) { + return ( context || root ).find( selector ); + + // HANDLE: $(expr, context) + // (which is just equivalent to: $(context).find(expr) + } else { + return this.constructor( context ).find( selector ); + } + + // HANDLE: $(DOMElement) + } else if ( selector.nodeType ) { + this[ 0 ] = selector; + this.length = 1; + return this; + + // HANDLE: $(function) + // Shortcut for document ready + } else if ( isFunction( selector ) ) { + return root.ready !== undefined ? + root.ready( selector ) : + + // Execute immediately if ready is not present + selector( jQuery ); + } + + return jQuery.makeArray( selector, this ); + }; + +// Give the init function the jQuery prototype for later instantiation +init.prototype = jQuery.fn; + +// Initialize central reference +rootjQuery = jQuery( document ); + + +var rparentsprev = /^(?:parents|prev(?:Until|All))/, + + // Methods guaranteed to produce a unique set when starting from a unique set + guaranteedUnique = { + children: true, + contents: true, + next: true, + prev: true + }; + +jQuery.fn.extend( { + has: function( target ) { + var targets = jQuery( target, this ), + l = targets.length; + + return this.filter( function() { + var i = 0; + for ( ; i < l; i++ ) { + if ( jQuery.contains( this, targets[ i ] ) ) { + return true; + } + } + } ); + }, + + closest: function( selectors, context ) { + var cur, + i = 0, + l = this.length, + matched = [], + targets = typeof selectors !== "string" && jQuery( selectors ); + + // Positional selectors never match, since there's no _selection_ context + if ( !rneedsContext.test( selectors ) ) { + for ( ; i < l; i++ ) { + for ( cur = this[ i ]; cur && cur !== context; cur = cur.parentNode ) { + + // Always skip document fragments + if ( cur.nodeType < 11 && ( targets ? + targets.index( cur ) > -1 : + + // Don't pass non-elements to Sizzle + cur.nodeType === 1 && + jQuery.find.matchesSelector( cur, selectors ) ) ) { + + matched.push( cur ); + break; + } + } + } + } + + return this.pushStack( matched.length > 1 ? jQuery.uniqueSort( matched ) : matched ); + }, + + // Determine the position of an element within the set + index: function( elem ) { + + // No argument, return index in parent + if ( !elem ) { + return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1; + } + + // Index in selector + if ( typeof elem === "string" ) { + return indexOf.call( jQuery( elem ), this[ 0 ] ); + } + + // Locate the position of the desired element + return indexOf.call( this, + + // If it receives a jQuery object, the first element is used + elem.jquery ? elem[ 0 ] : elem + ); + }, + + add: function( selector, context ) { + return this.pushStack( + jQuery.uniqueSort( + jQuery.merge( this.get(), jQuery( selector, context ) ) + ) + ); + }, + + addBack: function( selector ) { + return this.add( selector == null ? + this.prevObject : this.prevObject.filter( selector ) + ); + } +} ); + +function sibling( cur, dir ) { + while ( ( cur = cur[ dir ] ) && cur.nodeType !== 1 ) {} + return cur; +} + +jQuery.each( { + parent: function( elem ) { + var parent = elem.parentNode; + return parent && parent.nodeType !== 11 ? parent : null; + }, + parents: function( elem ) { + return dir( elem, "parentNode" ); + }, + parentsUntil: function( elem, i, until ) { + return dir( elem, "parentNode", until ); + }, + next: function( elem ) { + return sibling( elem, "nextSibling" ); + }, + prev: function( elem ) { + return sibling( elem, "previousSibling" ); + }, + nextAll: function( elem ) { + return dir( elem, "nextSibling" ); + }, + prevAll: function( elem ) { + return dir( elem, "previousSibling" ); + }, + nextUntil: function( elem, i, until ) { + return dir( elem, "nextSibling", until ); + }, + prevUntil: function( elem, i, until ) { + return dir( elem, "previousSibling", until ); + }, + siblings: function( elem ) { + return siblings( ( elem.parentNode || {} ).firstChild, elem ); + }, + children: function( elem ) { + return siblings( elem.firstChild ); + }, + contents: function( elem ) { + if ( nodeName( elem, "iframe" ) ) { + return elem.contentDocument; + } + + // Support: IE 9 - 11 only, iOS 7 only, Android Browser <=4.3 only + // Treat the template element as a regular one in browsers that + // don't support it. + if ( nodeName( elem, "template" ) ) { + elem = elem.content || elem; + } + + return jQuery.merge( [], elem.childNodes ); + } +}, function( name, fn ) { + jQuery.fn[ name ] = function( until, selector ) { + var matched = jQuery.map( this, fn, until ); + + if ( name.slice( -5 ) !== "Until" ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + matched = jQuery.filter( selector, matched ); + } + + if ( this.length > 1 ) { + + // Remove duplicates + if ( !guaranteedUnique[ name ] ) { + jQuery.uniqueSort( matched ); + } + + // Reverse order for parents* and prev-derivatives + if ( rparentsprev.test( name ) ) { + matched.reverse(); + } + } + + return this.pushStack( matched ); + }; +} ); +var rnothtmlwhite = ( /[^\x20\t\r\n\f]+/g ); + + + +// Convert String-formatted options into Object-formatted ones +function createOptions( options ) { + var object = {}; + jQuery.each( options.match( rnothtmlwhite ) || [], function( _, flag ) { + object[ flag ] = true; + } ); + return object; +} + +/* + * Create a callback list using the following parameters: + * + * options: an optional list of space-separated options that will change how + * the callback list behaves or a more traditional option object + * + * By default a callback list will act like an event callback list and can be + * "fired" multiple times. + * + * Possible options: + * + * once: will ensure the callback list can only be fired once (like a Deferred) + * + * memory: will keep track of previous values and will call any callback added + * after the list has been fired right away with the latest "memorized" + * values (like a Deferred) + * + * unique: will ensure a callback can only be added once (no duplicate in the list) + * + * stopOnFalse: interrupt callings when a callback returns false + * + */ +jQuery.Callbacks = function( options ) { + + // Convert options from String-formatted to Object-formatted if needed + // (we check in cache first) + options = typeof options === "string" ? + createOptions( options ) : + jQuery.extend( {}, options ); + + var // Flag to know if list is currently firing + firing, + + // Last fire value for non-forgettable lists + memory, + + // Flag to know if list was already fired + fired, + + // Flag to prevent firing + locked, + + // Actual callback list + list = [], + + // Queue of execution data for repeatable lists + queue = [], + + // Index of currently firing callback (modified by add/remove as needed) + firingIndex = -1, + + // Fire callbacks + fire = function() { + + // Enforce single-firing + locked = locked || options.once; + + // Execute callbacks for all pending executions, + // respecting firingIndex overrides and runtime changes + fired = firing = true; + for ( ; queue.length; firingIndex = -1 ) { + memory = queue.shift(); + while ( ++firingIndex < list.length ) { + + // Run callback and check for early termination + if ( list[ firingIndex ].apply( memory[ 0 ], memory[ 1 ] ) === false && + options.stopOnFalse ) { + + // Jump to end and forget the data so .add doesn't re-fire + firingIndex = list.length; + memory = false; + } + } + } + + // Forget the data if we're done with it + if ( !options.memory ) { + memory = false; + } + + firing = false; + + // Clean up if we're done firing for good + if ( locked ) { + + // Keep an empty list if we have data for future add calls + if ( memory ) { + list = []; + + // Otherwise, this object is spent + } else { + list = ""; + } + } + }, + + // Actual Callbacks object + self = { + + // Add a callback or a collection of callbacks to the list + add: function() { + if ( list ) { + + // If we have memory from a past run, we should fire after adding + if ( memory && !firing ) { + firingIndex = list.length - 1; + queue.push( memory ); + } + + ( function add( args ) { + jQuery.each( args, function( _, arg ) { + if ( isFunction( arg ) ) { + if ( !options.unique || !self.has( arg ) ) { + list.push( arg ); + } + } else if ( arg && arg.length && toType( arg ) !== "string" ) { + + // Inspect recursively + add( arg ); + } + } ); + } )( arguments ); + + if ( memory && !firing ) { + fire(); + } + } + return this; + }, + + // Remove a callback from the list + remove: function() { + jQuery.each( arguments, function( _, arg ) { + var index; + while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) { + list.splice( index, 1 ); + + // Handle firing indexes + if ( index <= firingIndex ) { + firingIndex--; + } + } + } ); + return this; + }, + + // Check if a given callback is in the list. + // If no argument is given, return whether or not list has callbacks attached. + has: function( fn ) { + return fn ? + jQuery.inArray( fn, list ) > -1 : + list.length > 0; + }, + + // Remove all callbacks from the list + empty: function() { + if ( list ) { + list = []; + } + return this; + }, + + // Disable .fire and .add + // Abort any current/pending executions + // Clear all callbacks and values + disable: function() { + locked = queue = []; + list = memory = ""; + return this; + }, + disabled: function() { + return !list; + }, + + // Disable .fire + // Also disable .add unless we have memory (since it would have no effect) + // Abort any pending executions + lock: function() { + locked = queue = []; + if ( !memory && !firing ) { + list = memory = ""; + } + return this; + }, + locked: function() { + return !!locked; + }, + + // Call all callbacks with the given context and arguments + fireWith: function( context, args ) { + if ( !locked ) { + args = args || []; + args = [ context, args.slice ? args.slice() : args ]; + queue.push( args ); + if ( !firing ) { + fire(); + } + } + return this; + }, + + // Call all the callbacks with the given arguments + fire: function() { + self.fireWith( this, arguments ); + return this; + }, + + // To know if the callbacks have already been called at least once + fired: function() { + return !!fired; + } + }; + + return self; +}; + + +function Identity( v ) { + return v; +} +function Thrower( ex ) { + throw ex; +} + +function adoptValue( value, resolve, reject, noValue ) { + var method; + + try { + + // Check for promise aspect first to privilege synchronous behavior + if ( value && isFunction( ( method = value.promise ) ) ) { + method.call( value ).done( resolve ).fail( reject ); + + // Other thenables + } else if ( value && isFunction( ( method = value.then ) ) ) { + method.call( value, resolve, reject ); + + // Other non-thenables + } else { + + // Control `resolve` arguments by letting Array#slice cast boolean `noValue` to integer: + // * false: [ value ].slice( 0 ) => resolve( value ) + // * true: [ value ].slice( 1 ) => resolve() + resolve.apply( undefined, [ value ].slice( noValue ) ); + } + + // For Promises/A+, convert exceptions into rejections + // Since jQuery.when doesn't unwrap thenables, we can skip the extra checks appearing in + // Deferred#then to conditionally suppress rejection. + } catch ( value ) { + + // Support: Android 4.0 only + // Strict mode functions invoked without .call/.apply get global-object context + reject.apply( undefined, [ value ] ); + } +} + +jQuery.extend( { + + Deferred: function( func ) { + var tuples = [ + + // action, add listener, callbacks, + // ... .then handlers, argument index, [final state] + [ "notify", "progress", jQuery.Callbacks( "memory" ), + jQuery.Callbacks( "memory" ), 2 ], + [ "resolve", "done", jQuery.Callbacks( "once memory" ), + jQuery.Callbacks( "once memory" ), 0, "resolved" ], + [ "reject", "fail", jQuery.Callbacks( "once memory" ), + jQuery.Callbacks( "once memory" ), 1, "rejected" ] + ], + state = "pending", + promise = { + state: function() { + return state; + }, + always: function() { + deferred.done( arguments ).fail( arguments ); + return this; + }, + "catch": function( fn ) { + return promise.then( null, fn ); + }, + + // Keep pipe for back-compat + pipe: function( /* fnDone, fnFail, fnProgress */ ) { + var fns = arguments; + + return jQuery.Deferred( function( newDefer ) { + jQuery.each( tuples, function( i, tuple ) { + + // Map tuples (progress, done, fail) to arguments (done, fail, progress) + var fn = isFunction( fns[ tuple[ 4 ] ] ) && fns[ tuple[ 4 ] ]; + + // deferred.progress(function() { bind to newDefer or newDefer.notify }) + // deferred.done(function() { bind to newDefer or newDefer.resolve }) + // deferred.fail(function() { bind to newDefer or newDefer.reject }) + deferred[ tuple[ 1 ] ]( function() { + var returned = fn && fn.apply( this, arguments ); + if ( returned && isFunction( returned.promise ) ) { + returned.promise() + .progress( newDefer.notify ) + .done( newDefer.resolve ) + .fail( newDefer.reject ); + } else { + newDefer[ tuple[ 0 ] + "With" ]( + this, + fn ? [ returned ] : arguments + ); + } + } ); + } ); + fns = null; + } ).promise(); + }, + then: function( onFulfilled, onRejected, onProgress ) { + var maxDepth = 0; + function resolve( depth, deferred, handler, special ) { + return function() { + var that = this, + args = arguments, + mightThrow = function() { + var returned, then; + + // Support: Promises/A+ section 2.3.3.3.3 + // https://promisesaplus.com/#point-59 + // Ignore double-resolution attempts + if ( depth < maxDepth ) { + return; + } + + returned = handler.apply( that, args ); + + // Support: Promises/A+ section 2.3.1 + // https://promisesaplus.com/#point-48 + if ( returned === deferred.promise() ) { + throw new TypeError( "Thenable self-resolution" ); + } + + // Support: Promises/A+ sections 2.3.3.1, 3.5 + // https://promisesaplus.com/#point-54 + // https://promisesaplus.com/#point-75 + // Retrieve `then` only once + then = returned && + + // Support: Promises/A+ section 2.3.4 + // https://promisesaplus.com/#point-64 + // Only check objects and functions for thenability + ( typeof returned === "object" || + typeof returned === "function" ) && + returned.then; + + // Handle a returned thenable + if ( isFunction( then ) ) { + + // Special processors (notify) just wait for resolution + if ( special ) { + then.call( + returned, + resolve( maxDepth, deferred, Identity, special ), + resolve( maxDepth, deferred, Thrower, special ) + ); + + // Normal processors (resolve) also hook into progress + } else { + + // ...and disregard older resolution values + maxDepth++; + + then.call( + returned, + resolve( maxDepth, deferred, Identity, special ), + resolve( maxDepth, deferred, Thrower, special ), + resolve( maxDepth, deferred, Identity, + deferred.notifyWith ) + ); + } + + // Handle all other returned values + } else { + + // Only substitute handlers pass on context + // and multiple values (non-spec behavior) + if ( handler !== Identity ) { + that = undefined; + args = [ returned ]; + } + + // Process the value(s) + // Default process is resolve + ( special || deferred.resolveWith )( that, args ); + } + }, + + // Only normal processors (resolve) catch and reject exceptions + process = special ? + mightThrow : + function() { + try { + mightThrow(); + } catch ( e ) { + + if ( jQuery.Deferred.exceptionHook ) { + jQuery.Deferred.exceptionHook( e, + process.stackTrace ); + } + + // Support: Promises/A+ section 2.3.3.3.4.1 + // https://promisesaplus.com/#point-61 + // Ignore post-resolution exceptions + if ( depth + 1 >= maxDepth ) { + + // Only substitute handlers pass on context + // and multiple values (non-spec behavior) + if ( handler !== Thrower ) { + that = undefined; + args = [ e ]; + } + + deferred.rejectWith( that, args ); + } + } + }; + + // Support: Promises/A+ section 2.3.3.3.1 + // https://promisesaplus.com/#point-57 + // Re-resolve promises immediately to dodge false rejection from + // subsequent errors + if ( depth ) { + process(); + } else { + + // Call an optional hook to record the stack, in case of exception + // since it's otherwise lost when execution goes async + if ( jQuery.Deferred.getStackHook ) { + process.stackTrace = jQuery.Deferred.getStackHook(); + } + window.setTimeout( process ); + } + }; + } + + return jQuery.Deferred( function( newDefer ) { + + // progress_handlers.add( ... ) + tuples[ 0 ][ 3 ].add( + resolve( + 0, + newDefer, + isFunction( onProgress ) ? + onProgress : + Identity, + newDefer.notifyWith + ) + ); + + // fulfilled_handlers.add( ... ) + tuples[ 1 ][ 3 ].add( + resolve( + 0, + newDefer, + isFunction( onFulfilled ) ? + onFulfilled : + Identity + ) + ); + + // rejected_handlers.add( ... ) + tuples[ 2 ][ 3 ].add( + resolve( + 0, + newDefer, + isFunction( onRejected ) ? + onRejected : + Thrower + ) + ); + } ).promise(); + }, + + // Get a promise for this deferred + // If obj is provided, the promise aspect is added to the object + promise: function( obj ) { + return obj != null ? jQuery.extend( obj, promise ) : promise; + } + }, + deferred = {}; + + // Add list-specific methods + jQuery.each( tuples, function( i, tuple ) { + var list = tuple[ 2 ], + stateString = tuple[ 5 ]; + + // promise.progress = list.add + // promise.done = list.add + // promise.fail = list.add + promise[ tuple[ 1 ] ] = list.add; + + // Handle state + if ( stateString ) { + list.add( + function() { + + // state = "resolved" (i.e., fulfilled) + // state = "rejected" + state = stateString; + }, + + // rejected_callbacks.disable + // fulfilled_callbacks.disable + tuples[ 3 - i ][ 2 ].disable, + + // rejected_handlers.disable + // fulfilled_handlers.disable + tuples[ 3 - i ][ 3 ].disable, + + // progress_callbacks.lock + tuples[ 0 ][ 2 ].lock, + + // progress_handlers.lock + tuples[ 0 ][ 3 ].lock + ); + } + + // progress_handlers.fire + // fulfilled_handlers.fire + // rejected_handlers.fire + list.add( tuple[ 3 ].fire ); + + // deferred.notify = function() { deferred.notifyWith(...) } + // deferred.resolve = function() { deferred.resolveWith(...) } + // deferred.reject = function() { deferred.rejectWith(...) } + deferred[ tuple[ 0 ] ] = function() { + deferred[ tuple[ 0 ] + "With" ]( this === deferred ? undefined : this, arguments ); + return this; + }; + + // deferred.notifyWith = list.fireWith + // deferred.resolveWith = list.fireWith + // deferred.rejectWith = list.fireWith + deferred[ tuple[ 0 ] + "With" ] = list.fireWith; + } ); + + // Make the deferred a promise + promise.promise( deferred ); + + // Call given func if any + if ( func ) { + func.call( deferred, deferred ); + } + + // All done! + return deferred; + }, + + // Deferred helper + when: function( singleValue ) { + var + + // count of uncompleted subordinates + remaining = arguments.length, + + // count of unprocessed arguments + i = remaining, + + // subordinate fulfillment data + resolveContexts = Array( i ), + resolveValues = slice.call( arguments ), + + // the master Deferred + master = jQuery.Deferred(), + + // subordinate callback factory + updateFunc = function( i ) { + return function( value ) { + resolveContexts[ i ] = this; + resolveValues[ i ] = arguments.length > 1 ? slice.call( arguments ) : value; + if ( !( --remaining ) ) { + master.resolveWith( resolveContexts, resolveValues ); + } + }; + }; + + // Single- and empty arguments are adopted like Promise.resolve + if ( remaining <= 1 ) { + adoptValue( singleValue, master.done( updateFunc( i ) ).resolve, master.reject, + !remaining ); + + // Use .then() to unwrap secondary thenables (cf. gh-3000) + if ( master.state() === "pending" || + isFunction( resolveValues[ i ] && resolveValues[ i ].then ) ) { + + return master.then(); + } + } + + // Multiple arguments are aggregated like Promise.all array elements + while ( i-- ) { + adoptValue( resolveValues[ i ], updateFunc( i ), master.reject ); + } + + return master.promise(); + } +} ); + + +// These usually indicate a programmer mistake during development, +// warn about them ASAP rather than swallowing them by default. +var rerrorNames = /^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/; + +jQuery.Deferred.exceptionHook = function( error, stack ) { + + // Support: IE 8 - 9 only + // Console exists when dev tools are open, which can happen at any time + if ( window.console && window.console.warn && error && rerrorNames.test( error.name ) ) { + window.console.warn( "jQuery.Deferred exception: " + error.message, error.stack, stack ); + } +}; + + + + +jQuery.readyException = function( error ) { + window.setTimeout( function() { + throw error; + } ); +}; + + + + +// The deferred used on DOM ready +var readyList = jQuery.Deferred(); + +jQuery.fn.ready = function( fn ) { + + readyList + .then( fn ) + + // Wrap jQuery.readyException in a function so that the lookup + // happens at the time of error handling instead of callback + // registration. + .catch( function( error ) { + jQuery.readyException( error ); + } ); + + return this; +}; + +jQuery.extend( { + + // Is the DOM ready to be used? Set to true once it occurs. + isReady: false, + + // A counter to track how many items to wait for before + // the ready event fires. See #6781 + readyWait: 1, + + // Handle when the DOM is ready + ready: function( wait ) { + + // Abort if there are pending holds or we're already ready + if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) { + return; + } + + // Remember that the DOM is ready + jQuery.isReady = true; + + // If a normal DOM Ready event fired, decrement, and wait if need be + if ( wait !== true && --jQuery.readyWait > 0 ) { + return; + } + + // If there are functions bound, to execute + readyList.resolveWith( document, [ jQuery ] ); + } +} ); + +jQuery.ready.then = readyList.then; + +// The ready event handler and self cleanup method +function completed() { + document.removeEventListener( "DOMContentLoaded", completed ); + window.removeEventListener( "load", completed ); + jQuery.ready(); +} + +// Catch cases where $(document).ready() is called +// after the browser event has already occurred. +// Support: IE <=9 - 10 only +// Older IE sometimes signals "interactive" too soon +if ( document.readyState === "complete" || + ( document.readyState !== "loading" && !document.documentElement.doScroll ) ) { + + // Handle it asynchronously to allow scripts the opportunity to delay ready + window.setTimeout( jQuery.ready ); + +} else { + + // Use the handy event callback + document.addEventListener( "DOMContentLoaded", completed ); + + // A fallback to window.onload, that will always work + window.addEventListener( "load", completed ); +} + + + + +// Multifunctional method to get and set values of a collection +// The value/s can optionally be executed if it's a function +var access = function( elems, fn, key, value, chainable, emptyGet, raw ) { + var i = 0, + len = elems.length, + bulk = key == null; + + // Sets many values + if ( toType( key ) === "object" ) { + chainable = true; + for ( i in key ) { + access( elems, fn, i, key[ i ], true, emptyGet, raw ); + } + + // Sets one value + } else if ( value !== undefined ) { + chainable = true; + + if ( !isFunction( value ) ) { + raw = true; + } + + if ( bulk ) { + + // Bulk operations run against the entire set + if ( raw ) { + fn.call( elems, value ); + fn = null; + + // ...except when executing function values + } else { + bulk = fn; + fn = function( elem, key, value ) { + return bulk.call( jQuery( elem ), value ); + }; + } + } + + if ( fn ) { + for ( ; i < len; i++ ) { + fn( + elems[ i ], key, raw ? + value : + value.call( elems[ i ], i, fn( elems[ i ], key ) ) + ); + } + } + } + + if ( chainable ) { + return elems; + } + + // Gets + if ( bulk ) { + return fn.call( elems ); + } + + return len ? fn( elems[ 0 ], key ) : emptyGet; +}; + + +// Matches dashed string for camelizing +var rmsPrefix = /^-ms-/, + rdashAlpha = /-([a-z])/g; + +// Used by camelCase as callback to replace() +function fcamelCase( all, letter ) { + return letter.toUpperCase(); +} + +// Convert dashed to camelCase; used by the css and data modules +// Support: IE <=9 - 11, Edge 12 - 15 +// Microsoft forgot to hump their vendor prefix (#9572) +function camelCase( string ) { + return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); +} +var acceptData = function( owner ) { + + // Accepts only: + // - Node + // - Node.ELEMENT_NODE + // - Node.DOCUMENT_NODE + // - Object + // - Any + return owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType ); +}; + + + + +function Data() { + this.expando = jQuery.expando + Data.uid++; +} + +Data.uid = 1; + +Data.prototype = { + + cache: function( owner ) { + + // Check if the owner object already has a cache + var value = owner[ this.expando ]; + + // If not, create one + if ( !value ) { + value = {}; + + // We can accept data for non-element nodes in modern browsers, + // but we should not, see #8335. + // Always return an empty object. + if ( acceptData( owner ) ) { + + // If it is a node unlikely to be stringify-ed or looped over + // use plain assignment + if ( owner.nodeType ) { + owner[ this.expando ] = value; + + // Otherwise secure it in a non-enumerable property + // configurable must be true to allow the property to be + // deleted when data is removed + } else { + Object.defineProperty( owner, this.expando, { + value: value, + configurable: true + } ); + } + } + } + + return value; + }, + set: function( owner, data, value ) { + var prop, + cache = this.cache( owner ); + + // Handle: [ owner, key, value ] args + // Always use camelCase key (gh-2257) + if ( typeof data === "string" ) { + cache[ camelCase( data ) ] = value; + + // Handle: [ owner, { properties } ] args + } else { + + // Copy the properties one-by-one to the cache object + for ( prop in data ) { + cache[ camelCase( prop ) ] = data[ prop ]; + } + } + return cache; + }, + get: function( owner, key ) { + return key === undefined ? + this.cache( owner ) : + + // Always use camelCase key (gh-2257) + owner[ this.expando ] && owner[ this.expando ][ camelCase( key ) ]; + }, + access: function( owner, key, value ) { + + // In cases where either: + // + // 1. No key was specified + // 2. A string key was specified, but no value provided + // + // Take the "read" path and allow the get method to determine + // which value to return, respectively either: + // + // 1. The entire cache object + // 2. The data stored at the key + // + if ( key === undefined || + ( ( key && typeof key === "string" ) && value === undefined ) ) { + + return this.get( owner, key ); + } + + // When the key is not a string, or both a key and value + // are specified, set or extend (existing objects) with either: + // + // 1. An object of properties + // 2. A key and value + // + this.set( owner, key, value ); + + // Since the "set" path can have two possible entry points + // return the expected data based on which path was taken[*] + return value !== undefined ? value : key; + }, + remove: function( owner, key ) { + var i, + cache = owner[ this.expando ]; + + if ( cache === undefined ) { + return; + } + + if ( key !== undefined ) { + + // Support array or space separated string of keys + if ( Array.isArray( key ) ) { + + // If key is an array of keys... + // We always set camelCase keys, so remove that. + key = key.map( camelCase ); + } else { + key = camelCase( key ); + + // If a key with the spaces exists, use it. + // Otherwise, create an array by matching non-whitespace + key = key in cache ? + [ key ] : + ( key.match( rnothtmlwhite ) || [] ); + } + + i = key.length; + + while ( i-- ) { + delete cache[ key[ i ] ]; + } + } + + // Remove the expando if there's no more data + if ( key === undefined || jQuery.isEmptyObject( cache ) ) { + + // Support: Chrome <=35 - 45 + // Webkit & Blink performance suffers when deleting properties + // from DOM nodes, so set to undefined instead + // https://bugs.chromium.org/p/chromium/issues/detail?id=378607 (bug restricted) + if ( owner.nodeType ) { + owner[ this.expando ] = undefined; + } else { + delete owner[ this.expando ]; + } + } + }, + hasData: function( owner ) { + var cache = owner[ this.expando ]; + return cache !== undefined && !jQuery.isEmptyObject( cache ); + } +}; +var dataPriv = new Data(); + +var dataUser = new Data(); + + + +// Implementation Summary +// +// 1. Enforce API surface and semantic compatibility with 1.9.x branch +// 2. Improve the module's maintainability by reducing the storage +// paths to a single mechanism. +// 3. Use the same single mechanism to support "private" and "user" data. +// 4. _Never_ expose "private" data to user code (TODO: Drop _data, _removeData) +// 5. Avoid exposing implementation details on user objects (eg. expando properties) +// 6. Provide a clear path for implementation upgrade to WeakMap in 2014 + +var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/, + rmultiDash = /[A-Z]/g; + +function getData( data ) { + if ( data === "true" ) { + return true; + } + + if ( data === "false" ) { + return false; + } + + if ( data === "null" ) { + return null; + } + + // Only convert to a number if it doesn't change the string + if ( data === +data + "" ) { + return +data; + } + + if ( rbrace.test( data ) ) { + return JSON.parse( data ); + } + + return data; +} + +function dataAttr( elem, key, data ) { + var name; + + // If nothing was found internally, try to fetch any + // data from the HTML5 data-* attribute + if ( data === undefined && elem.nodeType === 1 ) { + name = "data-" + key.replace( rmultiDash, "-$&" ).toLowerCase(); + data = elem.getAttribute( name ); + + if ( typeof data === "string" ) { + try { + data = getData( data ); + } catch ( e ) {} + + // Make sure we set the data so it isn't changed later + dataUser.set( elem, key, data ); + } else { + data = undefined; + } + } + return data; +} + +jQuery.extend( { + hasData: function( elem ) { + return dataUser.hasData( elem ) || dataPriv.hasData( elem ); + }, + + data: function( elem, name, data ) { + return dataUser.access( elem, name, data ); + }, + + removeData: function( elem, name ) { + dataUser.remove( elem, name ); + }, + + // TODO: Now that all calls to _data and _removeData have been replaced + // with direct calls to dataPriv methods, these can be deprecated. + _data: function( elem, name, data ) { + return dataPriv.access( elem, name, data ); + }, + + _removeData: function( elem, name ) { + dataPriv.remove( elem, name ); + } +} ); + +jQuery.fn.extend( { + data: function( key, value ) { + var i, name, data, + elem = this[ 0 ], + attrs = elem && elem.attributes; + + // Gets all values + if ( key === undefined ) { + if ( this.length ) { + data = dataUser.get( elem ); + + if ( elem.nodeType === 1 && !dataPriv.get( elem, "hasDataAttrs" ) ) { + i = attrs.length; + while ( i-- ) { + + // Support: IE 11 only + // The attrs elements can be null (#14894) + if ( attrs[ i ] ) { + name = attrs[ i ].name; + if ( name.indexOf( "data-" ) === 0 ) { + name = camelCase( name.slice( 5 ) ); + dataAttr( elem, name, data[ name ] ); + } + } + } + dataPriv.set( elem, "hasDataAttrs", true ); + } + } + + return data; + } + + // Sets multiple values + if ( typeof key === "object" ) { + return this.each( function() { + dataUser.set( this, key ); + } ); + } + + return access( this, function( value ) { + var data; + + // The calling jQuery object (element matches) is not empty + // (and therefore has an element appears at this[ 0 ]) and the + // `value` parameter was not undefined. An empty jQuery object + // will result in `undefined` for elem = this[ 0 ] which will + // throw an exception if an attempt to read a data cache is made. + if ( elem && value === undefined ) { + + // Attempt to get data from the cache + // The key will always be camelCased in Data + data = dataUser.get( elem, key ); + if ( data !== undefined ) { + return data; + } + + // Attempt to "discover" the data in + // HTML5 custom data-* attrs + data = dataAttr( elem, key ); + if ( data !== undefined ) { + return data; + } + + // We tried really hard, but the data doesn't exist. + return; + } + + // Set the data... + this.each( function() { + + // We always store the camelCased key + dataUser.set( this, key, value ); + } ); + }, null, value, arguments.length > 1, null, true ); + }, + + removeData: function( key ) { + return this.each( function() { + dataUser.remove( this, key ); + } ); + } +} ); + + +jQuery.extend( { + queue: function( elem, type, data ) { + var queue; + + if ( elem ) { + type = ( type || "fx" ) + "queue"; + queue = dataPriv.get( elem, type ); + + // Speed up dequeue by getting out quickly if this is just a lookup + if ( data ) { + if ( !queue || Array.isArray( data ) ) { + queue = dataPriv.access( elem, type, jQuery.makeArray( data ) ); + } else { + queue.push( data ); + } + } + return queue || []; + } + }, + + dequeue: function( elem, type ) { + type = type || "fx"; + + var queue = jQuery.queue( elem, type ), + startLength = queue.length, + fn = queue.shift(), + hooks = jQuery._queueHooks( elem, type ), + next = function() { + jQuery.dequeue( elem, type ); + }; + + // If the fx queue is dequeued, always remove the progress sentinel + if ( fn === "inprogress" ) { + fn = queue.shift(); + startLength--; + } + + if ( fn ) { + + // Add a progress sentinel to prevent the fx queue from being + // automatically dequeued + if ( type === "fx" ) { + queue.unshift( "inprogress" ); + } + + // Clear up the last queue stop function + delete hooks.stop; + fn.call( elem, next, hooks ); + } + + if ( !startLength && hooks ) { + hooks.empty.fire(); + } + }, + + // Not public - generate a queueHooks object, or return the current one + _queueHooks: function( elem, type ) { + var key = type + "queueHooks"; + return dataPriv.get( elem, key ) || dataPriv.access( elem, key, { + empty: jQuery.Callbacks( "once memory" ).add( function() { + dataPriv.remove( elem, [ type + "queue", key ] ); + } ) + } ); + } +} ); + +jQuery.fn.extend( { + queue: function( type, data ) { + var setter = 2; + + if ( typeof type !== "string" ) { + data = type; + type = "fx"; + setter--; + } + + if ( arguments.length < setter ) { + return jQuery.queue( this[ 0 ], type ); + } + + return data === undefined ? + this : + this.each( function() { + var queue = jQuery.queue( this, type, data ); + + // Ensure a hooks for this queue + jQuery._queueHooks( this, type ); + + if ( type === "fx" && queue[ 0 ] !== "inprogress" ) { + jQuery.dequeue( this, type ); + } + } ); + }, + dequeue: function( type ) { + return this.each( function() { + jQuery.dequeue( this, type ); + } ); + }, + clearQueue: function( type ) { + return this.queue( type || "fx", [] ); + }, + + // Get a promise resolved when queues of a certain type + // are emptied (fx is the type by default) + promise: function( type, obj ) { + var tmp, + count = 1, + defer = jQuery.Deferred(), + elements = this, + i = this.length, + resolve = function() { + if ( !( --count ) ) { + defer.resolveWith( elements, [ elements ] ); + } + }; + + if ( typeof type !== "string" ) { + obj = type; + type = undefined; + } + type = type || "fx"; + + while ( i-- ) { + tmp = dataPriv.get( elements[ i ], type + "queueHooks" ); + if ( tmp && tmp.empty ) { + count++; + tmp.empty.add( resolve ); + } + } + resolve(); + return defer.promise( obj ); + } +} ); +var pnum = ( /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/ ).source; + +var rcssNum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" ); + + +var cssExpand = [ "Top", "Right", "Bottom", "Left" ]; + +var isHiddenWithinTree = function( elem, el ) { + + // isHiddenWithinTree might be called from jQuery#filter function; + // in that case, element will be second argument + elem = el || elem; + + // Inline style trumps all + return elem.style.display === "none" || + elem.style.display === "" && + + // Otherwise, check computed style + // Support: Firefox <=43 - 45 + // Disconnected elements can have computed display: none, so first confirm that elem is + // in the document. + jQuery.contains( elem.ownerDocument, elem ) && + + jQuery.css( elem, "display" ) === "none"; + }; + +var swap = function( elem, options, callback, args ) { + var ret, name, + old = {}; + + // Remember the old values, and insert the new ones + for ( name in options ) { + old[ name ] = elem.style[ name ]; + elem.style[ name ] = options[ name ]; + } + + ret = callback.apply( elem, args || [] ); + + // Revert the old values + for ( name in options ) { + elem.style[ name ] = old[ name ]; + } + + return ret; +}; + + + + +function adjustCSS( elem, prop, valueParts, tween ) { + var adjusted, scale, + maxIterations = 20, + currentValue = tween ? + function() { + return tween.cur(); + } : + function() { + return jQuery.css( elem, prop, "" ); + }, + initial = currentValue(), + unit = valueParts && valueParts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ), + + // Starting value computation is required for potential unit mismatches + initialInUnit = ( jQuery.cssNumber[ prop ] || unit !== "px" && +initial ) && + rcssNum.exec( jQuery.css( elem, prop ) ); + + if ( initialInUnit && initialInUnit[ 3 ] !== unit ) { + + // Support: Firefox <=54 + // Halve the iteration target value to prevent interference from CSS upper bounds (gh-2144) + initial = initial / 2; + + // Trust units reported by jQuery.css + unit = unit || initialInUnit[ 3 ]; + + // Iteratively approximate from a nonzero starting point + initialInUnit = +initial || 1; + + while ( maxIterations-- ) { + + // Evaluate and update our best guess (doubling guesses that zero out). + // Finish if the scale equals or crosses 1 (making the old*new product non-positive). + jQuery.style( elem, prop, initialInUnit + unit ); + if ( ( 1 - scale ) * ( 1 - ( scale = currentValue() / initial || 0.5 ) ) <= 0 ) { + maxIterations = 0; + } + initialInUnit = initialInUnit / scale; + + } + + initialInUnit = initialInUnit * 2; + jQuery.style( elem, prop, initialInUnit + unit ); + + // Make sure we update the tween properties later on + valueParts = valueParts || []; + } + + if ( valueParts ) { + initialInUnit = +initialInUnit || +initial || 0; + + // Apply relative offset (+=/-=) if specified + adjusted = valueParts[ 1 ] ? + initialInUnit + ( valueParts[ 1 ] + 1 ) * valueParts[ 2 ] : + +valueParts[ 2 ]; + if ( tween ) { + tween.unit = unit; + tween.start = initialInUnit; + tween.end = adjusted; + } + } + return adjusted; +} + + +var defaultDisplayMap = {}; + +function getDefaultDisplay( elem ) { + var temp, + doc = elem.ownerDocument, + nodeName = elem.nodeName, + display = defaultDisplayMap[ nodeName ]; + + if ( display ) { + return display; + } + + temp = doc.body.appendChild( doc.createElement( nodeName ) ); + display = jQuery.css( temp, "display" ); + + temp.parentNode.removeChild( temp ); + + if ( display === "none" ) { + display = "block"; + } + defaultDisplayMap[ nodeName ] = display; + + return display; +} + +function showHide( elements, show ) { + var display, elem, + values = [], + index = 0, + length = elements.length; + + // Determine new display value for elements that need to change + for ( ; index < length; index++ ) { + elem = elements[ index ]; + if ( !elem.style ) { + continue; + } + + display = elem.style.display; + if ( show ) { + + // Since we force visibility upon cascade-hidden elements, an immediate (and slow) + // check is required in this first loop unless we have a nonempty display value (either + // inline or about-to-be-restored) + if ( display === "none" ) { + values[ index ] = dataPriv.get( elem, "display" ) || null; + if ( !values[ index ] ) { + elem.style.display = ""; + } + } + if ( elem.style.display === "" && isHiddenWithinTree( elem ) ) { + values[ index ] = getDefaultDisplay( elem ); + } + } else { + if ( display !== "none" ) { + values[ index ] = "none"; + + // Remember what we're overwriting + dataPriv.set( elem, "display", display ); + } + } + } + + // Set the display of the elements in a second loop to avoid constant reflow + for ( index = 0; index < length; index++ ) { + if ( values[ index ] != null ) { + elements[ index ].style.display = values[ index ]; + } + } + + return elements; +} + +jQuery.fn.extend( { + show: function() { + return showHide( this, true ); + }, + hide: function() { + return showHide( this ); + }, + toggle: function( state ) { + if ( typeof state === "boolean" ) { + return state ? this.show() : this.hide(); + } + + return this.each( function() { + if ( isHiddenWithinTree( this ) ) { + jQuery( this ).show(); + } else { + jQuery( this ).hide(); + } + } ); + } +} ); +var rcheckableType = ( /^(?:checkbox|radio)$/i ); + +var rtagName = ( /<([a-z][^\/\0>\x20\t\r\n\f]+)/i ); + +var rscriptType = ( /^$|^module$|\/(?:java|ecma)script/i ); + + + +// We have to close these tags to support XHTML (#13200) +var wrapMap = { + + // Support: IE <=9 only + option: [ 1, "" ], + + // XHTML parsers do not magically insert elements in the + // same way that tag soup parsers do. So we cannot shorten + // this by omitting
    or other required elements. + thead: [ 1, "
    ", "
    " ], + col: [ 2, "", "
    " ], + tr: [ 2, "", "
    " ], + td: [ 3, "", "
    " ], + + _default: [ 0, "", "" ] +}; + +// Support: IE <=9 only +wrapMap.optgroup = wrapMap.option; + +wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; +wrapMap.th = wrapMap.td; + + +function getAll( context, tag ) { + + // Support: IE <=9 - 11 only + // Use typeof to avoid zero-argument method invocation on host objects (#15151) + var ret; + + if ( typeof context.getElementsByTagName !== "undefined" ) { + ret = context.getElementsByTagName( tag || "*" ); + + } else if ( typeof context.querySelectorAll !== "undefined" ) { + ret = context.querySelectorAll( tag || "*" ); + + } else { + ret = []; + } + + if ( tag === undefined || tag && nodeName( context, tag ) ) { + return jQuery.merge( [ context ], ret ); + } + + return ret; +} + + +// Mark scripts as having already been evaluated +function setGlobalEval( elems, refElements ) { + var i = 0, + l = elems.length; + + for ( ; i < l; i++ ) { + dataPriv.set( + elems[ i ], + "globalEval", + !refElements || dataPriv.get( refElements[ i ], "globalEval" ) + ); + } +} + + +var rhtml = /<|&#?\w+;/; + +function buildFragment( elems, context, scripts, selection, ignored ) { + var elem, tmp, tag, wrap, contains, j, + fragment = context.createDocumentFragment(), + nodes = [], + i = 0, + l = elems.length; + + for ( ; i < l; i++ ) { + elem = elems[ i ]; + + if ( elem || elem === 0 ) { + + // Add nodes directly + if ( toType( elem ) === "object" ) { + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem ); + + // Convert non-html into a text node + } else if ( !rhtml.test( elem ) ) { + nodes.push( context.createTextNode( elem ) ); + + // Convert html into DOM nodes + } else { + tmp = tmp || fragment.appendChild( context.createElement( "div" ) ); + + // Deserialize a standard representation + tag = ( rtagName.exec( elem ) || [ "", "" ] )[ 1 ].toLowerCase(); + wrap = wrapMap[ tag ] || wrapMap._default; + tmp.innerHTML = wrap[ 1 ] + jQuery.htmlPrefilter( elem ) + wrap[ 2 ]; + + // Descend through wrappers to the right content + j = wrap[ 0 ]; + while ( j-- ) { + tmp = tmp.lastChild; + } + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( nodes, tmp.childNodes ); + + // Remember the top-level container + tmp = fragment.firstChild; + + // Ensure the created nodes are orphaned (#12392) + tmp.textContent = ""; + } + } + } + + // Remove wrapper from fragment + fragment.textContent = ""; + + i = 0; + while ( ( elem = nodes[ i++ ] ) ) { + + // Skip elements already in the context collection (trac-4087) + if ( selection && jQuery.inArray( elem, selection ) > -1 ) { + if ( ignored ) { + ignored.push( elem ); + } + continue; + } + + contains = jQuery.contains( elem.ownerDocument, elem ); + + // Append to fragment + tmp = getAll( fragment.appendChild( elem ), "script" ); + + // Preserve script evaluation history + if ( contains ) { + setGlobalEval( tmp ); + } + + // Capture executables + if ( scripts ) { + j = 0; + while ( ( elem = tmp[ j++ ] ) ) { + if ( rscriptType.test( elem.type || "" ) ) { + scripts.push( elem ); + } + } + } + } + + return fragment; +} + + +( function() { + var fragment = document.createDocumentFragment(), + div = fragment.appendChild( document.createElement( "div" ) ), + input = document.createElement( "input" ); + + // Support: Android 4.0 - 4.3 only + // Check state lost if the name is set (#11217) + // Support: Windows Web Apps (WWA) + // `name` and `type` must use .setAttribute for WWA (#14901) + input.setAttribute( "type", "radio" ); + input.setAttribute( "checked", "checked" ); + input.setAttribute( "name", "t" ); + + div.appendChild( input ); + + // Support: Android <=4.1 only + // Older WebKit doesn't clone checked state correctly in fragments + support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked; + + // Support: IE <=11 only + // Make sure textarea (and checkbox) defaultValue is properly cloned + div.innerHTML = ""; + support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue; +} )(); +var documentElement = document.documentElement; + + + +var + rkeyEvent = /^key/, + rmouseEvent = /^(?:mouse|pointer|contextmenu|drag|drop)|click/, + rtypenamespace = /^([^.]*)(?:\.(.+)|)/; + +function returnTrue() { + return true; +} + +function returnFalse() { + return false; +} + +// Support: IE <=9 only +// See #13393 for more info +function safeActiveElement() { + try { + return document.activeElement; + } catch ( err ) { } +} + +function on( elem, types, selector, data, fn, one ) { + var origFn, type; + + // Types can be a map of types/handlers + if ( typeof types === "object" ) { + + // ( types-Object, selector, data ) + if ( typeof selector !== "string" ) { + + // ( types-Object, data ) + data = data || selector; + selector = undefined; + } + for ( type in types ) { + on( elem, type, selector, data, types[ type ], one ); + } + return elem; + } + + if ( data == null && fn == null ) { + + // ( types, fn ) + fn = selector; + data = selector = undefined; + } else if ( fn == null ) { + if ( typeof selector === "string" ) { + + // ( types, selector, fn ) + fn = data; + data = undefined; + } else { + + // ( types, data, fn ) + fn = data; + data = selector; + selector = undefined; + } + } + if ( fn === false ) { + fn = returnFalse; + } else if ( !fn ) { + return elem; + } + + if ( one === 1 ) { + origFn = fn; + fn = function( event ) { + + // Can use an empty set, since event contains the info + jQuery().off( event ); + return origFn.apply( this, arguments ); + }; + + // Use same guid so caller can remove using origFn + fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ ); + } + return elem.each( function() { + jQuery.event.add( this, types, fn, data, selector ); + } ); +} + +/* + * Helper functions for managing events -- not part of the public interface. + * Props to Dean Edwards' addEvent library for many of the ideas. + */ +jQuery.event = { + + global: {}, + + add: function( elem, types, handler, data, selector ) { + + var handleObjIn, eventHandle, tmp, + events, t, handleObj, + special, handlers, type, namespaces, origType, + elemData = dataPriv.get( elem ); + + // Don't attach events to noData or text/comment nodes (but allow plain objects) + if ( !elemData ) { + return; + } + + // Caller can pass in an object of custom data in lieu of the handler + if ( handler.handler ) { + handleObjIn = handler; + handler = handleObjIn.handler; + selector = handleObjIn.selector; + } + + // Ensure that invalid selectors throw exceptions at attach time + // Evaluate against documentElement in case elem is a non-element node (e.g., document) + if ( selector ) { + jQuery.find.matchesSelector( documentElement, selector ); + } + + // Make sure that the handler has a unique ID, used to find/remove it later + if ( !handler.guid ) { + handler.guid = jQuery.guid++; + } + + // Init the element's event structure and main handler, if this is the first + if ( !( events = elemData.events ) ) { + events = elemData.events = {}; + } + if ( !( eventHandle = elemData.handle ) ) { + eventHandle = elemData.handle = function( e ) { + + // Discard the second event of a jQuery.event.trigger() and + // when an event is called after a page has unloaded + return typeof jQuery !== "undefined" && jQuery.event.triggered !== e.type ? + jQuery.event.dispatch.apply( elem, arguments ) : undefined; + }; + } + + // Handle multiple events separated by a space + types = ( types || "" ).match( rnothtmlwhite ) || [ "" ]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[ t ] ) || []; + type = origType = tmp[ 1 ]; + namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); + + // There *must* be a type, no attaching namespace-only handlers + if ( !type ) { + continue; + } + + // If event changes its type, use the special event handlers for the changed type + special = jQuery.event.special[ type ] || {}; + + // If selector defined, determine special event api type, otherwise given type + type = ( selector ? special.delegateType : special.bindType ) || type; + + // Update special based on newly reset type + special = jQuery.event.special[ type ] || {}; + + // handleObj is passed to all event handlers + handleObj = jQuery.extend( { + type: type, + origType: origType, + data: data, + handler: handler, + guid: handler.guid, + selector: selector, + needsContext: selector && jQuery.expr.match.needsContext.test( selector ), + namespace: namespaces.join( "." ) + }, handleObjIn ); + + // Init the event handler queue if we're the first + if ( !( handlers = events[ type ] ) ) { + handlers = events[ type ] = []; + handlers.delegateCount = 0; + + // Only use addEventListener if the special events handler returns false + if ( !special.setup || + special.setup.call( elem, data, namespaces, eventHandle ) === false ) { + + if ( elem.addEventListener ) { + elem.addEventListener( type, eventHandle ); + } + } + } + + if ( special.add ) { + special.add.call( elem, handleObj ); + + if ( !handleObj.handler.guid ) { + handleObj.handler.guid = handler.guid; + } + } + + // Add to the element's handler list, delegates in front + if ( selector ) { + handlers.splice( handlers.delegateCount++, 0, handleObj ); + } else { + handlers.push( handleObj ); + } + + // Keep track of which events have ever been used, for event optimization + jQuery.event.global[ type ] = true; + } + + }, + + // Detach an event or set of events from an element + remove: function( elem, types, handler, selector, mappedTypes ) { + + var j, origCount, tmp, + events, t, handleObj, + special, handlers, type, namespaces, origType, + elemData = dataPriv.hasData( elem ) && dataPriv.get( elem ); + + if ( !elemData || !( events = elemData.events ) ) { + return; + } + + // Once for each type.namespace in types; type may be omitted + types = ( types || "" ).match( rnothtmlwhite ) || [ "" ]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[ t ] ) || []; + type = origType = tmp[ 1 ]; + namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); + + // Unbind all events (on this namespace, if provided) for the element + if ( !type ) { + for ( type in events ) { + jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); + } + continue; + } + + special = jQuery.event.special[ type ] || {}; + type = ( selector ? special.delegateType : special.bindType ) || type; + handlers = events[ type ] || []; + tmp = tmp[ 2 ] && + new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ); + + // Remove matching events + origCount = j = handlers.length; + while ( j-- ) { + handleObj = handlers[ j ]; + + if ( ( mappedTypes || origType === handleObj.origType ) && + ( !handler || handler.guid === handleObj.guid ) && + ( !tmp || tmp.test( handleObj.namespace ) ) && + ( !selector || selector === handleObj.selector || + selector === "**" && handleObj.selector ) ) { + handlers.splice( j, 1 ); + + if ( handleObj.selector ) { + handlers.delegateCount--; + } + if ( special.remove ) { + special.remove.call( elem, handleObj ); + } + } + } + + // Remove generic event handler if we removed something and no more handlers exist + // (avoids potential for endless recursion during removal of special event handlers) + if ( origCount && !handlers.length ) { + if ( !special.teardown || + special.teardown.call( elem, namespaces, elemData.handle ) === false ) { + + jQuery.removeEvent( elem, type, elemData.handle ); + } + + delete events[ type ]; + } + } + + // Remove data and the expando if it's no longer used + if ( jQuery.isEmptyObject( events ) ) { + dataPriv.remove( elem, "handle events" ); + } + }, + + dispatch: function( nativeEvent ) { + + // Make a writable jQuery.Event from the native event object + var event = jQuery.event.fix( nativeEvent ); + + var i, j, ret, matched, handleObj, handlerQueue, + args = new Array( arguments.length ), + handlers = ( dataPriv.get( this, "events" ) || {} )[ event.type ] || [], + special = jQuery.event.special[ event.type ] || {}; + + // Use the fix-ed jQuery.Event rather than the (read-only) native event + args[ 0 ] = event; + + for ( i = 1; i < arguments.length; i++ ) { + args[ i ] = arguments[ i ]; + } + + event.delegateTarget = this; + + // Call the preDispatch hook for the mapped type, and let it bail if desired + if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) { + return; + } + + // Determine handlers + handlerQueue = jQuery.event.handlers.call( this, event, handlers ); + + // Run delegates first; they may want to stop propagation beneath us + i = 0; + while ( ( matched = handlerQueue[ i++ ] ) && !event.isPropagationStopped() ) { + event.currentTarget = matched.elem; + + j = 0; + while ( ( handleObj = matched.handlers[ j++ ] ) && + !event.isImmediatePropagationStopped() ) { + + // Triggered event must either 1) have no namespace, or 2) have namespace(s) + // a subset or equal to those in the bound event (both can have no namespace). + if ( !event.rnamespace || event.rnamespace.test( handleObj.namespace ) ) { + + event.handleObj = handleObj; + event.data = handleObj.data; + + ret = ( ( jQuery.event.special[ handleObj.origType ] || {} ).handle || + handleObj.handler ).apply( matched.elem, args ); + + if ( ret !== undefined ) { + if ( ( event.result = ret ) === false ) { + event.preventDefault(); + event.stopPropagation(); + } + } + } + } + } + + // Call the postDispatch hook for the mapped type + if ( special.postDispatch ) { + special.postDispatch.call( this, event ); + } + + return event.result; + }, + + handlers: function( event, handlers ) { + var i, handleObj, sel, matchedHandlers, matchedSelectors, + handlerQueue = [], + delegateCount = handlers.delegateCount, + cur = event.target; + + // Find delegate handlers + if ( delegateCount && + + // Support: IE <=9 + // Black-hole SVG instance trees (trac-13180) + cur.nodeType && + + // Support: Firefox <=42 + // Suppress spec-violating clicks indicating a non-primary pointer button (trac-3861) + // https://www.w3.org/TR/DOM-Level-3-Events/#event-type-click + // Support: IE 11 only + // ...but not arrow key "clicks" of radio inputs, which can have `button` -1 (gh-2343) + !( event.type === "click" && event.button >= 1 ) ) { + + for ( ; cur !== this; cur = cur.parentNode || this ) { + + // Don't check non-elements (#13208) + // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764) + if ( cur.nodeType === 1 && !( event.type === "click" && cur.disabled === true ) ) { + matchedHandlers = []; + matchedSelectors = {}; + for ( i = 0; i < delegateCount; i++ ) { + handleObj = handlers[ i ]; + + // Don't conflict with Object.prototype properties (#13203) + sel = handleObj.selector + " "; + + if ( matchedSelectors[ sel ] === undefined ) { + matchedSelectors[ sel ] = handleObj.needsContext ? + jQuery( sel, this ).index( cur ) > -1 : + jQuery.find( sel, this, null, [ cur ] ).length; + } + if ( matchedSelectors[ sel ] ) { + matchedHandlers.push( handleObj ); + } + } + if ( matchedHandlers.length ) { + handlerQueue.push( { elem: cur, handlers: matchedHandlers } ); + } + } + } + } + + // Add the remaining (directly-bound) handlers + cur = this; + if ( delegateCount < handlers.length ) { + handlerQueue.push( { elem: cur, handlers: handlers.slice( delegateCount ) } ); + } + + return handlerQueue; + }, + + addProp: function( name, hook ) { + Object.defineProperty( jQuery.Event.prototype, name, { + enumerable: true, + configurable: true, + + get: isFunction( hook ) ? + function() { + if ( this.originalEvent ) { + return hook( this.originalEvent ); + } + } : + function() { + if ( this.originalEvent ) { + return this.originalEvent[ name ]; + } + }, + + set: function( value ) { + Object.defineProperty( this, name, { + enumerable: true, + configurable: true, + writable: true, + value: value + } ); + } + } ); + }, + + fix: function( originalEvent ) { + return originalEvent[ jQuery.expando ] ? + originalEvent : + new jQuery.Event( originalEvent ); + }, + + special: { + load: { + + // Prevent triggered image.load events from bubbling to window.load + noBubble: true + }, + focus: { + + // Fire native event if possible so blur/focus sequence is correct + trigger: function() { + if ( this !== safeActiveElement() && this.focus ) { + this.focus(); + return false; + } + }, + delegateType: "focusin" + }, + blur: { + trigger: function() { + if ( this === safeActiveElement() && this.blur ) { + this.blur(); + return false; + } + }, + delegateType: "focusout" + }, + click: { + + // For checkbox, fire native event so checked state will be right + trigger: function() { + if ( this.type === "checkbox" && this.click && nodeName( this, "input" ) ) { + this.click(); + return false; + } + }, + + // For cross-browser consistency, don't fire native .click() on links + _default: function( event ) { + return nodeName( event.target, "a" ); + } + }, + + beforeunload: { + postDispatch: function( event ) { + + // Support: Firefox 20+ + // Firefox doesn't alert if the returnValue field is not set. + if ( event.result !== undefined && event.originalEvent ) { + event.originalEvent.returnValue = event.result; + } + } + } + } +}; + +jQuery.removeEvent = function( elem, type, handle ) { + + // This "if" is needed for plain objects + if ( elem.removeEventListener ) { + elem.removeEventListener( type, handle ); + } +}; + +jQuery.Event = function( src, props ) { + + // Allow instantiation without the 'new' keyword + if ( !( this instanceof jQuery.Event ) ) { + return new jQuery.Event( src, props ); + } + + // Event object + if ( src && src.type ) { + this.originalEvent = src; + this.type = src.type; + + // Events bubbling up the document may have been marked as prevented + // by a handler lower down the tree; reflect the correct value. + this.isDefaultPrevented = src.defaultPrevented || + src.defaultPrevented === undefined && + + // Support: Android <=2.3 only + src.returnValue === false ? + returnTrue : + returnFalse; + + // Create target properties + // Support: Safari <=6 - 7 only + // Target should not be a text node (#504, #13143) + this.target = ( src.target && src.target.nodeType === 3 ) ? + src.target.parentNode : + src.target; + + this.currentTarget = src.currentTarget; + this.relatedTarget = src.relatedTarget; + + // Event type + } else { + this.type = src; + } + + // Put explicitly provided properties onto the event object + if ( props ) { + jQuery.extend( this, props ); + } + + // Create a timestamp if incoming event doesn't have one + this.timeStamp = src && src.timeStamp || Date.now(); + + // Mark it as fixed + this[ jQuery.expando ] = true; +}; + +// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding +// https://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html +jQuery.Event.prototype = { + constructor: jQuery.Event, + isDefaultPrevented: returnFalse, + isPropagationStopped: returnFalse, + isImmediatePropagationStopped: returnFalse, + isSimulated: false, + + preventDefault: function() { + var e = this.originalEvent; + + this.isDefaultPrevented = returnTrue; + + if ( e && !this.isSimulated ) { + e.preventDefault(); + } + }, + stopPropagation: function() { + var e = this.originalEvent; + + this.isPropagationStopped = returnTrue; + + if ( e && !this.isSimulated ) { + e.stopPropagation(); + } + }, + stopImmediatePropagation: function() { + var e = this.originalEvent; + + this.isImmediatePropagationStopped = returnTrue; + + if ( e && !this.isSimulated ) { + e.stopImmediatePropagation(); + } + + this.stopPropagation(); + } +}; + +// Includes all common event props including KeyEvent and MouseEvent specific props +jQuery.each( { + altKey: true, + bubbles: true, + cancelable: true, + changedTouches: true, + ctrlKey: true, + detail: true, + eventPhase: true, + metaKey: true, + pageX: true, + pageY: true, + shiftKey: true, + view: true, + "char": true, + charCode: true, + key: true, + keyCode: true, + button: true, + buttons: true, + clientX: true, + clientY: true, + offsetX: true, + offsetY: true, + pointerId: true, + pointerType: true, + screenX: true, + screenY: true, + targetTouches: true, + toElement: true, + touches: true, + + which: function( event ) { + var button = event.button; + + // Add which for key events + if ( event.which == null && rkeyEvent.test( event.type ) ) { + return event.charCode != null ? event.charCode : event.keyCode; + } + + // Add which for click: 1 === left; 2 === middle; 3 === right + if ( !event.which && button !== undefined && rmouseEvent.test( event.type ) ) { + if ( button & 1 ) { + return 1; + } + + if ( button & 2 ) { + return 3; + } + + if ( button & 4 ) { + return 2; + } + + return 0; + } + + return event.which; + } +}, jQuery.event.addProp ); + +// Create mouseenter/leave events using mouseover/out and event-time checks +// so that event delegation works in jQuery. +// Do the same for pointerenter/pointerleave and pointerover/pointerout +// +// Support: Safari 7 only +// Safari sends mouseenter too often; see: +// https://bugs.chromium.org/p/chromium/issues/detail?id=470258 +// for the description of the bug (it existed in older Chrome versions as well). +jQuery.each( { + mouseenter: "mouseover", + mouseleave: "mouseout", + pointerenter: "pointerover", + pointerleave: "pointerout" +}, function( orig, fix ) { + jQuery.event.special[ orig ] = { + delegateType: fix, + bindType: fix, + + handle: function( event ) { + var ret, + target = this, + related = event.relatedTarget, + handleObj = event.handleObj; + + // For mouseenter/leave call the handler if related is outside the target. + // NB: No relatedTarget if the mouse left/entered the browser window + if ( !related || ( related !== target && !jQuery.contains( target, related ) ) ) { + event.type = handleObj.origType; + ret = handleObj.handler.apply( this, arguments ); + event.type = fix; + } + return ret; + } + }; +} ); + +jQuery.fn.extend( { + + on: function( types, selector, data, fn ) { + return on( this, types, selector, data, fn ); + }, + one: function( types, selector, data, fn ) { + return on( this, types, selector, data, fn, 1 ); + }, + off: function( types, selector, fn ) { + var handleObj, type; + if ( types && types.preventDefault && types.handleObj ) { + + // ( event ) dispatched jQuery.Event + handleObj = types.handleObj; + jQuery( types.delegateTarget ).off( + handleObj.namespace ? + handleObj.origType + "." + handleObj.namespace : + handleObj.origType, + handleObj.selector, + handleObj.handler + ); + return this; + } + if ( typeof types === "object" ) { + + // ( types-object [, selector] ) + for ( type in types ) { + this.off( type, selector, types[ type ] ); + } + return this; + } + if ( selector === false || typeof selector === "function" ) { + + // ( types [, fn] ) + fn = selector; + selector = undefined; + } + if ( fn === false ) { + fn = returnFalse; + } + return this.each( function() { + jQuery.event.remove( this, types, fn, selector ); + } ); + } +} ); + + +var + + /* eslint-disable max-len */ + + // See https://github.com/eslint/eslint/issues/3229 + rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([a-z][^\/\0>\x20\t\r\n\f]*)[^>]*)\/>/gi, + + /* eslint-enable */ + + // Support: IE <=10 - 11, Edge 12 - 13 only + // In IE/Edge using regex groups here causes severe slowdowns. + // See https://connect.microsoft.com/IE/feedback/details/1736512/ + rnoInnerhtml = /\s*$/g; + +// Prefer a tbody over its parent table for containing new rows +function manipulationTarget( elem, content ) { + if ( nodeName( elem, "table" ) && + nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ) { + + return jQuery( elem ).children( "tbody" )[ 0 ] || elem; + } + + return elem; +} + +// Replace/restore the type attribute of script elements for safe DOM manipulation +function disableScript( elem ) { + elem.type = ( elem.getAttribute( "type" ) !== null ) + "/" + elem.type; + return elem; +} +function restoreScript( elem ) { + if ( ( elem.type || "" ).slice( 0, 5 ) === "true/" ) { + elem.type = elem.type.slice( 5 ); + } else { + elem.removeAttribute( "type" ); + } + + return elem; +} + +function cloneCopyEvent( src, dest ) { + var i, l, type, pdataOld, pdataCur, udataOld, udataCur, events; + + if ( dest.nodeType !== 1 ) { + return; + } + + // 1. Copy private data: events, handlers, etc. + if ( dataPriv.hasData( src ) ) { + pdataOld = dataPriv.access( src ); + pdataCur = dataPriv.set( dest, pdataOld ); + events = pdataOld.events; + + if ( events ) { + delete pdataCur.handle; + pdataCur.events = {}; + + for ( type in events ) { + for ( i = 0, l = events[ type ].length; i < l; i++ ) { + jQuery.event.add( dest, type, events[ type ][ i ] ); + } + } + } + } + + // 2. Copy user data + if ( dataUser.hasData( src ) ) { + udataOld = dataUser.access( src ); + udataCur = jQuery.extend( {}, udataOld ); + + dataUser.set( dest, udataCur ); + } +} + +// Fix IE bugs, see support tests +function fixInput( src, dest ) { + var nodeName = dest.nodeName.toLowerCase(); + + // Fails to persist the checked state of a cloned checkbox or radio button. + if ( nodeName === "input" && rcheckableType.test( src.type ) ) { + dest.checked = src.checked; + + // Fails to return the selected option to the default selected state when cloning options + } else if ( nodeName === "input" || nodeName === "textarea" ) { + dest.defaultValue = src.defaultValue; + } +} + +function domManip( collection, args, callback, ignored ) { + + // Flatten any nested arrays + args = concat.apply( [], args ); + + var fragment, first, scripts, hasScripts, node, doc, + i = 0, + l = collection.length, + iNoClone = l - 1, + value = args[ 0 ], + valueIsFunction = isFunction( value ); + + // We can't cloneNode fragments that contain checked, in WebKit + if ( valueIsFunction || + ( l > 1 && typeof value === "string" && + !support.checkClone && rchecked.test( value ) ) ) { + return collection.each( function( index ) { + var self = collection.eq( index ); + if ( valueIsFunction ) { + args[ 0 ] = value.call( this, index, self.html() ); + } + domManip( self, args, callback, ignored ); + } ); + } + + if ( l ) { + fragment = buildFragment( args, collection[ 0 ].ownerDocument, false, collection, ignored ); + first = fragment.firstChild; + + if ( fragment.childNodes.length === 1 ) { + fragment = first; + } + + // Require either new content or an interest in ignored elements to invoke the callback + if ( first || ignored ) { + scripts = jQuery.map( getAll( fragment, "script" ), disableScript ); + hasScripts = scripts.length; + + // Use the original fragment for the last item + // instead of the first because it can end up + // being emptied incorrectly in certain situations (#8070). + for ( ; i < l; i++ ) { + node = fragment; + + if ( i !== iNoClone ) { + node = jQuery.clone( node, true, true ); + + // Keep references to cloned scripts for later restoration + if ( hasScripts ) { + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( scripts, getAll( node, "script" ) ); + } + } + + callback.call( collection[ i ], node, i ); + } + + if ( hasScripts ) { + doc = scripts[ scripts.length - 1 ].ownerDocument; + + // Reenable scripts + jQuery.map( scripts, restoreScript ); + + // Evaluate executable scripts on first document insertion + for ( i = 0; i < hasScripts; i++ ) { + node = scripts[ i ]; + if ( rscriptType.test( node.type || "" ) && + !dataPriv.access( node, "globalEval" ) && + jQuery.contains( doc, node ) ) { + + if ( node.src && ( node.type || "" ).toLowerCase() !== "module" ) { + + // Optional AJAX dependency, but won't run scripts if not present + if ( jQuery._evalUrl ) { + jQuery._evalUrl( node.src ); + } + } else { + DOMEval( node.textContent.replace( rcleanScript, "" ), doc, node ); + } + } + } + } + } + } + + return collection; +} + +function remove( elem, selector, keepData ) { + var node, + nodes = selector ? jQuery.filter( selector, elem ) : elem, + i = 0; + + for ( ; ( node = nodes[ i ] ) != null; i++ ) { + if ( !keepData && node.nodeType === 1 ) { + jQuery.cleanData( getAll( node ) ); + } + + if ( node.parentNode ) { + if ( keepData && jQuery.contains( node.ownerDocument, node ) ) { + setGlobalEval( getAll( node, "script" ) ); + } + node.parentNode.removeChild( node ); + } + } + + return elem; +} + +jQuery.extend( { + htmlPrefilter: function( html ) { + return html.replace( rxhtmlTag, "<$1>" ); + }, + + clone: function( elem, dataAndEvents, deepDataAndEvents ) { + var i, l, srcElements, destElements, + clone = elem.cloneNode( true ), + inPage = jQuery.contains( elem.ownerDocument, elem ); + + // Fix IE cloning issues + if ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) && + !jQuery.isXMLDoc( elem ) ) { + + // We eschew Sizzle here for performance reasons: https://jsperf.com/getall-vs-sizzle/2 + destElements = getAll( clone ); + srcElements = getAll( elem ); + + for ( i = 0, l = srcElements.length; i < l; i++ ) { + fixInput( srcElements[ i ], destElements[ i ] ); + } + } + + // Copy the events from the original to the clone + if ( dataAndEvents ) { + if ( deepDataAndEvents ) { + srcElements = srcElements || getAll( elem ); + destElements = destElements || getAll( clone ); + + for ( i = 0, l = srcElements.length; i < l; i++ ) { + cloneCopyEvent( srcElements[ i ], destElements[ i ] ); + } + } else { + cloneCopyEvent( elem, clone ); + } + } + + // Preserve script evaluation history + destElements = getAll( clone, "script" ); + if ( destElements.length > 0 ) { + setGlobalEval( destElements, !inPage && getAll( elem, "script" ) ); + } + + // Return the cloned set + return clone; + }, + + cleanData: function( elems ) { + var data, elem, type, + special = jQuery.event.special, + i = 0; + + for ( ; ( elem = elems[ i ] ) !== undefined; i++ ) { + if ( acceptData( elem ) ) { + if ( ( data = elem[ dataPriv.expando ] ) ) { + if ( data.events ) { + for ( type in data.events ) { + if ( special[ type ] ) { + jQuery.event.remove( elem, type ); + + // This is a shortcut to avoid jQuery.event.remove's overhead + } else { + jQuery.removeEvent( elem, type, data.handle ); + } + } + } + + // Support: Chrome <=35 - 45+ + // Assign undefined instead of using delete, see Data#remove + elem[ dataPriv.expando ] = undefined; + } + if ( elem[ dataUser.expando ] ) { + + // Support: Chrome <=35 - 45+ + // Assign undefined instead of using delete, see Data#remove + elem[ dataUser.expando ] = undefined; + } + } + } + } +} ); + +jQuery.fn.extend( { + detach: function( selector ) { + return remove( this, selector, true ); + }, + + remove: function( selector ) { + return remove( this, selector ); + }, + + text: function( value ) { + return access( this, function( value ) { + return value === undefined ? + jQuery.text( this ) : + this.empty().each( function() { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + this.textContent = value; + } + } ); + }, null, value, arguments.length ); + }, + + append: function() { + return domManip( this, arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.appendChild( elem ); + } + } ); + }, + + prepend: function() { + return domManip( this, arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.insertBefore( elem, target.firstChild ); + } + } ); + }, + + before: function() { + return domManip( this, arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this ); + } + } ); + }, + + after: function() { + return domManip( this, arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this.nextSibling ); + } + } ); + }, + + empty: function() { + var elem, + i = 0; + + for ( ; ( elem = this[ i ] ) != null; i++ ) { + if ( elem.nodeType === 1 ) { + + // Prevent memory leaks + jQuery.cleanData( getAll( elem, false ) ); + + // Remove any remaining nodes + elem.textContent = ""; + } + } + + return this; + }, + + clone: function( dataAndEvents, deepDataAndEvents ) { + dataAndEvents = dataAndEvents == null ? false : dataAndEvents; + deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents; + + return this.map( function() { + return jQuery.clone( this, dataAndEvents, deepDataAndEvents ); + } ); + }, + + html: function( value ) { + return access( this, function( value ) { + var elem = this[ 0 ] || {}, + i = 0, + l = this.length; + + if ( value === undefined && elem.nodeType === 1 ) { + return elem.innerHTML; + } + + // See if we can take a shortcut and just use innerHTML + if ( typeof value === "string" && !rnoInnerhtml.test( value ) && + !wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) { + + value = jQuery.htmlPrefilter( value ); + + try { + for ( ; i < l; i++ ) { + elem = this[ i ] || {}; + + // Remove element nodes and prevent memory leaks + if ( elem.nodeType === 1 ) { + jQuery.cleanData( getAll( elem, false ) ); + elem.innerHTML = value; + } + } + + elem = 0; + + // If using innerHTML throws an exception, use the fallback method + } catch ( e ) {} + } + + if ( elem ) { + this.empty().append( value ); + } + }, null, value, arguments.length ); + }, + + replaceWith: function() { + var ignored = []; + + // Make the changes, replacing each non-ignored context element with the new content + return domManip( this, arguments, function( elem ) { + var parent = this.parentNode; + + if ( jQuery.inArray( this, ignored ) < 0 ) { + jQuery.cleanData( getAll( this ) ); + if ( parent ) { + parent.replaceChild( elem, this ); + } + } + + // Force callback invocation + }, ignored ); + } +} ); + +jQuery.each( { + appendTo: "append", + prependTo: "prepend", + insertBefore: "before", + insertAfter: "after", + replaceAll: "replaceWith" +}, function( name, original ) { + jQuery.fn[ name ] = function( selector ) { + var elems, + ret = [], + insert = jQuery( selector ), + last = insert.length - 1, + i = 0; + + for ( ; i <= last; i++ ) { + elems = i === last ? this : this.clone( true ); + jQuery( insert[ i ] )[ original ]( elems ); + + // Support: Android <=4.0 only, PhantomJS 1 only + // .get() because push.apply(_, arraylike) throws on ancient WebKit + push.apply( ret, elems.get() ); + } + + return this.pushStack( ret ); + }; +} ); +var rnumnonpx = new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" ); + +var getStyles = function( elem ) { + + // Support: IE <=11 only, Firefox <=30 (#15098, #14150) + // IE throws on elements created in popups + // FF meanwhile throws on frame elements through "defaultView.getComputedStyle" + var view = elem.ownerDocument.defaultView; + + if ( !view || !view.opener ) { + view = window; + } + + return view.getComputedStyle( elem ); + }; + +var rboxStyle = new RegExp( cssExpand.join( "|" ), "i" ); + + + +( function() { + + // Executing both pixelPosition & boxSizingReliable tests require only one layout + // so they're executed at the same time to save the second computation. + function computeStyleTests() { + + // This is a singleton, we need to execute it only once + if ( !div ) { + return; + } + + container.style.cssText = "position:absolute;left:-11111px;width:60px;" + + "margin-top:1px;padding:0;border:0"; + div.style.cssText = + "position:relative;display:block;box-sizing:border-box;overflow:scroll;" + + "margin:auto;border:1px;padding:1px;" + + "width:60%;top:1%"; + documentElement.appendChild( container ).appendChild( div ); + + var divStyle = window.getComputedStyle( div ); + pixelPositionVal = divStyle.top !== "1%"; + + // Support: Android 4.0 - 4.3 only, Firefox <=3 - 44 + reliableMarginLeftVal = roundPixelMeasures( divStyle.marginLeft ) === 12; + + // Support: Android 4.0 - 4.3 only, Safari <=9.1 - 10.1, iOS <=7.0 - 9.3 + // Some styles come back with percentage values, even though they shouldn't + div.style.right = "60%"; + pixelBoxStylesVal = roundPixelMeasures( divStyle.right ) === 36; + + // Support: IE 9 - 11 only + // Detect misreporting of content dimensions for box-sizing:border-box elements + boxSizingReliableVal = roundPixelMeasures( divStyle.width ) === 36; + + // Support: IE 9 only + // Detect overflow:scroll screwiness (gh-3699) + div.style.position = "absolute"; + scrollboxSizeVal = div.offsetWidth === 36 || "absolute"; + + documentElement.removeChild( container ); + + // Nullify the div so it wouldn't be stored in the memory and + // it will also be a sign that checks already performed + div = null; + } + + function roundPixelMeasures( measure ) { + return Math.round( parseFloat( measure ) ); + } + + var pixelPositionVal, boxSizingReliableVal, scrollboxSizeVal, pixelBoxStylesVal, + reliableMarginLeftVal, + container = document.createElement( "div" ), + div = document.createElement( "div" ); + + // Finish early in limited (non-browser) environments + if ( !div.style ) { + return; + } + + // Support: IE <=9 - 11 only + // Style of cloned element affects source element cloned (#8908) + div.style.backgroundClip = "content-box"; + div.cloneNode( true ).style.backgroundClip = ""; + support.clearCloneStyle = div.style.backgroundClip === "content-box"; + + jQuery.extend( support, { + boxSizingReliable: function() { + computeStyleTests(); + return boxSizingReliableVal; + }, + pixelBoxStyles: function() { + computeStyleTests(); + return pixelBoxStylesVal; + }, + pixelPosition: function() { + computeStyleTests(); + return pixelPositionVal; + }, + reliableMarginLeft: function() { + computeStyleTests(); + return reliableMarginLeftVal; + }, + scrollboxSize: function() { + computeStyleTests(); + return scrollboxSizeVal; + } + } ); +} )(); + + +function curCSS( elem, name, computed ) { + var width, minWidth, maxWidth, ret, + + // Support: Firefox 51+ + // Retrieving style before computed somehow + // fixes an issue with getting wrong values + // on detached elements + style = elem.style; + + computed = computed || getStyles( elem ); + + // getPropertyValue is needed for: + // .css('filter') (IE 9 only, #12537) + // .css('--customProperty) (#3144) + if ( computed ) { + ret = computed.getPropertyValue( name ) || computed[ name ]; + + if ( ret === "" && !jQuery.contains( elem.ownerDocument, elem ) ) { + ret = jQuery.style( elem, name ); + } + + // A tribute to the "awesome hack by Dean Edwards" + // Android Browser returns percentage for some values, + // but width seems to be reliably pixels. + // This is against the CSSOM draft spec: + // https://drafts.csswg.org/cssom/#resolved-values + if ( !support.pixelBoxStyles() && rnumnonpx.test( ret ) && rboxStyle.test( name ) ) { + + // Remember the original values + width = style.width; + minWidth = style.minWidth; + maxWidth = style.maxWidth; + + // Put in the new values to get a computed value out + style.minWidth = style.maxWidth = style.width = ret; + ret = computed.width; + + // Revert the changed values + style.width = width; + style.minWidth = minWidth; + style.maxWidth = maxWidth; + } + } + + return ret !== undefined ? + + // Support: IE <=9 - 11 only + // IE returns zIndex value as an integer. + ret + "" : + ret; +} + + +function addGetHookIf( conditionFn, hookFn ) { + + // Define the hook, we'll check on the first run if it's really needed. + return { + get: function() { + if ( conditionFn() ) { + + // Hook not needed (or it's not possible to use it due + // to missing dependency), remove it. + delete this.get; + return; + } + + // Hook needed; redefine it so that the support test is not executed again. + return ( this.get = hookFn ).apply( this, arguments ); + } + }; +} + + +var + + // Swappable if display is none or starts with table + // except "table", "table-cell", or "table-caption" + // See here for display values: https://developer.mozilla.org/en-US/docs/CSS/display + rdisplayswap = /^(none|table(?!-c[ea]).+)/, + rcustomProp = /^--/, + cssShow = { position: "absolute", visibility: "hidden", display: "block" }, + cssNormalTransform = { + letterSpacing: "0", + fontWeight: "400" + }, + + cssPrefixes = [ "Webkit", "Moz", "ms" ], + emptyStyle = document.createElement( "div" ).style; + +// Return a css property mapped to a potentially vendor prefixed property +function vendorPropName( name ) { + + // Shortcut for names that are not vendor prefixed + if ( name in emptyStyle ) { + return name; + } + + // Check for vendor prefixed names + var capName = name[ 0 ].toUpperCase() + name.slice( 1 ), + i = cssPrefixes.length; + + while ( i-- ) { + name = cssPrefixes[ i ] + capName; + if ( name in emptyStyle ) { + return name; + } + } +} + +// Return a property mapped along what jQuery.cssProps suggests or to +// a vendor prefixed property. +function finalPropName( name ) { + var ret = jQuery.cssProps[ name ]; + if ( !ret ) { + ret = jQuery.cssProps[ name ] = vendorPropName( name ) || name; + } + return ret; +} + +function setPositiveNumber( elem, value, subtract ) { + + // Any relative (+/-) values have already been + // normalized at this point + var matches = rcssNum.exec( value ); + return matches ? + + // Guard against undefined "subtract", e.g., when used as in cssHooks + Math.max( 0, matches[ 2 ] - ( subtract || 0 ) ) + ( matches[ 3 ] || "px" ) : + value; +} + +function boxModelAdjustment( elem, dimension, box, isBorderBox, styles, computedVal ) { + var i = dimension === "width" ? 1 : 0, + extra = 0, + delta = 0; + + // Adjustment may not be necessary + if ( box === ( isBorderBox ? "border" : "content" ) ) { + return 0; + } + + for ( ; i < 4; i += 2 ) { + + // Both box models exclude margin + if ( box === "margin" ) { + delta += jQuery.css( elem, box + cssExpand[ i ], true, styles ); + } + + // If we get here with a content-box, we're seeking "padding" or "border" or "margin" + if ( !isBorderBox ) { + + // Add padding + delta += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); + + // For "border" or "margin", add border + if ( box !== "padding" ) { + delta += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + + // But still keep track of it otherwise + } else { + extra += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + } + + // If we get here with a border-box (content + padding + border), we're seeking "content" or + // "padding" or "margin" + } else { + + // For "content", subtract padding + if ( box === "content" ) { + delta -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); + } + + // For "content" or "padding", subtract border + if ( box !== "margin" ) { + delta -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + } + } + } + + // Account for positive content-box scroll gutter when requested by providing computedVal + if ( !isBorderBox && computedVal >= 0 ) { + + // offsetWidth/offsetHeight is a rounded sum of content, padding, scroll gutter, and border + // Assuming integer scroll gutter, subtract the rest and round down + delta += Math.max( 0, Math.ceil( + elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] - + computedVal - + delta - + extra - + 0.5 + ) ); + } + + return delta; +} + +function getWidthOrHeight( elem, dimension, extra ) { + + // Start with computed style + var styles = getStyles( elem ), + val = curCSS( elem, dimension, styles ), + isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box", + valueIsBorderBox = isBorderBox; + + // Support: Firefox <=54 + // Return a confounding non-pixel value or feign ignorance, as appropriate. + if ( rnumnonpx.test( val ) ) { + if ( !extra ) { + return val; + } + val = "auto"; + } + + // Check for style in case a browser which returns unreliable values + // for getComputedStyle silently falls back to the reliable elem.style + valueIsBorderBox = valueIsBorderBox && + ( support.boxSizingReliable() || val === elem.style[ dimension ] ); + + // Fall back to offsetWidth/offsetHeight when value is "auto" + // This happens for inline elements with no explicit setting (gh-3571) + // Support: Android <=4.1 - 4.3 only + // Also use offsetWidth/offsetHeight for misreported inline dimensions (gh-3602) + if ( val === "auto" || + !parseFloat( val ) && jQuery.css( elem, "display", false, styles ) === "inline" ) { + + val = elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ]; + + // offsetWidth/offsetHeight provide border-box values + valueIsBorderBox = true; + } + + // Normalize "" and auto + val = parseFloat( val ) || 0; + + // Adjust for the element's box model + return ( val + + boxModelAdjustment( + elem, + dimension, + extra || ( isBorderBox ? "border" : "content" ), + valueIsBorderBox, + styles, + + // Provide the current computed size to request scroll gutter calculation (gh-3589) + val + ) + ) + "px"; +} + +jQuery.extend( { + + // Add in style property hooks for overriding the default + // behavior of getting and setting a style property + cssHooks: { + opacity: { + get: function( elem, computed ) { + if ( computed ) { + + // We should always get a number back from opacity + var ret = curCSS( elem, "opacity" ); + return ret === "" ? "1" : ret; + } + } + } + }, + + // Don't automatically add "px" to these possibly-unitless properties + cssNumber: { + "animationIterationCount": true, + "columnCount": true, + "fillOpacity": true, + "flexGrow": true, + "flexShrink": true, + "fontWeight": true, + "lineHeight": true, + "opacity": true, + "order": true, + "orphans": true, + "widows": true, + "zIndex": true, + "zoom": true + }, + + // Add in properties whose names you wish to fix before + // setting or getting the value + cssProps: {}, + + // Get and set the style property on a DOM Node + style: function( elem, name, value, extra ) { + + // Don't set styles on text and comment nodes + if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) { + return; + } + + // Make sure that we're working with the right name + var ret, type, hooks, + origName = camelCase( name ), + isCustomProp = rcustomProp.test( name ), + style = elem.style; + + // Make sure that we're working with the right name. We don't + // want to query the value if it is a CSS custom property + // since they are user-defined. + if ( !isCustomProp ) { + name = finalPropName( origName ); + } + + // Gets hook for the prefixed version, then unprefixed version + hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; + + // Check if we're setting a value + if ( value !== undefined ) { + type = typeof value; + + // Convert "+=" or "-=" to relative numbers (#7345) + if ( type === "string" && ( ret = rcssNum.exec( value ) ) && ret[ 1 ] ) { + value = adjustCSS( elem, name, ret ); + + // Fixes bug #9237 + type = "number"; + } + + // Make sure that null and NaN values aren't set (#7116) + if ( value == null || value !== value ) { + return; + } + + // If a number was passed in, add the unit (except for certain CSS properties) + if ( type === "number" ) { + value += ret && ret[ 3 ] || ( jQuery.cssNumber[ origName ] ? "" : "px" ); + } + + // background-* props affect original clone's values + if ( !support.clearCloneStyle && value === "" && name.indexOf( "background" ) === 0 ) { + style[ name ] = "inherit"; + } + + // If a hook was provided, use that value, otherwise just set the specified value + if ( !hooks || !( "set" in hooks ) || + ( value = hooks.set( elem, value, extra ) ) !== undefined ) { + + if ( isCustomProp ) { + style.setProperty( name, value ); + } else { + style[ name ] = value; + } + } + + } else { + + // If a hook was provided get the non-computed value from there + if ( hooks && "get" in hooks && + ( ret = hooks.get( elem, false, extra ) ) !== undefined ) { + + return ret; + } + + // Otherwise just get the value from the style object + return style[ name ]; + } + }, + + css: function( elem, name, extra, styles ) { + var val, num, hooks, + origName = camelCase( name ), + isCustomProp = rcustomProp.test( name ); + + // Make sure that we're working with the right name. We don't + // want to modify the value if it is a CSS custom property + // since they are user-defined. + if ( !isCustomProp ) { + name = finalPropName( origName ); + } + + // Try prefixed name followed by the unprefixed name + hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; + + // If a hook was provided get the computed value from there + if ( hooks && "get" in hooks ) { + val = hooks.get( elem, true, extra ); + } + + // Otherwise, if a way to get the computed value exists, use that + if ( val === undefined ) { + val = curCSS( elem, name, styles ); + } + + // Convert "normal" to computed value + if ( val === "normal" && name in cssNormalTransform ) { + val = cssNormalTransform[ name ]; + } + + // Make numeric if forced or a qualifier was provided and val looks numeric + if ( extra === "" || extra ) { + num = parseFloat( val ); + return extra === true || isFinite( num ) ? num || 0 : val; + } + + return val; + } +} ); + +jQuery.each( [ "height", "width" ], function( i, dimension ) { + jQuery.cssHooks[ dimension ] = { + get: function( elem, computed, extra ) { + if ( computed ) { + + // Certain elements can have dimension info if we invisibly show them + // but it must have a current display style that would benefit + return rdisplayswap.test( jQuery.css( elem, "display" ) ) && + + // Support: Safari 8+ + // Table columns in Safari have non-zero offsetWidth & zero + // getBoundingClientRect().width unless display is changed. + // Support: IE <=11 only + // Running getBoundingClientRect on a disconnected node + // in IE throws an error. + ( !elem.getClientRects().length || !elem.getBoundingClientRect().width ) ? + swap( elem, cssShow, function() { + return getWidthOrHeight( elem, dimension, extra ); + } ) : + getWidthOrHeight( elem, dimension, extra ); + } + }, + + set: function( elem, value, extra ) { + var matches, + styles = getStyles( elem ), + isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box", + subtract = extra && boxModelAdjustment( + elem, + dimension, + extra, + isBorderBox, + styles + ); + + // Account for unreliable border-box dimensions by comparing offset* to computed and + // faking a content-box to get border and padding (gh-3699) + if ( isBorderBox && support.scrollboxSize() === styles.position ) { + subtract -= Math.ceil( + elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] - + parseFloat( styles[ dimension ] ) - + boxModelAdjustment( elem, dimension, "border", false, styles ) - + 0.5 + ); + } + + // Convert to pixels if value adjustment is needed + if ( subtract && ( matches = rcssNum.exec( value ) ) && + ( matches[ 3 ] || "px" ) !== "px" ) { + + elem.style[ dimension ] = value; + value = jQuery.css( elem, dimension ); + } + + return setPositiveNumber( elem, value, subtract ); + } + }; +} ); + +jQuery.cssHooks.marginLeft = addGetHookIf( support.reliableMarginLeft, + function( elem, computed ) { + if ( computed ) { + return ( parseFloat( curCSS( elem, "marginLeft" ) ) || + elem.getBoundingClientRect().left - + swap( elem, { marginLeft: 0 }, function() { + return elem.getBoundingClientRect().left; + } ) + ) + "px"; + } + } +); + +// These hooks are used by animate to expand properties +jQuery.each( { + margin: "", + padding: "", + border: "Width" +}, function( prefix, suffix ) { + jQuery.cssHooks[ prefix + suffix ] = { + expand: function( value ) { + var i = 0, + expanded = {}, + + // Assumes a single number if not a string + parts = typeof value === "string" ? value.split( " " ) : [ value ]; + + for ( ; i < 4; i++ ) { + expanded[ prefix + cssExpand[ i ] + suffix ] = + parts[ i ] || parts[ i - 2 ] || parts[ 0 ]; + } + + return expanded; + } + }; + + if ( prefix !== "margin" ) { + jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber; + } +} ); + +jQuery.fn.extend( { + css: function( name, value ) { + return access( this, function( elem, name, value ) { + var styles, len, + map = {}, + i = 0; + + if ( Array.isArray( name ) ) { + styles = getStyles( elem ); + len = name.length; + + for ( ; i < len; i++ ) { + map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles ); + } + + return map; + } + + return value !== undefined ? + jQuery.style( elem, name, value ) : + jQuery.css( elem, name ); + }, name, value, arguments.length > 1 ); + } +} ); + + +function Tween( elem, options, prop, end, easing ) { + return new Tween.prototype.init( elem, options, prop, end, easing ); +} +jQuery.Tween = Tween; + +Tween.prototype = { + constructor: Tween, + init: function( elem, options, prop, end, easing, unit ) { + this.elem = elem; + this.prop = prop; + this.easing = easing || jQuery.easing._default; + this.options = options; + this.start = this.now = this.cur(); + this.end = end; + this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" ); + }, + cur: function() { + var hooks = Tween.propHooks[ this.prop ]; + + return hooks && hooks.get ? + hooks.get( this ) : + Tween.propHooks._default.get( this ); + }, + run: function( percent ) { + var eased, + hooks = Tween.propHooks[ this.prop ]; + + if ( this.options.duration ) { + this.pos = eased = jQuery.easing[ this.easing ]( + percent, this.options.duration * percent, 0, 1, this.options.duration + ); + } else { + this.pos = eased = percent; + } + this.now = ( this.end - this.start ) * eased + this.start; + + if ( this.options.step ) { + this.options.step.call( this.elem, this.now, this ); + } + + if ( hooks && hooks.set ) { + hooks.set( this ); + } else { + Tween.propHooks._default.set( this ); + } + return this; + } +}; + +Tween.prototype.init.prototype = Tween.prototype; + +Tween.propHooks = { + _default: { + get: function( tween ) { + var result; + + // Use a property on the element directly when it is not a DOM element, + // or when there is no matching style property that exists. + if ( tween.elem.nodeType !== 1 || + tween.elem[ tween.prop ] != null && tween.elem.style[ tween.prop ] == null ) { + return tween.elem[ tween.prop ]; + } + + // Passing an empty string as a 3rd parameter to .css will automatically + // attempt a parseFloat and fallback to a string if the parse fails. + // Simple values such as "10px" are parsed to Float; + // complex values such as "rotate(1rad)" are returned as-is. + result = jQuery.css( tween.elem, tween.prop, "" ); + + // Empty strings, null, undefined and "auto" are converted to 0. + return !result || result === "auto" ? 0 : result; + }, + set: function( tween ) { + + // Use step hook for back compat. + // Use cssHook if its there. + // Use .style if available and use plain properties where available. + if ( jQuery.fx.step[ tween.prop ] ) { + jQuery.fx.step[ tween.prop ]( tween ); + } else if ( tween.elem.nodeType === 1 && + ( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null || + jQuery.cssHooks[ tween.prop ] ) ) { + jQuery.style( tween.elem, tween.prop, tween.now + tween.unit ); + } else { + tween.elem[ tween.prop ] = tween.now; + } + } + } +}; + +// Support: IE <=9 only +// Panic based approach to setting things on disconnected nodes +Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = { + set: function( tween ) { + if ( tween.elem.nodeType && tween.elem.parentNode ) { + tween.elem[ tween.prop ] = tween.now; + } + } +}; + +jQuery.easing = { + linear: function( p ) { + return p; + }, + swing: function( p ) { + return 0.5 - Math.cos( p * Math.PI ) / 2; + }, + _default: "swing" +}; + +jQuery.fx = Tween.prototype.init; + +// Back compat <1.8 extension point +jQuery.fx.step = {}; + + + + +var + fxNow, inProgress, + rfxtypes = /^(?:toggle|show|hide)$/, + rrun = /queueHooks$/; + +function schedule() { + if ( inProgress ) { + if ( document.hidden === false && window.requestAnimationFrame ) { + window.requestAnimationFrame( schedule ); + } else { + window.setTimeout( schedule, jQuery.fx.interval ); + } + + jQuery.fx.tick(); + } +} + +// Animations created synchronously will run synchronously +function createFxNow() { + window.setTimeout( function() { + fxNow = undefined; + } ); + return ( fxNow = Date.now() ); +} + +// Generate parameters to create a standard animation +function genFx( type, includeWidth ) { + var which, + i = 0, + attrs = { height: type }; + + // If we include width, step value is 1 to do all cssExpand values, + // otherwise step value is 2 to skip over Left and Right + includeWidth = includeWidth ? 1 : 0; + for ( ; i < 4; i += 2 - includeWidth ) { + which = cssExpand[ i ]; + attrs[ "margin" + which ] = attrs[ "padding" + which ] = type; + } + + if ( includeWidth ) { + attrs.opacity = attrs.width = type; + } + + return attrs; +} + +function createTween( value, prop, animation ) { + var tween, + collection = ( Animation.tweeners[ prop ] || [] ).concat( Animation.tweeners[ "*" ] ), + index = 0, + length = collection.length; + for ( ; index < length; index++ ) { + if ( ( tween = collection[ index ].call( animation, prop, value ) ) ) { + + // We're done with this property + return tween; + } + } +} + +function defaultPrefilter( elem, props, opts ) { + var prop, value, toggle, hooks, oldfire, propTween, restoreDisplay, display, + isBox = "width" in props || "height" in props, + anim = this, + orig = {}, + style = elem.style, + hidden = elem.nodeType && isHiddenWithinTree( elem ), + dataShow = dataPriv.get( elem, "fxshow" ); + + // Queue-skipping animations hijack the fx hooks + if ( !opts.queue ) { + hooks = jQuery._queueHooks( elem, "fx" ); + if ( hooks.unqueued == null ) { + hooks.unqueued = 0; + oldfire = hooks.empty.fire; + hooks.empty.fire = function() { + if ( !hooks.unqueued ) { + oldfire(); + } + }; + } + hooks.unqueued++; + + anim.always( function() { + + // Ensure the complete handler is called before this completes + anim.always( function() { + hooks.unqueued--; + if ( !jQuery.queue( elem, "fx" ).length ) { + hooks.empty.fire(); + } + } ); + } ); + } + + // Detect show/hide animations + for ( prop in props ) { + value = props[ prop ]; + if ( rfxtypes.test( value ) ) { + delete props[ prop ]; + toggle = toggle || value === "toggle"; + if ( value === ( hidden ? "hide" : "show" ) ) { + + // Pretend to be hidden if this is a "show" and + // there is still data from a stopped show/hide + if ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) { + hidden = true; + + // Ignore all other no-op show/hide data + } else { + continue; + } + } + orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop ); + } + } + + // Bail out if this is a no-op like .hide().hide() + propTween = !jQuery.isEmptyObject( props ); + if ( !propTween && jQuery.isEmptyObject( orig ) ) { + return; + } + + // Restrict "overflow" and "display" styles during box animations + if ( isBox && elem.nodeType === 1 ) { + + // Support: IE <=9 - 11, Edge 12 - 15 + // Record all 3 overflow attributes because IE does not infer the shorthand + // from identically-valued overflowX and overflowY and Edge just mirrors + // the overflowX value there. + opts.overflow = [ style.overflow, style.overflowX, style.overflowY ]; + + // Identify a display type, preferring old show/hide data over the CSS cascade + restoreDisplay = dataShow && dataShow.display; + if ( restoreDisplay == null ) { + restoreDisplay = dataPriv.get( elem, "display" ); + } + display = jQuery.css( elem, "display" ); + if ( display === "none" ) { + if ( restoreDisplay ) { + display = restoreDisplay; + } else { + + // Get nonempty value(s) by temporarily forcing visibility + showHide( [ elem ], true ); + restoreDisplay = elem.style.display || restoreDisplay; + display = jQuery.css( elem, "display" ); + showHide( [ elem ] ); + } + } + + // Animate inline elements as inline-block + if ( display === "inline" || display === "inline-block" && restoreDisplay != null ) { + if ( jQuery.css( elem, "float" ) === "none" ) { + + // Restore the original display value at the end of pure show/hide animations + if ( !propTween ) { + anim.done( function() { + style.display = restoreDisplay; + } ); + if ( restoreDisplay == null ) { + display = style.display; + restoreDisplay = display === "none" ? "" : display; + } + } + style.display = "inline-block"; + } + } + } + + if ( opts.overflow ) { + style.overflow = "hidden"; + anim.always( function() { + style.overflow = opts.overflow[ 0 ]; + style.overflowX = opts.overflow[ 1 ]; + style.overflowY = opts.overflow[ 2 ]; + } ); + } + + // Implement show/hide animations + propTween = false; + for ( prop in orig ) { + + // General show/hide setup for this element animation + if ( !propTween ) { + if ( dataShow ) { + if ( "hidden" in dataShow ) { + hidden = dataShow.hidden; + } + } else { + dataShow = dataPriv.access( elem, "fxshow", { display: restoreDisplay } ); + } + + // Store hidden/visible for toggle so `.stop().toggle()` "reverses" + if ( toggle ) { + dataShow.hidden = !hidden; + } + + // Show elements before animating them + if ( hidden ) { + showHide( [ elem ], true ); + } + + /* eslint-disable no-loop-func */ + + anim.done( function() { + + /* eslint-enable no-loop-func */ + + // The final step of a "hide" animation is actually hiding the element + if ( !hidden ) { + showHide( [ elem ] ); + } + dataPriv.remove( elem, "fxshow" ); + for ( prop in orig ) { + jQuery.style( elem, prop, orig[ prop ] ); + } + } ); + } + + // Per-property setup + propTween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim ); + if ( !( prop in dataShow ) ) { + dataShow[ prop ] = propTween.start; + if ( hidden ) { + propTween.end = propTween.start; + propTween.start = 0; + } + } + } +} + +function propFilter( props, specialEasing ) { + var index, name, easing, value, hooks; + + // camelCase, specialEasing and expand cssHook pass + for ( index in props ) { + name = camelCase( index ); + easing = specialEasing[ name ]; + value = props[ index ]; + if ( Array.isArray( value ) ) { + easing = value[ 1 ]; + value = props[ index ] = value[ 0 ]; + } + + if ( index !== name ) { + props[ name ] = value; + delete props[ index ]; + } + + hooks = jQuery.cssHooks[ name ]; + if ( hooks && "expand" in hooks ) { + value = hooks.expand( value ); + delete props[ name ]; + + // Not quite $.extend, this won't overwrite existing keys. + // Reusing 'index' because we have the correct "name" + for ( index in value ) { + if ( !( index in props ) ) { + props[ index ] = value[ index ]; + specialEasing[ index ] = easing; + } + } + } else { + specialEasing[ name ] = easing; + } + } +} + +function Animation( elem, properties, options ) { + var result, + stopped, + index = 0, + length = Animation.prefilters.length, + deferred = jQuery.Deferred().always( function() { + + // Don't match elem in the :animated selector + delete tick.elem; + } ), + tick = function() { + if ( stopped ) { + return false; + } + var currentTime = fxNow || createFxNow(), + remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ), + + // Support: Android 2.3 only + // Archaic crash bug won't allow us to use `1 - ( 0.5 || 0 )` (#12497) + temp = remaining / animation.duration || 0, + percent = 1 - temp, + index = 0, + length = animation.tweens.length; + + for ( ; index < length; index++ ) { + animation.tweens[ index ].run( percent ); + } + + deferred.notifyWith( elem, [ animation, percent, remaining ] ); + + // If there's more to do, yield + if ( percent < 1 && length ) { + return remaining; + } + + // If this was an empty animation, synthesize a final progress notification + if ( !length ) { + deferred.notifyWith( elem, [ animation, 1, 0 ] ); + } + + // Resolve the animation and report its conclusion + deferred.resolveWith( elem, [ animation ] ); + return false; + }, + animation = deferred.promise( { + elem: elem, + props: jQuery.extend( {}, properties ), + opts: jQuery.extend( true, { + specialEasing: {}, + easing: jQuery.easing._default + }, options ), + originalProperties: properties, + originalOptions: options, + startTime: fxNow || createFxNow(), + duration: options.duration, + tweens: [], + createTween: function( prop, end ) { + var tween = jQuery.Tween( elem, animation.opts, prop, end, + animation.opts.specialEasing[ prop ] || animation.opts.easing ); + animation.tweens.push( tween ); + return tween; + }, + stop: function( gotoEnd ) { + var index = 0, + + // If we are going to the end, we want to run all the tweens + // otherwise we skip this part + length = gotoEnd ? animation.tweens.length : 0; + if ( stopped ) { + return this; + } + stopped = true; + for ( ; index < length; index++ ) { + animation.tweens[ index ].run( 1 ); + } + + // Resolve when we played the last frame; otherwise, reject + if ( gotoEnd ) { + deferred.notifyWith( elem, [ animation, 1, 0 ] ); + deferred.resolveWith( elem, [ animation, gotoEnd ] ); + } else { + deferred.rejectWith( elem, [ animation, gotoEnd ] ); + } + return this; + } + } ), + props = animation.props; + + propFilter( props, animation.opts.specialEasing ); + + for ( ; index < length; index++ ) { + result = Animation.prefilters[ index ].call( animation, elem, props, animation.opts ); + if ( result ) { + if ( isFunction( result.stop ) ) { + jQuery._queueHooks( animation.elem, animation.opts.queue ).stop = + result.stop.bind( result ); + } + return result; + } + } + + jQuery.map( props, createTween, animation ); + + if ( isFunction( animation.opts.start ) ) { + animation.opts.start.call( elem, animation ); + } + + // Attach callbacks from options + animation + .progress( animation.opts.progress ) + .done( animation.opts.done, animation.opts.complete ) + .fail( animation.opts.fail ) + .always( animation.opts.always ); + + jQuery.fx.timer( + jQuery.extend( tick, { + elem: elem, + anim: animation, + queue: animation.opts.queue + } ) + ); + + return animation; +} + +jQuery.Animation = jQuery.extend( Animation, { + + tweeners: { + "*": [ function( prop, value ) { + var tween = this.createTween( prop, value ); + adjustCSS( tween.elem, prop, rcssNum.exec( value ), tween ); + return tween; + } ] + }, + + tweener: function( props, callback ) { + if ( isFunction( props ) ) { + callback = props; + props = [ "*" ]; + } else { + props = props.match( rnothtmlwhite ); + } + + var prop, + index = 0, + length = props.length; + + for ( ; index < length; index++ ) { + prop = props[ index ]; + Animation.tweeners[ prop ] = Animation.tweeners[ prop ] || []; + Animation.tweeners[ prop ].unshift( callback ); + } + }, + + prefilters: [ defaultPrefilter ], + + prefilter: function( callback, prepend ) { + if ( prepend ) { + Animation.prefilters.unshift( callback ); + } else { + Animation.prefilters.push( callback ); + } + } +} ); + +jQuery.speed = function( speed, easing, fn ) { + var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : { + complete: fn || !fn && easing || + isFunction( speed ) && speed, + duration: speed, + easing: fn && easing || easing && !isFunction( easing ) && easing + }; + + // Go to the end state if fx are off + if ( jQuery.fx.off ) { + opt.duration = 0; + + } else { + if ( typeof opt.duration !== "number" ) { + if ( opt.duration in jQuery.fx.speeds ) { + opt.duration = jQuery.fx.speeds[ opt.duration ]; + + } else { + opt.duration = jQuery.fx.speeds._default; + } + } + } + + // Normalize opt.queue - true/undefined/null -> "fx" + if ( opt.queue == null || opt.queue === true ) { + opt.queue = "fx"; + } + + // Queueing + opt.old = opt.complete; + + opt.complete = function() { + if ( isFunction( opt.old ) ) { + opt.old.call( this ); + } + + if ( opt.queue ) { + jQuery.dequeue( this, opt.queue ); + } + }; + + return opt; +}; + +jQuery.fn.extend( { + fadeTo: function( speed, to, easing, callback ) { + + // Show any hidden elements after setting opacity to 0 + return this.filter( isHiddenWithinTree ).css( "opacity", 0 ).show() + + // Animate to the value specified + .end().animate( { opacity: to }, speed, easing, callback ); + }, + animate: function( prop, speed, easing, callback ) { + var empty = jQuery.isEmptyObject( prop ), + optall = jQuery.speed( speed, easing, callback ), + doAnimation = function() { + + // Operate on a copy of prop so per-property easing won't be lost + var anim = Animation( this, jQuery.extend( {}, prop ), optall ); + + // Empty animations, or finishing resolves immediately + if ( empty || dataPriv.get( this, "finish" ) ) { + anim.stop( true ); + } + }; + doAnimation.finish = doAnimation; + + return empty || optall.queue === false ? + this.each( doAnimation ) : + this.queue( optall.queue, doAnimation ); + }, + stop: function( type, clearQueue, gotoEnd ) { + var stopQueue = function( hooks ) { + var stop = hooks.stop; + delete hooks.stop; + stop( gotoEnd ); + }; + + if ( typeof type !== "string" ) { + gotoEnd = clearQueue; + clearQueue = type; + type = undefined; + } + if ( clearQueue && type !== false ) { + this.queue( type || "fx", [] ); + } + + return this.each( function() { + var dequeue = true, + index = type != null && type + "queueHooks", + timers = jQuery.timers, + data = dataPriv.get( this ); + + if ( index ) { + if ( data[ index ] && data[ index ].stop ) { + stopQueue( data[ index ] ); + } + } else { + for ( index in data ) { + if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) { + stopQueue( data[ index ] ); + } + } + } + + for ( index = timers.length; index--; ) { + if ( timers[ index ].elem === this && + ( type == null || timers[ index ].queue === type ) ) { + + timers[ index ].anim.stop( gotoEnd ); + dequeue = false; + timers.splice( index, 1 ); + } + } + + // Start the next in the queue if the last step wasn't forced. + // Timers currently will call their complete callbacks, which + // will dequeue but only if they were gotoEnd. + if ( dequeue || !gotoEnd ) { + jQuery.dequeue( this, type ); + } + } ); + }, + finish: function( type ) { + if ( type !== false ) { + type = type || "fx"; + } + return this.each( function() { + var index, + data = dataPriv.get( this ), + queue = data[ type + "queue" ], + hooks = data[ type + "queueHooks" ], + timers = jQuery.timers, + length = queue ? queue.length : 0; + + // Enable finishing flag on private data + data.finish = true; + + // Empty the queue first + jQuery.queue( this, type, [] ); + + if ( hooks && hooks.stop ) { + hooks.stop.call( this, true ); + } + + // Look for any active animations, and finish them + for ( index = timers.length; index--; ) { + if ( timers[ index ].elem === this && timers[ index ].queue === type ) { + timers[ index ].anim.stop( true ); + timers.splice( index, 1 ); + } + } + + // Look for any animations in the old queue and finish them + for ( index = 0; index < length; index++ ) { + if ( queue[ index ] && queue[ index ].finish ) { + queue[ index ].finish.call( this ); + } + } + + // Turn off finishing flag + delete data.finish; + } ); + } +} ); + +jQuery.each( [ "toggle", "show", "hide" ], function( i, name ) { + var cssFn = jQuery.fn[ name ]; + jQuery.fn[ name ] = function( speed, easing, callback ) { + return speed == null || typeof speed === "boolean" ? + cssFn.apply( this, arguments ) : + this.animate( genFx( name, true ), speed, easing, callback ); + }; +} ); + +// Generate shortcuts for custom animations +jQuery.each( { + slideDown: genFx( "show" ), + slideUp: genFx( "hide" ), + slideToggle: genFx( "toggle" ), + fadeIn: { opacity: "show" }, + fadeOut: { opacity: "hide" }, + fadeToggle: { opacity: "toggle" } +}, function( name, props ) { + jQuery.fn[ name ] = function( speed, easing, callback ) { + return this.animate( props, speed, easing, callback ); + }; +} ); + +jQuery.timers = []; +jQuery.fx.tick = function() { + var timer, + i = 0, + timers = jQuery.timers; + + fxNow = Date.now(); + + for ( ; i < timers.length; i++ ) { + timer = timers[ i ]; + + // Run the timer and safely remove it when done (allowing for external removal) + if ( !timer() && timers[ i ] === timer ) { + timers.splice( i--, 1 ); + } + } + + if ( !timers.length ) { + jQuery.fx.stop(); + } + fxNow = undefined; +}; + +jQuery.fx.timer = function( timer ) { + jQuery.timers.push( timer ); + jQuery.fx.start(); +}; + +jQuery.fx.interval = 13; +jQuery.fx.start = function() { + if ( inProgress ) { + return; + } + + inProgress = true; + schedule(); +}; + +jQuery.fx.stop = function() { + inProgress = null; +}; + +jQuery.fx.speeds = { + slow: 600, + fast: 200, + + // Default speed + _default: 400 +}; + + +// Based off of the plugin by Clint Helfers, with permission. +// https://web.archive.org/web/20100324014747/http://blindsignals.com/index.php/2009/07/jquery-delay/ +jQuery.fn.delay = function( time, type ) { + time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time; + type = type || "fx"; + + return this.queue( type, function( next, hooks ) { + var timeout = window.setTimeout( next, time ); + hooks.stop = function() { + window.clearTimeout( timeout ); + }; + } ); +}; + + +( function() { + var input = document.createElement( "input" ), + select = document.createElement( "select" ), + opt = select.appendChild( document.createElement( "option" ) ); + + input.type = "checkbox"; + + // Support: Android <=4.3 only + // Default value for a checkbox should be "on" + support.checkOn = input.value !== ""; + + // Support: IE <=11 only + // Must access selectedIndex to make default options select + support.optSelected = opt.selected; + + // Support: IE <=11 only + // An input loses its value after becoming a radio + input = document.createElement( "input" ); + input.value = "t"; + input.type = "radio"; + support.radioValue = input.value === "t"; +} )(); + + +var boolHook, + attrHandle = jQuery.expr.attrHandle; + +jQuery.fn.extend( { + attr: function( name, value ) { + return access( this, jQuery.attr, name, value, arguments.length > 1 ); + }, + + removeAttr: function( name ) { + return this.each( function() { + jQuery.removeAttr( this, name ); + } ); + } +} ); + +jQuery.extend( { + attr: function( elem, name, value ) { + var ret, hooks, + nType = elem.nodeType; + + // Don't get/set attributes on text, comment and attribute nodes + if ( nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + // Fallback to prop when attributes are not supported + if ( typeof elem.getAttribute === "undefined" ) { + return jQuery.prop( elem, name, value ); + } + + // Attribute hooks are determined by the lowercase version + // Grab necessary hook if one is defined + if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { + hooks = jQuery.attrHooks[ name.toLowerCase() ] || + ( jQuery.expr.match.bool.test( name ) ? boolHook : undefined ); + } + + if ( value !== undefined ) { + if ( value === null ) { + jQuery.removeAttr( elem, name ); + return; + } + + if ( hooks && "set" in hooks && + ( ret = hooks.set( elem, value, name ) ) !== undefined ) { + return ret; + } + + elem.setAttribute( name, value + "" ); + return value; + } + + if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) { + return ret; + } + + ret = jQuery.find.attr( elem, name ); + + // Non-existent attributes return null, we normalize to undefined + return ret == null ? undefined : ret; + }, + + attrHooks: { + type: { + set: function( elem, value ) { + if ( !support.radioValue && value === "radio" && + nodeName( elem, "input" ) ) { + var val = elem.value; + elem.setAttribute( "type", value ); + if ( val ) { + elem.value = val; + } + return value; + } + } + } + }, + + removeAttr: function( elem, value ) { + var name, + i = 0, + + // Attribute names can contain non-HTML whitespace characters + // https://html.spec.whatwg.org/multipage/syntax.html#attributes-2 + attrNames = value && value.match( rnothtmlwhite ); + + if ( attrNames && elem.nodeType === 1 ) { + while ( ( name = attrNames[ i++ ] ) ) { + elem.removeAttribute( name ); + } + } + } +} ); + +// Hooks for boolean attributes +boolHook = { + set: function( elem, value, name ) { + if ( value === false ) { + + // Remove boolean attributes when set to false + jQuery.removeAttr( elem, name ); + } else { + elem.setAttribute( name, name ); + } + return name; + } +}; + +jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( i, name ) { + var getter = attrHandle[ name ] || jQuery.find.attr; + + attrHandle[ name ] = function( elem, name, isXML ) { + var ret, handle, + lowercaseName = name.toLowerCase(); + + if ( !isXML ) { + + // Avoid an infinite loop by temporarily removing this function from the getter + handle = attrHandle[ lowercaseName ]; + attrHandle[ lowercaseName ] = ret; + ret = getter( elem, name, isXML ) != null ? + lowercaseName : + null; + attrHandle[ lowercaseName ] = handle; + } + return ret; + }; +} ); + + + + +var rfocusable = /^(?:input|select|textarea|button)$/i, + rclickable = /^(?:a|area)$/i; + +jQuery.fn.extend( { + prop: function( name, value ) { + return access( this, jQuery.prop, name, value, arguments.length > 1 ); + }, + + removeProp: function( name ) { + return this.each( function() { + delete this[ jQuery.propFix[ name ] || name ]; + } ); + } +} ); + +jQuery.extend( { + prop: function( elem, name, value ) { + var ret, hooks, + nType = elem.nodeType; + + // Don't get/set properties on text, comment and attribute nodes + if ( nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { + + // Fix name and attach hooks + name = jQuery.propFix[ name ] || name; + hooks = jQuery.propHooks[ name ]; + } + + if ( value !== undefined ) { + if ( hooks && "set" in hooks && + ( ret = hooks.set( elem, value, name ) ) !== undefined ) { + return ret; + } + + return ( elem[ name ] = value ); + } + + if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) { + return ret; + } + + return elem[ name ]; + }, + + propHooks: { + tabIndex: { + get: function( elem ) { + + // Support: IE <=9 - 11 only + // elem.tabIndex doesn't always return the + // correct value when it hasn't been explicitly set + // https://web.archive.org/web/20141116233347/http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ + // Use proper attribute retrieval(#12072) + var tabindex = jQuery.find.attr( elem, "tabindex" ); + + if ( tabindex ) { + return parseInt( tabindex, 10 ); + } + + if ( + rfocusable.test( elem.nodeName ) || + rclickable.test( elem.nodeName ) && + elem.href + ) { + return 0; + } + + return -1; + } + } + }, + + propFix: { + "for": "htmlFor", + "class": "className" + } +} ); + +// Support: IE <=11 only +// Accessing the selectedIndex property +// forces the browser to respect setting selected +// on the option +// The getter ensures a default option is selected +// when in an optgroup +// eslint rule "no-unused-expressions" is disabled for this code +// since it considers such accessions noop +if ( !support.optSelected ) { + jQuery.propHooks.selected = { + get: function( elem ) { + + /* eslint no-unused-expressions: "off" */ + + var parent = elem.parentNode; + if ( parent && parent.parentNode ) { + parent.parentNode.selectedIndex; + } + return null; + }, + set: function( elem ) { + + /* eslint no-unused-expressions: "off" */ + + var parent = elem.parentNode; + if ( parent ) { + parent.selectedIndex; + + if ( parent.parentNode ) { + parent.parentNode.selectedIndex; + } + } + } + }; +} + +jQuery.each( [ + "tabIndex", + "readOnly", + "maxLength", + "cellSpacing", + "cellPadding", + "rowSpan", + "colSpan", + "useMap", + "frameBorder", + "contentEditable" +], function() { + jQuery.propFix[ this.toLowerCase() ] = this; +} ); + + + + + // Strip and collapse whitespace according to HTML spec + // https://infra.spec.whatwg.org/#strip-and-collapse-ascii-whitespace + function stripAndCollapse( value ) { + var tokens = value.match( rnothtmlwhite ) || []; + return tokens.join( " " ); + } + + +function getClass( elem ) { + return elem.getAttribute && elem.getAttribute( "class" ) || ""; +} + +function classesToArray( value ) { + if ( Array.isArray( value ) ) { + return value; + } + if ( typeof value === "string" ) { + return value.match( rnothtmlwhite ) || []; + } + return []; +} + +jQuery.fn.extend( { + addClass: function( value ) { + var classes, elem, cur, curValue, clazz, j, finalValue, + i = 0; + + if ( isFunction( value ) ) { + return this.each( function( j ) { + jQuery( this ).addClass( value.call( this, j, getClass( this ) ) ); + } ); + } + + classes = classesToArray( value ); + + if ( classes.length ) { + while ( ( elem = this[ i++ ] ) ) { + curValue = getClass( elem ); + cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); + + if ( cur ) { + j = 0; + while ( ( clazz = classes[ j++ ] ) ) { + if ( cur.indexOf( " " + clazz + " " ) < 0 ) { + cur += clazz + " "; + } + } + + // Only assign if different to avoid unneeded rendering. + finalValue = stripAndCollapse( cur ); + if ( curValue !== finalValue ) { + elem.setAttribute( "class", finalValue ); + } + } + } + } + + return this; + }, + + removeClass: function( value ) { + var classes, elem, cur, curValue, clazz, j, finalValue, + i = 0; + + if ( isFunction( value ) ) { + return this.each( function( j ) { + jQuery( this ).removeClass( value.call( this, j, getClass( this ) ) ); + } ); + } + + if ( !arguments.length ) { + return this.attr( "class", "" ); + } + + classes = classesToArray( value ); + + if ( classes.length ) { + while ( ( elem = this[ i++ ] ) ) { + curValue = getClass( elem ); + + // This expression is here for better compressibility (see addClass) + cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); + + if ( cur ) { + j = 0; + while ( ( clazz = classes[ j++ ] ) ) { + + // Remove *all* instances + while ( cur.indexOf( " " + clazz + " " ) > -1 ) { + cur = cur.replace( " " + clazz + " ", " " ); + } + } + + // Only assign if different to avoid unneeded rendering. + finalValue = stripAndCollapse( cur ); + if ( curValue !== finalValue ) { + elem.setAttribute( "class", finalValue ); + } + } + } + } + + return this; + }, + + toggleClass: function( value, stateVal ) { + var type = typeof value, + isValidValue = type === "string" || Array.isArray( value ); + + if ( typeof stateVal === "boolean" && isValidValue ) { + return stateVal ? this.addClass( value ) : this.removeClass( value ); + } + + if ( isFunction( value ) ) { + return this.each( function( i ) { + jQuery( this ).toggleClass( + value.call( this, i, getClass( this ), stateVal ), + stateVal + ); + } ); + } + + return this.each( function() { + var className, i, self, classNames; + + if ( isValidValue ) { + + // Toggle individual class names + i = 0; + self = jQuery( this ); + classNames = classesToArray( value ); + + while ( ( className = classNames[ i++ ] ) ) { + + // Check each className given, space separated list + if ( self.hasClass( className ) ) { + self.removeClass( className ); + } else { + self.addClass( className ); + } + } + + // Toggle whole class name + } else if ( value === undefined || type === "boolean" ) { + className = getClass( this ); + if ( className ) { + + // Store className if set + dataPriv.set( this, "__className__", className ); + } + + // If the element has a class name or if we're passed `false`, + // then remove the whole classname (if there was one, the above saved it). + // Otherwise bring back whatever was previously saved (if anything), + // falling back to the empty string if nothing was stored. + if ( this.setAttribute ) { + this.setAttribute( "class", + className || value === false ? + "" : + dataPriv.get( this, "__className__" ) || "" + ); + } + } + } ); + }, + + hasClass: function( selector ) { + var className, elem, + i = 0; + + className = " " + selector + " "; + while ( ( elem = this[ i++ ] ) ) { + if ( elem.nodeType === 1 && + ( " " + stripAndCollapse( getClass( elem ) ) + " " ).indexOf( className ) > -1 ) { + return true; + } + } + + return false; + } +} ); + + + + +var rreturn = /\r/g; + +jQuery.fn.extend( { + val: function( value ) { + var hooks, ret, valueIsFunction, + elem = this[ 0 ]; + + if ( !arguments.length ) { + if ( elem ) { + hooks = jQuery.valHooks[ elem.type ] || + jQuery.valHooks[ elem.nodeName.toLowerCase() ]; + + if ( hooks && + "get" in hooks && + ( ret = hooks.get( elem, "value" ) ) !== undefined + ) { + return ret; + } + + ret = elem.value; + + // Handle most common string cases + if ( typeof ret === "string" ) { + return ret.replace( rreturn, "" ); + } + + // Handle cases where value is null/undef or number + return ret == null ? "" : ret; + } + + return; + } + + valueIsFunction = isFunction( value ); + + return this.each( function( i ) { + var val; + + if ( this.nodeType !== 1 ) { + return; + } + + if ( valueIsFunction ) { + val = value.call( this, i, jQuery( this ).val() ); + } else { + val = value; + } + + // Treat null/undefined as ""; convert numbers to string + if ( val == null ) { + val = ""; + + } else if ( typeof val === "number" ) { + val += ""; + + } else if ( Array.isArray( val ) ) { + val = jQuery.map( val, function( value ) { + return value == null ? "" : value + ""; + } ); + } + + hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ]; + + // If set returns undefined, fall back to normal setting + if ( !hooks || !( "set" in hooks ) || hooks.set( this, val, "value" ) === undefined ) { + this.value = val; + } + } ); + } +} ); + +jQuery.extend( { + valHooks: { + option: { + get: function( elem ) { + + var val = jQuery.find.attr( elem, "value" ); + return val != null ? + val : + + // Support: IE <=10 - 11 only + // option.text throws exceptions (#14686, #14858) + // Strip and collapse whitespace + // https://html.spec.whatwg.org/#strip-and-collapse-whitespace + stripAndCollapse( jQuery.text( elem ) ); + } + }, + select: { + get: function( elem ) { + var value, option, i, + options = elem.options, + index = elem.selectedIndex, + one = elem.type === "select-one", + values = one ? null : [], + max = one ? index + 1 : options.length; + + if ( index < 0 ) { + i = max; + + } else { + i = one ? index : 0; + } + + // Loop through all the selected options + for ( ; i < max; i++ ) { + option = options[ i ]; + + // Support: IE <=9 only + // IE8-9 doesn't update selected after form reset (#2551) + if ( ( option.selected || i === index ) && + + // Don't return options that are disabled or in a disabled optgroup + !option.disabled && + ( !option.parentNode.disabled || + !nodeName( option.parentNode, "optgroup" ) ) ) { + + // Get the specific value for the option + value = jQuery( option ).val(); + + // We don't need an array for one selects + if ( one ) { + return value; + } + + // Multi-Selects return an array + values.push( value ); + } + } + + return values; + }, + + set: function( elem, value ) { + var optionSet, option, + options = elem.options, + values = jQuery.makeArray( value ), + i = options.length; + + while ( i-- ) { + option = options[ i ]; + + /* eslint-disable no-cond-assign */ + + if ( option.selected = + jQuery.inArray( jQuery.valHooks.option.get( option ), values ) > -1 + ) { + optionSet = true; + } + + /* eslint-enable no-cond-assign */ + } + + // Force browsers to behave consistently when non-matching value is set + if ( !optionSet ) { + elem.selectedIndex = -1; + } + return values; + } + } + } +} ); + +// Radios and checkboxes getter/setter +jQuery.each( [ "radio", "checkbox" ], function() { + jQuery.valHooks[ this ] = { + set: function( elem, value ) { + if ( Array.isArray( value ) ) { + return ( elem.checked = jQuery.inArray( jQuery( elem ).val(), value ) > -1 ); + } + } + }; + if ( !support.checkOn ) { + jQuery.valHooks[ this ].get = function( elem ) { + return elem.getAttribute( "value" ) === null ? "on" : elem.value; + }; + } +} ); + + + + +// Return jQuery for attributes-only inclusion + + +support.focusin = "onfocusin" in window; + + +var rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, + stopPropagationCallback = function( e ) { + e.stopPropagation(); + }; + +jQuery.extend( jQuery.event, { + + trigger: function( event, data, elem, onlyHandlers ) { + + var i, cur, tmp, bubbleType, ontype, handle, special, lastElement, + eventPath = [ elem || document ], + type = hasOwn.call( event, "type" ) ? event.type : event, + namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split( "." ) : []; + + cur = lastElement = tmp = elem = elem || document; + + // Don't do events on text and comment nodes + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + // focus/blur morphs to focusin/out; ensure we're not firing them right now + if ( rfocusMorph.test( type + jQuery.event.triggered ) ) { + return; + } + + if ( type.indexOf( "." ) > -1 ) { + + // Namespaced trigger; create a regexp to match event type in handle() + namespaces = type.split( "." ); + type = namespaces.shift(); + namespaces.sort(); + } + ontype = type.indexOf( ":" ) < 0 && "on" + type; + + // Caller can pass in a jQuery.Event object, Object, or just an event type string + event = event[ jQuery.expando ] ? + event : + new jQuery.Event( type, typeof event === "object" && event ); + + // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true) + event.isTrigger = onlyHandlers ? 2 : 3; + event.namespace = namespaces.join( "." ); + event.rnamespace = event.namespace ? + new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ) : + null; + + // Clean up the event in case it is being reused + event.result = undefined; + if ( !event.target ) { + event.target = elem; + } + + // Clone any incoming data and prepend the event, creating the handler arg list + data = data == null ? + [ event ] : + jQuery.makeArray( data, [ event ] ); + + // Allow special events to draw outside the lines + special = jQuery.event.special[ type ] || {}; + if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) { + return; + } + + // Determine event propagation path in advance, per W3C events spec (#9951) + // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) + if ( !onlyHandlers && !special.noBubble && !isWindow( elem ) ) { + + bubbleType = special.delegateType || type; + if ( !rfocusMorph.test( bubbleType + type ) ) { + cur = cur.parentNode; + } + for ( ; cur; cur = cur.parentNode ) { + eventPath.push( cur ); + tmp = cur; + } + + // Only add window if we got to document (e.g., not plain obj or detached DOM) + if ( tmp === ( elem.ownerDocument || document ) ) { + eventPath.push( tmp.defaultView || tmp.parentWindow || window ); + } + } + + // Fire handlers on the event path + i = 0; + while ( ( cur = eventPath[ i++ ] ) && !event.isPropagationStopped() ) { + lastElement = cur; + event.type = i > 1 ? + bubbleType : + special.bindType || type; + + // jQuery handler + handle = ( dataPriv.get( cur, "events" ) || {} )[ event.type ] && + dataPriv.get( cur, "handle" ); + if ( handle ) { + handle.apply( cur, data ); + } + + // Native handler + handle = ontype && cur[ ontype ]; + if ( handle && handle.apply && acceptData( cur ) ) { + event.result = handle.apply( cur, data ); + if ( event.result === false ) { + event.preventDefault(); + } + } + } + event.type = type; + + // If nobody prevented the default action, do it now + if ( !onlyHandlers && !event.isDefaultPrevented() ) { + + if ( ( !special._default || + special._default.apply( eventPath.pop(), data ) === false ) && + acceptData( elem ) ) { + + // Call a native DOM method on the target with the same name as the event. + // Don't do default actions on window, that's where global variables be (#6170) + if ( ontype && isFunction( elem[ type ] ) && !isWindow( elem ) ) { + + // Don't re-trigger an onFOO event when we call its FOO() method + tmp = elem[ ontype ]; + + if ( tmp ) { + elem[ ontype ] = null; + } + + // Prevent re-triggering of the same event, since we already bubbled it above + jQuery.event.triggered = type; + + if ( event.isPropagationStopped() ) { + lastElement.addEventListener( type, stopPropagationCallback ); + } + + elem[ type ](); + + if ( event.isPropagationStopped() ) { + lastElement.removeEventListener( type, stopPropagationCallback ); + } + + jQuery.event.triggered = undefined; + + if ( tmp ) { + elem[ ontype ] = tmp; + } + } + } + } + + return event.result; + }, + + // Piggyback on a donor event to simulate a different one + // Used only for `focus(in | out)` events + simulate: function( type, elem, event ) { + var e = jQuery.extend( + new jQuery.Event(), + event, + { + type: type, + isSimulated: true + } + ); + + jQuery.event.trigger( e, null, elem ); + } + +} ); + +jQuery.fn.extend( { + + trigger: function( type, data ) { + return this.each( function() { + jQuery.event.trigger( type, data, this ); + } ); + }, + triggerHandler: function( type, data ) { + var elem = this[ 0 ]; + if ( elem ) { + return jQuery.event.trigger( type, data, elem, true ); + } + } +} ); + + +// Support: Firefox <=44 +// Firefox doesn't have focus(in | out) events +// Related ticket - https://bugzilla.mozilla.org/show_bug.cgi?id=687787 +// +// Support: Chrome <=48 - 49, Safari <=9.0 - 9.1 +// focus(in | out) events fire after focus & blur events, +// which is spec violation - http://www.w3.org/TR/DOM-Level-3-Events/#events-focusevent-event-order +// Related ticket - https://bugs.chromium.org/p/chromium/issues/detail?id=449857 +if ( !support.focusin ) { + jQuery.each( { focus: "focusin", blur: "focusout" }, function( orig, fix ) { + + // Attach a single capturing handler on the document while someone wants focusin/focusout + var handler = function( event ) { + jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ) ); + }; + + jQuery.event.special[ fix ] = { + setup: function() { + var doc = this.ownerDocument || this, + attaches = dataPriv.access( doc, fix ); + + if ( !attaches ) { + doc.addEventListener( orig, handler, true ); + } + dataPriv.access( doc, fix, ( attaches || 0 ) + 1 ); + }, + teardown: function() { + var doc = this.ownerDocument || this, + attaches = dataPriv.access( doc, fix ) - 1; + + if ( !attaches ) { + doc.removeEventListener( orig, handler, true ); + dataPriv.remove( doc, fix ); + + } else { + dataPriv.access( doc, fix, attaches ); + } + } + }; + } ); +} +var location = window.location; + +var nonce = Date.now(); + +var rquery = ( /\?/ ); + + + +// Cross-browser xml parsing +jQuery.parseXML = function( data ) { + var xml; + if ( !data || typeof data !== "string" ) { + return null; + } + + // Support: IE 9 - 11 only + // IE throws on parseFromString with invalid input. + try { + xml = ( new window.DOMParser() ).parseFromString( data, "text/xml" ); + } catch ( e ) { + xml = undefined; + } + + if ( !xml || xml.getElementsByTagName( "parsererror" ).length ) { + jQuery.error( "Invalid XML: " + data ); + } + return xml; +}; + + +var + rbracket = /\[\]$/, + rCRLF = /\r?\n/g, + rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i, + rsubmittable = /^(?:input|select|textarea|keygen)/i; + +function buildParams( prefix, obj, traditional, add ) { + var name; + + if ( Array.isArray( obj ) ) { + + // Serialize array item. + jQuery.each( obj, function( i, v ) { + if ( traditional || rbracket.test( prefix ) ) { + + // Treat each array item as a scalar. + add( prefix, v ); + + } else { + + // Item is non-scalar (array or object), encode its numeric index. + buildParams( + prefix + "[" + ( typeof v === "object" && v != null ? i : "" ) + "]", + v, + traditional, + add + ); + } + } ); + + } else if ( !traditional && toType( obj ) === "object" ) { + + // Serialize object item. + for ( name in obj ) { + buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add ); + } + + } else { + + // Serialize scalar item. + add( prefix, obj ); + } +} + +// Serialize an array of form elements or a set of +// key/values into a query string +jQuery.param = function( a, traditional ) { + var prefix, + s = [], + add = function( key, valueOrFunction ) { + + // If value is a function, invoke it and use its return value + var value = isFunction( valueOrFunction ) ? + valueOrFunction() : + valueOrFunction; + + s[ s.length ] = encodeURIComponent( key ) + "=" + + encodeURIComponent( value == null ? "" : value ); + }; + + // If an array was passed in, assume that it is an array of form elements. + if ( Array.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) { + + // Serialize the form elements + jQuery.each( a, function() { + add( this.name, this.value ); + } ); + + } else { + + // If traditional, encode the "old" way (the way 1.3.2 or older + // did it), otherwise encode params recursively. + for ( prefix in a ) { + buildParams( prefix, a[ prefix ], traditional, add ); + } + } + + // Return the resulting serialization + return s.join( "&" ); +}; + +jQuery.fn.extend( { + serialize: function() { + return jQuery.param( this.serializeArray() ); + }, + serializeArray: function() { + return this.map( function() { + + // Can add propHook for "elements" to filter or add form elements + var elements = jQuery.prop( this, "elements" ); + return elements ? jQuery.makeArray( elements ) : this; + } ) + .filter( function() { + var type = this.type; + + // Use .is( ":disabled" ) so that fieldset[disabled] works + return this.name && !jQuery( this ).is( ":disabled" ) && + rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) && + ( this.checked || !rcheckableType.test( type ) ); + } ) + .map( function( i, elem ) { + var val = jQuery( this ).val(); + + if ( val == null ) { + return null; + } + + if ( Array.isArray( val ) ) { + return jQuery.map( val, function( val ) { + return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; + } ); + } + + return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; + } ).get(); + } +} ); + + +var + r20 = /%20/g, + rhash = /#.*$/, + rantiCache = /([?&])_=[^&]*/, + rheaders = /^(.*?):[ \t]*([^\r\n]*)$/mg, + + // #7653, #8125, #8152: local protocol detection + rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/, + rnoContent = /^(?:GET|HEAD)$/, + rprotocol = /^\/\//, + + /* Prefilters + * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example) + * 2) These are called: + * - BEFORE asking for a transport + * - AFTER param serialization (s.data is a string if s.processData is true) + * 3) key is the dataType + * 4) the catchall symbol "*" can be used + * 5) execution will start with transport dataType and THEN continue down to "*" if needed + */ + prefilters = {}, + + /* Transports bindings + * 1) key is the dataType + * 2) the catchall symbol "*" can be used + * 3) selection will start with transport dataType and THEN go to "*" if needed + */ + transports = {}, + + // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression + allTypes = "*/".concat( "*" ), + + // Anchor tag for parsing the document origin + originAnchor = document.createElement( "a" ); + originAnchor.href = location.href; + +// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport +function addToPrefiltersOrTransports( structure ) { + + // dataTypeExpression is optional and defaults to "*" + return function( dataTypeExpression, func ) { + + if ( typeof dataTypeExpression !== "string" ) { + func = dataTypeExpression; + dataTypeExpression = "*"; + } + + var dataType, + i = 0, + dataTypes = dataTypeExpression.toLowerCase().match( rnothtmlwhite ) || []; + + if ( isFunction( func ) ) { + + // For each dataType in the dataTypeExpression + while ( ( dataType = dataTypes[ i++ ] ) ) { + + // Prepend if requested + if ( dataType[ 0 ] === "+" ) { + dataType = dataType.slice( 1 ) || "*"; + ( structure[ dataType ] = structure[ dataType ] || [] ).unshift( func ); + + // Otherwise append + } else { + ( structure[ dataType ] = structure[ dataType ] || [] ).push( func ); + } + } + } + }; +} + +// Base inspection function for prefilters and transports +function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) { + + var inspected = {}, + seekingTransport = ( structure === transports ); + + function inspect( dataType ) { + var selected; + inspected[ dataType ] = true; + jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) { + var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR ); + if ( typeof dataTypeOrTransport === "string" && + !seekingTransport && !inspected[ dataTypeOrTransport ] ) { + + options.dataTypes.unshift( dataTypeOrTransport ); + inspect( dataTypeOrTransport ); + return false; + } else if ( seekingTransport ) { + return !( selected = dataTypeOrTransport ); + } + } ); + return selected; + } + + return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" ); +} + +// A special extend for ajax options +// that takes "flat" options (not to be deep extended) +// Fixes #9887 +function ajaxExtend( target, src ) { + var key, deep, + flatOptions = jQuery.ajaxSettings.flatOptions || {}; + + for ( key in src ) { + if ( src[ key ] !== undefined ) { + ( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ]; + } + } + if ( deep ) { + jQuery.extend( true, target, deep ); + } + + return target; +} + +/* Handles responses to an ajax request: + * - finds the right dataType (mediates between content-type and expected dataType) + * - returns the corresponding response + */ +function ajaxHandleResponses( s, jqXHR, responses ) { + + var ct, type, finalDataType, firstDataType, + contents = s.contents, + dataTypes = s.dataTypes; + + // Remove auto dataType and get content-type in the process + while ( dataTypes[ 0 ] === "*" ) { + dataTypes.shift(); + if ( ct === undefined ) { + ct = s.mimeType || jqXHR.getResponseHeader( "Content-Type" ); + } + } + + // Check if we're dealing with a known content-type + if ( ct ) { + for ( type in contents ) { + if ( contents[ type ] && contents[ type ].test( ct ) ) { + dataTypes.unshift( type ); + break; + } + } + } + + // Check to see if we have a response for the expected dataType + if ( dataTypes[ 0 ] in responses ) { + finalDataType = dataTypes[ 0 ]; + } else { + + // Try convertible dataTypes + for ( type in responses ) { + if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[ 0 ] ] ) { + finalDataType = type; + break; + } + if ( !firstDataType ) { + firstDataType = type; + } + } + + // Or just use first one + finalDataType = finalDataType || firstDataType; + } + + // If we found a dataType + // We add the dataType to the list if needed + // and return the corresponding response + if ( finalDataType ) { + if ( finalDataType !== dataTypes[ 0 ] ) { + dataTypes.unshift( finalDataType ); + } + return responses[ finalDataType ]; + } +} + +/* Chain conversions given the request and the original response + * Also sets the responseXXX fields on the jqXHR instance + */ +function ajaxConvert( s, response, jqXHR, isSuccess ) { + var conv2, current, conv, tmp, prev, + converters = {}, + + // Work with a copy of dataTypes in case we need to modify it for conversion + dataTypes = s.dataTypes.slice(); + + // Create converters map with lowercased keys + if ( dataTypes[ 1 ] ) { + for ( conv in s.converters ) { + converters[ conv.toLowerCase() ] = s.converters[ conv ]; + } + } + + current = dataTypes.shift(); + + // Convert to each sequential dataType + while ( current ) { + + if ( s.responseFields[ current ] ) { + jqXHR[ s.responseFields[ current ] ] = response; + } + + // Apply the dataFilter if provided + if ( !prev && isSuccess && s.dataFilter ) { + response = s.dataFilter( response, s.dataType ); + } + + prev = current; + current = dataTypes.shift(); + + if ( current ) { + + // There's only work to do if current dataType is non-auto + if ( current === "*" ) { + + current = prev; + + // Convert response if prev dataType is non-auto and differs from current + } else if ( prev !== "*" && prev !== current ) { + + // Seek a direct converter + conv = converters[ prev + " " + current ] || converters[ "* " + current ]; + + // If none found, seek a pair + if ( !conv ) { + for ( conv2 in converters ) { + + // If conv2 outputs current + tmp = conv2.split( " " ); + if ( tmp[ 1 ] === current ) { + + // If prev can be converted to accepted input + conv = converters[ prev + " " + tmp[ 0 ] ] || + converters[ "* " + tmp[ 0 ] ]; + if ( conv ) { + + // Condense equivalence converters + if ( conv === true ) { + conv = converters[ conv2 ]; + + // Otherwise, insert the intermediate dataType + } else if ( converters[ conv2 ] !== true ) { + current = tmp[ 0 ]; + dataTypes.unshift( tmp[ 1 ] ); + } + break; + } + } + } + } + + // Apply converter (if not an equivalence) + if ( conv !== true ) { + + // Unless errors are allowed to bubble, catch and return them + if ( conv && s.throws ) { + response = conv( response ); + } else { + try { + response = conv( response ); + } catch ( e ) { + return { + state: "parsererror", + error: conv ? e : "No conversion from " + prev + " to " + current + }; + } + } + } + } + } + } + + return { state: "success", data: response }; +} + +jQuery.extend( { + + // Counter for holding the number of active queries + active: 0, + + // Last-Modified header cache for next request + lastModified: {}, + etag: {}, + + ajaxSettings: { + url: location.href, + type: "GET", + isLocal: rlocalProtocol.test( location.protocol ), + global: true, + processData: true, + async: true, + contentType: "application/x-www-form-urlencoded; charset=UTF-8", + + /* + timeout: 0, + data: null, + dataType: null, + username: null, + password: null, + cache: null, + throws: false, + traditional: false, + headers: {}, + */ + + accepts: { + "*": allTypes, + text: "text/plain", + html: "text/html", + xml: "application/xml, text/xml", + json: "application/json, text/javascript" + }, + + contents: { + xml: /\bxml\b/, + html: /\bhtml/, + json: /\bjson\b/ + }, + + responseFields: { + xml: "responseXML", + text: "responseText", + json: "responseJSON" + }, + + // Data converters + // Keys separate source (or catchall "*") and destination types with a single space + converters: { + + // Convert anything to text + "* text": String, + + // Text to html (true = no transformation) + "text html": true, + + // Evaluate text as a json expression + "text json": JSON.parse, + + // Parse text as xml + "text xml": jQuery.parseXML + }, + + // For options that shouldn't be deep extended: + // you can add your own custom options here if + // and when you create one that shouldn't be + // deep extended (see ajaxExtend) + flatOptions: { + url: true, + context: true + } + }, + + // Creates a full fledged settings object into target + // with both ajaxSettings and settings fields. + // If target is omitted, writes into ajaxSettings. + ajaxSetup: function( target, settings ) { + return settings ? + + // Building a settings object + ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) : + + // Extending ajaxSettings + ajaxExtend( jQuery.ajaxSettings, target ); + }, + + ajaxPrefilter: addToPrefiltersOrTransports( prefilters ), + ajaxTransport: addToPrefiltersOrTransports( transports ), + + // Main method + ajax: function( url, options ) { + + // If url is an object, simulate pre-1.5 signature + if ( typeof url === "object" ) { + options = url; + url = undefined; + } + + // Force options to be an object + options = options || {}; + + var transport, + + // URL without anti-cache param + cacheURL, + + // Response headers + responseHeadersString, + responseHeaders, + + // timeout handle + timeoutTimer, + + // Url cleanup var + urlAnchor, + + // Request state (becomes false upon send and true upon completion) + completed, + + // To know if global events are to be dispatched + fireGlobals, + + // Loop variable + i, + + // uncached part of the url + uncached, + + // Create the final options object + s = jQuery.ajaxSetup( {}, options ), + + // Callbacks context + callbackContext = s.context || s, + + // Context for global events is callbackContext if it is a DOM node or jQuery collection + globalEventContext = s.context && + ( callbackContext.nodeType || callbackContext.jquery ) ? + jQuery( callbackContext ) : + jQuery.event, + + // Deferreds + deferred = jQuery.Deferred(), + completeDeferred = jQuery.Callbacks( "once memory" ), + + // Status-dependent callbacks + statusCode = s.statusCode || {}, + + // Headers (they are sent all at once) + requestHeaders = {}, + requestHeadersNames = {}, + + // Default abort message + strAbort = "canceled", + + // Fake xhr + jqXHR = { + readyState: 0, + + // Builds headers hashtable if needed + getResponseHeader: function( key ) { + var match; + if ( completed ) { + if ( !responseHeaders ) { + responseHeaders = {}; + while ( ( match = rheaders.exec( responseHeadersString ) ) ) { + responseHeaders[ match[ 1 ].toLowerCase() ] = match[ 2 ]; + } + } + match = responseHeaders[ key.toLowerCase() ]; + } + return match == null ? null : match; + }, + + // Raw string + getAllResponseHeaders: function() { + return completed ? responseHeadersString : null; + }, + + // Caches the header + setRequestHeader: function( name, value ) { + if ( completed == null ) { + name = requestHeadersNames[ name.toLowerCase() ] = + requestHeadersNames[ name.toLowerCase() ] || name; + requestHeaders[ name ] = value; + } + return this; + }, + + // Overrides response content-type header + overrideMimeType: function( type ) { + if ( completed == null ) { + s.mimeType = type; + } + return this; + }, + + // Status-dependent callbacks + statusCode: function( map ) { + var code; + if ( map ) { + if ( completed ) { + + // Execute the appropriate callbacks + jqXHR.always( map[ jqXHR.status ] ); + } else { + + // Lazy-add the new callbacks in a way that preserves old ones + for ( code in map ) { + statusCode[ code ] = [ statusCode[ code ], map[ code ] ]; + } + } + } + return this; + }, + + // Cancel the request + abort: function( statusText ) { + var finalText = statusText || strAbort; + if ( transport ) { + transport.abort( finalText ); + } + done( 0, finalText ); + return this; + } + }; + + // Attach deferreds + deferred.promise( jqXHR ); + + // Add protocol if not provided (prefilters might expect it) + // Handle falsy url in the settings object (#10093: consistency with old signature) + // We also use the url parameter if available + s.url = ( ( url || s.url || location.href ) + "" ) + .replace( rprotocol, location.protocol + "//" ); + + // Alias method option to type as per ticket #12004 + s.type = options.method || options.type || s.method || s.type; + + // Extract dataTypes list + s.dataTypes = ( s.dataType || "*" ).toLowerCase().match( rnothtmlwhite ) || [ "" ]; + + // A cross-domain request is in order when the origin doesn't match the current origin. + if ( s.crossDomain == null ) { + urlAnchor = document.createElement( "a" ); + + // Support: IE <=8 - 11, Edge 12 - 15 + // IE throws exception on accessing the href property if url is malformed, + // e.g. http://example.com:80x/ + try { + urlAnchor.href = s.url; + + // Support: IE <=8 - 11 only + // Anchor's host property isn't correctly set when s.url is relative + urlAnchor.href = urlAnchor.href; + s.crossDomain = originAnchor.protocol + "//" + originAnchor.host !== + urlAnchor.protocol + "//" + urlAnchor.host; + } catch ( e ) { + + // If there is an error parsing the URL, assume it is crossDomain, + // it can be rejected by the transport if it is invalid + s.crossDomain = true; + } + } + + // Convert data if not already a string + if ( s.data && s.processData && typeof s.data !== "string" ) { + s.data = jQuery.param( s.data, s.traditional ); + } + + // Apply prefilters + inspectPrefiltersOrTransports( prefilters, s, options, jqXHR ); + + // If request was aborted inside a prefilter, stop there + if ( completed ) { + return jqXHR; + } + + // We can fire global events as of now if asked to + // Don't fire events if jQuery.event is undefined in an AMD-usage scenario (#15118) + fireGlobals = jQuery.event && s.global; + + // Watch for a new set of requests + if ( fireGlobals && jQuery.active++ === 0 ) { + jQuery.event.trigger( "ajaxStart" ); + } + + // Uppercase the type + s.type = s.type.toUpperCase(); + + // Determine if request has content + s.hasContent = !rnoContent.test( s.type ); + + // Save the URL in case we're toying with the If-Modified-Since + // and/or If-None-Match header later on + // Remove hash to simplify url manipulation + cacheURL = s.url.replace( rhash, "" ); + + // More options handling for requests with no content + if ( !s.hasContent ) { + + // Remember the hash so we can put it back + uncached = s.url.slice( cacheURL.length ); + + // If data is available and should be processed, append data to url + if ( s.data && ( s.processData || typeof s.data === "string" ) ) { + cacheURL += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data; + + // #9682: remove data so that it's not used in an eventual retry + delete s.data; + } + + // Add or update anti-cache param if needed + if ( s.cache === false ) { + cacheURL = cacheURL.replace( rantiCache, "$1" ); + uncached = ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + ( nonce++ ) + uncached; + } + + // Put hash and anti-cache on the URL that will be requested (gh-1732) + s.url = cacheURL + uncached; + + // Change '%20' to '+' if this is encoded form body content (gh-2658) + } else if ( s.data && s.processData && + ( s.contentType || "" ).indexOf( "application/x-www-form-urlencoded" ) === 0 ) { + s.data = s.data.replace( r20, "+" ); + } + + // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. + if ( s.ifModified ) { + if ( jQuery.lastModified[ cacheURL ] ) { + jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] ); + } + if ( jQuery.etag[ cacheURL ] ) { + jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] ); + } + } + + // Set the correct header, if data is being sent + if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) { + jqXHR.setRequestHeader( "Content-Type", s.contentType ); + } + + // Set the Accepts header for the server, depending on the dataType + jqXHR.setRequestHeader( + "Accept", + s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[ 0 ] ] ? + s.accepts[ s.dataTypes[ 0 ] ] + + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) : + s.accepts[ "*" ] + ); + + // Check for headers option + for ( i in s.headers ) { + jqXHR.setRequestHeader( i, s.headers[ i ] ); + } + + // Allow custom headers/mimetypes and early abort + if ( s.beforeSend && + ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || completed ) ) { + + // Abort if not done already and return + return jqXHR.abort(); + } + + // Aborting is no longer a cancellation + strAbort = "abort"; + + // Install callbacks on deferreds + completeDeferred.add( s.complete ); + jqXHR.done( s.success ); + jqXHR.fail( s.error ); + + // Get transport + transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR ); + + // If no transport, we auto-abort + if ( !transport ) { + done( -1, "No Transport" ); + } else { + jqXHR.readyState = 1; + + // Send global event + if ( fireGlobals ) { + globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] ); + } + + // If request was aborted inside ajaxSend, stop there + if ( completed ) { + return jqXHR; + } + + // Timeout + if ( s.async && s.timeout > 0 ) { + timeoutTimer = window.setTimeout( function() { + jqXHR.abort( "timeout" ); + }, s.timeout ); + } + + try { + completed = false; + transport.send( requestHeaders, done ); + } catch ( e ) { + + // Rethrow post-completion exceptions + if ( completed ) { + throw e; + } + + // Propagate others as results + done( -1, e ); + } + } + + // Callback for when everything is done + function done( status, nativeStatusText, responses, headers ) { + var isSuccess, success, error, response, modified, + statusText = nativeStatusText; + + // Ignore repeat invocations + if ( completed ) { + return; + } + + completed = true; + + // Clear timeout if it exists + if ( timeoutTimer ) { + window.clearTimeout( timeoutTimer ); + } + + // Dereference transport for early garbage collection + // (no matter how long the jqXHR object will be used) + transport = undefined; + + // Cache response headers + responseHeadersString = headers || ""; + + // Set readyState + jqXHR.readyState = status > 0 ? 4 : 0; + + // Determine if successful + isSuccess = status >= 200 && status < 300 || status === 304; + + // Get response data + if ( responses ) { + response = ajaxHandleResponses( s, jqXHR, responses ); + } + + // Convert no matter what (that way responseXXX fields are always set) + response = ajaxConvert( s, response, jqXHR, isSuccess ); + + // If successful, handle type chaining + if ( isSuccess ) { + + // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. + if ( s.ifModified ) { + modified = jqXHR.getResponseHeader( "Last-Modified" ); + if ( modified ) { + jQuery.lastModified[ cacheURL ] = modified; + } + modified = jqXHR.getResponseHeader( "etag" ); + if ( modified ) { + jQuery.etag[ cacheURL ] = modified; + } + } + + // if no content + if ( status === 204 || s.type === "HEAD" ) { + statusText = "nocontent"; + + // if not modified + } else if ( status === 304 ) { + statusText = "notmodified"; + + // If we have data, let's convert it + } else { + statusText = response.state; + success = response.data; + error = response.error; + isSuccess = !error; + } + } else { + + // Extract error from statusText and normalize for non-aborts + error = statusText; + if ( status || !statusText ) { + statusText = "error"; + if ( status < 0 ) { + status = 0; + } + } + } + + // Set data for the fake xhr object + jqXHR.status = status; + jqXHR.statusText = ( nativeStatusText || statusText ) + ""; + + // Success/Error + if ( isSuccess ) { + deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] ); + } else { + deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] ); + } + + // Status-dependent callbacks + jqXHR.statusCode( statusCode ); + statusCode = undefined; + + if ( fireGlobals ) { + globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError", + [ jqXHR, s, isSuccess ? success : error ] ); + } + + // Complete + completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] ); + + if ( fireGlobals ) { + globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] ); + + // Handle the global AJAX counter + if ( !( --jQuery.active ) ) { + jQuery.event.trigger( "ajaxStop" ); + } + } + } + + return jqXHR; + }, + + getJSON: function( url, data, callback ) { + return jQuery.get( url, data, callback, "json" ); + }, + + getScript: function( url, callback ) { + return jQuery.get( url, undefined, callback, "script" ); + } +} ); + +jQuery.each( [ "get", "post" ], function( i, method ) { + jQuery[ method ] = function( url, data, callback, type ) { + + // Shift arguments if data argument was omitted + if ( isFunction( data ) ) { + type = type || callback; + callback = data; + data = undefined; + } + + // The url can be an options object (which then must have .url) + return jQuery.ajax( jQuery.extend( { + url: url, + type: method, + dataType: type, + data: data, + success: callback + }, jQuery.isPlainObject( url ) && url ) ); + }; +} ); + + +jQuery._evalUrl = function( url ) { + return jQuery.ajax( { + url: url, + + // Make this explicit, since user can override this through ajaxSetup (#11264) + type: "GET", + dataType: "script", + cache: true, + async: false, + global: false, + "throws": true + } ); +}; + + +jQuery.fn.extend( { + wrapAll: function( html ) { + var wrap; + + if ( this[ 0 ] ) { + if ( isFunction( html ) ) { + html = html.call( this[ 0 ] ); + } + + // The elements to wrap the target around + wrap = jQuery( html, this[ 0 ].ownerDocument ).eq( 0 ).clone( true ); + + if ( this[ 0 ].parentNode ) { + wrap.insertBefore( this[ 0 ] ); + } + + wrap.map( function() { + var elem = this; + + while ( elem.firstElementChild ) { + elem = elem.firstElementChild; + } + + return elem; + } ).append( this ); + } + + return this; + }, + + wrapInner: function( html ) { + if ( isFunction( html ) ) { + return this.each( function( i ) { + jQuery( this ).wrapInner( html.call( this, i ) ); + } ); + } + + return this.each( function() { + var self = jQuery( this ), + contents = self.contents(); + + if ( contents.length ) { + contents.wrapAll( html ); + + } else { + self.append( html ); + } + } ); + }, + + wrap: function( html ) { + var htmlIsFunction = isFunction( html ); + + return this.each( function( i ) { + jQuery( this ).wrapAll( htmlIsFunction ? html.call( this, i ) : html ); + } ); + }, + + unwrap: function( selector ) { + this.parent( selector ).not( "body" ).each( function() { + jQuery( this ).replaceWith( this.childNodes ); + } ); + return this; + } +} ); + + +jQuery.expr.pseudos.hidden = function( elem ) { + return !jQuery.expr.pseudos.visible( elem ); +}; +jQuery.expr.pseudos.visible = function( elem ) { + return !!( elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length ); +}; + + + + +jQuery.ajaxSettings.xhr = function() { + try { + return new window.XMLHttpRequest(); + } catch ( e ) {} +}; + +var xhrSuccessStatus = { + + // File protocol always yields status code 0, assume 200 + 0: 200, + + // Support: IE <=9 only + // #1450: sometimes IE returns 1223 when it should be 204 + 1223: 204 + }, + xhrSupported = jQuery.ajaxSettings.xhr(); + +support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported ); +support.ajax = xhrSupported = !!xhrSupported; + +jQuery.ajaxTransport( function( options ) { + var callback, errorCallback; + + // Cross domain only allowed if supported through XMLHttpRequest + if ( support.cors || xhrSupported && !options.crossDomain ) { + return { + send: function( headers, complete ) { + var i, + xhr = options.xhr(); + + xhr.open( + options.type, + options.url, + options.async, + options.username, + options.password + ); + + // Apply custom fields if provided + if ( options.xhrFields ) { + for ( i in options.xhrFields ) { + xhr[ i ] = options.xhrFields[ i ]; + } + } + + // Override mime type if needed + if ( options.mimeType && xhr.overrideMimeType ) { + xhr.overrideMimeType( options.mimeType ); + } + + // X-Requested-With header + // For cross-domain requests, seeing as conditions for a preflight are + // akin to a jigsaw puzzle, we simply never set it to be sure. + // (it can always be set on a per-request basis or even using ajaxSetup) + // For same-domain requests, won't change header if already provided. + if ( !options.crossDomain && !headers[ "X-Requested-With" ] ) { + headers[ "X-Requested-With" ] = "XMLHttpRequest"; + } + + // Set headers + for ( i in headers ) { + xhr.setRequestHeader( i, headers[ i ] ); + } + + // Callback + callback = function( type ) { + return function() { + if ( callback ) { + callback = errorCallback = xhr.onload = + xhr.onerror = xhr.onabort = xhr.ontimeout = + xhr.onreadystatechange = null; + + if ( type === "abort" ) { + xhr.abort(); + } else if ( type === "error" ) { + + // Support: IE <=9 only + // On a manual native abort, IE9 throws + // errors on any property access that is not readyState + if ( typeof xhr.status !== "number" ) { + complete( 0, "error" ); + } else { + complete( + + // File: protocol always yields status 0; see #8605, #14207 + xhr.status, + xhr.statusText + ); + } + } else { + complete( + xhrSuccessStatus[ xhr.status ] || xhr.status, + xhr.statusText, + + // Support: IE <=9 only + // IE9 has no XHR2 but throws on binary (trac-11426) + // For XHR2 non-text, let the caller handle it (gh-2498) + ( xhr.responseType || "text" ) !== "text" || + typeof xhr.responseText !== "string" ? + { binary: xhr.response } : + { text: xhr.responseText }, + xhr.getAllResponseHeaders() + ); + } + } + }; + }; + + // Listen to events + xhr.onload = callback(); + errorCallback = xhr.onerror = xhr.ontimeout = callback( "error" ); + + // Support: IE 9 only + // Use onreadystatechange to replace onabort + // to handle uncaught aborts + if ( xhr.onabort !== undefined ) { + xhr.onabort = errorCallback; + } else { + xhr.onreadystatechange = function() { + + // Check readyState before timeout as it changes + if ( xhr.readyState === 4 ) { + + // Allow onerror to be called first, + // but that will not handle a native abort + // Also, save errorCallback to a variable + // as xhr.onerror cannot be accessed + window.setTimeout( function() { + if ( callback ) { + errorCallback(); + } + } ); + } + }; + } + + // Create the abort callback + callback = callback( "abort" ); + + try { + + // Do send the request (this may raise an exception) + xhr.send( options.hasContent && options.data || null ); + } catch ( e ) { + + // #14683: Only rethrow if this hasn't been notified as an error yet + if ( callback ) { + throw e; + } + } + }, + + abort: function() { + if ( callback ) { + callback(); + } + } + }; + } +} ); + + + + +// Prevent auto-execution of scripts when no explicit dataType was provided (See gh-2432) +jQuery.ajaxPrefilter( function( s ) { + if ( s.crossDomain ) { + s.contents.script = false; + } +} ); + +// Install script dataType +jQuery.ajaxSetup( { + accepts: { + script: "text/javascript, application/javascript, " + + "application/ecmascript, application/x-ecmascript" + }, + contents: { + script: /\b(?:java|ecma)script\b/ + }, + converters: { + "text script": function( text ) { + jQuery.globalEval( text ); + return text; + } + } +} ); + +// Handle cache's special case and crossDomain +jQuery.ajaxPrefilter( "script", function( s ) { + if ( s.cache === undefined ) { + s.cache = false; + } + if ( s.crossDomain ) { + s.type = "GET"; + } +} ); + +// Bind script tag hack transport +jQuery.ajaxTransport( "script", function( s ) { + + // This transport only deals with cross domain requests + if ( s.crossDomain ) { + var script, callback; + return { + send: function( _, complete ) { + script = jQuery( "