mirror of
https://github.com/zsviczian/obsidian-excalidraw-plugin.git
synced 2025-08-06 05:46:28 +00:00
force embed image to 100% scale
This commit is contained in:
@@ -53,8 +53,8 @@ Please upgrade to Obsidian v0.12.19 or higher to get the latest release.
|
||||
- Insert LaTeX formulas using the Command Palette action "Insert LaTeX formula". You can edit formulas either in Markdown view, or by <kbd>CTRL/CMD + Click</kbd> on the formula.
|
||||
- Drag & Drop support
|
||||
- You can drag files from the Obsidian file explorer and they will become links to those files in Excalidraw.
|
||||
- Dragging image files (PNG, SVG, JPG, Excalidraw) from Obsidian's file explorer while pressing the <kbd>CTRL/CMD</kbd> button will embed the image into your drawing.
|
||||
- You can drag and drop images from outside Obsidian onto Excalidraw. These images will be embedded into your drawing and saved to Obsidian.
|
||||
- Dragging image files (PNG, SVG, JPG, ICO, GIF, WEBP, Excalidraw) from Obsidian's file explorer while pressing the <kbd>CTRL</kbd> (<kbd>SHIFT</kbd> on Mac) button will embed the image into your drawing.
|
||||
- If in addition to <kbd>CTRL</kbd> or <kbd>SHIFT</kbd> you also hold down <kbd>ALT<kbd>, the image will be inserted at 100% of its size. ⚠ Note: this is a very niche feature with a very particular behavior that I built primarily for myself (even more so than other features in Excalidraw Obsidian - also built primarily for myself 😉)... This will reset your embedded image to 100% size every time you open the Excalidraw drawing, or in case you have embedded an Excalidraw drawing on your canvas inserted using this function, every time you update the embedded drawing, it will be scaled back to 100% size. This means that even if you resize the image on the drawing, it will reset to 100% the next time you open the file or you modify the original embedded object. This feature is useful when you decompose a drawing into separate Excalidraw files, but when combined onto a single canvas you want the individual pieces to maintain their actual sizes. I use this feature to construct Book-on-a-Page summaries from atomic drawings.
|
||||
- You can drag and drop text from Markdown views onto Excalidraw.
|
||||
- You can drag and drop web addresses from your browser and they will become links.
|
||||
- Image support
|
||||
|
||||
@@ -48,6 +48,7 @@ export declare type MimeType =
|
||||
export type FileData = BinaryFileData & {
|
||||
size: Size;
|
||||
hasSVGwithBitmap: boolean;
|
||||
shouldScale: boolean; //true if image should maintain its area, false if image should display at 100% its size
|
||||
};
|
||||
|
||||
export type Size = {
|
||||
@@ -182,6 +183,14 @@ export class EmbeddedFile {
|
||||
}
|
||||
return this.img; //images that are not SVGwithBitmap, only the light string is stored, since inverted and non-inverted are ===
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @returns true if image should scale such as the updated images has the same area as the previous images, false if the image should be displayed at 100%
|
||||
*/
|
||||
public shouldScale() {
|
||||
return !Boolean(this.linkParts && this.linkParts.original && this.linkParts.original.endsWith("|100%"));
|
||||
}
|
||||
}
|
||||
|
||||
export class EmbeddedFilesLoader {
|
||||
@@ -367,6 +376,7 @@ export class EmbeddedFilesLoader {
|
||||
created: data.created,
|
||||
size: data.size,
|
||||
hasSVGwithBitmap: data.hasSVGwithBitmap,
|
||||
shouldScale: embeddedFile.shouldScale()
|
||||
});
|
||||
}
|
||||
} else if (embeddedFile.isSVGwithBitmap) {
|
||||
@@ -377,6 +387,7 @@ export class EmbeddedFilesLoader {
|
||||
created: embeddedFile.mtime,
|
||||
size: embeddedFile.size,
|
||||
hasSVGwithBitmap: embeddedFile.isSVGwithBitmap,
|
||||
shouldScale: embeddedFile.shouldScale()
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -395,6 +406,7 @@ export class EmbeddedFilesLoader {
|
||||
created: data.created,
|
||||
size: data.size,
|
||||
hasSVGwithBitmap: false,
|
||||
shouldScale: true
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -894,6 +894,7 @@ export class ExcalidrawAutomate implements ExcalidrawAutomateInterface {
|
||||
topX: number,
|
||||
topY: number,
|
||||
imageFile: TFile,
|
||||
scale: boolean = true, //true will scale the image to MAX_IMAGE_SIZE, false will insert image at 100% of its size
|
||||
): Promise<string> {
|
||||
const id = nanoid();
|
||||
const loader = new EmbeddedFilesLoader(
|
||||
@@ -910,11 +911,11 @@ export class ExcalidrawAutomate implements ExcalidrawAutomateInterface {
|
||||
id: fileId,
|
||||
dataURL: image.dataURL,
|
||||
created: image.created,
|
||||
file: imageFile.path,
|
||||
file: imageFile.path + (scale ? "":"|100%"),
|
||||
hasSVGwithBitmap: image.hasSVGwithBitmap,
|
||||
latex: null,
|
||||
};
|
||||
if (Math.max(image.size.width, image.size.height) > MAX_IMAGE_SIZE) {
|
||||
if (scale && (Math.max(image.size.width, image.size.height) > MAX_IMAGE_SIZE)) {
|
||||
const scale =
|
||||
MAX_IMAGE_SIZE / Math.max(image.size.width, image.size.height);
|
||||
image.size.width = scale * image.size.width;
|
||||
|
||||
@@ -2926,6 +2926,7 @@ export default class ExcalidrawView extends TextFileView {
|
||||
currentPosition.x,
|
||||
currentPosition.y,
|
||||
draggable.file,
|
||||
!event.altKey,
|
||||
);
|
||||
ea.addElementsToView(false, false, true);
|
||||
})();
|
||||
@@ -2955,6 +2956,7 @@ export default class ExcalidrawView extends TextFileView {
|
||||
currentPosition.x + counter*50,
|
||||
currentPosition.y + counter*50,
|
||||
f,
|
||||
!event.altKey,
|
||||
);
|
||||
counter++;
|
||||
await ea.addElementsToView(false, false, true);
|
||||
|
||||
@@ -27,6 +27,7 @@ export const updateEquation = async (
|
||||
created: data.created,
|
||||
size: data.size,
|
||||
hasSVGwithBitmap: false,
|
||||
shouldScale: true,
|
||||
});
|
||||
addFiles(files, view);
|
||||
}
|
||||
|
||||
@@ -17,12 +17,23 @@ export class InsertImageDialog extends FuzzySuggestModal<TFile> {
|
||||
this.limit = 20;
|
||||
this.setInstructions([
|
||||
{
|
||||
command: t("SELECT_FILE"),
|
||||
command: t("SELECT_FILE_WITH_OPTION_TO_SCALE"),
|
||||
purpose: "",
|
||||
},
|
||||
]);
|
||||
this.setPlaceholder(t("SELECT_DRAWING"));
|
||||
this.emptyStateText = t("NO_MATCH");
|
||||
this.inputEl.onkeyup = (e) => {
|
||||
//@ts-ignore
|
||||
if (e.key === "Enter" && e.altKey && this.chooser.values) {
|
||||
this.onChooseItem(
|
||||
//@ts-ignore
|
||||
this.chooser.values[this.chooser.selectedItem].item,
|
||||
new KeyboardEvent("keypress",{altKey: true})
|
||||
);
|
||||
this.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getItems(): TFile[] {
|
||||
@@ -39,13 +50,13 @@ export class InsertImageDialog extends FuzzySuggestModal<TFile> {
|
||||
return item.path;
|
||||
}
|
||||
|
||||
onChooseItem(item: TFile): void {
|
||||
onChooseItem(item: TFile, event: KeyboardEvent): void {
|
||||
const ea = this.plugin.ea;
|
||||
ea.reset();
|
||||
ea.setView(this.view);
|
||||
ea.canvas.theme = this.view.excalidrawAPI.getAppState().theme;
|
||||
(async () => {
|
||||
await ea.addImage(0, 0, item);
|
||||
await ea.addImage(0, 0, item, !event.altKey);
|
||||
ea.addElementsToView(true, false, true);
|
||||
})();
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ export default {
|
||||
INSERT_LINK_TO_ELEMENT_ERROR: "Select a single element in the scene",
|
||||
INSERT_LINK_TO_ELEMENT_READY: "Link is READY and available on the clipboard",
|
||||
INSERT_LINK: "Insert link to file",
|
||||
INSERT_IMAGE: "Insert image from vault",
|
||||
INSERT_IMAGE: "Insert image or Excalidraw drawing from your vault",
|
||||
INSERT_MD: "Insert markdown file from vault",
|
||||
INSERT_LATEX:
|
||||
"Insert LaTeX formula (e.g. \\binom{n}{k} = \\frac{n!}{k!(n-k)!})",
|
||||
@@ -418,9 +418,10 @@ export default {
|
||||
|
||||
//openDrawings.ts
|
||||
SELECT_FILE: "Select a file then press enter.",
|
||||
SELECT_FILE_WITH_OPTION_TO_SCALE: "Select a file then press ENTER, or ALT+ENTER to insert at 100% scale.",
|
||||
NO_MATCH: "No file matches your query.",
|
||||
SELECT_FILE_TO_LINK: "Select the file you want to insert the link for.",
|
||||
SELECT_DRAWING: "Select the drawing you want to insert",
|
||||
SELECT_DRAWING: "Select the image or drawing you want to insert",
|
||||
TYPE_FILENAME: "Type name of drawing to select.",
|
||||
SELECT_FILE_OR_TYPE_NEW:
|
||||
"Select existing drawing or type name of a new drawing then press Enter.",
|
||||
|
||||
@@ -16,6 +16,7 @@ import {
|
||||
getEmbedFilename,
|
||||
} from "./utils/FileUtils";
|
||||
import {
|
||||
fragWithHTML,
|
||||
setLeftHandedMode,
|
||||
} from "./utils/Utils";
|
||||
|
||||
@@ -198,9 +199,6 @@ export const DEFAULT_SETTINGS: ExcalidrawSettings = {
|
||||
mathjaxSourceURL: "https://cdn.jsdelivr.net/npm/mathjax@3.2.1/es5/tex-svg.js"
|
||||
};
|
||||
|
||||
const fragWithHTML = (html: string) =>
|
||||
createFragment((frag) => (frag.createDiv().innerHTML = html));
|
||||
|
||||
export class ExcalidrawSettingTab extends PluginSettingTab {
|
||||
plugin: ExcalidrawPlugin;
|
||||
private requestEmbedUpdate: boolean = false;
|
||||
|
||||
@@ -383,19 +383,29 @@ export const scaleLoadedImage = (
|
||||
.filter((e: any) => e.type === "image" && e.fileId === f.id)
|
||||
.forEach((el: any) => {
|
||||
const [w_old, h_old] = [el.width, el.height];
|
||||
const elementAspectRatio = w_old / h_old;
|
||||
if (imageAspectRatio != elementAspectRatio) {
|
||||
dirty = true;
|
||||
const h_new = Math.sqrt((w_old * h_old * h_image) / w_image);
|
||||
const w_new = Math.sqrt((w_old * h_old * w_image) / h_image);
|
||||
el.height = h_new;
|
||||
el.width = w_new;
|
||||
el.y += (h_old - h_new) / 2;
|
||||
el.x += (w_old - w_new) / 2;
|
||||
if(f.shouldScale) {
|
||||
const elementAspectRatio = w_old / h_old;
|
||||
if (imageAspectRatio != elementAspectRatio) {
|
||||
dirty = true;
|
||||
const h_new = Math.sqrt((w_old * h_old * h_image) / w_image);
|
||||
const w_new = Math.sqrt((w_old * h_old * w_image) / h_image);
|
||||
el.height = h_new;
|
||||
el.width = w_new;
|
||||
el.y += (h_old - h_new) / 2;
|
||||
el.x += (w_old - w_new) / 2;
|
||||
}
|
||||
} else {
|
||||
if(w_old !== w_image || h_old !== h_image) {
|
||||
dirty = true;
|
||||
el.height = h_image;
|
||||
el.width = w_image;
|
||||
el.y += (h_old - h_image) / 2;
|
||||
el.x += (w_old - w_image) / 2;
|
||||
}
|
||||
}
|
||||
});
|
||||
return { dirty, scene };
|
||||
}
|
||||
return { dirty, scene };
|
||||
};
|
||||
|
||||
export const setDocLeftHandedMode = (isLeftHanded: boolean, ownerDocument:Document) => {
|
||||
@@ -622,6 +632,9 @@ export const getEmbeddedFilenameParts = (fname:string):{
|
||||
}
|
||||
}
|
||||
|
||||
export const fragWithHTML = (html: string) =>
|
||||
createFragment((frag) => (frag.createDiv().innerHTML = html));
|
||||
|
||||
export const errorlog = (data: {}) => {
|
||||
console.error({ plugin: "Excalidraw", ...data });
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user