mirror of
https://github.com/zsviczian/obsidian-excalidraw-plugin.git
synced 2025-08-06 05:46:28 +00:00
Compare commits
10 Commits
2.6.0-beta
...
2.6.3-beta
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7233d1e037 | ||
|
|
5972f83369 | ||
|
|
0edfd7622c | ||
|
|
8f14f97007 | ||
|
|
758585a4c2 | ||
|
|
854eafaf91 | ||
|
|
ee89b80ce1 | ||
|
|
3e6200ac7e | ||
|
|
ee9364b645 | ||
|
|
5bbe66900e |
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"id": "obsidian-excalidraw-plugin",
|
||||
"name": "Excalidraw",
|
||||
"version": "2.6.0-beta-2",
|
||||
"version": "2.6.3-beta-1",
|
||||
"minAppVersion": "1.1.6",
|
||||
"description": "An Obsidian plugin to edit and view Excalidraw drawings",
|
||||
"author": "Zsolt Viczian",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"id": "obsidian-excalidraw-plugin",
|
||||
"name": "Excalidraw",
|
||||
"version": "2.5.2",
|
||||
"version": "2.6.2",
|
||||
"minAppVersion": "1.1.6",
|
||||
"description": "An Obsidian plugin to edit and view Excalidraw drawings",
|
||||
"author": "Zsolt Viczian",
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@popperjs/core": "^2.11.8",
|
||||
"@zsviczian/excalidraw": "0.17.6-6",
|
||||
"@zsviczian/excalidraw": "0.17.6-9",
|
||||
"chroma-js": "^2.4.2",
|
||||
"clsx": "^2.0.0",
|
||||
"@zsviczian/colormaster": "^1.2.2",
|
||||
|
||||
@@ -8,6 +8,7 @@ import fs from 'fs';
|
||||
import LZString from 'lz-string';
|
||||
import postprocess from '@zsviczian/rollup-plugin-postprocess';
|
||||
import cssnano from 'cssnano';
|
||||
import jsesc from 'jsesc';
|
||||
|
||||
// Load environment variables
|
||||
import dotenv from 'dotenv';
|
||||
@@ -52,11 +53,13 @@ if (!isLib) console.log(manifest.version);
|
||||
const packageString = isLib
|
||||
? ""
|
||||
: ';' + lzstring_pkg +
|
||||
'\nlet EXCALIDRAW_PACKAGES = LZString.decompressFromBase64("' + LZString.compressToBase64(react_pkg + reactdom_pkg + excalidraw_pkg) + '");\n' +
|
||||
'let {react, reactDOM, excalidrawLib} = window.eval.call(window, `(function() {' +
|
||||
'${EXCALIDRAW_PACKAGES};' +
|
||||
'return {react: React, reactDOM: ReactDOM, excalidrawLib: ExcalidrawLib};})();`);\n' +
|
||||
'let PLUGIN_VERSION="' + manifest.version + '";';
|
||||
'\nlet REACT_PACKAGES = `' +
|
||||
jsesc(react_pkg + reactdom_pkg, { quotes: 'backtick' }) +
|
||||
'`;\n' +
|
||||
'let EXCALIDRAW_PACKAGE = ""; const unpackExcalidraw = () => {EXCALIDRAW_PACKAGE = LZString.decompressFromBase64("' + LZString.compressToBase64(excalidraw_pkg) + '");};\n' +
|
||||
'let {react, reactDOM } = window.eval.call(window, `(function() {' + '${REACT_PACKAGES};' + 'return {react: React, reactDOM: ReactDOM};})();`);\n' +
|
||||
`let excalidrawLib = {};\n` +
|
||||
'let PLUGIN_VERSION="' + manifest.version + '";';
|
||||
|
||||
const BASE_CONFIG = {
|
||||
input: 'src/main.ts',
|
||||
|
||||
@@ -1106,8 +1106,49 @@ export class EmbeddedFilesLoader {
|
||||
}
|
||||
|
||||
const getSVGData = async (app: App, file: TFile, colorMap: ColorMap | null): Promise<DataURL> => {
|
||||
const svg = replaceSVGColors(await app.vault.read(file), colorMap) as string;
|
||||
return svgToBase64(svg) as DataURL;
|
||||
const svgString = replaceSVGColors(await app.vault.read(file), colorMap) as string;
|
||||
return svgToBase64(svgString) as DataURL;
|
||||
/*
|
||||
try {
|
||||
const container = document.createElement('div');
|
||||
container.innerHTML = svgString;
|
||||
|
||||
const svgElement = container.querySelector('svg');
|
||||
|
||||
if (!svgElement) {
|
||||
throw new Error('Invalid SVG content'); // Ensure there's an SVG element
|
||||
}
|
||||
|
||||
// Check for width and height attributes
|
||||
const hasWidth = svgElement.hasAttribute('width');
|
||||
const hasHeight = svgElement.hasAttribute('height');
|
||||
|
||||
// If width or height is missing, calculate based on viewBox
|
||||
if (!hasWidth || !hasHeight) {
|
||||
const viewBox = svgElement.getAttribute('viewBox');
|
||||
|
||||
if (viewBox) {
|
||||
const [ , , viewBoxWidth, viewBoxHeight] = viewBox.split(/\s+/).map(Number);
|
||||
|
||||
// Set width and height based on viewBox if they are missing
|
||||
if (!hasWidth) {
|
||||
svgElement.setAttribute('width', `${viewBoxWidth}px`);
|
||||
}
|
||||
if (!hasHeight) {
|
||||
svgElement.setAttribute('height', `${viewBoxHeight}px`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Get the updated SVG string from outerHTML
|
||||
const updatedSVGString = svgElement.outerHTML;
|
||||
|
||||
// Convert the updated SVG string to a base64 Data URL
|
||||
return svgToBase64(updatedSVGString) as DataURL;
|
||||
} catch (error) {
|
||||
errorlog({ where: "EmbeddedFileLoader.getSVGData", error });
|
||||
return svgToBase64(svgString) as DataURL;
|
||||
}*/
|
||||
};
|
||||
|
||||
/*export const generateIdFromFile = async (file: ArrayBuffer): Promise<FileId> => {
|
||||
|
||||
@@ -2621,26 +2621,31 @@ export class ExcalidrawAutomate {
|
||||
return null;
|
||||
}
|
||||
|
||||
const size = await this.getOriginalImageSize(imgEl, true);
|
||||
if (size) {
|
||||
const originalArea = imgEl.width * imgEl.height;
|
||||
const originalAspectRatio = size.width / size.height;
|
||||
let newWidth = Math.sqrt(originalArea * originalAspectRatio);
|
||||
let newHeight = Math.sqrt(originalArea / originalAspectRatio);
|
||||
const centerX = imgEl.x + imgEl.width / 2;
|
||||
const centerY = imgEl.y + imgEl.height / 2;
|
||||
let originalArea, originalAspectRatio;
|
||||
if(imgEl.crop) {
|
||||
originalArea = imgEl.width * imgEl.height;
|
||||
originalAspectRatio = imgEl.crop.width / imgEl.crop.height;
|
||||
} else {
|
||||
const size = await this.getOriginalImageSize(imgEl, true);
|
||||
if (!size) { return false; }
|
||||
originalArea = imgEl.width * imgEl.height;
|
||||
originalAspectRatio = size.width / size.height;
|
||||
}
|
||||
let newWidth = Math.sqrt(originalArea * originalAspectRatio);
|
||||
let newHeight = Math.sqrt(originalArea / originalAspectRatio);
|
||||
const centerX = imgEl.x + imgEl.width / 2;
|
||||
const centerY = imgEl.y + imgEl.height / 2;
|
||||
|
||||
if (newWidth !== imgEl.width || newHeight !== imgEl.height) {
|
||||
if(!this.getElement(imgEl.id)) {
|
||||
this.copyViewElementsToEAforEditing([imgEl]);
|
||||
}
|
||||
const eaEl = this.getElement(imgEl.id);
|
||||
eaEl.width = newWidth;
|
||||
eaEl.height = newHeight;
|
||||
eaEl.x = centerX - newWidth / 2;
|
||||
eaEl.y = centerY - newHeight / 2;
|
||||
return true;
|
||||
if (newWidth !== imgEl.width || newHeight !== imgEl.height) {
|
||||
if(!this.getElement(imgEl.id)) {
|
||||
this.copyViewElementsToEAforEditing([imgEl]);
|
||||
}
|
||||
const eaEl = this.getElement(imgEl.id);
|
||||
eaEl.width = newWidth;
|
||||
eaEl.height = newHeight;
|
||||
eaEl.x = centerX - newWidth / 2;
|
||||
eaEl.y = centerY - newHeight / 2;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -754,7 +754,7 @@ export class ExcalidrawData {
|
||||
notice.noticeEl.oncontextmenu = () => {
|
||||
displayFontMessage(this.app);
|
||||
}
|
||||
},2000);
|
||||
},5000);
|
||||
await loadSceneFonts(this.scene.elements);
|
||||
clearTimeout(timer);
|
||||
|
||||
|
||||
@@ -1575,6 +1575,7 @@ export default class ExcalidrawView extends TextFileView implements HoverParent{
|
||||
if(!this.plugin) {
|
||||
return;
|
||||
}
|
||||
await this.plugin.awaitInit();
|
||||
//implemented to overcome issue that activeLeafChangeEventHandler is not called when view is initialized from a saved workspace, since Obsidian 1.6.0
|
||||
let counter = 0;
|
||||
while(counter++<50 && (!Boolean(this?.plugin?.activeLeafChangeEventHandler) || !Boolean(this.canvasNodeFactory))) {
|
||||
@@ -2245,6 +2246,7 @@ export default class ExcalidrawView extends TextFileView implements HoverParent{
|
||||
//I am using last loaded file to control when the view reloads.
|
||||
//It seems text file view gets the modified file event after sync before the modifyEventHandler in main.ts
|
||||
//reload can only be triggered via reload()
|
||||
await this.plugin.awaitInit();
|
||||
if(this.lastLoadedFile === this.file) return;
|
||||
this.isLoaded = false;
|
||||
if(!this.file) return;
|
||||
@@ -2275,6 +2277,7 @@ export default class ExcalidrawView extends TextFileView implements HoverParent{
|
||||
if(!this?.app) {
|
||||
return;
|
||||
}
|
||||
await this.plugin.awaitInit();
|
||||
let counter = 0;
|
||||
while ((!this.file || !this.plugin.fourthFontLoaded) && counter++<50) await sleep(50);
|
||||
if(!this.file) return;
|
||||
@@ -3982,6 +3985,11 @@ export default class ExcalidrawView extends TextFileView implements HoverParent{
|
||||
(process.env.NODE_ENV === 'development') && DEBUGGING && debug(this.onPaste, "ExcalidrawView.onPaste", data, event);
|
||||
const api = this.excalidrawAPI as ExcalidrawImperativeAPI;
|
||||
const ea = this.getHookServer();
|
||||
if(data?.elements) {
|
||||
data.elements
|
||||
.filter(el=>el.type==="text" && !el.hasOwnProperty("rawText"))
|
||||
.forEach(el=>(el as Mutable<ExcalidrawTextElement>).rawText = (el as ExcalidrawTextElement).originalText);
|
||||
};
|
||||
if(data && ea.onPasteHook) {
|
||||
const res = ea.onPasteHook({
|
||||
ea,
|
||||
@@ -5875,6 +5883,7 @@ export default class ExcalidrawView extends TextFileView implements HoverParent{
|
||||
}
|
||||
) {
|
||||
(process.env.NODE_ENV === 'development') && DEBUGGING && debug(this.instantiateExcalidraw, "ExcalidrawView.instantiateExcalidraw", initdata);
|
||||
await this.plugin.awaitInit();
|
||||
while(!this.semaphores.scriptsReady) {
|
||||
await sleep(50);
|
||||
}
|
||||
|
||||
@@ -353,7 +353,8 @@ const getIMG = async (
|
||||
);
|
||||
|
||||
const cacheReady = imageCache.isReady();
|
||||
|
||||
|
||||
await plugin.awaitInit();
|
||||
switch (plugin.settings.previewImageType) {
|
||||
case PreviewImageType.PNG: {
|
||||
const img = createEl("img");
|
||||
|
||||
@@ -82,7 +82,7 @@ export const obsidianToExcalidrawMap: { [key: string]: string } = {
|
||||
};
|
||||
|
||||
|
||||
export const {
|
||||
export let {
|
||||
sceneCoordsToViewportCoords,
|
||||
viewportCoordsToSceneCoords,
|
||||
determineFocusDistance,
|
||||
@@ -106,6 +106,32 @@ export const {
|
||||
loadSceneFonts,
|
||||
} = excalidrawLib;
|
||||
|
||||
export function updateExcalidrawLib() {
|
||||
({
|
||||
sceneCoordsToViewportCoords,
|
||||
viewportCoordsToSceneCoords,
|
||||
determineFocusDistance,
|
||||
intersectElementWithLine,
|
||||
getCommonBoundingBox,
|
||||
getMaximumGroups,
|
||||
measureText,
|
||||
getLineHeight,
|
||||
wrapText,
|
||||
getFontString,
|
||||
getBoundTextMaxWidth,
|
||||
exportToSvg,
|
||||
exportToBlob,
|
||||
mutateElement,
|
||||
restore,
|
||||
mermaidToExcalidraw,
|
||||
getFontFamilyString,
|
||||
getContainerElement,
|
||||
refreshTextDimensions,
|
||||
getCSSFontDefinition,
|
||||
loadSceneFonts,
|
||||
} = excalidrawLib);
|
||||
}
|
||||
|
||||
export const FONTS_STYLE_ID = "excalidraw-custom-fonts";
|
||||
export const CJK_STYLE_ID = "excalidraw-cjk-fonts";
|
||||
|
||||
|
||||
44
src/dialogs/ExcalidrawLoading.ts
Normal file
44
src/dialogs/ExcalidrawLoading.ts
Normal file
@@ -0,0 +1,44 @@
|
||||
import { FileView, TextFileView, View, WorkspaceLeaf } from "obsidian";
|
||||
import ExcalidrawPlugin from "src/main";
|
||||
import { setExcalidrawView } from "src/utils/ObsidianUtils";
|
||||
|
||||
export default class ExcalidrawLoading extends FileView {
|
||||
constructor(leaf: WorkspaceLeaf, private plugin: ExcalidrawPlugin) {
|
||||
super(leaf);
|
||||
this.switchToeExcalidraw();
|
||||
this.displayLoadingText();
|
||||
}
|
||||
|
||||
public onload() {
|
||||
super.onload();
|
||||
this.displayLoadingText();
|
||||
}
|
||||
|
||||
private async switchToeExcalidraw() {
|
||||
await this.plugin.awaitInit();
|
||||
setExcalidrawView(this.leaf);
|
||||
}
|
||||
|
||||
getViewType(): string {
|
||||
return "excalidra-loading";
|
||||
}
|
||||
|
||||
getDisplayText() {
|
||||
return "Loading Excalidraw... " + (this.file?.basename ?? "");
|
||||
}
|
||||
|
||||
private displayLoadingText() {
|
||||
// Create a div element for displaying the text
|
||||
const loadingTextEl = this.contentEl.createEl("div", {
|
||||
text: this.getDisplayText()
|
||||
});
|
||||
|
||||
// Apply styling to center the text
|
||||
loadingTextEl.style.display = "flex";
|
||||
loadingTextEl.style.alignItems = "center";
|
||||
loadingTextEl.style.justifyContent = "center";
|
||||
loadingTextEl.style.height = "100%";
|
||||
loadingTextEl.style.fontSize = "1.5em"; // Adjust size as needed
|
||||
}
|
||||
|
||||
}
|
||||
@@ -15,7 +15,37 @@ export const RELEASE_NOTES: { [k: string]: string } = {
|
||||
|
||||
I develop this plugin as a hobby, spending my free time doing this. If you find it valuable, then please say THANK YOU or...
|
||||
|
||||
<div class="ex-coffee-div"><a href="https://ko-fi.com/zsolt"><img src="https://cdn.ko-fi.com/cdn/kofi3.png?v=3" height=45></a></div>
|
||||
<div class="ex-coffee-div"><a href="https://ko-fi.com/zsolt"><img src="https://storage.ko-fi.com/cdn/kofi6.png?v=6" border="0" alt="Buy Me a Coffee at ko-fi.com" height=45></a></div>
|
||||
`,
|
||||
"2.6.2":`
|
||||
## Fixed
|
||||
- Image scaling issue with SVGs that miss the width and height property. [#8729](https://github.com/excalidraw/excalidraw/issues/8729)
|
||||
`,
|
||||
"2.6.1":`
|
||||
## New
|
||||
- Pen-mode single-finger panning enabled also for the "Selection" tool.
|
||||
- You can disable pen-mode single-finger panning in Plugin Settings under Excalidraw Appearance and Behavior [#2080](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/2080)
|
||||
|
||||
## Fixed
|
||||
- Text tool did not work in pen-mode using finger [#2080](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/2080)
|
||||
- Pasting images to Excalidraw from the web resulted in filenames of "image_1.png", "image_2.png" instead of "Pasted Image TIMESTAMP" [#2081](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/2081)
|
||||
`,
|
||||
"2.6.0":`
|
||||
## Performance
|
||||
- Much faster plugin initialization. Down from 1000-3000ms to 100-300ms. According to my testing speed varies on a wide spectrum depending on device, size of Vault and other plugins being loaded. I measured values ranging from 84ms up to 782ms [#2068](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/2068)
|
||||
- Faster loading of scenes with many embedded illustrations or PDF pages.
|
||||
- SVG export results in even smaller files by further optimizing which characters are included in the embedded fonts. [#8641](https://github.com/excalidraw/excalidraw/pull/8641)
|
||||
|
||||
## New
|
||||
- Image cropping tool. Double click the image to crop it. [#8613](https://github.com/excalidraw/excalidraw/pull/8613)
|
||||
- Single finger panning in pen mode.
|
||||
- Native handwritten CJK Font support [8530](https://github.com/excalidraw/excalidraw/pull/8530)
|
||||
- Created a new **Fonts** section in settings. This includes configuration of the "Local Font" and downloading of the CJK fonts in case you need them offline.
|
||||
- Option under **Appearance and Behavior / Link Click** to disable double-click link navigation in view mode. [#2075](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/2075)
|
||||
- New RU translation 🙏[@tovBender](https://github.com/tovBender)
|
||||
|
||||
## Updated
|
||||
- CN translation 🙏[@dmscode](https://github.com/dmscode)
|
||||
`,
|
||||
"2.5.2": `
|
||||
## Fixed
|
||||
|
||||
@@ -355,6 +355,7 @@ FILENAME_HEAD: "Filename",
|
||||
DEFAULT_PEN_MODE_DESC:
|
||||
"Should pen mode be automatically enabled when opening Excalidraw?",
|
||||
DISABLE_DOUBLE_TAP_ERASER_NAME: "Enable double-tap eraser in pen mode",
|
||||
DISABLE_SINGLE_FINGER_PANNING_NAME: "Enable single-finger panning in pen mode",
|
||||
SHOW_PEN_MODE_FREEDRAW_CROSSHAIR_NAME: "Show (+) crosshair in pen mode",
|
||||
SHOW_PEN_MODE_FREEDRAW_CROSSHAIR_DESC:
|
||||
"Show crosshair in pen mode when using the freedraw tool. <b><u>Toggle ON:</u></b> SHOW <b><u>Toggle OFF:</u></b> HIDE<br>"+
|
||||
|
||||
@@ -98,6 +98,8 @@ export default {
|
||||
RESET_IMG_ASPECT_RATIO: "重置所选图像元素的纵横比",
|
||||
TEMPORARY_DISABLE_AUTOSAVE: "临时禁用自动保存功能,直到本次 Obsidian 退出(小白慎用!)",
|
||||
TEMPORARY_ENABLE_AUTOSAVE: "启用自动保存功能",
|
||||
FONTS_LOADED : "Excalidraw: CJK 字体已加载" ,
|
||||
FONTS_LOAD_ERROR : "Excalidraw: 在资源文件夹下找不到 CJK 字体\n" ,
|
||||
|
||||
//ExcalidrawView.ts
|
||||
NO_SEARCH_RESULT: "在绘图中未找到匹配的元素",
|
||||
@@ -353,6 +355,7 @@ FILENAME_HEAD: "文件名",
|
||||
DEFAULT_PEN_MODE_DESC:
|
||||
"打开绘图时,是否自动开启触控笔模式?",
|
||||
DISABLE_DOUBLE_TAP_ERASER_NAME: "启用手写模式下的双击橡皮擦功能",
|
||||
DISABLE_SINGLE_FINGER_PANNING_NAME: "启用手写模式下的单指平移功能",
|
||||
SHOW_PEN_MODE_FREEDRAW_CROSSHAIR_NAME: "在触控笔模式下显示十字准星(+)",
|
||||
SHOW_PEN_MODE_FREEDRAW_CROSSHAIR_DESC:
|
||||
"在触控笔模式下使用涂鸦功能会显示十字准星 <b><u>打开:</u></b> 显示 <b><u>关闭:</u></b> 隐藏<br>"+
|
||||
@@ -432,6 +435,7 @@ FILENAME_HEAD: "文件名",
|
||||
LONG_PRESS_DESKTOP_DESC: "长按(以毫秒为单位)打开在 Markdown 文件中嵌入的 Excalidraw 绘图。",
|
||||
LONG_PRESS_MOBILE_NAME: "长按打开(移动端)",
|
||||
LONG_PRESS_MOBILE_DESC: "长按(以毫秒为单位)打开在 Markdown 文件中嵌入的 Excalidraw 绘图。",
|
||||
DOUBLE_CLICK_LINK_OPEN_VIEW_MODE: "在查看模式下允许双击打开链接",
|
||||
|
||||
FOCUS_ON_EXISTING_TAB_NAME: "聚焦于当前标签页",
|
||||
FOCUS_ON_EXISTING_TAB_DESC: "当打开一个链接时,如果该文件已经打开,Excalidraw 将会聚焦到现有的标签页上 " +
|
||||
|
||||
156
src/main.ts
156
src/main.ts
@@ -46,6 +46,7 @@ import {
|
||||
sceneCoordsToViewportCoords,
|
||||
FONTS_STYLE_ID,
|
||||
CJK_STYLE_ID,
|
||||
updateExcalidrawLib,
|
||||
} from "./constants/constants";
|
||||
import ExcalidrawView, { TextMode, getTextMode } from "./ExcalidrawView";
|
||||
import {
|
||||
@@ -142,8 +143,11 @@ import { RankMessage } from "./dialogs/RankMessage";
|
||||
import { initCompressionWorker, terminateCompressionWorker } from "./workers/compression-worker";
|
||||
import { WeakArray } from "./utils/WeakArray";
|
||||
import { getCJKDataURLs } from "./utils/CJKLoader";
|
||||
import ExcalidrawLoading from "./dialogs/ExcalidrawLoading";
|
||||
|
||||
declare let EXCALIDRAW_PACKAGES:string;
|
||||
declare let EXCALIDRAW_PACKAGE:string;
|
||||
declare let REACT_PACKAGES:string;
|
||||
declare const unpackExcalidraw: Function;
|
||||
declare let react:any;
|
||||
declare let reactDOM:any;
|
||||
declare let excalidrawLib: typeof ExcalidrawLib;
|
||||
@@ -196,6 +200,7 @@ export default class ExcalidrawPlugin extends Plugin {
|
||||
private ribbonIcon:HTMLElement;
|
||||
public loadTimestamp:number;
|
||||
private isLocalCJKFontAvailabe:boolean = undefined
|
||||
public isReady = false;
|
||||
|
||||
constructor(app: App, manifest: PluginManifest) {
|
||||
super(app, manifest);
|
||||
@@ -270,7 +275,7 @@ export default class ExcalidrawPlugin extends Plugin {
|
||||
//@ts-ignore
|
||||
const {react:r, reactDOM:rd, excalidrawLib:e} = win.eval.call(win,
|
||||
`(function() {
|
||||
${EXCALIDRAW_PACKAGES};
|
||||
${REACT_PACKAGES + EXCALIDRAW_PACKAGE};
|
||||
return {react:React,reactDOM:ReactDOM,excalidrawLib:ExcalidrawLib};
|
||||
})()`);
|
||||
this.packageMap.set(win,{react:r, reactDOM:rd, excalidrawLib:e});
|
||||
@@ -345,11 +350,18 @@ export default class ExcalidrawPlugin extends Plugin {
|
||||
}
|
||||
|
||||
async onload() {
|
||||
initCompressionWorker();
|
||||
this.loadTimestamp = Date.now();
|
||||
addIcon(ICON_NAME, EXCALIDRAW_ICON);
|
||||
addIcon(SCRIPTENGINE_ICON_NAME, SCRIPTENGINE_ICON);
|
||||
addIcon(EXPORT_IMG_ICON_NAME, EXPORT_IMG_ICON);
|
||||
this.registerView(
|
||||
VIEW_TYPE_EXCALIDRAW,
|
||||
(leaf: WorkspaceLeaf) => {
|
||||
if(this.isReady) {
|
||||
return new ExcalidrawView(leaf, this);
|
||||
} else {
|
||||
return new ExcalidrawLoading(leaf, this);
|
||||
}
|
||||
},
|
||||
);
|
||||
//Compatibility mode with .excalidraw files
|
||||
this.registerExtensions(["excalidraw"], VIEW_TYPE_EXCALIDRAW);
|
||||
|
||||
await this.loadSettings({reEnableAutosave:true});
|
||||
const updateSettings = !this.settings.onceOffCompressFlagReset || !this.settings.onceOffGPTVersionReset;
|
||||
@@ -365,68 +377,83 @@ export default class ExcalidrawPlugin extends Plugin {
|
||||
if(updateSettings) {
|
||||
await this.saveSettings();
|
||||
}
|
||||
this.excalidrawConfig = new ExcalidrawConfig(this);
|
||||
await loadMermaid();
|
||||
this.editorHandler = new EditorHandler(this);
|
||||
this.editorHandler.setup();
|
||||
|
||||
this.addSettingTab(new ExcalidrawSettingTab(this.app, this));
|
||||
this.ea = await initExcalidrawAutomate(this);
|
||||
|
||||
this.registerView(
|
||||
VIEW_TYPE_EXCALIDRAW,
|
||||
(leaf: WorkspaceLeaf) => new ExcalidrawView(leaf, this),
|
||||
);
|
||||
|
||||
//Compatibility mode with .excalidraw files
|
||||
this.registerExtensions(["excalidraw"], VIEW_TYPE_EXCALIDRAW);
|
||||
|
||||
this.addMarkdownPostProcessor();
|
||||
this.registerInstallCodeblockProcessor();
|
||||
this.addThemeObserver();
|
||||
this.experimentalFileTypeDisplayToggle(this.settings.experimentalFileType);
|
||||
this.registerCommands();
|
||||
this.registerEventListeners();
|
||||
this.runStartupScript();
|
||||
this.initializeFonts();
|
||||
this.registerEditorSuggest(new FieldSuggester(this));
|
||||
this.setPropertyTypes();
|
||||
|
||||
this.app.workspace.onLayoutReady(async () => {
|
||||
unpackExcalidraw();
|
||||
excalidrawLib = window.eval.call(window,`(function() {${EXCALIDRAW_PACKAGE};return ExcalidrawLib;})()`);
|
||||
this.packageMap.set(window,{react, reactDOM, excalidrawLib});
|
||||
updateExcalidrawLib();
|
||||
initCompressionWorker();
|
||||
this.loadTimestamp = Date.now();
|
||||
addIcon(ICON_NAME, EXCALIDRAW_ICON);
|
||||
addIcon(SCRIPTENGINE_ICON_NAME, SCRIPTENGINE_ICON);
|
||||
addIcon(EXPORT_IMG_ICON_NAME, EXPORT_IMG_ICON);
|
||||
|
||||
//inspiration taken from kanban:
|
||||
//https://github.com/mgmeyers/obsidian-kanban/blob/44118e25661bff9ebfe54f71ae33805dc88ffa53/src/main.ts#L267
|
||||
this.registerMonkeyPatches();
|
||||
this.excalidrawConfig = new ExcalidrawConfig(this);
|
||||
await loadMermaid();
|
||||
this.editorHandler = new EditorHandler(this);
|
||||
this.editorHandler.setup();
|
||||
|
||||
this.registerInstallCodeblockProcessor();
|
||||
this.addThemeObserver();
|
||||
this.experimentalFileTypeDisplayToggle(this.settings.experimentalFileType);
|
||||
this.registerCommands();
|
||||
this.registerEventListeners();
|
||||
this.runStartupScript();
|
||||
this.initializeFonts();
|
||||
this.registerEditorSuggest(new FieldSuggester(this));
|
||||
this.setPropertyTypes();
|
||||
|
||||
this.stylesManager = new StylesManager(this);
|
||||
//inspiration taken from kanban:
|
||||
//https://github.com/mgmeyers/obsidian-kanban/blob/44118e25661bff9ebfe54f71ae33805dc88ffa53/src/main.ts#L267
|
||||
this.registerMonkeyPatches();
|
||||
|
||||
// const patches = new OneOffs(this);
|
||||
if (this.settings.showReleaseNotes) {
|
||||
//I am repurposing imageElementNotice, if the value is true, this means the plugin was just newly installed to Obsidian.
|
||||
const obsidianJustInstalled = this.settings.previousRelease === "0.0.0"
|
||||
this.stylesManager = new StylesManager(this);
|
||||
|
||||
if (isVersionNewerThanOther(PLUGIN_VERSION, this.settings.previousRelease)) {
|
||||
new ReleaseNotes(
|
||||
this.app,
|
||||
this,
|
||||
obsidianJustInstalled ? null : PLUGIN_VERSION,
|
||||
).open();
|
||||
// const patches = new OneOffs(this);
|
||||
if (this.settings.showReleaseNotes) {
|
||||
//I am repurposing imageElementNotice, if the value is true, this means the plugin was just newly installed to Obsidian.
|
||||
const obsidianJustInstalled = this.settings.previousRelease === "0.0.0"
|
||||
|
||||
if (isVersionNewerThanOther(PLUGIN_VERSION, this.settings.previousRelease)) {
|
||||
new ReleaseNotes(
|
||||
this.app,
|
||||
this,
|
||||
obsidianJustInstalled ? null : PLUGIN_VERSION,
|
||||
).open();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.switchToExcalidarwAfterLoad();
|
||||
this.switchToExcalidarwAfterLoad();
|
||||
|
||||
this.app.workspace.onLayoutReady(() => {
|
||||
(process.env.NODE_ENV === 'development') && DEBUGGING && debug(this.onload,"ExcalidrawPlugin.onload > app.workspace.onLayoutReady");
|
||||
this.scriptEngine = new ScriptEngine(this);
|
||||
imageCache.initializeDB(this);
|
||||
this.taskbone = new Taskbone(this);
|
||||
this.isReady = true;
|
||||
|
||||
this.app.workspace.onLayoutReady(() => {
|
||||
(process.env.NODE_ENV === 'development') && DEBUGGING && debug(this.onload,"ExcalidrawPlugin.onload > app.workspace.onLayoutReady");
|
||||
this.scriptEngine = new ScriptEngine(this);
|
||||
imageCache.initializeDB(this);
|
||||
});
|
||||
});
|
||||
this.taskbone = new Taskbone(this);
|
||||
}
|
||||
|
||||
public async awaitInit() {
|
||||
let counter = 0;
|
||||
while(!this.isReady && counter < 150) {
|
||||
await sleep(50);
|
||||
}
|
||||
}
|
||||
|
||||
private setPropertyTypes() {
|
||||
if(!this.settings.loadPropertySuggestions) return;
|
||||
const app = this.app;
|
||||
this.app.workspace.onLayoutReady(() => {
|
||||
this.app.workspace.onLayoutReady(async () => {
|
||||
(process.env.NODE_ENV === 'development') && DEBUGGING && debug(this.setPropertyTypes, `ExcalidrawPlugin.setPropertyTypes > app.workspace.onLayoutReady`);
|
||||
await this.awaitInit();
|
||||
Object.keys(FRONTMATTER_KEYS).forEach((key) => {
|
||||
if(FRONTMATTER_KEYS[key].depricated === true) return;
|
||||
const {name, type} = FRONTMATTER_KEYS[key];
|
||||
@@ -438,7 +465,7 @@ export default class ExcalidrawPlugin extends Plugin {
|
||||
public initializeFonts() {
|
||||
this.app.workspace.onLayoutReady(async () => {
|
||||
(process.env.NODE_ENV === 'development') && DEBUGGING && debug(this.initializeFonts, `ExcalidrawPlugin.initializeFonts > app.workspace.onLayoutReady`);
|
||||
|
||||
await this.awaitInit();
|
||||
const cjkFontDataURLs = await getCJKDataURLs(this);
|
||||
if(typeof cjkFontDataURLs === "boolean" && !cjkFontDataURLs) {
|
||||
new Notice(t("FONTS_LOAD_ERROR") + this.settings.fontAssetsPath,6000);
|
||||
@@ -534,8 +561,9 @@ export default class ExcalidrawPlugin extends Plugin {
|
||||
}
|
||||
|
||||
private switchToExcalidarwAfterLoad() {
|
||||
this.app.workspace.onLayoutReady(() => {
|
||||
this.app.workspace.onLayoutReady(async () => {
|
||||
(process.env.NODE_ENV === 'development') && DEBUGGING && debug(this.switchToExcalidarwAfterLoad, `ExcalidrawPlugin.switchToExcalidarwAfterLoad > app.workspace.onLayoutReady`);
|
||||
await this.awaitInit();
|
||||
let leaf: WorkspaceLeaf;
|
||||
for (leaf of this.app.workspace.getLeavesOfType("markdown")) {
|
||||
if ( leaf.view instanceof MarkdownView && this.isExcalidrawFile(leaf.view.file)) {
|
||||
@@ -767,9 +795,9 @@ export default class ExcalidrawPlugin extends Plugin {
|
||||
initializeMarkdownPostProcessor(this);
|
||||
this.registerMarkdownPostProcessor(markdownPostProcessor);
|
||||
|
||||
this.app.workspace.onLayoutReady(() => {
|
||||
this.app.workspace.onLayoutReady(async () => {
|
||||
(process.env.NODE_ENV === 'development') && DEBUGGING && debug(this.addMarkdownPostProcessor, `ExcalidrawPlugin.addMarkdownPostProcessor > app.workspace.onLayoutReady`);
|
||||
|
||||
await this.awaitInit();
|
||||
// internal-link quick preview
|
||||
this.registerEvent(this.app.workspace.on("hover-link", hoverEvent));
|
||||
|
||||
@@ -889,8 +917,9 @@ export default class ExcalidrawPlugin extends Plugin {
|
||||
? new CustomMutationObserver(fileExplorerObserverFn, "fileExplorerObserver")
|
||||
: new MutationObserver(fileExplorerObserverFn);
|
||||
|
||||
this.app.workspace.onLayoutReady(() => {
|
||||
this.app.workspace.onLayoutReady(async () => {
|
||||
(process.env.NODE_ENV === 'development') && DEBUGGING && debug(this.experimentalFileTypeDisplay, `ExcalidrawPlugin.experimentalFileTypeDisplay > app.workspace.onLayoutReady`);
|
||||
await this.awaitInit();
|
||||
document.querySelectorAll(".nav-file-title").forEach(insertFiletype); //apply filetype to files already displayed
|
||||
const container = document.querySelector(".nav-files-container");
|
||||
if (container) {
|
||||
@@ -1842,9 +1871,13 @@ export default class ExcalidrawPlugin extends Plugin {
|
||||
const size = await ea.getOriginalImageSize(el);
|
||||
if(size) {
|
||||
ea.copyViewElementsToEAforEditing(els);
|
||||
const eaEl = ea.getElement(el.id);
|
||||
//@ts-ignore
|
||||
eaEl.width = size.width; eaEl.height = size.height;
|
||||
const eaEl = ea.getElement(el.id) as Mutable<ExcalidrawImageElement>;
|
||||
if(eaEl.crop) {
|
||||
eaEl.width = eaEl.crop.width;
|
||||
eaEl.height = eaEl.crop.height;
|
||||
} else {
|
||||
eaEl.width = size.width; eaEl.height = size.height;
|
||||
}
|
||||
await ea.addElementsToView(false,false,false);
|
||||
}
|
||||
ea.destroy();
|
||||
@@ -2762,6 +2795,7 @@ export default class ExcalidrawPlugin extends Plugin {
|
||||
}
|
||||
this.app.workspace.onLayoutReady(async () => {
|
||||
(process.env.NODE_ENV === 'development') && DEBUGGING && debug(this.runStartupScript, `ExcalidrawPlugin.runStartupScript > app.workspace.onLayoutReady, scriptPath:${this.settings?.startupScriptPath}`);
|
||||
await this.awaitInit();
|
||||
const path = this.settings.startupScriptPath.endsWith(".md")
|
||||
? this.settings.startupScriptPath
|
||||
: `${this.settings.startupScriptPath}.md`;
|
||||
@@ -2922,6 +2956,7 @@ export default class ExcalidrawPlugin extends Plugin {
|
||||
private registerEventListeners() {
|
||||
this.app.workspace.onLayoutReady(async () => {
|
||||
(process.env.NODE_ENV === 'development') && DEBUGGING && debug(this.registerEventListeners,`ExcalidrawPlugin.registerEventListeners > app.workspace.onLayoutReady`);
|
||||
await this.awaitInit();
|
||||
const onPasteHandler = (
|
||||
evt: ClipboardEvent,
|
||||
editor: Editor,
|
||||
@@ -3370,7 +3405,8 @@ export default class ExcalidrawPlugin extends Plugin {
|
||||
|
||||
this.settings = null;
|
||||
clearMathJaxVariables();
|
||||
EXCALIDRAW_PACKAGES = "";
|
||||
EXCALIDRAW_PACKAGE = "";
|
||||
REACT_PACKAGES = "";
|
||||
//pluginPackages = null;
|
||||
PLUGIN_VERSION = null;
|
||||
//@ts-ignore
|
||||
|
||||
@@ -85,6 +85,7 @@ export interface ExcalidrawSettings {
|
||||
defaultMode: string;
|
||||
defaultPenMode: "never" | "mobile" | "always";
|
||||
penModeDoubleTapEraser: boolean;
|
||||
penModeSingleFingerPanning: boolean;
|
||||
penModeCrosshairVisible: boolean;
|
||||
renderImageInMarkdownReadingMode: boolean,
|
||||
renderImageInHoverPreviewForMDNotes: boolean,
|
||||
@@ -261,6 +262,7 @@ export const DEFAULT_SETTINGS: ExcalidrawSettings = {
|
||||
defaultMode: "normal",
|
||||
defaultPenMode: "never",
|
||||
penModeDoubleTapEraser: true,
|
||||
penModeSingleFingerPanning: true,
|
||||
penModeCrosshairVisible: true,
|
||||
renderImageInMarkdownReadingMode: false,
|
||||
renderImageInHoverPreviewForMDNotes: false,
|
||||
@@ -1066,6 +1068,17 @@ export class ExcalidrawSettingTab extends PluginSettingTab {
|
||||
this.applySettingsUpdate();
|
||||
}),
|
||||
);
|
||||
|
||||
new Setting(detailsEl)
|
||||
.setName(t("DISABLE_SINGLE_FINGER_PANNING_NAME"))
|
||||
.addToggle((toggle) =>
|
||||
toggle
|
||||
.setValue(this.plugin.settings.penModeSingleFingerPanning)
|
||||
.onChange(async (value) => {
|
||||
this.plugin.settings.penModeSingleFingerPanning = value;
|
||||
this.applySettingsUpdate();
|
||||
}),
|
||||
);
|
||||
|
||||
new Setting(detailsEl)
|
||||
.setName(t("SHOW_PEN_MODE_FREEDRAW_CROSSHAIR_NAME"))
|
||||
|
||||
27
src/utils/PDFUtils.ts
Normal file
27
src/utils/PDFUtils.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
//for future use, not used currently
|
||||
|
||||
import { ImageCrop } from "@zsviczian/excalidraw/types/excalidraw/element/types";
|
||||
import { LinkParts } from "./Utils";
|
||||
|
||||
export function getPDFCropRect (props: {
|
||||
scale: number,
|
||||
linkParts: LinkParts,
|
||||
naturalHeight: number,
|
||||
naturalWidth: number,
|
||||
}) : ImageCrop | null {
|
||||
const cropRect = props.linkParts.ref.split("rect=")[1]?.split(",").map(x=>parseInt(x));
|
||||
const validRect = cropRect && cropRect.length === 4 && cropRect.every(x=>!isNaN(x));
|
||||
|
||||
if(!validRect) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
x: cropRect[0] * props.scale,
|
||||
y: (props.naturalHeight/props.scale - cropRect[3]) * props.scale,
|
||||
width: (cropRect[2] - cropRect[0]) * props.scale,
|
||||
height: (cropRect[3] - cropRect[1]) * props.scale,
|
||||
naturalWidth: props.naturalWidth,
|
||||
naturalHeight: props.naturalHeight,
|
||||
}
|
||||
}
|
||||
@@ -41,6 +41,7 @@ export class StylesManager {
|
||||
this.plugin = plugin;
|
||||
plugin.app.workspace.onLayoutReady(async () => {
|
||||
(process.env.NODE_ENV === 'development') && DEBUGGING && debug(undefined, "StylesManager.constructor > app.workspace.onLayoutReady", this);
|
||||
await plugin.awaitInit();
|
||||
await this.harvestStyles();
|
||||
getAllWindowDocuments(plugin.app).forEach(doc => this.copyPropertiesToTheme(doc));
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ import {
|
||||
getContainerElement,
|
||||
} from "../constants/constants";
|
||||
import ExcalidrawPlugin from "../main";
|
||||
import { ExcalidrawElement, ExcalidrawTextElement } from "@zsviczian/excalidraw/types/excalidraw/element/types";
|
||||
import { ExcalidrawElement, ExcalidrawTextElement, ImageCrop } from "@zsviczian/excalidraw/types/excalidraw/element/types";
|
||||
import { ExportSettings } from "../ExcalidrawView";
|
||||
import { getDataURLFromURL, getIMGFilename, getMimeType, getURLImageExtension } from "./FileUtils";
|
||||
import { generateEmbeddableLink } from "./CustomEmbeddableUtils";
|
||||
@@ -30,6 +30,7 @@ import { CropImage } from "./CropImage";
|
||||
import opentype from 'opentype.js';
|
||||
import { runCompressionWorker } from "src/workers/compression-worker";
|
||||
import Pool from "es6-promise-pool";
|
||||
import { FileData } from "src/EmbeddedFileLoader";
|
||||
|
||||
declare const PLUGIN_VERSION:string;
|
||||
declare var LZString: any;
|
||||
@@ -428,14 +429,14 @@ export function addAppendUpdateCustomData (el: Mutable<ExcalidrawElement>, newDa
|
||||
|
||||
export function scaleLoadedImage (
|
||||
scene: any,
|
||||
files: any
|
||||
files: FileData[],
|
||||
): { dirty: boolean; scene: any } {
|
||||
let dirty = false;
|
||||
if (!files || !scene) {
|
||||
return { dirty, scene };
|
||||
}
|
||||
|
||||
for (const f of files.filter((f:any)=>{
|
||||
for (const img of files.filter((f:any)=>{
|
||||
if(!Boolean(EXCALIDRAW_PLUGIN)) return true; //this should never happen
|
||||
const ef = EXCALIDRAW_PLUGIN.filesMaster.get(f.id);
|
||||
if(!ef) return true; //mermaid SVG or equation
|
||||
@@ -443,34 +444,85 @@ export function scaleLoadedImage (
|
||||
if(!file || (file instanceof TFolder)) return false;
|
||||
return (file as TFile).extension==="md" || EXCALIDRAW_PLUGIN.isExcalidrawFile(file as TFile)
|
||||
})) {
|
||||
const [w_image, h_image] = [f.size.width, f.size.height];
|
||||
const imageAspectRatio = f.size.width / f.size.height;
|
||||
const [imgWidth, imgHeight] = [img.size.width, img.size.height];
|
||||
const imgAspectRatio = imgWidth / imgHeight;
|
||||
|
||||
scene.elements
|
||||
.filter((e: any) => e.type === "image" && e.fileId === f.id)
|
||||
.filter((e: any) => e.type === "image" && e.fileId === img.id)
|
||||
.forEach((el: any) => {
|
||||
const [w_old, h_old] = [el.width, el.height];
|
||||
if(el.customData?.isAnchored && f.shouldScale || !el.customData?.isAnchored && !f.shouldScale) {
|
||||
addAppendUpdateCustomData(el, f.shouldScale ? {isAnchored: false} : {isAnchored: true});
|
||||
const [elWidth, elHeight] = [el.width, el.height];
|
||||
const maintainArea = img.shouldScale; //true if image should maintain its area, false if image should display at 100% its size
|
||||
const elCrop: ImageCrop = el.crop;
|
||||
const isCropped = Boolean(elCrop);
|
||||
|
||||
|
||||
if(el.customData?.isAnchored && img.shouldScale || !el.customData?.isAnchored && !img.shouldScale) {
|
||||
//customData.isAnchored is used by the Excalidraw component to disable resizing of anchored images
|
||||
//customData.isAnchored has no direct role in the calculation in the scaleLoadedImage function
|
||||
addAppendUpdateCustomData(el, img.shouldScale ? {isAnchored: false} : {isAnchored: true});
|
||||
dirty = true;
|
||||
}
|
||||
if(f.shouldScale) {
|
||||
const elementAspectRatio = w_old / h_old;
|
||||
if (imageAspectRatio !== elementAspectRatio) {
|
||||
|
||||
if(isCropped) {
|
||||
if(elCrop.naturalWidth !== imgWidth || elCrop.naturalHeight !== imgHeight) {
|
||||
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;
|
||||
//the current crop area may be maintained, need to calculate the new crop.x, crop.y offsets
|
||||
el.crop.y += (imgHeight - elCrop.naturalHeight)/2;
|
||||
if(imgWidth < elCrop.width) {
|
||||
const scaleX = el.width / elCrop.width;
|
||||
el.crop.x = 0;
|
||||
el.crop.width = imgWidth;
|
||||
el.width = imgWidth * scaleX;
|
||||
} else {
|
||||
const ratioX = elCrop.x / (elCrop.naturalWidth - elCrop.x - elCrop.width);
|
||||
const gapX = imgWidth - elCrop.width;
|
||||
el.crop.x = ratioX * gapX / (1 + ratioX);
|
||||
// const ratioA = elCrop.x / (elCrop.naturalWidth - elCrop.x);
|
||||
// el.crop.x = ratioA * imgWidth / (1 + ratioA);
|
||||
if(el.crop.x + elCrop.width > imgWidth) {
|
||||
el.crop.x = (imgWidth - elCrop.width) / 2;
|
||||
}
|
||||
}
|
||||
if(imgHeight < elCrop.height) {
|
||||
const scaleY = el.height / elCrop.height;
|
||||
el.crop.y = 0;
|
||||
el.crop.height = imgHeight;
|
||||
el.height = imgHeight * scaleY;
|
||||
} else {
|
||||
const ratioY = elCrop.y / (elCrop.naturalHeight - elCrop.y - elCrop.height);
|
||||
const gapY = imgHeight - elCrop.height;
|
||||
el.crop.y = ratioY * gapY / (1 + ratioY);
|
||||
// const ratioB = elCrop.y / (elCrop.naturalHeight - elCrop.y);
|
||||
// el.crop.y = ratioB * imgHeight / (1 + ratioB);
|
||||
if(el.crop.y + elCrop.height > imgHeight) {
|
||||
el.crop.y = (imgHeight - elCrop.height)/2;
|
||||
}
|
||||
}
|
||||
el.crop.naturalWidth = imgWidth;
|
||||
el.crop.naturalHeight = imgHeight;
|
||||
const noCrop = el.crop.width === imgWidth && el.crop.height === imgHeight;
|
||||
if(noCrop) {
|
||||
el.crop = null;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if(w_old !== w_image || h_old !== h_image) {
|
||||
} else if(maintainArea) {
|
||||
const elAspectRatio = elWidth / elHeight;
|
||||
if (imgAspectRatio !== elAspectRatio) {
|
||||
dirty = true;
|
||||
el.height = h_image;
|
||||
el.width = w_image;
|
||||
el.y += (h_old - h_image) / 2;
|
||||
el.x += (w_old - w_image) / 2;
|
||||
const elNewHeight = Math.sqrt((elWidth * elHeight * imgHeight) / imgWidth);
|
||||
const elNewWidth = Math.sqrt((elWidth * elHeight * imgWidth) / imgHeight);
|
||||
el.height = elNewHeight;
|
||||
el.width = elNewWidth;
|
||||
el.y += (elHeight - elNewHeight) / 2;
|
||||
el.x += (elWidth - elNewWidth) / 2;
|
||||
}
|
||||
} else { //100% size
|
||||
if(elWidth !== imgWidth || elHeight !== imgHeight) {
|
||||
dirty = true;
|
||||
el.height = imgHeight;
|
||||
el.width = imgWidth;
|
||||
el.y += (elHeight - imgHeight) / 2;
|
||||
el.x += (elWidth - imgWidth) / 2;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user