Matter.js i need always same movement ( on any canvas size) - matter.js

I need help. I have a player and I want jump the player in same diametric order. I wanted to fix this with getHeight with return ( innerHeight/100 * per ), but there's no improvement. Even worse, if the canvas size becomes bigger the player doesn't jump as high and if the window becomes smaller the player jumps higher! I dont want to callibrate in hard code way. I need responsive function!
"leave a comment before vote negative"
r.player.force = {
x: 0,
y: -(getHeight(0.03)),
};
Matter.Body.applyForce(r.player, { x: r.player.position.x, y: r.player.position.y }, r.player.force);
public getHeight(percente: number): number {
return this.reperH() / 100 * percente;
}
this.reperH = function () {
if ((window as any).innerHeight > (window as any).innerWidth / this.aspectRatio) {
return (window as any).innerWidth / this.aspectRatio;
} else {
return (window as any).innerHeight;
}
};
Full source : link

I don't know about a single function to do everything, but you can multiply the force by window.innerHeight or window.innerWidth:
var windowWidth = window.innerWidth;
var windowHeight = window.innerHeight;
var vw = windowWidth/100;
var vh = windowHeight/100;
var jumpForce = vh*-5;
var pushX = vw*0.1;
After that, you just apply jumpForce to the player when they jump and pushX to the player when they move (You will have to multiply it by -1 when the player is moving to the left). If you want it to look even more consistent, you can have jumpForce use vw instead of vh and make sure all of the objects created in the game use vw for positioning and scaling.
Whether you do use only vw or not, you will have to convert all your pixel values into vw or vh (depending on whether you're changing the x or y of the object), so it looks like this:
var object = Bodies.rectangle(vw*60, vw*40, vw*8, vw*5);

I figure that matter.js already have diametric scale with simple number inputs.
When i remove all getHeight and getWidth and put numbers everything start works fine again.
It is my solution for any platform to get percent always no matter for screen size.
My opinion : Matter.js looks like good solution.

Related

Adjust font size based on screen size of smartphone React native

Hey guys im using const {width,height} = Dimensions.get('window');
to adjust my font based on screen width size.
using like this....
fontSize:width/24
its looks good in iPhone and android device like 5.5 inch device but in my Galaxy s9 it looks horrible I want to set my font based on screen which can be adjust by itself..
how can I do it
Then the best option is to use vmax and vmin units.
vmin: 1/100th of the smallest side,
vmax: 1/100th of the largest side
take a look at it here
Use a responsive ilibrary like this that will handle things better.
react-native-size-matters
Eg:
import { scale, verticalScale, moderateScale } from 'react-native-size-matters';
const Component = props =>
<View style={{
width: scale(30),
height: verticalScale(50),
padding: moderateScale(5)
}}/>;
Thus things will look better in all devices. Use verticalScale for defining things relative to height of the device. scale can be used for normal things .. then there is a custom option moderateScale where u can manually define the scaling ratio as well.
For more details refer : Scaling React Native apps
PS: there are other options as well where u can manually define a custom class to get the PixelRatio and everything. but this is a straight forward approach.
Refer PixelRatio Approach
In order to get access to the device's pixel density and font scale, you can benefit from PixelRatio according to the docs.
As indicated in the docs, PixelRatio.get() provides you with the device pixel density:
var dynamic_fontSize = 20;
if(PixelRatio.get() === 1) { // mdpi Android devices
dynamic_fontSize = 12;
} else if(PixelRatio.get() === 1.5) { // hdpi Android devices
...
}
else { ...
Another idea is to make use of the layout size using roundToNearestPixel().
Let's imagine you want to adjust the size of an element to take over 98% of the screen’s width in dp and 10% of the screen’s height in dp:
export const widthPercentageToDP = widthPercent => {
const screenWidth = Dimensions.get('window').width;
// Convert string input to decimal number
const elemWidth = parseFloat(widthPercent);
return PixelRatio.roundToNearestPixel(screenWidth * elemWidth / 100);
};
export const heightPercentageToDP = heightPercent => {
const screenHeight = Dimensions.get('window').height;
// Convert string input to decimal number
const elemHeight = parseFloat(heightPercent);
return PixelRatio.roundToNearestPixel(screenHeight * elemHeight / 100);
};
This thread provides you with a clear example: https://stackoverflow.com/a/35074379/4687359

compute mouse position within video with object-fit:contain

I am trying to convert a mouse event to pixel coordinates within a video. By pixel coordinates, I mean coordinates relative to the original video resolution.
My video element has object-fit: contain, which means that the top left corner of the video is not necessarily located at position (0,0), as this picture shows:
If I click on the top-left corner of the white section in this video then I want to get (0,0), but in order to do this I need to discover the offset of the video content (white area) relative to the video element (black border).
How can I recover this offset?
I am already aware of width, height, videoWidth, and videoHeight, but these only let me account for the scaling, not the offset.
The offset can be deduced. I think this kind of code should do the trick:
if(videoHeight/height > videoWidth/width){
scale = videoHeight/height;
offsetX = (videoWidth - width*scale)/2;
offsetY = 0;
}
else{
scale = videoWidth/width;
offsetY = (videoHeight - height*scale)/2;
offsetX = 0;
}
I was also interested in getting the actual pixel positions from mouse or touch events when using object-fit, and this is the only result I found when searching. Although I suspect it is probably too late to be helpful to you, I thought I'd answer in case anybody else comes across this in future like I did.
Because I'm working on code with other people, I needed a robust solution that would work even if someone changed or removed the object-fit or object-property in the css
The approach that I took was:
Implement the cover, contain etc algorithms myself, just functions doing math, not dependent on the DOM
Use getComputedStyle to get the element's objectFit and objectPosition properties
Use .getBoundingClientRect() to get the DOM pixel size of the element
Pass the element's current objectFit, objectPosition, its DOM pixel size and it's natural pixel size to my function to figure out where the fitted rectangle sat within the element
You then have enough information to transform the event point to a pixel location
There's more code than would comfortably fit here, but getting the size of the fitted rectangle for cover or contain is something like:
if ( fitMode === 'cover' || fitMode === 'contain' ) {
const wr = parent.width / child.width
const hr = parent.height / child.height
const ratio = fitMode === 'cover' ? Math.max( wr, hr ) : Math.min( wr, hr )
const width = child.width * ratio
const height = child.height * ratio
const size = { width, height }
return size
}
// handle other object-fit modes here
Hopefully this gives others a rough idea of how to solve this problem themselves, alternately I have published the code at the link below, it supports all object-fit modes and it includes examples showing how to get the actual pixel point that was clicked:
https://github.com/nrkn/object-fit-math

Twitter bootstrap carousel with pictures that are not uniform

Let me start with i am sorry for the long post.
I'm attempting to use the bootstrap carousel and unfortunately the pictures i have been given are NOT uniform. for example some are 100x200, doe are 150x100, etc. The aspect ratios are different, letter vs landscape. Ive attempted a number of things, including the using the following helper function on load of each of my images in the Carousel:
function ScaleImage(srcwidth, srcheight, targetwidth, targetheight, fLetterBox) {
var result = { width: 0, height: 0, fScaleToTargetWidth: true };
if ((srcwidth <= 0) || (srcheight <= 0) || (targetwidth <= 0) || (targetheight <= 0)) {
return result;
}
// scale to the target width
var scaleX1 = targetwidth;
var scaleY1 = (srcheight * targetwidth) / srcwidth;
// scale to the target height
var scaleX2 = (srcwidth * targetheight) / srcheight;
var scaleY2 = targetheight;
// now figure out which one we should use
var fScaleOnWidth = (scaleX2 > targetwidth);
if (fScaleOnWidth) {
fScaleOnWidth = fLetterBox;
}
else {
fScaleOnWidth = !fLetterBox;
}
if (fScaleOnWidth) {
result.width = Math.floor(scaleX1);
result.height = Math.floor(scaleY1);
result.fScaleToTargetWidth = true;
}
else {
result.width = Math.floor(scaleX2);
result.height = Math.floor(scaleY2);
result.fScaleToTargetWidth = false;
}
result.targetleft = Math.floor((targetwidth - result.width) / 2);
result.targettop = Math.floor((targetheight - result.height) / 2);
return result;
}
function OnImageLoad(evt) {
var img = evt.currentTarget;
// what's the size of this image and it's parent
var w = $(img).prop('naturalWidth');
var h = $(img).prop('naturalHeight');
//var tw = $(img).parent().width();
//var th = $(img).parent().height();
var tw = $(img).parent().parent().parent().parent().width();
var th = $(img).parent().parent().parent().parent().height();
// compute the new size and offsets
var result = ScaleImage(w, h, tw, th, true);
// adjust the image coordinates and size
img.width = result.width;
img.height = result.height;
$(img).css("left", result.targetleft);
$(img).css("top", result.targettop);
}
and using the following for each of my images for the carousel
<img src="~/Images/Img1_Tall.jpg" alt="Tall" id="firstImage" onload="OnImageLoad(event);" />
and for the FIRST image in the carousel it works great, but each one after that they seem to just end up their natural size and are horizontally centered but are just against the top boarder of the carousel.
I've even changed the "onload" to pass the values of the length and width of the image but that didn't work either, in debug it seems only the first image kicks off the "onload" event.
the effect i am going for is if the ratio of the container is 3:4 and the ratio of the image is 1:2, the image stretch to meet the left and right edges and would center vertically and have letter box above and below, but the container does not change so that the navigation buttons of the carousel do not move. if the image is 2:1, the image would stretch to meet the top and bottom centered horizontally with letterboxes on the right and left, again keeping the navigation buttons unmoved.
any help would be appreciated... including:
what you are trying to do is crazy
do you want to do something like http://jsbin.com/zotelasa/1 . With that code I can get the active items w,h or any other variables you used in your code to run scale image. Because of parent.parent codes it applies to carousels main divs but you can set your own container.
The quick and dirty solution would be to resize the images using an image editor, and save the properly-sized images to a folder named eg carousel_images. Then whenever you get new content you simply run the image through your editor. With a carousel you're most likely dealing with a number of images in the several to dozens range and not hundreds or thousands.
A more complicated solution is explain to your image provider that you need everything one size. The images aren't going to look right if you're stretching and skewing them on the fly, and you can show them an image with the aspect ratios wrong to explain what you mean.
Finally, as a technical solution, I would try to find out why your image resizer is only being run on the first image. From the sound of it, other images just aren't being run through your function. I think that the technical solution should be a last resort in this case because, like I said, the end results are just not going to be as good. You should at a minimum, if possible, handle each image by hand to make sure the result is adequate.
...And the answer is a little long too...
• I assume that the width’s image’s parent is a constant, and while you don’t change the width’s viewport that must remain.
A-. Get the width’s image’s parent…
(Because the id attribute I took the grand parent’s parameter, that is (must be) the same than the parent’s one).
B-. With the below value deduce the height’s image’s parent, including the preferred ratio (in this case 16x9…
C-. … And with this, set the images’ parents height collection (all the elements with class=”item”).
D-. In order to conserve your carousel’s responsive characteristic, you must add the $F_getAdjustImagesParents function to the window resize event.
E-. Set the slide’s images position to absolute (Note: That must be via JQuery because if you do it in Css the bootstrap carousel will not display correctly. I did it with a new class for the images ('myCarouselImgs').
• Bootstrap carousel’s event 'slide.bs.carousel' and 'slid.bs.carousel'.
As you know, after the ‘click’ event, the slide.bs.carousel event is one of the firsts events that imply the change from the present slide to the next one; while the 'slid.bs.carousel' one is the end of the process.
F-. In the first one (slide.bs.carousel event), using the ‘relatedTarget’ variable of the Bootstrap’s plugin, the item’s id attribute and a item’s data attribute, get the number of the next item (ensure that these last ones -id attribute and data attribute- be present).
G-. In the second one, 'slid.bs.carousel', get the image’s size. For that you need to identify the implied image. I gave an id to each one. With this and the value obtained in previus step, it can do it.
H-. Well, now you already have the four values required for the ScaleImage function. You can call it…
I-. … And apply the result with some effect
var $parentImgW = ' '
var $parentImgH = ' ';
var $myCarousel = $('#myCarousel')
var $carouseItems = $('.item');
function $F_getAdjustImagesParents(){
$parentImgW = $myCarousel.width(); // A
$parentImgH = ($parentImgW*9)/16; // B
$carouseItems.height($parentImgH+'px').css('max-height',$parentImgH+'px'); //C
console.log('$parentImgW ====> '+$parentImgW);
console.log('$parentImgH ====> '+$parentImgH)
};
$F_getAdjustImagesParents();
$(window).on('resize',function(){ // D
$F_getAdjustImagesParents();
});
$('.myCarouselImgs').css('position','absolute'); // E
$myCarousel.on('slide.bs.carousel', function(event) {// The slide’s change process starts
var $slideNum = $("#"+event.relatedTarget.id).data('slide_num'); // F
console.log('$lideNum ====> '+$slideNum)
$myCarousel.on('slid.bs.carousel', function(event) {//The slide’s change process ends
var $imgW = $('#myCarouselSlideImage'+$slideNum).width(); //G
var $imgH = $('#myCarouselSlideImage'+$slideNum).height(); //G
console.log('$imgW ====> '+$imgW);
console.log('$imgH ====> '+$imgH);
var $result = '';
$result = ScaleImage($imgW, $imgH, $parentImgW, $parentImgH, true); //H
console.log('$result.width ====> '+$result.width);
console.log('$result.height ====> '+$result.height);
console.log('$result.targetleft ====> '+$result.targetleft);
console.log('$result.targettop ====> '+$result.targettop);
$('#myCarouselSlideImage'+$slideNum).animate({ // I
width:$result.width+'px',
height:$result.height+'px',
left:$result.targetleft+'px',
top:$result.targettop+'px' },
300);
});
});
See it runnig at https://jsfiddle.net/nd90r1ht/57/ or at https://jsfiddle.net/omarlin25/nd90r1ht/59/

flex: Drag and drop- object centering

In a drag+drop situation using Flex, I am trying to get the object center aligned to the point of drop- somehow, irrespective of the adjustments to height and width, it is always positioning drop point to left top.
here is the code..
imageX = SkinnableContainer(event.currentTarget).mouseX;
imageY = SkinnableContainer(event.currentTarget).mouseY;
// Error checks if imageX/imageY dont satisfy certain conditions- move to a default position
// img.width and img.height are both defined and traced to be 10- idea to center image to drop point
Image(event.dragInitiator).x = imageX-(img.width)/2;
Image(event.dragInitiator).y = imageY-(img.height)/2
The last 2 lines don't seem to have any effect. Any ideas why-must be something straightforward, that I am missing...
You can use the following snippet:
private function on_drag_start(event:MouseEvent):void
{
var drag_source:DragSource = new DragSource();
var drag_initiator:UIComponent = event.currentTarget as UIComponent;
var thumbnail:Image = new Image();
// Thumbnail initialization code goes here
var offset:Point = this.localToGlobal(new Point(0, 0));
offset.x -= event.stageX;
offset.y -= event.stageY;
DragManager.doDrag(drag_initiator, drag_source, event, thumbnail, offset.x + thumbnail.width / 2, offset.y + thumbnail.height / 2, 1.0);
}
Here is one important detail. The snippet uses stage coordinate system.
If you use event.localX and event.localY, this approach will fail in some cases. For example, you click-and-drag a movie clip. If you use localX and localY instead of stage coordinates, localX and localY will define coordinates in currently clicked part of the movie clip, not in the whole movie clip.
Use the xOffset and yOffset properties in the doDrag method of DragManager.
Look here for an example.

fullcalendar - display half-day event in the month view

How do you display a half-day event in the month view? For instance, I have an event that is 12 hours long. I would like the date cell for that event to only show a half bar. Is that possible? If so, how do you implement this?
So the events are positioned "absolute", this is a tricky one .....
Use of the eventAfterRender callback like this :
, eventAfterRender: function(event, element, view) {
/**
* get the width of first day slot in calendar table
* next to event container div
*/
var containerWidth = jQuery(element).offsetParent()
.siblings("table").find(".fc-day-content").width();
// half a day
var elementWidth = parseInt(containerWidth / 2);
// set width of element
jQuery(element).css('width', elementWidth + "px");
}
Surely can be improved :-)
A little late to the party, but I've just managed to implement this in a way that works great, and works when the page is resized too.
eventAfterRender doesnt seem to work for me, but eventRender will do the same thing:
eventRender: function (event, element) {
// Get the page width, then
// subtract the margins around the side. I'm assuming a full
// size calendar with a margin of 15px on each side here.
var width = getWidth()-30;
width = width / 14; (7 days = 14 half days)
jQuery(event.el).css('margin-left', width + "px");
}
You then need to reload the events when the browser window is resized so that they remain in the middle, otherwise they will drift.
window.addEventListener('resize', function () {
calendar.refetchEvents();
});
Note: for getting the browser width I'm using this function to ensure it works across different browsers:
function getWidth() {
return Math.max(
document.body.scrollWidth,
document.documentElement.scrollWidth,
document.body.offsetWidth,
document.documentElement.offsetWidth,
document.documentElement.clientWidth
);
}

Resources