Files
invitation-maker/css/style.css

899 lines
16 KiB
CSS
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
html, body {
height: 100%;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', sans-serif;
background: #f5f5f5;
overflow: hidden;
-webkit-user-select: none;
user-select: none;
}
.app {
display: flex;
flex-direction: column;
height: 100vh;
}
/* 顶部工具栏 */
.toolbar {
display: flex;
justify-content: center;
align-items: center;
gap: 4px;
padding: 10px 12px;
background: #fff;
border-bottom: 1px solid #e0e0e0;
flex-shrink: 0;
}
.btn {
min-width: 56px;
height: 32px;
padding: 0 8px;
font-size: 13px;
border: 1px solid #ddd;
border-radius: 6px;
background: #fff;
color: #333;
cursor: pointer;
transition: all 0.2s;
white-space: nowrap;
display: flex;
align-items: center;
justify-content: center;
}
.btn:active {
background: #f0f0f0;
}
.btn-primary {
min-width: 80px;
background: #4a90e2;
color: #fff;
border-color: #4a90e2;
}
.btn-primary:active {
background: #3a7bc8;
}
/* 工具栏垂直分隔线 */
.toolbar-divider-v {
width: 1px;
height: 18px;
background: #e0e0e0;
margin: 0 1px;
}
/* 工具栏图标按钮 */
.toolbar-btn-icon {
width: 24px;
height: 24px;
font-size: 12px;
border: 1px solid #ddd;
border-radius: 4px;
background: #fff;
color: #555;
cursor: pointer;
transition: all 0.2s;
display: flex;
align-items: center;
justify-content: center;
padding: 0;
}
.toolbar-btn-icon:hover {
background: #f5f5f5;
border-color: #ccc;
}
.toolbar-btn-icon:active {
background: #e8e8e8;
}
.toolbar-btn-icon:disabled {
opacity: 0.3;
cursor: not-allowed;
background: #f5f5f5;
}
/* 撤销重做按钮组 */
.toolbar-action-group {
display: flex;
gap: 2px;
margin: 0 1px;
}
/* 左侧分隔线(文本按钮后) */
.toolbar-divider-v.divider-left {
margin-left: 2px;
margin-right: 0;
}
/* 右侧分隔线(保存按钮前) */
.toolbar-divider-v.divider-right {
margin-left: 0;
margin-right: 4px;
}
/* 撤销重做按钮组 */
.toolbar-action-group {
display: flex;
gap: 3px;
margin: 0;
}
/* 保存/预览按钮 */
.btn-primary {
min-width: 80px;
height: 36px;
padding: 0 14px;
font-size: 14px;
}
/* 文本输入框删除按钮 */
.text-input .text-delete-btn {
position: absolute;
top: -10px;
right: -10px;
width: 20px;
height: 20px;
background: #e74c3c;
color: #fff;
border: none;
border-radius: 50%;
font-size: 12px;
line-height: 20px;
text-align: center;
cursor: pointer;
display: none;
z-index: 10;
}
.text-input.selected:not(.editing) .text-delete-btn {
display: block;
}
/* 编辑器工具栏(文本/图片共用) */
.editor-toolbar {
position: absolute;
top: 52px;
left: 0;
right: 0;
display: flex;
justify-content: center;
align-items: center;
padding: 8px 12px;
background: #fff;
border-bottom: 1px solid #e0e0e0;
flex-shrink: 0;
visibility: hidden;
opacity: 0;
transition: opacity 0.2s;
z-index: 100;
}
/* 编辑模式:粘在视口顶部始终可见 */
.editor-toolbar.editing-mode {
position: fixed;
top: 0;
border-bottom: 1px solid #e0e0e0;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
z-index: 10000;
}
/* 移动端:允许横向滚动 */
@media (max-width: 768px) {
.editor-toolbar {
justify-content: flex-start;
overflow-x: auto;
-webkit-overflow-scrolling: touch;
scrollbar-width: none;
padding: 8px;
}
.editor-toolbar::-webkit-scrollbar {
display: none;
}
.toolbar-group {
gap: 2px;
flex-shrink: 0;
width: 100%;
justify-content: center;
}
.toolbar-btn {
width: 32px;
height: 32px;
font-size: 14px;
}
.toolbar-label {
font-size: 12px;
}
.toolbar-label span:first-child {
display: inline;
}
.roller-picker {
min-width: 50px;
height: 32px;
padding: 2px 4px;
}
}
.editor-toolbar.active {
visibility: visible;
opacity: 1;
}
.toolbar-group {
display: none;
justify-content: center;
align-items: center;
gap: 2px;
width: 100%;
}
.toolbar-group.active {
display: flex;
}
.toolbar-btn {
width: 36px;
height: 36px;
font-size: 16px;
font-weight: bold;
border: 1px solid #ddd;
border-radius: 6px;
background: #fff;
color: #333;
cursor: pointer;
transition: all 0.2s;
}
.toolbar-btn:active {
background: #f0f0f0;
}
.toolbar-btn.active {
background: #4a90e2;
color: #fff;
border-color: #4a90e2;
}
.toolbar-btn.italic {
font-style: italic;
}
/* 镜像按钮样式 */
.toolbar-btn.mirror-btn {
width: 30px;
height: 30px;
font-size: 16px;
}
.toolbar-divider {
width: 1px;
height: 24px;
background: #ddd;
margin: 0 1px;
}
.toolbar-label {
display: flex;
align-items: center;
gap: 2px;
font-size: 12px;
color: #666;
}
.toolbar-label select {
padding: 4px 6px;
font-size: 12px;
border: 1px solid #ddd;
border-radius: 4px;
background: #fff;
cursor: pointer;
}
.opacity-slider {
width: 100px;
height: 32px;
cursor: pointer;
accent-color: #4a90e2;
margin: 0;
}
.scale-slider {
width: 100px;
height: 32px;
cursor: pointer;
accent-color: #4a90e2;
margin: 0;
}
.rotate-slider {
width: 100px;
height: 32px;
cursor: pointer;
accent-color: #4a90e2;
margin: 0;
}
/* 旋转度数显示固定宽度 */
#rotateValue {
display: inline-block;
min-width: 40px;
text-align: center;
}
/* 百分比显示固定宽度 */
#opacityValue, #bgScaleValue, #bgOpacityValue {
display: inline-block;
min-width: 40px;
text-align: center;
}
/* 字号滚轮选择器 */
.roller-picker {
display: flex;
align-items: center;
gap: 4px;
padding: 4px 8px;
background: #fff;
border: 1px solid #ddd;
border-radius: 6px;
min-width: 65px;
height: 36px;
}
.roller-arrow {
font-size: 10px;
color: #666;
cursor: pointer;
padding: 2px 4px;
user-select: none;
transition: color 0.2s;
}
.roller-arrow:hover {
color: #4a90e2;
}
.roller-value {
font-size: 14px;
min-width: 24px;
text-align: center;
color: #333;
}
#fontPicker {
min-width: 55px;
}
.toolbar-label input[type="color"] {
width: 36px;
height: 36px;
padding: 2px;
border: 1px solid #ddd;
border-radius: 6px;
cursor: pointer;
}
/* 图片展示区 */
.canvas-area {
flex: 1;
display: flex;
align-items: center;
justify-content: center;
padding: 16px;
overflow: auto;
position: relative;
}
/* 空提示 - 移到预览白板中 */
.empty-tip {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
color: #999;
font-size: 14px;
text-align: center;
pointer-events: none;
z-index: 5;
}
/* 预览区域固定 3:5 比例,打开即显示空白面板 */
.preview {
overflow: hidden;
}
.image-container {
display: flex;
position: relative;
width: 100%;
max-width: 360px;
aspect-ratio: 960 / 1361;
box-shadow: 0 4px 20px rgba(0,0,0,0.15);
background: #fff;
overflow: hidden;
touch-action: pan-x;
margin: 0 auto;
contain: layout style paint;
}
.image-container.empty {
background: #f0f0f0;
border: 2px dashed #ddd;
}
/* 背景图层 - 用于滑动调整位置,溢出隐藏 */
.preview-bg-layer {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
overflow: hidden;
}
/* 层叠图层 - 位于背景图之上、文字之下、提示文字之上 */
.overlay-layer {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
pointer-events: none;
z-index: 6;
}
.overlay-layer .overlay-image {
position: absolute;
pointer-events: auto;
cursor: move;
touch-action: none;
}
.overlay-layer .overlay-image.selected {
outline: 2px dashed rgba(74, 144, 226, 0.8);
outline-offset: 2px;
}
.overlay-layer .overlay-image .resize-handle {
display: none;
}
.overlay-layer .overlay-image.selected .resize-handle {
display: block;
}
.overlay-layer .overlay-image .delete-btn {
position: absolute;
top: -10px;
right: -10px;
width: 20px;
height: 20px;
background: #e74c3c;
color: #fff;
border: none;
border-radius: 50%;
font-size: 12px;
line-height: 20px;
text-align: center;
cursor: pointer;
display: none;
z-index: 10;
}
.overlay-layer .overlay-image.selected .delete-btn {
display: block;
}
/* 输入框图层 - 与背景图层隔离 */
.preview-input-layer {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
pointer-events: none;
z-index: 7;
}
/* 输入框可交互 */
.preview-input-layer .text-input {
pointer-events: auto;
z-index: 8;
}
/* 背景图 - 保持比例,可滑动调整位置 */
#bgImage {
display: block;
position: absolute;
max-width: none;
-webkit-user-drag: none;
}
#bgImage[src=""] {
display: none;
}
/* 文字输入框 - 透明无边框设计,黑色微软雅黑16px */
.text-input {
position: absolute;
min-width: 80px;
min-height: 32px;
padding: 0;
font-size: 16px;
color: #000;
font-family: -apple-system, BlinkMacSystemFont, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Noto Sans CJK SC", sans-serif;
background: transparent;
outline: 2px solid transparent;
border-radius: 4px;
cursor: grab;
white-space: nowrap;
line-height: 1.4;
-webkit-user-select: none;
user-select: none;
transition: outline-color 0.2s;
z-index: 10;
overflow: visible;
max-width: none;
box-sizing: border-box;
font-weight: bold;
}
/* 选中状态(单击/长按) - 仅显示虚线轮廓 */
.text-input.selected {
outline: 2px dashed rgba(74, 144, 226, 0.6);
cursor: grab;
}
/* 锁定状态 */
.text-input.locked {
cursor: default !important;
}
.text-input.locked.selected {
outline: 2px dashed rgba(255, 193, 7, 0.8);
}
.text-input.locked .text-delete-btn {
display: none !important;
}
/* 空输入框显示 placeholder */
.text-input.show-placeholder::before {
content: attr(data-placeholder);
color: #999;
pointer-events: none;
}
/* 编辑状态(双击) - 显示实线轮廓 */
.text-input.editing {
outline: 2px solid #4a90e2;
background: rgba(255,255,255,0.1);
cursor: text;
-webkit-user-select: text;
user-select: text;
-webkit-touch-callout: default;
pointer-events: auto;
}
/* 拖拽状态 */
.text-input.dragging {
opacity: 0.8;
cursor: grabbing;
}
/* 隐藏元素 */
.hidden {
display: none !important;
}
/* 隐藏空提示 */
.empty-tip.hidden {
display: none;
}
/* 右键菜单 */
.context-menu {
position: fixed;
background: #fff;
border: 1px solid #ddd;
border-radius: 6px;
box-shadow: 0 4px 12px rgba(0,0,0,0.15);
padding: 4px 0;
z-index: 1000;
min-width: 140px;
}
.context-menu-item {
padding: 10px 16px;
font-size: 14px;
color: #333;
cursor: pointer;
transition: background 0.2s;
}
.context-menu-item:hover {
background: #f5f5f5;
}
.context-menu-item:active {
background: #e8e8e8;
}
/* 拖拽辅助线 */
.guide-line {
position: absolute;
pointer-events: none;
z-index: 1000;
display: none;
}
.guide-horizontal {
left: 0;
right: 0;
height: 1px;
background: #e74c3c;
box-shadow: 0 0 4px rgba(231, 76, 60, 0.5);
}
.guide-vertical {
top: 0;
bottom: 0;
width: 1px;
background: #e74c3c;
box-shadow: 0 0 4px rgba(231, 76, 60, 0.5);
}
.guide-line.visible {
display: block;
}
/* 1px 网格线 */
.grid-lines {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
pointer-events: none;
z-index: 5;
display: none;
background-image:
linear-gradient(to right, rgba(0, 0, 0, 0.05) 1px, transparent 1px),
linear-gradient(to bottom, rgba(0, 0, 0, 0.05) 1px, transparent 1px);
background-size: 10px 10px;
}
.grid-lines.visible {
display: block;
}
/* ==================== 图层面板样式 ==================== */
.layers-panel {
position: fixed;
top: 60px;
right: -280px;
width: 260px;
height: calc(100vh - 80px);
background: #fff;
border-left: 1px solid #e0e0e0;
box-shadow: -2px 0 10px rgba(0,0,0,0.1);
z-index: 200;
display: flex;
flex-direction: column;
transition: right 0.3s ease;
}
.layers-panel.active {
right: 0;
}
.layers-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 12px 16px;
border-bottom: 1px solid #e0e0e0;
background: #f8f8f8;
}
.layers-title {
font-size: 14px;
font-weight: 600;
color: #333;
}
.layers-close {
width: 24px;
height: 24px;
border: none;
background: transparent;
font-size: 18px;
color: #666;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
border-radius: 4px;
transition: all 0.2s;
}
.layers-close:hover {
background: #e0e0e0;
color: #333;
}
.layers-list {
flex: 1;
overflow-y: auto;
padding: 8px;
}
.layer-item {
display: flex;
align-items: center;
padding: 10px 12px;
margin-bottom: 4px;
background: #f5f5f5;
border-radius: 6px;
cursor: pointer;
transition: all 0.2s;
border: 2px solid transparent;
}
.layer-item:hover {
background: #e8e8e8;
}
.layer-item.selected {
background: #e3f2fd;
border-color: #4a90e2;
}
.layer-item.hidden {
opacity: 0.5;
display: flex !important;
}
.layer-icon {
width: 24px;
height: 24px;
display: flex;
align-items: center;
justify-content: center;
margin-right: 10px;
font-size: 14px;
}
.layer-info {
flex: 1;
min-width: 0;
}
.layer-name {
font-size: 13px;
color: #333;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.layer-type {
font-size: 11px;
color: #999;
margin-top: 2px;
}
.layer-visibility {
width: 24px;
height: 24px;
display: flex;
align-items: center;
justify-content: center;
font-size: 14px;
font-weight: bold;
cursor: pointer;
padding: 4px;
border-radius: 4px;
transition: all 0.2s;
background: #4CAF50;
color: white;
border: 2px solid transparent;
}
.layer-visibility.is-hidden {
background: #f44336;
color: white;
}
.layer-visibility:hover {
opacity: 0.8;
transform: scale(1.1);
}
.layer-visibility:active {
transform: scale(0.95);
}
.layers-actions {
display: flex;
align-items: center;
justify-content: center;
gap: 4px;
padding: 12px;
border-top: 1px solid #e0e0e0;
background: #f8f8f8;
flex-wrap: wrap;
}
.layers-btn {
width: 32px;
height: 32px;
border: 1px solid #ddd;
background: #fff;
border-radius: 4px;
cursor: pointer;
font-size: 14px;
display: flex;
align-items: center;
justify-content: center;
transition: all 0.2s;
}
.layers-btn:hover {
background: #f0f0f0;
border-color: #ccc;
}
.layers-btn:disabled {
opacity: 0.3;
cursor: not-allowed;
}
.layers-btn-danger:hover {
background: #ffebee;
border-color: #ef5350;
}
.layers-divider {
width: 1px;
height: 24px;
background: #ddd;
margin: 0 4px;
}
/* 图层隐藏状态(用于画布上的元素) */
.layer-hidden {
visibility: hidden !important;
pointer-events: none !important;
}
/* 移动端适配 */
@media (max-width: 768px) {
.layers-panel {
width: 240px;
right: -260px;
top: 50px;
height: calc(100vh - 50px);
}
.layers-actions {
padding: 8px;
}
.layers-btn {
width: 28px;
height: 28px;
font-size: 12px;
}
}