diff --git a/public/index.html b/public/index.html index 6ddf9fd8..95c0a285 100644 --- a/public/index.html +++ b/public/index.html @@ -16,6 +16,7 @@ + diff --git a/public/js/aligning_guidelines.js b/public/js/aligning_guidelines.js new file mode 100644 index 00000000..b21c56ce --- /dev/null +++ b/public/js/aligning_guidelines.js @@ -0,0 +1,230 @@ +/** + * Should objects be aligned by a bounding box? + * [Bug] Scaled objects sometimes can not be aligned by edges + * + */ +var ctx,canvasAligning +function initAligningGuidelines(canvas,bor) { + ctx = canvas.getSelectionContext() + canvasAligning = canvas + setCanvasAligning(bor) +} +var aligningLineOffset = 5, + aligningLineMargin = 4, + aligningLineWidth = 1, + aligningLineColor = 'rgb(178, 204, 255)', + viewportTransform, + zoom = 1; + +function drawVerticalLine(coords) { + drawLine( + coords.x + 0.5, + coords.y1 > coords.y2 ? coords.y2 : coords.y1, + coords.x + 0.5, + coords.y2 > coords.y1 ? coords.y2 : coords.y1); +} + +function drawHorizontalLine(coords) { + drawLine( + coords.x1 > coords.x2 ? coords.x2 : coords.x1, + coords.y + 0.5, + coords.x2 > coords.x1 ? coords.x2 : coords.x1, + coords.y + 0.5); +} + +function drawLine(x1, y1, x2, y2) { + ctx.save(); + ctx.lineWidth = aligningLineWidth; + ctx.strokeStyle = aligningLineColor; + ctx.beginPath(); + ctx.moveTo(x1 * zoom + viewportTransform[4], y1 * zoom + viewportTransform[5]); + ctx.lineTo(x2 * zoom + viewportTransform[4], y2 * zoom + viewportTransform[5]); + ctx.stroke(); + ctx.restore(); +} + +function isInRange(value1, value2) { + value1 = Math.round(value1); + value2 = Math.round(value2); + for (var i = value1 - aligningLineMargin, len = value1 + aligningLineMargin; i <= len; i++) { + if (i === value2) { + return true; + } + } + return false; +} + +var verticalLines = [], + horizontalLines = []; + stateAligning = false +let mouseDown = (e) => { + if(e.target){ + stateAligning = true + }else{ + stateAligning = false + } + viewportTransform = canvasAligning.viewportTransform; + zoom = canvasAligning.getZoom(); +} +let objectMoving = (e) => { + var activeObject = e.target, + canvasAligningObjects = canvasAligning.getObjects(), + activeObjectCenter = activeObject.getCenterPoint(), + activeObjectLeft = activeObjectCenter.x, + activeObjectTop = activeObjectCenter.y, + activeObjectBoundingRect = activeObject.getBoundingRect(), + activeObjectHeight = activeObjectBoundingRect.height / viewportTransform[3], + activeObjectWidth = activeObjectBoundingRect.width / viewportTransform[0], + horizontalInTheRange = false, + verticalInTheRange = false, + transform = canvasAligning._currentTransform; + + if (!transform) return; + + // It should be trivial to DRY this up by encapsulating (repeating) creation of x1, x2, y1, and y2 into functions, + // but we're not doing it here for perf. reasons -- as this a function that's invoked on every mouse move + + for (var i = canvasAligningObjects.length; i--;) { + + if (canvasAligningObjects[i] === activeObject) continue; + + var objectCenter = canvasAligningObjects[i].getCenterPoint(), + objectLeft = objectCenter.x, + objectTop = objectCenter.y, + objectBoundingRect = canvasAligningObjects[i].getBoundingRect(), + objectHeight = objectBoundingRect.height / viewportTransform[3], + objectWidth = objectBoundingRect.width / viewportTransform[0]; + + // snap by the horizontal center line + if (isInRange(objectLeft, activeObjectLeft)) { + verticalInTheRange = true; + verticalLines.push({ + x: objectLeft, + y1: (objectTop < activeObjectTop) + ? (objectTop - objectHeight / 2 - aligningLineOffset) + : (objectTop + objectHeight / 2 + aligningLineOffset), + y2: (activeObjectTop > objectTop) + ? (activeObjectTop + activeObjectHeight / 2 + aligningLineOffset) + : (activeObjectTop - activeObjectHeight / 2 - aligningLineOffset) + }); + activeObject.setPositionByOrigin(new fabric.Point(objectLeft, activeObjectTop), 'center', 'center'); + } + + // snap by the left edge + if (isInRange(objectLeft - objectWidth / 2, activeObjectLeft - activeObjectWidth / 2)) { + verticalInTheRange = true; + verticalLines.push({ + x: objectLeft - objectWidth / 2, + y1: (objectTop < activeObjectTop) + ? (objectTop - objectHeight / 2 - aligningLineOffset) + : (objectTop + objectHeight / 2 + aligningLineOffset), + y2: (activeObjectTop > objectTop) + ? (activeObjectTop + activeObjectHeight / 2 + aligningLineOffset) + : (activeObjectTop - activeObjectHeight / 2 - aligningLineOffset) + }); + activeObject.setPositionByOrigin(new fabric.Point(objectLeft - objectWidth / 2 + activeObjectWidth / 2, activeObjectTop), 'center', 'center'); + } + + // snap by the right edge + if (isInRange(objectLeft + objectWidth / 2, activeObjectLeft + activeObjectWidth / 2)) { + verticalInTheRange = true; + verticalLines.push({ + x: objectLeft + objectWidth / 2, + y1: (objectTop < activeObjectTop) + ? (objectTop - objectHeight / 2 - aligningLineOffset) + : (objectTop + objectHeight / 2 + aligningLineOffset), + y2: (activeObjectTop > objectTop) + ? (activeObjectTop + activeObjectHeight / 2 + aligningLineOffset) + : (activeObjectTop - activeObjectHeight / 2 - aligningLineOffset) + }); + activeObject.setPositionByOrigin(new fabric.Point(objectLeft + objectWidth / 2 - activeObjectWidth / 2, activeObjectTop), 'center', 'center'); + } + + // snap by the vertical center line + if (isInRange(objectTop, activeObjectTop)) { + horizontalInTheRange = true; + horizontalLines.push({ + y: objectTop, + x1: (objectLeft < activeObjectLeft) + ? (objectLeft - objectWidth / 2 - aligningLineOffset) + : (objectLeft + objectWidth / 2 + aligningLineOffset), + x2: (activeObjectLeft > objectLeft) + ? (activeObjectLeft + activeObjectWidth / 2 + aligningLineOffset) + : (activeObjectLeft - activeObjectWidth / 2 - aligningLineOffset) + }); + activeObject.setPositionByOrigin(new fabric.Point(activeObjectLeft, objectTop), 'center', 'center'); + } + + // snap by the top edge + if (isInRange(objectTop - objectHeight / 2, activeObjectTop - activeObjectHeight / 2)) { + horizontalInTheRange = true; + horizontalLines.push({ + y: objectTop - objectHeight / 2, + x1: (objectLeft < activeObjectLeft) + ? (objectLeft - objectWidth / 2 - aligningLineOffset) + : (objectLeft + objectWidth / 2 + aligningLineOffset), + x2: (activeObjectLeft > objectLeft) + ? (activeObjectLeft + activeObjectWidth / 2 + aligningLineOffset) + : (activeObjectLeft - activeObjectWidth / 2 - aligningLineOffset) + }); + activeObject.setPositionByOrigin(new fabric.Point(activeObjectLeft, objectTop - objectHeight / 2 + activeObjectHeight / 2), 'center', 'center'); + } + + // snap by the bottom edge + if (isInRange(objectTop + objectHeight / 2, activeObjectTop + activeObjectHeight / 2)) { + horizontalInTheRange = true; + horizontalLines.push({ + y: objectTop + objectHeight / 2, + x1: (objectLeft < activeObjectLeft) + ? (objectLeft - objectWidth / 2 - aligningLineOffset) + : (objectLeft + objectWidth / 2 + aligningLineOffset), + x2: (activeObjectLeft > objectLeft) + ? (activeObjectLeft + activeObjectWidth / 2 + aligningLineOffset) + : (activeObjectLeft - activeObjectWidth / 2 - aligningLineOffset) + }); + activeObject.setPositionByOrigin(new fabric.Point(activeObjectLeft, objectTop + objectHeight / 2 - activeObjectHeight / 2), 'center', 'center'); + } + } + + if (!horizontalInTheRange) { + horizontalLines.length = 0; + } + + if (!verticalInTheRange) { + verticalLines.length = 0; + } +} +let beforeRender = ()=>{ + if(stateAligning){ + canvasAligning.clearContext(canvasAligning.contextTop); + } +} +let afterRender = ()=>{ + for (var i = verticalLines.length; i--;) { + drawVerticalLine(verticalLines[i]); + } + for (var i = horizontalLines.length; i--;) { + drawHorizontalLine(horizontalLines[i]); + } + + verticalLines.length = horizontalLines.length = 0; +} +let mouseUp = ()=>{ + verticalLines.length = horizontalLines.length = 0; + canvasAligning.renderAll(); +} +let setCanvasAligning = (bor)=>{ + if(bor){ + canvasAligning.on('mouse:down', mouseDown); + canvasAligning.on('object:moving', objectMoving); + canvasAligning.on('before:render', beforeRender); + canvasAligning.on('after:render', afterRender); + canvasAligning.on('mouse:up', mouseUp); + }else{ + canvasAligning.off('mouse:down', mouseDown); + canvasAligning.off('object:moving', objectMoving); + canvasAligning.off('before:render', beforeRender); + canvasAligning.off('after:render', afterRender); + canvasAligning.off('mouse:up', mouseUp); + } +} diff --git a/src/assets/style/style.css b/src/assets/style/style.css index 9cbedd1b..252a13d1 100644 --- a/src/assets/style/style.css +++ b/src/assets/style/style.css @@ -1139,21 +1139,27 @@ i { width: 100%; height: 100%; } -.collection_modal_body .input_box, -.design_detail_modal_component .input_box, -.library_page .input_box { +.collection_modal_body .input_border, +.design_detail_modal_component .input_border, +.library_page .input_border { display: flex; align-items: center; position: sticky; - top: 0; - background: #fff; padding-top: calc(2.5rem*1.2); padding-bottom: calc(2rem*1.2); - z-index: 2; + background: #fff; + top: 0; } -.collection_modal_body .input_box input, -.design_detail_modal_component .input_box input, -.library_page .input_box input { +.collection_modal_body .input_border .input_box, +.design_detail_modal_component .input_border .input_box, +.library_page .input_border .input_box { + position: relative; + z-index: 2; + flex: 1; +} +.collection_modal_body .input_border input, +.design_detail_modal_component .input_border input, +.library_page .input_border input { border-radius: calc(0.5rem*1.2); width: 70%; border: 1px solid rgba(0, 0, 0, 0.15); @@ -1162,47 +1168,48 @@ i { font-size: calc(1.6rem*1.2); font-weight: 400; } -.collection_modal_body .input_box inputinput:-moz-placeholder, -.design_detail_modal_component .input_box inputinput:-moz-placeholder, -.library_page .input_box inputinput:-moz-placeholder { +.collection_modal_body .input_border inputinput:-moz-placeholder, +.design_detail_modal_component .input_border inputinput:-moz-placeholder, +.library_page .input_border inputinput:-moz-placeholder { color: rgba(0, 0, 0, 0.15); } -.collection_modal_body .input_box inputinput:-ms-input-placeholder, -.design_detail_modal_component .input_box inputinput:-ms-input-placeholder, -.library_page .input_box inputinput:-ms-input-placeholder { +.collection_modal_body .input_border inputinput:-ms-input-placeholder, +.design_detail_modal_component .input_border inputinput:-ms-input-placeholder, +.library_page .input_border inputinput:-ms-input-placeholder { color: rgba(0, 0, 0, 0.15); } -.collection_modal_body .input_box inputinput::-webkit-input-placeholder, -.design_detail_modal_component .input_box inputinput::-webkit-input-placeholder, -.library_page .input_box inputinput::-webkit-input-placeholder { +.collection_modal_body .input_border inputinput::-webkit-input-placeholder, +.design_detail_modal_component .input_border inputinput::-webkit-input-placeholder, +.library_page .input_border inputinput::-webkit-input-placeholder { color: rgba(0, 0, 0, 0.15); } -.collection_modal_body .input_box span, -.design_detail_modal_component .input_box span, -.library_page .input_box span { +.collection_modal_body .input_border span, +.design_detail_modal_component .input_border span, +.library_page .input_border span { position: absolute; - bottom: calc(0rem*1.2); + bottom: -1.5rem; + left: 0; font-size: calc(1.2rem*1.2); color: red; opacity: 0; transform: scale(0.7); transform-origin: left bottom; } -.collection_modal_body .input_box.active input, -.design_detail_modal_component .input_box.active input, -.library_page .input_box.active input { +.collection_modal_body .input_border.active input, +.design_detail_modal_component .input_border.active input, +.library_page .input_border.active input { border: 1px solid #ff0001; box-shadow: 0px 0px 3px 1px rgba(255, 0, 0, 0.2); } -.collection_modal_body .input_box.active span, -.design_detail_modal_component .input_box.active span, -.library_page .input_box.active span { +.collection_modal_body .input_border.active span, +.design_detail_modal_component .input_border.active span, +.library_page .input_border.active span { opacity: 1; } -.collection_modal_body .input_box .generage_btn, -.design_detail_modal_component .input_box .generage_btn, -.library_page .input_box .generage_btn { - margin: 0 auto; +.collection_modal_body .input_border .generage_btn, +.design_detail_modal_component .input_border .generage_btn, +.library_page .input_border .generage_btn { + margin-left: 2rem; } .collection_modal_body .upload_item, .design_detail_modal_component .upload_item, diff --git a/src/assets/style/style.less b/src/assets/style/style.less index 24226b8c..1a3edfdf 100644 --- a/src/assets/style/style.less +++ b/src/assets/style/style.less @@ -1247,15 +1247,19 @@ i{ //设计input和上传按钮样式 .collection_modal_body,.design_detail_modal_component,.library_page{ - .input_box{ + .input_border{ display: flex; align-items: center; position: sticky; - top: 0; - background: #fff; padding-top: calc(2.5rem*1.2); padding-bottom: calc(2rem*1.2); - z-index: 2; + background: #fff; + top: 0; + .input_box{ + position: relative; + z-index: 2; + flex: 1; + } input{ border-radius: calc(.5rem*1.2); width: 70%; @@ -1278,7 +1282,9 @@ i{ } span{ position: absolute; - bottom: calc(0rem*1.2); + // bottom: calc(0rem*1.2); + bottom: -1.5rem; + left: 0; font-size: calc(1.2rem*1.2); color: red; opacity: 0; @@ -1296,7 +1302,8 @@ i{ } } .generage_btn{ - margin: 0 auto; + // margin: 0 auto; + margin-left: 2rem; } diff --git a/src/component/HomePage/ExportModel.vue b/src/component/HomePage/ExportModel.vue index 4f12e0a2..da32f819 100644 --- a/src/component/HomePage/ExportModel.vue +++ b/src/component/HomePage/ExportModel.vue @@ -49,6 +49,7 @@ >
Entirety Moodboard
+
Printboard
Moodboard
Color
Sketch
@@ -130,7 +131,7 @@ -