You've already forked collage-maker
							
							Implement selecting template for collage #14
							
								
								
									
										6
									
								
								main.go
									
									
									
									
									
								
							
							
						
						
									
										6
									
								
								main.go
									
									
									
									
									
								
							| @@ -53,7 +53,10 @@ func main() { | ||||
|  | ||||
| 	if localAssets { | ||||
| 		httpFileServer := http.FileServer(http.Dir("web")) | ||||
| 		http.Handle("/", httpFileServer) | ||||
| 		http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { | ||||
| 			w.Header().Add("Cache-Control", "no-cache") | ||||
| 			httpFileServer.ServeHTTP(w, r) | ||||
| 		}) | ||||
| 	} else { | ||||
| 		fs, err := fs.Sub(webFS, "web") | ||||
|  | ||||
| @@ -123,7 +126,6 @@ func MakeCollage(req *collage.Request) (string, error) { | ||||
| 	out, err := os.Create(path.Join(collageDir, collageFile)) | ||||
| 	if err != nil { | ||||
| 		return "", fmt.Errorf("failed to create collage output file, err: %w", err) | ||||
| 		// slog.Error("failed to create collage output file", "error", err) | ||||
| 	} | ||||
| 	if err := collage.Make(req, imagesDirFs, out); err != nil { | ||||
| 		return "", fmt.Errorf("failed to make collage, err: %w", err) | ||||
|   | ||||
							
								
								
									
										104
									
								
								web/index.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										104
									
								
								web/index.css
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,104 @@ | ||||
| .container { | ||||
|     display: flex; | ||||
|     background-color: lightyellow; | ||||
|     height: calc(100vh - 20px); | ||||
| } | ||||
| .controls { | ||||
|     background-color: lightgrey; | ||||
|     display: flex; | ||||
|     align-items: center; | ||||
|     justify-content: space-around; | ||||
|     flex-direction: column; | ||||
|     flex: 25%; | ||||
| } | ||||
| .imagebox { | ||||
|     padding: 2rem; | ||||
|     flex: 75%; | ||||
| } | ||||
|  | ||||
| .image-surface { | ||||
|     overflow: hidden; | ||||
|     margin: auto; | ||||
|     border: 1px solid; | ||||
|     height: 100%; | ||||
|     width: auto; | ||||
|     --collage-ap: 110 / 85; | ||||
|     aspect-ratio: var(--collage-ap); | ||||
| } | ||||
| .showbuton { | ||||
|     font-size: 2rem; | ||||
| } | ||||
|  | ||||
| .templates { | ||||
|     display: flex; | ||||
|     flex-wrap: wrap; | ||||
|      gap: 1rem; | ||||
| } | ||||
|  | ||||
| .templates li { | ||||
|     list-style-type: none; | ||||
| } | ||||
|  | ||||
| #page_size_selector { | ||||
|     width: 100%; | ||||
| } | ||||
|  | ||||
| .template { | ||||
|     width: 100px; | ||||
|     height: 100px; | ||||
| } | ||||
|  | ||||
| .template div { | ||||
|     border: 1px solid; | ||||
| } | ||||
|  | ||||
| .single div { | ||||
|     width: 100%; | ||||
|     height: 100%; | ||||
| } | ||||
|  | ||||
| .one-two { | ||||
|     display: grid; | ||||
|     grid-template-areas:  | ||||
|     "one two" | ||||
|     "one three"; | ||||
| } | ||||
| .one-two .img1{ | ||||
|     grid-area: one; | ||||
| } | ||||
|  | ||||
| .half-leftright { | ||||
|     display:flex; | ||||
| } | ||||
|  | ||||
| .half-leftright .img { | ||||
|     flex: 50%; | ||||
| } | ||||
|  | ||||
| .half-topbottom .img { | ||||
|     width: 100%; | ||||
|     height: 50%; | ||||
| } | ||||
|  | ||||
| .two-one-two-leftright { | ||||
|     display: grid; | ||||
|     grid-template-areas:  | ||||
|     "one two two three" | ||||
|     "four two two five"; | ||||
| } | ||||
| .two-one-two-leftright .img2 { | ||||
|     grid-area: two; | ||||
| } | ||||
|  | ||||
| .two-one-two-topbottom { | ||||
|     display: grid; | ||||
|     grid-template-areas:  | ||||
|     "one two" | ||||
|     "three three" | ||||
|     "three three" | ||||
|     "four five" | ||||
| } | ||||
|  | ||||
| .two-one-two-topbottom .img3 { | ||||
|     grid-area: three; | ||||
| } | ||||
							
								
								
									
										136
									
								
								web/index.html
									
									
									
									
									
								
							
							
						
						
									
										136
									
								
								web/index.html
									
									
									
									
									
								
							| @@ -4,85 +4,85 @@ | ||||
|         <link rel="stylesheet" href="croppie.css" /> | ||||
|         <link rel="icon" href="data:;base64,iVBORw0KGgo=" /> | ||||
|         <script src="http://localhost:35729/livereload.js"></script> | ||||
|         <script src="croppie.js"></script> | ||||
|         <script src="index.js"></script> | ||||
|         <script src="croppie.js" defer></script> | ||||
|         <script src="index.js" defer></script> | ||||
|         <link rel="stylesheet" href="index.css" /> | ||||
|         <!-- | ||||
|             width: 3264px; | ||||
|             height: 4224px; | ||||
|             width: 8.5in; | ||||
|             height: 11in; | ||||
|         --> | ||||
|         <style> | ||||
|             .image-surface { | ||||
|                 overflow: hidden; | ||||
|                 margin: auto; | ||||
|                 background-color: lightgreen; | ||||
|             } | ||||
|             .imagebox { | ||||
|                 grid-area: image; | ||||
|                 display:flex; | ||||
|                 align-items: center; | ||||
|                 justify-content: center; | ||||
|                 padding: 50px; | ||||
|                 flex: 70%; | ||||
|             } | ||||
|             .container { | ||||
|                 display: flex; | ||||
|                 background-color: lightyellow; | ||||
|                 height: calc(100vh - 20px); | ||||
|             } | ||||
|             .controls { | ||||
|                 background-color: lightgrey; | ||||
|                 display: flex; | ||||
|                 grid-area: controls; | ||||
|                 align-items: center; | ||||
|                 justify-content: center; | ||||
|                 flex: 30%; | ||||
|             } | ||||
|             .showbuton { | ||||
|                 font-size: 2rem; | ||||
|             } | ||||
|             .letter-portrait { | ||||
|                 height: 100%; | ||||
|                 aspect-ratio: 85 / 110; | ||||
|             } | ||||
|             .letter-portrait .collage-img { | ||||
|                 height: 50%; | ||||
|             } | ||||
|             .letter-landscape-2 { | ||||
|                 display:flex; | ||||
|                 // width: 80vh; | ||||
|                 height: 100%; | ||||
|                 // margin: auto; | ||||
|                 aspect-ratio: 110 / 85; | ||||
|                 // aspect-ratio: 7 / 5; | ||||
|                 gap: 1rem; | ||||
|             } | ||||
|             .letter-landscape-2 .img1 { | ||||
|                 flex: 60%; | ||||
|             } | ||||
|             .letter-landscape-2 .img2 { | ||||
|                 flex: 40%; | ||||
|             } | ||||
|         </style> | ||||
|     </head> | ||||
|     <body onload="main()"> | ||||
|     <body> | ||||
|         <div class="container"> | ||||
|             <div class="controls"> | ||||
|                 <div> | ||||
|                     <button class="showbuton" onClick="snap()">Snap Collage</button> | ||||
|                     <p><a href="" target="_blank" id="collage-url"></a></p> | ||||
|                 </div> | ||||
|  | ||||
|  | ||||
|                 <label> | ||||
|                     <span>Paper size</span> | ||||
|                     <select id="page_size_selector" size=8> | ||||
| 
					
					balki marked this conversation as resolved
					
						
						
							Outdated
						
					
				 | ||||
|                         <option value="letter-portrait">Letter (Portrait)</option> | ||||
|                         <option selected value="letter-landscape">Letter (Landscape)</option> | ||||
|                         <option value="fiveseven-portrait">5 × 7 (Portrait)</option> | ||||
|                         <option value="fiveseven-landscape">7 × 5 (Landscape)</option> | ||||
|                         <option value="foursix-portrait">4 × 6 (Portrait)</option> | ||||
|                         <option value="foursix-landscape">4 × 6 (Landscape)</option> | ||||
|                     </select> | ||||
|                 </label> | ||||
|  | ||||
|  | ||||
|                 <ul class="templates"> | ||||
|                     <li> | ||||
|                         <div id="default_template" class="template single" data-collage-template="single"> | ||||
|                             <div class="img img1"></div> | ||||
| 
					
					balki marked this conversation as resolved
					
						
						
							Outdated
						
					
				 
				
					
						balki
						commented  Remove empty line inside div Remove empty line inside div | ||||
|                         </div> | ||||
|                     </li> | ||||
|                     <li> | ||||
|                         <div class="template one-two" data-collage-template="one-two"> | ||||
|                             <div class="img img1"></div> | ||||
|                             <div class="img img2"></div> | ||||
|                             <div class="img img3"></div> | ||||
|                         </div> | ||||
|                     </li> | ||||
|                     <li> | ||||
|                         <div class="template half-leftright" data-collage-template="half-leftright"> | ||||
|                             <div class="img img1"></div> | ||||
|                             <div class="img img2"></div> | ||||
|                         </div> | ||||
|                     </li> | ||||
|                     <li> | ||||
|                         <div class="template half-topbottom" data-collage-template="half-topbottom"> | ||||
|                             <div class="img img1"></div> | ||||
|                             <div class="img img2"></div> | ||||
|                         </div> | ||||
|                     </li> | ||||
|                     <li> | ||||
|                         <div class="template two-one-two-leftright" data-collage-template="two-one-two-leftright"> | ||||
|                             <div class="img img1"></div> | ||||
|                             <div class="img img2"></div> | ||||
|                             <div class="img img3"></div> | ||||
|                             <div class="img img4"></div> | ||||
|                             <div class="img img5"></div> | ||||
|                         </div> | ||||
|                     </li> | ||||
|                     <li> | ||||
|                         <div class="template two-one-two-topbottom" data-collage-template="two-one-two-topbottom"> | ||||
|                             <div class="img img1"></div> | ||||
|                             <div class="img img2"></div> | ||||
|                             <div class="img img3"></div> | ||||
|                             <div class="img img4"></div> | ||||
|                             <div class="img img5"></div> | ||||
|                         </div> | ||||
|                     </li> | ||||
|                 </ul> | ||||
|                 <button id="snapper" class="showbuton">Snap Collage</button> | ||||
|                 <p><a href="" target="_blank" id="collage-url"></a></p> | ||||
|  | ||||
|  | ||||
|             </div> | ||||
|             <div class="imagebox"> | ||||
|             <div id="collage" class="image-surface letter-landscape-2"> | ||||
|                 <div class="collage-img img1" data-collage-image-url="images/img1.jpg"> | ||||
|                     <!-- <img src="img1.jpg"> --> | ||||
|                 </div> | ||||
|                 <div class="collage-img img2" data-collage-image-url="images/img2.jpg"> | ||||
|                     <!-- <img src="img2.jpg"> --> | ||||
|                 </div> | ||||
|             </div> | ||||
|                 <div id="collage" class="image-surface"></div> | ||||
|             </div> | ||||
|         </div> | ||||
|     </body> | ||||
|   | ||||
							
								
								
									
										148
									
								
								web/index.js
									
									
									
									
									
								
							
							
						
						
									
										148
									
								
								web/index.js
									
									
									
									
									
								
							| @@ -1,10 +1,90 @@ | ||||
| "use strict"; | ||||
|  | ||||
| function main() { | ||||
|     initCollage("collage") | ||||
| const pageSizes = { | ||||
|     "letter-portrait" : { | ||||
|         "ap": "85 / 110", | ||||
|         "width": 3264, | ||||
|         "height": 4224, | ||||
|     }, | ||||
|     "letter-landscape" : { | ||||
|         "ap": "110 / 85", | ||||
|         "width": 4224, | ||||
|         "height": 3264, | ||||
|     }, | ||||
|     "fiveseven-portrait" : { | ||||
|         "ap": "5 / 7", | ||||
|         "width": 2250, | ||||
|         "height": 3150, | ||||
|     }, | ||||
|     "fiveseven-landscape" : { | ||||
|         "ap": "7 / 5", | ||||
|         "width": 3150, | ||||
|         "height": 2250, | ||||
|     }, | ||||
|     "foursix-portrait" : { | ||||
|         "ap": "4 / 6", | ||||
|         "width": 1800, | ||||
|         "height": 2700, | ||||
|     }, | ||||
|     "foursix-landscape" : { | ||||
|         "ap": "6 / 4", | ||||
|         "width": 2700, | ||||
|         "height": 1800, | ||||
|     }, | ||||
| } | ||||
|  | ||||
| // elements | ||||
|  | ||||
| /** @type {HTMLButtonElement} */ | ||||
| let snapButton | ||||
|  | ||||
| /** @type {HTMLDivElement} */ | ||||
| let collageDiv | ||||
|  | ||||
| /** @type {HTMLSelectElement} */ | ||||
| let pageSizeSelect | ||||
|  | ||||
| /** @type {HTMLAnchorElement} */ | ||||
| let collageUrlA | ||||
|  | ||||
| // collage state | ||||
|  | ||||
| let crops = []; | ||||
| let pageSize = "letter-landscape"; | ||||
| const imageUrls = [ | ||||
|     , // images start with index 1 | ||||
|     "images/img1.jpg", | ||||
|     "images/img2.jpg", | ||||
|     "images/img3.jpg", | ||||
|     "images/img4.jpg", | ||||
|     "images/img5.jpg", | ||||
|     "images/img6.jpg", | ||||
|     "images/img7.jpg", | ||||
| ] | ||||
|  | ||||
|  | ||||
| function main() { | ||||
|     snapButton = document.getElementById("snapper") | ||||
|     collageDiv = document.getElementById("collage") | ||||
|     pageSizeSelect = document.getElementById("page_size_selector") | ||||
|     collageUrlA = document.getElementById("collage-url") | ||||
|  | ||||
|     snapButton.onclick = () => snap() | ||||
|     pageSizeSelect.onchange  = () => pageSizeChange() | ||||
|  | ||||
|     for(const tmpl of document.getElementsByClassName("template")) { | ||||
|         tmpl.onclick = () => applyTemplate(tmpl) | ||||
|     } | ||||
|  | ||||
|     applyTemplate(document.getElementById("default_template")) | ||||
| } | ||||
|  | ||||
| /**  | ||||
|  * @param {HTMLDivElement} elem  | ||||
|  * @param {string} imgUrl | ||||
|  */ | ||||
| function makeCroppieElem(elem, imgUrl) { | ||||
|     cpie = new Croppie(elem, { | ||||
|     const cpie = new Croppie(elem, { | ||||
|         viewport: { | ||||
|             width: elem.clientWidth, | ||||
|             height: elem.clientHeight, | ||||
| @@ -18,18 +98,16 @@ function makeCroppieElem(elem, imgUrl) { | ||||
|     }); | ||||
|  | ||||
|     return cpie | ||||
|  | ||||
| } | ||||
|  | ||||
| // collage state | ||||
|  | ||||
| var collageDivId; | ||||
| var crops = []; | ||||
| function initCollage() { | ||||
|     for(const cpie of crops) { | ||||
|         cpie.destroy() | ||||
|     } | ||||
|     crops = [] | ||||
|  | ||||
| function initCollage(divId) { | ||||
|     collageDivId = divId | ||||
|     const collageDiv = document.getElementById(collageDivId) | ||||
|     for(elem of collageDiv.getElementsByClassName("collage-img")) { | ||||
|     for(const elem of collageDiv.getElementsByClassName("img")) { | ||||
|         const cpie = makeCroppieElem(elem, elem.dataset.collageImageUrl) | ||||
|         const lastLen = crops.push(cpie) | ||||
|         elem.dataset.collageCropieIndex = lastLen - 1 | ||||
| @@ -56,15 +134,14 @@ async function makeCollage(req) { | ||||
| } | ||||
|  | ||||
| function snap() { | ||||
|     const collageDiv = document.getElementById(collageDivId) | ||||
|     col = collageDiv.offsetLeft; | ||||
|     cot = collageDiv.offsetTop; | ||||
|     const col = collageDiv.offsetLeft; | ||||
|     const cot = collageDiv.offsetTop; | ||||
|     console.log("----------------------") | ||||
|     req = { | ||||
|     const req = { | ||||
|         background_image: "", | ||||
|         aspect: { | ||||
|             width: 528 * 4 * 2, | ||||
|             height: 816 * 4, | ||||
|             width: pageSizes[pageSize]["width"], | ||||
|             height: pageSizes[pageSize]["height"], | ||||
|         }, | ||||
|         dimension: { | ||||
|             width: collageDiv.clientWidth, | ||||
| @@ -73,7 +150,7 @@ function snap() { | ||||
|         photos: [], | ||||
|     }; | ||||
|  | ||||
|     for(elem of collageDiv.getElementsByClassName("collage-img")) { | ||||
|     for(const elem of collageDiv.getElementsByClassName("img")) { | ||||
|         const cpie = crops[elem.dataset.collageCropieIndex] | ||||
|         // console.log(cpie.get().points) | ||||
|         // console.log(elem.offsetLeft - col) | ||||
| @@ -111,10 +188,39 @@ function snap() { | ||||
|  | ||||
|     console.log(JSON.stringify(req)); | ||||
|     (async () => { | ||||
|         collagFile = await makeCollage(req) | ||||
|         // const collageUrlA = document.createElement("a"); | ||||
|         const collageUrlA = document.getElementById("collage-url"); | ||||
|         const collagFile = await makeCollage(req) | ||||
|         collageUrlA.href = `collages/${collagFile}`; | ||||
|         collageUrlA.text = `${collagFile} generated`; | ||||
|     })(); | ||||
| } | ||||
|  | ||||
| function pageSizeChange() { | ||||
|     collageDiv.style.setProperty('--collage-ap', pageSizes[pageSizeSelect.value]["ap"]) | ||||
|     pageSize = pageSizeSelect.value | ||||
|     initCollage() | ||||
| } | ||||
|  | ||||
| /**  | ||||
|  * @param {HTMLDivElement} templateDiv  | ||||
|  */ | ||||
| function applyTemplate(templateDiv) { | ||||
|     /** @type {HTMLDivElement} */ | ||||
|     const templateClone = templateDiv.cloneNode(true) | ||||
|     for (const index in imageUrls) { | ||||
|         const url = imageUrls[index] | ||||
|         const imgClass = `img${index}` | ||||
|  | ||||
|         const [imgDiv] = templateClone.getElementsByClassName(imgClass) | ||||
|         if(imgDiv === undefined) { | ||||
|             break; | ||||
|         } | ||||
|         imgDiv.dataset.collageImageUrl = url; | ||||
|     } | ||||
|     collageDiv.replaceChildren(...templateClone.children) | ||||
|     collageDiv.classList.remove(collageDiv.dataset.collageTemplate) | ||||
|     collageDiv.classList.add(templateDiv.dataset.collageTemplate) | ||||
|     collageDiv.dataset.collageTemplate = templateDiv.dataset.collageTemplate | ||||
|     initCollage() | ||||
| } | ||||
|  | ||||
| main() | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	
remove onChange