I'm using photoswipe with disabled zoom, like suggested here, but also want to avoid very landscapish images to reach beneath the prev/next arrows. Is there an easy way to achieve this?
Just found a solution, by
1) giving "padding" to the .pswp__item, like so:
.pswp__item {
left: 50px;
right: 50px;
}
2) updating the horizontal viewport size before resize:
pswp.listen('beforeResize', function(){
pswp.viewportSize.x = pswp.viewportSize.x - 100;
);
I can't comment on #johjoh's answer, so I'm going to copy it here and add the 3rd step required to get this working if you are using PhotoSwipe's getThumbBoundsFn.
1) giving "padding" to the .pswp__item, like so:
.pswp__item {
left: 50px;
right: 50px;
}
2) updating the horizontal viewport size before resize:
pswp.listen('beforeResize', function(){
pswp.viewportSize.x = pswp.viewportSize.x - 100;
);
3) Ensuring the getThumbBoundsFn properly calculates the x value by subtracting one side (50px in this example) from your calculated value:
bounds = {
x: {x} - 50,
y: ...,
w: ...,
}
Related
I'm using VictoryCharts, specifically the VictoryLegend component to render the legend for my chart. According to the docs it sounds like the only options for positioning the legend are absolute x and y coordinates. I'm trying to position the legend relatively, for example "at the bottom in the middle". This is the desired appearance:
Because the series labels in my legend are internationalized, the number of characters and thus the legend's width changes based on locale, so it isn't an option to hard-code an x coordinate to center the legend. I would also prefer not to have to calculate the y coordinate based on the height of my chart. Is there any way to relatively position the VictoryLegend below the chart and horizontally centered?
According to the maintainer in a Gitter conversation, it appears this is not possible:
This is possible, but there's nothing entirely built-in with Victory charts to do it. The library has an amazing amount of flexibility but a terrible dearth of sensible defaults.
To begin, you first have to backfill basic chart responsiveness as outlined here:
https://github.com/FormidableLabs/victory/issues/396#issuecomment-773791721
Then you can use the same boundingRect width/height to position the legend as well:
https://codesandbox.io/s/loving-fog-f3ed9d?file=/index.js
Or the relevant code pieces here:
const Chart = () => {
//NOTE victory charts don't automatically resize width 🤦♂️ yet - https://github.com/FormidableLabs/victory/issues/396
const [boundingRect, setBoundingRect] = useState({ width: 0, height: 0 });
const containerRef = useCallback((node) => {
if (node !== null) {
setBoundingRect(node.getBoundingClientRect());
}
}, []);
//...
return (
<div ref={containerRef} style={{ width: "90vw", height: "90vh" }}>
<VictoryChart
domainPadding={30}
theme={VictoryTheme.material}
height={boundingRect.width * 0.9}
width={boundingRect.width}
>
<VictoryBar
data={chartData}
cornerRadius={2}
style={{ data: { fill: ({ datum }) => datum.fill } }}
/>
<VictoryLegend
data={legendData}
centerTitle
gutter={20}
itemsPerRow={2}
orientation="horizontal"
rowGutter={{ top: 0, bottom: -10 }}
style={{ title: { fontSize: 20 } }}
titleOrientation="bottom"
x={50}
y={boundingRect.width * 0.81}
/>
</VictoryChart>
</div>
);
};
I've been trying to using jQuery resizable to resize an element in a container that is scrollable. I need to be able to make the element larger than what fits in the viewport, so therefor the page must scroll during the resize. How do I do that?
Note that the element is also draggable but not by the same handle (I'm not sure if that will affect the solution?)
When I've tried I get an issue with the handle which doesn't follow the mouse when I scroll the page.
First when I resized the element and drags the mouse down, the page didn't scroll. so therefor I've added the following (which might not be correct) on the resize event of the resizable element to scroll when the handle gets close to the upper or lower border:
resize: (event, ui) => {
var container = $(".container");
var pos = ui.originalPosition.top + ui.size.height;
var currentH = container.outerHeight() + container.scrollTop();
if (pos+20 >= currentH) {
container.scrollTop(pos + 20 - container.outerHeight());
}
if (pos-20 <= container.scrollTop()) {
container.scrollTop(pos-20);
}
}
this makes the page scroll but, then I get the problem:
That the handle no longer follow the mouse. And the longer I scroll the longer from the cursor the handle is. I've recreated this issue here based on TJ VanTolls fiddle http://jsfiddle.net/tj_vantoll/YwMXS/:
$('#inner').resizable({
containment: '#outer',
handles: 'all'
});
body { padding: 20px; }
p { line-height: 1.5; margin-bottom: 20px; }
#outer, #inner {
border: 1px solid black;
}
#outer {
width: 400px;
height: 300px;
overflow-y: scroll;
}
#inner {
height: 200px;
width: 200px;
top: 50px;
left: 50px;
}
#content {
height: 2000px;
width: 200px;
}
<link href="http://code.jquery.com/ui/1.11.4/themes/smoothness/jquery-ui.css" rel="stylesheet" />
<script src="http://code.jquery.com/jquery-3.1.0.js"></script>
<script src="http://code.jquery.com/ui/1.11.4/jquery-ui.js"></script>
<p>
When scrolling during resize the handle does no longer follow the mouse.
To recreate: start resizing and during the resize scroll the parent.</p>
<div id="outer">
<div id="inner"></div>
<div id="content"></div>
</div>
So my Question is, do you know a way to fix my first problem without causing the second or if there is a way to fix the second issue?
Thanks in advance!
i know it's a bit late but here's what works for me, the issue is that your css is centering the element so you'll need to double the width and height of the resized elemnt to keep in sync with the mouse:
resize: function (event, ui) {
var newWidth = ui.originalSize.width + ((ui.size.width - ui.originalSize.width) * 2);
//restrict min size if you want
if (newWidth < 50) {
newWidth = 50;
}
var newHeight = ui.originalSize.height + ((ui.size.height - ui.originalSize.height) * 2);
//restrict min size if you want
if (newHeight < 50) {
newHeight = 50;
}
//constrain this to the immediate parent
var parent = $(this).closest(".my-container");
if (parent.length) {
$(this).width(newWidth).position({
of: parent,
my: "center center",
at: "center center"
});
$(this).height(newHeight).position({
of: parent,
my: "center center",
at: "center center"
});
}
}
I'm using http://photoswipe.com/ here: http://www.michelperezphoto.com/.
Trying to add padding or margin so that the image displayed in lightbox does not occupy the whole width and or height of screen...
Tried this:
.pswp__item {
margin: 5%;
}
But now the lightbox image is not centered ...its slightly offcenter to the right...
Any insight would be greatly appreciated...
Cheers.....
I have a border-radius and drop shadow applied to my images, using the margin technique above masked my images and didn't look good. I found a better solution:
.pswp__img {
transform: scale(0.9);
}
In case this helps someone, I got desired effect using this:
#media (min-width: 900px) {
.pswp__item {
margin: 5% 5% 5% 0%;
}
}
Now there are two options for lightbox. padding and paddingFn https://photoswipe.com/options/#padding, https://photoswipe.com/options/#paddingfn
For example
const lightbox = new PhotoSwipeLightbox({
// ...
paddingFn: (viewportSize, itemData, index) => {
return {
top: viewportSize.x > 600 ? 82 : 0,
bottom: viewportSize.x > 600 ? 100 : 0,
left: viewportSize.x < 600 ? 10 : 0,
right: viewportSize.x < 600 ? 10 : 0
}
}
})
I'm trying to nest an image in a div and make it draggable on the X axis within this div.
Here's a jsFiddle to illustrate my point
I'd like the blue box to stop dragging once the user reaches its left/right edges, he shouldn't be able to see any of the red wrapper anymore.
Imagine the blue box is a very wide image, I want to be able to drag it from its left side to its right side without exceeding its width. It means you can't drag it to the right when you reached its left edge, and you can't drag it to the left when you reached its right side.
In a nutshell, when you reach the edges of the image, you can't drag it any more.
How can I set that kind of behavior ?
I tried playing with containment but I couldn't achieve what I wanted.
Thanks for your help.
HTML :
<div id="wrapper">
<p id="timeline"><img src="" alt="Timeline" width="2000" height="400"/></p>
</div>
CSS :
#wrapper {
width: 800px;
height: 400px;
background-color : red;
overflow: hidden;
cursor: w-resize;
}
#timeline {
width: 2000px;
height: 400px;
margin: 0 auto;
background-color: blue;
}
JS :
$("#timeline").draggable({
axis: "x"
});
You were correct to use the containment option but you'll want to pass in array of coordinates to constrain the draggable.
Per the jQuery UI docs the containment option can take an Array in format [x1, y1, x2, y2]. In your case the y values are irrelevant because you are already constraining the draggable to the x axis, so you can simply pass in 0.
For the x values 0 will work for x1 since the image is already starting on the right edge. For x2 you'll need to use:
(width of parent - width of image)
So
(800 - 2000) = -1200
Therefore you can pass the following in for the containment option:
containment: [-1200, 0, 0, 0]
Live Example - http://jsfiddle.net/LMXLj/
I am using jquery-ui and at some point I use the show and hide functions quite heavily to animate changing images coming in and out.
From some reason, after a few tries all of a sudden the controls on my page stop responding to clicks. After a bit of poking arround using firebug I discovered my page is filled with div's of the class ui-effects-wrapper.
I have no idea why this happens or how to stop it. If I remove these divs I can no longer see the images I've been animating.
Any ideas?
ui-effects-wrapper was added by jquery UI effect plugin.
Here is some code taken from jquery.effects.core.js:
// Wraps the element around a wrapper that copies position properties
createWrapper: function(element) {
// if the element is already wrapped, return it
if (element.parent().is('.ui-effects-wrapper')) {
return element.parent();
}
// wrap the element
var props = {
width: element.outerWidth(true),
height: element.outerHeight(true),
'float': element.css('float')
},
wrapper = $('<div></div>')
.addClass('ui-effects-wrapper')
.css({
fontSize: '100%',
background: 'transparent',
border: 'none',
margin: 0,
padding: 0
});
element.wrap(wrapper);
wrapper = element.parent(); //Hotfix for jQuery 1.4 since some change in wrap() seems to actually loose the reference to the wrapped element
// transfer positioning properties to the wrapper
if (element.css('position') == 'static') {
wrapper.css({ position: 'relative' });
element.css({ position: 'relative' });
} else {
$.extend(props, {
position: element.css('position'),
zIndex: element.css('z-index')
});
$.each(['top', 'left', 'bottom', 'right'], function(i, pos) {
props[pos] = element.css(pos);
if (isNaN(parseInt(props[pos], 10))) {
props[pos] = 'auto';
}
});
element.css({position: 'relative', top: 0, left: 0, right: 'auto', bottom: 'auto' });
}
return wrapper.css(props).show();
},
In one function, I had some code that toggled the visibility of two buttons and employed effects such as fadeTo and bounce. Occasionally there would be a wrapper remaining.
I tried adding this to my method, the idea being that it removes the wrappers 1.1 seconds after the effects have been queued up.
setTimeout('$(".ui-effects-wrapper").children().unwrap();', 1100);
This removes the stale wrappers, but there is the chance that it can also remove subsequent wrappers that are being used for effects.
I'd be very interested in seeing any improvements on this technique.