break up script into 4 smaller refactor scripts preparing it to be ported to modular library leveraing vuejs
21
vue/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
.DS_Store
|
||||||
|
node_modules
|
||||||
|
/dist
|
||||||
|
|
||||||
|
# local env files
|
||||||
|
.env.local
|
||||||
|
.env.*.local
|
||||||
|
|
||||||
|
# Log files
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
|
||||||
|
# Editor directories and files
|
||||||
|
.idea
|
||||||
|
.vscode
|
||||||
|
*.suo
|
||||||
|
*.ntvs*
|
||||||
|
*.njsproj
|
||||||
|
*.sln
|
||||||
|
*.sw*
|
||||||
20
vue/README.md
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
# VUE
|
||||||
|
|
||||||
|
We are using are VueJS as a build tool to help create a modular version of the Fantasy Map Generator so that individual contributors can work with more manageable files.
|
||||||
|
|
||||||
|
## Goal
|
||||||
|
|
||||||
|
We could divide and conquer in steps.
|
||||||
|
|
||||||
|
* Quarter the codebase - take the 10K line codebase and create 4 script files containing 2.5K each
|
||||||
|
* repeat with each 2.5K file so that we're down to many 500 line or less files - about 16 files
|
||||||
|
* Create 1 main component which imports in all these functions.
|
||||||
|
|
||||||
|
Run the project and it should appear exactly like the 10K original script file except everything is modularized.
|
||||||
|
Once the codebase is divided into folders and sub folders and we're now leveraging import/export pattern to rebuild the main component by importing all the functions.
|
||||||
|
|
||||||
|
Then we could begin looking a candidates for other components such the editor overlay and also begin refactoring and modernizing the code to es6/7 standards.
|
||||||
|
|
||||||
|
## Tests
|
||||||
|
|
||||||
|
We need to figure out how to run the tests.
|
||||||
5
vue/babel.config.js
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
module.exports = {
|
||||||
|
presets: [
|
||||||
|
'@vue/app'
|
||||||
|
]
|
||||||
|
}
|
||||||
43
vue/package.json
Normal file
|
|
@ -0,0 +1,43 @@
|
||||||
|
{
|
||||||
|
"name": "vue",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"private": true,
|
||||||
|
"scripts": {
|
||||||
|
"serve": "vue-cli-service serve",
|
||||||
|
"build": "vue-cli-service build",
|
||||||
|
"lint": "vue-cli-service lint"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"vue": "^2.5.17"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@vue/cli-plugin-babel": "^3.0.1",
|
||||||
|
"@vue/cli-plugin-eslint": "^3.0.1",
|
||||||
|
"@vue/cli-service": "^3.0.1",
|
||||||
|
"vue-template-compiler": "^2.5.17"
|
||||||
|
},
|
||||||
|
"eslintConfig": {
|
||||||
|
"root": true,
|
||||||
|
"env": {
|
||||||
|
"node": true
|
||||||
|
},
|
||||||
|
"extends": [
|
||||||
|
"plugin:vue/essential",
|
||||||
|
"eslint:recommended"
|
||||||
|
],
|
||||||
|
"rules": {},
|
||||||
|
"parserOptions": {
|
||||||
|
"parser": "babel-eslint"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"postcss": {
|
||||||
|
"plugins": {
|
||||||
|
"autoprefixer": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"browserslist": [
|
||||||
|
"> 1%",
|
||||||
|
"last 2 versions",
|
||||||
|
"not ie <= 8"
|
||||||
|
]
|
||||||
|
}
|
||||||
BIN
vue/public/favicon.ico
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
175
vue/public/fonts.css
Normal file
|
|
@ -0,0 +1,175 @@
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Amatic SC';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 700;
|
||||||
|
src: local('Amatic SC Bold'), local('AmaticSC-Bold'), url(https://fonts.gstatic.com/s/amaticsc/v11/TUZ3zwprpvBS1izr_vOMscGKfrUC.woff2) format('woff2');
|
||||||
|
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Architects Daughter';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 400;
|
||||||
|
src: local('Architects Daughter Regular'), local('ArchitectsDaughter-Regular'), url(https://fonts.gstatic.com/s/architectsdaughter/v8/RXTgOOQ9AAtaVOHxx0IUBM3t7GjCYufj5TXV5VnA2p8.woff2) format('woff2');
|
||||||
|
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215;
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Bitter';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 400;
|
||||||
|
src: local('Bitter Regular'), local('Bitter-Regular'), url(https://fonts.gstatic.com/s/bitter/v12/zfs6I-5mjWQ3nxqccMoL2A.woff2) format('woff2');
|
||||||
|
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215;
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Caesar Dressing';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 400;
|
||||||
|
src: local('Caesar Dressing'), local('CaesarDressing-Regular'), url(https://fonts.gstatic.com/s/caesardressing/v6/yYLx0hLa3vawqtwdswbotmK4vrRHdrz7.woff2) format('woff2');
|
||||||
|
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Cinzel';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 400;
|
||||||
|
src: local('Cinzel Regular'), local('Cinzel-Regular'), url(https://fonts.gstatic.com/s/cinzel/v7/zOdksD_UUTk1LJF9z4tURA.woff2) format('woff2');
|
||||||
|
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215;
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Comfortaa';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 700;
|
||||||
|
src: local('Comfortaa Bold'), local('Comfortaa-Bold'), url(https://fonts.gstatic.com/s/comfortaa/v12/fND5XPYKrF2tQDwwfWZJI-gdm0LZdjqr5-oayXSOefg.woff2) format('woff2');
|
||||||
|
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215;
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Dancing Script';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 700;
|
||||||
|
src: local('Dancing Script Bold'), local('DancingScript-Bold'), url(https://fonts.gstatic.com/s/dancingscript/v9/KGBfwabt0ZRLA5W1ywjowUHdOuSHeh0r6jGTOGdAKHA.woff2) format('woff2');
|
||||||
|
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215;
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Fredericka the Great';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 400;
|
||||||
|
src: local('Fredericka the Great'), local('FrederickatheGreat'), url(https://fonts.gstatic.com/s/frederickathegreat/v6/9Bt33CxNwt7aOctW2xjbCstzwVKsIBVV--Sjxbc.woff2) format('woff2');
|
||||||
|
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Gloria Hallelujah';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 400;
|
||||||
|
src: local('Gloria Hallelujah'), local('GloriaHallelujah'), url(https://fonts.gstatic.com/s/gloriahallelujah/v9/CA1k7SlXcY5kvI81M_R28cNDay8z-hHR7F16xrcXsJw.woff2) format('woff2');
|
||||||
|
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215;
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Great Vibes';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 400;
|
||||||
|
src: local('Great Vibes'), local('GreatVibes-Regular'), url(https://fonts.gstatic.com/s/greatvibes/v5/6q1c0ofG6NKsEhAc2eh-3Y4P5ICox8Kq3LLUNMylGO4.woff2) format('woff2');
|
||||||
|
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215;
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: 'IM Fell English';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 400;
|
||||||
|
src: local('IM FELL English Roman'), local('IM_FELL_English_Roman'), url(https://fonts.gstatic.com/s/imfellenglish/v7/xwIisCqGFi8pff-oa9uSVAkYLEKE0CJQa8tfZYc_plY.woff2) format('woff2');
|
||||||
|
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215;
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Kaushan Script';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 400;
|
||||||
|
src: local('Kaushan Script'), local('KaushanScript-Regular'), url(https://fonts.gstatic.com/s/kaushanscript/v6/qx1LSqts-NtiKcLw4N03IEd0sm1ffa_JvZxsF_BEwQk.woff2) format('woff2');
|
||||||
|
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215;
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: 'MedievalSharp';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 400;
|
||||||
|
src: local('MedievalSharp'), url(https://fonts.gstatic.com/s/medievalsharp/v9/EvOJzAlL3oU5AQl2mP5KdgptMqhwMg.woff2) format('woff2');
|
||||||
|
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Metamorphous';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 400;
|
||||||
|
src: local('Metamorphous'), url(https://fonts.gstatic.com/s/metamorphous/v7/Wnz8HA03aAXcC39ZEX5y133EOyqs.woff2) format('woff2');
|
||||||
|
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Montez';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 400;
|
||||||
|
src: local('Montez Regular'), local('Montez-Regular'), url(https://fonts.gstatic.com/s/montez/v8/aq8el3-0osHIcFK6bXAPkw.woff2) format('woff2');
|
||||||
|
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215;
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Nova Script';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 400;
|
||||||
|
src: local('Nova Script Regular'), local('NovaScript-Regular'), url(https://fonts.gstatic.com/s/novascript/v10/7Au7p_IpkSWSTWaFWkumvlQKGFw.woff2) format('woff2');
|
||||||
|
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Orbitron';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 400;
|
||||||
|
src: local('Orbitron Regular'), local('Orbitron-Regular'), url(https://fonts.gstatic.com/s/orbitron/v9/HmnHiRzvcnQr8CjBje6GQvesZW2xOQ-xsNqO47m55DA.woff2) format('woff2');
|
||||||
|
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215;
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Satisfy';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 400;
|
||||||
|
src: local('Satisfy Regular'), local('Satisfy-Regular'), url(https://fonts.gstatic.com/s/satisfy/v8/2OzALGYfHwQjkPYWELy-cw.woff2) format('woff2');
|
||||||
|
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215;
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Shadows Into Light';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 400;
|
||||||
|
src: local('Shadows Into Light'), local('ShadowsIntoLight'), url(https://fonts.gstatic.com/s/shadowsintolight/v7/clhLqOv7MXn459PTh0gXYFK2TSYBz0eNcHnp4YqE4Ts.woff2) format('woff2');
|
||||||
|
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215;
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Uncial Antiqua';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 400;
|
||||||
|
src: local('Uncial Antiqua'), local('UncialAntiqua-Regular'), url(https://fonts.gstatic.com/s/uncialantiqua/v5/N0bM2S5WOex4OUbESzoESK-i-MfWQZQ.woff2) format('woff2');
|
||||||
|
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Underdog';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 400;
|
||||||
|
src: local('Underdog'), local('Underdog-Regular'), url(https://fonts.gstatic.com/s/underdog/v6/CHygV-jCElj7diMroWSlWV8.woff2) format('woff2');
|
||||||
|
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Yellowtail';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 400;
|
||||||
|
src: local('Yellowtail Regular'), local('Yellowtail-Regular'), url(https://fonts.gstatic.com/s/yellowtail/v8/GcIHC9QEwVkrA19LJU1qlPk_vArhqVIZ0nv9q090hN8.woff2) format('woff2');
|
||||||
|
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215;
|
||||||
|
}
|
||||||
212
vue/public/icons.css
Normal file
BIN
vue/public/images/Facebook.png
Normal file
|
After Width: | Height: | Size: 318 B |
BIN
vue/public/images/Pinterest.png
Normal file
|
After Width: | Height: | Size: 443 B |
BIN
vue/public/images/Reddit.png
Normal file
|
After Width: | Height: | Size: 509 B |
BIN
vue/public/images/Tumblr.png
Normal file
|
After Width: | Height: | Size: 310 B |
BIN
vue/public/images/Twitter.png
Normal file
|
After Width: | Height: | Size: 379 B |
BIN
vue/public/images/favicon-16x16.png
Normal file
|
After Width: | Height: | Size: 740 B |
BIN
vue/public/images/favicon-32x32.png
Normal file
|
After Width: | Height: | Size: 2.2 KiB |
BIN
vue/public/images/preview.png
Normal file
|
After Width: | Height: | Size: 88 KiB |
1427
vue/public/index.css
Normal file
1307
vue/public/index.html
Normal file
20
vue/public/index_vue.html
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
|
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
||||||
|
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
|
||||||
|
<title>vue</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<noscript>
|
||||||
|
<strong>We're sorry but vue doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
|
||||||
|
</noscript>
|
||||||
|
<div id="app"></div>
|
||||||
|
<!-- built files will be auto injected -->
|
||||||
|
|
||||||
|
<script src="four"></script>
|
||||||
|
<script src="main"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
2
vue/public/libs/d3-scale-chromatic.v1.min.js
vendored
Normal file
2
vue/public/libs/d3.v4.min.js
vendored
Normal file
4
vue/public/libs/jquery-3.1.1.min.js
vendored
Normal file
558
vue/public/libs/jquery-ui.css
vendored
Normal file
|
|
@ -0,0 +1,558 @@
|
||||||
|
/*! jQuery UI - v1.12.1 - 2018-08-15 http://jqueryui.com
|
||||||
|
* Includes: draggable.css, core.css, resizable.css, sortable.css, button.css, controlgroup.css, checkboxradio.css, dialog.css, theme.css
|
||||||
|
* Copyright jQuery Foundation and other contributors; Licensed MIT */
|
||||||
|
|
||||||
|
.ui-draggable-handle {
|
||||||
|
-ms-touch-action: none;
|
||||||
|
touch-action: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui-helper-hidden {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.ui-helper-hidden-accessible {
|
||||||
|
border: 0;
|
||||||
|
clip: rect(0 0 0 0);
|
||||||
|
height: 1px;
|
||||||
|
margin: -1px;
|
||||||
|
overflow: hidden;
|
||||||
|
padding: 0;
|
||||||
|
position: absolute;
|
||||||
|
width: 1px;
|
||||||
|
}
|
||||||
|
.ui-helper-reset {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
border: 0;
|
||||||
|
outline: 0;
|
||||||
|
line-height: 1.3;
|
||||||
|
text-decoration: none;
|
||||||
|
font-size: 100%;
|
||||||
|
list-style: none;
|
||||||
|
}
|
||||||
|
.ui-helper-clearfix:before,
|
||||||
|
.ui-helper-clearfix:after {
|
||||||
|
content: "";
|
||||||
|
display: table;
|
||||||
|
border-collapse: collapse;
|
||||||
|
}
|
||||||
|
.ui-helper-clearfix:after {
|
||||||
|
clear: both;
|
||||||
|
}
|
||||||
|
.ui-helper-zfix {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
position: absolute;
|
||||||
|
opacity: 0;
|
||||||
|
filter:Alpha(Opacity=0); /* support: IE8 */
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui-front {
|
||||||
|
z-index: 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Interaction Cues
|
||||||
|
----------------------------------*/
|
||||||
|
.ui-state-disabled {
|
||||||
|
cursor: default !important;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Icons
|
||||||
|
----------------------------------*/
|
||||||
|
.ui-icon {
|
||||||
|
display: inline-block;
|
||||||
|
vertical-align: middle;
|
||||||
|
margin-top: -.25em;
|
||||||
|
position: relative;
|
||||||
|
text-indent: -99999px;
|
||||||
|
overflow: hidden;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui-widget-icon-block {
|
||||||
|
left: 50%;
|
||||||
|
margin-left: -8px;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Misc visuals
|
||||||
|
----------------------------------*/
|
||||||
|
|
||||||
|
/* Overlays */
|
||||||
|
.ui-widget-overlay {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
.ui-resizable {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
.ui-resizable-handle {
|
||||||
|
position: absolute;
|
||||||
|
font-size: 0.1px;
|
||||||
|
display: block;
|
||||||
|
-ms-touch-action: none;
|
||||||
|
touch-action: none;
|
||||||
|
}
|
||||||
|
.ui-resizable-disabled .ui-resizable-handle,
|
||||||
|
.ui-resizable-autohide .ui-resizable-handle {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.ui-resizable-n {
|
||||||
|
cursor: n-resize;
|
||||||
|
height: 7px;
|
||||||
|
width: 100%;
|
||||||
|
top: -5px;
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
.ui-resizable-s {
|
||||||
|
cursor: s-resize;
|
||||||
|
height: 7px;
|
||||||
|
width: 100%;
|
||||||
|
bottom: -5px;
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
.ui-resizable-e {
|
||||||
|
cursor: e-resize;
|
||||||
|
width: 7px;
|
||||||
|
right: -5px;
|
||||||
|
top: 0;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
.ui-resizable-w {
|
||||||
|
cursor: w-resize;
|
||||||
|
width: 7px;
|
||||||
|
left: -5px;
|
||||||
|
top: 0;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
.ui-resizable-se {
|
||||||
|
cursor: se-resize;
|
||||||
|
width: 12px;
|
||||||
|
height: 12px;
|
||||||
|
right: 1px;
|
||||||
|
bottom: 1px;
|
||||||
|
}
|
||||||
|
.ui-resizable-sw {
|
||||||
|
cursor: sw-resize;
|
||||||
|
width: 9px;
|
||||||
|
height: 9px;
|
||||||
|
left: -5px;
|
||||||
|
bottom: -5px;
|
||||||
|
}
|
||||||
|
.ui-resizable-nw {
|
||||||
|
cursor: nw-resize;
|
||||||
|
width: 9px;
|
||||||
|
height: 9px;
|
||||||
|
left: -5px;
|
||||||
|
top: -5px;
|
||||||
|
}
|
||||||
|
.ui-resizable-ne {
|
||||||
|
cursor: ne-resize;
|
||||||
|
width: 9px;
|
||||||
|
height: 9px;
|
||||||
|
right: -5px;
|
||||||
|
top: -5px;
|
||||||
|
}
|
||||||
|
.ui-sortable-handle {
|
||||||
|
-ms-touch-action: none;
|
||||||
|
touch-action: none;
|
||||||
|
}
|
||||||
|
.ui-button {
|
||||||
|
padding: .4em 1em;
|
||||||
|
display: inline-block;
|
||||||
|
position: relative;
|
||||||
|
line-height: normal;
|
||||||
|
margin-right: .1em;
|
||||||
|
cursor: pointer;
|
||||||
|
vertical-align: middle;
|
||||||
|
text-align: center;
|
||||||
|
-webkit-user-select: none;
|
||||||
|
-moz-user-select: none;
|
||||||
|
-ms-user-select: none;
|
||||||
|
user-select: none;
|
||||||
|
|
||||||
|
/* Support: IE <= 11 */
|
||||||
|
overflow: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui-button,
|
||||||
|
.ui-button:link,
|
||||||
|
.ui-button:visited,
|
||||||
|
.ui-button:hover,
|
||||||
|
.ui-button:active {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* to make room for the icon, a width needs to be set here */
|
||||||
|
.ui-button-icon-only {
|
||||||
|
width: 2em;
|
||||||
|
box-sizing: border-box;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* button icon element(s) */
|
||||||
|
.ui-button-icon-only .ui-icon {
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
margin-top: -8px;
|
||||||
|
margin-left: -8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui-button.ui-icon-notext .ui-icon {
|
||||||
|
padding: 0;
|
||||||
|
width: 2.1em;
|
||||||
|
height: 2.1em;
|
||||||
|
text-indent: -9999px;
|
||||||
|
white-space: nowrap;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
input.ui-button.ui-icon-notext .ui-icon {
|
||||||
|
width: auto;
|
||||||
|
height: auto;
|
||||||
|
text-indent: 0;
|
||||||
|
white-space: normal;
|
||||||
|
padding: .4em 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* workarounds */
|
||||||
|
/* Support: Firefox 5 - 40 */
|
||||||
|
input.ui-button::-moz-focus-inner,
|
||||||
|
button.ui-button::-moz-focus-inner {
|
||||||
|
border: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
.ui-controlgroup {
|
||||||
|
vertical-align: middle;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
.ui-controlgroup > .ui-controlgroup-item {
|
||||||
|
float: left;
|
||||||
|
margin-left: 0;
|
||||||
|
margin-right: 0;
|
||||||
|
}
|
||||||
|
.ui-controlgroup > .ui-controlgroup-item:focus,
|
||||||
|
.ui-controlgroup > .ui-controlgroup-item.ui-visual-focus {
|
||||||
|
z-index: 9999;
|
||||||
|
}
|
||||||
|
.ui-controlgroup-vertical > .ui-controlgroup-item {
|
||||||
|
display: block;
|
||||||
|
float: none;
|
||||||
|
width: 100%;
|
||||||
|
margin-top: 0;
|
||||||
|
margin-bottom: 0;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
.ui-controlgroup-vertical .ui-controlgroup-item {
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
.ui-controlgroup .ui-controlgroup-label {
|
||||||
|
padding: .4em 1em;
|
||||||
|
}
|
||||||
|
.ui-controlgroup .ui-controlgroup-label span {
|
||||||
|
font-size: 80%;
|
||||||
|
}
|
||||||
|
.ui-controlgroup-horizontal .ui-controlgroup-label + .ui-controlgroup-item {
|
||||||
|
border-left: none;
|
||||||
|
}
|
||||||
|
.ui-controlgroup-vertical .ui-controlgroup-label + .ui-controlgroup-item {
|
||||||
|
border-top: none;
|
||||||
|
}
|
||||||
|
.ui-controlgroup-horizontal .ui-controlgroup-label.ui-widget-content {
|
||||||
|
border-right: none;
|
||||||
|
}
|
||||||
|
.ui-controlgroup-vertical .ui-controlgroup-label.ui-widget-content {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Spinner specific style fixes */
|
||||||
|
.ui-controlgroup-vertical .ui-spinner-input {
|
||||||
|
|
||||||
|
/* Support: IE8 only, Android < 4.4 only */
|
||||||
|
width: 75%;
|
||||||
|
width: calc( 100% - 2.4em );
|
||||||
|
}
|
||||||
|
.ui-controlgroup-vertical .ui-spinner .ui-spinner-up {
|
||||||
|
border-top-style: solid;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui-checkboxradio-label .ui-icon-background {
|
||||||
|
box-shadow: inset 1px 1px 1px #ccc;
|
||||||
|
border-radius: .12em;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
.ui-checkboxradio-radio-label .ui-icon-background {
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
border-radius: 1em;
|
||||||
|
overflow: visible;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
.ui-checkboxradio-radio-label.ui-checkboxradio-checked .ui-icon,
|
||||||
|
.ui-checkboxradio-radio-label.ui-checkboxradio-checked:hover .ui-icon {
|
||||||
|
background-image: none;
|
||||||
|
width: 8px;
|
||||||
|
height: 8px;
|
||||||
|
border-width: 4px;
|
||||||
|
border-style: solid;
|
||||||
|
}
|
||||||
|
.ui-checkboxradio-disabled {
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
body .ui-dialog {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
outline: 0;
|
||||||
|
padding: 0;
|
||||||
|
font-size: 12px;
|
||||||
|
background-color: inherit;
|
||||||
|
}
|
||||||
|
.ui-dialog .ui-dialog-titlebar {
|
||||||
|
padding: .4em 1em;
|
||||||
|
position: relative;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
.ui-dialog .ui-dialog-title {
|
||||||
|
float: left;
|
||||||
|
margin: .1em 0;
|
||||||
|
white-space: nowrap;
|
||||||
|
width: 90%;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
.ui-dialog .ui-dialog-titlebar-close {
|
||||||
|
position: absolute;
|
||||||
|
right: .5em;
|
||||||
|
top: 53%;
|
||||||
|
width: 18px;
|
||||||
|
margin: -10px 0 0 0;
|
||||||
|
padding: 0;
|
||||||
|
height: 18px;
|
||||||
|
color: #ffffff;
|
||||||
|
background: none;
|
||||||
|
font-size: 10px;
|
||||||
|
}
|
||||||
|
.ui-dialog .ui-dialog-content {
|
||||||
|
position: relative;
|
||||||
|
border: 0;
|
||||||
|
padding: .5em 1em;
|
||||||
|
background: none;
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
.ui-dialog .ui-dialog-buttonpane {
|
||||||
|
text-align: left;
|
||||||
|
border-width: 1px 0 0 0;
|
||||||
|
background-image: none;
|
||||||
|
margin-top: .5em;
|
||||||
|
padding: .3em 1em .5em .4em;
|
||||||
|
}
|
||||||
|
.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
.ui-dialog .ui-dialog-buttonpane button {
|
||||||
|
margin: .5em .4em .5em 0;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.ui-dialog .ui-resizable-n {
|
||||||
|
height: 2px;
|
||||||
|
top: 0;
|
||||||
|
}
|
||||||
|
.ui-dialog .ui-resizable-e {
|
||||||
|
width: 2px;
|
||||||
|
right: 0;
|
||||||
|
}
|
||||||
|
.ui-dialog .ui-resizable-s {
|
||||||
|
height: 2px;
|
||||||
|
bottom: 0;
|
||||||
|
}
|
||||||
|
.ui-dialog .ui-resizable-w {
|
||||||
|
width: 2px;
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
.ui-dialog .ui-resizable-se,
|
||||||
|
.ui-dialog .ui-resizable-sw,
|
||||||
|
.ui-dialog .ui-resizable-ne,
|
||||||
|
.ui-dialog .ui-resizable-nw {
|
||||||
|
width: 7px;
|
||||||
|
height: 7px;
|
||||||
|
}
|
||||||
|
.ui-dialog .ui-resizable-se {
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
}
|
||||||
|
.ui-dialog .ui-resizable-sw {
|
||||||
|
left: 0;
|
||||||
|
bottom: 0;
|
||||||
|
}
|
||||||
|
.ui-dialog .ui-resizable-ne {
|
||||||
|
right: 0;
|
||||||
|
top: 0;
|
||||||
|
}
|
||||||
|
.ui-dialog .ui-resizable-nw {
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
}
|
||||||
|
.ui-draggable .ui-dialog-titlebar {
|
||||||
|
cursor: move;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Component containers
|
||||||
|
----------------------------------*/
|
||||||
|
.ui-widget {
|
||||||
|
font-family: Arial,Helvetica,sans-serif;
|
||||||
|
}
|
||||||
|
.ui-widget input,
|
||||||
|
.ui-widget select,
|
||||||
|
.ui-widget textarea,
|
||||||
|
.ui-widget button {
|
||||||
|
font-family: Arial,Helvetica,sans-serif;
|
||||||
|
font-size: 1em;
|
||||||
|
}
|
||||||
|
.ui-widget.ui-widget-content {
|
||||||
|
border: 1px solid #5e4fa2;
|
||||||
|
color: #333333;
|
||||||
|
}
|
||||||
|
.ui-widget-content {
|
||||||
|
border: 1px solid #dddddd;
|
||||||
|
color: #333333;
|
||||||
|
}
|
||||||
|
.ui-widget-content a {
|
||||||
|
color: #333333;
|
||||||
|
}
|
||||||
|
.ui-widget-header {
|
||||||
|
border-bottom: 1px solid #5d4651;
|
||||||
|
background: #916e7f;
|
||||||
|
color: #ffffff;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
.ui-widget-header a {
|
||||||
|
color: #333333;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Interaction states
|
||||||
|
----------------------------------*/
|
||||||
|
.ui-state-default,
|
||||||
|
.ui-widget-content .ui-state-default,
|
||||||
|
.ui-widget-header .ui-state-default,
|
||||||
|
.ui-button,
|
||||||
|
|
||||||
|
/* We use html here because we need a greater specificity to make sure disabled
|
||||||
|
works properly when clicked or hovered */
|
||||||
|
html .ui-button.ui-state-disabled:hover,
|
||||||
|
html .ui-button.ui-state-disabled:active {
|
||||||
|
border: 1px solid #c5c5c5;
|
||||||
|
background: #f6f6f6;
|
||||||
|
font-weight: normal;
|
||||||
|
color: #454545;
|
||||||
|
}
|
||||||
|
.ui-state-default a,
|
||||||
|
.ui-state-default a:link,
|
||||||
|
.ui-state-default a:visited,
|
||||||
|
a.ui-button,
|
||||||
|
a:link.ui-button,
|
||||||
|
a:visited.ui-button,
|
||||||
|
.ui-button {
|
||||||
|
color: #454545;
|
||||||
|
}
|
||||||
|
.ui-button:active {
|
||||||
|
color: #5d4651;
|
||||||
|
border-color: #5d4651;
|
||||||
|
}
|
||||||
|
.ui-state-hover a,
|
||||||
|
.ui-state-hover a:hover,
|
||||||
|
.ui-state-hover a:link,
|
||||||
|
.ui-state-hover a:visited,
|
||||||
|
.ui-state-focus a,
|
||||||
|
.ui-state-focus a:hover,
|
||||||
|
.ui-state-focus a:link,
|
||||||
|
.ui-state-focus a:visited,
|
||||||
|
a.ui-button:hover,
|
||||||
|
a.ui-button:focus {
|
||||||
|
color: #2b2b2b;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui-visual-focus {
|
||||||
|
box-shadow: 0 0 3px 1px rgb(94, 158, 214);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Interaction Cues
|
||||||
|
----------------------------------*/
|
||||||
|
.ui-state-highlight,
|
||||||
|
.ui-widget-content .ui-state-highlight,
|
||||||
|
.ui-widget-header .ui-state-highlight {
|
||||||
|
border: 1px solid #dad55e;
|
||||||
|
background: #fffa90;
|
||||||
|
color: #777620;
|
||||||
|
}
|
||||||
|
.ui-state-checked {
|
||||||
|
border: 1px solid #dad55e;
|
||||||
|
background: #fffa90;
|
||||||
|
}
|
||||||
|
.ui-state-highlight a,
|
||||||
|
.ui-widget-content .ui-state-highlight a,
|
||||||
|
.ui-widget-header .ui-state-highlight a {
|
||||||
|
color: #777620;
|
||||||
|
}
|
||||||
|
.ui-state-error,
|
||||||
|
.ui-widget-content .ui-state-error,
|
||||||
|
.ui-widget-header .ui-state-error {
|
||||||
|
border: 1px solid #f1a899;
|
||||||
|
background: #fddfdf;
|
||||||
|
color: #5f3f3f;
|
||||||
|
}
|
||||||
|
.ui-state-error a,
|
||||||
|
.ui-widget-content .ui-state-error a,
|
||||||
|
.ui-widget-header .ui-state-error a {
|
||||||
|
color: #5f3f3f;
|
||||||
|
}
|
||||||
|
.ui-state-error-text,
|
||||||
|
.ui-widget-content .ui-state-error-text,
|
||||||
|
.ui-widget-header .ui-state-error-text {
|
||||||
|
color: #5f3f3f;
|
||||||
|
}
|
||||||
|
.ui-priority-primary,
|
||||||
|
.ui-widget-content .ui-priority-primary,
|
||||||
|
.ui-widget-header .ui-priority-primary {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
.ui-priority-secondary,
|
||||||
|
.ui-widget-content .ui-priority-secondary,
|
||||||
|
.ui-widget-header .ui-priority-secondary {
|
||||||
|
opacity: .7;
|
||||||
|
filter:Alpha(Opacity=70); /* support: IE8 */
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
.ui-state-disabled,
|
||||||
|
.ui-widget-content .ui-state-disabled,
|
||||||
|
.ui-widget-header .ui-state-disabled {
|
||||||
|
opacity: .35;
|
||||||
|
filter:Alpha(Opacity=35); /* support: IE8 */
|
||||||
|
background-image: none;
|
||||||
|
}
|
||||||
|
.ui-state-disabled .ui-icon {
|
||||||
|
filter:Alpha(Opacity=35); /* support: IE8 - See #6059 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Misc visuals
|
||||||
|
----------------------------------*/
|
||||||
|
/* Overlays */
|
||||||
|
.ui-widget-overlay {
|
||||||
|
background: #aaaaaa;
|
||||||
|
opacity: .3;
|
||||||
|
filter: Alpha(Opacity=30); /* support: IE8 */
|
||||||
|
}
|
||||||
|
.ui-widget-shadow {
|
||||||
|
-webkit-box-shadow: 0px 0px 5px #666666;
|
||||||
|
box-shadow: 0px 0px 5px #666666;
|
||||||
|
}
|
||||||
9
vue/public/libs/jquery-ui.min.js
vendored
Normal file
11
vue/public/libs/jquery.ui.touch-punch.min.js
vendored
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
/*!
|
||||||
|
* jQuery UI Touch Punch 0.2.3
|
||||||
|
*
|
||||||
|
* Copyright 2011–2014, Dave Furfero
|
||||||
|
* Dual licensed under the MIT or GPL Version 2 licenses.
|
||||||
|
*
|
||||||
|
* Depends:
|
||||||
|
* jquery.ui.widget.js
|
||||||
|
* jquery.ui.mouse.js
|
||||||
|
*/
|
||||||
|
!function(a){function f(a,b){if(!(a.originalEvent.touches.length>1)){a.preventDefault();var c=a.originalEvent.changedTouches[0],d=document.createEvent("MouseEvents");d.initMouseEvent(b,!0,!0,window,1,c.screenX,c.screenY,c.clientX,c.clientY,!1,!1,!1,!1,0,null),a.target.dispatchEvent(d)}}if(a.support.touch="ontouchend"in document,a.support.touch){var e,b=a.ui.mouse.prototype,c=b._mouseInit,d=b._mouseDestroy;b._touchStart=function(a){var b=this;!e&&b._mouseCapture(a.originalEvent.changedTouches[0])&&(e=!0,b._touchMoved=!1,f(a,"mouseover"),f(a,"mousemove"),f(a,"mousedown"))},b._touchMove=function(a){e&&(this._touchMoved=!0,f(a,"mousemove"))},b._touchEnd=function(a){e&&(f(a,"mouseup"),f(a,"mouseout"),this._touchMoved||f(a,"click"),e=!1)},b._mouseInit=function(){var b=this;b.element.bind({touchstart:a.proxy(b,"_touchStart"),touchmove:a.proxy(b,"_touchMove"),touchend:a.proxy(b,"_touchEnd")}),c.call(b)},b._mouseDestroy=function(){var b=this;b.element.unbind({touchstart:a.proxy(b,"_touchStart"),touchmove:a.proxy(b,"_touchMove"),touchend:a.proxy(b,"_touchEnd")}),d.call(b)}}}(jQuery);
|
||||||
232
vue/public/libs/polylabel.js
Normal file
|
|
@ -0,0 +1,232 @@
|
||||||
|
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.polylabel = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var Queue = require('tinyqueue');
|
||||||
|
|
||||||
|
module.exports = polylabel;
|
||||||
|
|
||||||
|
function polylabel(polygon, precision, debug) {
|
||||||
|
precision = precision || 1.0;
|
||||||
|
|
||||||
|
// find the bounding box of the outer ring
|
||||||
|
var minX, minY, maxX, maxY;
|
||||||
|
for (var i = 0; i < polygon[0].length; i++) {
|
||||||
|
var p = polygon[0][i];
|
||||||
|
if (!i || p[0] < minX) minX = p[0];
|
||||||
|
if (!i || p[1] < minY) minY = p[1];
|
||||||
|
if (!i || p[0] > maxX) maxX = p[0];
|
||||||
|
if (!i || p[1] > maxY) maxY = p[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
var width = maxX - minX;
|
||||||
|
var height = maxY - minY;
|
||||||
|
var cellSize = Math.min(width, height);
|
||||||
|
var h = cellSize / 2;
|
||||||
|
|
||||||
|
// a priority queue of cells in order of their "potential" (max distance to polygon)
|
||||||
|
var cellQueue = new Queue(null, compareMax);
|
||||||
|
|
||||||
|
// cover polygon with initial cells
|
||||||
|
for (var x = minX; x < maxX; x += cellSize) {
|
||||||
|
for (var y = minY; y < maxY; y += cellSize) {
|
||||||
|
cellQueue.push(new Cell(x + h, y + h, h, polygon));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// take centroid as the first best guess
|
||||||
|
var bestCell = getCentroidCell(polygon);
|
||||||
|
var numProbes = cellQueue.length;
|
||||||
|
|
||||||
|
while (cellQueue.length) {
|
||||||
|
// pick the most promising cell from the queue
|
||||||
|
var cell = cellQueue.pop();
|
||||||
|
|
||||||
|
// update the best cell if we found a better one
|
||||||
|
if (cell.d > bestCell.d) {
|
||||||
|
bestCell = cell;
|
||||||
|
if (debug) console.log('found best %d after %d probes', Math.round(1e4 * cell.d) / 1e4, numProbes);
|
||||||
|
}
|
||||||
|
|
||||||
|
// do not drill down further if there's no chance of a better solution
|
||||||
|
if (cell.max - bestCell.d <= precision) continue;
|
||||||
|
|
||||||
|
// split the cell into four cells
|
||||||
|
h = cell.h / 2;
|
||||||
|
cellQueue.push(new Cell(cell.x - h, cell.y - h, h, polygon));
|
||||||
|
cellQueue.push(new Cell(cell.x + h, cell.y - h, h, polygon));
|
||||||
|
cellQueue.push(new Cell(cell.x - h, cell.y + h, h, polygon));
|
||||||
|
cellQueue.push(new Cell(cell.x + h, cell.y + h, h, polygon));
|
||||||
|
numProbes += 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (debug) {
|
||||||
|
console.log('num probes: ' + numProbes);
|
||||||
|
console.log('best distance: ' + bestCell.d);
|
||||||
|
}
|
||||||
|
|
||||||
|
return [bestCell.x, bestCell.y];
|
||||||
|
}
|
||||||
|
|
||||||
|
function compareMax(a, b) {
|
||||||
|
return b.max - a.max;
|
||||||
|
}
|
||||||
|
|
||||||
|
function Cell(x, y, h, polygon) {
|
||||||
|
this.x = x; // cell center x
|
||||||
|
this.y = y; // cell center y
|
||||||
|
this.h = h; // half the cell size
|
||||||
|
this.d = pointToPolygonDist(x, y, polygon); // distance from cell center to polygon
|
||||||
|
this.max = this.d + this.h * Math.SQRT2; // max distance to polygon within a cell
|
||||||
|
}
|
||||||
|
|
||||||
|
// signed distance from point to polygon outline (negative if point is outside)
|
||||||
|
function pointToPolygonDist(x, y, polygon) {
|
||||||
|
var inside = false;
|
||||||
|
var minDistSq = Infinity;
|
||||||
|
|
||||||
|
for (var k = 0; k < polygon.length; k++) {
|
||||||
|
var ring = polygon[k];
|
||||||
|
|
||||||
|
for (var i = 0, len = ring.length, j = len - 1; i < len; j = i++) {
|
||||||
|
var a = ring[i];
|
||||||
|
var b = ring[j];
|
||||||
|
|
||||||
|
if ((a[1] > y !== b[1] > y) &&
|
||||||
|
(x < (b[0] - a[0]) * (y - a[1]) / (b[1] - a[1]) + a[0])) inside = !inside;
|
||||||
|
|
||||||
|
minDistSq = Math.min(minDistSq, getSegDistSq(x, y, a, b));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (inside ? 1 : -1) * Math.sqrt(minDistSq);
|
||||||
|
}
|
||||||
|
|
||||||
|
// get polygon centroid
|
||||||
|
function getCentroidCell(polygon) {
|
||||||
|
var area = 0;
|
||||||
|
var x = 0;
|
||||||
|
var y = 0;
|
||||||
|
var points = polygon[0];
|
||||||
|
|
||||||
|
for (var i = 0, len = points.length, j = len - 1; i < len; j = i++) {
|
||||||
|
var a = points[i];
|
||||||
|
var b = points[j];
|
||||||
|
var f = a[0] * b[1] - b[0] * a[1];
|
||||||
|
x += (a[0] + b[0]) * f;
|
||||||
|
y += (a[1] + b[1]) * f;
|
||||||
|
area += f * 3;
|
||||||
|
}
|
||||||
|
return new Cell(x / area, y / area, 0, polygon);
|
||||||
|
}
|
||||||
|
|
||||||
|
// get squared distance from a point to a segment
|
||||||
|
function getSegDistSq(px, py, a, b) {
|
||||||
|
|
||||||
|
var x = a[0];
|
||||||
|
var y = a[1];
|
||||||
|
var dx = b[0] - x;
|
||||||
|
var dy = b[1] - y;
|
||||||
|
|
||||||
|
if (dx !== 0 || dy !== 0) {
|
||||||
|
|
||||||
|
var t = ((px - x) * dx + (py - y) * dy) / (dx * dx + dy * dy);
|
||||||
|
|
||||||
|
if (t > 1) {
|
||||||
|
x = b[0];
|
||||||
|
y = b[1];
|
||||||
|
|
||||||
|
} else if (t > 0) {
|
||||||
|
x += dx * t;
|
||||||
|
y += dy * t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dx = px - x;
|
||||||
|
dy = py - y;
|
||||||
|
|
||||||
|
return dx * dx + dy * dy;
|
||||||
|
}
|
||||||
|
|
||||||
|
},{"tinyqueue":2}],2:[function(require,module,exports){
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
module.exports = TinyQueue;
|
||||||
|
|
||||||
|
function TinyQueue(data, compare) {
|
||||||
|
if (!(this instanceof TinyQueue)) return new TinyQueue(data, compare);
|
||||||
|
|
||||||
|
this.data = data || [];
|
||||||
|
this.length = this.data.length;
|
||||||
|
this.compare = compare || defaultCompare;
|
||||||
|
|
||||||
|
if (data) for (var i = Math.floor(this.length / 2); i >= 0; i--) this._down(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
function defaultCompare(a, b) {
|
||||||
|
return a < b ? -1 : a > b ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
TinyQueue.prototype = {
|
||||||
|
|
||||||
|
push: function (item) {
|
||||||
|
this.data.push(item);
|
||||||
|
this.length++;
|
||||||
|
this._up(this.length - 1);
|
||||||
|
},
|
||||||
|
|
||||||
|
pop: function () {
|
||||||
|
var top = this.data[0];
|
||||||
|
this.data[0] = this.data[this.length - 1];
|
||||||
|
this.length--;
|
||||||
|
this.data.pop();
|
||||||
|
this._down(0);
|
||||||
|
return top;
|
||||||
|
},
|
||||||
|
|
||||||
|
peek: function () {
|
||||||
|
return this.data[0];
|
||||||
|
},
|
||||||
|
|
||||||
|
_up: function (pos) {
|
||||||
|
var data = this.data,
|
||||||
|
compare = this.compare;
|
||||||
|
|
||||||
|
while (pos > 0) {
|
||||||
|
var parent = Math.floor((pos - 1) / 2);
|
||||||
|
if (compare(data[pos], data[parent]) < 0) {
|
||||||
|
swap(data, parent, pos);
|
||||||
|
pos = parent;
|
||||||
|
|
||||||
|
} else break;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_down: function (pos) {
|
||||||
|
var data = this.data,
|
||||||
|
compare = this.compare,
|
||||||
|
len = this.length;
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
var left = 2 * pos + 1,
|
||||||
|
right = left + 1,
|
||||||
|
min = pos;
|
||||||
|
|
||||||
|
if (left < len && compare(data[left], data[min]) < 0) min = left;
|
||||||
|
if (right < len && compare(data[right], data[min]) < 0) min = right;
|
||||||
|
|
||||||
|
if (min === pos) return;
|
||||||
|
|
||||||
|
swap(data, min, pos);
|
||||||
|
pos = min;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function swap(data, i, j) {
|
||||||
|
var tmp = data[i];
|
||||||
|
data[i] = data[j];
|
||||||
|
data[j] = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
},{}]},{},[1])(1)
|
||||||
|
});
|
||||||
1
vue/public/libs/polylabel.min.js
vendored
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
!function(t){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{("undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this).polylabel=t()}}(function(){return function t(n,e,r){function o(a,u){if(!e[a]){if(!n[a]){var f="function"==typeof require&&require;if(!u&&f)return f(a,!0);if(i)return i(a,!0);var h=new Error("Cannot find module '"+a+"'");throw h.code="MODULE_NOT_FOUND",h}var s=e[a]={exports:{}};n[a][0].call(s.exports,function(t){var e=n[a][1][t];return o(e||t)},s,s.exports,t,n,e,r)}return e[a].exports}for(var i="function"==typeof require&&require,a=0;a<r.length;a++)o(r[a]);return o}({1:[function(t,n,e){"use strict";var r=t("tinyqueue");function o(t,n){return n.max-t.max}function i(t,n,e,r){this.x=t,this.y=n,this.h=e,this.d=function(t,n,e){for(var r=!1,o=1/0,i=0;i<e.length;i++)for(var u=e[i],f=0,h=u.length,s=h-1;f<h;s=f++){var d=u[f],l=u[s];d[1]>n!=l[1]>n&&t<(l[0]-d[0])*(n-d[1])/(l[1]-d[1])+d[0]&&(r=!r),o=Math.min(o,a(t,n,d,l))}return(r?1:-1)*Math.sqrt(o)}(t,n,r),this.max=this.d+this.h*Math.SQRT2}function a(t,n,e,r){var o=e[0],i=e[1],a=r[0]-o,u=r[1]-i;if(0!==a||0!==u){var f=((t-o)*a+(n-i)*u)/(a*a+u*u);f>1?(o=r[0],i=r[1]):f>0&&(o+=a*f,i+=u*f)}return(a=t-o)*a+(u=n-i)*u}n.exports=function(t,n,e){var a,u,f,h;n=n||1;for(var s=0;s<t[0].length;s++){var d=t[0][s];(!s||d[0]<a)&&(a=d[0]),(!s||d[1]<u)&&(u=d[1]),(!s||d[0]>f)&&(f=d[0]),(!s||d[1]>h)&&(h=d[1])}for(var l=f-a,p=h-u,c=Math.min(l,p),v=c/2,g=new r(null,o),x=a;x<f;x+=c)for(var y=u;y<h;y+=c)g.push(new i(x+v,y+v,v,t));var w=function(t){for(var n=0,e=0,r=0,o=t[0],a=0,u=o.length,f=u-1;a<u;f=a++){var h=o[a],s=o[f],d=h[0]*s[1]-s[0]*h[1];e+=(h[0]+s[0])*d,r+=(h[1]+s[1])*d,n+=3*d}return new i(e/n,r/n,0,t)}(t),m=g.length;for(;g.length;){var b=g.pop();b.d>w.d&&(w=b,e&&console.log("found best %d after %d probes",Math.round(1e4*b.d)/1e4,m)),b.max-w.d<=n||(v=b.h/2,g.push(new i(b.x-v,b.y-v,v,t)),g.push(new i(b.x+v,b.y-v,v,t)),g.push(new i(b.x-v,b.y+v,v,t)),g.push(new i(b.x+v,b.y+v,v,t)),m+=4)}e&&(console.log("num probes: "+m),console.log("best distance: "+w.d));return[w.x,w.y]}},{tinyqueue:2}],2:[function(t,n,e){"use strict";function r(t,n){if(!(this instanceof r))return new r(t,n);if(this.data=t||[],this.length=this.data.length,this.compare=n||o,t)for(var e=Math.floor(this.length/2);e>=0;e--)this._down(e)}function o(t,n){return t<n?-1:t>n?1:0}function i(t,n,e){var r=t[n];t[n]=t[e],t[e]=r}n.exports=r,r.prototype={push:function(t){this.data.push(t),this.length++,this._up(this.length-1)},pop:function(){var t=this.data[0];return this.data[0]=this.data[this.length-1],this.length--,this.data.pop(),this._down(0),t},peek:function(){return this.data[0]},_up:function(t){for(var n=this.data,e=this.compare;t>0;){var r=Math.floor((t-1)/2);if(!(e(n[t],n[r])<0))break;i(n,r,t),t=r}},_down:function(t){for(var n=this.data,e=this.compare,r=this.length;;){var o=2*t+1,a=o+1,u=t;if(o<r&&e(n[o],n[u])<0&&(u=o),a<r&&e(n[a],n[u])<0&&(u=a),u===t)return;i(n,u,t),t=u}}}},{}]},{},[1])(1)});
|
||||||
387
vue/public/libs/priority-queue.js
Normal file
|
|
@ -0,0 +1,387 @@
|
||||||
|
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.PriorityQueue = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(_dereq_,module,exports){
|
||||||
|
var AbstractPriorityQueue, ArrayStrategy, BHeapStrategy, BinaryHeapStrategy, PriorityQueue,
|
||||||
|
extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
|
||||||
|
hasProp = {}.hasOwnProperty;
|
||||||
|
|
||||||
|
AbstractPriorityQueue = _dereq_('./PriorityQueue/AbstractPriorityQueue');
|
||||||
|
|
||||||
|
ArrayStrategy = _dereq_('./PriorityQueue/ArrayStrategy');
|
||||||
|
|
||||||
|
BinaryHeapStrategy = _dereq_('./PriorityQueue/BinaryHeapStrategy');
|
||||||
|
|
||||||
|
BHeapStrategy = _dereq_('./PriorityQueue/BHeapStrategy');
|
||||||
|
|
||||||
|
PriorityQueue = (function(superClass) {
|
||||||
|
extend(PriorityQueue, superClass);
|
||||||
|
|
||||||
|
function PriorityQueue(options) {
|
||||||
|
options || (options = {});
|
||||||
|
options.strategy || (options.strategy = BinaryHeapStrategy);
|
||||||
|
options.comparator || (options.comparator = function(a, b) {
|
||||||
|
return (a || 0) - (b || 0);
|
||||||
|
});
|
||||||
|
PriorityQueue.__super__.constructor.call(this, options);
|
||||||
|
}
|
||||||
|
|
||||||
|
return PriorityQueue;
|
||||||
|
|
||||||
|
})(AbstractPriorityQueue);
|
||||||
|
|
||||||
|
PriorityQueue.ArrayStrategy = ArrayStrategy;
|
||||||
|
|
||||||
|
PriorityQueue.BinaryHeapStrategy = BinaryHeapStrategy;
|
||||||
|
|
||||||
|
PriorityQueue.BHeapStrategy = BHeapStrategy;
|
||||||
|
|
||||||
|
module.exports = PriorityQueue;
|
||||||
|
|
||||||
|
|
||||||
|
},{"./PriorityQueue/AbstractPriorityQueue":2,"./PriorityQueue/ArrayStrategy":3,"./PriorityQueue/BHeapStrategy":4,"./PriorityQueue/BinaryHeapStrategy":5}],2:[function(_dereq_,module,exports){
|
||||||
|
var AbstractPriorityQueue;
|
||||||
|
|
||||||
|
module.exports = AbstractPriorityQueue = (function() {
|
||||||
|
function AbstractPriorityQueue(options) {
|
||||||
|
var ref;
|
||||||
|
if ((options != null ? options.strategy : void 0) == null) {
|
||||||
|
throw 'Must pass options.strategy, a strategy';
|
||||||
|
}
|
||||||
|
if ((options != null ? options.comparator : void 0) == null) {
|
||||||
|
throw 'Must pass options.comparator, a comparator';
|
||||||
|
}
|
||||||
|
this.priv = new options.strategy(options);
|
||||||
|
this.length = (options != null ? (ref = options.initialValues) != null ? ref.length : void 0 : void 0) || 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
AbstractPriorityQueue.prototype.queue = function(value) {
|
||||||
|
this.length++;
|
||||||
|
this.priv.queue(value);
|
||||||
|
return void 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
AbstractPriorityQueue.prototype.dequeue = function(value) {
|
||||||
|
if (!this.length) {
|
||||||
|
throw 'Empty queue';
|
||||||
|
}
|
||||||
|
this.length--;
|
||||||
|
return this.priv.dequeue();
|
||||||
|
};
|
||||||
|
|
||||||
|
AbstractPriorityQueue.prototype.peek = function(value) {
|
||||||
|
if (!this.length) {
|
||||||
|
throw 'Empty queue';
|
||||||
|
}
|
||||||
|
return this.priv.peek();
|
||||||
|
};
|
||||||
|
|
||||||
|
AbstractPriorityQueue.prototype.clear = function() {
|
||||||
|
this.length = 0;
|
||||||
|
return this.priv.clear();
|
||||||
|
};
|
||||||
|
|
||||||
|
return AbstractPriorityQueue;
|
||||||
|
|
||||||
|
})();
|
||||||
|
|
||||||
|
|
||||||
|
},{}],3:[function(_dereq_,module,exports){
|
||||||
|
var ArrayStrategy, binarySearchForIndexReversed;
|
||||||
|
|
||||||
|
binarySearchForIndexReversed = function(array, value, comparator) {
|
||||||
|
var high, low, mid;
|
||||||
|
low = 0;
|
||||||
|
high = array.length;
|
||||||
|
while (low < high) {
|
||||||
|
mid = (low + high) >>> 1;
|
||||||
|
if (comparator(array[mid], value) >= 0) {
|
||||||
|
low = mid + 1;
|
||||||
|
} else {
|
||||||
|
high = mid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return low;
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = ArrayStrategy = (function() {
|
||||||
|
function ArrayStrategy(options) {
|
||||||
|
var ref;
|
||||||
|
this.options = options;
|
||||||
|
this.comparator = this.options.comparator;
|
||||||
|
this.data = ((ref = this.options.initialValues) != null ? ref.slice(0) : void 0) || [];
|
||||||
|
this.data.sort(this.comparator).reverse();
|
||||||
|
}
|
||||||
|
|
||||||
|
ArrayStrategy.prototype.queue = function(value) {
|
||||||
|
var pos;
|
||||||
|
pos = binarySearchForIndexReversed(this.data, value, this.comparator);
|
||||||
|
this.data.splice(pos, 0, value);
|
||||||
|
return void 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
ArrayStrategy.prototype.dequeue = function() {
|
||||||
|
return this.data.pop();
|
||||||
|
};
|
||||||
|
|
||||||
|
ArrayStrategy.prototype.peek = function() {
|
||||||
|
return this.data[this.data.length - 1];
|
||||||
|
};
|
||||||
|
|
||||||
|
ArrayStrategy.prototype.clear = function() {
|
||||||
|
this.data.length = 0;
|
||||||
|
return void 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
return ArrayStrategy;
|
||||||
|
|
||||||
|
})();
|
||||||
|
|
||||||
|
|
||||||
|
},{}],4:[function(_dereq_,module,exports){
|
||||||
|
var BHeapStrategy;
|
||||||
|
|
||||||
|
module.exports = BHeapStrategy = (function() {
|
||||||
|
function BHeapStrategy(options) {
|
||||||
|
var arr, i, j, k, len, ref, ref1, shift, value;
|
||||||
|
this.comparator = (options != null ? options.comparator : void 0) || function(a, b) {
|
||||||
|
return a - b;
|
||||||
|
};
|
||||||
|
this.pageSize = (options != null ? options.pageSize : void 0) || 512;
|
||||||
|
this.length = 0;
|
||||||
|
shift = 0;
|
||||||
|
while ((1 << shift) < this.pageSize) {
|
||||||
|
shift += 1;
|
||||||
|
}
|
||||||
|
if (1 << shift !== this.pageSize) {
|
||||||
|
throw 'pageSize must be a power of two';
|
||||||
|
}
|
||||||
|
this._shift = shift;
|
||||||
|
this._emptyMemoryPageTemplate = arr = [];
|
||||||
|
for (i = j = 0, ref = this.pageSize; 0 <= ref ? j < ref : j > ref; i = 0 <= ref ? ++j : --j) {
|
||||||
|
arr.push(null);
|
||||||
|
}
|
||||||
|
this._memory = [];
|
||||||
|
this._mask = this.pageSize - 1;
|
||||||
|
if (options.initialValues) {
|
||||||
|
ref1 = options.initialValues;
|
||||||
|
for (k = 0, len = ref1.length; k < len; k++) {
|
||||||
|
value = ref1[k];
|
||||||
|
this.queue(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BHeapStrategy.prototype.queue = function(value) {
|
||||||
|
this.length += 1;
|
||||||
|
this._write(this.length, value);
|
||||||
|
this._bubbleUp(this.length, value);
|
||||||
|
return void 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
BHeapStrategy.prototype.dequeue = function() {
|
||||||
|
var ret, val;
|
||||||
|
ret = this._read(1);
|
||||||
|
val = this._read(this.length);
|
||||||
|
this.length -= 1;
|
||||||
|
if (this.length > 0) {
|
||||||
|
this._write(1, val);
|
||||||
|
this._bubbleDown(1, val);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
};
|
||||||
|
|
||||||
|
BHeapStrategy.prototype.peek = function() {
|
||||||
|
return this._read(1);
|
||||||
|
};
|
||||||
|
|
||||||
|
BHeapStrategy.prototype.clear = function() {
|
||||||
|
this.length = 0;
|
||||||
|
this._memory.length = 0;
|
||||||
|
return void 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
BHeapStrategy.prototype._write = function(index, value) {
|
||||||
|
var page;
|
||||||
|
page = index >> this._shift;
|
||||||
|
while (page >= this._memory.length) {
|
||||||
|
this._memory.push(this._emptyMemoryPageTemplate.slice(0));
|
||||||
|
}
|
||||||
|
return this._memory[page][index & this._mask] = value;
|
||||||
|
};
|
||||||
|
|
||||||
|
BHeapStrategy.prototype._read = function(index) {
|
||||||
|
return this._memory[index >> this._shift][index & this._mask];
|
||||||
|
};
|
||||||
|
|
||||||
|
BHeapStrategy.prototype._bubbleUp = function(index, value) {
|
||||||
|
var compare, indexInPage, parentIndex, parentValue;
|
||||||
|
compare = this.comparator;
|
||||||
|
while (index > 1) {
|
||||||
|
indexInPage = index & this._mask;
|
||||||
|
if (index < this.pageSize || indexInPage > 3) {
|
||||||
|
parentIndex = (index & ~this._mask) | (indexInPage >> 1);
|
||||||
|
} else if (indexInPage < 2) {
|
||||||
|
parentIndex = (index - this.pageSize) >> this._shift;
|
||||||
|
parentIndex += parentIndex & ~(this._mask >> 1);
|
||||||
|
parentIndex |= this.pageSize >> 1;
|
||||||
|
} else {
|
||||||
|
parentIndex = index - 2;
|
||||||
|
}
|
||||||
|
parentValue = this._read(parentIndex);
|
||||||
|
if (compare(parentValue, value) < 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
this._write(parentIndex, value);
|
||||||
|
this._write(index, parentValue);
|
||||||
|
index = parentIndex;
|
||||||
|
}
|
||||||
|
return void 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
BHeapStrategy.prototype._bubbleDown = function(index, value) {
|
||||||
|
var childIndex1, childIndex2, childValue1, childValue2, compare;
|
||||||
|
compare = this.comparator;
|
||||||
|
while (index < this.length) {
|
||||||
|
if (index > this._mask && !(index & (this._mask - 1))) {
|
||||||
|
childIndex1 = childIndex2 = index + 2;
|
||||||
|
} else if (index & (this.pageSize >> 1)) {
|
||||||
|
childIndex1 = (index & ~this._mask) >> 1;
|
||||||
|
childIndex1 |= index & (this._mask >> 1);
|
||||||
|
childIndex1 = (childIndex1 + 1) << this._shift;
|
||||||
|
childIndex2 = childIndex1 + 1;
|
||||||
|
} else {
|
||||||
|
childIndex1 = index + (index & this._mask);
|
||||||
|
childIndex2 = childIndex1 + 1;
|
||||||
|
}
|
||||||
|
if (childIndex1 !== childIndex2 && childIndex2 <= this.length) {
|
||||||
|
childValue1 = this._read(childIndex1);
|
||||||
|
childValue2 = this._read(childIndex2);
|
||||||
|
if (compare(childValue1, value) < 0 && compare(childValue1, childValue2) <= 0) {
|
||||||
|
this._write(childIndex1, value);
|
||||||
|
this._write(index, childValue1);
|
||||||
|
index = childIndex1;
|
||||||
|
} else if (compare(childValue2, value) < 0) {
|
||||||
|
this._write(childIndex2, value);
|
||||||
|
this._write(index, childValue2);
|
||||||
|
index = childIndex2;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else if (childIndex1 <= this.length) {
|
||||||
|
childValue1 = this._read(childIndex1);
|
||||||
|
if (compare(childValue1, value) < 0) {
|
||||||
|
this._write(childIndex1, value);
|
||||||
|
this._write(index, childValue1);
|
||||||
|
index = childIndex1;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return void 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
return BHeapStrategy;
|
||||||
|
|
||||||
|
})();
|
||||||
|
|
||||||
|
|
||||||
|
},{}],5:[function(_dereq_,module,exports){
|
||||||
|
var BinaryHeapStrategy;
|
||||||
|
|
||||||
|
module.exports = BinaryHeapStrategy = (function() {
|
||||||
|
function BinaryHeapStrategy(options) {
|
||||||
|
var ref;
|
||||||
|
this.comparator = (options != null ? options.comparator : void 0) || function(a, b) {
|
||||||
|
return a - b;
|
||||||
|
};
|
||||||
|
this.length = 0;
|
||||||
|
this.data = ((ref = options.initialValues) != null ? ref.slice(0) : void 0) || [];
|
||||||
|
this._heapify();
|
||||||
|
}
|
||||||
|
|
||||||
|
BinaryHeapStrategy.prototype._heapify = function() {
|
||||||
|
var i, j, ref;
|
||||||
|
if (this.data.length > 0) {
|
||||||
|
for (i = j = 1, ref = this.data.length; 1 <= ref ? j < ref : j > ref; i = 1 <= ref ? ++j : --j) {
|
||||||
|
this._bubbleUp(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return void 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
BinaryHeapStrategy.prototype.queue = function(value) {
|
||||||
|
this.data.push(value);
|
||||||
|
this._bubbleUp(this.data.length - 1);
|
||||||
|
return void 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
BinaryHeapStrategy.prototype.dequeue = function() {
|
||||||
|
var last, ret;
|
||||||
|
ret = this.data[0];
|
||||||
|
last = this.data.pop();
|
||||||
|
if (this.data.length > 0) {
|
||||||
|
this.data[0] = last;
|
||||||
|
this._bubbleDown(0);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
};
|
||||||
|
|
||||||
|
BinaryHeapStrategy.prototype.peek = function() {
|
||||||
|
return this.data[0];
|
||||||
|
};
|
||||||
|
|
||||||
|
BinaryHeapStrategy.prototype.clear = function() {
|
||||||
|
this.length = 0;
|
||||||
|
this.data.length = 0;
|
||||||
|
return void 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
BinaryHeapStrategy.prototype._bubbleUp = function(pos) {
|
||||||
|
var parent, x;
|
||||||
|
while (pos > 0) {
|
||||||
|
parent = (pos - 1) >>> 1;
|
||||||
|
if (this.comparator(this.data[pos], this.data[parent]) < 0) {
|
||||||
|
x = this.data[parent];
|
||||||
|
this.data[parent] = this.data[pos];
|
||||||
|
this.data[pos] = x;
|
||||||
|
pos = parent;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return void 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
BinaryHeapStrategy.prototype._bubbleDown = function(pos) {
|
||||||
|
var last, left, minIndex, right, x;
|
||||||
|
last = this.data.length - 1;
|
||||||
|
while (true) {
|
||||||
|
left = (pos << 1) + 1;
|
||||||
|
right = left + 1;
|
||||||
|
minIndex = pos;
|
||||||
|
if (left <= last && this.comparator(this.data[left], this.data[minIndex]) < 0) {
|
||||||
|
minIndex = left;
|
||||||
|
}
|
||||||
|
if (right <= last && this.comparator(this.data[right], this.data[minIndex]) < 0) {
|
||||||
|
minIndex = right;
|
||||||
|
}
|
||||||
|
if (minIndex !== pos) {
|
||||||
|
x = this.data[minIndex];
|
||||||
|
this.data[minIndex] = this.data[pos];
|
||||||
|
this.data[pos] = x;
|
||||||
|
pos = minIndex;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return void 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
return BinaryHeapStrategy;
|
||||||
|
|
||||||
|
})();
|
||||||
|
|
||||||
|
|
||||||
|
},{}]},{},[1])(1)
|
||||||
|
});
|
||||||
1
vue/public/libs/priority-queue.min.js
vendored
Normal file
436
vue/public/libs/quantize.js
Normal file
|
|
@ -0,0 +1,436 @@
|
||||||
|
// Forked from color-thief.js Copyright 2011 Lokesh Dhakar under MIT license
|
||||||
|
// var pixelArray = [[190,197,190], [202,204,200], [207,214,210]]; // ... etc;
|
||||||
|
// var cmap = MMCQ.quantize(pixelArray, colorCount);
|
||||||
|
// var palette = cmap ? cmap.palette() : null;
|
||||||
|
|
||||||
|
// Protovis. Copyright 2010 Stanford Visualization Group (http://mbostock.github.com/protovis/)
|
||||||
|
// Licensed under the BSD License: http://www.opensource.org/licenses/bsd-license.php
|
||||||
|
if (!pv) {
|
||||||
|
var pv = {
|
||||||
|
map: function(array, f) {
|
||||||
|
var o = {};
|
||||||
|
return f ? array.map(function(d, i) { o.index = i; return f.call(o, d); }) : array.slice();
|
||||||
|
},
|
||||||
|
naturalOrder: function(a, b) {
|
||||||
|
return (a < b) ? -1 : ((a > b) ? 1 : 0);
|
||||||
|
},
|
||||||
|
sum: function(array, f) {
|
||||||
|
var o = {};
|
||||||
|
return array.reduce(f ? function(p, d, i) { o.index = i; return p + f.call(o, d); } : function(p, d) { return p + d; }, 0);
|
||||||
|
},
|
||||||
|
max: function(array, f) {
|
||||||
|
return Math.max.apply(null, f ? pv.map(array, f) : array);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// MMCQ (Modified median cut quantization). Algorithm from the Leptonica library, modified by Nick Rabinowitz
|
||||||
|
// quantize.js Copyright 2008 Nick Rabinowitz under MIT license
|
||||||
|
var MMCQ = (function() {
|
||||||
|
// private constants
|
||||||
|
var sigbits = 5,
|
||||||
|
rshift = 8 - sigbits,
|
||||||
|
maxIterations = 1000,
|
||||||
|
fractByPopulations = 0.75;
|
||||||
|
|
||||||
|
// get reduced-space color index for a pixel
|
||||||
|
function getColorIndex(r, g, b) {
|
||||||
|
return (r << (2 * sigbits)) + (g << sigbits) + b;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Simple priority queue
|
||||||
|
function PQueue(comparator) {
|
||||||
|
var contents = [],
|
||||||
|
sorted = false;
|
||||||
|
|
||||||
|
function sort() {
|
||||||
|
contents.sort(comparator);
|
||||||
|
sorted = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
push: function(o) {
|
||||||
|
contents.push(o);
|
||||||
|
sorted = false;
|
||||||
|
},
|
||||||
|
peek: function(index) {
|
||||||
|
if (!sorted) sort();
|
||||||
|
if (index===undefined) index = contents.length - 1;
|
||||||
|
return contents[index];
|
||||||
|
},
|
||||||
|
pop: function() {
|
||||||
|
if (!sorted) sort();
|
||||||
|
return contents.pop();
|
||||||
|
},
|
||||||
|
size: function() {
|
||||||
|
return contents.length;
|
||||||
|
},
|
||||||
|
map: function(f) {
|
||||||
|
return contents.map(f);
|
||||||
|
},
|
||||||
|
debug: function() {
|
||||||
|
if (!sorted) sort();
|
||||||
|
return contents;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3d color space box
|
||||||
|
function VBox(r1, r2, g1, g2, b1, b2, histo) {
|
||||||
|
var vbox = this;
|
||||||
|
vbox.r1 = r1;
|
||||||
|
vbox.r2 = r2;
|
||||||
|
vbox.g1 = g1;
|
||||||
|
vbox.g2 = g2;
|
||||||
|
vbox.b1 = b1;
|
||||||
|
vbox.b2 = b2;
|
||||||
|
vbox.histo = histo;
|
||||||
|
}
|
||||||
|
VBox.prototype = {
|
||||||
|
volume: function(force) {
|
||||||
|
var vbox = this;
|
||||||
|
if (!vbox._volume || force) {
|
||||||
|
vbox._volume = ((vbox.r2 - vbox.r1 + 1) * (vbox.g2 - vbox.g1 + 1) * (vbox.b2 - vbox.b1 + 1));
|
||||||
|
}
|
||||||
|
return vbox._volume;
|
||||||
|
},
|
||||||
|
count: function(force) {
|
||||||
|
var vbox = this,
|
||||||
|
histo = vbox.histo;
|
||||||
|
if (!vbox._count_set || force) {
|
||||||
|
var npix = 0,
|
||||||
|
index, i, j, k;
|
||||||
|
for (i = vbox.r1; i <= vbox.r2; i++) {
|
||||||
|
for (j = vbox.g1; j <= vbox.g2; j++) {
|
||||||
|
for (k = vbox.b1; k <= vbox.b2; k++) {
|
||||||
|
index = getColorIndex(i,j,k);
|
||||||
|
npix += (histo[index] || 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
vbox._count = npix;
|
||||||
|
vbox._count_set = true;
|
||||||
|
}
|
||||||
|
return vbox._count;
|
||||||
|
},
|
||||||
|
copy: function() {
|
||||||
|
var vbox = this;
|
||||||
|
return new VBox(vbox.r1, vbox.r2, vbox.g1, vbox.g2, vbox.b1, vbox.b2, vbox.histo);
|
||||||
|
},
|
||||||
|
avg: function(force) {
|
||||||
|
var vbox = this,
|
||||||
|
histo = vbox.histo;
|
||||||
|
if (!vbox._avg || force) {
|
||||||
|
var ntot = 0,
|
||||||
|
mult = 1 << (8 - sigbits),
|
||||||
|
rsum = 0,
|
||||||
|
gsum = 0,
|
||||||
|
bsum = 0,
|
||||||
|
hval,
|
||||||
|
i, j, k, histoindex;
|
||||||
|
for (i = vbox.r1; i <= vbox.r2; i++) {
|
||||||
|
for (j = vbox.g1; j <= vbox.g2; j++) {
|
||||||
|
for (k = vbox.b1; k <= vbox.b2; k++) {
|
||||||
|
histoindex = getColorIndex(i,j,k);
|
||||||
|
hval = histo[histoindex] || 0;
|
||||||
|
ntot += hval;
|
||||||
|
rsum += (hval * (i + 0.5) * mult);
|
||||||
|
gsum += (hval * (j + 0.5) * mult);
|
||||||
|
bsum += (hval * (k + 0.5) * mult);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ntot) {
|
||||||
|
vbox._avg = [~~(rsum/ntot), ~~(gsum/ntot), ~~(bsum/ntot)];
|
||||||
|
} else {
|
||||||
|
// console.log('empty box');
|
||||||
|
vbox._avg = [
|
||||||
|
~~(mult * (vbox.r1 + vbox.r2 + 1) / 2),
|
||||||
|
~~(mult * (vbox.g1 + vbox.g2 + 1) / 2),
|
||||||
|
~~(mult * (vbox.b1 + vbox.b2 + 1) / 2)
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return vbox._avg;
|
||||||
|
},
|
||||||
|
contains: function(pixel) {
|
||||||
|
var vbox = this,
|
||||||
|
rval = pixel[0] >> rshift;
|
||||||
|
gval = pixel[1] >> rshift;
|
||||||
|
bval = pixel[2] >> rshift;
|
||||||
|
return (rval >= vbox.r1 && rval <= vbox.r2 &&
|
||||||
|
gval >= vbox.g1 && gval <= vbox.g2 &&
|
||||||
|
bval >= vbox.b1 && bval <= vbox.b2);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Color map
|
||||||
|
function CMap() {
|
||||||
|
this.vboxes = new PQueue(function(a,b) {
|
||||||
|
return pv.naturalOrder(
|
||||||
|
a.vbox.count()*a.vbox.volume(),
|
||||||
|
b.vbox.count()*b.vbox.volume()
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
CMap.prototype = {
|
||||||
|
push: function(vbox) {
|
||||||
|
this.vboxes.push({
|
||||||
|
vbox: vbox,
|
||||||
|
color: vbox.avg()
|
||||||
|
});
|
||||||
|
},
|
||||||
|
palette: function() {
|
||||||
|
return this.vboxes.map(function(vb) { return vb.color; });
|
||||||
|
},
|
||||||
|
size: function() {
|
||||||
|
return this.vboxes.size();
|
||||||
|
},
|
||||||
|
map: function(color) {
|
||||||
|
var vboxes = this.vboxes;
|
||||||
|
for (var i=0; i<vboxes.size(); i++) {
|
||||||
|
if (vboxes.peek(i).vbox.contains(color)) {
|
||||||
|
return vboxes.peek(i).color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this.nearest(color);
|
||||||
|
},
|
||||||
|
nearest: function(color) {
|
||||||
|
var vboxes = this.vboxes,
|
||||||
|
d1, d2, pColor;
|
||||||
|
for (var i=0; i<vboxes.size(); i++) {
|
||||||
|
d2 = Math.sqrt(
|
||||||
|
Math.pow(color[0] - vboxes.peek(i).color[0], 2) +
|
||||||
|
Math.pow(color[1] - vboxes.peek(i).color[1], 2) +
|
||||||
|
Math.pow(color[2] - vboxes.peek(i).color[2], 2)
|
||||||
|
);
|
||||||
|
if (d2 < d1 || d1 === undefined) {
|
||||||
|
d1 = d2;
|
||||||
|
pColor = vboxes.peek(i).color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return pColor;
|
||||||
|
},
|
||||||
|
forcebw: function() {
|
||||||
|
// XXX: won't work yet
|
||||||
|
var vboxes = this.vboxes;
|
||||||
|
vboxes.sort(function(a,b) { return pv.naturalOrder(pv.sum(a.color), pv.sum(b.color));});
|
||||||
|
|
||||||
|
// force darkest color to black if everything < 5
|
||||||
|
var lowest = vboxes[0].color;
|
||||||
|
if (lowest[0] < 5 && lowest[1] < 5 && lowest[2] < 5)
|
||||||
|
vboxes[0].color = [0,0,0];
|
||||||
|
|
||||||
|
// force lightest color to white if everything > 251
|
||||||
|
var idx = vboxes.length-1,
|
||||||
|
highest = vboxes[idx].color;
|
||||||
|
if (highest[0] > 251 && highest[1] > 251 && highest[2] > 251)
|
||||||
|
vboxes[idx].color = [255,255,255];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// histo (1-d array, giving the number of pixels in
|
||||||
|
// each quantized region of color space), or null on error
|
||||||
|
function getHisto(pixels) {
|
||||||
|
var histosize = 1 << (3 * sigbits),
|
||||||
|
histo = new Array(histosize),
|
||||||
|
index, rval, gval, bval;
|
||||||
|
pixels.forEach(function(pixel) {
|
||||||
|
rval = pixel[0] >> rshift;
|
||||||
|
gval = pixel[1] >> rshift;
|
||||||
|
bval = pixel[2] >> rshift;
|
||||||
|
index = getColorIndex(rval, gval, bval);
|
||||||
|
histo[index] = (histo[index] || 0) + 1;
|
||||||
|
});
|
||||||
|
return histo;
|
||||||
|
}
|
||||||
|
|
||||||
|
function vboxFromPixels(pixels, histo) {
|
||||||
|
var rmin=1000000, rmax=0,
|
||||||
|
gmin=1000000, gmax=0,
|
||||||
|
bmin=1000000, bmax=0,
|
||||||
|
rval, gval, bval;
|
||||||
|
// find min/max
|
||||||
|
pixels.forEach(function(pixel) {
|
||||||
|
rval = pixel[0] >> rshift;
|
||||||
|
gval = pixel[1] >> rshift;
|
||||||
|
bval = pixel[2] >> rshift;
|
||||||
|
if (rval < rmin) rmin = rval;
|
||||||
|
else if (rval > rmax) rmax = rval;
|
||||||
|
if (gval < gmin) gmin = gval;
|
||||||
|
else if (gval > gmax) gmax = gval;
|
||||||
|
if (bval < bmin) bmin = bval;
|
||||||
|
else if (bval > bmax) bmax = bval;
|
||||||
|
});
|
||||||
|
return new VBox(rmin, rmax, gmin, gmax, bmin, bmax, histo);
|
||||||
|
}
|
||||||
|
|
||||||
|
function medianCutApply(histo, vbox) {
|
||||||
|
if (!vbox.count()) return;
|
||||||
|
|
||||||
|
var rw = vbox.r2 - vbox.r1 + 1,
|
||||||
|
gw = vbox.g2 - vbox.g1 + 1,
|
||||||
|
bw = vbox.b2 - vbox.b1 + 1,
|
||||||
|
maxw = pv.max([rw, gw, bw]);
|
||||||
|
// only one pixel, no split
|
||||||
|
if (vbox.count() == 1) {
|
||||||
|
return [vbox.copy()];
|
||||||
|
}
|
||||||
|
/* Find the partial sum arrays along the selected axis. */
|
||||||
|
var total = 0,
|
||||||
|
partialsum = [],
|
||||||
|
lookaheadsum = [],
|
||||||
|
i, j, k, sum, index;
|
||||||
|
if (maxw == rw) {
|
||||||
|
for (i = vbox.r1; i <= vbox.r2; i++) {
|
||||||
|
sum = 0;
|
||||||
|
for (j = vbox.g1; j <= vbox.g2; j++) {
|
||||||
|
for (k = vbox.b1; k <= vbox.b2; k++) {
|
||||||
|
index = getColorIndex(i,j,k);
|
||||||
|
sum += (histo[index] || 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
total += sum;
|
||||||
|
partialsum[i] = total;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (maxw == gw) {
|
||||||
|
for (i = vbox.g1; i <= vbox.g2; i++) {
|
||||||
|
sum = 0;
|
||||||
|
for (j = vbox.r1; j <= vbox.r2; j++) {
|
||||||
|
for (k = vbox.b1; k <= vbox.b2; k++) {
|
||||||
|
index = getColorIndex(j,i,k);
|
||||||
|
sum += (histo[index] || 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
total += sum;
|
||||||
|
partialsum[i] = total;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else { /* maxw == bw */
|
||||||
|
for (i = vbox.b1; i <= vbox.b2; i++) {
|
||||||
|
sum = 0;
|
||||||
|
for (j = vbox.r1; j <= vbox.r2; j++) {
|
||||||
|
for (k = vbox.g1; k <= vbox.g2; k++) {
|
||||||
|
index = getColorIndex(j,k,i);
|
||||||
|
sum += (histo[index] || 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
total += sum;
|
||||||
|
partialsum[i] = total;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
partialsum.forEach(function(d,i) {
|
||||||
|
lookaheadsum[i] = total-d;
|
||||||
|
});
|
||||||
|
function doCut(color) {
|
||||||
|
var dim1 = color + '1',
|
||||||
|
dim2 = color + '2',
|
||||||
|
left, right, vbox1, vbox2, d2, count2=0;
|
||||||
|
for (i = vbox[dim1]; i <= vbox[dim2]; i++) {
|
||||||
|
if (partialsum[i] > total / 2) {
|
||||||
|
vbox1 = vbox.copy();
|
||||||
|
vbox2 = vbox.copy();
|
||||||
|
left = i - vbox[dim1];
|
||||||
|
right = vbox[dim2] - i;
|
||||||
|
if (left <= right)
|
||||||
|
d2 = Math.min(vbox[dim2] - 1, ~~(i + right / 2));
|
||||||
|
else d2 = Math.max(vbox[dim1], ~~(i - 1 - left / 2));
|
||||||
|
// avoid 0-count boxes
|
||||||
|
while (!partialsum[d2]) d2++;
|
||||||
|
count2 = lookaheadsum[d2];
|
||||||
|
while (!count2 && partialsum[d2-1]) count2 = lookaheadsum[--d2];
|
||||||
|
// set dimensions
|
||||||
|
vbox1[dim2] = d2;
|
||||||
|
vbox2[dim1] = vbox1[dim2] + 1;
|
||||||
|
// console.log('vbox counts:', vbox.count(), vbox1.count(), vbox2.count());
|
||||||
|
return [vbox1, vbox2];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
// determine the cut planes
|
||||||
|
return maxw == rw ? doCut('r') :
|
||||||
|
maxw == gw ? doCut('g') :
|
||||||
|
doCut('b');
|
||||||
|
}
|
||||||
|
|
||||||
|
function quantize(pixels, maxcolors) {
|
||||||
|
maxcolors++;
|
||||||
|
if (!pixels.length || maxcolors < 2 || maxcolors > 256) {return false;}
|
||||||
|
|
||||||
|
// XXX: check color content and convert to grayscale if insufficient
|
||||||
|
var histo = getHisto(pixels),
|
||||||
|
histosize = 1 << (3 * sigbits);
|
||||||
|
|
||||||
|
// check that we aren't below maxcolors already
|
||||||
|
var nColors = 0;
|
||||||
|
histo.forEach(function() { nColors++; });
|
||||||
|
if (nColors <= maxcolors) {
|
||||||
|
// XXX: generate the new colors from the histo and return
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the beginning vbox from the colors
|
||||||
|
var vbox = vboxFromPixels(pixels, histo),
|
||||||
|
pq = new PQueue(function(a,b) { return pv.naturalOrder(a.count(), b.count()); });
|
||||||
|
pq.push(vbox);
|
||||||
|
|
||||||
|
// inner function to do the iteration
|
||||||
|
function iter(lh, target) {
|
||||||
|
var ncolors = 1,
|
||||||
|
niters = 0,
|
||||||
|
vbox;
|
||||||
|
while (niters < maxIterations) {
|
||||||
|
vbox = lh.pop();
|
||||||
|
if (!vbox.count()) { /* just put it back */
|
||||||
|
lh.push(vbox);
|
||||||
|
niters++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// do the cut
|
||||||
|
var vboxes = medianCutApply(histo, vbox),
|
||||||
|
vbox1 = vboxes[0],
|
||||||
|
vbox2 = vboxes[1];
|
||||||
|
|
||||||
|
if (!vbox1) {
|
||||||
|
// console.log("vbox1 not defined; shouldn't happen!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
lh.push(vbox1);
|
||||||
|
if (vbox2) { /* vbox2 can be null */
|
||||||
|
lh.push(vbox2);
|
||||||
|
ncolors++;
|
||||||
|
}
|
||||||
|
if (ncolors >= target) return;
|
||||||
|
if (niters++ > maxIterations) {
|
||||||
|
// console.log("infinite loop; perhaps too few pixels!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// first set of colors, sorted by population
|
||||||
|
iter(pq, fractByPopulations * maxcolors);
|
||||||
|
|
||||||
|
// Re-sort by the product of pixel occupancy times the size in color space.
|
||||||
|
var pq2 = new PQueue(function(a,b) {
|
||||||
|
return pv.naturalOrder(a.count()*a.volume(), b.count()*b.volume());
|
||||||
|
});
|
||||||
|
while (pq.size()) {
|
||||||
|
pq2.push(pq.pop());
|
||||||
|
}
|
||||||
|
|
||||||
|
// next set - generate the median cuts using the (npix * vol) sorting.
|
||||||
|
iter(pq2, maxcolors - pq2.size());
|
||||||
|
|
||||||
|
// calculate the actual colors
|
||||||
|
var cmap = new CMap();
|
||||||
|
while (pq2.size()) {cmap.push(pq2.pop());}
|
||||||
|
|
||||||
|
return cmap;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
quantize: quantize
|
||||||
|
};
|
||||||
|
})();
|
||||||
1
vue/public/libs/quantize.min.js
vendored
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
if(!pv)var pv={map:function(r,n){var o={};return n?r.map(function(r,t){return o.index=t,n.call(o,r)}):r.slice()},naturalOrder:function(r,n){return r<n?-1:r>n?1:0},sum:function(r,n){var o={};return r.reduce(n?function(r,t,u){return o.index=u,r+n.call(o,t)}:function(r,n){return r+n},0)},max:function(r,n){return Math.max.apply(null,n?pv.map(r,n):r)}};var MMCQ=function(){var r=5,n=8-r,o=1e3,t=.75;function u(n,o,t){return(n<<2*r)+(o<<r)+t}function e(r){var n=[],o=!1;function t(){n.sort(r),o=!0}return{push:function(r){n.push(r),o=!1},peek:function(r){return o||t(),void 0===r&&(r=n.length-1),n[r]},pop:function(){return o||t(),n.pop()},size:function(){return n.length},map:function(r){return n.map(r)},debug:function(){return o||t(),n}}}function i(r,n,o,t,u,e,i){var c=this;c.r1=r,c.r2=n,c.g1=o,c.g2=t,c.b1=u,c.b2=e,c.histo=i}function c(){this.vboxes=new e(function(r,n){return pv.naturalOrder(r.vbox.count()*r.vbox.volume(),n.vbox.count()*n.vbox.volume())})}function f(r,n){if(n.count()){var o=n.r2-n.r1+1,t=n.g2-n.g1+1,e=n.b2-n.b1+1,i=pv.max([o,t,e]);if(1==n.count())return[n.copy()];var c,f,a,v,s=0,p=[],l=[];if(i==o)for(c=n.r1;c<=n.r2;c++){for(v=0,f=n.g1;f<=n.g2;f++)for(a=n.b1;a<=n.b2;a++)v+=r[u(c,f,a)]||0;s+=v,p[c]=s}else if(i==t)for(c=n.g1;c<=n.g2;c++){for(v=0,f=n.r1;f<=n.r2;f++)for(a=n.b1;a<=n.b2;a++)v+=r[u(f,c,a)]||0;s+=v,p[c]=s}else for(c=n.b1;c<=n.b2;c++){for(v=0,f=n.r1;f<=n.r2;f++)for(a=n.g1;a<=n.g2;a++)v+=r[u(f,a,c)]||0;s+=v,p[c]=s}return p.forEach(function(r,n){l[n]=s-r}),h(i==o?"r":i==t?"g":"b")}function h(r){var o,t,u,e,i,f=r+"1",a=r+"2",v=0;for(c=n[f];c<=n[a];c++)if(p[c]>s/2){for(u=n.copy(),e=n.copy(),i=(o=c-n[f])<=(t=n[a]-c)?Math.min(n[a]-1,~~(c+t/2)):Math.max(n[f],~~(c-1-o/2));!p[i];)i++;for(v=l[i];!v&&p[i-1];)v=l[--i];return u[a]=i,e[f]=u[a]+1,[u,e]}}}return i.prototype={volume:function(r){var n=this;return n._volume&&!r||(n._volume=(n.r2-n.r1+1)*(n.g2-n.g1+1)*(n.b2-n.b1+1)),n._volume},count:function(r){var n=this,o=n.histo;if(!n._count_set||r){var t,e,i,c=0;for(t=n.r1;t<=n.r2;t++)for(e=n.g1;e<=n.g2;e++)for(i=n.b1;i<=n.b2;i++)c+=o[u(t,e,i)]||0;n._count=c,n._count_set=!0}return n._count},copy:function(){var r=this;return new i(r.r1,r.r2,r.g1,r.g2,r.b1,r.b2,r.histo)},avg:function(n){var o=this,t=o.histo;if(!o._avg||n){var e,i,c,f,a=0,v=1<<8-r,s=0,p=0,l=0;for(i=o.r1;i<=o.r2;i++)for(c=o.g1;c<=o.g2;c++)for(f=o.b1;f<=o.b2;f++)a+=e=t[u(i,c,f)]||0,s+=e*(i+.5)*v,p+=e*(c+.5)*v,l+=e*(f+.5)*v;o._avg=a?[~~(s/a),~~(p/a),~~(l/a)]:[~~(v*(o.r1+o.r2+1)/2),~~(v*(o.g1+o.g2+1)/2),~~(v*(o.b1+o.b2+1)/2)]}return o._avg},contains:function(r){var o=this,t=r[0]>>n;return gval=r[1]>>n,bval=r[2]>>n,t>=o.r1&&t<=o.r2&&gval>=o.g1&&gval<=o.g2&&bval>=o.b1&&bval<=o.b2}},c.prototype={push:function(r){this.vboxes.push({vbox:r,color:r.avg()})},palette:function(){return this.vboxes.map(function(r){return r.color})},size:function(){return this.vboxes.size()},map:function(r){for(var n=this.vboxes,o=0;o<n.size();o++)if(n.peek(o).vbox.contains(r))return n.peek(o).color;return this.nearest(r)},nearest:function(r){for(var n,o,t,u=this.vboxes,e=0;e<u.size();e++)((o=Math.sqrt(Math.pow(r[0]-u.peek(e).color[0],2)+Math.pow(r[1]-u.peek(e).color[1],2)+Math.pow(r[2]-u.peek(e).color[2],2)))<n||void 0===n)&&(n=o,t=u.peek(e).color);return t},forcebw:function(){var r=this.vboxes;r.sort(function(r,n){return pv.naturalOrder(pv.sum(r.color),pv.sum(n.color))});var n=r[0].color;n[0]<5&&n[1]<5&&n[2]<5&&(r[0].color=[0,0,0]);var o=r.length-1,t=r[o].color;t[0]>251&&t[1]>251&&t[2]>251&&(r[o].color=[255,255,255])}},{quantize:function(a,v){if(v++,!a.length||v<2||v>256)return!1;var s,p,l,h,b,g,m=(s=a,g=new Array(1<<3*r),s.forEach(function(r){l=r[0]>>n,h=r[1]>>n,b=r[2]>>n,p=u(l,h,b),g[p]=(g[p]||0)+1}),g);m.forEach(function(){});var x,_,d,w,z,M,y,k,O,E,q=(x=m,z=1e6,M=0,y=1e6,k=0,O=1e6,E=0,a.forEach(function(r){_=r[0]>>n,d=r[1]>>n,w=r[2]>>n,_<z?z=_:_>M&&(M=_),d<y?y=d:d>k&&(k=d),w<O?O=w:w>E&&(E=w)}),new i(z,M,y,k,O,E,x)),A=new e(function(r,n){return pv.naturalOrder(r.count(),n.count())});function C(r,n){for(var t,u=1,e=0;e<o;)if((t=r.pop()).count()){var i=f(m,t),c=i[0],a=i[1];if(!c)return;if(r.push(c),a&&(r.push(a),u++),u>=n)return;if(e++>o)return}else r.push(t),e++}A.push(q),C(A,t*v);for(var Q=new e(function(r,n){return pv.naturalOrder(r.count()*r.volume(),n.count()*n.volume())});A.size();)Q.push(A.pop());C(Q,v-Q.size());for(var j=new c;Q.size();)j.push(Q.pop());return j}}}();
|
||||||
1
vue/public/libs/seedrandom.min.js
vendored
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
!function(a,b){var l,c=eval("this"),d=256,g="random",h=b.pow(d,6),i=b.pow(2,52),j=2*i,k=d-1;function m(r,t,e){var u=[],f=q(function n(r,t){var e,o=[],i=typeof r;if(t&&"object"==i)for(e in r)try{o.push(n(r[e],t-1))}catch(n){}return o.length?o:"string"==i?r:r+"\0"}((t=1==t?{entropy:!0}:t||{}).entropy?[r,s(a)]:null==r?function(){try{var n;return l&&(n=l.randomBytes)?n=n(d):(n=new Uint8Array(d),(c.crypto||c.msCrypto).getRandomValues(n)),s(n)}catch(n){var r=c.navigator,t=r&&r.plugins;return[+new Date,c,t,c.screen,s(a)]}}():r,3),u),p=new n(u),m=function(){for(var n=p.g(6),r=h,t=0;n<i;)n=(n+t)*d,r*=d,t=p.g(1);for(;j<=n;)n/=2,r/=2,t>>>=1;return(n+t)/r};return m.int32=function(){return 0|p.g(4)},m.quick=function(){return p.g(4)/4294967296},m.double=m,q(s(p.S),a),(t.pass||e||function(n,r,t,e){return e&&(e.S&&o(e,p),n.state=function(){return o(p,{})}),t?(b[g]=n,r):n})(m,f,"global"in t?t.global:this==b,t.state)}function n(n){var r,t=n.length,u=this,e=0,o=u.i=u.j=0,i=u.S=[];for(t||(n=[t++]);e<d;)i[e]=e++;for(e=0;e<d;e++)i[e]=i[o=k&o+n[e%t]+(r=i[e])],i[o]=r;(u.g=function(n){for(var r,t=0,e=u.i,o=u.j,i=u.S;n--;)r=i[e=k&e+1],t=t*d+i[k&(i[e]=i[o=k&o+r])+(i[o]=r)];return u.i=e,u.j=o,t})(d)}function o(n,r){return r.i=n.i,r.j=n.j,r.S=n.S.slice(),r}function q(n,r){for(var t,e=n+"",o=0;o<e.length;)r[k&o]=k&(t^=19*r[k&o])+e.charCodeAt(o++);return s(r)}function s(n){return String.fromCharCode.apply(0,n)}if(b["seed"+g]=m,q(b.random(),a),"object"==typeof module&&module.exports){module.exports=m;try{l=require("crypto")}catch(n){}}else"function"==typeof define&&define.amd&&define(function(){return m})}([],Math);
|
||||||
9424
vue/public/refactor-four.js
Normal file
957
vue/public/refactor-main.js
Normal file
2091
vue/public/refactor-one.js
Normal file
3763
vue/public/refactor-three.js
Normal file
997
vue/public/refactor-two.js
Normal file
|
|
@ -0,0 +1,997 @@
|
||||||
|
function addRoutePoint(point) {
|
||||||
|
const controlPoints = debug.select(".controlPoints").size()
|
||||||
|
? debug.select(".controlPoints")
|
||||||
|
: debug.append("g").attr("class", "controlPoints");
|
||||||
|
controlPoints.append("circle")
|
||||||
|
.attr("cx", point.x).attr("cy", point.y).attr("r", 0.35)
|
||||||
|
.call(d3.drag().on("drag", routePointDrag))
|
||||||
|
.on("click", function(d) {
|
||||||
|
if ($("#routeSplit").hasClass('pressed')) {
|
||||||
|
routeSplitInPoint(this);
|
||||||
|
} else {
|
||||||
|
$(this).remove();
|
||||||
|
routeRedraw();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function routePointDrag() {
|
||||||
|
d3.select(this).attr("cx", d3.event.x).attr("cy", d3.event.y);
|
||||||
|
routeRedraw();
|
||||||
|
}
|
||||||
|
|
||||||
|
function routeRedraw() {
|
||||||
|
let points = [];
|
||||||
|
debug.select(".controlPoints").selectAll("circle").each(function() {
|
||||||
|
const el = d3.select(this);
|
||||||
|
points.push({scX: +el.attr("cx"), scY: +el.attr("cy")});
|
||||||
|
});
|
||||||
|
lineGen.curve(d3.curveCatmullRom.alpha(0.1));
|
||||||
|
elSelected.attr("d", lineGen(points));
|
||||||
|
// get route distance
|
||||||
|
const l = elSelected.node().getTotalLength();
|
||||||
|
routeLength.innerHTML = rn(l * distanceScale.value) + " " + distanceUnit.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
function addNewRoute() {
|
||||||
|
let routeType = elSelected && elSelected.node() ? elSelected.node().parentNode.id : "searoutes";
|
||||||
|
const group = routes.select("#"+routeType);
|
||||||
|
const id = routeType + "" + group.selectAll("*").size();
|
||||||
|
elSelected = group.append("path").attr("data-route", "new").attr("id", id).on("click", editRoute);
|
||||||
|
routeUpdateGroups();
|
||||||
|
$("#routeEditor").dialog({
|
||||||
|
title: "Edit Route", minHeight: 30, width: "auto", resizable: false,
|
||||||
|
close: function() {
|
||||||
|
if ($("#addRoute").hasClass('pressed')) completeNewRoute();
|
||||||
|
if ($("#routeSplit").hasClass('pressed')) $("#routeSplit").removeClass('pressed');
|
||||||
|
unselect();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function newRouteAddPoint() {
|
||||||
|
const point = d3.mouse(this);
|
||||||
|
const x = rn(point[0],2), y = rn(point[1],2);
|
||||||
|
addRoutePoint({x, y});
|
||||||
|
routeRedraw();
|
||||||
|
}
|
||||||
|
|
||||||
|
function completeNewRoute() {
|
||||||
|
$("#routeNew, #addRoute").removeClass('pressed');
|
||||||
|
restoreDefaultEvents();
|
||||||
|
if (!elSelected.size()) return;
|
||||||
|
if (elSelected.attr("data-route") === "new") {
|
||||||
|
routeRedraw();
|
||||||
|
elSelected.attr("data-route", "");
|
||||||
|
const node = elSelected.node();
|
||||||
|
const l = node.getTotalLength();
|
||||||
|
let pathCells = [];
|
||||||
|
for (let i = 0; i <= l; i ++) {
|
||||||
|
const p = node.getPointAtLength(i);
|
||||||
|
const cell = diagram.find(p.x, p.y);
|
||||||
|
if (!cell) {return;}
|
||||||
|
pathCells.push(cell.index);
|
||||||
|
}
|
||||||
|
const uniqueCells = [...new Set(pathCells)];
|
||||||
|
uniqueCells.map(function(c) {
|
||||||
|
if (cells[c].path !== undefined) {cells[c].path += 1;}
|
||||||
|
else {cells[c].path = 1;}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
tip("", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
function routeUpdateGroups() {
|
||||||
|
routeGroup.innerHTML = "";
|
||||||
|
routes.selectAll("g").each(function() {
|
||||||
|
const opt = document.createElement("option");
|
||||||
|
opt.value = opt.innerHTML = this.id;
|
||||||
|
routeGroup.add(opt);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function routeSplitInPoint(clicked) {
|
||||||
|
const group = d3.select(elSelected.node().parentNode);
|
||||||
|
$("#routeSplit").removeClass('pressed');
|
||||||
|
const points1 = [],points2 = [];
|
||||||
|
let points = points1;
|
||||||
|
debug.select(".controlPoints").selectAll("circle").each(function() {
|
||||||
|
const el = d3.select(this);
|
||||||
|
points.push({scX: +el.attr("cx"), scY: +el.attr("cy")});
|
||||||
|
if (this === clicked) {
|
||||||
|
points = points2;
|
||||||
|
points.push({scX: +el.attr("cx"), scY: +el.attr("cy")});
|
||||||
|
}
|
||||||
|
el.remove();
|
||||||
|
});
|
||||||
|
lineGen.curve(d3.curveCatmullRom.alpha(0.1));
|
||||||
|
elSelected.attr("d", lineGen(points1));
|
||||||
|
const id = routeGroup.value + "" + group.selectAll("*").size();
|
||||||
|
group.append("path").attr("id", id).attr("d", lineGen(points2)).on("click", editRoute);
|
||||||
|
routeDrawPoints();
|
||||||
|
}
|
||||||
|
|
||||||
|
$("#routeGroup").change(function() {
|
||||||
|
$(elSelected.node()).detach().appendTo($("#"+this.value));
|
||||||
|
});
|
||||||
|
|
||||||
|
// open legendsEditor
|
||||||
|
document.getElementById("routeLegend").addEventListener("click", function() {
|
||||||
|
let id = elSelected.attr("id");
|
||||||
|
editLegends(id, id);
|
||||||
|
});
|
||||||
|
|
||||||
|
$("#routeNew").click(function() {
|
||||||
|
if ($(this).hasClass('pressed')) {
|
||||||
|
completeNewRoute();
|
||||||
|
} else {
|
||||||
|
// enter creation mode
|
||||||
|
$(".pressed").removeClass('pressed');
|
||||||
|
$("#routeNew, #addRoute").addClass('pressed');
|
||||||
|
debug.select(".controlPoints").selectAll("*").remove();
|
||||||
|
addNewRoute();
|
||||||
|
viewbox.style("cursor", "crosshair").on("click", newRouteAddPoint);
|
||||||
|
tip("Click on map to add route point", true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$("#routeRemove").click(function() {
|
||||||
|
alertMessage.innerHTML = `Are you sure you want to remove the route?`;
|
||||||
|
$("#alert").dialog({resizable: false, title: "Remove route",
|
||||||
|
buttons: {
|
||||||
|
Remove: function() {
|
||||||
|
$(this).dialog("close");
|
||||||
|
elSelected.remove();
|
||||||
|
$("#routeEditor").dialog("close");
|
||||||
|
},
|
||||||
|
Cancel: function() {$(this).dialog("close");}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function editIcon() {
|
||||||
|
if (customization) return;
|
||||||
|
if (elSelected) if (this.isSameNode(elSelected.node())) return;
|
||||||
|
|
||||||
|
unselect();
|
||||||
|
closeDialogs("#iconEditor, .stable");
|
||||||
|
elSelected = d3.select(this).call(d3.drag().on("start", elementDrag)).classed("draggable", true);
|
||||||
|
|
||||||
|
// update group parameters
|
||||||
|
const group = d3.select(this.parentNode);
|
||||||
|
iconUpdateGroups();
|
||||||
|
iconGroup.value = group.attr("id");
|
||||||
|
iconFillColor.value = group.attr("fill");
|
||||||
|
iconStrokeColor.value = group.attr("stroke");
|
||||||
|
iconSize.value = group.attr("size");
|
||||||
|
iconStrokeWidth.value = group.attr("stroke-width");
|
||||||
|
|
||||||
|
$("#iconEditor").dialog({
|
||||||
|
title: "Edit icon: " + group.attr("id"),
|
||||||
|
minHeight: 30, width: "auto", resizable: false,
|
||||||
|
position: {my: "center top+20", at: "top", of: d3.event},
|
||||||
|
close: unselect
|
||||||
|
});
|
||||||
|
|
||||||
|
if (modules.editIcon) {return;}
|
||||||
|
modules.editIcon = true;
|
||||||
|
|
||||||
|
$("#iconGroups").click(function() {
|
||||||
|
$("#iconEditor > button").not(this).toggle();
|
||||||
|
$("#iconGroupsSelection").toggle();
|
||||||
|
});
|
||||||
|
|
||||||
|
function iconUpdateGroups() {
|
||||||
|
iconGroup.innerHTML = "";
|
||||||
|
const anchor = group.attr("id").includes("anchor");
|
||||||
|
icons.selectAll("g").each(function(d) {
|
||||||
|
const id = d3.select(this).attr("id");
|
||||||
|
if (id === "burgs") return;
|
||||||
|
if (!anchor && id.includes("anchor")) return;
|
||||||
|
if (anchor && !id.includes("anchor")) return;
|
||||||
|
const opt = document.createElement("option");
|
||||||
|
opt.value = opt.innerHTML = id;
|
||||||
|
iconGroup.add(opt);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
$("#iconGroup").change(function() {
|
||||||
|
const newGroup = this.value;
|
||||||
|
const to = $("#icons > #"+newGroup);
|
||||||
|
$(elSelected.node()).detach().appendTo(to);
|
||||||
|
});
|
||||||
|
|
||||||
|
$("#iconCopy").click(function() {
|
||||||
|
const group = d3.select(elSelected.node().parentNode);
|
||||||
|
const copy = elSelected.node().cloneNode();
|
||||||
|
copy.removeAttribute("data-id"); // remove assignment to burg if any
|
||||||
|
const tr = parseTransform(copy.getAttribute("transform"));
|
||||||
|
const shift = 10 / Math.sqrt(scale);
|
||||||
|
let transform = "translate(" + rn(tr[0] - shift, 1) + "," + rn(tr[1] - shift, 1) + ")";
|
||||||
|
for (let i=2; group.selectAll("[transform='" + transform + "']").size() > 0; i++) {
|
||||||
|
transform = "translate(" + rn(tr[0] - shift * i, 1) + "," + rn(tr[1] - shift * i, 1) + ")";
|
||||||
|
}
|
||||||
|
copy.setAttribute("transform", transform);
|
||||||
|
group.node().insertBefore(copy, null);
|
||||||
|
copy.addEventListener("click", editIcon);
|
||||||
|
});
|
||||||
|
|
||||||
|
$("#iconRemoveGroup").click(function() {
|
||||||
|
const group = d3.select(elSelected.node().parentNode);
|
||||||
|
const count = group.selectAll("*").size();
|
||||||
|
if (count < 2) {
|
||||||
|
group.remove();
|
||||||
|
$("#labelEditor").dialog("close");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const message = "Are you sure you want to remove all '" + iconGroup.value + "' icons (" + count + ")?";
|
||||||
|
alertMessage.innerHTML = message;
|
||||||
|
$("#alert").dialog({resizable: false, title: "Remove icon group",
|
||||||
|
buttons: {
|
||||||
|
Remove: function() {
|
||||||
|
$(this).dialog("close");
|
||||||
|
group.remove();
|
||||||
|
$("#iconEditor").dialog("close");
|
||||||
|
},
|
||||||
|
Cancel: function() {$(this).dialog("close");}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
$("#iconColors").click(function() {
|
||||||
|
$("#iconEditor > button").not(this).toggle();
|
||||||
|
$("#iconColorsSection").toggle();
|
||||||
|
});
|
||||||
|
|
||||||
|
$("#iconFillColor").change(function() {
|
||||||
|
const group = d3.select(elSelected.node().parentNode);
|
||||||
|
group.attr("fill", this.value);
|
||||||
|
});
|
||||||
|
|
||||||
|
$("#iconStrokeColor").change(function() {
|
||||||
|
const group = d3.select(elSelected.node().parentNode);
|
||||||
|
group.attr("stroke", this.value);
|
||||||
|
});
|
||||||
|
|
||||||
|
$("#iconSetSize").click(function() {
|
||||||
|
$("#iconEditor > button").not(this).toggle();
|
||||||
|
$("#iconSizeSection").toggle();
|
||||||
|
});
|
||||||
|
|
||||||
|
$("#iconSize").change(function() {
|
||||||
|
const group = d3.select(elSelected.node().parentNode);
|
||||||
|
const size = +this.value;
|
||||||
|
group.attr("size", size);
|
||||||
|
group.selectAll("*").each(function() {d3.select(this).attr("width", size).attr("height", size)});
|
||||||
|
});
|
||||||
|
|
||||||
|
$("#iconStrokeWidth").change(function() {
|
||||||
|
const group = d3.select(elSelected.node().parentNode);
|
||||||
|
group.attr("stroke-width", this.value);
|
||||||
|
});
|
||||||
|
|
||||||
|
$("#iconRemove").click(function() {
|
||||||
|
alertMessage.innerHTML = `Are you sure you want to remove the icon?`;
|
||||||
|
$("#alert").dialog({resizable: false, title: "Remove icon",
|
||||||
|
buttons: {
|
||||||
|
Remove: function() {
|
||||||
|
$(this).dialog("close");
|
||||||
|
elSelected.remove();
|
||||||
|
$("#iconEditor").dialog("close");
|
||||||
|
},
|
||||||
|
Cancel: function() {$(this).dialog("close");}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function editReliefIcon() {
|
||||||
|
if (customization) return;
|
||||||
|
if (elSelected) if (this.isSameNode(elSelected.node())) return;
|
||||||
|
|
||||||
|
unselect();
|
||||||
|
closeDialogs("#reliefEditor, .stable");
|
||||||
|
elSelected = d3.select(this).raise().call(d3.drag().on("start", elementDrag)).classed("draggable", true);
|
||||||
|
const group = elSelected.node().parentNode.id;
|
||||||
|
reliefGroup.value = group;
|
||||||
|
|
||||||
|
let bulkRemoveSection = document.getElementById("reliefBulkRemoveSection");
|
||||||
|
if (bulkRemoveSection.style.display != "none") reliefBulkRemove.click();
|
||||||
|
|
||||||
|
$("#reliefEditor").dialog({
|
||||||
|
title: "Edit relief icon",
|
||||||
|
minHeight: 30, width: "auto", resizable: false,
|
||||||
|
position: {my: "center top+40", at: "top", of: d3.event},
|
||||||
|
close: unselect
|
||||||
|
});
|
||||||
|
|
||||||
|
if (modules.editReliefIcon) {return;}
|
||||||
|
modules.editReliefIcon = true;
|
||||||
|
|
||||||
|
$("#reliefGroups").click(function() {
|
||||||
|
$("#reliefEditor > button").not(this).toggle();
|
||||||
|
$("#reliefGroupsSelection").toggle();
|
||||||
|
});
|
||||||
|
|
||||||
|
$("#reliefGroup").change(function() {
|
||||||
|
const type = this.value;
|
||||||
|
const bbox = elSelected.node().getBBox();
|
||||||
|
const cx = bbox.x;
|
||||||
|
const cy = bbox.y + bbox.height / 2;
|
||||||
|
const cell = diagram.find(cx, cy).index;
|
||||||
|
const height = cell !== undefined ? cells[cell].height : 50;
|
||||||
|
elSelected.remove();
|
||||||
|
elSelected = addReliefIcon(height / 100, type, cx, cy, cell);
|
||||||
|
elSelected.call(d3.drag().on("start", elementDrag));
|
||||||
|
});
|
||||||
|
|
||||||
|
$("#reliefCopy").click(function() {
|
||||||
|
const group = d3.select(elSelected.node().parentNode);
|
||||||
|
const copy = elSelected.node().cloneNode(true);
|
||||||
|
const tr = parseTransform(copy.getAttribute("transform"));
|
||||||
|
const shift = 10 / Math.sqrt(scale);
|
||||||
|
let transform = "translate(" + rn(tr[0] - shift, 1) + "," + rn(tr[1] - shift, 1) + ")";
|
||||||
|
for (let i=2; group.selectAll("[transform='" + transform + "']").size() > 0; i++) {
|
||||||
|
transform = "translate(" + rn(tr[0] - shift * i, 1) + "," + rn(tr[1] - shift * i, 1) + ")";
|
||||||
|
}
|
||||||
|
copy.setAttribute("transform", transform);
|
||||||
|
group.node().insertBefore(copy, null);
|
||||||
|
copy.addEventListener("click", editReliefIcon);
|
||||||
|
});
|
||||||
|
|
||||||
|
$("#reliefAddfromEditor").click(function() {
|
||||||
|
clickToAdd(); // to load on click event function
|
||||||
|
$("#addRelief").click();
|
||||||
|
});
|
||||||
|
|
||||||
|
$("#reliefRemoveGroup").click(function() {
|
||||||
|
const group = d3.select(elSelected.node().parentNode);
|
||||||
|
const count = group.selectAll("*").size();
|
||||||
|
if (count < 2) {
|
||||||
|
group.selectAll("*").remove();
|
||||||
|
$("#labelEditor").dialog("close");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const message = "Are you sure you want to remove all '" + reliefGroup.value + "' icons (" + count + ")?";
|
||||||
|
alertMessage.innerHTML = message;
|
||||||
|
$("#alert").dialog({resizable: false, title: "Remove all icons within group",
|
||||||
|
buttons: {
|
||||||
|
Remove: function() {
|
||||||
|
$(this).dialog("close");
|
||||||
|
group.selectAll("*").remove();
|
||||||
|
$("#reliefEditor").dialog("close");
|
||||||
|
},
|
||||||
|
Cancel: function() {$(this).dialog("close");}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
$("#reliefBulkRemove").click(function() {
|
||||||
|
$("#reliefEditor > button").not(this).toggle();
|
||||||
|
let section = document.getElementById("reliefBulkRemoveSection");
|
||||||
|
if (section.style.display === "none") {
|
||||||
|
section.style.display = "inline-block";
|
||||||
|
tip("Drag to remove relief icons in radius", true);
|
||||||
|
viewbox.style("cursor", "crosshair").call(d3.drag().on("drag", dragToRemoveReliefIcons));
|
||||||
|
customization = 5;
|
||||||
|
} else {
|
||||||
|
section.style.display = "none";
|
||||||
|
restoreDefaultEvents();
|
||||||
|
customization = 0;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
function dragToRemoveReliefIcons() {
|
||||||
|
let point = d3.mouse(this);
|
||||||
|
let cell = diagram.find(point[0], point[1]).index;
|
||||||
|
let radius = +reliefBulkRemoveRadius.value;
|
||||||
|
let r = rn(6 / graphSize * radius, 1);
|
||||||
|
moveCircle(point[0], point[1], r);
|
||||||
|
let selection = defineBrushSelection(cell, radius);
|
||||||
|
if (selection) removeReliefIcons(selection);
|
||||||
|
}
|
||||||
|
|
||||||
|
function removeReliefIcons(selection) {
|
||||||
|
if (selection.length === 0) return;
|
||||||
|
selection.map(function(index) {
|
||||||
|
const selected = terrain.selectAll("g").selectAll("g[data-cell='"+index+"']");
|
||||||
|
selected.remove();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
$("#reliefRemove").click(function() {
|
||||||
|
alertMessage.innerHTML = `Are you sure you want to remove the icon?`;
|
||||||
|
$("#alert").dialog({resizable: false, title: "Remove relief icon",
|
||||||
|
buttons: {
|
||||||
|
Remove: function() {
|
||||||
|
$(this).dialog("close");
|
||||||
|
elSelected.remove();
|
||||||
|
$("#reliefEditor").dialog("close");
|
||||||
|
},
|
||||||
|
Cancel: function() {$(this).dialog("close");}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function editBurg() {
|
||||||
|
if (customization) return;
|
||||||
|
unselect();
|
||||||
|
closeDialogs("#burgEditor, .stable");
|
||||||
|
elSelected = d3.select(this);
|
||||||
|
const id = +elSelected.attr("data-id");
|
||||||
|
if (id === undefined) return;
|
||||||
|
d3.selectAll("[data-id='" + id + "']").call(d3.drag().on("start", elementDrag)).classed("draggable", true);
|
||||||
|
|
||||||
|
// update Burg details
|
||||||
|
const type = elSelected.node().parentNode.id;
|
||||||
|
const labelGroup = burgLabels.select("#"+type);
|
||||||
|
const iconGroup = burgIcons.select("#"+type);
|
||||||
|
burgNameInput.value = manors[id].name;
|
||||||
|
updateBurgsGroupOptions();
|
||||||
|
burgSelectGroup.value = labelGroup.attr("id");
|
||||||
|
burgSelectDefaultFont.value = fonts.indexOf(labelGroup.attr("data-font"));
|
||||||
|
burgSetLabelSize.value = labelGroup.attr("data-size");
|
||||||
|
burgLabelColorInput.value = toHEX(labelGroup.attr("fill"));
|
||||||
|
burgLabelOpacity.value = labelGroup.attr("opacity") === undefined ? 1 : +labelGroup.attr("opacity");
|
||||||
|
const tr = parseTransform(elSelected.attr("transform"));
|
||||||
|
burgLabelAngle.value = tr[2];
|
||||||
|
burgLabelAngleOutput.innerHTML = Math.abs(+tr[2]) + "°";
|
||||||
|
burgIconSize.value = iconGroup.attr("size");
|
||||||
|
burgIconFillOpacity.value = iconGroup.attr("fill-opacity") === undefined ? 1 : +iconGroup.attr("fill-opacity");
|
||||||
|
burgIconFillColor.value = iconGroup.attr("fill");
|
||||||
|
burgIconStrokeWidth.value = iconGroup.attr("stroke-width");
|
||||||
|
burgIconStrokeOpacity.value = iconGroup.attr("stroke-opacity") === undefined ? 1 : +iconGroup.attr("stroke-opacity");
|
||||||
|
burgIconStrokeColor.value = iconGroup.attr("stroke");
|
||||||
|
const cell = cells[manors[id].cell];
|
||||||
|
if (cell.region !== "neutral" && cell.region !== undefined) {
|
||||||
|
burgToggleCapital.disabled = false;
|
||||||
|
const capital = states[manors[id].region] ? id === states[manors[id].region].capital ? 1 : 0 : 0;
|
||||||
|
d3.select("#burgToggleCapital").classed("pressed", capital);
|
||||||
|
} else {
|
||||||
|
burgToggleCapital.disabled = true;
|
||||||
|
d3.select("#burgToggleCapital").classed("pressed", false);
|
||||||
|
}
|
||||||
|
d3.select("#burgTogglePort").classed("pressed", cell.port !== undefined);
|
||||||
|
burgPopulation.value = manors[id].population;
|
||||||
|
burgPopulationFriendly.value = rn(manors[id].population * urbanization.value * populationRate.value * 1000);
|
||||||
|
|
||||||
|
$("#burgEditor").dialog({
|
||||||
|
title: "Edit Burg: " + manors[id].name,
|
||||||
|
minHeight: 30, width: "auto", resizable: false,
|
||||||
|
position: {my: "center top+40", at: "top", of: d3.event},
|
||||||
|
close: function() {
|
||||||
|
d3.selectAll("[data-id='" + id + "']").call(d3.drag().on("drag", null)).classed("draggable", false);
|
||||||
|
elSelected = null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (modules.editBurg) return;
|
||||||
|
modules.editBurg = true;
|
||||||
|
|
||||||
|
loadDefaultFonts();
|
||||||
|
|
||||||
|
function updateBurgsGroupOptions() {
|
||||||
|
burgSelectGroup.innerHTML = "";
|
||||||
|
burgIcons.selectAll("g").each(function(d) {
|
||||||
|
const opt = document.createElement("option");
|
||||||
|
opt.value = opt.innerHTML = d3.select(this).attr("id");
|
||||||
|
burgSelectGroup.add(opt);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
$("#burgEditor > button").not("#burgAddfromEditor").not("#burgRelocate").not("#burgRemove").click(function() {
|
||||||
|
if ($(this).next().is(":visible")) {
|
||||||
|
$("#burgEditor > button").show();
|
||||||
|
$(this).next("div").hide();
|
||||||
|
} else {
|
||||||
|
$("#burgEditor > *").not(this).hide();
|
||||||
|
$(this).next("div").show();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$("#burgEditor > div > button").click(function() {
|
||||||
|
if ($(this).next().is(":visible")) {
|
||||||
|
$("#burgEditor > div > button").show();
|
||||||
|
$(this).parent().prev().show();
|
||||||
|
$(this).next("div").hide();
|
||||||
|
} else {
|
||||||
|
$("#burgEditor > div > button").not(this).hide();
|
||||||
|
$(this).parent().prev().hide();
|
||||||
|
$(this).next("div").show();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$("#burgSelectGroup").change(function() {
|
||||||
|
const id = +elSelected.attr("data-id");
|
||||||
|
const g = this.value;
|
||||||
|
moveBurgToGroup(id, g);
|
||||||
|
});
|
||||||
|
|
||||||
|
$("#burgInputGroup").change(function() {
|
||||||
|
let newGroup = this.value.toLowerCase().replace(/ /g, "_").replace(/[^\w\s]/gi, "");
|
||||||
|
if (Number.isFinite(+newGroup.charAt(0))) newGroup = "g" + newGroup;
|
||||||
|
if (burgLabels.select("#"+newGroup).size()) {
|
||||||
|
tip('The group "'+ newGroup + '" is already exists');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
burgInputGroup.value = "";
|
||||||
|
// clone old group assigning new id
|
||||||
|
const id = elSelected.node().parentNode.id;
|
||||||
|
const l = burgLabels.select("#"+id).node().cloneNode(false);
|
||||||
|
l.id = newGroup;
|
||||||
|
const i = burgIcons.select("#"+id).node().cloneNode(false);
|
||||||
|
i.id = newGroup;
|
||||||
|
burgLabels.node().insertBefore(l, null);
|
||||||
|
burgIcons.node().insertBefore(i, null);
|
||||||
|
// select new group
|
||||||
|
const opt = document.createElement("option");
|
||||||
|
opt.value = opt.innerHTML = newGroup;
|
||||||
|
burgSelectGroup.add(opt);
|
||||||
|
$("#burgSelectGroup").val(newGroup).change();
|
||||||
|
$("#burgSelectGroup, #burgInputGroup").toggle();
|
||||||
|
updateLabelGroups();
|
||||||
|
});
|
||||||
|
|
||||||
|
$("#burgAddGroup").click(function() {
|
||||||
|
if ($("#burgInputGroup").css("display") === "none") {
|
||||||
|
$("#burgInputGroup").css("display", "inline-block");
|
||||||
|
$("#burgSelectGroup").css("display", "none");
|
||||||
|
burgInputGroup.focus();
|
||||||
|
} else {
|
||||||
|
$("#burgSelectGroup").css("display", "inline-block");
|
||||||
|
$("#burgInputGroup").css("display", "none");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$("#burgRemoveGroup").click(function() {
|
||||||
|
const group = d3.select(elSelected.node().parentNode);
|
||||||
|
const type = group.attr("id");
|
||||||
|
const id = +elSelected.attr("data-id");
|
||||||
|
const count = group.selectAll("*").size();
|
||||||
|
const message = "Are you sure you want to remove all Burgs (" + count + ") of that group?";
|
||||||
|
alertMessage.innerHTML = message;
|
||||||
|
$("#alert").dialog({resizable: false, title: "Remove Burgs",
|
||||||
|
buttons: {
|
||||||
|
Remove: function() {
|
||||||
|
$(this).dialog("close");
|
||||||
|
group.selectAll("*").each(function(d) {
|
||||||
|
const id = +d3.select(this).attr("data-id");
|
||||||
|
if (id === undefined) return;
|
||||||
|
const cell = manors[id].cell;
|
||||||
|
const state = manors[id].region;
|
||||||
|
if (states[state]) {
|
||||||
|
if (states[state].capital === id) states[state].capital = "select";
|
||||||
|
states[state].burgs --;
|
||||||
|
}
|
||||||
|
manors[id].region = "removed";
|
||||||
|
cells[cell].manor = undefined;
|
||||||
|
});
|
||||||
|
burgLabels.select("#"+type).selectAll("*").remove();
|
||||||
|
burgIcons.select("#"+type).selectAll("*").remove();
|
||||||
|
$("#icons g[id*='anchors'] [data-id=" + id + "]").parent().children().remove();
|
||||||
|
closeDialogs(".stable");
|
||||||
|
updateCountryEditors();
|
||||||
|
$("#burgEditor").dialog("close");
|
||||||
|
},
|
||||||
|
Cancel: function() {$(this).dialog("close");}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
$("#burgNameInput").on("input", function() {
|
||||||
|
if (this.value === "") {
|
||||||
|
tip("Name should not be blank, set opacity to 0 to hide label or remove button to delete");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const id = +elSelected.attr("data-id");
|
||||||
|
burgLabels.selectAll("[data-id='" + id + "']").text(this.value);
|
||||||
|
manors[id].name = this.value;
|
||||||
|
$("div[aria-describedby='burgEditor'] .ui-dialog-title").text("Edit Burg: " + this.value);
|
||||||
|
});
|
||||||
|
|
||||||
|
$("#burgNameReCulture, #burgNameReRandom").click(function() {
|
||||||
|
const id = +elSelected.attr("data-id");
|
||||||
|
const culture = this.id === "burgNameReCulture" ? manors[id].culture : Math.floor(Math.random() * cultures.length);
|
||||||
|
const name = generateName(culture);
|
||||||
|
burgLabels.selectAll("[data-id='" + id + "']").text(name);
|
||||||
|
manors[id].name = name;
|
||||||
|
burgNameInput.value = name;
|
||||||
|
$("div[aria-describedby='burgEditor'] .ui-dialog-title").text("Edit Burg: " + name);
|
||||||
|
});
|
||||||
|
|
||||||
|
$("#burgToggleExternalFont").click(function() {
|
||||||
|
if ($("#burgInputExternalFont").css("display") === "none") {
|
||||||
|
$("#burgInputExternalFont").css("display", "inline-block");
|
||||||
|
$("#burgSelectDefaultFont").css("display", "none");
|
||||||
|
burgInputExternalFont.focus();
|
||||||
|
} else {
|
||||||
|
$("#burgSelectDefaultFont").css("display", "inline-block");
|
||||||
|
$("#burgInputExternalFont").css("display", "none");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$("#burgSelectDefaultFont").change(function() {
|
||||||
|
const type = elSelected.node().parentNode.id;
|
||||||
|
const group = burgLabels.select("#"+type);
|
||||||
|
if (burgSelectDefaultFont.value === "") return;
|
||||||
|
const font = fonts[burgSelectDefaultFont.value].split(':')[0].replace(/\+/g, " ");
|
||||||
|
group.attr("font-family", font).attr("data-font", fonts[burgSelectDefaultFont.value]);
|
||||||
|
});
|
||||||
|
|
||||||
|
$("#burgInputExternalFont").change(function() {
|
||||||
|
fetchFonts(this.value).then(fetched => {
|
||||||
|
if (!fetched) return;
|
||||||
|
burgToggleExternalFont.click();
|
||||||
|
burgInputExternalFont.value = "";
|
||||||
|
if (fetched === 1) $("#burgSelectDefaultFont").val(fonts.length - 1).change();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
$("#burgSetLabelSize").on("input", function() {
|
||||||
|
const type = elSelected.node().parentNode.id;
|
||||||
|
const group = burgLabels.select("#"+type);
|
||||||
|
group.attr("data-size", +this.value);
|
||||||
|
invokeActiveZooming();
|
||||||
|
});
|
||||||
|
|
||||||
|
$("#burgLabelColorInput").on("input", function() {
|
||||||
|
const type = elSelected.node().parentNode.id;
|
||||||
|
const group = burgLabels.select("#"+type);
|
||||||
|
group.attr("fill", this.value);
|
||||||
|
});
|
||||||
|
|
||||||
|
$("#burgLabelOpacity").on("input", function() {
|
||||||
|
const type = elSelected.node().parentNode.id;
|
||||||
|
const group = burgLabels.select("#"+type);
|
||||||
|
group.attr("opacity", +this.value);
|
||||||
|
});
|
||||||
|
|
||||||
|
$("#burgLabelAngle").on("input", function() {
|
||||||
|
const id = +elSelected.attr("data-id");
|
||||||
|
const el = burgLabels.select("[data-id='"+ id +"']");
|
||||||
|
const tr = parseTransform(el.attr("transform"));
|
||||||
|
const c = el.node().getBBox();
|
||||||
|
burgLabelAngleOutput.innerHTML = Math.abs(+this.value) + "°";
|
||||||
|
const angle = +this.value;
|
||||||
|
const transform = `translate(${tr[0]},${tr[1]}) rotate(${angle} ${(c.x+c.width/2)} ${(c.y+c.height/2)})`;
|
||||||
|
el.attr("transform", transform);
|
||||||
|
});
|
||||||
|
|
||||||
|
$("#burgIconSize").on("input", function() {
|
||||||
|
const type = elSelected.node().parentNode.id;
|
||||||
|
const group = burgIcons.select("#"+type);
|
||||||
|
const size = +this.value;
|
||||||
|
group.attr("size", size);
|
||||||
|
group.selectAll("*").each(function() {d3.select(this).attr("r", size)});
|
||||||
|
});
|
||||||
|
|
||||||
|
$("#burgIconFillOpacity").on("input", function() {
|
||||||
|
const type = elSelected.node().parentNode.id;
|
||||||
|
const group = burgIcons.select("#"+type);
|
||||||
|
group.attr("fill-opacity", +this.value);
|
||||||
|
});
|
||||||
|
|
||||||
|
$("#burgIconFillColor").on("input", function() {
|
||||||
|
const type = elSelected.node().parentNode.id;
|
||||||
|
const group = burgIcons.select("#"+type);
|
||||||
|
group.attr("fill", this.value);
|
||||||
|
});
|
||||||
|
|
||||||
|
$("#burgIconStrokeWidth").on("input", function() {
|
||||||
|
const type = elSelected.node().parentNode.id;
|
||||||
|
const group = burgIcons.select("#"+type);
|
||||||
|
group.attr("stroke-width", +this.value);
|
||||||
|
});
|
||||||
|
|
||||||
|
$("#burgIconStrokeOpacity").on("input", function() {
|
||||||
|
const type = elSelected.node().parentNode.id;
|
||||||
|
const group = burgIcons.select("#"+type);
|
||||||
|
group.attr("stroke-opacity", +this.value);
|
||||||
|
});
|
||||||
|
|
||||||
|
$("#burgIconStrokeColor").on("input", function() {
|
||||||
|
const type = elSelected.node().parentNode.id;
|
||||||
|
const group = burgIcons.select("#"+type);
|
||||||
|
group.attr("stroke", this.value);
|
||||||
|
});
|
||||||
|
|
||||||
|
$("#burgToggleCapital").click(function() {
|
||||||
|
const id = +elSelected.attr("data-id");
|
||||||
|
const state = manors[id].region;
|
||||||
|
if (states[state] === undefined) return;
|
||||||
|
const capital = states[manors[id].region] ? id === states[manors[id].region].capital ? 0 : 1 : 1;
|
||||||
|
if (capital && states[state].capital !== "select") {
|
||||||
|
// move oldCapital to a town group
|
||||||
|
const oldCapital = states[state].capital;
|
||||||
|
moveBurgToGroup(oldCapital, "towns");
|
||||||
|
}
|
||||||
|
states[state].capital = capital ? id : "select";
|
||||||
|
d3.select("#burgToggleCapital").classed("pressed", capital);
|
||||||
|
const g = capital ? "capitals" : "towns";
|
||||||
|
moveBurgToGroup(id, g);
|
||||||
|
});
|
||||||
|
|
||||||
|
$("#burgTogglePort").click(function() {
|
||||||
|
const id = +elSelected.attr("data-id");
|
||||||
|
const cell = cells[manors[id].cell];
|
||||||
|
const markAsPort = cell.port === undefined ? true : undefined;
|
||||||
|
cell.port = markAsPort;
|
||||||
|
d3.select("#burgTogglePort").classed("pressed", markAsPort);
|
||||||
|
if (markAsPort) {
|
||||||
|
const type = elSelected.node().parentNode.id;
|
||||||
|
const ag = type === "capitals" ? "#capital-anchors" : "#town-anchors";
|
||||||
|
const group = icons.select(ag);
|
||||||
|
const size = +group.attr("size");
|
||||||
|
const x = rn(manors[id].x - size * 0.47, 2);
|
||||||
|
const y = rn(manors[id].y - size * 0.47, 2);
|
||||||
|
group.append("use").attr("xlink:href", "#icon-anchor").attr("data-id", id)
|
||||||
|
.attr("x", x).attr("y", y).attr("width", size).attr("height", size)
|
||||||
|
.on("click", editIcon);
|
||||||
|
} else {
|
||||||
|
$("#icons g[id*='anchors'] [data-id=" + id + "]").remove();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$("#burgPopulation").on("input", function() {
|
||||||
|
const id = +elSelected.attr("data-id");
|
||||||
|
burgPopulationFriendly.value = rn(this.value * urbanization.value * populationRate.value * 1000);
|
||||||
|
manors[id].population = +this.value;
|
||||||
|
});
|
||||||
|
|
||||||
|
$("#burgRelocate").click(function() {
|
||||||
|
if ($(this).hasClass('pressed')) {
|
||||||
|
$(".pressed").removeClass('pressed');
|
||||||
|
restoreDefaultEvents();
|
||||||
|
tip("", true);
|
||||||
|
} else {
|
||||||
|
$(".pressed").removeClass('pressed');
|
||||||
|
const id = elSelected.attr("data-id");
|
||||||
|
$(this).addClass('pressed').attr("data-id", id);
|
||||||
|
viewbox.style("cursor", "crosshair").on("click", relocateBurgOnClick);
|
||||||
|
tip("Click on map to relocate burg. Hold Shift for continuous move", true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// open legendsEditor
|
||||||
|
document.getElementById("burglLegend").addEventListener("click", function() {
|
||||||
|
let burg = +elSelected.attr("data-id");
|
||||||
|
let id = "burg" + burg;
|
||||||
|
let name = manors[burg].name;
|
||||||
|
editLegends(id, name);
|
||||||
|
});
|
||||||
|
|
||||||
|
// move burg to a different cell
|
||||||
|
function relocateBurgOnClick() {
|
||||||
|
const point = d3.mouse(this);
|
||||||
|
const index = getIndex(point);
|
||||||
|
const i = +$("#burgRelocate").attr("data-id");
|
||||||
|
if (isNaN(i) || !manors[i]) return;
|
||||||
|
|
||||||
|
if (cells[index].height < 20) {
|
||||||
|
tip("Cannot place burg in the water! Select a land cell", null, "error");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cells[index].manor !== undefined && cells[index].manor !== i) {
|
||||||
|
tip("There is already a burg in this cell. Please select a free cell", null, "error");
|
||||||
|
$('#grid').fadeIn();
|
||||||
|
d3.select("#toggleGrid").classed("buttonoff", false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let region = cells[index].region;
|
||||||
|
const oldRegion = manors[i].region;
|
||||||
|
// relocating capital to other country you "conquer" target cell
|
||||||
|
if (states[oldRegion] && states[oldRegion].capital === i) {
|
||||||
|
if (region !== oldRegion) {
|
||||||
|
tip("Capital cannot be moved to another country!", null, "error");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (d3.event.shiftKey === false) {
|
||||||
|
$("#burgRelocate").removeClass("pressed");
|
||||||
|
restoreDefaultEvents();
|
||||||
|
tip("", true);
|
||||||
|
if (region !== oldRegion) {
|
||||||
|
recalculateStateData(oldRegion);
|
||||||
|
recalculateStateData(region);
|
||||||
|
updateCountryEditors();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const x = rn(point[0],2), y = rn(point[1],2);
|
||||||
|
burgIcons.select("circle[data-id='"+i+"']").attr("transform", null).attr("cx", x).attr("cy", y);
|
||||||
|
burgLabels.select("text[data-id='"+i+"']").attr("transform", null).attr("x", x).attr("y", y);
|
||||||
|
const anchor = icons.select("use[data-id='"+i+"']");
|
||||||
|
if (anchor.size()) {
|
||||||
|
const size = anchor.attr("width");
|
||||||
|
const xa = rn(x - size * 0.47, 2);
|
||||||
|
const ya = rn(y - size * 0.47, 2);
|
||||||
|
anchor.attr("transform", null).attr("x", xa).attr("y", ya);
|
||||||
|
}
|
||||||
|
cells[index].manor = i;
|
||||||
|
cells[manors[i].cell].manor = undefined;
|
||||||
|
manors[i].x = x, manors[i].y = y, manors[i].region = region, manors[i].cell = index;
|
||||||
|
}
|
||||||
|
|
||||||
|
// open in MFCG
|
||||||
|
$("#burgSeeInMFCG").click(function() {
|
||||||
|
const id = +elSelected.attr("data-id");
|
||||||
|
const name = manors[id].name;
|
||||||
|
const cell = manors[id].cell;
|
||||||
|
const pop = rn(manors[id].population);
|
||||||
|
const size = pop > 65 ? 65 : pop < 6 ? 6 : pop;
|
||||||
|
const s = seed + "" + id;
|
||||||
|
const hub = cells[cell].crossroad > 2 ? 1 : 0;
|
||||||
|
const river = cells[cell].river ? 1 : 0;
|
||||||
|
const coast = cells[cell].port !== undefined ? 1 : 0;
|
||||||
|
const sec = pop > 40 ? 1 : Math.random() < pop / 100 ? 1 : 0;
|
||||||
|
const thr = sec && Math.random() < 0.8 ? 1 : 0;
|
||||||
|
const url = "http://fantasycities.watabou.ru/";
|
||||||
|
let params = `?name=${name}&size=${size}&seed=${s}&hub=${hub}&random=0&continuous=0`;
|
||||||
|
params += `&river=${river}&coast=${coast}&citadel=${id&1}&plaza=${sec}&temple=${thr}&walls=${sec}&shantytown=${sec}`;
|
||||||
|
const win = window.open(url+params, '_blank');
|
||||||
|
win.focus();
|
||||||
|
});
|
||||||
|
|
||||||
|
$("#burgAddfromEditor").click(function() {
|
||||||
|
clickToAdd(); // to load on click event function
|
||||||
|
$("#addBurg").click();
|
||||||
|
});
|
||||||
|
|
||||||
|
$("#burgRemove").click(function() {
|
||||||
|
alertMessage.innerHTML = `Are you sure you want to remove the Burg?`;
|
||||||
|
$("#alert").dialog({resizable: false, title: "Remove Burg",
|
||||||
|
buttons: {
|
||||||
|
Remove: function() {
|
||||||
|
$(this).dialog("close");
|
||||||
|
const id = +elSelected.attr("data-id");
|
||||||
|
d3.selectAll("[data-id='" + id + "']").remove();
|
||||||
|
const cell = manors[id].cell;
|
||||||
|
const state = manors[id].region;
|
||||||
|
if (states[state]) {
|
||||||
|
if (states[state].capital === id) states[state].capital = "select";
|
||||||
|
states[state].burgs --;
|
||||||
|
}
|
||||||
|
manors[id].region = "removed";
|
||||||
|
cells[cell].manor = undefined;
|
||||||
|
closeDialogs(".stable");
|
||||||
|
updateCountryEditors();
|
||||||
|
},
|
||||||
|
Cancel: function() {$(this).dialog("close");}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function editMarker() {
|
||||||
|
if (customization) return;
|
||||||
|
|
||||||
|
unselect();
|
||||||
|
closeDialogs("#markerEditor, .stable");
|
||||||
|
elSelected = d3.select(this).call(d3.drag().on("start", elementDrag)).classed("draggable", true);
|
||||||
|
|
||||||
|
$("#markerEditor").dialog({
|
||||||
|
title: "Edit Marker",
|
||||||
|
minHeight: 30, width: "auto", maxWidth: 275, resizable: false,
|
||||||
|
position: {my: "center top+30", at: "bottom", of: d3.event},
|
||||||
|
close: unselect
|
||||||
|
});
|
||||||
|
|
||||||
|
// update inputs
|
||||||
|
let id = elSelected.attr("href");
|
||||||
|
let symbol = d3.select("#defs-markers").select(id);
|
||||||
|
let icon = symbol.select("text");
|
||||||
|
markerSelectGroup.value = id.slice(1);
|
||||||
|
markerIconSize.value = parseFloat(icon.attr("font-size"));
|
||||||
|
markerIconShiftX.value = parseFloat(icon.attr("x"));
|
||||||
|
markerIconShiftY.value = parseFloat(icon.attr("y"));
|
||||||
|
markerIconFill.value = icon.attr("fill");
|
||||||
|
markerIconStrokeWidth.value = icon.attr("stroke-width");
|
||||||
|
markerIconStroke.value = icon.attr("stroke");
|
||||||
|
markerSize.value = elSelected.attr("data-size");
|
||||||
|
markerBase.value = symbol.select("path").attr("fill");
|
||||||
|
markerFill.value = symbol.select("circle").attr("fill");
|
||||||
|
let opacity = symbol.select("circle").attr("opacity");
|
||||||
|
markerToggleBubble.className = opacity === "0" ? "icon-info" : "icon-info-circled";
|
||||||
|
|
||||||
|
let table = document.getElementById("markerIconTable");
|
||||||
|
let selected = table.getElementsByClassName("selected");
|
||||||
|
if (selected.length) selected[0].removeAttribute("class");
|
||||||
|
selected = document.querySelectorAll("#markerIcon" + icon.text().codePointAt());
|
||||||
|
if (selected.length) selected[0].className = "selected";
|
||||||
|
markerIconCustom.value = selected.length ? "" : icon.text();
|
||||||
|
|
||||||
|
if (modules.editMarker) return;
|
||||||
|
modules.editMarker = true;
|
||||||
|
|
||||||
|
$("#markerGroup").click(function() {
|
||||||
|
$("#markerEditor > button").not(this).toggle();
|
||||||
|
$("#markerGroupSection").toggle();
|
||||||
|
updateMarkerGroupOptions();
|
||||||
|
});
|
||||||
|
|
||||||
|
function updateMarkerGroupOptions() {
|
||||||
|
markerSelectGroup.innerHTML = "";
|
||||||
|
d3.select("#defs-markers").selectAll("symbol").each(function() {
|
||||||
|
let opt = document.createElement("option");
|
||||||
|
opt.value = opt.innerHTML = this.id;
|
||||||
|
markerSelectGroup.add(opt);
|
||||||
|
});
|
||||||
|
let id = elSelected.attr("href").slice(1);
|
||||||
|
markerSelectGroup.value = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
// on add marker type click
|
||||||
|
document.getElementById("markerAddGroup").addEventListener("click", function() {
|
||||||
|
if ($("#markerInputGroup").css("display") === "none") {
|
||||||
|
$("#markerInputGroup").css("display", "inline-block");
|
||||||
|
$("#markerSelectGroup").css("display", "none");
|
||||||
|
markerInputGroup.focus();
|
||||||
|
} else {
|
||||||
|
$("#markerSelectGroup").css("display", "inline-block");
|
||||||
|
$("#markerInputGroup").css("display", "none");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// on marker type change
|
||||||
|
document.getElementById("markerSelectGroup").addEventListener("change", function() {
|
||||||
|
elSelected.attr("href", "#"+this.value);
|
||||||
|
elSelected.attr("data-id", "#"+this.value);
|
||||||
|
});
|
||||||
|
|
||||||
|
// on new type input
|
||||||
|
document.getElementById("markerInputGroup").addEventListener("change", function() {
|
||||||
|
let newGroup = this.value.toLowerCase().replace(/ /g, "_").replace(/[^\w\s]/gi, "");
|
||||||
|
if (Number.isFinite(+newGroup.charAt(0))) newGroup = "m" + newGroup;
|
||||||
|
if (d3.select("#defs-markers").select("#"+newGroup).size()) {
|
||||||
|
tip('The type "'+ newGroup + '" is already exists');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
markerInputGroup.value = "";
|
||||||
|
// clone old group assigning new id
|
||||||
|
let id = elSelected.attr("href");
|
||||||
|
let l = d3.select("#defs-markers").select(id).node().cloneNode(true);
|
||||||
|
l.id = newGroup;
|
||||||
|
elSelected.attr("href", "#"+newGroup);
|
||||||
|
elSelected.attr("data-id", "#"+newGroup);
|
||||||
|
document.getElementById("defs-markers").insertBefore(l, null);
|
||||||
|
|
||||||
|
// select new group
|
||||||
|
let opt = document.createElement("option");
|
||||||
|
opt.value = opt.innerHTML = newGroup;
|
||||||
|
markerSelectGroup.add(opt);
|
||||||
|
$("#markerSelectGroup").val(newGroup).change();
|
||||||
|
$("#markerSelectGroup, #markerInputGroup").toggle();
|
||||||
|
updateMarkerGroupOptions();
|
||||||
|
});
|
||||||
|
|
||||||
|
$("#markerIconButton").click(function() {
|
||||||
|
$("#markerEditor > button").not(this).toggle();
|
||||||
|
$("#markerIconButtons").toggle();
|
||||||
|
if (!$("#markerIconTable").text()) drawIconsList(icons);
|
||||||
|
});
|
||||||
|
|
||||||
|
$("#markerRemoveGroup").click(function() {
|
||||||
|
let id = elSelected.attr("href");
|
||||||
|
let used = document.querySelectorAll("use[data-id='"+id+"']");
|
||||||
|
let count = used.length === 1 ? "1 element" : used.length + " elements";
|
||||||
|
const message = "Are you sure you want to remove the marker (" + count + ")?";
|
||||||
|
alertMessage.innerHTML = message;
|
||||||
|
$("#alert").dialog({resizable: false, title: "Remove marker",
|
||||||
|
buttons: {
|
||||||
|
Remove: function() {
|
||||||
|
$(this).dialog("close");
|
||||||
|
if (id !== "#marker0") d3.select("#defs-markers").select(id).remove();
|
||||||
|
used.forEach(function(e) {e.remove();});
|
||||||
|
updateMarkerGroupOptions();
|
||||||
|
$("#markerEditor").dialog("close");
|
||||||
|
},
|
||||||
|
Cancel: function() {$(this).dialog("close");}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
28
vue/src/App.vue
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
<template>
|
||||||
|
<div id="app">
|
||||||
|
<img alt="Vue logo" src="./assets/logo.png">
|
||||||
|
<HelloWorld msg="Welcome to Your Vue.js App"/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import HelloWorld from './components/HelloWorld.vue'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'app',
|
||||||
|
components: {
|
||||||
|
HelloWorld
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
#app {
|
||||||
|
font-family: 'Avenir', Helvetica, Arial, sans-serif;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
-moz-osx-font-smoothing: grayscale;
|
||||||
|
text-align: center;
|
||||||
|
color: #2c3e50;
|
||||||
|
margin-top: 60px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
10382
vue/src/FantasyMapGenerator.js
Normal file
BIN
vue/src/assets/logo.png
Normal file
|
After Width: | Height: | Size: 6.7 KiB |
58
vue/src/components/HelloWorld.vue
Normal file
|
|
@ -0,0 +1,58 @@
|
||||||
|
<template>
|
||||||
|
<div class="hello">
|
||||||
|
<h1>{{ msg }}</h1>
|
||||||
|
<p>
|
||||||
|
For guide and recipes on how to configure / customize this project,<br>
|
||||||
|
check out the
|
||||||
|
<a href="https://cli.vuejs.org" target="_blank" rel="noopener">vue-cli documentation</a>.
|
||||||
|
</p>
|
||||||
|
<h3>Installed CLI Plugins</h3>
|
||||||
|
<ul>
|
||||||
|
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-babel" target="_blank" rel="noopener">babel</a></li>
|
||||||
|
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-eslint" target="_blank" rel="noopener">eslint</a></li>
|
||||||
|
</ul>
|
||||||
|
<h3>Essential Links</h3>
|
||||||
|
<ul>
|
||||||
|
<li><a href="https://vuejs.org" target="_blank" rel="noopener">Core Docs</a></li>
|
||||||
|
<li><a href="https://forum.vuejs.org" target="_blank" rel="noopener">Forum</a></li>
|
||||||
|
<li><a href="https://chat.vuejs.org" target="_blank" rel="noopener">Community Chat</a></li>
|
||||||
|
<li><a href="https://twitter.com/vuejs" target="_blank" rel="noopener">Twitter</a></li>
|
||||||
|
<li><a href="https://news.vuejs.org" target="_blank" rel="noopener">News</a></li>
|
||||||
|
</ul>
|
||||||
|
<h3>Ecosystem</h3>
|
||||||
|
<ul>
|
||||||
|
<li><a href="https://router.vuejs.org" target="_blank" rel="noopener">vue-router</a></li>
|
||||||
|
<li><a href="https://vuex.vuejs.org" target="_blank" rel="noopener">vuex</a></li>
|
||||||
|
<li><a href="https://github.com/vuejs/vue-devtools#vue-devtools" target="_blank" rel="noopener">vue-devtools</a></li>
|
||||||
|
<li><a href="https://vue-loader.vuejs.org" target="_blank" rel="noopener">vue-loader</a></li>
|
||||||
|
<li><a href="https://github.com/vuejs/awesome-vue" target="_blank" rel="noopener">awesome-vue</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'HelloWorld',
|
||||||
|
props: {
|
||||||
|
msg: String
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<!-- Add "scoped" attribute to limit CSS to this component only -->
|
||||||
|
<style scoped>
|
||||||
|
h3 {
|
||||||
|
margin: 40px 0 0;
|
||||||
|
}
|
||||||
|
ul {
|
||||||
|
list-style-type: none;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
li {
|
||||||
|
display: inline-block;
|
||||||
|
margin: 0 10px;
|
||||||
|
}
|
||||||
|
a {
|
||||||
|
color: #42b983;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
8
vue/src/main.js
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
import Vue from 'vue'
|
||||||
|
import App from './App.vue'
|
||||||
|
|
||||||
|
Vue.config.productionTip = false
|
||||||
|
|
||||||
|
new Vue({
|
||||||
|
render: h => h(App)
|
||||||
|
}).$mount('#app')
|
||||||