-
์ํ์ฝ๋ฉ ๋ง์ธ๋๋งต ๋ผ์ด๋ธ๋ฌ๋ฆฌ cytoscape ์ฌ์ฉ๋ฒProject/Web 2023. 7. 13. 21:24๋ฐ์ํ
๐ ๋ฐ๋จ
์ํ์ฝ๋ฉ์ ์ ์ํด์ ์์ ์๊ฐ ์น์ ์ผ๋ก ๊ฐ๋ฉด ์์ ๊ฐ์ ๊ด๊ณ๋ฅผ ํ์ธํ ์ ์๋ ๋ง์ธ๋ ๋งต์ด ์์ต๋๋ค.
๊ฐ์ธ์ ์ผ๋ก ๊ณต๋ถํ ๊ฒ๋ค์ ํ๋ฆ์ ์์ ๊ฐ์ด ์ ๋ฆฌํ๋ฉด ์ข์ ๊ฒ ๊ฐ์์ต๋๋ค.
๊ทธ๋์ ํด๋น ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ cytoscape๋ผ๋ ๊ฒ์ ํ์ธ ํ ์ด๋ฅผ ํ์ฉํด ๋น์ทํ ์ฌ์ดํธ๋ฅผ ๊ฐ๋ฐ์ ํด๋ดค์ต๋๋ค.๊ทธ๋ฌ๋ cytoscape ๊ด๋ จํ ๋ณ๋์ ํ๊ธ ์ ๋ณด๊ฐ ์์ด ์์ด๋ฅผ ์ ๋ชปํ๋ ์ ๋ ์๋ง์ ์ฝ์ง์ ์๊ฐ์ ๊ฑฐ์ณ์ผ ํ๊ธฐ์ ๋ค๋ฅธ ๋ถ๋ค์ ํด๋น ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ข ๋ ํธํ๊ฒ ์ฐ์ค ์ ์๋๋ก ๊ฐ๋ฐํ๋ฉด์ ์๊ฒ ๋ ๊ฒ๋ค์ ํ๊ธ๊ธฐ๋ก์ผ๋ก ๋จ๊น๋๋ค. ๋์์ด ๋์์ผ๋ฉด ์ข๊ฒ ์ต๋๋ค!
๐งต ์ด๊ธฐ ์ค์
ํด์ Visual Studio Code ๊ธฐ์ค์ผ๋ก ์ค๋ช ๋๋ฆฌ๊ณ NPM์ ์ค์น๋์ด ์๋ค๊ณ ๊ฐ์ ํ๊ฒ ์ต๋๋ค.
๋จผ์ ํ์ํ ํจํค์ง๋ฅผ ์ค์นํด์ผ ํฉ๋๋ค. ํฐ๋ฏธ๋์ ์ด์ด์npm init -y
๋ก ์ด๊ธฐํ ํ ํ
npm install @babel/core @babel/preset-env @babel/preset-react babel-loader clean-webpack-plugin css-loader html-loader file-loader html-webpack-plugin mini-css-extract-plugin webpack webpack-cli webpack-dev-server cytoscape
๋ฅผ ์ ๋ ฅํด ํ์ํ ํจํค์ง๋ค์ ์ค์นํด ์ค๋๋ค. ๊ทธ ๋ค์์
์์ ๊ฐ์ด ๊ฒฝ๋ก๋ฅผ ๊ตฌ์ฑํ๊ณ ํ์ผ์ ์์ฑํฉ๋๋ค. ๋ด์ฉ์ ์๋์ ๊ฐ์ต๋๋ค.
index.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters<!DOCTYPE html> <html lang="ko"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Take Knowledge's Study Map</title> </head> <body> <div id="cy"></div> </body> </html> style.css
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactershtml,body,#cy { width: 100%; height: 100%; } body { margin: 0; } index.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersimport cytoscape from 'cytoscape'; import './style.css'; // webpack์ผ๋ก ๋ฌถ์ด์ค์ผ ํ๋ cssํ์ผ์ ์ง์ ์ ์ธ index.js ์ import ํฉ๋๋ค // ์๋๋ ๊ณต์ ์ฌ์ดํธ์ ์ฌ๋ผ์ ์๋ ์์ ์ฝ๋์ ๋๋ค var cy = cytoscape({ container: document.getElementById('cy'), // container to render in elements: [ // list of graph elements to start with { // node a "data": { "id": 'a' } }, { // node b "data": { "id": 'b' } }, { // edge ab "data": { "id": 'ab', "source": 'a', "target": 'b' } } ], style: [ // the stylesheet for the graph { selector: 'node', style: { 'background-color': '#666', 'label': 'data(id)' } }, { selector: 'edge', style: { 'width': 3, 'line-color': '#ccc', 'target-arrow-color': '#ccc', 'target-arrow-shape': 'triangle' } } ], layout: { name: 'grid', rows: 5 } }); .babelrc
// .babelrc { "presets": [ "@babel/preset-env" ] }
.gitignore
node_modules
package.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters// ์ค์น๊ฐ ๋์๋ค๋ฉด ๋ค๋ฅธ ๋ถ๋ถ์ ์ด๋ฏธ ๋์ผํ๊ฒ ์ ๋ ฅ๋์ด ์์ ๊ฒ๋๋ค. // scripts ๋ถ๋ถ๋ง ์ ์ ์ด์ฃผ์ธ์! { "name": "cytoscape_prj", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "build": "webpack", "start": "webpack serve" }, "keywords": [], "author": "", "license": "ISC", "dependencies": { "@babel/core": "^7.22.5", "@babel/preset-env": "^7.22.5", "@babel/preset-react": "^7.22.5", "babel-loader": "^9.1.2", "clean-webpack-plugin": "^4.0.0", "css-loader": "^6.8.1", "cytoscape": "^3.25.0", "file-loader": "^6.2.0", "html-loader": "^4.2.0", "html-webpack-plugin": "^5.5.3", "mini-css-extract-plugin": "^2.7.6", "webpack": "^5.88.1", "webpack-cli": "^5.1.4", "webpack-dev-server": "^4.15.1" } } webpack.config.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersconst path = require("path"); const HtmlWebPackPlugin = require("html-webpack-plugin"); // html ํ์ผ ์ถ์ถ ํ๋ฌ๊ทธ์ธ์ ๋๋ค const MiniCssExtractPlugin = require("mini-css-extract-plugin"); // css ํ์ผ ์ถ์ถ ํ๋ฌ๊ทธ์ธ์ ๋๋ค const { CleanWebpackPlugin } = require("clean-webpack-plugin"); // build ํด๋ ์๋ ์ ๋ฆฌ๋ฅผ ์ํ ํ๋ฌ๊ทธ์ธ ์ ๋๋ค module.exports = { entry: "./src/index.js", output: { filename: "bundle.js", path: path.resolve(__dirname + "/build"), }, devServer: { static: { directory: path.join(__dirname, "public"), }, compress: true, port: 9000, // ๋ณ๊ฒฝ ์ฌํญ ์๋ ์ ์ฉ์ ์ํ ์ค์ ์ ๋๋ค }, mode: "none", module: { rules: [ { test: /\.(js|jsx)$/, exclude: "/node_modules", use: ["babel-loader"], }, { test: /\.html$/, use: [ { loader: "html-loader", options: { minimize: true }, }, ], }, { test: /\.css$/, use: [MiniCssExtractPlugin.loader, "css-loader"], }, ], // js, jsx, html, css ํ์ผ ๋ฒ๋ค๋ง ๊ด๋ จ ์ค์ ์ ๋๋ค }, plugins: [ new HtmlWebPackPlugin({ template: "./public/index.html", filename: "index.html", }), new MiniCssExtractPlugin({ filename: "style.css", }), new CleanWebpackPlugin(), // ํ๋ฌ๊ทธ์ธ ์ค์ ๋ค์ ๋๋ค ], }; ์์ ๊ฐ์ด ์ค์ ํด ์ค ๋ค์
npm run start
์์ ํค์๋๋ฅผ ์ ๋ ฅํ ํ http://localhost:9000/ ๋ก ์ ์ํ๋ฉด
์์ ๊ฐ์ ํ๋ฉด์ด ์ถ๋ ฅ๋๊ณ , ์ด๋ฌ๋ฉด ์ด์ ์ธํ ์ ๋๋ฌ์ต๋๋ค.
๐ฅ cytoscape ํ์ฉ๋ฒ
๐น ๋ฐ์ดํฐ ๊ตฌ์ฑ
cytoscape๋ฅผ ํ์ฉํ๊ธฐ ์ํด์ ๋จผ์ node์ edge๋ฅผ ๊ตฌ์ฑํด์ผ ํฉ๋๋ค.
๋จผ์ ๊ฑฐ์ ์ด ๋๋ node๋
"data": { "id": 'id', "url": '๋งํฌ๊ฑธ๊ณ ์ถ์ ์ฃผ์(์ต์ )' "label": 'ํ์ํ๊ณ ์ถ์ ๋ด์ฉ(์ต์ )' }
์ ๊ฐ์ ํํ๋ก ๊ตฌ์ฑํด์ฃผ๋ฉด ๋๊ณ ์ฐ๊ฒฐ์ ์ธ edge๋
"data": { "id": 'id', "source": '์ฐ๊ฒฐํ ๋ ธ๋ ์ค ํ์์ ๋ node id', "target":'์ฐ๊ฒฐํ ๋ ธ๋ ์ค ์์์ ๋ node id' }
ํํ๋ก ์ ๋ ฅํ๋ฉด ๋ฉ๋๋ค.
source์ ํ์์ ๋ node๋ฅผ, target์ ์์์ ๋ node๋ฅผ ๋ฌ์ผ ํ๋ค๋ ๋ถ๋ถ์ด ์์ํ์ค ํ ์ง๋ง(์ ๋ ์ด๊ฒ ์ด์ํ์ต๋๋ค) ๊ทธ ์ด์ ๋ ์ ์ ํ 'depth์ ๋ฐ๋ผ node์ ํฌ๊ธฐ๋ฅผ ๋ค๋ฅด๊ฒ' ์ฑํฐ์์ ํ์ธํ์ค ์ ์์ต๋๋ค.
๊ทธ ์ธ์ ์ฃผ์ํ ์ ์ id์ ๊ณต๋ฐฑ๊ณผ .์ด ํฌํจ๋๋ฉด ์๋ฉ๋๋ค. ํฌํจํด๋ ๋น์ฅ ๋ ๋๋ง์ ๋ฌธ์ ๊ฐ ์์ง๋ง ํฌํจ๋์ด ์์ผ๋ฉด cytoscape๊ฐ ์ ๊ณตํ๋ ํจ์ ์ค id๋ก node๋ฅผ ๊ฒ์ํ๋ ํจ์๋ฅผ ์ธ ๋ ์๋ฌ๊ฐ ๋๋ ํฌํจํ์ง ๋ง์๋ค.
์ด ์ ์ ์ฃผ์ํด์ node์ edge๋ฅผ ๊ตฌ์ฑํ ํ ๋ฐฐ์ด๋ก cytoscape ํจ์ ๋ด๋ถ์ elements ๋ถ๋ถ์ ์ ๋ ฅํด์ฃผ๋ฉด ๋ฉ๋๋ค. ์ ํ์์ ๋ฐ๋ผ ๊ตฌ์ฑํ๊ณ ์ ๋ ฅํ ์์ค๋ ์๋์ ๊ฐ์ต๋๋ค.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersimport cytoscape from 'cytoscape'; import './style.css'; // webpack์ผ๋ก ๋ฌถ์ด์ค์ผ ํ๋ cssํ์ผ์ ์ง์ ์ ์ธ index.js ์ import ํฉ๋๋ค const data = [ { "data": { "id": "PJ-mindMap", "url": "https://github.com/nomelancholy/js-project-driven-study-mind-map/projects/1?add_cards_query=is%3Aopen", "label": "Project Driven Study Map" } }, { "data": { "id": "ISSUE-packageJson", "url": "https://www.google.co.kr/search?newwindow=1&safe=off&sxsrf=ACYBGNQPahfceN-IrrIMqFcBxt0bBJxcog%3A1577373548670&source=hp&ei=bM8EXp3aJoKpoASW2InwAg&q=no+such+file+or+directory%2C+open+%27C%3A%5Cdev%5Cworkspace%5Cjs-seomal-clone%5Cpackage.json%27&oq=no+such+file+or+directory%2C+open+%27C%3A%5Cdev%5Cworkspace%5Cjs-seomal-clone%5Cpackage.json%27&gs_l=psy-ab.3...7437.7437..8911...1.0..0.95.95.1......0....2j1..gws-wiz.pzIrSS2UT84&ved=0ahUKEwidwK2wztPmAhWCFIgKHRZsAi4Q4dUDCAY&uact=5", "label": "package.json ์๋ฌ" } }, { "data": { "id": "PJ-mindMap->ISSUE-packageJson", "source": "ISSUE-packageJson", "target": "PJ-mindMap" } }, { "data": { "id": "STUDY-npmInit", "url": "https://stackoverflow.com/questions/9484829/npm-cant-find-package-json", "label": "npm ํจํค์ง ์ค์น ์์ ์์ง" } }, { "data": { "id": "ISSUE-packageJson->STUDY-npmInit", "source": "STUDY-npmInit", "target": "ISSUE-packageJson" } }, { "data": { "id": "ISSUE-outsideModule", "url": "https://www.google.co.kr/search?newwindow=1&safe=off&sxsrf=ACYBGNT3L0sknJfq3DO75H55Q5VQJODk-Q%3A1577373778729&ei=UtAEXvGVLMLh-AbOm7CYDA&q=Uncaught+SyntaxError%3A+Cannot+use+import+statement+outside+a+modul&oq=Uncaught+SyntaxError%3A+Cannot+use+import+statement+outside+a+modul&gs_l=psy-ab.3..35i39j0l2j0i203l7.513620.513620..514369...0.0..0.167.374.1j2......0....2j1..gws-wiz.gwgT-rwsfWw&ved=0ahUKEwjxhomez9PmAhXCMN4KHc4NDMMQ4dUDCAs&uact=5", "label": "script module ์๋ฌ" } }, { "data": { "id": "PJ-mindmap->ISSUE-outsideModule", "source": "ISSUE-outsideModule", "target": "PJ-mindMap" } }, { "data": { "id": "STUDY-scriptModule", "url": "https://velog.io/@takeknowledge/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EB%AA%A8%EB%93%88-%ED%95%99%EC%8A%B5-%EB%82%B4%EC%9A%A9-%EC%9A%94%EC%95%BD-lwk4drjnni", "label": "js module ํ์ต" } }, { "data": { "id": "ISSUE-outsideModule->STUDY-scriptModule", "source": "STUDY-scriptModule", "target": "ISSUE-outsideModule" } }, { "data": { "id": "STUDY-scriptPosition", "url": "https://velog.io/@takeknowledge/script-%ED%83%9C%EA%B7%B8%EB%8A%94-%EC%96%B4%EB%94%94%EC%97%90-%EC%9C%84%EC%B9%98%ED%95%B4%EC%95%BC-%ED%95%A0%EA%B9%8C%EC%9A%94", "label": "script ํ๊ทธ ์์น ํ์ต" } }, { "data": { "id": "ISSUE-outsideModule->STUDY-scriptPosition", "source": "STUDY-scriptPosition", "target": "ISSUE-outsideModule" } }, { "data": { "id": "ISSUE-localCORS", "url": "https://www.google.co.kr/search?newwindow=1&safe=off&sxsrf=ACYBGNSmKE1wN_fBQuRtT5pwz0hZ5JqldQ%3A1577374293889&ei=VdIEXtP7NY-lmAX82Z7oDg&q=Access+to+script+at+%27file%3A%2F%2F%2FC%3A%2Fdev%2Fworkspace%2Fjs-seomal-clone%2Fjs%2Fcyto.js%27+from+origin+%27null%27+has+been+blocked+by+CORS+policy%3A+Cross+origin+requests+are+only+supported+for+protocol+schemes%3A+http%2C+data%2C+chrome%2C+chrome-extension%2C+https.&oq=Access+to+script+at+%27file%3A%2F%2F%2FC%3A%2Fdev%2Fworkspace%2Fjs-seomal-clone%2Fjs%2Fcyto.js%27+from+origin+%27null%27+has+been+blocked+by+CORS+policy%3A+Cross+origin+requests+are+only+supported+for+protocol+schemes%3A+http%2C+data%2C+chrome%2C+chrome-extension%2C+https.&gs_l=psy-ab.3..35i39j0i20i263l2j0i203l7.516217.516217..516645...0.0..0.177.281.0j2......0....2j1..gws-wiz.JE3_EPpI5o4&ved=0ahUKEwiT-tuT0dPmAhWPEqYKHfysB-0Q4dUDCAs&uact=5", "label": "local ์คํ์ CORS ์๋ฌ" } }, { "data": { "id": "PJ-mindmap->ISSUE-localCORS", "source": "ISSUE-localCORS", "target": "PJ-mindMap" } }, { "data": { "id": "STUDY-localCORS", "url": "https://velog.io/@takeknowledge/%EB%A1%9C%EC%BB%AC%EC%97%90%EC%84%9C-CORS-policy-%EA%B4%80%EB%A0%A8-%EC%97%90%EB%9F%AC%EA%B0%80-%EB%B0%9C%EC%83%9D%ED%95%98%EB%8A%94-%EC%9D%B4%EC%9C%A0-3gk4gyhreu", "label": "CORS & SOP ํ์ต" } }, { "data": { "id": "ISSUE-localCORS->STUDY-localCORS", "source": "STUDY-localCORS", "target": "ISSUE-localCORS" } }, { "data": { "id": "ISSUE-moduleImport", "url": "https://goenning.net/2017/07/21/how-to-avoid-relative-path-hell-javascript-typescript-projects/", "label": "module import ๊ฒฝ๋ก ์๋ฌ" } }, { "data": { "id": "PJ-mindmap->ISSUE-moduleImport", "source": "ISSUE-moduleImport", "target": "PJ-mindMap" } }, { "data": { "id": "STUDY-webpackBuild", "url": "https://github.com/nomelancholy/webpack-build-practice", "label": "webpack build ์ค์ต" } }, { "data": { "id": "ISSUE-moduleImport->STUDY-webpackBuild", "source": "STUDY-webpackBuild", "target": "ISSUE-moduleImport" } }, { "data": { "id": "STUDY-jsBrowser", "url": "https://github.com/nomelancholy/webpack-build-practice", "label": "js ์์ง๊ณผ runtime ํ์ต" } }, { "data": { "id": "STUDY-webpackBuild->STUDY-jsBrowser", "source": "STUDY-jsBrowser", "target": "STUDY-webpackBuild" } } ]; // ์๋๋ ๊ณต์ ์ฌ์ดํธ์ ์ฌ๋ผ์ ์๋ ์์ ์ฝ๋์ ๋๋ค const cy = cytoscape({ container: document.getElementById('cy'), // container to render in elements: data, style: [ // the stylesheet for the graph { selector: 'node', style: { 'background-color': '#666', 'label': 'data(id)' } }, { selector: 'edge', style: { 'width': 3, 'line-color': '#ccc', 'target-arrow-color': '#ccc', 'target-arrow-shape': 'triangle' } } ], layout: { name: 'grid', rows: 5 } }); ๊ทธ๋ฌ๋ ์์ ๊ฐ์ด ์ ๋ ฅํ๋ฉด
๋ณด๋ค์ํผ ํ๋ฉด์ด seomal.org์์ ๋ณด๋ ๊ฒ๊ณผ๋ ๋ง์ด ๋ค๋ฅธ ํ๋ฉด์ด ๋์ต๋๋ค. ์ฐจ๊ทผ ์ฐจ๊ทผ ์ซ์๊ฐ ๋ด ์๋ค.
๐ id๊ฐ ์๋ ๋ผ๋ฒจ์ด ํ์๋๊ฒ
๋จผ์ node ์์ id๊ฐ ์๋ ์ฐ๋ฆฌ๊ฐ ์ ๋ ฅํ ๋ผ๋ฒจ์ด ํ์๋๋๋ก ํด๋ด ์๋ค. ๋ฐฉ๋ฒ์ ๊ฐ๋จํฉ๋๋ค. index.js ํ๋จ style ์ชฝ์์ node์ style์ ์ค์ ํ๋ ๋ถ๋ถ์ ๋ณด๋ฉด label์ด data(id)๋ก ๋์ด ์๋๋ฐ ์ด๊ฑธ data(label)๋ก ๋ฐ๊ฟ์ฃผ๋ฉด
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersimport cytoscape from 'cytoscape'; import './style.css'; const data = ... const cy = cytoscape({ container: document.getElementById('cy'), // container to render in elements: data, style: [ // the stylesheet for the graph { selector: 'node', style: { 'background-color': '#666', // ๋ณ๊ฒฝ๋ ๋ถ๋ถ 'label': 'data(label)' // } }, { selector: 'edge', style: { 'width': 3, 'line-color': '#ccc', 'target-arrow-color': '#ccc', 'target-arrow-shape': 'triangle' } } ], layout: { name: 'grid', rows: 5 } }); id๊ฐ ์๋ label์ด node์ ์ด๋ฆ์ผ๋ก ๋์ค๋ ๊ฑธ ๋ณผ ์ ์์ต๋๋ค.
๐ edge styling
๋ค์์ผ๋ก๋ edge์ ์คํ์ผ๋ง์ ํด๋ณด์ฃ . ๋จผ์ edge์ ๋ฐฉํฅ์ ํ์ํด๋ด ์๋ค. ์ด ์ค์ ์ style์์ edge์ style์ ์ค์ ํ๋ ๋ถ๋ถ์ ๊ฐ์ ํตํด ์ ์ดํ ์ ์์ต๋๋ค.
๋จผ์ ์ธํ ๋์ด ์๋ ์ํ์์ 'curve-style'์ ๊ฐ์ 'bezier'๋ก ์ฃผ๋ฉด ํ์ดํ๊ฐ ๋ฑ์ฅํฉ๋๋ค.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters// index.js ์ style ๋ถ๋ถ์ ๋๋ค. ์ ์ฒด ์ฝ๋๋ ๋ง์ง๋ง์ ์ฌ๋ฆด๊ฒ์ style: [ // the stylesheet for the graph { selector: 'node', style: { 'background-color': '#666', 'label': 'data(label)' } }, { selector: 'edge', style: { 'width': 3, // ์ถ๊ฐ๋ ๋ถ๋ถ 'curve-style': 'bezier', // 'line-color': '#ccc', 'target-arrow-color': '#ccc', 'target-arrow-shape': 'triangle' } } ], ๊ทธ๋ฐ๋ฐ ํ์ดํ ๋ฐฉํฅ์ด ์์๋ฅผ ๊ฐ๋ฅดํค๊ณ ์๋๊ฒ ๋ญ๊ฐ ์ด์ํ์ฃ ? ๊ณ ์ณ๋ด ์๋ค.
target-arrow-shape์ target-arrow-color์์ source-arrow-shape์ source-arrow-color๋ก์.
๊ทธ๋ ๊ฒ ํด์ฃผ๋ฉด ํ์ดํ ๋ฐฉํฅ์ด ๋ฐ๋๋๋ค.This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersstyle: [ // the stylesheet for the graph { selector: 'node', style: { 'background-color': '#666', 'label': 'data(label)' } }, { selector: 'edge', style: { 'width': 3, 'curve-style': 'bezier', 'line-color': '#ccc', // ๋ณ๊ฒฝ๋ ๋ถ๋ถ 'source-arrow-color': '#ccc', 'source-arrow-shape': 'triangle' // } } ], ๋ง์ง๋ง์ผ๋ก ํ์ดํ ๋ชจ์๋ ๋ฐ๊ฟ๋ด ์๋ค. ํ์ดํ ๋ชจ์์ ์ฌ๊ธฐ์ ํ์ธ ๊ฐ๋ฅํฉ๋๋ค.
์ vee๊ฐ ๋ง์์ ๋ค๋๊ตฐ์. ์ ์ฉํ๋ฉด
์ข ๋ ๋ ์นด๋ก์ด ํ์ดํ ๋ชจ์์ผ๋ก ์ ๋ฐ๋์์ต๋๋ค.
data ๋ถ๋ถ์ ์๋ตํ ์ฌ๊ธฐ๊น์ง์ ์ ์ฒด ์ฝ๋๋ ์๋์ ๊ฐ์ต๋๋ค.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersimport cytoscape from 'cytoscape'; import './style.css'; const data = ... const cy = cytoscape({ container: document.getElementById('cy'), // container to render in elements: data, style: [ // the stylesheet for the graph { selector: 'node', style: { 'background-color': '#666', 'label': 'data(label)' } }, { selector: 'edge', style: { 'width': 3, 'line-color': '#ccc', 'source-arrow-color': '#ccc', // ๋ณ๊ฒฝ๋ ๋ถ๋ถ 'source-arrow-shape': 'vee' // } } ], layout: { name: 'grid', rows: 5 } }); ๐ layout ์ค์
๋ค์์ผ๋ก๋ layout์ ์ค์ ํด์ ~์ธ๋ฐ์์ด~ ์ ๋ ฌ๋์ด ์๋ ํํ๋ฅผ ์ข ๋ ๋ง์ธ๋๋งต์ค๋ฝ๊ฒ ๋ฐ๊ฟ๋ด ์๋ค
layout์ ํํ๋ค์ ์ฌ๊ธฐ์ ํ์ธํ ์ ์์ต๋๋ค. ์ cose-bilkent๊ฐ ๋ง์์ ๋๋ค์. ์ด๊ฑธ ์ฌ์ฉํด๋ณด๊ฒ ์ต๋๋ค.๋จผ์ ์ค์น๋ฅผ ํด์ค์ผํฉ๋๋ค. ํฐ๋ฏธ๋์ ํ๋ ๋ ์ฌ์๊ณ
npm install cytoscape-cose-bilkent
์ ์ ๋ ฅํด ํด๋น layout์ ์ค์นํฉ๋๋ค. ์ดํ์ index.js ์ต์๋จ์ผ๋ก ์ด๋ํด์
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersimport cytoscape from 'cytoscape'; import coseBilkent from 'cytoscape-cose-bilkent'; cytoscape.use(coseBilkent); import './style.css'; ... ... style: [ // the stylesheet for the graph { selector: 'node', style: { 'background-color': '#666', 'label': 'data(label)' } }, { selector: 'edge', style: { 'width': 3, 'curve-style': 'bezier', 'line-color': '#ccc', 'source-arrow-color': '#ccc', 'source-arrow-shape': 'vee' } } ], // ๋ณ๊ฒฝ๋ ๋ถ๋ถ layout: { name: 'cose-bilkent', animate: false, gravityRangeCompound: 1.5, fit: true, tile: true } // ์์ ๊ฐ์ด cytoscape-cose-bilkent๋ฅผ import ํ๊ณ ์ฌ์ฉํ๋๋ก ์ ์ธํ ํ
node์ edge์ style๊ด๋ จ ์ค์ ์ ํด์คฌ๋ ๋ถ๋ถ ์๋ ์๋ layout์ ๋ฐ๊ฟ์ฃผ๋ฉด๋ง์นจ๋ด ๋ง์ธ๋๋งต ๊ฐ์ ํํ๊ฐ ๋ํ๋ฌ์ต๋๋ค!
๐งฒ ํ์ดํผ ๋งํฌ ์ฐ๊ฒฐ
์ด์ node๋ฅผ ํด๋ฆญํ๋ฉด ๋ฐ์ดํฐ ๊ตฌ์ฑ๋ ์ ๋ ฅํด์ค url์ด ์์ฐฝ์์ ์ด๋ฆฌ๊ฒ ์ค์ ํด ์ค์๋ค.
cytoscape์๋ on() ๋ฉ์๋๋ฅผ ์ด์ฉํด ์ด๋ฒคํธ๋ฅผ ๋ถ์ฌํ ์ ์์ต๋๋ค.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersconst cy = cytoscape({ ... }); cy.on('tap', function (e) { const url = e.target.data('url') if (url && url !== '') { window.open(url); } }); tap์ ์ธ์๋ก ์ค์ ํด๋ฆญ์ด๋ฒคํธ๋ฅผ ์ฃผ๊ณ ํด๋น url์ด ์์ฐฝ์ผ๋ก ์ฐ๊ฒฐ๋๊ฒ ์ค์ ํด์ฃผ๋ฉด
ํด๋ฆญ์ ๋งํฌ๋ก ์ฐ๊ฒฐ๋๋ ์ด๋ฒคํธ๊ฐ ์ ์๋ํฉ๋๋ค.
๐ depth์ ๋ฐ๋ผ node์ ํฌ๊ธฐ๋ฅผ ๋ค๋ฅด๊ฒ
์ด์ depth์ ๋ฐ๋ผ node์ ํฌ๊ธฐ๋ฅผ ๋ค๋ฅด๊ฒ ๋ง๋ค์ด ๋ด ์๋ค.
๋จผ์ ์ด๊ฑธ ์ํด์ ๋์ผํ data๋ฅผ elements๋ก ๊ฐ๋ cytoscape ๊ฐ์ฒด๊ฐ ํ๋ ๋ ์์ด์ผ ํฉ๋๋ค.data์ cy ์ฌ์ด์ ํฌ๊ธฐ ๋ณ๊ฒฝ์ ์ํ ์ฝ๋๋ฅผ ์ถ๊ฐํ๊ณ , cy์style๋ถ๋ถ์ ๊ฐ์ width, height, font-size๋ฅผ ๋ณ๊ฒฝํด์ฃผ๋ฉด
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersconst data = [...]; const cy_for_rank = cytoscape({ elements: data }); // rank๋ฅผ ํ์ฉํ๊ธฐ ์ํด data๋ง ์ ๋ ฅํ cytoscape ๊ฐ์ฒด์ ๋๋ค const pageRank = cy_for_rank.elements().pageRank(); // elements๋ค์ rank๋ค์ ๋๋ค. const nodeMaxSize = 50; const nodeMinSize = 5; const fontMaxSize = 8; const fontMinSize = 5; // ์ถํ ๋ง์ฐ์ค ์ธ/์์ ์์๋ ํ์ฉํด์ผ ํ๋ node์ font์ ์ต๋๊ฐ/์ต์๊ฐ์ ๋ณ์๋ก ๋นผ์ค๋๋ค const cy = cytoscape({ container: document.getElementById("cy"), // container to render in elements: data, style: [ // the stylesheet for the graph { selector: "node", style: { "background-color": "#666", label: "data(label)", width: function (ele) { return nodeMaxSize * pageRank.rank("#" + ele.id()) + nodeMinSize; }, height: function (ele) { return nodeMaxSize * pageRank.rank("#" + ele.id()) + nodeMinSize; }, "font-size": function (ele) { return fontMaxSize * pageRank.rank("#" + ele.id()) + fontMinSize; }, }, }, ], layout: { name: "cose-bilkent", animate: false, gravityRangeCompound: 1.5, fit: true, tile: true, }, }); ... ๋ง์นจ๋ด depth์ ๋ฐ๋ผ ํฌ๊ธฐ๊ฐ ์ฐจ๋ฑ ์ ์ฉ๋๋ ๋ถ๋ถ๊น์ง๋ ๊ตฌํ์ด ๋๋ฌ์ต๋๋ค.
๋๋ณด๊ธฐ์์์๋ ์ ์์ง๋ง ๋ง์ฝ node id์ ๊ณต๋ฐฑ์ด๋ . ์ด ๋ค์ด๊ฐ ์์ผ๋ฉด ์ด ๋ถ๋ถ์์ ์๋ฌ๊ฐ ๋ฐ์ํฉ๋๋ค.
target์ผ๋ก depth๊ฐ ๊น์ ์๋ก rank ๊ฐ์ด ๋๊ฒ ์ ์ฉ๋๋๊ตฐ์.
์์์ source์ target์ ๊ฑฐ๊พธ๋ก ์ ์ ์ด์ ๊ฐ ์ด rank ๊ฐ ๋งํผ node์ ํฌ๊ธฐ๋ฅผ ์ค์ ํ๊ธฐ ์ํด์์ ๋๋คโจ ๋ง์ฐ์ค ์ธ / ์์์ ํ์ด๋ผ์ดํธ ์ ์ฉ / ํด์
์ด์ ๋ง์ฐ์ค ์ธ / ์์์ ํ์ด๋ผ์ดํธ ์ ์ฉ / ํด์ ๊ธฐ๋ฅ์ ๊ตฌํํด๋ด ์๋ค.
๋ง์ฐ์ค ์ธ/์์ ๊ฐ์ง ๋ ๋ชจ๋ ํด๋ฆญ์ ํ์ดํผ๋งํฌ ์ฐ๊ฒฐ ๊ธฐ๋ฅ ๊ตฌํ๋ ์ฌ์ฉํ on ๋ฉ์๋๋ฅผ ์ฌ์ฉํฉ๋๋ค.This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters... cy.on('tap', function (e) {...}); cy.on('tapstart mouseover', 'node', function(e){ console.log("in"); }); cy.on('tapend mouseout', 'node', function(e){ console.log("out"); }); ๋จผ์ ์์ ๊ฐ์ด ์์ฑํด ์ ๊ฐ์งํ๋์ง ํ์ธํด์ค์๋ค.
์ ์๋ํ๋ค๋ฉด ๋ค์์ node์ edge์ style์ ๋ฐ๊ฟ์ค ํจ์๋ฅผ ์์ฑํ ์ฐจ๋กํฉ๋๋ค.๋จผ์ ์ฌ์ฉํ ์๊ณผ ํฌ๊ธฐ๊ฐ๋ค์ ๋ณ์๋ก ๊บผ๋ ์๋ค. ์์ ์ ์ฌ๊ธฐ์ ์ ํํ์ต๋๋ค. ์ ํ node์ ํฌ๊ธฐ์ ์, font ํฌ๊ธฐ, edge & ํ์ดํ ํฌ๊ธฐ์ ์ ๋ฑ๋ฑ์ ์ค์ ํด
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersconst pageRank = cy_for_rank.elements().pageRank(); // elements๋ค์ rank๋ค์ ๋๋ค. /// ๋ณ๊ฒฝ๋ ๋ถ๋ถ const nodeMaxSize = 50; const nodeMinSize = 5; const nodeActiveSize = 28; const fontMaxSize = 8; const fontMinSize = 5; const fontActiveSize = 7; // node & font ํฌ๊ธฐ ๊ฐ const edgeWidth = '2px'; var edgeActiveWidth = '4px'; const arrowScale = 0.8; const arrowActiveScale = 1.2; // edge & arrow ํฌ๊ธฐ๊ฐ const dimColor = '#dfe4ea'; const edgeColor = '#ced6e0'; const nodeColor = '#57606f'; const nodeActiveColor = '#ffa502'; const successorColor = '#ff6348'; // ์์ node & edge color const predecessorsColor = '#1e90ff'; // ํ์ node & edge color // ๋ณ๊ฒฝ๋ ๋ถ๋ถ const cy = cytoscape({...}); ์์ ์์น์ ์์ฑํด์ค๋๋ค. ๊ฐ์ ๋ณ์๋ก ๋นผ๋์ผ๋ ํ๋์ฝ๋ฉ ๋์ด ์๋ style ๊ฐ๋ ๋ณ๊ฒฝ์ ํด์ค์ผ๊ฒ ์ฃ
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersstyle: [ // the stylesheet for the graph { selector: 'node', style: { // ๋ณ๊ฒฝ๋ ๋ถ๋ถ 'background-color': nodeColor, // 'label': 'data(label)', 'width': function (ele) { return nodeMaxSize * pageRank.rank('#' + ele.id()) + nodeMinSize; }, 'height': function (ele) { return nodeMaxSize * pageRank.rank('#' + ele.id()) + nodeMinSize; }, 'font-size': function (ele) { return fontMaxSize * pageRank.rank('#' + ele.id()) + fontMinSize; }, // ์ถ๊ฐ๋ ๋ถ๋ถ 'color': nodeColor // } }, { selector: 'edge', style: { // ๋ณ๊ฒฝ๋ ๋ถ๋ถ 'width': edgeWidth, 'curve-style': 'bezier', 'line-color': edgeColor, 'source-arrow-color': edgeColor, 'source-arrow-shape': 'vee', 'arrow-scale': arrowScale // } } ], ์์ ๊ฐ์ด ๋ฐ๊ฟจ์ผ๋ฉด ์ด์ ์ด ๋ค๊ฐ์ ํจ์๋ฅผ ๋ง๋ค์ด์ผ ํฉ๋๋ค. ๊ฐ๊ฐ์ ์ด๋ฆ๊ณผ ์ญํ ์ ์๋์ ๊ฐ์ต๋๋ค.
- setDimStyle(target_cy, style)
๋ชจ๋ node์ edge๋ฅผ ์ฐํ๊ฒ ๋ง๋๋ ์ญํ ์ ํฉ๋๋ค. - setFocus(target_element, successorColor, predecessorsColor, edgeWidth, arrowScale)
์ ํํ node ์ edge, ๊ทธ๋ฆฌ๊ณ ์ํ์ node์ edge๋ฅผ ํฌ๊ธฐ์ ์์ผ๋ก ๊ตฌ๋ถํ๋ ์ญํ ์ ํฉ๋๋ค. - setOpacityElement(target_element, degree)
opacity๋ฅผ ํ์ฉํด ๋ฐ๋ก ์ด์ํ ์ฐ๊ด๊ด๊ณ์ ๊ทธ๋ ์ง ์์ ์ฐ๊ด ๊ด๊ณ๋ฅผ ๊ตฌ๋ถํ๋ ์ญํ ์ ํฉ๋๋ค. - setResetFocus(target_cy)
node๋ฅผ ์ ํํ๊ธฐ ์ ์ ์ํ๋ก ๋๋๋ฆฌ๋ ์ญํ ์ ํฉ๋๋ค.
ํจ์์ ์์ธ ์ฝ๋๋ ์๋์ ๊ฐ์ต๋๋ค
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersfunction setDimStyle(target_cy, style) { target_cy.nodes().forEach(function (target) { target.style(style); }); target_cy.edges().forEach(function (target) { target.style(style); }); } function setFocus(target_element, successorColor, predecessorsColor, edgeWidth, arrowScale) { target_element.style('background-color', nodeActiveColor); target_element.style('color', nodeColor); target_element.successors().each(function (e) { // ์์ ์ฃ์ง์ ๋ ธ๋ if (e.isEdge()) { e.style('width', edgeWidth); e.style('arrow-scale', arrowScale); } e.style('color', nodeColor); e.style('background-color', successorColor); e.style('line-color', successorColor); e.style('source-arrow-color', successorColor); setOpacityElement(e, 0.5); } ); target_element.predecessors().each(function (e) { // ํ์ ์ฃ์ง์ ๋ ธ๋ if (e.isEdge()) { e.style('width', edgeWidth); e.style('arrow-scale', arrowScale); } e.style('color', nodeColor); e.style('background-color', predecessorsColor); e.style('line-color', predecessorsColor); e.style('source-arrow-color', predecessorsColor); setOpacityElement(e, 0.5); }); target_element.neighborhood().each(function (e) { // ์ด์ํ ์ฃ์ง์ ๋ ธ๋ setOpacityElement(e, 1); } ); target_element.style('width', Math.max(parseFloat(target_element.style('width')), nodeActiveSize)); target_element.style('height', Math.max(parseFloat(target_element.style('height')), nodeActiveSize)); target_element.style('font-size', Math.max(parseFloat(target_element.style('font-size')), fontActiveSize)); } function setOpacityElement(target_element, degree) { target_element.style('opacity', degree); } function setResetFocus(target_cy) { target_cy.nodes().forEach(function (target) { target.style('background-color', nodeColor); var rank = pageRank.rank(target); target.style('width', nodeMaxSize * rank + nodeMinSize); target.style('height', nodeMaxSize * rank + nodeMinSize); target.style('font-size', fontMaxSize * rank + fontMinSize); target.style('color', nodeColor); target.style('opacity', 1); }); target_cy.edges().forEach(function (target) { target.style('line-color', edgeColor); target.style('source-arrow-color', edgeColor); target.style('width', edgeWidth); target.style('arrow-scale', arrowScale); target.style('opacity', 1); }); } ์ด์ฒ๋ผ ์์ฑํด์ฃผ์๊ณ , ํจ์๋ฅผ ๋ง๋ค์์ผ๋ ์ฌ์ฉํด์ผ๊ฒ ์ฃ . ์๊น ๋ง๋ค์ด ๋ mouse in๊ณผ out์ ๊ฐ์งํ๋ ๋ถ๋ถ์
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characterscy.on('tapstart mouseover', 'node', function (e) { setDimStyle(cy, { 'background-color': dimColor, 'line-color': dimColor, 'source-arrow-color': dimColor, 'color': dimColor }); setFocus(e.target, successorColor, predecessorsColor, edgeActiveWidth, arrowActiveScale); }); cy.on('tapend mouseout', 'node', function (e) { setResetFocus(e.cy); }); ์์ ๊ฐ์ด ํจ์๋ฅผ ์ธํ ํด์ค๋๋ค. ๊ทธ๋ฌ๋ฉด
์ธ ์์ ์ด๋ฒคํธ๊ฐ ์ ์๋ํฉ๋๋ค!
๐ ๋ธ๋ผ์ฐ์ ํฌ๊ธฐ ๋ณ๊ฒฝ์ cytoscape ํฌ๊ธฐ ์กฐ์
์ด์ ๋ธ๋ผ์ฐ์ ํฌ๊ธฐ ๋ณ๊ฒฝ์ cytoscape์ ํฌ๊ธฐ๊ฐ ์๋์ผ๋ก ์กฐ์ ๋๊ฒ ํด๋ด ์๋ค. seomal.org์ ๊ฒฝ์ฐ
์์ ๊ฐ์ด ๋ธ๋ผ์ฐ์ ์ ํฌ๊ธฐ๊ฐ ๋ณ๊ฒฝ๋๋ ๊ฒฝ์ฐ cytoscape์ ํฌ๊ธฐ๊ฐ ์๋์ผ๋ก ๋ณํ์ง๋ง
์ฐ๋ฆฐ ๊ฐ๋ฐ์ ๋๊ตฌ๋ฅผ ์ด์ด๋ ์๋ฌด ๋ณํ๊ฐ ์์ต๋๋ค. ์ด ๊ธฐ๋ฅ์ ์ถ๊ฐํด๋ด ์๋ค. ์ ์ฉ์ ๊ฐ๋จํฉ๋๋ค.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characterscy.on('tapend mouseout', 'node', function (e) {...}); // ์ถ๊ฐ๋๋ ๋ถ๋ถ let resizeTimer; window.addEventListener('resize', function () { this.clearTimeout(resizeTimer); resizeTimer = this.setTimeout(function(){ cy.fit(); },200); }); // ์์ ๊ฐ์ ์ฝ๋๋ฅผ ์ถ๊ฐํด์ฃผ๋ฉด
๋ธ๋ผ์ฐ์ ํฌ๊ธฐ ๋ณ๊ฒฝ์ cytoscape ํฌ๊ธฐ๊ฐ ์๋์ผ๋ก ์ ๋ณ๊ฒฝ๋ฉ๋๋ค!
๋๋ณด๊ธฐ์ ์ฝ๋์์ clearTimout๊ณผ setTimout ๋ถ๋ถ์ ์ ์ธํ๋ฉด resize ๊ฐ์ง๋ ๋๋๋ฐ cy.fit() ์คํ์ ์๋๋๊ตฐ์. ์ผ๋จ ์ฌ๊ธฐ๋ฅผ ์ฐธ๊ณ ํด ํด๊ฒฐ์ ํ๋๋ฐ ์ด๋ ๊ฒ ์๋ํ๋ ์์ธํ ์ด์ ๋ฅผ ์๋ ๋ถ ํน์ ๊ณ์๋ฉด ๋๊ธ ๋ถํ๋๋ฆฝ๋๋ค!
๐ซ data ์ถ์ถ
๊ธฐ๋ฅ์ ๋ค ๊ตฌํํ์ผ๋ ์ด์ ๋ง์ง๋ง์ผ๋ก ํ์ผ์ ์ ๋ฆฌํ๊ธฐ ์ํด data๋ฅผ ๋ณ๋์ json ํ์ผ๋ก ์ถ์ถํด๋ด ์๋ค.
์์ ๊ฐ์ด model ํด๋ ํ์์ data.json ํ์ผ์ ๋ง๋ค๊ณ
๊ทธ ๋ค์์ webpack.config.js ํ์ผ๋ก ๊ฐ์ module - rules์
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersmodule: { rules: [ { test: /\.(js|jsx)$/, exclude: "/node_modules", use: ["babel-loader"], }, { test: /\.html$/, use: [ { loader: "html-loader", options: { minimize: true }, }, ], }, { test: /\.css$/, use: [MiniCssExtractPlugin.loader, "css-loader"], }, { test: /\.json$/, type: "javascript/auto", loader: "file-loader", options: { name: "model/[name].[ext]", }, include: [path.resolve(__dirname, "./model")], }, ], }, ์์ฒ๋ผ json ๊ด๋ จ ์ค์ ์ ์ถ๊ฐํด์ค๋๋ค. ์ดํ์ index.js ์์ data ๋ณ์๋ก ๋ฐ๋
const data = [...];
[ ] ์ ํฌํจํ์ฌ ๊ทธ ์์ ์๋ ๋ชจ๋ ๋ฐ์ดํฐ๋ค์ ๋ณต์ฌํด์ model - data.json์ ๋ถ์ฌ๋ฃ๊ธฐ ํด์ค๋๋ค.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters... import '../model/data.json'; fetch('./model/data.json', { mode: 'no-cors' }) .then(function (res) { return res.json(); }) .then(function (data) { // ๊ธฐ์กด ์ฝ๋ ์ด ์์ผ๋ก ๋ถ์ฌ๋ฃ๊ธฐ! }); ์ดํ์ index.js ์๋จ์ data.json ๊ฒฝ๋ก๋ฅผ ์ํฌํธ ํด์ฃผ๊ณ import ๋ถ๋ถ์ ์ ์ธํ ๊ธฐ์กด ์ฝ๋๋ฅผ data.json fetch ํจ์ ์์ผ๋ก ์ง์ด๋ฃ์ผ๋ฉด
ํ๋ฉด์ด ์ ๋์ต๋๋ค! ์ดํ์ gh pages๋ netlify๋ฅผ ํ์ฉํด ๋ฐฐํฌ ํ ์ฌ์ฉํ์๋ฉด ๋ฉ๋๋ค!
๐ ๋ง์น๋ฉฐ
ํด๋น ํ๋ก์ ํธ์ ์งํ ๊ณผ์ ์ github project์ ์ ๋ฆฌํด๋๊ณ ์์ค์ฝ๋๋ repository์ ์ฌ๋ ค๋์ผ๋
์ค๋ช ์ด ๋ถ์กฑํ๋ ๋ถ๋ถ์ ์ด ๋ ๊ณณ์ ์ฐธ๊ณ ํด์ฃผ์๊ณ ์ง๋ฌธ์ ๋๊ธ์ ๋จ๊ฒจ์ฃผ์ธ์!๋ชจ์ชผ๋ก ๋์์ด ๋์์ผ๋ฉด ์ข๊ฒ ์ต๋๋ค!
๋ฐ์ํ'Project > Web' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
๋ฝ๋ชจ๋๋ก ํ์ด๋จธ / Pomodoro Timer ์นํ์ด์ง ๊ฐ๋ฐ (0) 2018.06.17 - setDimStyle(target_cy, style)