Developer Kit · Examples
Custom Drawing parte 1: dibujar sobre una imagen
Custom Drawing parte 1: dibujar sobre una imagen
Dibujar sobre una imagen
En el siguiente caso de uso te mostramos una guía paso a paso de cómo construir una herramienta con la que puedes subir imágenes, dibujar sobre ellas y volver a guardarlas. Y todo esto de forma muy sencilla en Ninox.
Widgets necesarios
- Custom Drawing
- Custom Upload
- Custom Layout
- Custom Grid
- Icon
- Button
- Image
Procedimiento
Para usar Custom Drawing correctamente en el caso de uso "dibujar sobre una imagen", debes tener en cuenta algunos pasos en tu base de datos de Ninox.
<li data-preset-tag="h3">### Crear tablas
</li> <img src="https://framerusercontent.com/images/FXs6EGkJav8ct28r4gXntUaYOk.png" alt="" loading="lazy" />
- Proyectos </p><ul><li data-preset-tag="p">Defectos (subtabla)
- Documentos (subtabla)
Shapes (subtabla)
</li></ul></li></ul></li></ul><li data-preset-tag="h3">### Crear campos en Shapes
</li> <img src="https://framerusercontent.com/images/2SOGhZq195OiG9yGhAgx6Fs3B0.png" alt="" loading="lazy" />
A continuación debes crear los siguientes campos en la subtabla Shapes. Ten en cuenta que los campos deben llamarse exactamente como se indica aquí.
helper_shapeDataValue- Nombre:
helper_shapeDataValue - Tipo: Texto
- Trigger tras cambio: ninguno
- Asignación: por registro en el servidor
data_shapeData- Nombre:
data_shapeData - Tipo: Función
- Código:
let current := this; let backgroundShape := first(Dokumente.Shapes[helper_shapeDataValue != null and parseJSON(helper_shapeDataValue).type = "image"]); let parsedShapeData := parseJSON(helper_shapeDataValue); setItem(parsedShapeData, "x", parsedShapeData.x); setItem(parsedShapeData, "y", parsedShapeData.y); parsedShapeData; let isBackgroundShape := backgroundShape = Nr; { dataTableId: tableId(this), dataFieldId: fieldId(this, "shapeDataValue"), sortId: if isBackgroundShape then 0 else number(Nr) end, isBackgroundShape: isBackgroundShape, movable: first(Dokumente.Shapes[helper_shapeDataValue != null and parseJSON(helper_shapeDataValue).type = "image"]) != Nr, x: if backgroundShape = true then 0 else number(parseJSON(helper_shapeDataValue).x) end, y: if backgroundShape = true then 0 else number(parseJSON(helper_shapeDataValue).y) end, width: parsedShapeData.width, height: parsedShapeData.height, type: parsedShapeData.type }helper_disable- Nombre:
helper_disable - Tipo: Sí / No
- Trigger tras cambio: ninguno
- Asignación: por registro en el servidor
<li data-preset-tag="h3">### Crear campos en Documentos
</li> <img src="https://framerusercontent.com/images/onylekPc8iehfVgr8vQ1JIQLOHo.png" alt="" loading="lazy" />
Dateiname- Nombre:
Dateiname - Tipo: Texto
- Trigger tras cambio: ninguno
- Asignación: por registro en el servidor
helper_base64- Nombre:
helper_base64 - Tipo: Texto
- Trigger tras cambio: ninguno
- Asignación: por registro en el servidor
helper_width- Nombre:
helper_width - Tipo: Número
- Trigger tras cambio: ninguno
- Asignación: por registro en el servidor
helper_height- Nombre:
helper_height - Tipo: Número
- Trigger tras cambio: ninguno
- Asignación: por registro en el servidor
trigger_addBackgroundImage_browser- Nombre:
trigger_addBackgroundImage_browser - Tipo: Texto
- Asignación: por registro en el servidor
- Trigger tras cambio:
let current := this; helper_base64 := trigger_addBackgroundImage_browser; let shapeImage := text({ type: "image", href: trigger_addBackgroundImage_browser, width: round(current.helper_width), height: round(current.helper_height), x: 0, y: 0 }); if cnt(Shapes[data_shapeData.isBackgroundImage]) = 0 then let newShape := (create Shapes); newShape.( Dokumente := current; helper_shapeDataValue := shapeImage ) end; 'Mängel'.(helper_selectedImageDrawing := number(current.Nr)); trigger_addBackgroundImage_browser := nulltrigger_addBackgroundImage_app- Nombre:
trigger_addBackgroundImage_app - Tipo: Texto
- Asignación: por registro en memoria (navegador)
- Trigger tras cambio:
let current := this; helper_base64 := trigger_addBackgroundImage_app; let shapeImage := text({ type: "image", href: trigger_addBackgroundImage_app, width: round(current.helper_width), height: round(current.helper_height), x: 0, y: 0 }); if cnt(Shapes[data_shapeData.isBackgroundImage]) = 0 then let newShape := (create Shapes); newShape.( Dokumente := current; helper_shapeDataValue := shapeImage ) end; trigger_addBackgroundImage_app := null; 'Mängel'.(helper_selectedImageDrawing := number(current.Nr))trigger_deleteImage- Nombre:
trigger_deleteImage - Tipo: Sí / No
- Asignación: por registro en memoria (navegador)
- Trigger tras cambio:
let current := this; 'Mängel'.(helper_selectedImageDrawing := first(current.'Mängel'.Dokumente[Nr != current.Nr])); delete this<li data-preset-tag="h3">### Crear campos en Defectos
</li> <img src="https://framerusercontent.com/images/0kPkYLUsef3L1wZIgaUzecnA8I.png" alt="" loading="lazy" />
Crea aquí una pestaña extra "Helper". Es útil porque en la primera pestaña se muestra tu widget Custom Drawing y no deberían verse campos de Ninox innecesarios. En la pestaña "Helper" crea ahora los siguientes campos:
helper_selectedImageDrawing- Nombre:
helper_selectedImageDrawing - Tipo: Número
- Trigger tras cambio: ninguno
- Asignación: por registro en memoria (navegador)
helper_showLayer- Nombre:
helper_showLayer - Tipo: Sí / No
- Trigger tras cambio: ninguno
- Asignación: por registro en memoria (navegador)
helper_currentColor- Nombre:
helper_currentColor - Tipo: Texto
- Trigger tras cambio: ninguno
- Asignación: por registro en memoria (navegador)
helper_strokeWidth- Nombre:
helper_strokeWidth - Tipo: Número
- Trigger tras cambio: ninguno
- Asignación: por registro en memoria (navegador)
trigger_undoLastShape- Nombre:
trigger_undoLastShape - Tipo: Texto
- Asignación: por registro en memoria (navegador)
- Trigger tras cambio:
let recordSelectedImageDrawing := record(Dokumente,number(helper_selectedImageDrawing)); if trigger_undoLastShape != null then let lastEdited := last(recordSelectedImageDrawing.Shapes order by 'Erstellt am'); if trigger_undoLastShape = "undo" then last(recordSelectedImageDrawing.Shapes[helper_disable != true and data_shapeData.isBackgroundShape != true] order by 'Erstellt am').(helper_disable := true) else if trigger_undoLastShape = "redo" then lastEdited.(helper_disable := if lastEdited.helper_disable = true then null else true end) end end; trigger_undoLastShape := null end<li data-preset-tag="h3">### Insertar widgets en Defectos
</li> En la tabla Defectos inserta ahora el siguiente código de aplicación. Este incluye los widgets descritos arriba.
let current := this; let fontColor := "#7a83a2"; let recordSelectedImageDrawing := record(Dokumente,helper_selectedImageDrawing); let colors := ["#FF5733", "#33FF57", "#3357FF", "#FF33A6", "#FFC300", "#DAF7A6", "#900C3F", "#581845", "#C70039", "#FFC0CB"]; let colorSet := arcCustomGrid({ uniqueId: "colorGrid", width: "100%", height: "auto", columns: "auto-fill", columnWidth: "38px", gap: "5px", paddingY: "20px", paddingX: "0", blocks: for item in colors do { width: "38px", height: "38px", alignX: "center", alignY: "center", backgroundColor: item, styles: html(--- border-radius: 50%; border: 4px solid { if helper_currentColor = item then }#575b79{ else }#272A40{ end }; ---), value: "", clickAction: { type: "update", recordId: current.Nr, field: fieldId(current.Nr, "helper_currentColor"), value: item } } end }); let strokeSizes := [5, 10, 15, 20, 25, 30]; let strokeSet := arcCustomLayout({ uniqueId: "colorGrid", width: "100%", height: "45px", direction: "horizontal", gap: "5px", alignX: "between", alignY: "center", paddingY: "0", paddingX: "0", blocks: for item in strokeSizes do { width: "fraction", height: "100%", alignX: "center", alignY: "center", backgroundColor: "", styles: html(--- align-items:center; justify-content:center; border-bottom:3px solid { if item = helper_strokeWidth then }{ if current.helper_currentColor then }{ current.helper_currentColor }{ else }#575b79{ end }{ else }#181C2B{ end }; { if item != 30 then }border-right:1px solid #262b40;{ else }{ end } ---), value: html(--- <div style="width:{ item }px; height:{ item }px;background-color:{ if current.helper_currentColor then }{ current.helper_currentColor }{ else }#fff{ end };border-radius:50%;"></div> ---), clickAction: { type: "update", recordId: current.Nr, field: fieldId(current.Nr, "helper_strokeWidth"), value: item } } end }); let imageGrid := arcCustomGrid({ uniqueId: "imageGrid " + Nr, embedded: true, width: "100%", height: "100%", columns: "auto-fill", columnWidth: "50px", gap: "10px", paddingY: "0", paddingX: "0", blocks: let images := Dokumente.[{ blockId: "", width: "100%", height: "100px", alignX: "center", alignY: "center", paddingY: "", paddingX: "", backgroundColor: "", lineHeight: "", styles: "", value: arcCustomImage({ uniqueId: "image mangel " + Nr, title: Dateiname, width: "100%", height: "100%", backgroundSize: "cover", backgroundColor: "", style: "", radius: "5px", borderColor: "", link: helper_base64 }), clickAction: { type: "update", recordId: current.Nr, field: fieldId(current.Nr, "helper_selectedImageDrawing"), value: number(Nr) } }]; let new := [{ blockId: "", width: "100%", height: "100px", alignX: "center", alignY: "center", paddingY: "", paddingX: "", backgroundColor: "#272a40", lineHeight: "", styles: "", value: arcCustomUpload({ uniqueId: "multi image upload in drawing " + current.Nr, capture: true, multiupload: true, embedded: true, container: { icon: "", label: "Bilder Upload", height: "100%", width: "100%", value: arcCustomIcon({ name: "plus", color: "#fff" }) }, filename: { tableId: tableId("Dokumente"), fieldId: fieldId("Dokumente", "Dateiname") }, image: { tableId: tableId("Dokumente"), fieldId: if ninoxApp() = "web" then fieldId("Dokumente", "trigger_addBackgroundImage_browser") else fieldId("Dokumente", "trigger_addBackgroundImage_app") end, width: 2000, height: 1000, widthFieldId: fieldId("Dokumente", "helper_width"), heightFieldId: fieldId("Dokumente", "helper_height") }, changeFieldValues: [{ fieldId: fieldId("Dokumente", "Mängel"), value: number(current.Nr) }] }) }]; array(images, new) }); let drawingSticker := [{ uid: "red_sticker", image: "data:image/svg+xml;base64,PHN2ZyB4bWxucz0naHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmcnIHZpZXdCb3g9JzAgMCA3MiA3Mic+PHBhdGggZmlsbD0nI0VBNUE0NycgZD0nTTM1Ljk3MiA5LjcyYy02LjQyMiAwLTExLjY0NiA1LjIyNC0xMS42NDYgMTEuNjQ2UzI5LjU1IDMzLjAxIDM1Ljk3MiAzMy4wMWM2LjQyMSAwIDExLjY0Ni01LjIyNCAxMS42NDYtMTEuNjQ1UzQyLjM5MyA5LjcyIDM1Ljk3MiA5LjcyJy8+PHBhdGggZmlsbD0nI0QyMkYyNycgZD0nTTM5LjE2OSAzMi4zODJjMS43MjYtLjY0NiAzLjI4OS0uODE3IDQuODE0LTIuMjEyIDIuMTAyLTEuOTIzIDMuOTA0LTUuMzQgMy45MDQtOC4wMjQgMC0yLjQ0NS0uNTc4LTUuMzAzLTIuMzQyLTcuNjMzLTEuNjI4LTIuMTUtNC4zNjEtMy44NDItNi4zNzYtNC41NTQgMCAwIDMuNTE3IDUuNjUgMy41MTcgMTEuMzczcy0zLjUxNyAxMS4wNS0zLjUxNyAxMS4wNScvPjxwYXRoIGZpbGw9JyNEMENGQ0UnIGQ9J20zNS44MzcgNjMuNDg5IDIuODQ3LTcuNjdzLS44MjUtMTkuNTc3LS4zOC0xOS42NzhoLTUuMTY4Yy40NDYuMS0uMjI1IDE5LjU1OS0uMjI1IDE5LjU1OXonLz48cGF0aCBmaWxsPScjOUI5QjlBJyBkPSdtMzUuOTU2IDYyLjczOCAyLjY0OS03LjA3OHMuMTA0LTE5LjA1Ny4wNjItMTkuNTI2bC0yLjkzMy4wMDd6Jy8+PGcgZmlsbD0nbm9uZScgc3Ryb2tlPScjMDAwJyBzdHJva2UtbGluZWNhcD0ncm91bmQnIHN0cm9rZS1saW5lam9pbj0ncm91bmQnIHN0cm9rZS1taXRlcmxpbWl0PScxMCc+PGNpcmNsZSBjeD0nMzUuOTcxJyBjeT0nMjEuMzY2JyByPScxMS44MDgnIHN0cm9rZS13aWR0aD0nMicvPjxwYXRoIGQ9J00zOC41MiAzNy4wOTh2MTguNjE2bC0yLjU4NCA4LjUwNS0zLjAxNS04LjUwNVYzNy4wOTgnLz48L2c+PC9zdmc+Cg==", icon: "data:image/svg+xml;base64,PHN2ZyB4bWxucz0naHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmcnIHZpZXdCb3g9JzAgMCA3MiA3Mic+PHBhdGggZmlsbD0nI0VBNUE0NycgZD0nTTM1Ljk3MiA5LjcyYy02LjQyMiAwLTExLjY0NiA1LjIyNC0xMS42NDYgMTEuNjQ2UzI5LjU1IDMzLjAxIDM1Ljk3MiAzMy4wMWM2LjQyMSAwIDExLjY0Ni01LjIyNCAxMS42NDYtMTEuNjQ1UzQyLjM5MyA5LjcyIDM1Ljk3MiA5LjcyJy8+PHBhdGggZmlsbD0nI0QyMkYyNycgZD0nTTM5LjE2OSAzMi4zODJjMS43MjYtLjY0NiAzLjI4OS0uODE3IDQuODE0LTIuMjEyIDIuMTAyLTEuOTIzIDMuOTA0LTUuMzQgMy45MDQtOC4wMjQgMC0yLjQ0NS0uNTc4LTUuMzAzLTIuMzQyLTcuNjMzLTEuNjI4LTIuMTUtNC4zNjEtMy44NDItNi4zNzYtNC41NTQgMCAwIDMuNTE3IDUuNjUgMy41MTcgMTEuMzczcy0zLjUxNyAxMS4wNS0zLjUxNyAxMS4wNScvPjxwYXRoIGZpbGw9JyNEMENGQ0UnIGQ9J20zNS44MzcgNjMuNDg5IDIuODQ3LTcuNjdzLS44MjUtMTkuNTc3LS4zOC0xOS42NzhoLTUuMTY4Yy40NDYuMS0uMjI1IDE5LjU1OS0uMjI1IDE5LjU1OXonLz48cGF0aCBmaWxsPScjOUI5QjlBJyBkPSdtMzUuOTU2IDYyLjczOCAyLjY0OS03LjA3OHMuMTA0LTE5LjA1Ny4wNjItMTkuNTI2bC0yLjkzMy4wMDd6Jy8+PGcgZmlsbD0nbm9uZScgc3Ryb2tlPScjMDAwJyBzdHJva2UtbGluZWNhcD0ncm91bmQnIHN0cm9rZS1saW5lam9pbj0ncm91bmQnIHN0cm9rZS1taXRlcmxpbWl0PScxMCc+PGNpcmNsZSBjeD0nMzUuOTcxJyBjeT0nMjEuMzY2JyByPScxMS44MDgnIHN0cm9rZS13aWR0aD0nMicvPjxwYXRoIGQ9J00zOC41MiAzNy4wOTh2MTguNjE2bC0yLjU4NCA4LjUwNS0zLjAxNS04LjUwNVYzNy4wOTgnLz48L2c+PC9zdmc+Cg==", label: "Red Sticker", width: 100, height: 100, originX: 0.5, originY: 0.89, default: true }, { uid: "green_sticker", image: "data:image/svg+xml;base64,PHN2ZyB4bWxucz0naHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmcnIHZpZXdCb3g9JzAgMCA3MiA3Mic+PHBhdGggZmlsbD0nIzQ2ZWI1ZCcgZD0nTTM1Ljk3MiA5LjcyYy02LjQyMiAwLTExLjY0NiA1LjIyNC0xMS42NDYgMTEuNjQ2UzI5LjU1IDMzLjAxIDM1Ljk3MiAzMy4wMWM2LjQyMSAwIDExLjY0Ni01LjIyNCAxMS42NDYtMTEuNjQ1UzQyLjM5MyA5LjcyIDM1Ljk3MiA5LjcyJy8+PHBhdGggZmlsbD0nIzI3ZDIzZScgZD0nTTM5LjE2OSAzMi4zODJjMS43MjYtLjY0NiAzLjI4OS0uODE3IDQuODE0LTIuMjEyIDIuMTAyLTEuOTIzIDMuOTA0LTUuMzQgMy45MDQtOC4wMjQgMC0yLjQ0NS0uNTc4LTUuMzAzLTIuMzQyLTcuNjMzLTEuNjI4LTIuMTUtNC4zNjEtMy44NDItNi4zNzYtNC41NTQgMCAwIDMuNTE3IDUuNjUgMy41MTcgMTEuMzczcy0zLjUxNyAxMS4wNS0zLjUxNyAxMS4wNScvPjxwYXRoIGZpbGw9JyNEMENGQ0UnIGQ9J20zNS44MzcgNjMuNDg5IDIuODQ3LTcuNjdzLS44MjUtMTkuNTc3LS4zOC0xOS42NzhoLTUuMTY4Yy40NDYuMS0uMjI1IDE5LjU1OS0uMjI1IDE5LjU1OXonLz48cGF0aCBmaWxsPScjOUI5QjlBJyBkPSdtMzUuOTU2IDYyLjczOCAyLjY0OS03LjA3OHMuMTA0LTE5LjA1Ny4wNjItMTkuNTI2bC0yLjkzMy4wMDd6Jy8+PGcgZmlsbD0nbm9uZScgc3Ryb2tlPScjMDAwJyBzdHJva2UtbGluZWNhcD0ncm91bmQnIHN0cm9rZS1saW5lam9pbj0ncm91bmQnIHN0cm9rZS1taXRlcmxpbWl0PScxMCc+PGNpcmNsZSBjeD0nMzUuOTcxJyBjeT0nMjEuMzY2JyByPScxMS44MDgnIHN0cm9rZS13aWR0aD0nMicvPjxwYXRoIGQ9J00zOC41MiAzNy4wOTh2MTguNjE2bC0yLjU4NCA4LjUwNS0zLjAxNS04LjUwNVYzNy4wOTgnLz48L2c+PC9zdmc+Cg==", icon: "data:image/svg+xml;base64,PHN2ZyB4bWxucz0naHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmcnIHZpZXdCb3g9JzAgMCA3MiA3Mic+PHBhdGggZmlsbD0nIzQ2ZWI1ZCcgZD0nTTM1Ljk3MiA5LjcyYy02LjQyMiAwLTExLjY0NiA1LjIyNC0xMS42NDYgMTEuNjQ2UzI5LjU1IDMzLjAxIDM1Ljk3MiAzMy4wMWM2LjQyMSAwIDExLjY0Ni01LjIyNCAxMS42NDYtMTEuNjQ1UzQyLjM5MyA5LjcyIDM1Ljk3MiA5LjcyJy8+PHBhdGggZmlsbD0nIzI3ZDIzZScgZD0nTTM5LjE2OSAzMi4zODJjMS43MjYtLjY0NiAzLjI4OS0uODE3IDQuODE0LTIuMjEyIDIuMTAyLTEuOTIzIDMuOTA0LTUuMzQgMy45MDQtOC4wMjQgMC0yLjQ0NS0uNTc4LTUuMzAzLTIuMzQyLTcuNjMzLTEuNjI4LTIuMTUtNC4zNjEtMy44NDItNi4zNzYtNC41NTQgMCAwIDMuNTE3IDUuNjUgMy41MTcgMTEuMzczcy0zLjUxNyAxMS4wNS0zLjUxNyAxMS4wNScvPjxwYXRoIGZpbGw9JyNEMENGQ0UnIGQ9J20zNS44MzcgNjMuNDg5IDIuODQ3LTcuNjdzLS44MjUtMTkuNTc3LS4zOC0xOS42NzhoLTUuMTY4Yy40NDYuMS0uMjI1IDE5LjU1OS0uMjI1IDE5LjU1OXonLz48cGF0aCBmaWxsPScjOUI5QjlBJyBkPSdtMzUuOTU2IDYyLjczOCAyLjY0OS03LjA3OHMuMTA0LTE5LjA1Ny4wNjItMTkuNTI2bC0yLjkzMy4wMDd6Jy8+PGcgZmlsbD0nbm9uZScgc3Ryb2tlPScjMDAwJyBzdHJva2UtbGluZWNhcD0ncm91bmQnIHN0cm9rZS1saW5lam9pbj0ncm91bmQnIHN0cm9rZS1taXRlcmxpbWl0PScxMCc+PGNpcmNsZSBjeD0nMzUuOTcxJyBjeT0nMjEuMzY2JyByPScxMS44MDgnIHN0cm9rZS13aWR0aD0nMicvPjxwYXRoIGQ9J00zOC41MiAzNy4wOTh2MTguNjE2bC0yLjU4NCA4LjUwNS0zLjAxNS04LjUwNVYzNy4wOTgnLz48L2c+PC9zdmc+Cg==", label: "Green Sticker", width: 100, height: 100, originX: 0.5, originY: 0.89 }, { uid: "red_arrow_up_right", image: "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzMiIgaGVpZ2h0PSIzMiIgZmlsbD0iI2Y1MTQxNCIgdmlld0JveD0iMCAwIDI1NiAyNTYiPjxwYXRoIGQ9Ik0yMDAsNjRWMTY4YTgsOCwwLDAsMS0xNiwwVjgzLjMxTDY5LjY2LDE5Ny42NmE4LDgsMCwwLDEtMTEuMzItMTEuMzJMMTcyLjY5LDcySDg4YTgsOCwwLDAsMSwwLTE2SDE5MkE4LDgsMCwwLDEsMjAwLDY0WiI+PC9wYXRoPjwvc3ZnPg==", icon: "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzMiIgaGVpZ2h0PSIzMiIgZmlsbD0iI2Y1MTQxNCIgdmlld0JveD0iMCAwIDI1NiAyNTYiPjxwYXRoIGQ9Ik0yMDAsNjRWMTY4YTgsOCwwLDAsMS0xNiwwVjgzLjMxTDY5LjY2LDE5Ny42NmE4LDgsMCwwLDEtMTEuMzItMTEuMzJMMTcyLjY5LDcySDg4YTgsOCwwLDAsMSwwLTE2SDE5MkE4LDgsMCwwLDEsMjAwLDY0WiI+PC9wYXRoPjwvc3ZnPg==", label: "Pfeil 1", width: 100, height: 100, originX: 0.5, originY: 0.5, default: true }, { uid: "red_arrow_down_left", image: "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzMiIgaGVpZ2h0PSIzMiIgZmlsbD0iI2Y1MTQxNCIgdmlld0JveD0iMCAwIDI1NiAyNTYiPjxwYXRoIGQ9Ik0xOTcuNjYsNjkuNjYsODMuMzEsMTg0SDE2OGE4LDgsMCwwLDEsMCwxNkg2NGE4LDgsMCwwLDEtOC04Vjg4YTgsOCwwLDAsMSwxNiwwdjg0LjY5TDE4Ni4zNCw1OC4zNGE4LDgsMCwwLDEsMTEuMzIsMTEuMzJaIj48L3BhdGg+PC9zdmc+", icon: "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzMiIgaGVpZ2h0PSIzMiIgZmlsbD0iI2Y1MTQxNCIgdmlld0JveD0iMCAwIDI1NiAyNTYiPjxwYXRoIGQ9Ik0xOTcuNjYsNjkuNjYsODMuMzEsMTg0SDE2OGE4LDgsMCwwLDEsMCwxNkg2NGE4LDgsMCwwLDEtOC04Vjg4YTgsOCwwLDAsMSwxNiwwdjg0LjY5TDE4Ni4zNCw1OC4zNGE4LDgsMCwwLDEsMTEuMzIsMTEuMzJaIj48L3BhdGg+PC9zdmc+", label: "Pfeil 2", width: 100, height: 100, originX: 0, originY: -0.0001 }]; let drawingArea := arcCustomDrawing({ uniqueId: "issue board" + Nr, embedded: true, height: "100%", tableId: tableId("Shapes"), fieldId: fieldId("Shapes", "helper_shapeDataValue"), changeFieldValues: [{ fieldId: fieldId("Shapes", "Dokumente"), value: helper_selectedImageDrawing }], exportSettings: { allowedTypes: ["jpg"], target: "field", recordId: recordSelectedImageDrawing.Nr, fieldId: fieldId(recordSelectedImageDrawing.Nr, "helper_base64") }, canvas: { width: recordSelectedImageDrawing.helper_width, height: recordSelectedImageDrawing.helper_height, offsetX: 0, offsetY: 0 }, zooming: { step: 0.25, min: 0.3, max: 4 }, drawingSettings: { strokeWidth: if helper_strokeWidth then helper_strokeWidth else 5 end, strokeColor: if helper_currentColor then helper_currentColor else "#e9595c" end }, artboard: { width: recordSelectedImageDrawing.helper_width, height: recordSelectedImageDrawing.helper_height }, stickerTypes: drawingSticker, shapes: (recordSelectedImageDrawing.Shapes[helper_disable != true] order by data_shapeData.sortId).[{ shapeId: Nr, movable: data_shapeData.movable, shapeDataValue: helper_shapeDataValue, sidebarItem: { header: "Object ID:" + Nr, content: arcCustomButton({ title: "Öffnen", actions: [{ type: "popup", recordId: Nr }] }) } }], rightSideContent: { show: true, header: arcCustomLayout({ uniqueId: "drawing right side header " + Nr, embedded: true, direction: "vertical", alignX: "left", alignY: "top", width: "100%", height: "100%", gap: "10px", backgroundColor: "", paddingY: "20px", paddingX: "20px", styles: "", scrollSettings: { scrollY: false, scrollX: false }, blocks: [{ width: "", height: "auto", lineHeight: "", alignX: "left", color: "", value: imageGrid }] }), content: { showShapeLayers: helper_showLayer, value: "" }, footer: arcCustomLayout({ uniqueId: "drawing right side footer " + Nr, embedded: true, direction: "vertical", alignX: "left", alignY: "center", width: "100%", height: "", gap: "0", backgroundColor: "", paddingY: "0", paddingX: "0", styles: "", scrollSettings: { scrollY: false, scrollX: false }, blocks: [{ width: "100%", height: "fraction", lineHeight: "", alignX: "left", color: "", styles: "border-bottom: 1px solid #262b40;", value: "" }, { width: "100%", height: "auto", lineHeight: "", alignX: "left", color: "", styles: "border-bottom: 1px solid #262b40;", value: strokeSet }, { width: "100%", height: "auto", lineHeight: "", alignX: "left", color: "", styles: "border-bottom: 1px solid #262b40;padding:8px;", value: colorSet }, { width: "100%", height: "auto", lineHeight: "", alignX: "left", color: "", styles: "padding:8px", value: arcCustomButton({ uniqueId: "undo action" + Nr, title: "Aktion rückgängig", width: "100%", height: "", alignY: "", alignX: "30px", gap: "5px", fontSize: "16px", fontColor: "#fff", backgroundColor: "#272A40", borderColor: "transparent", borderRadius: "5px", showBadge: false, badgeTitle: "", badgeColor: "", badgeBackground: "", badgeBorderColor: "", badgePosition: "", actions: let id := this; [{ type: "update", recordId: current.Nr, field: fieldId(current.Nr, "trigger_undoLastShape"), value: "undo" }] }) }, { width: "100%", height: "auto", lineHeight: "", alignX: "left", color: "", styles: "padding:8px", value: arcCustomButton({ uniqueId: "undo action" + Nr, title: "Löschen", width: "100%", height: "", alignY: "", alignX: "30px", gap: "5px", fontSize: "16px", fontColor: "#fff", backgroundColor: "#e9595c", borderColor: "transparent", borderRadius: "5px", showBadge: false, badgeTitle: "", badgeColor: "", badgeBackground: "", badgeBorderColor: "", badgePosition: "", actions: let id := this; [{ type: "update", recordId: recordSelectedImageDrawing.Nr, field: fieldId(recordSelectedImageDrawing.Nr, "trigger_deleteImage"), value: true }] }) }] }) } }); arcCustomLayout({ uniqueId: "drawing " + Nr, embedded: false, fullscreen: true, ninoxVersion: "3.13", page: false, fullscreenMode: if isAdminMode() then " else "full" end, showAdminTools: false, hideHeaderIcons: false, direction: "vertical", alignX: "left", alignY: "center", width: "100%", height: "100%", gap: "0", backgroundColor: "#181d2c", paddingY: "", paddingX: "", styles: "", scrollSettings: { scrollY: true }, blocks: [if false then { width: "", height: "100px", lineHeight: "", alignX: "left", paddingX: "", styles: "", value: arcCustomLayout({ uniqueId: "layout header " + Nr, embedded: true, direction: "horizontal", alignX: "left", alignY: "center", width: "100%", height: "100%", gap: "10px", backgroundColor: "", paddingY: "", paddingX: "", styles: "border-bottom: 1px solid #262b40;", scrollSettings: { scrollY: true }, blocks: [{ width: "fraction", height: "auto", lineHeight: "", alignX: "left", color: "", styles: "font-size:24px;color:#7a83a2;text-wrap:nowrap;padding:0 40px;", value: html(--- Title ---) }, { width: "auto", height: "auto", lineHeight: "", alignX: "right", color: "", value: arcCustomButton({ uniqueId: "Button schließen" + Nr, title: "Schließen", width: "", height: "", alignY: "", alignX: "", paddingX: "", paddingY: "", gap: "5px", icon: arcCustomIcon({ name: "x", color: fontColor }), iconPosition: "right", fontSize: "", fontColor: fontColor, backgroundColor: "transparent", borderColor: "transparent", borderRadius: "5px", actions: [{ type: "openRecord", tab: "Allgemeines", recordId: current.Nr }] }) }] }) } end, if false then { width: "100%", height: "50px", lineHeight: "", alignX: "left", color: "", backgroundColor: "#141925", styles: "border-bottom: 1px solid #262b40;border-top: 1px solid #262b40;", value: arcCustomLayout({ uniqueId: "layout action bar " + Nr, embedded: true, fullscreen: false, ninoxVersion: "", page: true, fullscreenMode: "", showAdminTools: true, hideHeaderIcons: true, direction: "horizontal", alignX: "left", alignY: "center", width: "", height: "", gap: "10px", backgroundColor: "", paddingY: "", paddingX: "", styles: "", scrollSettings: { scrollY: false, scrollX: false }, blocks: [{ width: "200px", height: "100%", lineHeight: "", alignX: "left", color: "", styles: "", value: "block 1" }, { width: "", height: "auto", lineHeight: "", alignX: "left", color: "", value: "block 2" }] }) } end, { width: "100%", height: "100%", lineHeight: "", alignX: "left", color: "", backgroundColor: "#181d2c", value: drawingArea }] })¡Tadaaaaa 🧙🏼♀️ El widget "dibujar sobre una imagen" ya debería funcionar en tu sistema.
- Nombre: