Add very simple end animation

This commit is contained in:
DD committed 2018-02-23 15:35:42 -05:00
1 parent 97d6308aa5
commit 4aa3b20a93
9 files changed
+135 -77

No files matched your search

@@ -112,3 +112,34 @@
75% {transform: rotate(-2deg) scale(1.05);}
100% {transform: rotate(0deg) scale(1.05);}
}
.receivedBlocks {
-webkit-animation: glowing 250ms;
-moz-animation: glowing 250ms;
-o-animation: glowing 250ms;
animation: glowing 250ms;
}
@-webkit-keyframes glowing {
10% { -webkit-box-shadow: 0 0 10px #7fff1e; }
90% { -webkit-box-shadow: 0 0 10px #7fff1e; }
100% { -webkit-box-shadow: none; }
}
@-moz-keyframes glowing {
10% { -moz-box-shadow: 0 0 10px #7fff1e; }
90% { -moz-box-shadow: 0 0 10px #7fff1e; }
100% { -moz-box-shadow: none; }
}
@-o-keyframes glowing {
10% { box-shadow: 0 0 10px #7fff1e; }
90% { box-shadow: 0 0 10px #7fff1e; }
100% { box-shadow: none; }
}
@keyframes glowing {
10% { box-shadow: 0 0 10px #7fff1e; }
90% { box-shadow: 0 0 10px #7fff1e; }
100% { box-shadow: none; }
}
@@ -21,6 +21,8 @@ const messages = defineMessages({
const SpriteSelectorComponent = function (props) {
const {
editingTarget,
hoveredTarget,
intl,
onChangeSpriteDirection,
onChangeSpriteName,
@@ -30,8 +32,6 @@ const SpriteSelectorComponent = function (props) {
onChangeSpriteY,
onDeleteSprite,
onDuplicateSprite,
onMouseOutSprite,
onMouseOverSprite,
onNewSpriteClick,
onSelectSprite,
raised,
@@ -76,10 +76,12 @@ const SpriteSelectorComponent = function (props) {
.map(sprite => (
<SpriteSelectorItem
assetId={sprite.costume && sprite.costume.assetId}
className={
(raised && sprite.id !== selectedId) ?
classNames(styles.sprite, styles.raised) : styles.sprite
}
className={hoveredTarget.sprite === sprite.id &&
sprite.id !== editingTarget &&
hoveredTarget.receivedBlocks ?
classNames(styles.sprite, styles.receivedBlocks) :
raised && sprite.id !== editingTarget ?
classNames(styles.sprite, styles.raised) : styles.sprite}
id={sprite.id}
key={sprite.id}
name={sprite.name}
@@ -87,8 +89,6 @@ const SpriteSelectorComponent = function (props) {
onClick={onSelectSprite}
onDeleteButtonClick={onDeleteSprite}
onDuplicateButtonClick={onDuplicateSprite}
onMouseOut={onMouseOutSprite}
onMouseOver={onMouseOverSprite}
/>
))
}
@@ -105,6 +105,11 @@ const SpriteSelectorComponent = function (props) {
};
SpriteSelectorComponent.propTypes = {
editingTarget: PropTypes.string,
hoveredTarget: PropTypes.shape({
hoveredSprite: PropTypes.string,
receivedBlocks: PropTypes.bool
}),
intl: intlShape.isRequired,
onChangeSpriteDirection: PropTypes.func,
onChangeSpriteName: PropTypes.func,
@@ -114,8 +119,6 @@ SpriteSelectorComponent.propTypes = {
onChangeSpriteY: PropTypes.func,
onDeleteSprite: PropTypes.func,
onDuplicateSprite: PropTypes.func,
onMouseOutSprite: PropTypes.func,
onMouseOverSprite: PropTypes.func,
onNewSpriteClick: PropTypes.func,
onSelectSprite: PropTypes.func,
raised: PropTypes.bool,
+7 -6
View File
@@ -19,6 +19,7 @@ import styles from './target-pane.css';
const TargetPane = ({
backdropLibraryVisible,
editingTarget,
hoveredTarget,
spriteLibraryVisible,
onChangeSpriteDirection,
onChangeSpriteName,
@@ -28,8 +29,6 @@ const TargetPane = ({
onChangeSpriteY,
onDeleteSprite,
onDuplicateSprite,
onMouseOutSprite,
onMouseOverSprite,
onNewSpriteClick,
onRequestCloseSpriteLibrary,
onRequestCloseBackdropLibrary,
@@ -46,6 +45,8 @@ const TargetPane = ({
>
<SpriteSelectorComponent
editingTarget={editingTarget}
hoveredTarget={hoveredTarget}
raised={raiseSprites}
selectedId={editingTarget}
sprites={sprites}
@@ -57,8 +58,6 @@ const TargetPane = ({
onChangeSpriteY={onChangeSpriteY}
onDeleteSprite={onDeleteSprite}
onDuplicateSprite={onDuplicateSprite}
onMouseOutSprite={onMouseOutSprite}
onMouseOverSprite={onMouseOverSprite}
onNewSpriteClick={onNewSpriteClick}
onSelectSprite={onSelectSprite}
/>
@@ -113,6 +112,10 @@ TargetPane.propTypes = {
backdropLibraryVisible: PropTypes.bool,
editingTarget: PropTypes.string,
extensionLibraryVisible: PropTypes.bool,
hoveredTarget: PropTypes.shape({
hoveredSprite: PropTypes.string,
receivedBlocks: PropTypes.bool
}),
onChangeSpriteDirection: PropTypes.func,
onChangeSpriteName: PropTypes.func,
onChangeSpriteSize: PropTypes.func,
@@ -121,8 +124,6 @@ TargetPane.propTypes = {
onChangeSpriteY: PropTypes.func,
onDeleteSprite: PropTypes.func,
onDuplicateSprite: PropTypes.func,
onMouseOutSprite: PropTypes.func,
onMouseOverSprite: PropTypes.func,
onNewSpriteClick: PropTypes.func,
onRequestCloseBackdropLibrary: PropTypes.func,
onRequestCloseExtensionLibrary: PropTypes.func,
+20 -12
View File
@@ -1,9 +1,10 @@
import bindAll from 'lodash.bindall';
import PropTypes from 'prop-types';
import React from 'react';
import {connect} from 'react-redux';
import {setHoveredSprite} from '../reducers/hovered-target';
import SpriteSelectorItemComponent from '../components/sprite-selector-item/sprite-selector-item.jsx';
class SpriteSelectorItem extends React.Component {
@@ -33,10 +34,10 @@ class SpriteSelectorItem extends React.Component {
this.props.onDuplicateButtonClick(this.props.id);
}
handleMouseOut () {
this.props.onMouseOut(this.props.id);
this.props.dispatchSetHoveredSprite(null);
}
handleMouseOver () {
this.props.onMouseOver(this.props.id);
this.props.dispatchSetHoveredSprite(this.props.id);
}
render () {
const {
@@ -46,8 +47,7 @@ class SpriteSelectorItem extends React.Component {
onClick,
onDeleteButtonClick,
onDuplicateButtonClick,
onMouseOut,
onMouseOver,
receivedBlocks,
/* eslint-enable no-unused-vars */
...props
} = this.props;
@@ -56,8 +56,8 @@ class SpriteSelectorItem extends React.Component {
onClick={this.handleClick}
onDeleteButtonClick={onDeleteButtonClick ? this.handleDelete : null}
onDuplicateButtonClick={onDuplicateButtonClick ? this.handleDuplicate : null}
onMouseOut={onMouseOut ? this.handleMouseOut : null}
onMouseOver={onMouseOver ? this.handleMouseOver : null}
onMouseOut={this.handleMouseOut}
onMouseOver={this.handleMouseOver}
{...props}
/>
);
@@ -67,20 +67,28 @@ class SpriteSelectorItem extends React.Component {
SpriteSelectorItem.propTypes = {
assetId: PropTypes.string,
costumeURL: PropTypes.string,
dispatchSetHoveredSprite: PropTypes.func.isRequired,
id: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
name: PropTypes.string,
onClick: PropTypes.func,
onDeleteButtonClick: PropTypes.func,
onDuplicateButtonClick: PropTypes.func,
onMouseOut: PropTypes.func,
onMouseOver: PropTypes.func,
receivedBlocks: PropTypes.bool,
selected: PropTypes.bool
};
const mapStateToProps = (state, {assetId, costumeURL}) => ({
costumeURL: costumeURL || (assetId && state.vm.runtime.storage.get(assetId).encodeDataURI())
const mapStateToProps = (state, {assetId, costumeURL, id}) => ({
costumeURL: costumeURL || (assetId && state.vm.runtime.storage.get(assetId).encodeDataURI()),
receivedBlocks: state.hoveredTarget.receivedBlocks &&
state.hoveredTarget.sprite === id
});
const mapDispatchToProps = dispatch => ({
dispatchSetHoveredSprite: spriteId => {
dispatch(setHoveredSprite(spriteId));
}
});
export default connect(
mapStateToProps
mapStateToProps,
mapDispatchToProps
)(SpriteSelectorItem);
+1 -15
View File
@@ -9,8 +9,6 @@ import {
closeSpriteLibrary
} from '../reducers/modals';
import {setHoveredSprite} from '../reducers/hovered-target-sprite';
import TargetPaneComponent from '../components/target-pane/target-pane.jsx';
class TargetPane extends React.Component {
@@ -25,8 +23,6 @@ class TargetPane extends React.Component {
'handleChangeSpriteY',
'handleDeleteSprite',
'handleDuplicateSprite',
'handleMouseOutSprite',
'handleMouseOverSprite',
'handleSelectSprite'
]);
}
@@ -54,12 +50,6 @@ class TargetPane extends React.Component {
handleDuplicateSprite (id) {
this.props.vm.duplicateSprite(id);
}
handleMouseOutSprite () {
this.props.setHoveredSprite(null);
}
handleMouseOverSprite (id) {
this.props.setHoveredSprite(id);
}
handleSelectSprite (id) {
this.props.vm.setEditingTarget(id);
}
@@ -75,8 +65,6 @@ class TargetPane extends React.Component {
onChangeSpriteY={this.handleChangeSpriteY}
onDeleteSprite={this.handleDeleteSprite}
onDuplicateSprite={this.handleDuplicateSprite}
onMouseOutSprite={this.handleMouseOutSprite}
onMouseOverSprite={this.handleMouseOverSprite}
onSelectSprite={this.handleSelectSprite}
/>
);
@@ -94,6 +82,7 @@ TargetPane.propTypes = {
const mapStateToProps = state => ({
editingTarget: state.targets.editingTarget,
hoveredTarget: state.hoveredTarget,
sprites: Object.keys(state.targets.sprites).reduce((sprites, k) => {
let {direction, size, x, y, ...sprite} = state.targets.sprites[k];
if (typeof direction !== 'undefined') direction = Math.round(direction);
@@ -118,9 +107,6 @@ const mapDispatchToProps = dispatch => ({
},
onRequestCloseBackdropLibrary: () => {
dispatch(closeBackdropLibrary());
},
setHoveredSprite: spriteId => {
dispatch(setHoveredSprite(spriteId));
}
});
+13 -4
View File
@@ -8,6 +8,7 @@ import {connect} from 'react-redux';
import {updateEditingTarget, updateTargets} from '../reducers/targets';
import {updateBlockDrag} from '../reducers/block-drag';
import {updateMonitors} from '../reducers/monitors';
import {setReceivedBlocks} from '../reducers/hovered-target';
/*
* Higher Order Component to manage events emitted by the VM
@@ -51,8 +52,9 @@ const vmListenerHOC = function (WrappedComponent) {
}
}
handleBlockDragEnd (blocks) {
if (this.props.hoveredTargetSprite && this.props.hoveredTargetSprite !== this.props.editingTarget) {
this.props.vm.shareBlocksToTarget(blocks, this.props.hoveredTargetSprite);
if (this.props.hoveredSprite && this.props.hoveredSprite !== this.props.editingTarget) {
this.props.vm.shareBlocksToTarget(blocks, this.props.hoveredSprite);
this.props.onReceivedBlocks(true);
}
}
handleKeyDown (e) {
@@ -86,10 +88,13 @@ const vmListenerHOC = function (WrappedComponent) {
const {
/* eslint-disable no-unused-vars */
attachKeyboardEvents,
editingTarget,
hoveredSprite,
onBlockDragUpdate,
onKeyDown,
onKeyUp,
onMonitorsUpdate,
onReceivedBlocks,
onTargetsUpdate,
/* eslint-enable no-unused-vars */
...props
@@ -100,11 +105,12 @@ const vmListenerHOC = function (WrappedComponent) {
VMListener.propTypes = {
attachKeyboardEvents: PropTypes.bool,
editingTarget: PropTypes.string,
hoveredTargetSprite: PropTypes.string,
hoveredSprite: PropTypes.string,
onBlockDragUpdate: PropTypes.func.isRequired,
onKeyDown: PropTypes.func,
onKeyUp: PropTypes.func,
onMonitorsUpdate: PropTypes.func.isRequired,
onReceivedBlocks: PropTypes.func.isRequired,
onTargetsUpdate: PropTypes.func.isRequired,
vm: PropTypes.instanceOf(VM).isRequired
};
@@ -113,7 +119,7 @@ const vmListenerHOC = function (WrappedComponent) {
};
const mapStateToProps = state => ({
vm: state.vm,
hoveredTargetSprite: state.hoveredTargetSprite,
hoveredSprite: state.hoveredTarget.sprite,
editingTarget: state.targets.editingTarget
});
const mapDispatchToProps = dispatch => ({
@@ -126,6 +132,9 @@ const vmListenerHOC = function (WrappedComponent) {
},
onBlockDragUpdate: areBlocksOverGui => {
dispatch(updateBlockDrag(areBlocksOverGui));
},
onReceivedBlocks: receivedBlocks => {
dispatch(setReceivedBlocks(receivedBlocks));
}
});
return connect(
+2 -2
View File
@@ -2,7 +2,7 @@ import {combineReducers} from 'redux';
import colorPickerReducer from './color-picker';
import customProceduresReducer from './custom-procedures';
import blockDragReducer from './block-drag';
import hoveredTargetSpriteReducer from './hovered-target-sprite';
import hoveredTargetReducer from './hovered-target';
import intlReducer from './intl';
import modalReducer from './modals';
import monitorReducer from './monitors';
@@ -17,7 +17,7 @@ export default combineReducers({
blockDrag: blockDragReducer,
colorPicker: colorPickerReducer,
customProcedures: customProceduresReducer,
hoveredTargetSprite: hoveredTargetSpriteReducer,
hoveredTarget: hoveredTargetReducer,
intl: intlReducer,
stageSize: stageSizeReducer,
modals: modalReducer,
-28
View File
@@ -1,28 +0,0 @@
const SET_HOVERED_SPRITE = 'scratch-gui/hovered-target-sprite/SET_HOVERED_SPRITE';
const initialState = null;
const reducer = function (state, action) {
if (typeof state === 'undefined') state = initialState;
switch (action.type) {
case SET_HOVERED_SPRITE:
return action.spriteId;
default:
return state;
}
};
const setHoveredSprite = function (spriteId) {
return {
type: SET_HOVERED_SPRITE,
spriteId: spriteId,
meta: {
throttle: 30
}
};
};
export {
reducer as default,
setHoveredSprite
};
+48
View File
@@ -0,0 +1,48 @@
const SET_HOVERED_SPRITE = 'scratch-gui/hovered-target/SET_HOVERED_SPRITE';
const SET_RECEIVED_BLOCKS = 'scratch-gui/hovered-target/SET_RECEIVED_BLOCKS';
const initialState = {
sprite: null,
receivedBlocks: false
};
const reducer = function (state, action) {
if (typeof state === 'undefined') state = initialState;
switch (action.type) {
case SET_HOVERED_SPRITE:
return {
sprite: action.spriteId,
receivedBlocks: false
};
case SET_RECEIVED_BLOCKS:
return {
sprite: state.sprite,
receivedBlocks: action.receivedBlocks
};
default:
return state;
}
};
const setHoveredSprite = function (spriteId) {
return {
type: SET_HOVERED_SPRITE,
spriteId: spriteId,
meta: {
throttle: 30
}
};
};
const setReceivedBlocks = function (receivedBlocks) {
return {
type: SET_RECEIVED_BLOCKS,
receivedBlocks: receivedBlocks
};
};
export {
reducer as default,
setHoveredSprite,
setReceivedBlocks
};