-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
0d9a447
commit 5de5f1d
Showing
15 changed files
with
506 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
root = true | ||
|
||
[*] | ||
charset = utf-8 | ||
end_of_line = lf | ||
insert_final_newline = true | ||
indent_style = space | ||
indent_size = 4 | ||
trim_trailing_whitespace = true | ||
|
||
[*.md] | ||
trim_trailing_whitespace = false |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
node_modules | ||
.vscode |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
MIT License | ||
Copyright (c) 2021 Michael Lefrancois | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
# Alpine Focal | ||
|
||
Add focal point alignment of images to your Alpine 3.x components with a custom directive. | ||
|
||
![GitHub](https://img.shields.io/github/license/lefrancois/alpine-focal?color=red&style=flat-square) | ||
![Build size Brotli](https://img.badgesize.io/lefrancois/alpine-focal/master/dist/cdn.min.js.svg?compression=gzip&style=flat-square&color=green) | ||
[![](https://data.jsdelivr.com/v1/package/npm/@lefrancois/alpine-focal/badge)](https://www.jsdelivr.com/package/npm/@lefrancois/alpine-focal) | ||
[![](https://img.shields.io/discord/492260310414262274.svg?color=7289da&label=lefrancois&logo=discord&style=flat-square)](https://discord.gg/fnBQBdVdSZ) | ||
[![](https://img.shields.io/twitter/follow/lefrancois?style=flat-square)](https://www.twitter.com/lefrancois) | ||
|
||
> This package only supports Alpine v3.x. | ||
## About | ||
|
||
This plugin adds a new `x-focal` directive to Alpine that allows to easliy align your images to keep focus on the selected part of the image. | ||
|
||
## Installation | ||
|
||
### CDN | ||
|
||
Include the following `<script>` tag in the `<head>` of your document, just before Alpine. | ||
|
||
```html | ||
<script | ||
src="https://cdn.jsdelivr.net/npm/@lefrancois/alpine-focal@1/dist/cdn.min.js" | ||
defer | ||
></script> | ||
``` | ||
|
||
### NPM | ||
|
||
```bash | ||
npm install @lefrancois/alpine-focal | ||
``` | ||
|
||
Add the `x-focal` directive to your project by registering the plugin with Alpine. | ||
|
||
```js | ||
import Alpine from "alpinejs"; | ||
import Focal from "@lefrancois/alpine-focal"; | ||
|
||
Alpine.plugin(Focal); | ||
|
||
window.Alpine = Alpine; | ||
window.Alpine.start(); | ||
``` | ||
|
||
## Usage | ||
|
||
Attach the `x-focal` directive on an image element and enter the point (unsing px or % informations) to keep in focus while containing the image. | ||
|
||
```html | ||
<div x-data> | ||
<img | ||
src="..." | ||
width="400px" | ||
height="600px" | ||
x-focal="10% 80%" | ||
> | ||
</img> | ||
</div> | ||
``` | ||
|
||
Optinally you can use set the third parameter to true (`x-focal="100px 100px true"`) to get a preview image where you can set the focal point with an easy click on the image. Note: Just copy and paste the value to the `x-focal` attribute of the image element in production. ;) This is just a helper for your development. | ||
|
||
## License | ||
|
||
Copyright (c) 2021 Michael Lefrancois | ||
|
||
Licensed under the MIT license, see [LICENSE.md](LICENSE.md) for details. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
import Focal from '../src/index' | ||
|
||
document.addEventListener('alpine:initializing', () => { | ||
window.Alpine.plugin(Focal) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
import Focal from '../src/index' | ||
|
||
export default Focal |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
(() => { | ||
// src/index.js | ||
function src_default(Alpine) { | ||
Alpine.directive("focal", (el, {expression}) => { | ||
const parts = expression.split(" "); | ||
let xOffset = parts[0] || "50%"; | ||
let yOffset = parts[1] || "50%"; | ||
let edit = parts[2] || false; | ||
if (edit) { | ||
el.style["object-fit"] = ""; | ||
el.onclick = (e) => { | ||
const rect = el.getBoundingClientRect(); | ||
const x = (e.clientX - rect.left) / rect.width; | ||
const y = (e.clientY - rect.top) / rect.height; | ||
const shiftCenterX = (rect.width / 2 - x * rect.width) / rect.width; | ||
const shiftCenterY = (rect.height / 2 - y * rect.height) / rect.height; | ||
xOffset = (x - shiftCenterX / 2) * 100; | ||
yOffset = (y - shiftCenterY / 2) * 100; | ||
if (xOffset > 100) | ||
xOffset = 100; | ||
if (xOffset < 0) | ||
xOffset = 0; | ||
if (yOffset > 100) | ||
yOffset = 100; | ||
if (yOffset < 0) | ||
yOffset = 0; | ||
xOffset = Math.round(xOffset); | ||
yOffset = Math.round(yOffset); | ||
const xPixelOffset = Math.round(xOffset / 100 * el.naturalWidth); | ||
const yPixelOffset = Math.round(yOffset / 100 * el.naturalHeight); | ||
el.style["object-fit"] = "cover"; | ||
el.style["object-position"] = `${xOffset}% ${yOffset}%`; | ||
alert(`Use ${xOffset}% ${yOffset}% or ${xPixelOffset}px ${yPixelOffset}px`); | ||
}; | ||
} else { | ||
if (xOffset.endsWith("x")) { | ||
xOffset = `${parseInt(xOffset) * 100 / el.naturalWidth}%`; | ||
} | ||
if (yOffset.endsWith("x")) { | ||
yOffset = `${parseInt(yOffset) * 100 / el.naturalHeight}%`; | ||
} | ||
el.style["object-fit"] = "cover"; | ||
el.style["object-position"] = `${xOffset} ${yOffset}`; | ||
} | ||
}); | ||
} | ||
|
||
// builds/cdn.js | ||
document.addEventListener("alpine:initializing", () => { | ||
window.Alpine.plugin(src_default); | ||
}); | ||
})(); |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
var __defProp = Object.defineProperty; | ||
var __markAsModule = (target) => __defProp(target, "__esModule", {value: true}); | ||
var __export = (target, all) => { | ||
for (var name in all) | ||
__defProp(target, name, {get: all[name], enumerable: true}); | ||
}; | ||
|
||
// builds/module.js | ||
__markAsModule(exports); | ||
__export(exports, { | ||
default: () => module_default | ||
}); | ||
|
||
// src/index.js | ||
function src_default(Alpine) { | ||
Alpine.directive("focal", (el, {expression}) => { | ||
const parts = expression.split(" "); | ||
let xOffset = parts[0] || "50%"; | ||
let yOffset = parts[1] || "50%"; | ||
let edit = parts[2] || false; | ||
if (edit) { | ||
el.style["object-fit"] = ""; | ||
el.onclick = (e) => { | ||
const rect = el.getBoundingClientRect(); | ||
const x = (e.clientX - rect.left) / rect.width; | ||
const y = (e.clientY - rect.top) / rect.height; | ||
const shiftCenterX = (rect.width / 2 - x * rect.width) / rect.width; | ||
const shiftCenterY = (rect.height / 2 - y * rect.height) / rect.height; | ||
xOffset = (x - shiftCenterX / 2) * 100; | ||
yOffset = (y - shiftCenterY / 2) * 100; | ||
if (xOffset > 100) | ||
xOffset = 100; | ||
if (xOffset < 0) | ||
xOffset = 0; | ||
if (yOffset > 100) | ||
yOffset = 100; | ||
if (yOffset < 0) | ||
yOffset = 0; | ||
xOffset = Math.round(xOffset); | ||
yOffset = Math.round(yOffset); | ||
const xPixelOffset = Math.round(xOffset / 100 * el.naturalWidth); | ||
const yPixelOffset = Math.round(yOffset / 100 * el.naturalHeight); | ||
el.style["object-fit"] = "cover"; | ||
el.style["object-position"] = `${xOffset}% ${yOffset}%`; | ||
alert(`Use ${xOffset}% ${yOffset}% or ${xPixelOffset}px ${yPixelOffset}px`); | ||
}; | ||
} else { | ||
if (xOffset.endsWith("x")) { | ||
xOffset = `${parseInt(xOffset) * 100 / el.naturalWidth}%`; | ||
} | ||
if (yOffset.endsWith("x")) { | ||
yOffset = `${parseInt(yOffset) * 100 / el.naturalHeight}%`; | ||
} | ||
el.style["object-fit"] = "cover"; | ||
el.style["object-position"] = `${xOffset} ${yOffset}`; | ||
} | ||
}); | ||
} | ||
|
||
// builds/module.js | ||
var module_default = src_default; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
// src/index.js | ||
function src_default(Alpine) { | ||
Alpine.directive("focal", (el, {expression}) => { | ||
const parts = expression.split(" "); | ||
let xOffset = parts[0] || "50%"; | ||
let yOffset = parts[1] || "50%"; | ||
let edit = parts[2] || false; | ||
if (edit) { | ||
el.style["object-fit"] = ""; | ||
el.onclick = (e) => { | ||
const rect = el.getBoundingClientRect(); | ||
const x = (e.clientX - rect.left) / rect.width; | ||
const y = (e.clientY - rect.top) / rect.height; | ||
const shiftCenterX = (rect.width / 2 - x * rect.width) / rect.width; | ||
const shiftCenterY = (rect.height / 2 - y * rect.height) / rect.height; | ||
xOffset = (x - shiftCenterX / 2) * 100; | ||
yOffset = (y - shiftCenterY / 2) * 100; | ||
if (xOffset > 100) | ||
xOffset = 100; | ||
if (xOffset < 0) | ||
xOffset = 0; | ||
if (yOffset > 100) | ||
yOffset = 100; | ||
if (yOffset < 0) | ||
yOffset = 0; | ||
xOffset = Math.round(xOffset); | ||
yOffset = Math.round(yOffset); | ||
const xPixelOffset = Math.round(xOffset / 100 * el.naturalWidth); | ||
const yPixelOffset = Math.round(yOffset / 100 * el.naturalHeight); | ||
el.style["object-fit"] = "cover"; | ||
el.style["object-position"] = `${xOffset}% ${yOffset}%`; | ||
alert(`Use ${xOffset}% ${yOffset}% or ${xPixelOffset}px ${yPixelOffset}px`); | ||
}; | ||
} else { | ||
if (xOffset.endsWith("x")) { | ||
xOffset = `${parseInt(xOffset) * 100 / el.naturalWidth}%`; | ||
} | ||
if (yOffset.endsWith("x")) { | ||
yOffset = `${parseInt(yOffset) * 100 / el.naturalHeight}%`; | ||
} | ||
el.style["object-fit"] = "cover"; | ||
el.style["object-position"] = `${xOffset} ${yOffset}`; | ||
} | ||
}); | ||
} | ||
|
||
// builds/module.js | ||
var module_default = src_default; | ||
export { | ||
module_default as default | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
<html> | ||
<head> | ||
<meta charset="UTF-8"> | ||
<meta http-equiv="X-UA-Compatible" content="IE=edge"> | ||
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||
<title>Alpine.js Focal</title> | ||
<script type="module"> | ||
import Focal from '../dist/module.esm.js' | ||
|
||
document.addEventListener('alpine:initializing', () => { | ||
window.Alpine.plugin(Focal) | ||
}) | ||
</script> | ||
<script defer src="https://unpkg.com/[email protected]/dist/cdn.min.js"></script> | ||
</head> | ||
<body> | ||
<img | ||
src="https://images.unsplash.com/photo-1542114904-3bc059596c5f?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=2070&q=80" | ||
width="400px" | ||
height="600px" | ||
x-focal="1656px 345px" | ||
x-data> | ||
</img> | ||
</body> | ||
</html> |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
{ | ||
"name": "@lefrancois/alpine-focal", | ||
"description": "Add focal point image alignment to your Alpine 3.x components with a custom directive.", | ||
"version": "1.0.0", | ||
"author": { | ||
"name": "Michael Lefrancois", | ||
"email": "[email protected]", | ||
"url": "https://www.lefrancois.de" | ||
}, | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/lefrancois/alpine-focal" | ||
}, | ||
"main": "dist/module.cjs.js", | ||
"module": "dist/module.esm.js", | ||
"devDependencies": { | ||
"brotli-size": "^4.0.0", | ||
"esbuild": "^0.8.39" | ||
}, | ||
"scripts": { | ||
"build": "node ./scripts/build.js", | ||
"watch": "node ./scripts/build.js --watch" | ||
} | ||
} |
Oops, something went wrong.