From 77f58580012f51ebcd7975e28b051ffcd285122f Mon Sep 17 00:00:00 2001 From: CPunisher <1343316114@qq.com> Date: Sat, 15 Aug 2020 14:37:55 +0800 Subject: [PATCH] [title & icon] --- src/actions/index.js | 14 ++++ src/components/app/PartParams.js | 4 ++ src/components/param/FrameworkParam.js | 18 +++++ src/components/param/ParamColor.js | 2 +- src/components/param/ParamCorrectLevel.js | 31 --------- src/components/param/ParamList.js | 20 ++---- .../param/disposable/ParamCorrectLevel.js | 25 +++++++ src/components/param/disposable/ParamIcon.js | 50 ++++++++++++++ src/components/param/disposable/ParamTitle.js | 67 +++++++++++++++++++ src/components/renderer/RendererFunc.js | 1 - src/components/style/Renderer.js | 66 +++++++++++++++--- src/constant/ActionTypes.js | 2 + .../param/ParamCorrectLevelViewer.js | 2 +- .../param/disposable/ParamIconSrcViewer.js | 23 +++++++ .../param/disposable/ParamIconViewer.js | 15 +++++ .../param/disposable/ParamTitleColorViewer.js | 16 +++++ .../param/disposable/ParamTitleViewer.js | 15 +++++ src/containers/style/RendererViewer.js | 2 + src/reducers/index.js | 12 ++++ 19 files changed, 329 insertions(+), 56 deletions(-) create mode 100644 src/components/param/FrameworkParam.js delete mode 100644 src/components/param/ParamCorrectLevel.js create mode 100644 src/components/param/disposable/ParamCorrectLevel.js create mode 100644 src/components/param/disposable/ParamIcon.js create mode 100644 src/components/param/disposable/ParamTitle.js create mode 100644 src/containers/param/disposable/ParamIconSrcViewer.js create mode 100644 src/containers/param/disposable/ParamIconViewer.js create mode 100644 src/containers/param/disposable/ParamTitleColorViewer.js create mode 100644 src/containers/param/disposable/ParamTitleViewer.js diff --git a/src/actions/index.js b/src/actions/index.js index a7e3ef6..ad09615 100644 --- a/src/actions/index.js +++ b/src/actions/index.js @@ -36,3 +36,17 @@ export const loadDownloadData = (data) => ({ type: actionTypes.LOAD_DOWNLOAD_DATA, data }) + +export const changeTitle = (title) => { + return { + type: actionTypes.CHANGE_TITLE, + title + } +} + +export const changeIcon = (icon) => { + return { + type: actionTypes.CHANGE_ICON, + icon + } +} diff --git a/src/components/app/PartParams.js b/src/components/app/PartParams.js index 968ecda..51bfde0 100644 --- a/src/components/app/PartParams.js +++ b/src/components/app/PartParams.js @@ -2,6 +2,8 @@ import React from 'react'; import './App.css'; import ParamListViewer from "../../containers/param/ParamListViewer"; import ParamCorrectLevelViewer from "../../containers/param/ParamCorrectLevelViewer"; +import ParamTitleViewer from "../../containers/param/disposable/ParamTitleViewer"; +import ParamIconViewer from "../../containers/param/disposable/ParamIconViewer"; const PartParams = () => (
@@ -12,6 +14,8 @@ const PartParams = () => (
+ +
diff --git a/src/components/param/FrameworkParam.js b/src/components/param/FrameworkParam.js new file mode 100644 index 0000000..a0d0337 --- /dev/null +++ b/src/components/param/FrameworkParam.js @@ -0,0 +1,18 @@ +import React from 'react'; +import PropTypes from 'prop-types' +import '../Qrcode.css'; + +const FrameworkParam = ({ paramName, children, ...other }) => ( + + + + + + + +
{ paramName } + { children } +
+) + +export default FrameworkParam; diff --git a/src/components/param/ParamColor.js b/src/components/param/ParamColor.js index e8ecd08..3c83c84 100644 --- a/src/components/param/ParamColor.js +++ b/src/components/param/ParamColor.js @@ -42,7 +42,7 @@ const ParamColor = ({ rendererIndex, paramIndex, value, onChange }) => {
setDisplay(false)} /> ( - - - - - - - -
容错率 - -
-) - -ParamCorrectLevel.propTypes = { - value: PropTypes.number.isRequired, - onChange: PropTypes.func.isRequired -} - -export default ParamCorrectLevel; diff --git a/src/components/param/ParamList.js b/src/components/param/ParamList.js index fdb52da..6662755 100644 --- a/src/components/param/ParamList.js +++ b/src/components/param/ParamList.js @@ -6,6 +6,7 @@ import ParamSelectViewer from "../../containers/param/ParamSelectViewer"; import ParamColorViewer from "../../containers/param/ParamColorViewer"; import ParamUploadViewer from "../../containers/param/ParamUploadViewer"; import ParamCheckBoxViewer from "../../containers/param/ParamCheckBoxViewer"; +import FrameworkParam from "./FrameworkParam"; const mapTypeToComponent = ({ [ParamTypes.TEXT_EDITOR]: ParamTextViewer, @@ -18,19 +19,12 @@ const mapTypeToComponent = ({ const ParamList = ({ rendererIndex, paramInfo }) => ( paramInfo.map((item, paramIndex) => { return ( - - - - - - - -
{item.key} - {React.createElement(mapTypeToComponent[item.type], { - rendererIndex: rendererIndex, - paramIndex: paramIndex - })} -
+ + {React.createElement(mapTypeToComponent[item.type], { + rendererIndex: rendererIndex, + paramIndex: paramIndex + })} + ); }) ) diff --git a/src/components/param/disposable/ParamCorrectLevel.js b/src/components/param/disposable/ParamCorrectLevel.js new file mode 100644 index 0000000..b6c3540 --- /dev/null +++ b/src/components/param/disposable/ParamCorrectLevel.js @@ -0,0 +1,25 @@ +import React from 'react'; +import PropTypes from 'prop-types' +import '../../Qrcode.css'; +import FrameworkParam from "../FrameworkParam"; + +const ParamCorrectLevel = ({value, onChange}) => ( + + + +) + +ParamCorrectLevel.propTypes = { + value: PropTypes.number.isRequired, + onChange: PropTypes.func.isRequired +} + +export default ParamCorrectLevel; diff --git a/src/components/param/disposable/ParamIcon.js b/src/components/param/disposable/ParamIcon.js new file mode 100644 index 0000000..9180c10 --- /dev/null +++ b/src/components/param/disposable/ParamIcon.js @@ -0,0 +1,50 @@ +import React from 'react'; +import PropTypes from 'prop-types' +import '../../Qrcode.css'; +import FrameworkParam from "../FrameworkParam"; +import {getExactValue} from "../../../utils/util"; +import ParamIconSrcViewer from "../../../containers/param/disposable/ParamIconSrcViewer"; + +const IconParams = ({ icon, onChange }) => { + const { enabled, src, scale } = icon; + if (getExactValue(enabled, 0)) { + return ( + + + + + + onChange({...icon, scale: e.target.value})} + /> + + + ) + } + return null; +} + +const ParamIcon = ({icon, onChange}) => ( + + + + + + +) + +ParamIcon.propTypes = { + icon: PropTypes.object.isRequired, + onChange: PropTypes.func.isRequired +} + +export default ParamIcon; diff --git a/src/components/param/disposable/ParamTitle.js b/src/components/param/disposable/ParamTitle.js new file mode 100644 index 0000000..206c73b --- /dev/null +++ b/src/components/param/disposable/ParamTitle.js @@ -0,0 +1,67 @@ +import React from 'react'; +import PropTypes from 'prop-types' +import '../../Qrcode.css'; +import FrameworkParam from "../FrameworkParam"; +import {getExactValue} from "../../../utils/util"; +import ParamTitleColorViewer from "../../../containers/param/disposable/ParamTitleColorViewer"; + +const TitleParams = ({ title, onChange }) => { + const { enabled, text, color, size, align } = title; + if (getExactValue(enabled, 0)) { + return ( + + + onChange({...title, text: e.target.value})} + /> + + + + + + onChange({...title, size: e.target.value})} + /> + + + + + + ) + } + return null; +} + +const ParamTitle = ({title, onChange}) => ( + + + + + + +) + +ParamTitle.propTypes = { + title: PropTypes.object.isRequired, + onChange: PropTypes.func.isRequired +} + +export default ParamTitle; diff --git a/src/components/renderer/RendererFunc.js b/src/components/renderer/RendererFunc.js index 82ba1b2..7bd2b46 100644 --- a/src/components/renderer/RendererFunc.js +++ b/src/components/renderer/RendererFunc.js @@ -13,7 +13,6 @@ function listPoints(qrcode, params) { let type = params[0]; let size = params[1] / 100; let funcType = params[1]; - let opacity = params[2] / 100; let posType = params[3]; let id = 0; let otherColor = params[4]; diff --git a/src/components/style/Renderer.js b/src/components/style/Renderer.js index 8a64af6..4c9fa9e 100644 --- a/src/components/style/Renderer.js +++ b/src/components/style/Renderer.js @@ -1,5 +1,5 @@ import React, {useEffect} from "react"; -import {extend} from "../../utils/util"; +import {extend, getExactValue} from "../../utils/util"; const Renderer = ({ rendererType, ...other }) => ( React.createElement(rendererType, other) @@ -9,24 +9,72 @@ function areEqual(prevProps, nextProps) { return !(prevProps.selected === true || nextProps.selected === true) } -export function createRenderer(renderer) { - let defaultViewBox = function (qrcode) { - if (!qrcode) return '0 0 0 0'; +let defaultViewBox = function (qrcode) { + if (!qrcode) return '0 0 0 0'; - const nCount = qrcode.getModuleCount(); - return String(-nCount / 5) + ' ' + String(-nCount / 5) + ' ' + String(nCount + nCount / 5 * 2) + ' ' + String(nCount + nCount / 5 * 2); + const nCount = qrcode.getModuleCount(); + return String(-nCount / 5) + ' ' + String(-nCount / 5) + ' ' + String(nCount + nCount / 5 * 2) + ' ' + String(nCount + nCount / 5 * 2); +} + +let drawIcon = function (qrcode, title, icon) { + if (!qrcode) return [] + if (!title && !icon) return null; + + let id = 0; + const titleEnabled = getExactValue(title.enabled, 0); + const iconEnabled = getExactValue(icon.enabled, 0); + const {text, color, size, align} = title; + const {src, scale} = icon; + + const nCount = qrcode.getModuleCount(); + // const { fontSize, color, verticalAlign, ...titleStyle } = styles.title || {}; + // const titleVerticalAlign = titleAlign || verticalAlign || (icon ? "bottom" : "middle"); + // iconScale = iconScale > .33 ? .33 : iconScale; + const titleStyle = {}; + const titleVerticalAlign = align; + + const iconSize = Number(nCount * (scale > .33 ? .33 : scale)); + const iconXY = (nCount - iconSize) / 2; + + const pointList = []; + if ((titleEnabled && align === "middle") || iconEnabled) { + pointList.push(); } + if (icon && iconEnabled) { + pointList.push(); + } + + if (title && titleEnabled) { + // const svgWidth = styles.svg && styles.svg.width ? styles.svg.width.replace("px", "") : 300; + // const titleFontSize = Number(nCount + nCount / 5 * 2) * (titleSize || fontSize || 12) / svgWidth; + // const titleFontColor = titleColor || color || "#000000"; + const svgWidth = 300; + const titleFontSize = Number(nCount + nCount / 5 * 2) * size / svgWidth; + const titleFontColor = color; + + const fontY = titleVerticalAlign === "middle" + ? (icon ? (iconXY + iconSize) : (nCount / 2 + titleFontSize * .5)) + : Number(nCount + nCount / 5) - titleFontSize * .5; + + pointList.push({text}) + } + + return pointList; +} + +export function createRenderer(renderer) { + + renderer = extend({ getViewBox: defaultViewBox, listPoints: (qrcode, params) => { return []; }, getParamInfo: () => {return []; }, beginRendering: ({ qrcode, params, setParamInfo }) => {}, beforeListing: ({ qrcode, params, setParamInfo }) => {}, - afterListing: ({ qrcode, params, setParamInfo }) => {}, }, renderer); - return ({ qrcode, params, setParamInfo}) => { + return ({ qrcode, params, title, icon, setParamInfo}) => { useEffect(() => { setParamInfo(renderer.getParamInfo()); }, [setParamInfo]); @@ -37,7 +85,7 @@ export function createRenderer(renderer) { xmlns="http://www.w3.org/2000/svg" xmlnsXlink="http://www.w3.org/1999/xlink"> {renderer.beforeListing({ qrcode, params, setParamInfo })} {renderer.listPoints(qrcode, params)} - {renderer.afterListing({ qrcode, params, setParamInfo })} + {drawIcon(qrcode, title, icon)} ); } diff --git a/src/constant/ActionTypes.js b/src/constant/ActionTypes.js index 12a5c88..b2a11df 100644 --- a/src/constant/ActionTypes.js +++ b/src/constant/ActionTypes.js @@ -5,4 +5,6 @@ export const actionTypes = { CREATE_PARAM: 'CREATE_PARAM', CHANGE_PARAM: 'CHANGE_PARAM', LOAD_DOWNLOAD_DATA: 'LOAD_DOWNLOAD_DATA', + CHANGE_TITLE: 'CHANGE_TITLE', + CHANGE_ICON: 'CHANGE_ICON' } diff --git a/src/containers/param/ParamCorrectLevelViewer.js b/src/containers/param/ParamCorrectLevelViewer.js index aa872ae..db00b3b 100644 --- a/src/containers/param/ParamCorrectLevelViewer.js +++ b/src/containers/param/ParamCorrectLevelViewer.js @@ -1,5 +1,5 @@ import {changeCorrectLevel} from "../../actions"; -import ParamCorrectLevel from "../../components/param/ParamCorrectLevel"; +import ParamCorrectLevel from "../../components/param/disposable/ParamCorrectLevel"; import {connect} from "react-redux"; const mapStateToProps = (state) => ({ diff --git a/src/containers/param/disposable/ParamIconSrcViewer.js b/src/containers/param/disposable/ParamIconSrcViewer.js new file mode 100644 index 0000000..3c859b7 --- /dev/null +++ b/src/containers/param/disposable/ParamIconSrcViewer.js @@ -0,0 +1,23 @@ +import { connect } from 'react-redux'; +import {isPicture, toBase64} from "../../../utils/imageUtils"; +import ParamUpload from "../../../components/param/ParamUpload"; + +const mapStateToProps = (state, ownProps) => ({ + rendererIndex: -1, + paramIndex: -1, +}) + +const mapDispatchToProps = (dispatch, ownProps) => ({ + onChange: (e) => { + if (e.target.files.length > 0) { + const file = e.target.files[0]; + if (isPicture(file)) { + toBase64(file, 1.0).then(res => { + ownProps.onChange({ ...ownProps.icon, src: res}) + }) + } + } + } +}) + +export default connect(mapStateToProps, mapDispatchToProps)(ParamUpload); diff --git a/src/containers/param/disposable/ParamIconViewer.js b/src/containers/param/disposable/ParamIconViewer.js new file mode 100644 index 0000000..83b9304 --- /dev/null +++ b/src/containers/param/disposable/ParamIconViewer.js @@ -0,0 +1,15 @@ +import { connect } from 'react-redux'; +import ParamIcon from "../../../components/param/disposable/ParamIcon"; +import {changeIcon} from "../../../actions"; + +const mapStateToProps = (state, ownProps) => ({ + icon: state.icon +}) + +const mapDispatchToProps = (dispatch, ownProps) => ({ + onChange: (icon) => { + dispatch(changeIcon(icon)) + } +}) + +export default connect(mapStateToProps, mapDispatchToProps)(ParamIcon); diff --git a/src/containers/param/disposable/ParamTitleColorViewer.js b/src/containers/param/disposable/ParamTitleColorViewer.js new file mode 100644 index 0000000..3f8f930 --- /dev/null +++ b/src/containers/param/disposable/ParamTitleColorViewer.js @@ -0,0 +1,16 @@ +import { connect } from 'react-redux'; +import ParamColor from "../../../components/param/ParamColor"; + +const mapStateToProps = (state, ownProps) => ({ + rendererIndex: -1, + paramIndex: -1, + value: state.title.color +}) + +const mapDispatchToProps = (dispatch, ownProps) => ({ + onChange: (color) => { + ownProps.onChange({ ...ownProps.title, color: color.hex }) + } +}) + +export default connect(mapStateToProps, mapDispatchToProps)(ParamColor); diff --git a/src/containers/param/disposable/ParamTitleViewer.js b/src/containers/param/disposable/ParamTitleViewer.js new file mode 100644 index 0000000..dc50fe4 --- /dev/null +++ b/src/containers/param/disposable/ParamTitleViewer.js @@ -0,0 +1,15 @@ +import { connect } from 'react-redux'; +import ParamTitle from "../../../components/param/disposable/ParamTitle"; +import {changeTitle} from "../../../actions"; + +const mapStateToProps = (state, ownProps) => ({ + title: state.title +}) + +const mapDispatchToProps = (dispatch, ownProps) => ({ + onChange: (title) => { + dispatch(changeTitle(title)) + } +}) + +export default connect(mapStateToProps, mapDispatchToProps)(ParamTitle); diff --git a/src/containers/style/RendererViewer.js b/src/containers/style/RendererViewer.js index 6553625..b28787b 100644 --- a/src/containers/style/RendererViewer.js +++ b/src/containers/style/RendererViewer.js @@ -7,6 +7,8 @@ const mapStateToProps = (state, ownProps) => ({ rendererIndex: ownProps.index, qrcode: state.qrcode, params: fillEmptyWith(state.paramValue[ownProps.index].slice(), 0), + title: state.title, + icon: state.icon, selected: state.selectedIndex === ownProps.index, }) diff --git a/src/reducers/index.js b/src/reducers/index.js index 417abf0..30fba13 100644 --- a/src/reducers/index.js +++ b/src/reducers/index.js @@ -13,6 +13,8 @@ const initialState = { history: [], downloadData: [], qrcode: encodeData({text: QRBTF_URL, correctLevel: 0}), + icon: { enabled: 0, src: '', scale: 0.33 }, + title: { enabled: 0, text: '', color: 'black', size: 20, align: 'middle'}, paramInfo: new Array(16).fill(new Array(16)), paramValue: new Array(16).fill(new Array(16)) } @@ -65,6 +67,16 @@ export default function appReducer(state = initialState, action) { downloadData: action.data }); } + case actionTypes.CHANGE_TITLE: { + return Object.assign({}, state, { + title: Object.assign({}, state.title, action.title) + }); + } + case actionTypes.CHANGE_ICON: { + return Object.assign({}, state, { + icon: Object.assign({}, state.icon, action.icon) + }); + } default: return state } }