Compare commits
6 Commits
c8c98f7ec6
...
functions-
| Author | SHA1 | Date | |
|---|---|---|---|
| 1bf1e1b389 | |||
| 49f631f854 | |||
| b1a2dac5e4 | |||
| 44a52e0627 | |||
| 1459d4ab8d | |||
| ff88da0079 |
34
README.md
34
README.md
@@ -8,29 +8,29 @@ Funkcjonalności aplikacji koncentrują się na tworzeniu i modyfikacji kształt
|
|||||||
## Funkcje:
|
## Funkcje:
|
||||||
|
|
||||||
### Kształty
|
### Kształty
|
||||||
1. Tworzenie prostokąta
|
- [x] 1. Tworzenie prostokąta
|
||||||
2. Tworzenie rombu
|
- [x] 2. Tworzenie rombu
|
||||||
3. Tworzenie elipsy
|
- [x] 3. Tworzenie elipsy
|
||||||
|
|
||||||
### Akcje na kształtach
|
### Akcje na kształtach
|
||||||
4. Zmiana rozmiaru kształtów.
|
- [ ] 4. Zmiana rozmiaru kształtów.
|
||||||
5. Przeciągnięcie kzstałtu po planszy
|
- [x] 5. Przeciągnięcie kzstałtu po planszy
|
||||||
6. Usunięcie kształtu
|
- [x] 6. Usunięcie kształtu
|
||||||
7. Zaznaczenie kształtu
|
- [x] 7. Zaznaczenie kształtu
|
||||||
8. Kopiowanie kształtu
|
- [ ] 8. Kopiowanie kształtu
|
||||||
9. Wklejanie kształtu
|
- [ ] 9. Wklejanie kształtu
|
||||||
10. Zmiana kolorów kształtów
|
- [ ] 10. Zmiana kolorów kształtów
|
||||||
11. Połączenie kształtów (strzałka ->)
|
- [ ] 11. Połączenie kształtów (strzałka ->)
|
||||||
12. Usunięcie kształtów
|
- [ ] 12. Usunięcie kształtów
|
||||||
|
|
||||||
### Tekst
|
### Tekst
|
||||||
13. Dodanie tekstu
|
- [x] 13. Dodanie tekstu
|
||||||
14. Usunięcie tekstu
|
- [x] 14. Usunięcie tekstu
|
||||||
|
|
||||||
### Plansza i akcje na niej
|
### Plansza i akcje na niej
|
||||||
15. Przybliżenie planszy
|
- [x] 15. Przybliżenie planszy
|
||||||
16. Oddalenie planszy
|
- [x] 16. Oddalenie planszy
|
||||||
17. Przewijanie planszy
|
- [x] 17. Przewijanie planszy
|
||||||
|
|
||||||
*P.S. Jak będzie brakować funkcjonalności:*
|
*P.S. Jak będzie brakować funkcjonalności:*
|
||||||
- Obracanie kształtu
|
- Obracanie kształtu
|
||||||
|
|||||||
416
index.html
416
index.html
@@ -11,13 +11,18 @@
|
|||||||
|
|
||||||
<body>
|
<body>
|
||||||
<div class="toolbar">
|
<div class="toolbar">
|
||||||
<p>Kształty</p>
|
<p>Kształty - przeciągnij i upuść</p>
|
||||||
<div class="shape-wrapper toolbar-wrapper">
|
<div class="shape-wrapper toolbar-wrapper">
|
||||||
<div id="shape-rectangle" class="shape" data-type="rectangle"></div>
|
<div id="shape-rectangle" class="shape" data-type="rectangle"></div>
|
||||||
<div id="shape-ellipse" class="shape" data-type="ellipse"></div>
|
<div id="shape-ellipse" class="shape" data-type="ellipse"></div>
|
||||||
<div id="shape-diamond" class="shape" data-type="diamond"></div>
|
<div id="shape-diamond" class="shape" data-type="diamond"></div>
|
||||||
<div id="shape-text" class="shape" data-type="text">Tekst</div>
|
<div id="shape-text" class="shape" data-type="text">Tekst</div>
|
||||||
</div>
|
</div>
|
||||||
|
<p>Zoom</p>
|
||||||
|
<div class="zoom-wrapper toolbar-wrapper">
|
||||||
|
<button id="zoom-in">+</button>
|
||||||
|
<button id="zoom-out">-</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="canvas-container">
|
<div class="canvas-container">
|
||||||
<div id="paper"></div>
|
<div id="paper"></div>
|
||||||
@@ -25,154 +30,273 @@
|
|||||||
|
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
|
||||||
<script src="https://code.jquery.com/ui/1.13.2/jquery-ui.min.js"></script>
|
<script src="https://code.jquery.com/ui/1.13.2/jquery-ui.min.js"></script>
|
||||||
<script src="https://cdn.jsdelivr.net/npm/@joint/core@4.0.1/dist/joint.js"></script>
|
<script src="joint.js"></script>
|
||||||
<script>
|
<script>
|
||||||
$(document).ready(function () {
|
let selectedElement = null;
|
||||||
//init paper - Start
|
let activeElementView = null;
|
||||||
const graph = new joint.dia.Graph();
|
|
||||||
const paper = new joint.dia.Paper({
|
|
||||||
el: $('#paper'),
|
|
||||||
model: graph,
|
|
||||||
width: window.innerWidth,
|
|
||||||
height: window.innerHeight,
|
|
||||||
gridSize: 20,
|
|
||||||
});
|
|
||||||
//init paper - END
|
|
||||||
|
|
||||||
//create shape - START
|
$(document).ready(function () {
|
||||||
function createRectangle(paperX, paperY) {
|
//init paper - Start
|
||||||
const rect = new joint.shapes.standard.Rectangle({
|
const graph = new joint.dia.Graph();
|
||||||
position: { x: paperX - 40, y: paperY - 24 },
|
const paper = new joint.dia.Paper({
|
||||||
size: { width: 80, height: 48 },
|
el: $('#paper'),
|
||||||
attrs: {
|
model: graph,
|
||||||
body: {
|
width: window.innerWidth,
|
||||||
fill: 'transparent',
|
height: window.innerHeight,
|
||||||
stroke: '#000000',
|
gridSize: 20,
|
||||||
strokeWidth: 1
|
|
||||||
},
|
|
||||||
label: {
|
|
||||||
text: ''
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
graph.addCell(rect);
|
|
||||||
}
|
|
||||||
|
|
||||||
function createDiamond(paperX, paperY) {
|
|
||||||
const rect = new joint.shapes.standard.Rectangle({
|
|
||||||
position: { x: paperX - 24, y: paperY - 24 },
|
|
||||||
size: { width: 48, height: 48 },
|
|
||||||
angle: 45,
|
|
||||||
attrs: {
|
|
||||||
body: {
|
|
||||||
fill: 'transparent',
|
|
||||||
stroke: '#000000',
|
|
||||||
strokeWidth: 1
|
|
||||||
},
|
|
||||||
label: {
|
|
||||||
text: ''
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
graph.addCell(rect);
|
|
||||||
}
|
|
||||||
|
|
||||||
function createEllipse(paperX, paperY) {
|
|
||||||
const rect = new joint.shapes.standard.Ellipse({
|
|
||||||
position: { x: paperX - 40, y: paperY - 24 },
|
|
||||||
size: { width: 80, height: 48 },
|
|
||||||
attrs: {
|
|
||||||
body: {
|
|
||||||
fill: 'transparent',
|
|
||||||
stroke: '#000000',
|
|
||||||
strokeWidth: 1
|
|
||||||
},
|
|
||||||
label: {
|
|
||||||
text: ''
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
graph.addCell(rect);
|
|
||||||
}
|
|
||||||
|
|
||||||
function createText(paperX, paperY) {
|
|
||||||
const textBlock = new joint.shapes.standard.TextBlock({
|
|
||||||
position: { x: paperX - 40, y: paperY - 24 },
|
|
||||||
size: { width: 80, height: 48 },
|
|
||||||
attrs: {
|
|
||||||
body: {
|
|
||||||
fill: 'transparent',
|
|
||||||
stroke: '#000000',
|
|
||||||
strokeWidth: 1,
|
|
||||||
strokeDasharray: '5,5'
|
|
||||||
},
|
|
||||||
label: {
|
|
||||||
text: 'Tekst...',
|
|
||||||
fill: '#000000'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
graph.addCell(textBlock);
|
|
||||||
}
|
|
||||||
//create shape - END
|
|
||||||
|
|
||||||
//init draggalble - START
|
|
||||||
$('.shape').draggable({
|
|
||||||
helper: function () {
|
|
||||||
const $clone = $(this).clone();
|
|
||||||
$clone.css({
|
|
||||||
opacity: 0.8,
|
|
||||||
cursor: 'grabbing',
|
|
||||||
borderColor: '#000',
|
|
||||||
color: '#000',
|
|
||||||
});
|
|
||||||
return $clone;
|
|
||||||
},
|
|
||||||
cursor: 'move',
|
|
||||||
revert: 'invalid',
|
|
||||||
appendTo: 'body',
|
|
||||||
zIndex: 1000
|
|
||||||
});
|
|
||||||
|
|
||||||
$('#paper').droppable({
|
|
||||||
accept: '.shape',
|
|
||||||
drop: function (event, ui) {
|
|
||||||
const shapeType = ui.helper.data('type');
|
|
||||||
|
|
||||||
const containerOffset = $(this).offset();
|
|
||||||
const x = event.pageX - containerOffset.left;
|
|
||||||
const y = event.pageY - containerOffset.top;
|
|
||||||
|
|
||||||
const scale = paper.scale();
|
|
||||||
const translate = paper.translate();
|
|
||||||
const paperX = (x - translate.tx) / scale.sx;
|
|
||||||
const paperY = (y - translate.ty) / scale.sy;
|
|
||||||
|
|
||||||
if (shapeType === 'rectangle') {
|
|
||||||
createRectangle(paperX, paperY);
|
|
||||||
} else if (shapeType === 'ellipse') {
|
|
||||||
createEllipse(paperX, paperY);
|
|
||||||
} else if (shapeType === 'diamond') {
|
|
||||||
createDiamond(paperX, paperY);
|
|
||||||
} else if (shapeType === 'text') {
|
|
||||||
createText(paperX, paperY);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
//init draggable - END
|
|
||||||
|
|
||||||
//add text to text block - START
|
|
||||||
paper.on('element:pointerdblclick', function (elementView) {
|
|
||||||
if (elementView.model.attributes.type === 'standard.TextBlock') {
|
|
||||||
const currentText = elementView.model.attr('label/text');
|
|
||||||
const newText = prompt('Edytuj tekst:', currentText);
|
|
||||||
if (newText != null) {
|
|
||||||
elementView.model.attr('label/text', newText);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
//add text to text block - END
|
|
||||||
});
|
});
|
||||||
|
//init paper - END
|
||||||
|
|
||||||
|
// obwódka i znaczek usuwanie
|
||||||
|
function createToolsView() {
|
||||||
|
return new joint.dia.ToolsView({
|
||||||
|
tools: [
|
||||||
|
new joint.elementTools.Boundary({
|
||||||
|
padding: 10,
|
||||||
|
}),
|
||||||
|
new joint.elementTools.Remove({
|
||||||
|
focusOpacity: 0.5,
|
||||||
|
})
|
||||||
|
]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
//create shape - START
|
||||||
|
function createRectangle(paperX, paperY) {
|
||||||
|
const rect = new joint.shapes.standard.Rectangle({
|
||||||
|
position: { x: paperX - 40, y: paperY - 24 },
|
||||||
|
size: { width: 80, height: 48 },
|
||||||
|
attrs: {
|
||||||
|
body: {
|
||||||
|
fill: 'transparent',
|
||||||
|
stroke: '#000000',
|
||||||
|
strokeWidth: 1
|
||||||
|
},
|
||||||
|
label: {
|
||||||
|
text: ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
graph.addCell(rect);
|
||||||
|
const elementView = rect.findView(paper);
|
||||||
|
elementView.addTools(createToolsView());
|
||||||
|
}
|
||||||
|
|
||||||
|
function createDiamond(paperX, paperY) {
|
||||||
|
const rect = new joint.shapes.standard.Rectangle({
|
||||||
|
position: { x: paperX - 24, y: paperY - 24 },
|
||||||
|
size: { width: 48, height: 48 },
|
||||||
|
angle: 45,
|
||||||
|
attrs: {
|
||||||
|
body: {
|
||||||
|
fill: 'transparent',
|
||||||
|
stroke: '#000000',
|
||||||
|
strokeWidth: 1
|
||||||
|
},
|
||||||
|
label: {
|
||||||
|
text: ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
graph.addCell(rect);
|
||||||
|
const elementView = rect.findView(paper);
|
||||||
|
elementView.addTools(createToolsView());
|
||||||
|
}
|
||||||
|
|
||||||
|
function createEllipse(paperX, paperY) {
|
||||||
|
const rect = new joint.shapes.standard.Ellipse({
|
||||||
|
position: { x: paperX - 40, y: paperY - 24 },
|
||||||
|
size: { width: 80, height: 48 },
|
||||||
|
attrs: {
|
||||||
|
body: {
|
||||||
|
fill: 'transparent',
|
||||||
|
stroke: '#000000',
|
||||||
|
strokeWidth: 1
|
||||||
|
},
|
||||||
|
label: {
|
||||||
|
text: ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
graph.addCell(rect);
|
||||||
|
const elementView = rect.findView(paper);
|
||||||
|
elementView.addTools(createToolsView());
|
||||||
|
}
|
||||||
|
|
||||||
|
function createText(paperX, paperY) {
|
||||||
|
const textBlock = new joint.shapes.standard.TextBlock({
|
||||||
|
position: { x: paperX - 40, y: paperY - 24 },
|
||||||
|
size: { width: 80, height: 48 },
|
||||||
|
attrs: {
|
||||||
|
body: {
|
||||||
|
fill: 'transparent',
|
||||||
|
stroke: '#000000',
|
||||||
|
strokeWidth: 1,
|
||||||
|
strokeDasharray: '5,5'
|
||||||
|
},
|
||||||
|
label: {
|
||||||
|
text: 'Tekst...',
|
||||||
|
fill: '#000000'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
graph.addCell(textBlock);
|
||||||
|
const elementView = textBlock.findView(paper);
|
||||||
|
elementView.addTools(createToolsView());
|
||||||
|
}
|
||||||
|
//create shape - END
|
||||||
|
|
||||||
|
//init draggalble - START
|
||||||
|
$('.shape').draggable({
|
||||||
|
helper: function () {
|
||||||
|
const $clone = $(this).clone();
|
||||||
|
$clone.css({
|
||||||
|
opacity: 0.8,
|
||||||
|
cursor: 'grabbing',
|
||||||
|
borderColor: '#000',
|
||||||
|
color: '#000',
|
||||||
|
});
|
||||||
|
return $clone;
|
||||||
|
},
|
||||||
|
cursor: 'move',
|
||||||
|
revert: 'invalid',
|
||||||
|
appendTo: 'body',
|
||||||
|
zIndex: 1000
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#paper').droppable({
|
||||||
|
accept: '.shape',
|
||||||
|
drop: function (event, ui) {
|
||||||
|
const shapeType = ui.helper.data('type');
|
||||||
|
|
||||||
|
const containerOffset = $(this).offset();
|
||||||
|
const x = event.pageX - containerOffset.left;
|
||||||
|
const y = event.pageY - containerOffset.top;
|
||||||
|
|
||||||
|
const scale = paper.scale();
|
||||||
|
const translate = paper.translate();
|
||||||
|
const paperX = (x - translate.tx) / scale.sx;
|
||||||
|
const paperY = (y - translate.ty) / scale.sy;
|
||||||
|
|
||||||
|
activeElementView = null;
|
||||||
|
selectedElement = null;
|
||||||
|
|
||||||
|
if (shapeType === 'rectangle') {
|
||||||
|
createRectangle(paperX, paperY);
|
||||||
|
} else if (shapeType === 'ellipse') {
|
||||||
|
createEllipse(paperX, paperY);
|
||||||
|
} else if (shapeType === 'diamond') {
|
||||||
|
createDiamond(paperX, paperY);
|
||||||
|
} else if (shapeType === 'text') {
|
||||||
|
createText(paperX, paperY);
|
||||||
|
}
|
||||||
|
const cells = graph.getCells();
|
||||||
|
if (cells.length > 0) {
|
||||||
|
const lastCell = cells[cells.length - 1];
|
||||||
|
const lastView = lastCell.findView(paper);
|
||||||
|
if (lastView && typeof lastView.hideTools === 'function') {
|
||||||
|
lastView.hideTools();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
//init draggable - END
|
||||||
|
|
||||||
|
paper.on('element:pointerclick', function (elementView) {
|
||||||
|
if (activeElementView && activeElementView !== elementView) {
|
||||||
|
activeElementView.hideTools();
|
||||||
|
}
|
||||||
|
elementView.showTools();
|
||||||
|
activeElementView = elementView;
|
||||||
|
|
||||||
|
selectedElement = elementView.model;
|
||||||
|
});
|
||||||
|
|
||||||
|
let panStart = null;
|
||||||
|
paper.on('blank:pointerdown', function (evt) {
|
||||||
|
if (activeElementView) {
|
||||||
|
if (typeof activeElementView.hideTools === 'function') {
|
||||||
|
activeElementView.hideTools();
|
||||||
|
}
|
||||||
|
if (typeof activeElementView.unhighlight === 'function') {
|
||||||
|
activeElementView.unhighlight();
|
||||||
|
}
|
||||||
|
activeElementView = null;
|
||||||
|
}
|
||||||
|
selectedElement = null;
|
||||||
|
//ruszanie caloscia
|
||||||
|
panStart = {
|
||||||
|
x: evt.clientX,
|
||||||
|
y: evt.clientY,
|
||||||
|
tx: paper.translate().tx,
|
||||||
|
ty: paper.translate().ty
|
||||||
|
};
|
||||||
|
paper.$el.css('cursor', 'grabbing');
|
||||||
|
});
|
||||||
|
|
||||||
|
$(document).on('mousemove', function (evt) {
|
||||||
|
if (panStart) {
|
||||||
|
const dx = evt.clientX - panStart.x;
|
||||||
|
const dy = evt.clientY - panStart.y;
|
||||||
|
paper.translate(panStart.tx + dx, panStart.ty + dy);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$(document).on('mouseup', function () {
|
||||||
|
if (panStart) {
|
||||||
|
panStart = null;
|
||||||
|
paper.$el.css('cursor', 'default');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
//add text to text block - START
|
||||||
|
paper.on('element:pointerdblclick', function (elementView) {
|
||||||
|
if (elementView.model.attributes.type === 'standard.TextBlock') {
|
||||||
|
const currentText = elementView.model.attr('label/text');
|
||||||
|
const newText = prompt('Edytuj tekst:', currentText);
|
||||||
|
if (newText != null) {
|
||||||
|
elementView.model.attr('label/text', newText);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$(document).on('keydown', function (e) {
|
||||||
|
if (e.key === 'Delete' && selectedElement) {
|
||||||
|
// if (selectedElement.attributes.type === 'standard.TextBlock') {
|
||||||
|
selectedElement.remove();
|
||||||
|
selectedElement = null;
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
});
|
||||||
|
//add text to text block - END
|
||||||
|
|
||||||
|
// Zoom
|
||||||
|
const zoomStep = 0.2;
|
||||||
|
const minScale = 0.2;
|
||||||
|
const maxScale = 3.0;
|
||||||
|
|
||||||
|
$('#zoom-in').click(function () {
|
||||||
|
const currentScale = paper.scale().sx;
|
||||||
|
const newScale = Math.min(maxScale, currentScale + zoomStep);
|
||||||
|
paper.scale(newScale, newScale);
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#zoom-out').click(function () {
|
||||||
|
const currentScale = paper.scale().sx;
|
||||||
|
const newScale = Math.max(minScale, currentScale - zoomStep);
|
||||||
|
paper.scale(newScale, newScale);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Zoom za pomoca kolka myszy
|
||||||
|
paper.on('blank:mousewheel cell:mousewheel', function (evt, x, y, delta) {
|
||||||
|
evt.preventDefault();
|
||||||
|
const oldScale = paper.scale().sx;
|
||||||
|
const zoomFactor = 0.2;
|
||||||
|
let newScale = oldScale * (1 + delta * zoomFactor);
|
||||||
|
newScale = Math.max(minScale, Math.min(maxScale, newScale));
|
||||||
|
paper.scale(newScale, newScale, x, y);
|
||||||
|
});
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
|
|||||||
47
style.css
47
style.css
@@ -44,6 +44,7 @@
|
|||||||
.shape {
|
.shape {
|
||||||
background: transparent;
|
background: transparent;
|
||||||
border: 1px solid white;
|
border: 1px solid white;
|
||||||
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.toolbar {
|
.toolbar {
|
||||||
@@ -68,4 +69,48 @@
|
|||||||
.toolbar-wrapper {
|
.toolbar-wrapper {
|
||||||
padding-bottom: 30px;
|
padding-bottom: 30px;
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.zoom-wrapper {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 15px;
|
||||||
|
padding: 10px 20px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.zoom-wrapper button {
|
||||||
|
background: white;
|
||||||
|
color: #3498db;
|
||||||
|
border: none;
|
||||||
|
border-radius: 50%;
|
||||||
|
width: 50px;
|
||||||
|
height: 50px;
|
||||||
|
font-size: 24px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
cursor: pointer;
|
||||||
|
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.15);
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.zoom-wrapper button:hover {
|
||||||
|
background: #2980b9;
|
||||||
|
color: white;
|
||||||
|
transform: scale(1.1);
|
||||||
|
box-shadow: 0 6px 15px rgba(0, 0, 0, 0.25);
|
||||||
|
}
|
||||||
|
|
||||||
|
.zoom-wrapper button:active {
|
||||||
|
transform: scale(0.95);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Fajny efekt przy najechaniu */
|
||||||
|
.zoom-wrapper button i {
|
||||||
|
transition: transform 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.zoom-wrapper button:hover i {
|
||||||
|
transform: scale(1.2);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user