From f74e829ef94789535e85dbca615c6bcbdda9f6ab Mon Sep 17 00:00:00 2001 From: Jyotiranjan Mohanty Date: Thu, 25 Sep 2025 16:50:09 +0530 Subject: [PATCH] Update badge-page.ts --- src/pages/badge-page.ts | 324 +++++++++++++++++++++++++--------------- 1 file changed, 206 insertions(+), 118 deletions(-) diff --git a/src/pages/badge-page.ts b/src/pages/badge-page.ts index 8b8f9798..5f5322ca 100644 --- a/src/pages/badge-page.ts +++ b/src/pages/badge-page.ts @@ -10,18 +10,20 @@ import { updateMetadata } from '../utils/metadata'; declare var Cropper: any; @customElement('badge-page') export class BadgePage extends PolymerElement { - static get template() { return html` - - + +
[[heroSettings.title]]
-
@@ -227,7 +243,10 @@ export class BadgePage extends PolymerElement {

Now that you are here, how about personalising your profile? Upload an image and generate a personalised badge with the GDG DevFest Ahmedabad 2024 frame. Also share your image using - + #DevFestAhm on different social platforms. @@ -246,7 +265,7 @@ export class BadgePage extends PolymerElement {

-
+
@@ -254,20 +273,11 @@ export class BadgePage extends PolymerElement {
-
+
Original
-
- Square -
-
- Circle -
+
Square
+
Circle
@@ -282,8 +292,8 @@ export class BadgePage extends PolymerElement { @@ -294,7 +304,7 @@ export class BadgePage extends PolymerElement {
- Uploaded Image + Uploaded Image
@@ -309,19 +319,42 @@ export class BadgePage extends PolymerElement {
-
- - +
+
+ +
+ + Download + + + + + +
+
+
+
+
- +
Done @@ -340,23 +373,31 @@ export class BadgePage extends PolymerElement { canvas: any; ctx: any; image: any; - shape = "original"; + shape = 'original'; banner = new Image(); dpi = window.devicePixelRatio; cropper: any; imageCropper: any; + + // ==================== NEWLY ADDED PROPERTIES START ==================== + speakerCanvas: any; + speakerCtx: any; + speakerBanner = new Image(); + // ==================== NEWLY ADDED PROPERTIES END ==================== + onAfterEnter() { setTimeout(() => { this.setProfileCanvas(); + this.setSpeakerCanvas(); // NEW }, 1000); updateMetadata(this.heroSettings.title, this.heroSettings.metaDescription); } setProfileCanvas() { this.canvas = this.shadowRoot?.querySelector('#profile-canvas'); - this.ctx = this.canvas.getContext("2d"); - this.banner.setAttribute('crossOrigin', 'anonymous') + this.ctx = this.canvas.getContext('2d'); + this.banner.setAttribute('crossOrigin', 'anonymous'); this.banner.src = '/images/badge-profile.png'; this.banner.onload = () => { this.ctx.imageSmoothingEnabled = false; @@ -364,63 +405,74 @@ export class BadgePage extends PolymerElement { }; } + // ==================== NEWLY ADDED FUNCTION START ==================== + setSpeakerCanvas() { + this.speakerCanvas = this.shadowRoot?.querySelector('#speaker-canvas'); + this.speakerCtx = this.speakerCanvas.getContext('2d'); + this.speakerBanner.setAttribute('crossOrigin', 'anonymous'); + // IMPORTANT: You need to create and add this image to your /images/ folder + this.speakerBanner.src = '/images/badge_dev.png'; + this.speakerBanner.onload = () => { + this.speakerCtx.imageSmoothingEnabled = false; + this.drawSpeakerBadge(); + }; + } + // ==================== NEWLY ADDED FUNCTION END ==================== + changeShape(event: any) { - const original:any = this.shadowRoot?.querySelector( - ".select-container .select#original" - ); - const square:any = this.shadowRoot?.querySelector(".select-container .select#square"); - const circle:any = this.shadowRoot?.querySelector(".select-container .select#circle"); + const original: any = this.shadowRoot?.querySelector('.select-container .select#original'); + const square: any = this.shadowRoot?.querySelector('.select-container .select#square'); + const circle: any = this.shadowRoot?.querySelector('.select-container .select#circle'); const type: any = event.target.id; this.shape = event.target.id; switch (type) { - case "original": { - original.setAttribute("selected", ""); - square.removeAttribute("selected"); - circle.removeAttribute("selected"); + case 'original': { + original.setAttribute('selected', ''); + square.removeAttribute('selected'); + circle.removeAttribute('selected'); break; } - case "square": { - square.setAttribute("selected", ""); - original.removeAttribute("selected"); - circle.removeAttribute("selected"); + case 'square': { + square.setAttribute('selected', ''); + original.removeAttribute('selected'); + circle.removeAttribute('selected'); break; } - case "circle": { - circle.setAttribute("selected", ""); - original.removeAttribute("selected"); - square.removeAttribute("selected"); + case 'circle': { + circle.setAttribute('selected', ''); + original.removeAttribute('selected'); + square.removeAttribute('selected'); break; } } this.draw(); - }; + } - upload = (e:any) => { + upload = (e: any) => { this.open = false; if (e && e.target.files && e.target.files[0]) { this.open = true; const reader = new FileReader(); - reader.onload = (event:any) => { + reader.onload = (event: any) => { const img = new Image(); img.onload = () => { this.image = img; this.draw(); + this.drawSpeakerBadge(); // NEW }; img.src = event.target.result; - // console.log("🚀 ~ file: badge-page.ts:399 ~ BadgePage ~ event.target.result:", event.target.result) this.imageCropper = this.shadowRoot?.querySelector('#image-cropper'); this.imageCropper.src = event.target.result; this.initCropper(); }; reader.readAsDataURL(e.target.files[0]); - } }; draw = () => { if (this.image) { switch (this.shape) { - case "original": { + case 'original': { this.canvas.width = this.image.width; this.canvas.height = this.image.height; this.ctx.drawImage(this.image, 0, 0); @@ -451,7 +503,7 @@ export class BadgePage extends PolymerElement { } else { this.ctx.canvas.width = 500 * this.dpi; this.ctx.canvas.height = 500 * this.dpi; - this.ctx.fillStyle = "#fff"; + this.ctx.fillStyle = '#fff'; this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height); } @@ -470,13 +522,13 @@ export class BadgePage extends PolymerElement { height ); - this.ctx.fillStyle = "#757575"; - this.ctx.textAlign = "center"; - this.ctx.textBaseline = "middle"; + this.ctx.fillStyle = '#757575'; + this.ctx.textAlign = 'center'; + this.ctx.textBaseline = 'middle'; this.ctx.font = `${fontSize}px Google Sans, sans-serif`; - if (this.shape === "circle") { - this.ctx.globalCompositeOperation = "destination-in"; + if (this.shape === 'circle') { + this.ctx.globalCompositeOperation = 'destination-in'; this.ctx.beginPath(); this.ctx.arc( this.canvas.width / 2, @@ -490,64 +542,80 @@ export class BadgePage extends PolymerElement { } }; + // ==================== NEWLY ADDED FUNCTION START ==================== + drawSpeakerBadge = () => { + this.speakerCanvas.width = 500 * this.dpi; + this.speakerCanvas.height = 500 * this.dpi; + + // Draw the user image + if (this.image) { + const hRatio = this.speakerCanvas.width / this.image.width; + const vRatio = this.speakerCanvas.height / this.image.height; + const ratio = Math.max(hRatio, vRatio); + const x = (this.speakerCanvas.width - this.image.width * ratio) / 2; + const y = (this.speakerCanvas.height - this.image.height * ratio) / 2; + this.speakerCtx.drawImage( + this.image, + 0, + 0, + this.image.width, + this.image.height, + x, + y, + this.image.width * ratio, + this.image.height * ratio + ); + } else { + // Draw a white background if no image + this.speakerCtx.fillStyle = '#fff'; + this.speakerCtx.fillRect(0, 0, this.speakerCanvas.width, this.speakerCanvas.height); + } + + // Draw the speaker banner over the image + this.speakerCtx.drawImage( + this.speakerBanner, + 0, + 0, + this.speakerCanvas.width, + this.speakerCanvas.height + ); + }; + // ==================== NEWLY ADDED FUNCTION END ==================== + download = () => { - const a = document.createElement("a"); - const url = this.canvas.toDataURL("image/png;base64"); - a.download = "devfestahm-profile-badge.png"; + const a = document.createElement('a'); + const url = this.canvas.toDataURL('image/png;base64'); + a.download = 'devfestahm-profile-badge.png'; a.href = url; a.click(); }; downloadTicketBadge() { const badgeContainer: any = this.shadowRoot?.querySelector('#ticket-container'); - - // Create a canvas with a higher resolution const canvas = document.createElement('canvas'); const context: any = canvas.getContext('2d'); - const scaleFactor = 2; // Adjust this scale factor as needed for better quality - + const scaleFactor = 2; canvas.width = badgeContainer.offsetWidth * scaleFactor; canvas.height = badgeContainer.offsetHeight * scaleFactor; - const backgroundImage = new Image(); - const ticketImage = this.shadowRoot?.querySelector('#ticket-image'); - + const ticketImage: any = this.shadowRoot?.querySelector('#ticket-image'); backgroundImage.src = '/images/badge-ticket.png'; backgroundImage.onload = function () { context.drawImage(backgroundImage, 0, 0, canvas.width, canvas.height); - - // Draw the uploaded image with a rounded clipping path const centerX = canvas.width / 2; const centerY = canvas.height / 2; const radius = 76 * scaleFactor; - context.save(); context.beginPath(); context.arc(centerX, centerY, radius, 0, Math.PI * 2); context.closePath(); context.clip(); - - // Draw a border for the badge-image - // context.lineWidth = 6; // Adjust border width as needed - // context.strokeStyle = '#fff'; // Border color - - // Adjust the parameters to draw the badge-image in the center const ticketImageSize = 150 * scaleFactor; const ticketImageX = centerX - ticketImageSize / 2; const ticketImageY = centerY - ticketImageSize / 2; - - context.drawImage( - ticketImage, - ticketImageX, - ticketImageY, - ticketImageSize, - ticketImageSize - ); - - context.stroke(); // Stroke the border - + context.drawImage(ticketImage, ticketImageX, ticketImageY, ticketImageSize, ticketImageSize); + context.stroke(); context.restore(); - const link = document.createElement('a'); link.href = canvas.toDataURL('image/png'); link.download = 'devfestahm-ticket-badge.png'; @@ -555,12 +623,25 @@ export class BadgePage extends PolymerElement { }; } + // ==================== NEWLY ADDED FUNCTION START ==================== + downloadSpeakerBadge = () => { + const a = document.createElement('a'); + const url = this.speakerCanvas.toDataURL('image/png;base64'); + a.download = 'devfestahm-speaker-badge.png'; + a.href = url; + a.click(); + }; + // ==================== NEWLY ADDED FUNCTION END ==================== + initCropper() { + if (this.cropper) { + this.cropper.destroy(); + } this.cropper = new Cropper(this.imageCropper, { aspectRatio: 1, viewMode: 1, autoCropArea: 1, - dragMode: 'move' + dragMode: 'move', }); } @@ -568,13 +649,20 @@ export class BadgePage extends PolymerElement { const ticketImage: any = this.shadowRoot?.querySelector('#ticket-image'); const croppedImageData = this.cropper.getCroppedCanvas().toDataURL('image/png'); - // Set the cropped image as the badge image ticketImage.src = croppedImageData; - // Hide the modal dialog - this.open = false; + // ==================== MODIFICATION START ==================== + // Update the main image property so all badges use the cropped version + const croppedImg = new Image(); + croppedImg.onload = () => { + this.image = croppedImg; + this.draw(); // Redraw the profile badge + this.drawSpeakerBadge(); // Redraw the new speaker badge + }; + croppedImg.src = croppedImageData; + // ==================== MODIFICATION END ==================== - // Destroy the cropper instance + this.open = false; this.cropper.destroy(); this.cropper = null; }