Skip to content
Snippets Groups Projects
Commit bd7c6ca0 authored by Alexa Valentová's avatar Alexa Valentová
Browse files

Add force template

parent 9dbd2f3e
Branches
No related tags found
No related merge requests found
Pipeline #20889 passed
frontend/src/assets/previews/back_in_full_force_photo_banner.png

95.5 KiB

frontend/src/assets/template/back_in_full_force_banner/background.png

14.7 KiB

File added
frontend/src/assets/template/back_in_full_force_banner/background_inverted.png

14.5 KiB

import basicPhotoBannerImage from "./assets/previews/basic_photo_banner.png";
import urgentBasicPhotoBannerImage from "./assets/previews/urgent_basic_photo_banner.png";
import makeawishPhotoBannerImage from "./assets/previews/make_a_wish_photo_banner.png";
import backInFullForcePhotoBannerImage from "./assets/previews/back_in_full_force_photo_banner.png";
import urgentTextBannerImage from "./assets/previews/urgent_text_banner.png";
import textBannerImage from "./assets/previews/text_banner.png";
import newspaperQuoteBottomImage from "./assets/previews/newspaper_quote_bottom.png";
......@@ -55,6 +56,15 @@ const TEMPLATES = {
title: "Máte přání banner",
},
},
back_in_full_force_banner: {
name: "Zpátky v plné síle banner",
image: backInFullForcePhotoBannerImage,
path: "/back-in-full-force-banner",
component: () => import("./views/back_in_full_force_banner/BackInFullForceBanner.vue"),
meta: {
title: "Zpátky v plné síle banner",
},
},
urgent_text_banner: {
name: "Urgentní banner pouze s textem",
image: urgentTextBannerImage,
......
<script setup>
import { watch, ref } from "vue";
import COLORS from "../../colors";
import PEOPLE from "../../people";
import TEMPLATES from "../../templates";
import DEFAULT_CONTRACTOR from "../../contractors";
import {
loadFonts,
loadCanvasStorage,
setCanvasStorage,
updateAutoRedrawStorage,
} from "../../utils";
import Canvas from "../../components/canvas/Canvas.vue";
import redraw from "./canvas";
import Navbar from "../../components/Navbar.vue";
import MainContainer from "../../components/MainContainer.vue";
import ImageInput from "../../components/inputs/ImageInput.vue";
import LongTextInput from "../../components/inputs/text/LongTextInput.vue";
import ShortTextInput from "../../components/inputs/text/ShortTextInput.vue";
import RangeInput from "../../components/inputs/RangeInput.vue";
import InputSeparator from "../../components/inputs/InputSeparator.vue";
import SelectInput from "../../components/inputs/SelectInput.vue";
import MultipleColorPicker from "../../components/inputs/colors/MultipleColorPicker.vue";
import ReloadButton from "../../components/reload/ReloadButton.vue";
import AutoReloadCheckbox from "../../components/reload/AutoReloadCheckbox.vue";
</script>
<script>
await loadFonts([
"12px Bebas Neue",
"12px Roboto Condensed",
"bold 12px Roboto Condensed",
]);
export default {
components: {
Canvas,
Navbar,
MainContainer,
ImageInput,
LongTextInput,
ShortTextInput,
RangeInput,
SelectInput,
InputSeparator,
MultipleColorPicker,
},
data() {
const predefinedColors = {
base: {
name: "Černé pozadí",
colors: {
background: COLORS.black,
highlight: COLORS.yellow1,
baseText: COLORS.white,
nameText: COLORS.yellow1,
highlightedText: COLORS.black,
contractedByText: COLORS.gray1,
},
},
white: {
name: "Bílé pozadí",
colors: {
background: COLORS.white,
highlight: COLORS.yellow1,
baseText: COLORS.black,
nameText: COLORS.black,
highlightedText: COLORS.black,
contractedByText: COLORS.gray1,
},
},
};
return {
mainImage: null,
mainText: null,
personName: null,
personPosition: null,
contractedBy: DEFAULT_CONTRACTOR,
colorLabels: {
background: "Pozadí",
highlight: "Zvýraznění",
baseText: "Text",
highlightedText: "Zvýrazněný text",
},
predefinedColors: predefinedColors,
colors: predefinedColors.base.colors,
autoRedraw: false,
};
},
async created() {
await loadCanvasStorage(this);
},
methods: {
async reloadCanvasProperties() {
const canvasProperties = {
mainImage: this.mainImage,
mainText: this.mainText,
personName: this.personName,
personPosition: this.personPosition,
contractedBy: this.contractedBy,
colors: this.colors,
};
if (canvasProperties.mainText) {
window.fileName = canvasProperties.mainText;
}
await this.$refs.canvas.redraw(canvasProperties);
delete canvasProperties.colors;
setCanvasStorage(canvasProperties);
},
},
mounted() {
this.$watch(
(vm) => [
vm.mainImage,
vm.mainText,
vm.personName,
vm.personPosition,
vm.contractedBy,
vm.colors,
],
async (value) => {
if (this.autoRedraw) {
await this.reloadCanvasProperties();
}
},
{
immediate: true,
deep: true,
},
);
this.$watch(
(vm) => [vm.autoRedraw],
async (value) => {
updateAutoRedrawStorage(this.autoRedraw);
if (this.autoRedraw) {
await this.reloadCanvasProperties();
}
},
);
},
};
</script>
<template>
<header>
<Navbar :defaultTemplate="TEMPLATES.basic_photo_banner"></Navbar>
</header>
<main>
<MainContainer>
<template v-slot:left>
<Canvas
ref="canvas"
:redrawFunction="redraw"
width="2000"
height="2000"
/>
</template>
<template v-slot:right>
<ReloadButton :parentRefs="$refs" @click="reloadCanvasProperties" />
<AutoReloadCheckbox v-model="autoRedraw" />
<ImageInput
name="Obrázek"
v-model="mainImage"
:important="true"
zIndex="10"
/>
<LongTextInput
name="Hlavní text"
v-model="mainText"
:important="true"
:highlightable="true"
zIndex="9"
/>
<ShortTextInput
name="Jméno osoby"
v-model="personName"
v-model:relatedModel="personPosition"
:predefinedValues="PEOPLE"
:important="true"
zIndex="8"
/>
<LongTextInput
ref="refPersonPosition"
name="Pozice osoby"
v-model="personPosition"
:important="false"
zIndex="7"
/>
<InputSeparator />
<MultipleColorPicker
name="Barvy"
v-model="colors"
:important="false"
:colorLabels="colorLabels"
:predefinedColors="predefinedColors"
:defaultPredefinedColors="predefinedColors.base"
zIndex="5"
></MultipleColorPicker>
<ShortTextInput
name="Zadavatel a zpracovatel"
v-model="contractedBy"
:defaultValue="DEFAULT_CONTRACTOR"
:important="false"
zIndex="4"
/>
</template>
</MainContainer>
</main>
</template>
<style>
@import "vue-select/dist/vue-select.css";
</style>
import { fabric } from "fabric";
import {
clearObjects,
sortObjects,
transformHighlightedText,
checkTextBoxHeight,
} from "../../components/canvas/utils";
import { PaddedHighlightingTextbox } from "../../components/canvas/textbox";
import backgroundURL from "../../assets/template/back_in_full_force_banner/background.png";
import backgroundURLInverted from "../../assets/template/back_in_full_force_banner/background_inverted.png";
import COLORS from "../../colors";
let mainTextBox = null;
let personNameText = null;
let personPositionText = null;
let mainImage = null;
let backgroundImage = null;
let previousBackgroundImageColor = null;
let contractedByTextbox = null;
let mainImageSource = null;
const redraw = async (canvas, options) => {
clearObjects(
[
mainTextBox,
personNameText,
personPositionText,
contractedByTextbox,
],
canvas,
);
canvas.preserveObjectStacking = true;
const textMarginLeft = Math.ceil(canvas.width * 0.24);
const textMarginRight = Math.ceil(canvas.width * 0.21);
let mainTextMarginBottom = Math.ceil(canvas.height * 0.085);
const mainTextBackgroundMarginTop = Math.ceil(canvas.height * 0.14);
const mainTextSize = Math.ceil(canvas.height * 0.07);
const mainTextHeightLimit = Math.ceil(mainTextSize * 3.3);
const mainTextLineHeight = 1;
const bottomTextSize = Math.ceil(canvas.height * 0.035);
const positionTextSize = Math.ceil(canvas.height * 0.025);
const nameTextMarginBottom = Math.ceil(canvas.height * 0.132);
const nameTextMarginLeft = Math.ceil(canvas.width * 0.05);
const nameTextExtraBottomMargin = Math.ceil(canvas.height * 0.05);
const nameTextMaxWidth = Math.ceil(canvas.width * 0.16);
const positionTextSideGap = nameTextMarginLeft;
const positionTextMarginBottom = Math.ceil(canvas.height * 0.073);
const positionTextSeparatorWidth = Math.ceil(canvas.width * 0.0035);
const positionTextMaxWidth = Math.ceil(canvas.width * 0.16);
const contractedByTextSize = Math.ceil(canvas.height * 0.02);
const contractedByTextMaxWidth = Math.ceil(canvas.width * 0.9);
const contractedByTextSidesMargin = Math.ceil(canvas.width * 0.03);
if (options.mainText !== null) {
/* BEGIN Background render */
if (backgroundImage === null || options.colors.background.value != previousBackgroundImageColor.value) {
backgroundImage = new Image();
await new Promise((resolve) => {
backgroundImage.onload = () => {
resolve();
};
if (options.colors.background.value == COLORS.black.value) {
backgroundImage.src = backgroundURL;
} else {
backgroundImage.src = backgroundURLInverted;
}
});
backgroundImage = new fabric.Image(backgroundImage, {
top: canvas.height - backgroundImage.height, // FIXME: Why???? Fabric.js, what are you trying to tell me?!
left: -20,
zIndex: 10,
selectable: false,
});
backgroundImage.scaleToWidth(canvas.width + 22);
previousBackgroundImageColor = options.colors.background;
canvas.add(backgroundImage);
}
/* END Background render */
/* BEGIN Name text render */
if (options.personName !== null) {
let styles = {
0: {},
};
/*
for (let position = 0; position < options.personName.length; position++) {
styles[0][position] = {
fontWeight: "bold",
};
}
*/
personNameText = new fabric.Textbox(options.personName, {
left: nameTextMarginLeft,
top: canvas.height - bottomTextSize - nameTextMarginBottom,
width: nameTextMaxWidth,
fontFamily: "Bebas Neue",
fontSize: bottomTextSize,
styles: styles,
fill: options.colors.nameText.value,
selectable: false,
zIndex: 20,
});
checkTextBoxHeight(personNameText, 1);
if (options.personPosition !== null) {
personPositionText = new fabric.Textbox(options.personPosition, {
left: positionTextSideGap,
top: canvas.height - bottomTextSize - positionTextMarginBottom,
width: positionTextMaxWidth,
fontFamily: "Roboto Condensed",
fontSize: positionTextSize,
fill: options.colors.baseText.value,
selectable: false,
zIndex: 20,
});
checkTextBoxHeight(personPositionText, 1);
if (personPositionText._textLines.length === 2) {
mainTextMarginBottom += nameTextExtraBottomMargin;
personNameText.set({
top: personNameText.top - nameTextExtraBottomMargin,
});
personPositionText.set({
top: personPositionText.top - nameTextExtraBottomMargin,
});
}
canvas.add(personPositionText);
canvas.renderAll();
}
canvas.add(personNameText);
}
/* END Name text render */
/* BEGIN Main text render */
const mainTextWidth = canvas.width - textMarginRight;
const highlightedData = transformHighlightedText(
options.mainText,
mainTextSize,
mainTextWidth,
"Bebas Neue",
options.colors.highlight.value,
options.colors.highlightedText.value,
{ padWhenDiacritics: false, invertHighlight: true },
);
mainTextBox = new PaddedHighlightingTextbox(highlightedData.text, {
width: canvas.width,
left: textMarginLeft,
textAlign: "left",
fontFamily: "Bebas Neue",
fontSize: mainTextSize,
lineHeight: mainTextLineHeight,
fill: options.colors.baseText.value,
styles: highlightedData.styles,
selectable: false,
highlightPadding: canvas.height * 0.003,
zIndex: 20,
});
checkTextBoxHeight(mainTextBox, 1);
canvas.add(mainTextBox);
const mainTextBoxTop =
canvas.height - mainTextBox.height - mainTextMarginBottom;
mainTextBox.top = mainTextBoxTop - highlightedData.paddingBottom;
canvas.renderAll();
/* END Main text render */
}
/* BEGIN Contracted by render */
if (options.contractedBy !== null) {
contractedByTextbox = new fabric.Textbox(options.contractedBy, {
left: contractedByTextSidesMargin,
top: contractedByTextSidesMargin,
width: contractedByTextMaxWidth,
fontFamily: "Roboto Condensed",
fontSize: contractedByTextSize,
textAlign: "left",
fill: options.colors.contractedByText.value,
selectable: false,
zIndex: 20,
});
checkTextBoxHeight(contractedByTextbox, 1);
canvas.add(contractedByTextbox);
}
/* END Contracted by render */
/* BEGIN Main image render */
if (
options.mainImage !== null &&
(!canvas.contains(mainImage) ||
mainImage === null ||
options.mainImage.src !== mainImageSource)
) {
if (mainImage !== null) {
canvas.remove(mainImage);
}
mainImage = new fabric.Image(options.mainImage, {
left: 0,
top: 0,
zIndex: 0,
});
mainImage.controls = {
...fabric.Image.prototype.controls,
mtr: new fabric.Control({ visible: false }),
};
if (mainImage.width >= mainImage.height) {
mainImage.scaleToHeight(canvas.height);
} else {
mainImage.scaleToWidth(canvas.width);
}
canvas.add(mainImage);
mainImageSource = options.mainImage.src;
// canvas.centerObject(mainImage)
} else if (mainImage !== null && options.mainImage === null) {
canvas.remove(mainImage);
}
/* END Main image render */
sortObjects(canvas);
};
export default redraw;
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment