mirror of
https://github.com/xiaoqidun/ofdgo.git
synced 2026-10-30 01:27:26 +08:00
This commit is contained in:
1 parent
cabe631b97
commit
4487fbd55a
3 files changed
+115
-47
No files matched your search
@@ -2222,6 +2222,29 @@ button.outline-link:hover {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media (min-width: 901px) and (max-width: 1600px) and (pointer: fine) {
|
||||||
|
.editor-group {
|
||||||
|
padding-inline: 5px;
|
||||||
|
column-gap: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.editor-toolbar .button {
|
||||||
|
padding-inline: 7px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.editor-group:has(#textFont) {
|
||||||
|
grid-template-columns: 144px 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.editor-paragraph {
|
||||||
|
grid-template-columns: 54px 108px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toolbar {
|
||||||
|
--tool-gap: 6px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@media (max-width: 900px) {
|
@media (max-width: 900px) {
|
||||||
:root {
|
:root {
|
||||||
--sidebar-width: min(78vw, 292px);
|
--sidebar-width: min(78vw, 292px);
|
||||||
|
|||||||
+47
-23
@@ -1642,22 +1642,34 @@ function shapeStyle() {
|
|||||||
lineWidth: Number(el.shapeWidth.value) * 25.4 / 72 };
|
lineWidth: Number(el.shapeWidth.value) * 25.4 / 72 };
|
||||||
}
|
}
|
||||||
|
|
||||||
async function changeShapeStyle() {
|
function selectedPath(item) {
|
||||||
const item = canvasEditor.selected;
|
if (!item?.items) return item?.type === "PathObject" ? item : null;
|
||||||
|
if (!item.items.every(member => member.type === "PathObject")) return null;
|
||||||
|
const path = { ...item, type: "PathObject", shape: item.items.every(member => lineShape(member.shape)) ? "line" : "" };
|
||||||
|
for (const key of ["fill", "stroke", "fillColor", "strokeColor", "lineWidth"]) {
|
||||||
|
const value = item.items[0][key];
|
||||||
|
path[key] = item.items.every(member => member[key] === value) ? value : undefined;
|
||||||
|
}
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function changeShapeStyle({ target }) {
|
||||||
|
const item = selectedPath(canvasEditor.selected);
|
||||||
if (!state.editing || document.body.hasAttribute("aria-busy")) {
|
if (!state.editing || document.body.hasAttribute("aria-busy")) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!el.shapeWidth.checkValidity() || Number(el.shapeWidth.value) <= 0) {
|
if (canvasEditor.selected && (!item || !canEditObject(item, "update"))) return;
|
||||||
el.shapeWidth.value = String(item?.type === "PathObject" ? displayPoints(item.lineWidth) : 1);
|
if (target === el.shapeWidth && (!el.shapeWidth.checkValidity() || Number(el.shapeWidth.value) <= 0)) {
|
||||||
|
el.shapeWidth.value = item ? item.lineWidth === undefined ? "" : String(displayPoints(item.lineWidth)) : "1";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!el.shapeFill.checked && !el.shapeStroke.checked) {
|
if (item) {
|
||||||
el.shapeStroke.checked = true;
|
const values = [el.shapeFill, el.shapeFillColor, el.shapeStroke, el.shapeStrokeColor, el.shapeWidth].map(input => {
|
||||||
}
|
if (input !== target) return null;
|
||||||
const style = shapeStyle();
|
if (input === el.shapeFill || input === el.shapeStroke) return input.checked;
|
||||||
if (item?.type === "PathObject") {
|
return input === el.shapeWidth ? inputMillimeters(input, item.lineWidth) : input.value;
|
||||||
await changeDocument("ofdgoUpdatePathStyle", item, style.fill, style.fillColor, style.stroke, style.strokeColor,
|
});
|
||||||
inputMillimeters(el.shapeWidth, item.lineWidth));
|
await changeDocument("ofdgoUpdatePathStyle", { ...item, id: (item.items || [item]).map(member => member.id) }, ...values);
|
||||||
updateObjectControls(canvasEditor.selected, true);
|
updateObjectControls(canvasEditor.selected, true);
|
||||||
} else {
|
} else {
|
||||||
el.shapeWidth.value = String(Number(el.shapeWidth.value));
|
el.shapeWidth.value = String(Number(el.shapeWidth.value));
|
||||||
@@ -1676,11 +1688,14 @@ function toggleDrawingTool(tool) {
|
|||||||
|
|
||||||
function updateDrawingControls() {
|
function updateDrawingControls() {
|
||||||
const tool = canvasEditor.tool;
|
const tool = canvasEditor.tool;
|
||||||
|
const path = selectedPath(canvasEditor.selected);
|
||||||
el.insertTextButton.setAttribute("aria-pressed", String(tool === "text"));
|
el.insertTextButton.setAttribute("aria-pressed", String(tool === "text"));
|
||||||
const line = lineShape(tool) || !tool && lineShape(canvasEditor.selected?.shape);
|
const line = lineShape(tool) || !tool && lineShape(path?.shape);
|
||||||
if (line) {
|
if (line) {
|
||||||
el.shapeFill.checked = false;
|
el.shapeFill.checked = false;
|
||||||
el.shapeStroke.checked = true;
|
el.shapeStroke.checked = true;
|
||||||
|
} else if (!path && !el.shapeFill.checked && !el.shapeStroke.checked) {
|
||||||
|
el.shapeStroke.checked = true;
|
||||||
}
|
}
|
||||||
const disabled = !state.editing || !state.ready || state.exporting;
|
const disabled = !state.editing || !state.ready || state.exporting;
|
||||||
el.arrowTool.disabled = disabled || !pageCan("insert");
|
el.arrowTool.disabled = disabled || !pageCan("insert");
|
||||||
@@ -1691,11 +1706,10 @@ function updateDrawingControls() {
|
|||||||
el.eraseButton.disabled = el.eraseMode.disabled = disabled;
|
el.eraseButton.disabled = el.eraseMode.disabled = disabled;
|
||||||
el.eraseButton.setAttribute("aria-pressed", String(tool.startsWith("erase-")));
|
el.eraseButton.setAttribute("aria-pressed", String(tool.startsWith("erase-")));
|
||||||
el.selectObjectButton.setAttribute("aria-pressed", String(canvasEditor.enabled && !tool));
|
el.selectObjectButton.setAttribute("aria-pressed", String(canvasEditor.enabled && !tool));
|
||||||
const styleDisabled = disabled || (canvasEditor.selected?.type === "PathObject"
|
const styleDisabled = disabled || (canvasEditor.selected ? !path || !canEditObject(path, "update") : !pageCan("insert"));
|
||||||
? !canEditObject(canvasEditor.selected, "update") : !pageCan("insert"));
|
|
||||||
el.shapeFill.disabled = el.shapeStroke.disabled = styleDisabled || line;
|
el.shapeFill.disabled = el.shapeStroke.disabled = styleDisabled || line;
|
||||||
el.shapeFillColor.disabled = styleDisabled || line || !el.shapeFill.checked;
|
el.shapeFillColor.disabled = styleDisabled || line || !el.shapeFill.checked && !el.shapeFill.indeterminate;
|
||||||
el.shapeStrokeColor.disabled = el.shapeWidth.disabled = styleDisabled || !line && !el.shapeStroke.checked;
|
el.shapeStrokeColor.disabled = el.shapeWidth.disabled = styleDisabled || !line && !el.shapeStroke.checked && !el.shapeStroke.indeterminate;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function changeDocument(name, item, ...args) {
|
async function changeDocument(name, item, ...args) {
|
||||||
@@ -5220,14 +5234,24 @@ function updateObjectControls(item, reset = false) {
|
|||||||
if (reset || el.textColor.disabled || document.activeElement !== el.textColor) {
|
if (reset || el.textColor.disabled || document.activeElement !== el.textColor) {
|
||||||
el.textColor.value = text.color || "#000000";
|
el.textColor.value = text.color || "#000000";
|
||||||
}
|
}
|
||||||
if (item?.type === "PathObject" && canEditObject(item, "update")) {
|
const path = selectedPath(item);
|
||||||
el.shapeFill.checked = item.fill;
|
for (const [input, key] of [[el.shapeFill, "fill"], [el.shapeStroke, "stroke"]]) {
|
||||||
el.shapeStroke.checked = item.stroke;
|
input.indeterminate = Boolean(path?.items && path[key] === undefined);
|
||||||
el.shapeFillColor.value = item.fillColor;
|
if (path) input.checked = Boolean(path[key]);
|
||||||
el.shapeStrokeColor.value = item.strokeColor;
|
|
||||||
if (reset || document.activeElement !== el.shapeWidth) {
|
|
||||||
el.shapeWidth.value = displayPoints(item.lineWidth);
|
|
||||||
}
|
}
|
||||||
|
for (const [input, key, label] of [[el.shapeFillColor, "fillColor", "填充颜色"], [el.shapeStrokeColor, "strokeColor", "描边颜色"]]) {
|
||||||
|
const mixed = Boolean(path?.items && path[key] === undefined);
|
||||||
|
input.classList.toggle("mixed-color", mixed);
|
||||||
|
input.title = mixed ? `${label}:混合` : label;
|
||||||
|
if (path && (reset || document.activeElement !== input)) input.value = path[key] || "#000000";
|
||||||
|
}
|
||||||
|
el.shapeWidth.placeholder = path?.items && path.lineWidth === undefined ? "混合" : "";
|
||||||
|
if (path && canEditObject(path, "update")) {
|
||||||
|
if (reset || document.activeElement !== el.shapeWidth) {
|
||||||
|
el.shapeWidth.value = path.lineWidth === undefined ? "" : displayPoints(path.lineWidth);
|
||||||
|
}
|
||||||
|
} else if (!item && !el.shapeWidth.value) {
|
||||||
|
el.shapeWidth.value = "1";
|
||||||
}
|
}
|
||||||
updateDrawingControls();
|
updateDrawingControls();
|
||||||
const members = item?.items || (item ? [item] : []);
|
const members = item?.items || (item ? [item] : []);
|
||||||
|
|||||||
+45
-24
@@ -1556,33 +1556,58 @@ func editorPathScale(object ofdgo.PathObject) float64 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// setPathStyle 应用图形填充、描边和线宽
|
// setPathStyle 应用图形填充、描边和线宽
|
||||||
// 入参: object 路径对象, args 填充开关及色值、描边开关及色值、线宽
|
// 入参: object 路径对象, args 填充开关及色值、描边开关及色值、线宽,null保持原值
|
||||||
// 返回: error 错误信息
|
// 返回: error 错误信息
|
||||||
func setPathStyle(object *ofdgo.PathObject, args []js.Value) error {
|
func setPathStyle(object *ofdgo.PathObject, args []js.Value) error {
|
||||||
fill, stroke, width := args[0].Bool(), args[2].Bool(), args[4].Float()
|
fill, stroke := object.Fill != nil && *object.Fill, object.Stroke == nil || *object.Stroke
|
||||||
if kind, _ := object.Shape(); kind == ofdgo.ShapeLine {
|
if !args[0].IsNull() {
|
||||||
|
fill = args[0].Bool()
|
||||||
|
}
|
||||||
|
if !args[2].IsNull() {
|
||||||
|
stroke = args[2].Bool()
|
||||||
|
}
|
||||||
|
if kind, _ := object.Shape(); kind == ofdgo.ShapeLine || kind == ofdgo.ShapeArrow || kind == ofdgo.ShapeDoubleArrow {
|
||||||
fill, stroke = false, true
|
fill, stroke = false, true
|
||||||
}
|
}
|
||||||
if !fill && !stroke {
|
if !fill && !stroke {
|
||||||
|
if args[0].IsNull() || args[2].IsNull() {
|
||||||
|
stroke = true
|
||||||
|
} else {
|
||||||
return fmt.Errorf("fill or stroke must be enabled")
|
return fmt.Errorf("fill or stroke must be enabled")
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if !args[0].IsNull() || fill != (object.Fill != nil && *object.Fill) {
|
||||||
|
object.Fill = &fill
|
||||||
|
}
|
||||||
|
if !args[2].IsNull() || stroke != (object.Stroke == nil || *object.Stroke) {
|
||||||
|
object.Stroke = &stroke
|
||||||
|
}
|
||||||
|
if !args[4].IsNull() {
|
||||||
|
width := args[4].Float()
|
||||||
if width <= 0 || math.IsNaN(width) || math.IsInf(width, 0) {
|
if width <= 0 || math.IsNaN(width) || math.IsInf(width, 0) {
|
||||||
return fmt.Errorf("line width must be positive and finite")
|
return fmt.Errorf("line width must be positive and finite")
|
||||||
}
|
}
|
||||||
object.Fill, object.Stroke = &fill, &stroke
|
|
||||||
if scale := editorPathScale(*object); width != object.LineWidth*scale {
|
if scale := editorPathScale(*object); width != object.LineWidth*scale {
|
||||||
object.LineWidth = width / scale
|
object.LineWidth = width / scale
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if !args[1].IsNull() {
|
||||||
if object.FillColor == nil {
|
if object.FillColor == nil {
|
||||||
object.FillColor = &ofdgo.FillColor{}
|
object.FillColor = &ofdgo.FillColor{}
|
||||||
}
|
}
|
||||||
if object.StrokeColor == nil {
|
|
||||||
object.StrokeColor = &ofdgo.StrokeColor{}
|
|
||||||
}
|
|
||||||
if err := setEditorColor(object.FillColor, args[1].String()); err != nil {
|
if err := setEditorColor(object.FillColor, args[1].String()); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return setEditorColor((*ofdgo.FillColor)(object.StrokeColor), args[3].String())
|
}
|
||||||
|
if !args[3].IsNull() {
|
||||||
|
if object.StrokeColor == nil {
|
||||||
|
object.StrokeColor = &ofdgo.StrokeColor{}
|
||||||
|
}
|
||||||
|
if err := setEditorColor((*ofdgo.FillColor)(object.StrokeColor), args[3].String()); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// insertShape 创建标准路径图形
|
// insertShape 创建标准路径图形
|
||||||
@@ -1605,32 +1630,28 @@ func insertShape(args []js.Value) (any, error) {
|
|||||||
return previewEditor(currentEditor, currentSession.Renderer.RenderAnnotations)
|
return previewEditor(currentEditor, currentSession.Renderer.RenderAnnotations)
|
||||||
}
|
}
|
||||||
|
|
||||||
// updatePathStyle 更新选中路径的绘制样式
|
// updatePathStyle 原子更新选中路径的绘制样式,保留未修改属性
|
||||||
// 入参: args 页码、对象标识和绘制样式
|
// 入参: args 页码、对象标识列表和绘制样式
|
||||||
// 返回: any 文档信息, error 错误信息
|
// 返回: any 文档信息, error 错误信息
|
||||||
func updatePathStyle(args []js.Value) (any, error) {
|
func updatePathStyle(args []js.Value) (any, error) {
|
||||||
if currentEditor == nil {
|
return changeObjects(func() error {
|
||||||
return nil, fmt.Errorf("no document is being edited")
|
page, ids := args[0].Int(), stringsFromJS(args[1])
|
||||||
}
|
objects := make([]ofdgo.GraphicObject, len(ids))
|
||||||
page, id := args[0].Int(), args[1].String()
|
for i, id := range ids {
|
||||||
object, err := currentEditor.Object(page, id)
|
object, err := currentEditor.Object(page, id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
if object.Type != "PathObject" {
|
if object.Type != "PathObject" {
|
||||||
return nil, fmt.Errorf("object is not a path")
|
return fmt.Errorf("object is not a path")
|
||||||
}
|
}
|
||||||
if err := setPathStyle(&object.PathObject, args[2:]); err != nil {
|
if err := setPathStyle(&object.PathObject, args[2:]); err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
revision := currentEditor.Revision()
|
objects[i] = object
|
||||||
if err := currentEditor.UpdateObject(page, id, object); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
}
|
||||||
if currentEditor.Revision() == revision {
|
return currentEditor.UpdateObjects(page, objects)
|
||||||
return editorSummary(), nil
|
})
|
||||||
}
|
|
||||||
return previewEditor(currentEditor, currentSession.Renderer.RenderAnnotations)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// insertText 使用选定字体创建文字对象
|
// insertText 使用选定字体创建文字对象
|
||||||
|
|||||||
Reference in new issue
Block a user