From 90c669f0a6e963debe0d66c584eda2ff0bc8493d Mon Sep 17 00:00:00 2001 From: RaymondDashWu Date: Wed, 15 Jul 2020 19:28:44 -0700 Subject: [PATCH 01/17] [ADD] Export button. Wooogit status Took a while to find out where that code livedgit status --- src/components/common/animation-control/animation-control.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/components/common/animation-control/animation-control.js b/src/components/common/animation-control/animation-control.js index c50e88846e..0812d11460 100644 --- a/src/components/common/animation-control/animation-control.js +++ b/src/components/common/animation-control/animation-control.js @@ -161,7 +161,9 @@ function AnimationControlFactory( /> + + ); } From f6db6ddca19683357ce4fda4169e4a2f9084a53c Mon Sep 17 00:00:00 2001 From: RaymondDashWu Date: Thu, 16 Jul 2020 09:55:23 -0700 Subject: [PATCH 02/17] [FIX] Use common styled components for button --- src/components/common/animation-control/animation-control.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/common/animation-control/animation-control.js b/src/components/common/animation-control/animation-control.js index 0812d11460..bf3f71f8ba 100644 --- a/src/components/common/animation-control/animation-control.js +++ b/src/components/common/animation-control/animation-control.js @@ -23,7 +23,7 @@ import styled from 'styled-components'; import moment from 'moment'; import Slider from 'components/common/slider/slider'; -import {BottomWidgetInner} from 'components/common/styled-components'; +import {BottomWidgetInner, Button} from 'components/common/styled-components'; import SpeedControlFactory from './speed-control'; import AnimationPlaybacksFactory from './playback-controls'; import FloatingTimeDisplayFactory from './floating-time-display'; @@ -161,7 +161,7 @@ function AnimationControlFactory( /> - + From a466b1c34d5003b947208b2deb7a5aee9329153f Mon Sep 17 00:00:00 2001 From: RaymondDashWu Date: Thu, 16 Jul 2020 22:37:51 -0700 Subject: [PATCH 03/17] [ADD] Styled button + function to handle click in progress --- .../common/animation-control/animation-control.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/components/common/animation-control/animation-control.js b/src/components/common/animation-control/animation-control.js index bf3f71f8ba..2a9dfaeb5d 100644 --- a/src/components/common/animation-control/animation-control.js +++ b/src/components/common/animation-control/animation-control.js @@ -101,6 +101,10 @@ function AnimationControlFactory( this.props.updateAnimationTime(Array.isArray(value) ? value[0] : value); }; + handleExport = () => { + console.log(this); + } + render() { const {currentTime, domain, speed, step, timeSteps} = this.props.animationConfig; const {showSpeedControl} = this.state; @@ -161,7 +165,7 @@ function AnimationControlFactory( /> - + From de80a23e8da98cbe7e79b3e90a3c9d93e9b5097b Mon Sep 17 00:00:00 2001 From: RaymondDashWu Date: Mon, 20 Jul 2020 19:20:40 -0700 Subject: [PATCH 04/17] [ADD] log of all passed down props --- .../animation-control/animation-control.js | 17 +++++-- src/components/hubble-export.js | 48 +++++++++++++++++++ 2 files changed, 62 insertions(+), 3 deletions(-) create mode 100644 src/components/hubble-export.js diff --git a/src/components/common/animation-control/animation-control.js b/src/components/common/animation-control/animation-control.js index 2a9dfaeb5d..0da5eda664 100644 --- a/src/components/common/animation-control/animation-control.js +++ b/src/components/common/animation-control/animation-control.js @@ -19,7 +19,7 @@ // THE SOFTWARE. import React from 'react'; -import styled from 'styled-components'; +import styled, { withTheme } from 'styled-components'; import moment from 'moment'; import Slider from 'components/common/slider/slider'; @@ -30,6 +30,9 @@ import FloatingTimeDisplayFactory from './floating-time-display'; import AnimationControllerFactory from './animation-controller'; import {snapToMarks} from 'utils/data-utils'; import {DEFAULT_TIME_FORMAT, ANIMATION_TYPE} from 'constants'; +import HubbleExport from 'components/hubble-export'; +import {connect as keplerGlConnect} from 'connect/keplergl-connect'; + const SliderWrapper = styled.div` display: flex; @@ -102,7 +105,13 @@ function AnimationControlFactory( }; handleExport = () => { - console.log(this); + + // log all the props from mapComponent/mapComponentFactory + // stop rendering in bg + // setState + // pop up modal if isOpen. If false, closes modal TODO put function into render + // all the data is passed through and can use in deck/hubble components + return keplerGlConnect(mapStateToProps, makeMapDispatchToProps)(withTheme(KeplerGL)); } render() { @@ -165,7 +174,9 @@ function AnimationControlFactory( /> - + {/* Button or clickable interface */} + {/* Once "Export" button is clicked, this.state.isOpen: === True, once "X" is clicked, isOpen === False */} + {/* */} diff --git a/src/components/hubble-export.js b/src/components/hubble-export.js new file mode 100644 index 0000000000..2b8e0be916 --- /dev/null +++ b/src/components/hubble-export.js @@ -0,0 +1,48 @@ +import React, {Component} from 'react'; +import styled, {withTheme} from 'styled-components'; +import {connect as keplerGlConnect} from 'connect/keplergl-connect'; + +function mapStateToProps(state = {}, props) { + return { + ...props, + visState: state.visState, + mapStyle: state.mapStyle, + mapState: state.mapState, + uiState: state.uiState, + providerState: state.providerState + }; +} + +function makeMapDispatchToProps() { + // const getActionCreators = makeGetActionCreators(); + const mapDispatchToProps = (dispatch, ownProps) => { + // const groupedActionCreators = getActionCreators(dispatch, ownProps); + + return { + // ...groupedActionCreators, + dispatch + }; + }; + + return mapDispatchToProps; +} + +class HubbleExport extends Component { + // To be used to store all modal components & functions +// this.states = [ // React props +// keyframes: abstraction of keyframes, +// dlsjkas, +// ] + render() { + console.log(this.props) + return (
REACHED
) + // console.log(this.props) // might need to return div + } +}; + +// States we need: +// +// +// +export default keplerGlConnect(mapStateToProps, makeMapDispatchToProps)(withTheme(HubbleExport)); + From e780a6c286758a7ec51441657c93e790389c1ff8 Mon Sep 17 00:00:00 2001 From: RaymondDashWu Date: Wed, 22 Jul 2020 10:19:05 -0700 Subject: [PATCH 05/17] [BLOCKED] Can't figure out how to use Hubble modal --- package.json | 1 + .../animation-control/animation-control.js | 13 +-- src/components/hubble-export.js | 35 +++++- src/reducers/vis-state-selectors.js | 20 ++++ yarn.lock | 104 +++++++++++++++++- 5 files changed, 158 insertions(+), 15 deletions(-) diff --git a/package.json b/package.json index 391eea3a1c..1b6ffd54f8 100644 --- a/package.json +++ b/package.json @@ -115,6 +115,7 @@ "global": "^4.3.0", "h3-js": "^3.1.0", "html-webpack-plugin": "^4.3.0", + "hubble.gl": "^1.0.1", "keymirror": "^0.1.1", "lodash.clonedeep": "^4.0.1", "lodash.curry": "^4.1.1", diff --git a/src/components/common/animation-control/animation-control.js b/src/components/common/animation-control/animation-control.js index 0da5eda664..47d1bbab64 100644 --- a/src/components/common/animation-control/animation-control.js +++ b/src/components/common/animation-control/animation-control.js @@ -104,16 +104,6 @@ function AnimationControlFactory( this.props.updateAnimationTime(Array.isArray(value) ? value[0] : value); }; - handleExport = () => { - - // log all the props from mapComponent/mapComponentFactory - // stop rendering in bg - // setState - // pop up modal if isOpen. If false, closes modal TODO put function into render - // all the data is passed through and can use in deck/hubble components - return keplerGlConnect(mapStateToProps, makeMapDispatchToProps)(withTheme(KeplerGL)); - } - render() { const {currentTime, domain, speed, step, timeSteps} = this.props.animationConfig; const {showSpeedControl} = this.state; @@ -174,7 +164,8 @@ function AnimationControlFactory( /> - {/* Button or clickable interface */} + + {/* Once "Export" button is clicked, this.state.isOpen: === True, once "X" is clicked, isOpen === False */} {/* */} diff --git a/src/components/hubble-export.js b/src/components/hubble-export.js index 2b8e0be916..c8db874dfb 100644 --- a/src/components/hubble-export.js +++ b/src/components/hubble-export.js @@ -1,7 +1,13 @@ import React, {Component} from 'react'; -import styled, {withTheme} from 'styled-components'; +import {ThemeProvider, withTheme} from 'styled-components'; + import {connect as keplerGlConnect} from 'connect/keplergl-connect'; +import RenderSettingsModal from 'hubble.gl'; +import {Button} from 'components/common/styled-components'; +import {theme} from '../styles'; + +// TODO this isn't DRY. Comes from https://github.com/keplergl/kepler.gl/blob/995024e86880fefb0624af4ed1e98d3879558336/src/components/kepler-gl.js function mapStateToProps(state = {}, props) { return { ...props, @@ -28,15 +34,38 @@ function makeMapDispatchToProps() { } class HubbleExport extends Component { + constructor(props) { + super(props); + this.state = { + isOpen: false + }; + } // To be used to store all modal components & functions // this.states = [ // React props // keyframes: abstraction of keyframes, // dlsjkas, // ] + handleExport() { + this.setState(state => ({ + isOpen: !state.isOpen + })); + console.log("Reached") + + // stop rendering in bg + // setState + // pop up modal if isOpen. If false, closes modal TODO put function into render + // all the data is passed through and can use in deck/hubble components + return

REACHED

+ } + render() { console.log(this.props) - return (
REACHED
) - // console.log(this.props) // might need to return div + return ( +
+ + +
+ ) } }; diff --git a/src/reducers/vis-state-selectors.js b/src/reducers/vis-state-selectors.js index 7a3b5c3220..43c0594d1a 100644 --- a/src/reducers/vis-state-selectors.js +++ b/src/reducers/vis-state-selectors.js @@ -1,3 +1,23 @@ +// Copyright (c) 2020 Uber Technologies, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + import {createSelector} from 'reselect'; // NOTE: default formats must match file-handler.js diff --git a/yarn.lock b/yarn.lock index 0fcb1e199e..2213c1cba8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1356,6 +1356,21 @@ dependencies: "@hapi/hoek" "^8.3.0" +"@hubble.gl/core@1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@hubble.gl/core/-/core-1.0.1.tgz#f46a964e781ad685fa82bf2e6197f1b17817422c" + integrity sha512-dKRknK4xkOFAc0AYVHSvdN+4Fkfyv114G9g4umTHtgHnlFP6FxkVpkYMoN0ZXuyz+dmetfYYwSMhQVpRxh6adQ== + dependencies: + "@luma.gl/engine" "^8.1.2" + downloadjs "^1.4.7" + popmotion "^8.6.10" + webm-writer "^0.2.2" + +"@hubble.gl/react@1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@hubble.gl/react/-/react-1.0.1.tgz#e98eecf149fdca5974d94ad26c9f6547446ae2f8" + integrity sha512-yuDbW8HD204Ybd+ZMTxmBtX8Lb8FjmdS52rTm1JlPTzKPDOoxNLSk9YW1l+i3XnuzvfR+BWDnzYiIpi+BAkM/A== + "@icons/material@^0.2.4": version "0.2.4" resolved "https://registry.yarnpkg.com/@icons/material/-/material-0.2.4.tgz#e90c9f71768b3736e76d7dd6783fc6c2afa88bc8" @@ -2293,6 +2308,14 @@ "@babel/runtime" "^7.3.1" "@probe.gl/stats" "^3.3.0" +"@loaders.gl/loader-utils@^2.2.5": + version "2.2.8" + resolved "https://registry.yarnpkg.com/@loaders.gl/loader-utils/-/loader-utils-2.2.8.tgz#9f12f3460260b15e961fa46c3d3c867d7bf48bee" + integrity sha512-3F2VgxJPxjuZwAr8fDBkZzx3Wg275XdVaWnyYQ3uyZQ22yGEkrzKc+TlgcqSrxbO5pHrtS5PdS7dmyoJo2+Bdg== + dependencies: + "@babel/runtime" "^7.3.1" + "@probe.gl/stats" "^3.3.0" + "@loaders.gl/math@2.2.5": version "2.2.5" resolved "https://registry.yarnpkg.com/@loaders.gl/math/-/math-2.2.5.tgz#d3c52a75821b5934e54dd82211a372a69ec6474e" @@ -2369,7 +2392,7 @@ "@luma.gl/shadertools" "8.2.0" "@luma.gl/webgl" "8.2.0" -"@luma.gl/engine@8.2.0": +"@luma.gl/engine@8.2.0", "@luma.gl/engine@^8.1.2": version "8.2.0" resolved "https://registry.yarnpkg.com/@luma.gl/engine/-/engine-8.2.0.tgz#e598b723639619e00cff8acaf4af39de4d9fb61f" integrity sha512-HxlwU66TCJzMCY+wuxiyapiGFEp0HrRqg2m2fj8K5h5PBYMjDZSrs2JuDoOz97oFVALfujAEw74OX9pFr5uiRg== @@ -2666,6 +2689,22 @@ dependencies: "@types/node" ">= 8" +"@popmotion/easing@^1.0.1": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@popmotion/easing/-/easing-1.0.2.tgz#17d925c45b4bf44189e5a38038d149df42d8c0b4" + integrity sha512-IkdW0TNmRnWTeWI7aGQIVDbKXPWHVEYdGgd5ZR4SH/Ty/61p63jCjrPxX1XrR7IGkl08bjhJROStD7j+RKgoIw== + +"@popmotion/popcorn@^0.4.4": + version "0.4.4" + resolved "https://registry.yarnpkg.com/@popmotion/popcorn/-/popcorn-0.4.4.tgz#a5f906fccdff84526e3fcb892712d7d8a98d6adc" + integrity sha512-jYO/8319fKoNLMlY4ZJPiPu8Ea8occYwRZhxpaNn/kZsK4QG2E7XFlXZMJBsTWDw7I1i0uaqyC4zn1nwEezLzg== + dependencies: + "@popmotion/easing" "^1.0.1" + framesync "^4.0.1" + hey-listen "^1.0.8" + style-value-types "^3.1.7" + tslib "^1.10.0" + "@probe.gl/stats@3.2.1": version "3.2.1" resolved "https://registry.yarnpkg.com/@probe.gl/stats/-/stats-3.2.1.tgz#4e95c75513229ebb01384045e89524a466c022eb" @@ -6151,6 +6190,11 @@ dotignore@~0.1.2: dependencies: minimatch "^3.0.4" +downloadjs@^1.4.7: + version "1.4.7" + resolved "https://registry.yarnpkg.com/downloadjs/-/downloadjs-1.4.7.tgz#f69f96f940e0d0553dac291139865a3cd0101e3c" + integrity sha1-9p+W+UDg0FU9rCkROYZaPNAQHjw= + draco3d@^1.3.4: version "1.3.6" resolved "https://registry.yarnpkg.com/draco3d/-/draco3d-1.3.6.tgz#e4d9e7d846637775328c903721c932b953dce331" @@ -7370,6 +7414,14 @@ fragment-cache@^0.2.1: dependencies: map-cache "^0.2.2" +framesync@^4.0.0, framesync@^4.0.1: + version "4.0.4" + resolved "https://registry.yarnpkg.com/framesync/-/framesync-4.0.4.tgz#79c42c0118f26821c078570db0ff81fb863516a2" + integrity sha512-mdP0WvVHe0/qA62KG2LFUAOiWLng5GLpscRlwzBxu2VXOp6B8hNs5C5XlFigsMgrfDrr2YbqTsgdWZTc4RXRMQ== + dependencies: + hey-listen "^1.0.8" + tslib "^1.10.0" + fresh@0.5.2: version "0.5.2" resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" @@ -8131,6 +8183,11 @@ he@1.2.x, he@^1.1.0, he@^1.2.0: resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== +hey-listen@^1.0.5, hey-listen@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/hey-listen/-/hey-listen-1.0.8.tgz#8e59561ff724908de1aa924ed6ecc84a56a9aa68" + integrity sha512-COpmrF2NOg4TBWUJ5UVyaCU2A88wEMkUPK4hNqyCkqHbxT92BbvfjoSozkAIIm6XhicGlJHhFdullInrdhwU8Q== + highlight.js@^10.0.0: version "10.0.3" resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-10.0.3.tgz#5effcc58420f113f279a0badb8ac50c4be06e63b" @@ -8420,6 +8477,14 @@ https-proxy-agent@^4.0.0: agent-base "5" debug "4" +hubble.gl@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/hubble.gl/-/hubble.gl-1.0.1.tgz#06845da48be6e45163bb78a6151188a5b7d4ade5" + integrity sha512-hrFSaXhBrLRzx0EuDKMFrzPIhahU+YYB5Wm9jp1pyIuC58VHz2qwKr/G//3Bzv0O84C/NrJEkWsdnSxHyyMaPw== + dependencies: + "@hubble.gl/core" "1.0.1" + "@hubble.gl/react" "1.0.1" + human-signals@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-1.1.1.tgz#c5b1cd14f50aeae09ab6c59fe63ba3395fe4dfa3" @@ -12490,6 +12555,19 @@ pngjs@^3.0.0, pngjs@^3.3.3: resolved "https://registry.yarnpkg.com/pngjs/-/pngjs-3.4.0.tgz#99ca7d725965fb655814eaf65f38f12bbdbf555f" integrity sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w== +popmotion@^8.6.10: + version "8.7.3" + resolved "https://registry.yarnpkg.com/popmotion/-/popmotion-8.7.3.tgz#330a77fd8b288f0e8f930e3d3f351d6eb4897860" + integrity sha512-OcpS/V9sCJjrKiVfp3JB5kp5SBqefZ4RvM9GBLYgv0YbULxv9S5METP9ueVJxSClR3yrfFEY2pLWTWKLn/EUfg== + dependencies: + "@popmotion/easing" "^1.0.1" + "@popmotion/popcorn" "^0.4.4" + framesync "^4.0.0" + hey-listen "^1.0.5" + style-value-types "^3.1.7" + stylefire "^7.0.1" + tslib "^1.10.0" + portfinder@^1.0.25: version "1.0.25" resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.25.tgz#254fd337ffba869f4b9d37edc298059cb4d35eca" @@ -15076,6 +15154,14 @@ strong-log-transformer@^2.0.0: minimist "^1.2.0" through "^2.3.4" +style-value-types@^3.1.7: + version "3.1.7" + resolved "https://registry.yarnpkg.com/style-value-types/-/style-value-types-3.1.7.tgz#3d7d3cf9cb9f9ee86c00e19ba65d6a181a0db33a" + integrity sha512-jPaG5HcAPs3vetSwOJozrBXxuHo9tjZVnbRyBjxqb00c2saIoeuBJc1/2MtvB8eRZy41u/BBDH0CpfzWixftKg== + dependencies: + hey-listen "^1.0.8" + tslib "^1.10.0" + styled-components@^4.1.3: version "4.4.1" resolved "https://registry.yarnpkg.com/styled-components/-/styled-components-4.4.1.tgz#e0631e889f01db67df4de576fedaca463f05c2f2" @@ -15095,6 +15181,17 @@ styled-components@^4.1.3: stylis-rule-sheet "^0.0.10" supports-color "^5.5.0" +stylefire@^7.0.1: + version "7.0.3" + resolved "https://registry.yarnpkg.com/stylefire/-/stylefire-7.0.3.tgz#9120ecbb084111788e0ddaa04074799750f20d1d" + integrity sha512-Q0l7NSeFz/OkX+o6/7Zg3VZxSAZeQzQpYomWmIpOehFM/rJNMSLVX5fgg6Q48ut2ETNKwdhm97mPNU643EBCoQ== + dependencies: + "@popmotion/popcorn" "^0.4.4" + framesync "^4.0.0" + hey-listen "^1.0.8" + style-value-types "^3.1.7" + tslib "^1.10.0" + stylis-rule-sheet@^0.0.10: version "0.0.10" resolved "https://registry.yarnpkg.com/stylis-rule-sheet/-/stylis-rule-sheet-0.0.10.tgz#44e64a2b076643f4b52e5ff71efc04d8c3c4a430" @@ -16490,6 +16587,11 @@ webidl-conversions@^5.0.0: resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-5.0.0.tgz#ae59c8a00b121543a2acc65c0434f57b0fc11aff" integrity sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA== +webm-writer@^0.2.2: + version "0.2.5" + resolved "https://registry.yarnpkg.com/webm-writer/-/webm-writer-0.2.5.tgz#cca049f392c5e47a328d83590e983f97e8f28fda" + integrity sha512-wzHOIZkvKDOC/GJdOalYlzH0NypLvlaXdUhliTkH7Y5akdmBl0TOVmRTPFW3yfw+cAYS3RMtu5nCYIGovDUsvw== + webpack-bundle-analyzer@^3.0.3, webpack-bundle-analyzer@^3.3.2: version "3.6.0" resolved "https://registry.yarnpkg.com/webpack-bundle-analyzer/-/webpack-bundle-analyzer-3.6.0.tgz#39b3a8f829ca044682bc6f9e011c95deb554aefd" From 0d67d4d162a2ec75b71ac11e1a1822f83443b433 Mon Sep 17 00:00:00 2001 From: RaymondDashWu Date: Wed, 22 Jul 2020 10:21:57 -0700 Subject: [PATCH 06/17] [BLOCKED] Can't figure out how to use Hubble modal --- src/components/hubble-export.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/hubble-export.js b/src/components/hubble-export.js index c8db874dfb..a6d9eb2120 100644 --- a/src/components/hubble-export.js +++ b/src/components/hubble-export.js @@ -2,7 +2,7 @@ import React, {Component} from 'react'; import {ThemeProvider, withTheme} from 'styled-components'; import {connect as keplerGlConnect} from 'connect/keplergl-connect'; -import RenderSettingsModal from 'hubble.gl'; +import * as RenderSettingsModal from 'hubble.gl'; import {Button} from 'components/common/styled-components'; import {theme} from '../styles'; From a8184a03ba6ebaca9e5cb492f727d7237aca8bca Mon Sep 17 00:00:00 2001 From: RaymondDashWu Date: Wed, 22 Jul 2020 10:23:23 -0700 Subject: [PATCH 07/17] [BLOCKED] Can't figure out how to use Hubble modal --- src/components/hubble-export.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/hubble-export.js b/src/components/hubble-export.js index a6d9eb2120..3fe68d0ec1 100644 --- a/src/components/hubble-export.js +++ b/src/components/hubble-export.js @@ -2,7 +2,7 @@ import React, {Component} from 'react'; import {ThemeProvider, withTheme} from 'styled-components'; import {connect as keplerGlConnect} from 'connect/keplergl-connect'; -import * as RenderSettingsModal from 'hubble.gl'; +import * as RenderSettingsModal from 'hubble.gl/animation-control/render-settings-modal'; import {Button} from 'components/common/styled-components'; import {theme} from '../styles'; From c021c70638e96159a6b2e14670b23218c5bc1220 Mon Sep 17 00:00:00 2001 From: RaymondDashWu Date: Wed, 22 Jul 2020 11:47:21 -0700 Subject: [PATCH 08/17] [ADD] Modal open/close states --- src/components/hubble-export.js | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/src/components/hubble-export.js b/src/components/hubble-export.js index 3fe68d0ec1..e6158dd9ff 100644 --- a/src/components/hubble-export.js +++ b/src/components/hubble-export.js @@ -2,7 +2,7 @@ import React, {Component} from 'react'; import {ThemeProvider, withTheme} from 'styled-components'; import {connect as keplerGlConnect} from 'connect/keplergl-connect'; -import * as RenderSettingsModal from 'hubble.gl/animation-control/render-settings-modal'; +// import * as RenderSettingsModal from 'hubble.gl/animation-control/render-settings-modal'; import {Button} from 'components/common/styled-components'; import {theme} from '../styles'; @@ -45,12 +45,16 @@ class HubbleExport extends Component { // keyframes: abstraction of keyframes, // dlsjkas, // ] + handleClose() { + this.setState(state => ({ + isOpen: false + })); + } + handleExport() { this.setState(state => ({ - isOpen: !state.isOpen - })); - console.log("Reached") - + isOpen: true + })); // stop rendering in bg // setState // pop up modal if isOpen. If false, closes modal TODO put function into render @@ -59,11 +63,13 @@ class HubbleExport extends Component { } render() { - console.log(this.props) + // console.log(this.props) + console.log(this.state) return (
- - + {/* */} + {/* anonymous function to bind state onclick */} +
) } From 93e080edc6b138836e4052bd4e17c4b4035f5344 Mon Sep 17 00:00:00 2001 From: RaymondDashWu Date: Thu, 23 Jul 2020 12:48:16 -0700 Subject: [PATCH 09/17] [ADD] Open/Close functionality of mock modal --- src/components/hubble-export.js | 16 +- src/components/render-settings-modal.js | 114 +++++++++++++ src/components/render-settings-panel.js | 207 ++++++++++++++++++++++++ 3 files changed, 327 insertions(+), 10 deletions(-) create mode 100644 src/components/render-settings-modal.js create mode 100644 src/components/render-settings-panel.js diff --git a/src/components/hubble-export.js b/src/components/hubble-export.js index e6158dd9ff..f48cd6a60f 100644 --- a/src/components/hubble-export.js +++ b/src/components/hubble-export.js @@ -2,7 +2,7 @@ import React, {Component} from 'react'; import {ThemeProvider, withTheme} from 'styled-components'; import {connect as keplerGlConnect} from 'connect/keplergl-connect'; -// import * as RenderSettingsModal from 'hubble.gl/animation-control/render-settings-modal'; +import RenderSettingsModal from './render-settings-modal'; import {Button} from 'components/common/styled-components'; import {theme} from '../styles'; @@ -45,16 +45,12 @@ class HubbleExport extends Component { // keyframes: abstraction of keyframes, // dlsjkas, // ] - handleClose() { - this.setState(state => ({ - isOpen: false - })); - } + handleClose() {this.setState({isOpen: false})} // X button in Kepler UI was clicked - handleExport() { + handleExport() { // Export button in Kepler UI was clicked this.setState(state => ({ isOpen: true - })); + })); // stop rendering in bg // setState // pop up modal if isOpen. If false, closes modal TODO put function into render @@ -67,9 +63,9 @@ class HubbleExport extends Component { console.log(this.state) return (
- {/* */} + + {/* anonymous function to bind state onclick */} -
) } diff --git a/src/components/render-settings-modal.js b/src/components/render-settings-modal.js new file mode 100644 index 0000000000..e8ce63a24f --- /dev/null +++ b/src/components/render-settings-modal.js @@ -0,0 +1,114 @@ +/* eslint-disable no-invalid-this */ +import React, {Component, createRef} from 'react'; +import styled, {withTheme} from 'styled-components'; +import {createSelector} from 'reselect'; +import RenderSettingsPanel from './render-settings-panel'; +import Modal from 'react-modal'; +import {DIMENSIONS} from 'kepler.gl/constants/default-settings'; + +const ModalContainer = styled.div` + position: relative; +`; + +class RenderSettingsModal extends Component { + static defaultProps = { + defaultSettingsPos: {top: '320px', left: '320px'}, + bottomBuffer: 212 + }; + + root = createRef(); + + // derive settings position based on root component + showSettingsSelector(props) { + return props.showSettings; + } + themeSelector(props) { + return props.theme; + } + settingsPosSelector = createSelector(this.showSettingsSelector, (showSettings, theme = {}) => { + const {defaultSettingsPos, bottomBuffer, settingsHeight} = this.props; + if (showSettings === false || !this.root || !this.root.current) return defaultSettingsPos; + const {sidePanelInnerPadding = 16, sidePanel = {}, sidePanelScrollBarWidth = 10} = theme; + const sidePanelLeft = (sidePanel.margin || {}).left || 20; + const offsetX = sidePanelInnerPadding + sidePanelLeft + sidePanelScrollBarWidth; + // find component Root position + const bounding = this.root.current.getBoundingClientRect(); + const {x, y, width} = bounding; + + // set the top so it won't collide with bottom widget + const top = + y + settingsHeight <= window.innerHeight - bottomBuffer + ? y + : window.innerHeight - bottomBuffer - settingsHeight; + + return {top: `${top}px`, left: `${x + width + offsetX}px`}; + }); + + modalStylesSelector = createSelector( + this.themeSelector, + this.settingsPosSelector, + (theme, settingsPos) => ({ + content: { + top: 'auto', + left: 'auto', + right: `calc(50% - ${DIMENSIONS.sidePanel.width / 2}px)`, + bottom: '50%', + transform: 'translate(50%, 50%)', + padding: '0px 0px 0px 0px', + border: 0, + backgroundColor: theme.sidePanelBg, + borderRadius: theme.panelBorderRadius || '2px' + }, + overlay: { + backgroundColor: 'rgba(0, 0, 0, 0)' + } + // content: { + // top: 0, + // left: 0, + // border: 0, + // right: 'auto', + // bottom: 'auto', + // padding: '0px 0px 0px 0px', + // borderRadius: theme.panelBorderRadius || '2px' + // }, + // overlay: { + // ...settingsPos, + // right: 'auto', + // bottom: 'auto', + // backgroundColor: 'rgba(0, 0, 0, 0)' + // } + }) + ); + + render() { + const {isOpen, handleClose} = this.props; + + const modalStyles = this.modalStylesSelector(this.props); + return ( + + {this.root.current ? ( + { + // React modal issue: https://github.com/reactjs/react-modal/issues/769 + // failed to execute removeChild on parent node when it is already unmounted + return ( + this.root.current || { + removeChild: () => {}, + appendChild: () => {} + } + ); + }} + > + {handleClose()}}/> + {/* */} + + ) : null} + + ); + } +} + +export default withTheme(RenderSettingsModal); \ No newline at end of file diff --git a/src/components/render-settings-panel.js b/src/components/render-settings-panel.js new file mode 100644 index 0000000000..b1f71671e1 --- /dev/null +++ b/src/components/render-settings-panel.js @@ -0,0 +1,207 @@ +import React, {Component} from 'react'; +import styled, {withTheme} from 'styled-components'; +import {Button, Input} from 'kepler.gl/components/common/styled-components'; +import {Delete} from 'kepler.gl/components/common/icons'; +import ItemSelector from 'kepler.gl/components/common/item-selector/item-selector'; + +const DEFAULT_BUTTON_HEIGHT = '32px'; +const DEFAULT_BUTTON_WIDTH = '64px'; +const DEFAULT_PADDING = '32px'; +const DEFAULT_ROW_GAP = '16px'; + +function nop() {} + +const IconButton = styled(Button)` + padding: 0; + svg { + margin: 0; + } +`; + +const PanelCloseInner = styled.div` + display: flex; + justify-content: flex-end; + padding: ${DEFAULT_PADDING} ${DEFAULT_PADDING} 0 ${DEFAULT_PADDING}; +`; + +const PanelClose = ({buttonHeight, handleClose}) => ( + // TODO pass in isOpen to false + + {handleClose()}}> + {/* */} + + + +); + +const StyledTitle = styled.div` + color: ${props => props.theme.titleTextColor}; + font-size: 20px; + font-weight: 400; + line-height: ${props => props.theme.lineHeight}; +`; + +const StyledSection = styled.div` + align-self: center; + color: ${props => props.theme.labelColor}; + font-weight: 500; + font-size: 13px; + margin-top: ${DEFAULT_PADDING}; + margin-bottom: ${DEFAULT_ROW_GAP}; +`; + +const StyledLabelCell = styled.div` + align-self: center; + color: ${props => props.theme.labelColor}; + font-weight: 400; + font-size: 11px; +`; + +const StyledValueCell = styled.div` + align-self: center; + color: ${props => props.theme.textColor}; + font-weight: 500; + font-size: 11px; + padding: 0 12px; +`; + +const PanelBodyInner = styled.div` + padding: 0 ${DEFAULT_PADDING}; +`; + +const InputGrid = styled.div` + display: grid; + grid-template-columns: 88px auto; + grid-template-rows: repeat( + ${props => props.rows}, + ${props => (props.rowHeight ? props.rowHeight : '34px')} + ); + grid-row-gap: ${DEFAULT_ROW_GAP}; +`; + +const PanelBody = () => ( + + Export Video + Video Effects + + Timestamp {/* TODO add functionality */} + + Camera {/* TODO add functionality */} + + + Export Settings {/* TODO add functionality */} + + File Name + + Media Type {/* TODO add functionality */} + + Quality {/* TODO add functionality */} + + + + Duration {/* TODO add functionality */} + 00:00:30 + File Size {/* TODO add functionality */} + 36 MB + + +); + +const PanelFooterInner = styled.div` + display: flex; + justify-content: space-between; + margin-top: ${DEFAULT_ROW_GAP}; + padding: ${DEFAULT_PADDING}; +`; + +const ButtonGroup = styled.div` + display: flex; +`; + +const PanelFooter = () => ( + + + + + + + +); + +const Panel = styled.div` + width: ${props => props.settingsWidth}px; +`; + +class RenderSettingsPanel extends Component { + static defaultProps = { + settingsWidth: 480, + buttonHeight: '16px' + }; + + render() { + const {buttonHeight, settingsWidth, handleClose} = this.props; + + return ( + + + + + + ); + } +} + +export default withTheme(RenderSettingsPanel); \ No newline at end of file From 5f71052cdbe0fdda2f2ef28a86aef228f76b187b Mon Sep 17 00:00:00 2001 From: RaymondDashWu Date: Thu, 23 Jul 2020 14:03:32 -0700 Subject: [PATCH 10/17] [FIX/DEL] Export button put in wrong scope + deleted unused test code --- .../common/animation-control/animation-control.js | 8 +++----- src/components/hubble-export.js | 11 +---------- src/components/render-settings-modal.js | 3 +-- src/components/render-settings-panel.js | 2 -- 4 files changed, 5 insertions(+), 19 deletions(-) diff --git a/src/components/common/animation-control/animation-control.js b/src/components/common/animation-control/animation-control.js index 47d1bbab64..c91e4afa48 100644 --- a/src/components/common/animation-control/animation-control.js +++ b/src/components/common/animation-control/animation-control.js @@ -163,13 +163,11 @@ function AnimationControlFactory( buttonHeight={BUTTON_HEIGHT} /> +
+ +
- - - {/* Once "Export" button is clicked, this.state.isOpen: === True, once "X" is clicked, isOpen === False */} - {/* */} - ); } diff --git a/src/components/hubble-export.js b/src/components/hubble-export.js index f48cd6a60f..ed84348c96 100644 --- a/src/components/hubble-export.js +++ b/src/components/hubble-export.js @@ -40,12 +40,7 @@ class HubbleExport extends Component { isOpen: false }; } - // To be used to store all modal components & functions -// this.states = [ // React props -// keyframes: abstraction of keyframes, -// dlsjkas, -// ] - handleClose() {this.setState({isOpen: false})} // X button in Kepler UI was clicked + handleClose() {this.setState({isOpen: false})} // X button in Modal UI was clicked handleExport() { // Export button in Kepler UI was clicked this.setState(state => ({ @@ -71,9 +66,5 @@ class HubbleExport extends Component { } }; -// States we need: -// -// -// export default keplerGlConnect(mapStateToProps, makeMapDispatchToProps)(withTheme(HubbleExport)); diff --git a/src/components/render-settings-modal.js b/src/components/render-settings-modal.js index e8ce63a24f..c4d7e4460c 100644 --- a/src/components/render-settings-modal.js +++ b/src/components/render-settings-modal.js @@ -88,7 +88,7 @@ class RenderSettingsModal extends Component { {this.root.current ? ( { @@ -103,7 +103,6 @@ class RenderSettingsModal extends Component { }} > {handleClose()}}/> - {/* */} ) : null} diff --git a/src/components/render-settings-panel.js b/src/components/render-settings-panel.js index b1f71671e1..5fa73437dc 100644 --- a/src/components/render-settings-panel.js +++ b/src/components/render-settings-panel.js @@ -25,10 +25,8 @@ const PanelCloseInner = styled.div` `; const PanelClose = ({buttonHeight, handleClose}) => ( - // TODO pass in isOpen to false {handleClose()}}> - {/* */} From 25dd5ebf703e7ec15a711e7f031528aaf6c6a1f4 Mon Sep 17 00:00:00 2001 From: RaymondDashWu Date: Thu, 23 Jul 2020 17:08:44 -0700 Subject: [PATCH 11/17] [FIX] Cancel button now closes modal --- src/components/render-settings-panel.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/components/render-settings-panel.js b/src/components/render-settings-panel.js index 5fa73437dc..5a342551c7 100644 --- a/src/components/render-settings-panel.js +++ b/src/components/render-settings-panel.js @@ -26,7 +26,7 @@ const PanelCloseInner = styled.div` const PanelClose = ({buttonHeight, handleClose}) => ( - {handleClose()}}> + {handleClose()}}> @@ -146,7 +146,7 @@ const ButtonGroup = styled.div` display: flex; `; -const PanelFooter = () => ( +const PanelFooter = ({handleClose}) => ( @@ -194,9 +194,9 @@ class RenderSettingsPanel extends Component { return ( - + {/* handleClose for X button */} - + {/* handleClose for Cancel button */} ); } From b1fa12b37a565054d977c021525765577dd9f21d Mon Sep 17 00:00:00 2001 From: RaymondDashWu Date: Mon, 27 Jul 2020 20:05:19 -0700 Subject: [PATCH 12/17] [ADD] Pseudocode on how to implement itemselector options --- src/components/hubble-export.js | 2 ++ src/components/render-settings-panel.js | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/components/hubble-export.js b/src/components/hubble-export.js index ed84348c96..8a424b068c 100644 --- a/src/components/hubble-export.js +++ b/src/components/hubble-export.js @@ -16,6 +16,7 @@ function mapStateToProps(state = {}, props) { mapState: state.mapState, uiState: state.uiState, providerState: state.providerState + // isOpen: state.isOpen TODO }; } @@ -25,6 +26,7 @@ function makeMapDispatchToProps() { // const groupedActionCreators = getActionCreators(dispatch, ownProps); return { + // TODO Put action creator and return here // ...groupedActionCreators, dispatch }; diff --git a/src/components/render-settings-panel.js b/src/components/render-settings-panel.js index 5a342551c7..53c216b926 100644 --- a/src/components/render-settings-panel.js +++ b/src/components/render-settings-panel.js @@ -113,7 +113,8 @@ const PanelBody = () => ( Media Type {/* TODO add functionality */} Date: Tue, 28 Jul 2020 15:17:45 -0500 Subject: [PATCH 13/17] Integration of deckgl Canvas with modal --- .gitignore | 1 + package.json | 2 +- src/components/hubble-export.js | 22 ++- src/components/map-container.js | 44 +++-- src/components/render-settings-modal.js | 22 ++- src/components/render-settings-panel.js | 121 +++++++++++-- src/components/scene.js | 224 ++++++++++++++++++++++++ yarn.lock | 59 +++++-- 8 files changed, 449 insertions(+), 46 deletions(-) create mode 100644 src/components/scene.js diff --git a/.gitignore b/.gitignore index 8725630bf8..9b34857e57 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,7 @@ umd/ typedoc/ +*/**/node_modules */**/yarn.lock yarn-error.log */**/package-lock.json diff --git a/package.json b/package.json index 1b6ffd54f8..4a921f730e 100644 --- a/package.json +++ b/package.json @@ -115,7 +115,7 @@ "global": "^4.3.0", "h3-js": "^3.1.0", "html-webpack-plugin": "^4.3.0", - "hubble.gl": "^1.0.1", + "hubble.gl": "1.1.0-alpha.4", "keymirror": "^0.1.1", "lodash.clonedeep": "^4.0.1", "lodash.curry": "^4.1.1", diff --git a/src/components/hubble-export.js b/src/components/hubble-export.js index 8a424b068c..78338ee377 100644 --- a/src/components/hubble-export.js +++ b/src/components/hubble-export.js @@ -1,3 +1,23 @@ +// Copyright (c) 2020 Uber Technologies, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + import React, {Component} from 'react'; import {ThemeProvider, withTheme} from 'styled-components'; @@ -60,7 +80,7 @@ class HubbleExport extends Component { console.log(this.state) return (
- + {/* anonymous function to bind state onclick */}
diff --git a/src/components/map-container.js b/src/components/map-container.js index 6cc116fc19..e7ca961e98 100644 --- a/src/components/map-container.js +++ b/src/components/map-container.js @@ -63,7 +63,7 @@ const TRANSITION_DURATION = 0; const Attribution = () => ( - © kepler.gl |{' '} + © kepler.gl|{' '} © Mapbox |{' '} @@ -287,31 +287,28 @@ export default function MapContainerFactory(MapPopover, MapControl, Editor) { layerHoverProp.compareType = interactionConfig.tooltip.config.compareType; } } - const commonProp = { - onClose: this._onCloseMapPopover, - mapW: mapState.width, - mapH: mapState.height, - zoom: mapState.zoom - }; - return (
{hasTooltip && ( )} {hasComparisonTooltip && ( )}
@@ -373,6 +370,9 @@ export default function MapContainerFactory(MapPopover, MapControl, Editor) { } = this.props; let deckGlLayers = []; + + + // wait until data is ready before render data layers if (layerData && layerData.length) { // last layer render first @@ -398,6 +398,7 @@ export default function MapContainerFactory(MapPopover, MapControl, Editor) { }) ); } + return ( ; @@ -483,8 +489,9 @@ export default function MapContainerFactory(MapPopover, MapControl, Editor) { }; const isEdit = uiState.mapControls.mapDraw.active; - + return ( + + + 'pointer' : undefined} transitionDuration={TRANSITION_DURATION} - onMouseMove={this.props.visStateActions.onMouseMove} + onMouseMove={this.props.visStateActions.onMouseMove}*/ > - {this._renderDeckOverlay(layersToRender)} - {this._renderMapboxOverlays(layersToRender)} + + + + {/*this._renderDeckOverlay(layersToRender) Provisional*/} + {/*this._renderMapboxOverlays(layersToRender)*/} + + - {handleClose()}}/> + {handleClose()}} prop={this.props.prop}/> ) : null} diff --git a/src/components/render-settings-panel.js b/src/components/render-settings-panel.js index 53c216b926..557aa52e6e 100644 --- a/src/components/render-settings-panel.js +++ b/src/components/render-settings-panel.js @@ -1,14 +1,108 @@ +// Copyright (c) 2020 Uber Technologies, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + import React, {Component} from 'react'; import styled, {withTheme} from 'styled-components'; import {Button, Input} from 'kepler.gl/components/common/styled-components'; import {Delete} from 'kepler.gl/components/common/icons'; import ItemSelector from 'kepler.gl/components/common/item-selector/item-selector'; +import {Scene} from 'components/scene'; + + +import {DeckScene, CameraKeyframes} from '@hubble.gl/core'; +import {easing} from 'popmotion'; +import {DeckAdapter} from 'hubble.gl'; const DEFAULT_BUTTON_HEIGHT = '32px'; const DEFAULT_BUTTON_WIDTH = '64px'; const DEFAULT_PADDING = '32px'; const DEFAULT_ROW_GAP = '16px'; +function sceneBuilder(animationLoop) { + const data = {}; + const keyframes = { + camera: new CameraKeyframes({ + timings: [0, 3000], + keyframes: [ + { + longitude: 0, + latitude: 11, + zoom: 2, + pitch: 0, + bearing: 0 + }, + { + longitude: 0, + latitude: 33, + zoom: 3, + bearing: 90, + pitch: 50 + } + ], + easings: [easing.easeInOut] + }) + }; + animationLoop.timeline.attachAnimation(keyframes.camera); + + // TODO: Figure out how to set up the size + return new DeckScene({ + animationLoop, + keyframes, + lengthMs: 5000, + data, + width: 480, + height: 460 + }); +} + +const encoderSettings = { + framerate: 30, + webm: { + quality: 0.8 + }, + jpeg: { + quality: 0.8 + }, + gif: { + sampleInterval: 1000 + } +}; + +var _core = require("@hubble.gl/core"); +const adapter = new DeckAdapter(sceneBuilder); + +function preview() { + adapter.render(_core.PreviewEncoder, encoderSettings, ()=>{}); +} + +// TODO: + +// Changes Timestamp function +// Camera function (preset keyframes) +// File Name function +// MediaType function +// Quality function +// Set Duration function +// Calculate File Size function +// Render Function + function nop() {} const IconButton = styled(Button)` @@ -65,6 +159,9 @@ const StyledValueCell = styled.div` const PanelBodyInner = styled.div` padding: 0 ${DEFAULT_PADDING}; + display: grid; + grid-template-columns: 480px auto; + grid-column-gap: 20px; `; const InputGrid = styled.div` @@ -77,8 +174,12 @@ const InputGrid = styled.div` grid-row-gap: ${DEFAULT_ROW_GAP}; `; -const PanelBody = () => ( +const PanelBody = ({props}) => ( +
+ +
+
Export Video Video Effects @@ -94,9 +195,9 @@ const PanelBody = () => ( selectedItems={['None']} options={[ 'None', - 'Oribit (90º)', - 'Oribit (180º)', - 'Oribit (360º)', + 'Orbit (90º)', + 'Orbit (180º)', + 'Orbit (360º)', 'North to South', 'South to North', 'East to West', @@ -113,8 +214,7 @@ const PanelBody = () => ( Media Type {/* TODO add functionality */} ( File Size {/* TODO add functionality */} 36 MB +
); @@ -154,7 +255,7 @@ const PanelFooter = ({handleClose}) => ( height={DEFAULT_BUTTON_HEIGHT} secondary className={'render-settings-button'} - onClick={nop} + onClick={preview} > Preview @@ -186,17 +287,17 @@ const Panel = styled.div` class RenderSettingsPanel extends Component { static defaultProps = { - settingsWidth: 480, + settingsWidth: 980, buttonHeight: '16px' }; render() { const {buttonHeight, settingsWidth, handleClose} = this.props; - + console.log("props from render setting panel", this.props.prop); return ( {/* handleClose for X button */} - + {/* handleClose for Cancel button */} ); diff --git a/src/components/scene.js b/src/components/scene.js new file mode 100644 index 0000000000..d37059d699 --- /dev/null +++ b/src/components/scene.js @@ -0,0 +1,224 @@ +// Copyright (c) 2020 Uber Technologies, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +import React, {Component, useState, useRef} from 'react'; + +//Map Component +import DeckGL from '@deck.gl/react'; +import {OVERLAY_TYPE} from 'layers/base-layer'; +import MapboxGLMap from 'react-map-gl'; +import {transformRequest} from 'utils/map-style-utils/mapbox-utils'; + +//Hubble Imports - Animation (from example for starters) +import {DeckScene, CameraKeyframes} from '@hubble.gl/core'; +import {easing} from 'popmotion'; +import {BasicControls} from '@hubble.gl/react'; +import {DeckAdapter} from 'hubble.gl'; + + +// Hubble Part (Maybe we should get this in a different file or put everything on a folder) +// Question: Does is make sense to have the sceneBuilder and enconderSettings in RenderSettingsPanel? +/*function sceneBuilder(animationLoop) { + const data = {}; + const keyframes = { + camera: new CameraKeyframes({ + timings: [0, 2000], + keyframes: [ + { + longitude: 0, + latitude: 11, + zoom: 2, + pitch: 0, + bearing: 0 + }, + { + longitude: 0, + latitude: 11, + zoom: 2, + bearing: 90, + pitch: 0 + } + ], + easings: [easing.easeInOut] + }) + }; + animationLoop.timeline.attachAnimation(keyframes.camera); + + // TODO: Figure out how to set up the size + return new DeckScene({ + animationLoop, + keyframes, + lengthMs: 5000, + data, + width: 480, + height: 460 + }); + }*/ + + /* const encoderSettings = { + framerate: 30, + webm: { + quality: 0.8 + }, + jpeg: { + quality: 0.8 + }, + gif: { + sampleInterval: 1000 + } + };*/ + + +const TRANSITION_DURATION = 0; + +export class Scene extends Component { + + constructor(props) { + super(props); + this.prop = this.props.prop; + + //this.adapter = new DeckAdapter(this.props.sceneBuilder); + } + + _renderLayer = (overlays, idx) => { + const datasets = this.prop.visState.datasets; + const layers = this.prop.visState.layers; + const layerData = this.prop.visState.layerData; + const hoverInfo = this.prop.visState.hoverInfo; + const clicked = this.prop.visState.clicked; + const mapState = this.prop.mapState; + const interactionConfig = this.prop.visState.interactionConfig; + const animationConfig = this.prop.visState.animationConfig; + + const layer = layers[idx]; + const data = layerData[idx]; + const {gpuFilter} = datasets[layer.config.dataId] || {}; + + const objectHovered = clicked || hoverInfo; + const layerCallbacks = { + onSetLayerDomain: val => this._onLayerSetDomain(idx, val) + }; + + // Layer is Layer class + const layerOverlay = layer.renderLayer({ + data, + gpuFilter, + idx, + interactionConfig, + layerCallbacks, + mapState, + animationConfig, + objectHovered + }); + return overlays.concat(layerOverlay || []); + }; + + // Testing purposes + print(prop){ + console.log("this.deckgl", prop); + }; + + // Is this being used right? + componentDidMount() { + this.forceUpdate(); + } + + // interactionConfig, + render() { + console.log("all props ", this.props.prop); + + const mapStyle = this.prop.mapStyle; + const mapState = this.prop.mapState; + const layers = this.prop.visState.layers; + const layerData = this.prop.visState.layerData; + const layerOrder = this.prop.visState.layerOrder; + const animationConfig = this.prop.visState.animationConfig; + const width = '100%'; + const height = '100%'; + const useDevicePixels = 2; + //Map data + const mapboxApiAccessToken = this.prop.mapStyle.mapboxApiAccessToken; + const mapboxApiUrl = this.prop.mapStyle.mapboxApiUrl; + // define trip and geojson layers + let deckGlLayers = []; + + // wait until data is ready before render data layers + if (layerData && layerData.length) { + // last layer render first + deckGlLayers = layerOrder + .slice() + .reverse() + .filter( + idx => layers[idx].overlayType === OVERLAY_TYPE.deckgl && layers[idx].id + ) + .reduce(this._renderLayer, []); + } + + // MapboxGLMap + const mapProps = { + ...mapState, + preserveDrawingBuffer: true, + mapboxApiAccessToken, + mapboxApiUrl, + transformRequest + }; + + const style = { + position: 'relative' + } + console.log("mapState prop ",mapState); + + return ( +
+ {this.deckgl={current:r}}} + viewState={mapState} + id="default-deckgl-overlay2" + layers={deckGlLayers} + useDevicePixels={useDevicePixels} + width={width} + height={height} + style={style} + /* onBeforeRender={this._onBeforeRender} // Not yet + onHover={visStateActions.onLayerHover} // Not yet + onClick={visStateActions.onLayerClick}*/ // Not yet + {...this.props.adapter.getProps(this.deckgl, () => {}, () => {this.forceUpdate()})} + > + 'pointer' : undefined} + transitionDuration={TRANSITION_DURATION} + > + +
+ {}} + /> +
+
+ ); + } + +} \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index 2213c1cba8..60727feff4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1356,20 +1356,22 @@ dependencies: "@hapi/hoek" "^8.3.0" -"@hubble.gl/core@1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@hubble.gl/core/-/core-1.0.1.tgz#f46a964e781ad685fa82bf2e6197f1b17817422c" - integrity sha512-dKRknK4xkOFAc0AYVHSvdN+4Fkfyv114G9g4umTHtgHnlFP6FxkVpkYMoN0ZXuyz+dmetfYYwSMhQVpRxh6adQ== - dependencies: - "@luma.gl/engine" "^8.1.2" +"@hubble.gl/core@1.1.0-alpha.4": + version "1.1.0-alpha.4" + resolved "https://registry.yarnpkg.com/@hubble.gl/core/-/core-1.1.0-alpha.4.tgz#85d2ab543e7dc8c9cad61aaad3b2ee32d9aad860" + integrity sha512-QMW3SF0AYuvR2sARkmTGPV4gvVsMh0MIqytbdkxkqqLODv1O9HLtnpUSGvE3Z/6u0J02mmHqPIECRWKAAAj4NA== + dependencies: + "@loaders.gl/core" "^2.1.6" + "@loaders.gl/video" "2.2.0-alpha.1" + "@luma.gl/engine" "^8.2.0" downloadjs "^1.4.7" popmotion "^8.6.10" webm-writer "^0.2.2" -"@hubble.gl/react@1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@hubble.gl/react/-/react-1.0.1.tgz#e98eecf149fdca5974d94ad26c9f6547446ae2f8" - integrity sha512-yuDbW8HD204Ybd+ZMTxmBtX8Lb8FjmdS52rTm1JlPTzKPDOoxNLSk9YW1l+i3XnuzvfR+BWDnzYiIpi+BAkM/A== +"@hubble.gl/react@1.1.0-alpha.4": + version "1.1.0-alpha.4" + resolved "https://registry.yarnpkg.com/@hubble.gl/react/-/react-1.1.0-alpha.4.tgz#a63f06ffd107df32f4297bae8b7659d27a214c3a" + integrity sha512-808DCV9LWshTa4wMYYgy6vqFBlxg7mu0EpXQNlItubHwFEeBUCIWbh2BS1lrhU9QBMUC2d6c85PFlzLmZx6yaQ== "@icons/material@^0.2.4": version "0.2.4" @@ -2258,6 +2260,14 @@ "@babel/runtime" "^7.3.1" "@loaders.gl/loader-utils" "2.2.5" +"@loaders.gl/core@^2.1.6": + version "2.2.8" + resolved "https://registry.yarnpkg.com/@loaders.gl/core/-/core-2.2.8.tgz#fb2060f3b90d3babe0de2a128fc5227f921c08ad" + integrity sha512-PM74zQA6Kn6NJCMoRdEDENy9jQWQyMkICKZ6o8UGa6/oi3dD4LO5GhFZSwU6W/Lxl/IeUwaZBQ3MqfT3aXA0Dg== + dependencies: + "@babel/runtime" "^7.3.1" + "@loaders.gl/loader-utils" "2.2.8" + "@loaders.gl/csv@^2.2.5": version "2.2.5" resolved "https://registry.yarnpkg.com/@loaders.gl/csv/-/csv-2.2.5.tgz#4667cbfb62b98d918a1c4e233bfb880939ab74fb" @@ -2308,7 +2318,7 @@ "@babel/runtime" "^7.3.1" "@probe.gl/stats" "^3.3.0" -"@loaders.gl/loader-utils@^2.2.5": +"@loaders.gl/loader-utils@2.2.8", "@loaders.gl/loader-utils@^2.1.3", "@loaders.gl/loader-utils@^2.2.5": version "2.2.8" resolved "https://registry.yarnpkg.com/@loaders.gl/loader-utils/-/loader-utils-2.2.8.tgz#9f12f3460260b15e961fa46c3d3c867d7bf48bee" integrity sha512-3F2VgxJPxjuZwAr8fDBkZzx3Wg275XdVaWnyYQ3uyZQ22yGEkrzKc+TlgcqSrxbO5pHrtS5PdS7dmyoJo2+Bdg== @@ -2376,6 +2386,14 @@ "@math.gl/web-mercator" "^3.2.0" "@probe.gl/stats" "^3.3.0" +"@loaders.gl/video@2.2.0-alpha.1": + version "2.2.0-alpha.1" + resolved "https://registry.yarnpkg.com/@loaders.gl/video/-/video-2.2.0-alpha.1.tgz#1bb09e9e507605a72c6e8a13b34926b69c717191" + integrity sha512-4NDe3fNPOTS4MvPxlxrbqr/kKgkB9tOVY2in/s/oYBo0uiDK+WSU0AztnyKxF1b/EsHzTEIzhOEhjvSwbgRQgQ== + dependencies: + "@loaders.gl/loader-utils" "^2.1.3" + gifshot "^0.4.5" + "@luma.gl/constants@8.2.0", "@luma.gl/constants@^8.2.0": version "8.2.0" resolved "https://registry.yarnpkg.com/@luma.gl/constants/-/constants-8.2.0.tgz#0789c629edbb8b69b7f810ae10c91501b97c634b" @@ -2392,7 +2410,7 @@ "@luma.gl/shadertools" "8.2.0" "@luma.gl/webgl" "8.2.0" -"@luma.gl/engine@8.2.0", "@luma.gl/engine@^8.1.2": +"@luma.gl/engine@8.2.0", "@luma.gl/engine@^8.2.0": version "8.2.0" resolved "https://registry.yarnpkg.com/@luma.gl/engine/-/engine-8.2.0.tgz#e598b723639619e00cff8acaf4af39de4d9fb61f" integrity sha512-HxlwU66TCJzMCY+wuxiyapiGFEp0HrRqg2m2fj8K5h5PBYMjDZSrs2JuDoOz97oFVALfujAEw74OX9pFr5uiRg== @@ -7661,6 +7679,11 @@ gif-encoder@~0.4.1: dependencies: readable-stream "~1.1.9" +gifshot@^0.4.5: + version "0.4.5" + resolved "https://registry.yarnpkg.com/gifshot/-/gifshot-0.4.5.tgz#e3cb570203a3b139ff3069d7578098a29c03b0f8" + integrity sha1-48tXAgOjsTn/MGnXV4CYopwDsPg= + git-raw-commits@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/git-raw-commits/-/git-raw-commits-2.0.0.tgz#d92addf74440c14bcc5c83ecce3fb7f8a79118b5" @@ -8477,13 +8500,13 @@ https-proxy-agent@^4.0.0: agent-base "5" debug "4" -hubble.gl@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/hubble.gl/-/hubble.gl-1.0.1.tgz#06845da48be6e45163bb78a6151188a5b7d4ade5" - integrity sha512-hrFSaXhBrLRzx0EuDKMFrzPIhahU+YYB5Wm9jp1pyIuC58VHz2qwKr/G//3Bzv0O84C/NrJEkWsdnSxHyyMaPw== +hubble.gl@1.1.0-alpha.4: + version "1.1.0-alpha.4" + resolved "https://registry.yarnpkg.com/hubble.gl/-/hubble.gl-1.1.0-alpha.4.tgz#0393a11d1272af35ca69950e86d25dce315682b5" + integrity sha512-Xb7rKzBG4fPuUgTQ/sPkFucidwG4Ld2CkkXGGh6ikC2OAOrUs3IffhCmeOwecPkg66tBrULOfpfT8XDnViYbZQ== dependencies: - "@hubble.gl/core" "1.0.1" - "@hubble.gl/react" "1.0.1" + "@hubble.gl/core" "1.1.0-alpha.4" + "@hubble.gl/react" "1.1.0-alpha.4" human-signals@^1.1.1: version "1.1.1" From 1d0fa9f37fc6474084c40a3c9c575bb3a19981a6 Mon Sep 17 00:00:00 2001 From: Elisa Martinez <97morningstar@gmail.com> Date: Tue, 28 Jul 2020 16:02:32 -0500 Subject: [PATCH 14/17] Better naming of the global object that contains the Map Data --- src/components/hubble-export.js | 2 +- src/components/map-container.js | 28 +++++++----------- src/components/render-settings-modal.js | 2 +- src/components/render-settings-panel.js | 16 +++++++---- src/components/scene.js | 38 ++++++++++++------------- 5 files changed, 42 insertions(+), 44 deletions(-) diff --git a/src/components/hubble-export.js b/src/components/hubble-export.js index 78338ee377..8f14f71e99 100644 --- a/src/components/hubble-export.js +++ b/src/components/hubble-export.js @@ -80,7 +80,7 @@ class HubbleExport extends Component { console.log(this.state) return (
- + {/* anonymous function to bind state onclick */}
diff --git a/src/components/map-container.js b/src/components/map-container.js index e7ca961e98..6bb71fef98 100644 --- a/src/components/map-container.js +++ b/src/components/map-container.js @@ -63,7 +63,7 @@ const TRANSITION_DURATION = 0; const Attribution = () => (
- © kepler.gl|{' '} + © kepler.gl |{' '} © Mapbox |{' '} @@ -287,28 +287,32 @@ export default function MapContainerFactory(MapPopover, MapControl, Editor) { layerHoverProp.compareType = interactionConfig.tooltip.config.compareType; } } + + const commonProp = { + onClose: this._onCloseMapPopover, + mapW: mapState.width, + mapH: mapState.height, + zoom: mapState.zoom + }; + return (
{hasTooltip && ( )} {hasComparisonTooltip && ( )}
@@ -370,9 +374,6 @@ export default function MapContainerFactory(MapPopover, MapControl, Editor) { } = this.props; let deckGlLayers = []; - - - // wait until data is ready before render data layers if (layerData && layerData.length) { // last layer render first @@ -398,7 +399,6 @@ export default function MapContainerFactory(MapPopover, MapControl, Editor) { }) ); } - return ( ; @@ -489,7 +484,6 @@ export default function MapContainerFactory(MapPopover, MapControl, Editor) { }; const isEdit = uiState.mapControls.mapDraw.active; - return ( diff --git a/src/components/render-settings-modal.js b/src/components/render-settings-modal.js index 3a83a2be76..443d95cc77 100644 --- a/src/components/render-settings-modal.js +++ b/src/components/render-settings-modal.js @@ -122,7 +122,7 @@ class RenderSettingsModal extends Component { ); }} > - {handleClose()}} prop={this.props.prop}/> + {handleClose()}} mapData={this.props.mapData}/> ) : null} diff --git a/src/components/render-settings-panel.js b/src/components/render-settings-panel.js index 557aa52e6e..ed5e37f9b6 100644 --- a/src/components/render-settings-panel.js +++ b/src/components/render-settings-panel.js @@ -25,7 +25,7 @@ import {Delete} from 'kepler.gl/components/common/icons'; import ItemSelector from 'kepler.gl/components/common/item-selector/item-selector'; import {Scene} from 'components/scene'; - +import {PreviewEncoder} from '@hubble.gl/core' import {DeckScene, CameraKeyframes} from '@hubble.gl/core'; import {easing} from 'popmotion'; import {DeckAdapter} from 'hubble.gl'; @@ -85,11 +85,15 @@ const encoderSettings = { } }; -var _core = require("@hubble.gl/core"); + const adapter = new DeckAdapter(sceneBuilder); function preview() { - adapter.render(_core.PreviewEncoder, encoderSettings, ()=>{}); + adapter.render(PreviewEncoder, encoderSettings, ()=>{}); +} + +function render(){ + } // TODO: @@ -174,10 +178,10 @@ const InputGrid = styled.div` grid-row-gap: ${DEFAULT_ROW_GAP}; `; -const PanelBody = ({props}) => ( +const PanelBody = ({mapData}) => (
- +
Export Video @@ -297,7 +301,7 @@ class RenderSettingsPanel extends Component { return ( {/* handleClose for X button */} - + {/* handleClose for Cancel button */} ); diff --git a/src/components/scene.js b/src/components/scene.js index d37059d699..88b9690ee2 100644 --- a/src/components/scene.js +++ b/src/components/scene.js @@ -92,20 +92,20 @@ export class Scene extends Component { constructor(props) { super(props); - this.prop = this.props.prop; + this.mapData = this.props.mapData; //this.adapter = new DeckAdapter(this.props.sceneBuilder); } _renderLayer = (overlays, idx) => { - const datasets = this.prop.visState.datasets; - const layers = this.prop.visState.layers; - const layerData = this.prop.visState.layerData; - const hoverInfo = this.prop.visState.hoverInfo; - const clicked = this.prop.visState.clicked; - const mapState = this.prop.mapState; - const interactionConfig = this.prop.visState.interactionConfig; - const animationConfig = this.prop.visState.animationConfig; + const datasets = this.mapData.visState.datasets; + const layers = this.mapData.visState.layers; + const layerData = this.mapData.visState.layerData; + const hoverInfo = this.mapData.visState.hoverInfo; + const clicked = this.mapData.visState.clicked; + const mapState = this.mapData.mapState; + const interactionConfig = this.mapData.visState.interactionConfig; + const animationConfig = this.mapData.visState.animationConfig; const layer = layers[idx]; const data = layerData[idx]; @@ -142,20 +142,20 @@ export class Scene extends Component { // interactionConfig, render() { - console.log("all props ", this.props.prop); - - const mapStyle = this.prop.mapStyle; - const mapState = this.prop.mapState; - const layers = this.prop.visState.layers; - const layerData = this.prop.visState.layerData; - const layerOrder = this.prop.visState.layerOrder; - const animationConfig = this.prop.visState.animationConfig; + console.log("all props ", this.props.mapData); + + const mapStyle = this.mapData.mapStyle; + const mapState = this.mapData.mapState; + const layers = this.mapData.visState.layers; + const layerData = this.mapData.visState.layerData; + const layerOrder = this.mapData.visState.layerOrder; + const animationConfig = this.mapData.visState.animationConfig; const width = '100%'; const height = '100%'; const useDevicePixels = 2; //Map data - const mapboxApiAccessToken = this.prop.mapStyle.mapboxApiAccessToken; - const mapboxApiUrl = this.prop.mapStyle.mapboxApiUrl; + const mapboxApiAccessToken = this.mapData.mapStyle.mapboxApiAccessToken; + const mapboxApiUrl = this.mapData.mapStyle.mapboxApiUrl; // define trip and geojson layers let deckGlLayers = []; From 93854936e63d167b247679f202836c649cbafe43 Mon Sep 17 00:00:00 2001 From: Elisa Martinez <97morningstar@gmail.com> Date: Wed, 29 Jul 2020 13:52:26 -0500 Subject: [PATCH 15/17] [ADD] Camera function (preset keyframes), File Name, MediaType and Render --- src/components/render-settings-panel.js | 292 +++++++++++++++++++++--- src/components/scene.js | 81 +------ 2 files changed, 263 insertions(+), 110 deletions(-) diff --git a/src/components/render-settings-panel.js b/src/components/render-settings-panel.js index ed5e37f9b6..806a51440c 100644 --- a/src/components/render-settings-panel.js +++ b/src/components/render-settings-panel.js @@ -25,21 +25,33 @@ import {Delete} from 'kepler.gl/components/common/icons'; import ItemSelector from 'kepler.gl/components/common/item-selector/item-selector'; import {Scene} from 'components/scene'; -import {PreviewEncoder} from '@hubble.gl/core' +import { + WebMEncoder, + JPEGSequenceEncoder, + PNGSequenceEncoder, + PreviewEncoder, + GifEncoder +} from '@hubble.gl/core'; import {DeckScene, CameraKeyframes} from '@hubble.gl/core'; import {easing} from 'popmotion'; -import {DeckAdapter} from 'hubble.gl'; +import {DeckAdapter, ScatterPlotLayerKeyframes} from 'hubble.gl'; + +import {DEFAULT_TIME_FORMAT} from 'constants'; +import moment from 'moment'; const DEFAULT_BUTTON_HEIGHT = '32px'; const DEFAULT_BUTTON_WIDTH = '64px'; const DEFAULT_PADDING = '32px'; const DEFAULT_ROW_GAP = '16px'; +//const keyframes = setKeyframes(camera); +let adapter = new DeckAdapter(sceneBuilder); + function sceneBuilder(animationLoop) { const data = {}; const keyframes = { camera: new CameraKeyframes({ - timings: [0, 3000], + timings: [0, 500], keyframes: [ { longitude: 0, @@ -50,10 +62,10 @@ function sceneBuilder(animationLoop) { }, { longitude: 0, - latitude: 33, - zoom: 3, - bearing: 90, - pitch: 50 + latitude: 11, + zoom: 2, + bearing: 180, + pitch: 0 } ], easings: [easing.easeInOut] @@ -65,13 +77,129 @@ function sceneBuilder(animationLoop) { return new DeckScene({ animationLoop, keyframes, - lengthMs: 5000, + lengthMs: 500, data, width: 480, height: 460 }); } +function setKeyframes(cameraType){ + adapter.scene.keyframes.camera._lastTime = 0; + adapter.scene.keyframes.camera.factor = 0; + if(cameraType === 'Orbit (90º)'){ + // How to reset the camera to its initial position? + adapter.scene.keyframes.camera.values[0].bearing = 0; + adapter.scene.keyframes.camera.values[0].latitude = 0; + adapter.scene.keyframes.camera.values[0].longitude = 11; + adapter.scene.keyframes.camera.values[0].pitch = 0; + adapter.scene.keyframes.camera.values[0].zoom = 2; + + adapter.scene.keyframes.camera.values[1].bearing = 90; + adapter.scene.keyframes.camera.values[1].latitude = 0; + adapter.scene.keyframes.camera.values[1].longitude = 11; + adapter.scene.keyframes.camera.values[1].pitch = 0; + adapter.scene.keyframes.camera.values[1].zoom = 2; + }else if(cameraType === 'Orbit (180º)'){ + adapter.scene.keyframes.camera.values[0].bearing = 0; + adapter.scene.keyframes.camera.values[0].latitude = 0; + adapter.scene.keyframes.camera.values[0].longitude = 11; + adapter.scene.keyframes.camera.values[0].pitch = 0; + adapter.scene.keyframes.camera.values[0].zoom = 2; + + adapter.scene.keyframes.camera.values[1].bearing = 180; + adapter.scene.keyframes.camera.values[1].latitude = 0; + adapter.scene.keyframes.camera.values[1].longitude = 11; + adapter.scene.keyframes.camera.values[1].pitch = 0; + adapter.scene.keyframes.camera.values[1].zoom = 2; + }else if(cameraType === 'Orbit (360º)'){ + adapter.scene.keyframes.camera.values[0].bearing = 0; + adapter.scene.keyframes.camera.values[0].latitude = 0; + adapter.scene.keyframes.camera.values[0].longitude = 11; + adapter.scene.keyframes.camera.values[0].pitch = 0; + adapter.scene.keyframes.camera.values[0].zoom = 2; + + adapter.scene.keyframes.camera.values[1].bearing = 360; + adapter.scene.keyframes.camera.values[1].latitude = 0; + adapter.scene.keyframes.camera.values[1].longitude = 11; + adapter.scene.keyframes.camera.values[1].pitch = 0; + adapter.scene.keyframes.camera.values[1].zoom = 2; + }else if(cameraType === 'North to South'){ + adapter.scene.keyframes.camera.values[0].bearing = 0; + adapter.scene.keyframes.camera.values[0].latitude = 70; + adapter.scene.keyframes.camera.values[0].longitude = 11; + adapter.scene.keyframes.camera.values[0].pitch = 0; + adapter.scene.keyframes.camera.values[0].zoom = 2; + + adapter.scene.keyframes.camera.values[1].bearing = 0; + adapter.scene.keyframes.camera.values[1].latitude = -20; + adapter.scene.keyframes.camera.values[1].longitude = 11; + adapter.scene.keyframes.camera.values[1].pitch = 0; + adapter.scene.keyframes.camera.values[1].zoom = 2; + }else if(cameraType === 'South to North'){ + adapter.scene.keyframes.camera.values[0].bearing = 0; + adapter.scene.keyframes.camera.values[0].latitude = -20; + adapter.scene.keyframes.camera.values[0].longitude = 11; + adapter.scene.keyframes.camera.values[0].pitch = 0; + adapter.scene.keyframes.camera.values[0].zoom = 2; + + adapter.scene.keyframes.camera.values[1].bearing = 0; + adapter.scene.keyframes.camera.values[1].latitude = 70; + adapter.scene.keyframes.camera.values[1].longitude = 11; + adapter.scene.keyframes.camera.values[1].pitch = 0; + adapter.scene.keyframes.camera.values[1].zoom = 2; + }else if(cameraType === 'East to West'){ + adapter.scene.keyframes.camera.values[0].bearing = 0; + adapter.scene.keyframes.camera.values[0].latitude = 11; + adapter.scene.keyframes.camera.values[0].longitude = 55; + adapter.scene.keyframes.camera.values[0].pitch = 0; + adapter.scene.keyframes.camera.values[0].zoom = 2; + + adapter.scene.keyframes.camera.values[1].bearing = 0; + adapter.scene.keyframes.camera.values[1].latitude = 11; + adapter.scene.keyframes.camera.values[1].longitude = -77; + adapter.scene.keyframes.camera.values[1].pitch = 0; + adapter.scene.keyframes.camera.values[1].zoom = 2; + }else if(cameraType === 'West to East'){ + adapter.scene.keyframes.camera.values[0].bearing = 0; + adapter.scene.keyframes.camera.values[0].latitude = 11; + adapter.scene.keyframes.camera.values[0].longitude = -77; + adapter.scene.keyframes.camera.values[0].pitch = 0; + adapter.scene.keyframes.camera.values[0].zoom = 2; + + adapter.scene.keyframes.camera.values[1].bearing = 0; + adapter.scene.keyframes.camera.values[1].latitude = 11; + adapter.scene.keyframes.camera.values[1].longitude = 55; + adapter.scene.keyframes.camera.values[1].pitch = 0; + adapter.scene.keyframes.camera.values[0].zoom = 2; + }else if(cameraType === 'Zoom Out'){ + adapter.scene.keyframes.camera.values[0].bearing = 0; + adapter.scene.keyframes.camera.values[0].latitude = 0; + adapter.scene.keyframes.camera.values[0].longitude = 11; + adapter.scene.keyframes.camera.values[0].pitch = 0; + adapter.scene.keyframes.camera.values[0].zoom = 15; + + adapter.scene.keyframes.camera.values[1].bearing = 0; + adapter.scene.keyframes.camera.values[1].latitude = 0; + adapter.scene.keyframes.camera.values[1].longitude = 11; + adapter.scene.keyframes.camera.values[1].pitch = 0; + adapter.scene.keyframes.camera.values[1].zoom = 2; + }else if(cameraType === 'Zoom In'){ + adapter.scene.keyframes.camera.values[0].bearing = 0; + adapter.scene.keyframes.camera.values[0].latitude = 0; + adapter.scene.keyframes.camera.values[0].longitude = 11; + adapter.scene.keyframes.camera.values[0].pitch = 0; + adapter.scene.keyframes.camera.values[0].zoom = 2; + + adapter.scene.keyframes.camera.values[1].bearing = 0; + adapter.scene.keyframes.camera.values[1].latitude = 0; + adapter.scene.keyframes.camera.values[1].longitude = 11; + adapter.scene.keyframes.camera.values[1].pitch = 0; + adapter.scene.keyframes.camera.values[1].zoom = 15; + } + console.log("adapter", adapter); +} + const encoderSettings = { framerate: 30, webm: { @@ -82,30 +210,61 @@ const encoderSettings = { }, gif: { sampleInterval: 1000 - } + }, + webm:{ + quality: 0.8 + }, + filename: "Default Video Name" + " " + moment().format(DEFAULT_TIME_FORMAT).toString() }; - -const adapter = new DeckAdapter(sceneBuilder); - function preview() { adapter.render(PreviewEncoder, encoderSettings, ()=>{}); } -function render(){ - +function setFileNameDeckAdapter(name){ + encoderSettings.filename = name + " " + moment().format(DEFAULT_TIME_FORMAT).toString(); } +/*function setResolution(resolution){ + if(resolution === 'Good (540p)'){ + adapter.scene.width = 960; + adapter.scene.height = 540; + }else if(resolution === 'High (720p)'){ + adapter.scene.width = 1280; + adapter.scene.height = 720; + }else if(resolution === 'Highest (1080p)'){ + adapter.scene.width = 1920; + adapter.scene.height = 1080; + } +}*/ + +// This is temporary, for showing purposes on Friday, resolution settings should be in a separate function, +// only because we are against the clock. +// TODO: refactor +function render(settingsdata){ + + // setResolution(settingsdata.resolution); // Remove this + + if (settingsdata.mediaType === 'WebM Video') { + adapter.render(WebMEncoder, encoderSettings, () => {}); + } else if (settingsdata.mediaType === 'PNG Sequence') { + adapter.render(PNGSequenceEncoder, encoderSettings, () => {}); + } else if (settingsdata.mediaType === 'JPEG Sequence') { + adapter.render(JPEGSequenceEncoder, encoderSettings, () => {}); + } + // preview(); + } + // TODO: // Changes Timestamp function -// Camera function (preset keyframes) -// File Name function -// MediaType function +// Camera function (preset keyframes) DONE +// File Name function DONE +// MediaType function DONE // Quality function // Set Duration function // Calculate File Size function -// Render Function +// Render Function DONE function nop() {} @@ -135,6 +294,7 @@ const StyledTitle = styled.div` font-size: 20px; font-weight: 400; line-height: ${props => props.theme.lineHeight}; + padding: 0 ${DEFAULT_PADDING} 16px ${DEFAULT_PADDING}; `; const StyledSection = styled.div` @@ -178,13 +338,12 @@ const InputGrid = styled.div` grid-row-gap: ${DEFAULT_ROW_GAP}; `; -const PanelBody = ({mapData}) => ( - -
- +const PanelBody = ({mapData, setMediaType, setCamera, setFileName/*, setQuality*/, settingsData}) => ( + +
+
- Export Video Video Effects Timestamp {/* TODO add functionality */} @@ -196,7 +355,7 @@ const PanelBody = ({mapData}) => ( /> Camera {/* TODO add functionality */} ( 'South to North', 'East to West', 'West to East', - 'Zoom Out' + 'Zoom Out', + 'Zoom In' ]} multiSelect={false} searchable={false} + onChange={setCamera} /> Export Settings {/* TODO add functionality */} File Name - + Media Type {/* TODO add functionality */} Quality {/* TODO add functionality */} @@ -252,7 +415,7 @@ const ButtonGroup = styled.div` display: flex; `; -const PanelFooter = ({handleClose}) => ( +const PanelFooter = ({handleClose, settingsData}) => ( @@ -290,19 +453,80 @@ const Panel = styled.div` `; class RenderSettingsPanel extends Component { + constructor(props) { + super(props); + + this.state = { + mediaType: "WebM Video", + camera: "None", + fileName: "Video Name", + // quality: "High (720p)" + }; + + this.setMediaTypeState = this.setMediaTypeState.bind(this); + this.setCamera = this.setCamera.bind(this); + this.setFileName = this.setFileName.bind(this); + // this.setQuality = this.setQuality.bind(this); + } + static defaultProps = { settingsWidth: 980, buttonHeight: '16px' }; + setMediaTypeState(media){ + this.setState({ + mediaType: media + }); + } + setCamera(option){ + this.setState({ + camera: option + }); + setKeyframes(option); + } + setFileName(name){ + this.setState({ + fileName: name.target.value + }); + setFileNameDeckAdapter(name.target.value); + } + /* setQuality(resolution){ + this.setState({ + quality: resolution + }); + setResolution(resolution); + }*/ + + render() { + const {buttonHeight, settingsWidth, handleClose} = this.props; - console.log("props from render setting panel", this.props.prop); + const settingsData = { + mediaType : this.state.mediaType, + camera : this.state.camera, + fileName: this.state.fileName, + resolution: this.state.quality, + } + return ( - {/* handleClose for X button */} - - {/* handleClose for Cancel button */} + {/* handleClose for X button */} + Export Video + + {/* handleClose for Cancel button */} ); } diff --git a/src/components/scene.js b/src/components/scene.js index 88b9690ee2..a1acb1af2b 100644 --- a/src/components/scene.js +++ b/src/components/scene.js @@ -26,66 +26,6 @@ import {OVERLAY_TYPE} from 'layers/base-layer'; import MapboxGLMap from 'react-map-gl'; import {transformRequest} from 'utils/map-style-utils/mapbox-utils'; -//Hubble Imports - Animation (from example for starters) -import {DeckScene, CameraKeyframes} from '@hubble.gl/core'; -import {easing} from 'popmotion'; -import {BasicControls} from '@hubble.gl/react'; -import {DeckAdapter} from 'hubble.gl'; - - -// Hubble Part (Maybe we should get this in a different file or put everything on a folder) -// Question: Does is make sense to have the sceneBuilder and enconderSettings in RenderSettingsPanel? -/*function sceneBuilder(animationLoop) { - const data = {}; - const keyframes = { - camera: new CameraKeyframes({ - timings: [0, 2000], - keyframes: [ - { - longitude: 0, - latitude: 11, - zoom: 2, - pitch: 0, - bearing: 0 - }, - { - longitude: 0, - latitude: 11, - zoom: 2, - bearing: 90, - pitch: 0 - } - ], - easings: [easing.easeInOut] - }) - }; - animationLoop.timeline.attachAnimation(keyframes.camera); - - // TODO: Figure out how to set up the size - return new DeckScene({ - animationLoop, - keyframes, - lengthMs: 5000, - data, - width: 480, - height: 460 - }); - }*/ - - /* const encoderSettings = { - framerate: 30, - webm: { - quality: 0.8 - }, - jpeg: { - quality: 0.8 - }, - gif: { - sampleInterval: 1000 - } - };*/ - - const TRANSITION_DURATION = 0; export class Scene extends Component { @@ -142,7 +82,7 @@ export class Scene extends Component { // interactionConfig, render() { - console.log("all props ", this.props.mapData); + // console.log("all props ", this.props.mapData); const mapStyle = this.mapData.mapStyle; const mapState = this.mapData.mapState; @@ -150,9 +90,7 @@ export class Scene extends Component { const layerData = this.mapData.visState.layerData; const layerOrder = this.mapData.visState.layerOrder; const animationConfig = this.mapData.visState.animationConfig; - const width = '100%'; - const height = '100%'; - const useDevicePixels = 2; + const useDevicePixels = false; //Map data const mapboxApiAccessToken = this.mapData.mapStyle.mapboxApiAccessToken; const mapboxApiUrl = this.mapData.mapStyle.mapboxApiUrl; @@ -183,18 +121,16 @@ export class Scene extends Component { const style = { position: 'relative' } - console.log("mapState prop ",mapState); + // console.log("mapState prop ",mapState); return ( -
+
{this.deckgl={current:r}}} viewState={mapState} id="default-deckgl-overlay2" layers={deckGlLayers} useDevicePixels={useDevicePixels} - width={width} - height={height} style={style} /* onBeforeRender={this._onBeforeRender} // Not yet onHover={visStateActions.onLayerHover} // Not yet @@ -209,14 +145,7 @@ export class Scene extends Component { getCursor={this.props.hoverInfo ? () => 'pointer' : undefined} transitionDuration={TRANSITION_DURATION} > - -
- {}} - /> -
+
); } From 2a81bc5f0e20cd679e6d598c29292ee45234c7db Mon Sep 17 00:00:00 2001 From: Elisa Martinez <97morningstar@gmail.com> Date: Thu, 30 Jul 2020 20:29:29 -0500 Subject: [PATCH 16/17] TileLayer added for demo day instead of Mapbox --- src/components/map-container.js | 8 +- src/components/render-settings-panel.js | 143 +++++++++++++----------- src/components/scene.js | 90 +++++++++++++-- 3 files changed, 161 insertions(+), 80 deletions(-) diff --git a/src/components/map-container.js b/src/components/map-container.js index 6bb71fef98..718465cbf1 100644 --- a/src/components/map-container.js +++ b/src/components/map-container.js @@ -512,19 +512,19 @@ export default function MapContainerFactory(MapPopover, MapControl, Editor) { 'pointer' : undefined} transitionDuration={TRANSITION_DURATION} - onMouseMove={this.props.visStateActions.onMouseMove}*/ + onMouseMove={this.props.visStateActions.onMouseMove} > - {/*this._renderDeckOverlay(layersToRender) Provisional*/} - {/*this._renderMapboxOverlays(layersToRender)*/} + {this._renderDeckOverlay(layersToRender)} + {this._renderMapboxOverlays(layersToRender)} { + const { + bbox: { west, south, east, north } + } = props.tile; + + return new BitmapLayer(props, { + data: [], + image: props.data, + bounds: [west, south, east, north] + }); + } +}) + + +/* global window */ +const devicePixelRatio = (typeof window !== 'undefined' && window.devicePixelRatio) || 1; + export class Scene extends Component { constructor(props) { super(props); + this.mapData = this.props.mapData; - + //this.adapter = new DeckAdapter(this.props.sceneBuilder); } + _renderLayer = (overlays, idx) => { const datasets = this.mapData.visState.datasets; const layers = this.mapData.visState.layers; @@ -79,6 +131,15 @@ export class Scene extends Component { componentDidMount() { this.forceUpdate(); } + + // This is provisional - + // [ADD] TileLayer to the array of layers + + + + + + // interactionConfig, render() { @@ -97,8 +158,11 @@ export class Scene extends Component { // define trip and geojson layers let deckGlLayers = []; + + + // wait until data is ready before render data layers - if (layerData && layerData.length) { + if (layerOrder && layerOrder.length) { // last layer render first deckGlLayers = layerOrder .slice() @@ -109,6 +173,14 @@ export class Scene extends Component { .reduce(this._renderLayer, []); } + deckGlLayers[2] = deckGlLayers[1]; + deckGlLayers[1] = deckGlLayers[0] + deckGlLayers[0] = tileLayer; + + + + console.log("deckGlLayers ", deckGlLayers); + // MapboxGLMap const mapProps = { ...mapState, @@ -121,7 +193,7 @@ export class Scene extends Component { const style = { position: 'relative' } - // console.log("mapState prop ",mapState); + console.log("tilelayer ",tileLayer); return (
@@ -132,19 +204,15 @@ export class Scene extends Component { layers={deckGlLayers} useDevicePixels={useDevicePixels} style={style} + views={new MapView({repeat: true})} /* onBeforeRender={this._onBeforeRender} // Not yet onHover={visStateActions.onLayerHover} // Not yet onClick={visStateActions.onLayerClick}*/ // Not yet {...this.props.adapter.getProps(this.deckgl, () => {}, () => {this.forceUpdate()})} > - 'pointer' : undefined} - transitionDuration={TRANSITION_DURATION} - > + + +
); From 3d85f64c3f9a3a956dc757b7814ea9f235deab94 Mon Sep 17 00:00:00 2001 From: Elisa Martinez <97morningstar@gmail.com> Date: Thu, 6 Aug 2020 14:47:59 -0500 Subject: [PATCH 17/17] Organize code that handles settings in the modal --- examples/demo-app/package.json | 3 +- src/components/map-container.js | 2 +- src/components/render-settings-panel.js | 305 +++---------------- src/components/render/encoder-settings.js | 18 ++ src/components/render/keyframes.js | 126 ++++++++ src/components/render/settings-controller.js | 130 ++++++++ src/components/scene.js | 15 +- 7 files changed, 328 insertions(+), 271 deletions(-) create mode 100644 src/components/render/encoder-settings.js create mode 100644 src/components/render/keyframes.js create mode 100644 src/components/render/settings-controller.js diff --git a/examples/demo-app/package.json b/examples/demo-app/package.json index 24ce8092a6..b93b57e450 100644 --- a/examples/demo-app/package.json +++ b/examples/demo-app/package.json @@ -56,6 +56,7 @@ "babel-loader": "^8.0.0", "babel-plugin-module-resolver": "^3.0.0", "babel-plugin-transform-builtin-extend": "^1.1.0", + "gh-pages": "^3.1.0", "webpack": "^4.29.0", "webpack-cli": "^3.2.1", "webpack-dev-middleware": "^3.5.1", @@ -63,4 +64,4 @@ "webpack-hot-middleware": "^2.24.3", "webpack-stats-plugin": "^0.2.1" } -} \ No newline at end of file +} diff --git a/src/components/map-container.js b/src/components/map-container.js index 718465cbf1..59193a0604 100644 --- a/src/components/map-container.js +++ b/src/components/map-container.js @@ -518,7 +518,7 @@ export default function MapContainerFactory(MapPopover, MapControl, Editor) { mapStyle={mapStyle.bottomMapStyle} getCursor={this.props.hoverInfo ? () => 'pointer' : undefined} transitionDuration={TRANSITION_DURATION} - onMouseMove={this.props.visStateActions.onMouseMove} + onMouseMove={this.props.visStateActions.onMouseMove} > diff --git a/src/components/render-settings-panel.js b/src/components/render-settings-panel.js index 64e3696cc4..9e0504cf99 100644 --- a/src/components/render-settings-panel.js +++ b/src/components/render-settings-panel.js @@ -26,259 +26,19 @@ import ItemSelector from 'kepler.gl/components/common/item-selector/item-selecto import {Scene} from 'components/scene'; import { - WebMEncoder, - JPEGSequenceEncoder, - PNGSequenceEncoder, - PreviewEncoder, - GifEncoder -} from '@hubble.gl/core'; -import {DeckScene, CameraKeyframes} from '@hubble.gl/core'; -import {easing} from 'popmotion'; -import {DeckAdapter, ScatterPlotLayerKeyframes} from 'hubble.gl'; + SettingsController, + preview, + setFileNameDeckAdapter, + render + } from 'components/render/settings-controller'; -import {DEFAULT_TIME_FORMAT} from 'constants'; -import moment from 'moment'; +import {setKeyframes} from 'components/render/keyframes'; const DEFAULT_BUTTON_HEIGHT = '32px'; const DEFAULT_BUTTON_WIDTH = '64px'; const DEFAULT_PADDING = '32px'; const DEFAULT_ROW_GAP = '16px'; -//const keyframes = setKeyframes(camera); -let adapter = new DeckAdapter(sceneBuilder); -let mapdataGlobal = null; - -function sceneBuilder(animationLoop) { - const data = {}; - const keyframes = { - camera: new CameraKeyframes({ - timings: [0, 1000], - keyframes: [ - { - longitude: mapdataGlobal.mapState.longitude, - latitude: mapdataGlobal.mapState.latitude, - zoom: mapdataGlobal.mapState.zoom, - pitch: 0, - bearing: 0 - }, - { - longitude: mapdataGlobal.mapState.longitude, - latitude: mapdataGlobal.mapState.latitude, - zoom: mapdataGlobal.mapState.zoom, - bearing: 0, - pitch: 0 - } - ], - easings: [easing.easeInOut] - }) - }; - animationLoop.timeline.attachAnimation(keyframes.camera); - - // TODO: Figure out how to set up the size - return new DeckScene({ - animationLoop, - keyframes, - lengthMs: 1000, - data, - width: 480, - height: 460 - }); -} - -function setKeyframes(cameraType){ - adapter.scene.keyframes.camera._lastTime = 0; - adapter.scene.keyframes.camera.factor = 0; - - // I'm not sure - adapter.scene.keyframes.camera.values[0].latitude = mapdataGlobal.mapState.latitude; - adapter.scene.keyframes.camera.values[0].longitude = mapdataGlobal.mapState.longitude; - adapter.scene.keyframes.camera.values[1].latitude = mapdataGlobal.mapState.latitude; - adapter.scene.keyframes.camera.values[1].longitude = mapdataGlobal.mapState.longitude; - adapter.scene.keyframes.camera.values[0].zoom = mapdataGlobal.mapState.zoom; - adapter.scene.keyframes.camera.values[1].zoom = mapdataGlobal.mapState.zoom; - - if(cameraType === 'Orbit (90º)'){ - // How to reset the camera to its initial position? - adapter.scene.keyframes.camera.values[0].bearing = 0; - adapter.scene.keyframes.camera.values[0].latitude = mapdataGlobal.mapState.latitude; - adapter.scene.keyframes.camera.values[0].longitude = mapdataGlobal.mapState.longitude; - adapter.scene.keyframes.camera.values[0].pitch = 0; - adapter.scene.keyframes.camera.values[0].zoom = mapdataGlobal.mapState.zoom; - - adapter.scene.keyframes.camera.values[1].bearing = 90; - adapter.scene.keyframes.camera.values[1].latitude = mapdataGlobal.mapState.latitude; - adapter.scene.keyframes.camera.values[1].longitude = mapdataGlobal.mapState.longitude; - adapter.scene.keyframes.camera.values[1].pitch = 0; - adapter.scene.keyframes.camera.values[1].zoom = mapdataGlobal.mapState.zoom; - }else if(cameraType === 'Orbit (180º)'){ - adapter.scene.keyframes.camera.values[0].bearing = 0; - adapter.scene.keyframes.camera.values[0].latitude = mapdataGlobal.mapState.latitude; - adapter.scene.keyframes.camera.values[0].longitude = mapdataGlobal.mapState.longitude; - adapter.scene.keyframes.camera.values[0].pitch = 0; - adapter.scene.keyframes.camera.values[0].zoom = mapdataGlobal.mapState.zoom; - - adapter.scene.keyframes.camera.values[1].bearing = 180; - adapter.scene.keyframes.camera.values[1].latitude = mapdataGlobal.mapState.latitude; - adapter.scene.keyframes.camera.values[1].longitude = mapdataGlobal.mapState.longitude; - adapter.scene.keyframes.camera.values[1].pitch = 0; - adapter.scene.keyframes.camera.values[1].zoom = mapdataGlobal.mapState.zoom; - }else if(cameraType === 'Orbit (360º)'){ - adapter.scene.keyframes.camera.values[0].bearing = 0; - adapter.scene.keyframes.camera.values[0].latitude = mapdataGlobal.mapState.latitude; - adapter.scene.keyframes.camera.values[0].longitude = mapdataGlobal.mapState.longitude; - adapter.scene.keyframes.camera.values[0].pitch = 0; - adapter.scene.keyframes.camera.values[0].zoom = mapdataGlobal.mapState.zoom; - - adapter.scene.keyframes.camera.values[1].bearing = 360; - adapter.scene.keyframes.camera.values[1].latitude = mapdataGlobal.mapState.latitude; - adapter.scene.keyframes.camera.values[1].longitude = mapdataGlobal.mapState.longitude; - adapter.scene.keyframes.camera.values[1].pitch = 0; - adapter.scene.keyframes.camera.values[1].zoom = mapdataGlobal.mapState.zoom; - }else if(cameraType === 'North to South'){ - adapter.scene.keyframes.camera.values[0].bearing = 0; - adapter.scene.keyframes.camera.values[0].latitude = mapdataGlobal.mapState.latitude + 25; - adapter.scene.keyframes.camera.values[0].longitude = mapdataGlobal.mapState.longitude; - adapter.scene.keyframes.camera.values[0].pitch = 0; - adapter.scene.keyframes.camera.values[0].zoom = mapdataGlobal.mapState.zoom; - - adapter.scene.keyframes.camera.values[1].bearing = 0; - adapter.scene.keyframes.camera.values[1].latitude = mapdataGlobal.mapState.latitude - 25; - adapter.scene.keyframes.camera.values[1].longitude = mapdataGlobal.mapState.longitude; - adapter.scene.keyframes.camera.values[1].pitch = 0; - adapter.scene.keyframes.camera.values[1].zoom = mapdataGlobal.mapState.zoom; - }else if(cameraType === 'South to North'){ - adapter.scene.keyframes.camera.values[0].bearing = 0; - adapter.scene.keyframes.camera.values[0].latitude = mapdataGlobal.mapState.latitude - 25; - adapter.scene.keyframes.camera.values[0].longitude = mapdataGlobal.mapState.longitude; - adapter.scene.keyframes.camera.values[0].pitch = 0; - adapter.scene.keyframes.camera.values[0].zoom = mapdataGlobal.mapState.zoom; - - adapter.scene.keyframes.camera.values[1].bearing = 0; - adapter.scene.keyframes.camera.values[1].latitude = mapdataGlobal.mapState.latitude + 25; - adapter.scene.keyframes.camera.values[1].longitude = mapdataGlobal.mapState.longitude; - adapter.scene.keyframes.camera.values[1].pitch = 0; - adapter.scene.keyframes.camera.values[1].zoom = mapdataGlobal.mapState.zoom; - }else if(cameraType === 'East to West'){ - adapter.scene.keyframes.camera.values[0].bearing = 0; - adapter.scene.keyframes.camera.values[0].latitude = mapdataGlobal.mapState.latitude; - adapter.scene.keyframes.camera.values[0].longitude = mapdataGlobal.mapState.longitude + 25; - adapter.scene.keyframes.camera.values[0].pitch = 0; - adapter.scene.keyframes.camera.values[0].zoom = mapdataGlobal.mapState.zoom; - - adapter.scene.keyframes.camera.values[1].bearing = 0; - adapter.scene.keyframes.camera.values[1].latitude = mapdataGlobal.mapState.latitude; - adapter.scene.keyframes.camera.values[1].longitude = mapdataGlobal.mapState.longitude - 25; - adapter.scene.keyframes.camera.values[1].pitch = 0; - adapter.scene.keyframes.camera.values[1].zoom = mapdataGlobal.mapState.zoom; - }else if(cameraType === 'West to East'){ - adapter.scene.keyframes.camera.values[0].bearing = 0; - adapter.scene.keyframes.camera.values[0].latitude = mapdataGlobal.mapState.latitude; - adapter.scene.keyframes.camera.values[0].longitude = mapdataGlobal.mapState.longitude - 25; - adapter.scene.keyframes.camera.values[0].pitch = 0; - adapter.scene.keyframes.camera.values[0].zoom = mapdataGlobal.mapState.zoom; - - adapter.scene.keyframes.camera.values[1].bearing = 0; - adapter.scene.keyframes.camera.values[1].latitude = mapdataGlobal.mapState.latitude; - adapter.scene.keyframes.camera.values[1].longitude = mapdataGlobal.mapState.longitude + 25; - adapter.scene.keyframes.camera.values[1].pitch = 0; - adapter.scene.keyframes.camera.values[0].zoom = mapdataGlobal.mapState.zoom; - }else if(cameraType === 'Zoom Out'){ - adapter.scene.keyframes.camera.values[0].bearing = 0; - adapter.scene.keyframes.camera.values[0].latitude = mapdataGlobal.mapState.latitude; - adapter.scene.keyframes.camera.values[0].longitude = mapdataGlobal.mapState.longitude; - adapter.scene.keyframes.camera.values[0].pitch = 0; - adapter.scene.keyframes.camera.values[0].zoom = mapdataGlobal.mapState.zoom; - - adapter.scene.keyframes.camera.values[1].bearing = 0; - adapter.scene.keyframes.camera.values[1].latitude = mapdataGlobal.mapState.latitude; - adapter.scene.keyframes.camera.values[1].longitude = mapdataGlobal.mapState.longitude; - adapter.scene.keyframes.camera.values[1].pitch = 0; - adapter.scene.keyframes.camera.values[1].zoom = mapdataGlobal.mapState.zoom - 2; - }else if(cameraType === 'Zoom In'){ - adapter.scene.keyframes.camera.values[0].bearing = 0; - adapter.scene.keyframes.camera.values[0].latitude = mapdataGlobal.mapState.latitude; - adapter.scene.keyframes.camera.values[0].longitude = mapdataGlobal.mapState.longitude; - adapter.scene.keyframes.camera.values[0].pitch = 0; - adapter.scene.keyframes.camera.values[0].zoom = mapdataGlobal.mapState.zoom; - - adapter.scene.keyframes.camera.values[1].bearing = 0; - adapter.scene.keyframes.camera.values[1].latitude = mapdataGlobal.mapState.latitude; - adapter.scene.keyframes.camera.values[1].longitude = mapdataGlobal.mapState.longitude; - adapter.scene.keyframes.camera.values[1].pitch = 0; - adapter.scene.keyframes.camera.values[1].zoom = mapdataGlobal.mapState.zoom + 2; - } - console.log("adapter", adapter); -} - -const encoderSettings = { - framerate: 30, - webm: { - quality: 0.8 - }, - jpeg: { - quality: 0.8 - }, - gif: { - sampleInterval: 1000 - }, - webm:{ - quality: 1.5 - }, - filename: "Default Video Name" + " " + moment().format(DEFAULT_TIME_FORMAT).toString() -}; - -function preview() { - adapter.render(PreviewEncoder, encoderSettings, ()=>{}); -} - -function setFileNameDeckAdapter(name){ - console.log(mapdataGlobal); - encoderSettings.filename = name + " " + moment().format(DEFAULT_TIME_FORMAT).toString(); -} - -/*function setResolution(resolution){ - if(resolution === 'Good (540p)'){ - adapter.scene.width = 960; - adapter.scene.height = 540; - }else if(resolution === 'High (720p)'){ - adapter.scene.width = 1280; - adapter.scene.height = 720; - }else if(resolution === 'Highest (1080p)'){ - adapter.scene.width = 1920; - adapter.scene.height = 1080; - } -}*/ - -// This is temporary, for showing purposes on Friday, resolution settings should be in a separate function, -// only because we are against the clock. -// TODO: refactor -function render(settingsdata){ - - // setResolution(settingsdata.resolution); // Remove this - - if (settingsdata.mediaType === 'WebM Video') { - adapter.render(WebMEncoder, encoderSettings, () => {}); - } else if (settingsdata.mediaType === 'PNG Sequence') { - adapter.render(PNGSequenceEncoder, encoderSettings, () => {}); - } else if (settingsdata.mediaType === 'JPEG Sequence') { - adapter.render(JPEGSequenceEncoder, encoderSettings, () => {}); - } - // preview(); - } - -// TODO: - -// Changes Timestamp function -// Camera function (preset keyframes) DONE -// File Name function DONE -// MediaType function DONE -// Quality function -// Set Duration function -// Calculate File Size function -// Render Function DONE - -function nop() {} - const IconButton = styled(Button)` padding: 0; svg { @@ -349,20 +109,21 @@ const InputGrid = styled.div` grid-row-gap: ${DEFAULT_ROW_GAP}; `; -const PanelBody = ({mapData, setMediaType, setCamera, setFileName/*, setQuality*/, settingsData}) => ( +const PanelBody = ({mapData, setMediaType, setCamera, setFileName, setQuality, setTimeStamps, settingsData}) => (
- +
Video Effects Timestamp {/* TODO add functionality */} Camera {/* TODO add functionality */} @@ -426,14 +187,14 @@ const ButtonGroup = styled.div` display: flex; `; -const PanelFooter = ({handleClose, settingsData}) => ( +const PanelFooter = ({handleClose, settingsData, preview}) => ( @@ -451,7 +212,7 @@ const PanelFooter = ({handleClose, settingsData}) => ( width={DEFAULT_BUTTON_WIDTH} height={DEFAULT_BUTTON_HEIGHT} className={'render-settings-button'} - onClick={() => render(settingsData)} + onClick={() => render(settingsData, settingsData.adapter)} > Render @@ -471,19 +232,24 @@ class RenderSettingsPanel extends Component { mediaType: "WebM Video", camera: "None", fileName: "Video Name", - // quality: "High (720p)" + quality: "High (720p)", + timestamps: "None" }; this.setMediaTypeState = this.setMediaTypeState.bind(this); this.setCamera = this.setCamera.bind(this); this.setFileName = this.setFileName.bind(this); - // this.setQuality = this.setQuality.bind(this); - mapdataGlobal = this.props.mapData; + this.setQuality = this.setQuality.bind(this); + this.setTimeStamps = this.setTimeStamps.bind(this); + + this.mapDataGlobal = this.props.mapData; + this.settingsController = ; + } static defaultProps = { settingsWidth: 980, - buttonHeight: '16px' + buttonHeight: '16px', }; setMediaTypeState(media){ @@ -495,7 +261,7 @@ class RenderSettingsPanel extends Component { this.setState({ camera: option }); - setKeyframes(option); + setKeyframes(option, this.settingsController.props.adapter, this.mapdataGlobal); } setFileName(name){ this.setState({ @@ -503,24 +269,31 @@ class RenderSettingsPanel extends Component { }); setFileNameDeckAdapter(name.target.value); } - /* setQuality(resolution){ + setQuality(resolution){ this.setState({ quality: resolution }); - setResolution(resolution); - }*/ - - + } + setTimeStamps(time){ + this.setState({ + timestamps: time + }); + } + render() { + const adapter = this.settingsController.props.adapter; + const {buttonHeight, settingsWidth, handleClose} = this.props; const settingsData = { mediaType : this.state.mediaType, camera : this.state.camera, fileName: this.state.fileName, resolution: this.state.quality, + time: this.state.timestamps, + adapter: adapter } - + return ( @@ -533,12 +306,14 @@ class RenderSettingsPanel extends Component { setMediaType={this.setMediaTypeState} setCamera={this.setCamera} setFileName={this.setFileName} - // setQuality={this.setQuality} + setQuality={this.setQuality} + setTimeStamps={this.setTimeStamps} settingsData={settingsData} /> {/* handleClose for Cancel button */} ); diff --git a/src/components/render/encoder-settings.js b/src/components/render/encoder-settings.js new file mode 100644 index 0000000000..8198e8e46b --- /dev/null +++ b/src/components/render/encoder-settings.js @@ -0,0 +1,18 @@ +import React, {Component} from 'react'; + +export const encoderSettings = { + framerate: 30, + webm: { + quality: 0.8 + }, + jpeg: { + quality: 2 + }, + gif: { + sampleInterval: 1000 + }, + webm:{ + quality: 1.5 + }, + filename: "Default Video Name" + " " + moment().format(DEFAULT_TIME_FORMAT).toString() + }; \ No newline at end of file diff --git a/src/components/render/keyframes.js b/src/components/render/keyframes.js new file mode 100644 index 0000000000..37c6e4e874 --- /dev/null +++ b/src/components/render/keyframes.js @@ -0,0 +1,126 @@ +export function setKeyframes(cameraType, adapter, mapdataGlobal){ + adapter.scene.keyframes.camera._lastTime = 0; + adapter.scene.keyframes.camera.factor = 0; + + + adapter.scene.keyframes.camera.values[0].latitude = mapdataGlobal.mapState.latitude; + adapter.scene.keyframes.camera.values[0].longitude = mapdataGlobal.mapState.longitude; + adapter.scene.keyframes.camera.values[1].latitude = mapdataGlobal.mapState.latitude; + adapter.scene.keyframes.camera.values[1].longitude = mapdataGlobal.mapState.longitude; + adapter.scene.keyframes.camera.values[0].zoom = mapdataGlobal.mapState.zoom; + adapter.scene.keyframes.camera.values[1].zoom = mapdataGlobal.mapState.zoom; + + if(cameraType === 'Orbit (90º)'){ + // How to reset the camera to its initial position? + adapter.scene.keyframes.camera.values[0].bearing = 0; + adapter.scene.keyframes.camera.values[0].latitude = mapdataGlobal.mapState.latitude; + adapter.scene.keyframes.camera.values[0].longitude = mapdataGlobal.mapState.longitude; + adapter.scene.keyframes.camera.values[0].pitch = 0; + adapter.scene.keyframes.camera.values[0].zoom = mapdataGlobal.mapState.zoom; + + adapter.scene.keyframes.camera.values[1].bearing = 90; + adapter.scene.keyframes.camera.values[1].latitude = mapdataGlobal.mapState.latitude; + adapter.scene.keyframes.camera.values[1].longitude = mapdataGlobal.mapState.longitude; + adapter.scene.keyframes.camera.values[1].pitch = 0; + adapter.scene.keyframes.camera.values[1].zoom = mapdataGlobal.mapState.zoom; + }else if(cameraType === 'Orbit (180º)'){ + adapter.scene.keyframes.camera.values[0].bearing = 0; + adapter.scene.keyframes.camera.values[0].latitude = mapdataGlobal.mapState.latitude; + adapter.scene.keyframes.camera.values[0].longitude = mapdataGlobal.mapState.longitude; + adapter.scene.keyframes.camera.values[0].pitch = 0; + adapter.scene.keyframes.camera.values[0].zoom = mapdataGlobal.mapState.zoom; + + adapter.scene.keyframes.camera.values[1].bearing = 180; + adapter.scene.keyframes.camera.values[1].latitude = mapdataGlobal.mapState.latitude; + adapter.scene.keyframes.camera.values[1].longitude = mapdataGlobal.mapState.longitude; + adapter.scene.keyframes.camera.values[1].pitch = 0; + adapter.scene.keyframes.camera.values[1].zoom = mapdataGlobal.mapState.zoom; + }else if(cameraType === 'Orbit (360º)'){ + adapter.scene.keyframes.camera.values[0].bearing = 0; + adapter.scene.keyframes.camera.values[0].latitude = mapdataGlobal.mapState.latitude; + adapter.scene.keyframes.camera.values[0].longitude = mapdataGlobal.mapState.longitude; + adapter.scene.keyframes.camera.values[0].pitch = 0; + adapter.scene.keyframes.camera.values[0].zoom = mapdataGlobal.mapState.zoom; + + adapter.scene.keyframes.camera.values[1].bearing = 360; + adapter.scene.keyframes.camera.values[1].latitude = mapdataGlobal.mapState.latitude; + adapter.scene.keyframes.camera.values[1].longitude = mapdataGlobal.mapState.longitude; + adapter.scene.keyframes.camera.values[1].pitch = 0; + adapter.scene.keyframes.camera.values[1].zoom = mapdataGlobal.mapState.zoom; + }else if(cameraType === 'North to South'){ + adapter.scene.keyframes.camera.values[0].bearing = 0; + adapter.scene.keyframes.camera.values[0].latitude = mapdataGlobal.mapState.latitude + 25; + adapter.scene.keyframes.camera.values[0].longitude = mapdataGlobal.mapState.longitude; + adapter.scene.keyframes.camera.values[0].pitch = 0; + adapter.scene.keyframes.camera.values[0].zoom = mapdataGlobal.mapState.zoom; + + adapter.scene.keyframes.camera.values[1].bearing = 0; + adapter.scene.keyframes.camera.values[1].latitude = mapdataGlobal.mapState.latitude - 25; + adapter.scene.keyframes.camera.values[1].longitude = mapdataGlobal.mapState.longitude; + adapter.scene.keyframes.camera.values[1].pitch = 0; + adapter.scene.keyframes.camera.values[1].zoom = mapdataGlobal.mapState.zoom; + }else if(cameraType === 'South to North'){ + adapter.scene.keyframes.camera.values[0].bearing = 0; + adapter.scene.keyframes.camera.values[0].latitude = mapdataGlobal.mapState.latitude - 25; + adapter.scene.keyframes.camera.values[0].longitude = mapdataGlobal.mapState.longitude; + adapter.scene.keyframes.camera.values[0].pitch = 0; + adapter.scene.keyframes.camera.values[0].zoom = mapdataGlobal.mapState.zoom; + + adapter.scene.keyframes.camera.values[1].bearing = 0; + adapter.scene.keyframes.camera.values[1].latitude = mapdataGlobal.mapState.latitude + 25; + adapter.scene.keyframes.camera.values[1].longitude = mapdataGlobal.mapState.longitude; + adapter.scene.keyframes.camera.values[1].pitch = 0; + adapter.scene.keyframes.camera.values[1].zoom = mapdataGlobal.mapState.zoom; + }else if(cameraType === 'East to West'){ + adapter.scene.keyframes.camera.values[0].bearing = 0; + adapter.scene.keyframes.camera.values[0].latitude = mapdataGlobal.mapState.latitude; + adapter.scene.keyframes.camera.values[0].longitude = mapdataGlobal.mapState.longitude + 25; + adapter.scene.keyframes.camera.values[0].pitch = 0; + adapter.scene.keyframes.camera.values[0].zoom = mapdataGlobal.mapState.zoom; + + adapter.scene.keyframes.camera.values[1].bearing = 0; + adapter.scene.keyframes.camera.values[1].latitude = mapdataGlobal.mapState.latitude; + adapter.scene.keyframes.camera.values[1].longitude = mapdataGlobal.mapState.longitude - 25; + adapter.scene.keyframes.camera.values[1].pitch = 0; + adapter.scene.keyframes.camera.values[1].zoom = mapdataGlobal.mapState.zoom; + }else if(cameraType === 'West to East'){ + adapter.scene.keyframes.camera.values[0].bearing = 0; + adapter.scene.keyframes.camera.values[0].latitude = mapdataGlobal.mapState.latitude; + adapter.scene.keyframes.camera.values[0].longitude = mapdataGlobal.mapState.longitude - 25; + adapter.scene.keyframes.camera.values[0].pitch = 0; + adapter.scene.keyframes.camera.values[0].zoom = mapdataGlobal.mapState.zoom; + + adapter.scene.keyframes.camera.values[1].bearing = 0; + adapter.scene.keyframes.camera.values[1].latitude = mapdataGlobal.mapState.latitude; + adapter.scene.keyframes.camera.values[1].longitude = mapdataGlobal.mapState.longitude + 25; + adapter.scene.keyframes.camera.values[1].pitch = 0; + adapter.scene.keyframes.camera.values[0].zoom = mapdataGlobal.mapState.zoom; + }else if(cameraType === 'Zoom Out'){ + adapter.scene.keyframes.camera.values[0].bearing = 0; + adapter.scene.keyframes.camera.values[0].latitude = mapdataGlobal.mapState.latitude; + adapter.scene.keyframes.camera.values[0].longitude = mapdataGlobal.mapState.longitude; + adapter.scene.keyframes.camera.values[0].pitch = 0; + adapter.scene.keyframes.camera.values[0].zoom = mapdataGlobal.mapState.zoom; + + adapter.scene.keyframes.camera.values[1].bearing = 0; + adapter.scene.keyframes.camera.values[1].latitude = mapdataGlobal.mapState.latitude; + adapter.scene.keyframes.camera.values[1].longitude = mapdataGlobal.mapState.longitude; + adapter.scene.keyframes.camera.values[1].pitch = 0; + adapter.scene.keyframes.camera.values[1].zoom = mapdataGlobal.mapState.zoom - 2; + }else if(cameraType === 'Zoom In'){ + adapter.scene.keyframes.camera.values[0].bearing = 0; + adapter.scene.keyframes.camera.values[0].latitude = mapdataGlobal.mapState.latitude; + adapter.scene.keyframes.camera.values[0].longitude = mapdataGlobal.mapState.longitude; + adapter.scene.keyframes.camera.values[0].pitch = 0; + adapter.scene.keyframes.camera.values[0].zoom = mapdataGlobal.mapState.zoom; + + adapter.scene.keyframes.camera.values[1].bearing = 0; + adapter.scene.keyframes.camera.values[1].latitude = mapdataGlobal.mapState.latitude; + adapter.scene.keyframes.camera.values[1].longitude = mapdataGlobal.mapState.longitude; + adapter.scene.keyframes.camera.values[1].pitch = 0; + adapter.scene.keyframes.camera.values[1].zoom = mapdataGlobal.mapState.zoom + 2; + } + + + console.log("adapter", adapter); + } \ No newline at end of file diff --git a/src/components/render/settings-controller.js b/src/components/render/settings-controller.js new file mode 100644 index 0000000000..4c6c006af4 --- /dev/null +++ b/src/components/render/settings-controller.js @@ -0,0 +1,130 @@ +import React, {Component} from 'react'; +import {DeckScene, CameraKeyframes} from '@hubble.gl/core'; +import {easing} from 'popmotion'; +import {DeckAdapter} from 'hubble.gl'; + +import { + WebMEncoder, + JPEGSequenceEncoder, + PNGSequenceEncoder, + PreviewEncoder, + GifEncoder + } from '@hubble.gl/core'; + +import {DEFAULT_TIME_FORMAT} from 'constants'; +import moment from 'moment'; + +let mapDataGlobal = null; + +const encoderSettings = { + framerate: 30, + webm: { + quality: 0.8 + }, + jpeg: { + quality: 2 + }, + gif: { + sampleInterval: 1000 + }, + webm:{ + quality: 1 + }, + filename: "Default Video Name" + " " + moment().format(DEFAULT_TIME_FORMAT).toString() + }; + +export class SettingsController extends Component{ + constructor(props) { + super(props); + + // I need to pass mapDataGlobal to be used here + } + + static defaultProps = { + adapter: new DeckAdapter(sceneBuilder) + }; + +} + + function sceneBuilder(animationLoop) { + console.log(" this.props.mapDataGlobal", mapDataGlobal); + const data = {}; + const keyframes = { + camera: new CameraKeyframes({ + timings: [0, 1000], + keyframes: [ + { + longitude: mapDataGlobal.mapState.longitude, + latitude: mapDataGlobal.mapState.latitude, + zoom: mapDataGlobal.mapState.zoom, + pitch: 0, + bearing: 0 + /* longitude: 11, + latitude: 0, + zoom: 2, + pitch: 0, + bearing: 0*/ + }, + { + longitude: mapDataGlobal.mapState.longitude, + latitude: mapDataGlobal.mapState.latitude, + zoom: mapDataGlobal.mapState.zoom, + bearing: 0, + pitch: 0 + /* longitude: 11, + latitude: 0, + zoom: 2, + pitch: 0, + bearing: 0*/ + } + ], + easings: [easing.easeInOut] + }) + }; + animationLoop.timeline.attachAnimation(keyframes.camera); + + // TODO: Figure out how to set up the size + return new DeckScene({ + animationLoop, + keyframes, + lengthMs: 1000, + data, + width: 480, + height: 460 + }); + } + + export function preview(adapter) { + adapter.render(PreviewEncoder, encoderSettings, ()=>{}); + } + + export function setFileNameDeckAdapter(name){ + encoderSettings.filename = name + " " + moment().format(DEFAULT_TIME_FORMAT).toString(); + } + + export function render(settingsdata, adapter){ + + // setResolution(settingsdata.resolution); // Remove this + + if (settingsdata.mediaType === 'WebM Video') { + adapter.render(WebMEncoder, encoderSettings, () => {}); // Onstop callback + } else if (settingsdata.mediaType === 'PNG Sequence') { + adapter.render(PNGSequenceEncoder, encoderSettings, () => {}); + } else if (settingsdata.mediaType === 'JPEG Sequence') { + adapter.render(JPEGSequenceEncoder, encoderSettings, () => {}); + } + // preview(); + } + + /*function setResolution(resolution){ + if(resolution === 'Good (540p)'){ + adapter.scene.width = 960; + adapter.scene.height = 540; + }else if(resolution === 'High (720p)'){ + adapter.scene.width = 1280; + adapter.scene.height = 720; + }else if(resolution === 'Highest (1080p)'){ + adapter.scene.width = 1920; + adapter.scene.height = 1080; + } +}*/ diff --git a/src/components/scene.js b/src/components/scene.js index e1373786eb..4d02b68247 100644 --- a/src/components/scene.js +++ b/src/components/scene.js @@ -173,9 +173,9 @@ export class Scene extends Component { .reduce(this._renderLayer, []); } - deckGlLayers[2] = deckGlLayers[1]; + /* deckGlLayers[2] = deckGlLayers[1]; deckGlLayers[1] = deckGlLayers[0] - deckGlLayers[0] = tileLayer; + deckGlLayers[0] = tileLayer; */ @@ -193,7 +193,7 @@ export class Scene extends Component { const style = { position: 'relative' } - console.log("tilelayer ",tileLayer); + console.log("adapter from scene ", this.props.adapter); return (
@@ -211,7 +211,14 @@ export class Scene extends Component { {...this.props.adapter.getProps(this.deckgl, () => {}, () => {this.forceUpdate()})} > - + 'pointer' : undefined} + transitionDuration={TRANSITION_DURATION} + >