Fix misaligned image occlusions (#2512)
* Cloze styling is not required in I/O notetype * Use raw string for IO template * Rename to notetype.css and use more specific ids * Move internal i/o styling into runtime Storing it in the notetype makes it difficult to make changes, and makes it easier for the user to break. * Fix misaligned occlusions At larger screen sizes, the canvas was not increasing above its configured size, so it ended up being placed top center instead of expanding to fit the entire container area. To resolve this, both the image and canvas are forced to the container size, and the container is constrained to the size of the viewport, with the same aspect ratio as the image. Closes #2492
This commit is contained in:
parent
581f82c589
commit
7686cb8de8
@ -394,7 +394,7 @@ fn build_and_check_editor(build: &mut Build) -> Result<()> {
|
||||
}
|
||||
|
||||
fn build_and_check_reviewer(build: &mut Build) -> Result<()> {
|
||||
let reviewer_deps = inputs![":ts:lib", glob!("ts/reviewer/**")];
|
||||
let reviewer_deps = inputs![":ts:lib", glob!("ts/reviewer/**"),];
|
||||
build.add(
|
||||
"ts:reviewer:reviewer.js",
|
||||
EsbuildScript {
|
||||
@ -410,7 +410,7 @@ fn build_and_check_reviewer(build: &mut Build) -> Result<()> {
|
||||
CompileSass {
|
||||
input: inputs!["ts/reviewer/reviewer.scss"],
|
||||
output: "ts/reviewer/reviewer.css",
|
||||
deps: ":sass".into(),
|
||||
deps: inputs![":sass", "ts/image-occlusion/review.scss"],
|
||||
load_paths: vec!["."],
|
||||
},
|
||||
)?;
|
||||
|
@ -1,41 +0,0 @@
|
||||
.image-occlusion-canvas {
|
||||
--inactive-shape-color: #ffeba2;
|
||||
--active-shape-color: #ff8e8e;
|
||||
--inactive-shape-border: 1px #212121;
|
||||
--active-shape-border: 1px #212121;
|
||||
}
|
||||
|
||||
.card {
|
||||
font-family: arial;
|
||||
font-size: 20px;
|
||||
text-align: center;
|
||||
color: black;
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
.cloze {
|
||||
font-weight: bold;
|
||||
color: blue;
|
||||
}
|
||||
|
||||
.nightMode .cloze {
|
||||
color: lightblue;
|
||||
}
|
||||
|
||||
#container {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
img {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 50%;
|
||||
transform: translate(-50%, 0);
|
||||
}
|
||||
|
||||
#canvas {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 50%;
|
||||
transform: translate(-50%, 0);
|
||||
}
|
@ -47,10 +47,7 @@ impl Collection {
|
||||
let mgr = MediaManager::new(&self.media_folder, &self.media_db)?;
|
||||
let actual_image_name_after_adding = mgr.add_file(&image_filename, &image_bytes)?;
|
||||
|
||||
let image_tag = format!(
|
||||
r#"<img id="img" src="{}">"#,
|
||||
&actual_image_name_after_adding
|
||||
);
|
||||
let image_tag = format!(r#"<img src="{}">"#, &actual_image_name_after_adding);
|
||||
|
||||
let current_deck = self.get_current_deck()?;
|
||||
self.transact(Op::ImageOcclusion, |col| {
|
||||
|
14
rslib/src/image_occlusion/notetype.css
Normal file
14
rslib/src/image_occlusion/notetype.css
Normal file
@ -0,0 +1,14 @@
|
||||
#image-occlusion-canvas {
|
||||
--inactive-shape-color: #ffeba2;
|
||||
--active-shape-color: #ff8e8e;
|
||||
--inactive-shape-border: 1px #212121;
|
||||
--active-shape-border: 1px #212121;
|
||||
}
|
||||
|
||||
.card {
|
||||
font-family: arial;
|
||||
font-size: 20px;
|
||||
text-align: center;
|
||||
color: black;
|
||||
background-color: white;
|
||||
}
|
@ -51,7 +51,7 @@ impl Collection {
|
||||
}
|
||||
|
||||
pub(crate) fn image_occlusion_notetype(tr: &I18n) -> Notetype {
|
||||
const IMAGE_CLOZE_CSS: &str = include_str!("image_occlusion_styling.css");
|
||||
const IMAGE_CLOZE_CSS: &str = include_str!("notetype.css");
|
||||
let mut nt = empty_stock(
|
||||
NotetypeKind::Cloze,
|
||||
OriginalStockKind::ImageOcclusion,
|
||||
@ -71,31 +71,29 @@ pub(crate) fn image_occlusion_notetype(tr: &I18n) -> Notetype {
|
||||
|
||||
let err_loading = tr.notetypes_error_loading_image_occlusion();
|
||||
let qfmt = format!(
|
||||
"\
|
||||
{{{{#{header}}}}}<div>{{{{{header}}}}}</div>{{{{/{header}}}}}
|
||||
<div style=\"display: none\">{{{{cloze:{occlusion}}}}}</div>
|
||||
<div id=\"err\"></div>
|
||||
<div id=container>
|
||||
r#"{{{{#{header}}}}}<div>{{{{{header}}}}}</div>{{{{/{header}}}}}
|
||||
<div style="display: none">{{{{cloze:{occlusion}}}}}</div>
|
||||
<div id="err"></div>
|
||||
<div id="image-occlusion-container">
|
||||
{{{{{image}}}}}
|
||||
<canvas id=\"canvas\" class=\"image-occlusion-canvas\"></canvas>
|
||||
<canvas id="image-occlusion-canvas"></canvas>
|
||||
</div>
|
||||
<script>
|
||||
try {{
|
||||
anki.setupImageCloze();
|
||||
}} catch (exc) {{
|
||||
document.getElementById(\"err\").innerHTML = `{err_loading}<br><br>${{exc}}`;
|
||||
document.getElementById("err").innerHTML = `{err_loading}<br><br>${{exc}}`;
|
||||
}}
|
||||
</script>
|
||||
"
|
||||
"#
|
||||
);
|
||||
|
||||
let toggle_masks = tr.notetypes_toggle_masks();
|
||||
let afmt = format!(
|
||||
"\
|
||||
{qfmt}
|
||||
<div><button id=\"toggle\">{toggle_masks}</button></div>
|
||||
r#"{qfmt}
|
||||
<div><button id="toggle">{toggle_masks}</button></div>
|
||||
{{{{#{back_extra}}}}}<div>{{{{{back_extra}}}}}</div>{{{{/{back_extra}}}}}
|
||||
",
|
||||
"#,
|
||||
);
|
||||
nt.add_template(nt.name.clone(), qfmt, afmt);
|
||||
nt
|
||||
|
28
ts/image-occlusion/review.scss
Normal file
28
ts/image-occlusion/review.scss
Normal file
@ -0,0 +1,28 @@
|
||||
#image-occlusion-container {
|
||||
position: relative;
|
||||
// if height-constrained, ensure container is centered
|
||||
left: 50%;
|
||||
transform: translate(-50%, 0);
|
||||
// allow for 20px margin on html element, or short windows can truncate
|
||||
// image
|
||||
max-height: calc(95vh - 40px);
|
||||
}
|
||||
|
||||
#image-occlusion-container img {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
// remove the default image limits, as we rely on container
|
||||
max-width: unset;
|
||||
max-height: unset;
|
||||
}
|
||||
|
||||
#image-occlusion-canvas {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
@ -12,17 +12,14 @@ export function setupImageCloze(): void {
|
||||
}
|
||||
|
||||
function setupImageClozeInner(): void {
|
||||
const canvas = document.querySelector("canvas") as HTMLCanvasElement | null;
|
||||
const canvas = document.querySelector("#image-occlusion-canvas") as HTMLCanvasElement | null;
|
||||
if (canvas == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
canvas.style.maxWidth = "100%";
|
||||
canvas.style.maxHeight = "95vh";
|
||||
|
||||
const ctx: CanvasRenderingContext2D = canvas.getContext("2d")!;
|
||||
const container = document.getElementById("container") as HTMLDivElement;
|
||||
const image = document.getElementById("img") as HTMLImageElement;
|
||||
const container = document.getElementById("image-occlusion-container") as HTMLDivElement;
|
||||
const image = document.querySelector("#image-occlusion-container img") as HTMLImageElement;
|
||||
if (image == null) {
|
||||
container.innerText = tr.notetypeErrorNoImageToShow();
|
||||
return;
|
||||
@ -32,8 +29,8 @@ function setupImageClozeInner(): void {
|
||||
canvas.width = size.width;
|
||||
canvas.height = size.height;
|
||||
|
||||
// set height for div container (used 'relative' in css)
|
||||
container.style.height = `${image.height}px`;
|
||||
// Enforce aspect ratio of image
|
||||
container.style.aspectRatio = `${size.width / size.height}`;
|
||||
|
||||
// setup button for toggle image occlusion
|
||||
const button = document.getElementById("toggle");
|
||||
@ -151,7 +148,7 @@ function getShapeProperty(): {
|
||||
activeBorder: { width: number; color: string };
|
||||
inActiveBorder: { width: number; color: string };
|
||||
} {
|
||||
const canvas = document.getElementById("canvas");
|
||||
const canvas = document.getElementById("image-occlusion-canvas");
|
||||
const computedStyle = window.getComputedStyle(canvas!);
|
||||
// it may throw error if the css variable is not defined
|
||||
try {
|
||||
@ -199,7 +196,7 @@ function getShapeProperty(): {
|
||||
}
|
||||
|
||||
const toggleMasks = (): void => {
|
||||
const canvas = document.getElementById("canvas") as HTMLCanvasElement;
|
||||
const canvas = document.getElementById("image-occlusion-canvas") as HTMLCanvasElement;
|
||||
const display = canvas.style.display;
|
||||
if (display === "none") {
|
||||
canvas.style.display = "unset";
|
||||
|
@ -2,6 +2,7 @@
|
||||
* License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html */
|
||||
|
||||
@use "sass/vars";
|
||||
@use "ts/image-occlusion/review";
|
||||
|
||||
hr {
|
||||
background-color: vars.palette(darkgray, 0);
|
||||
|
Loading…
Reference in New Issue
Block a user