UIScrollView is stopping too soon - xamarin.ios

I'm using a scrollview to make a image gallery for my app and I have it mostly working. it'll allow me to scroll through the images one by one but the very last image always get cut off and I'm not sure why.
this is the bulk of the operation:
var idx = 0;
foreach (var mediaItem in _mediaItems)
{
var xPosition = UIScreen.MainScreen.Bounds.Width * idx;
var imageView = new UIImageView();
imageView.SetImage(new NSUrl(mediaItem), UIImage.FromBundle("image_placeholder"));
imageView.Frame = new CGRect(xPosition, 0, svGallery.Frame.Width + 50, svGallery.Frame.Height);
imageView.ContentMode = UIViewContentMode.ScaleAspectFit;
svGallery.ContentSize = new CGSize
{
Width = svGallery.Frame.Width * (idx + 1)
};
svGallery.AddSubview(imageView);
idx++;
}
minus that flaw, this works perfectly and as I expect it to.

From shared code , the Width of ContenSize is:
Width = svGallery.Frame.Width * (idx + 1)
However, each Width(svGallery.Frame.Width + 50) of ImageView is greater than vGallery.Frame.Width:
imageView.Frame = new CGRect(xPosition, 0, svGallery.Frame.Width + 50, svGallery.Frame.Height);
Therefore, the actually Width of ContenSize can not contains all the ImageView's Content. And if the number of ImageView is larger, the last picture will be cut off more.
You can modif the Width of ContentSize as follow to check whether it works:
svGallery.ContentSize = new CGSize
{
Width = (svGallery.Frame.Width + 50) * (idx + 1)
};

Related

scale SVG pathPoints

I am scaling a polygon and set the actual scaled points into the pathArray
const pointsCal = this.findPoints(allocatedTable.tableType.shape.pathArray);//calculating max x,y min x,y of pathArray
const diameterX = (pointsCal.highX - pointsCal.lowX)/2;
const diameterY = (pointsCal.highY - pointsCal.lowX)/2;
const scalex = (diameterX + this.settings.tableTableSpace) / diameterX;
const scaleY = (diameterY + this.settings.tableTableSpace) / diameterY;
pathArray.forEach((point) => {
if (point.command !== 'z') {
point.x -= tableCenterPoint.x;
point.y -= tableCenterPoint.y;
point.x *= scalex;
point.y *= scaleY;
point.x += tableCenterPoint.x;
point.y += tableCenterPoint.y;[enter image description here][1]
}
});
but for the regular rectangle it is working properly but for the rotated Shapes it is not scling propely
I think I had made a mistake in logic in calculating scale X and scaleY value
Why the divide by 2?
Try something like this:
const width = pointsCal.highX - pointsCal.lowX;
const height = pointsCal.highY - pointsCal.lowY;
const scalex = this.settings.tableTableSpace / width;
const scaleY = this.settings.tableTableSpace / height;
If that doesn't work, then you'll need to provide a minimal workable example
Update
I'm still not 100% sure what you want. But looking at the code, I assume you are wanting to scale the original shape so that it fills the SVG. But also allowing for some padding around it.
If so, you'll want to do something like this:
DrawScalledRectangle() {
// Get the size of the original polygon
const bbox = this.tableGroup.getBBox();
// Get the size of the <svg> element.
// This will be the value at the time this function is run. But the <svg> has width
// and height of "100%" so it may change if the window is resized.
const mainSvg = document.getElementById("mainSVG");
const svgWidth = mainSvg.clientWidth;
const svgHeight = mainSvg.clientHeight;
// The scale will be svgSize / originalSize (but we subtract the padding from the svgSize first)
const scaleX = (svgWidth - this.tableTableSpace * 2) / bbox.width;
const scaleY = (svgHeight- this.tableTableSpace * 2) / bbox.height;
this.pathArray.forEach(point => {
if (point.command !== "z") {
// New point location = padding + (oldPoint - shapePosition) * scale
point.x = this.tableTableSpace + (point.x - bbox.x) * scaleX;
point.y = this.tableTableSpace + (point.y - bbox.y) * scaleY;
}
});
console.log(this.pathArray);
...snip...
}
https://stackblitz.com/edit/angular-thb9w5?file=src/app/app.component.ts

How can I make an image used on multiple Excel spreadsheets always display at its full size (Aspose Cells)?

I am using the following code to place an image on a spreadsheet:
var ms = new MemoryStream();
Image _logo = RoboReporterConstsAndUtils.GetURLImage("http://www.proactusa.com/bla/pa_logo_notag.png");
_logo.Save(ms, ImageFormat.Png);
ms.Position = 0;
locationWorksheet.Pictures.Add(0, 4, ms);
AutoFitterOptions options = new AutoFitterOptions { OnlyAuto = true };
locationWorksheet.AutoFitRows(options);
It works fine; however, I use this same code on two different reports, and the image displays at different sizes. On one it has a height of 0.85" (63%) and a width of 1.1" (53%), while on the other it has a height of 1.44" (106%) and a width of 2.07" (100%).
Why would they differ in size? And why wouldn't they be 100% of the original image size?
The other code, which seems to be exactly the same (although in this case the column at which the image appears is dynamic), is:
var ms = new MemoryStream();
Image _logo = RoboReporterConstsAndUtils.GetURLImage("http://www.proactusa.com/bla/pa_logo_notag.png");
_logo.Save(ms, ImageFormat.Png);
ms.Position = 0;
pivotTableSheet.Pictures.Add(0, _grandTotalsColumnPivotTable - 1, ms);
AutoFitterOptions options = new AutoFitterOptions { OnlyAuto = true };
pivotTableSheet.AutoFitRows(options);
The image itself, at the location referenced, has a height of 1.35" and a width of 2.07"
The method called is:
internal static Image GetURLImage(string url)
{
WebClient wc = new WebClient();
byte[] bytes = wc.DownloadData(url);
MemoryStream ms = new MemoryStream(bytes);
return Image.FromStream(ms);
}
How can I get the image to always display at 100%, or at least at a given size?
UPDATE
I also have (at least for now) some reports in the same project that are generated using EPPlus. In these, I have the following code, which allows me to set the exact size of the image:
private void AddImage(ExcelWorksheet oSheet, int rowIndex, int colIndex)
{
Image _logo = RoboReporterConstsAndUtils.GetURLImage("http://www.proactusa.com/bla/pa_logo_notag.png");
var excelImage = oSheet.Drawings.AddPicture("PRO*ACT Logo", _logo);
excelImage.From.Column = colIndex - 1;
excelImage.From.Row = rowIndex - 1;
excelImage.SetSize(199, 130); // 199WX130H is the actual size of the image
excelImage.From.ColumnOff = Pixel2MTU(2);
excelImage.From.RowOff = Pixel2MTU(2);
}
...which is called like so:
AddImage(deliveryPerformanceWorksheet, UNIT_ROW, LOGO_FIRST_COLUMN);
...but this won't fly in the Aspose code, because the sheet is of a different type - an Aspose.Cells.Worksheet instead of an ExcelWorksheet, and thus this code:
AddImage(locationWorksheet, 0, 4);
... won't compile in the Aspose report. I wish I could temporarily convert the Aspose.Cells.Worksheet to an ExcelWorksheet as cavalierly as this:
ExcelWorksheet ews = locationWorksheet; // naive attempt to magically morph an Aspose.Cells.Worksheet to an ExcelWorksheet
AddImage(ews, 0, 4);
...so that I could call AddImage(), but that flagrant attempt is tweeted to a halt by the compiler whistling, "Cannot implicitly convert type 'Aspose.Cells.Worksheet' to 'OfficeOpenXml.ExcelWorksheet'"
UPDATE 2
The image is the expected size; this code:
int h = _logo.Height; //130, as expected
int w = _logo.Width; //199, " "
...showed the image was the original size. Could the problem be the AutoFitterOptions setting? Does OnlyAuto allow stretching/squashing of the image, depending on the size of the cell into which it is plopped?
UPDATE 3
In EPPlus I can get the images to display at exactly the same size using this code:
private void AddImage(ExcelWorksheet oSheet, int rowIndex, int colIndex)
{
Image _logo = RoboReporterConstsAndUtils.GetURLImage("http://www.proactusa.com/bla/pa_logo_notag.png");
var excelImage = oSheet.Drawings.AddPicture("PRO*ACT Logo", _logo);
excelImage.From.Column = colIndex - 2;
excelImage.From.Row = rowIndex - 1;
excelImage.SetSize(199, 130);
excelImage.From.ColumnOff = Pixel2MTU(2);
excelImage.From.RowOff = Pixel2MTU(2);
}
...but in Aspose I can only come close using:
var ms = new MemoryStream();
Image _logo = RoboReporterConstsAndUtils.GetURLImage("http://www.proactusa.com/bla/pa_logo_notag.png");
_logo.Save(ms, ImageFormat.Png);
ms.Position = 0;
pivotTableSheet.Pictures.Add(0, _grandTotalsColumnPivotTable - 1, ms);
And the EPPlus code also retains the height/width ratio:
The original image is 199 pixels wide and 130 pixels high.
The EPPlus-plopped images are 1.33 X 2.05, so the ratio of 1.5:1 (close approximation) is retained.
The Aspose-plopped images, though, are 1.63 and 1.67 X 2.07, so the ratio is more like 1.25:1
So even with the AutoFitter jazz commented out of the Aspose code, the image still gets either squashed in width or stretched in height.
UPDATE 4
Based on a thread here, I tried this (afer copying the image to my bin folder):
int index = locationWorksheet.Pictures.Add(0, 4, 6, 5, "LogoFromSite.png");
Picture pic = locationWorksheet.Pictures[index];
pic.Placement = PlacementType.FreeFloating;
The first four arguments to [sheet].Pictures.Add() are Upper Left Row, Upper Left Column, Lower Right Row, and Lower Right Column.
However, this puts the image on the page in the right place, but then moves it to the left several columns (!?!)
UPDATE 5
I found another ray of hope here, and tried this code:
Aspose.Cells.Rendering.ImageOrPrintOptions opts = new Aspose.Cells.Rendering.ImageOrPrintOptions();
opts.OnePagePerSheet = true;
opts.ImageFormat = ImageFormat.Png;
opts.SetDesiredSize(199, 130);
Aspose.Cells.Rendering.SheetRender sr = new Aspose.Cells.Rendering.SheetRender(locationWorksheet, opts);
sr.ToImage(0, "LogoFromSite.png");
...but got this:
So: squashed again.
UPDATE 6
I tried some code provided by the Aspose Cells cats themselves, but they admitted there was a problem with it, and were looking into it. Just for grins, I gave it a shot to see what would transpire. This code:
byte[] bts1 = File.ReadAllBytes("LogoFromSite.png");
byte[] bts2 = File.ReadAllBytes("LogoFromSite.png");
MemoryStream ms1 = new MemoryStream();
ms1.Write(bts1, 0, bts1.Length);
ms1.Position = 0;
//This is for second picture in sheet2
MemoryStream ms2 = new MemoryStream();
ms2.Write(bts2, 0, bts2.Length);
ms2.Position = 0;
//Add picture in first worksheet
int idx = locationWorksheet.Pictures.Add(0, 4, ms1);
//Add picture in second worksheet with original size
idx = locationWorksheet.Pictures.Add(0, 10, ms2);
Picture pic = locationWorksheet.Pictures[idx];
pic.HeightScale = 100;
pic.WidthScale = 100;
...resulted in these "no image images":
UPDATE 7
I made another venture; as the height was being increased above and beyond 100%, I thought I would resize the image into another one, and use that:
var ms = new MemoryStream();
Image _logo = GetURLImage("http://www.proactusa.com/bla/pa_logo_notag.png");
double newHeightDbl = _logo.Height * 0.8;
int newHeightInt = (int)Math.Ceiling(newHeightDbl);
Image resizedImage = ResizeImage(_logo, newHeightInt, _logo.Width);
resizedImage.Save(ms, ImageFormat.Png);
ms.Position = 0;
locationWorksheet.Pictures.Add(0, 4, ms);
...but no! It stuffs the whole shebang into one measly column, like so:
...and gumbifies it galore vertically, thus making it look queasier than a lubber on a tempest-tossed tug.
Here is the (stolen/borrowed) code to resize the image:
// from http://stackoverflow.com/questions/1922040/resize-an-image-c-sharp
public static Bitmap ResizeImage(Image image, int width, int height)
{
var destRect = new Rectangle(0, 0, width, height);
var destImage = new Bitmap(width, height);
destImage.SetResolution(image.HorizontalResolution, image.VerticalResolution);
using (var graphics = Graphics.FromImage(destImage))
{
graphics.CompositingMode = CompositingMode.SourceCopy;
graphics.CompositingQuality = CompositingQuality.HighQuality;
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphics.SmoothingMode = SmoothingMode.HighQuality;
graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
using (var wrapMode = new ImageAttributes())
{
wrapMode.SetWrapMode(WrapMode.TileFlipXY);
graphics.DrawImage(image, destRect, 0, 0, image.Width, image.Height, GraphicsUnit.Pixel, wrapMode);
}
}
return destImage;
}
Please check your thread in Aspose.Cells forum which answers two of your following questions.
1 - Can we reuse same memory stream object containing picture in workbooks and worksheets?
2 - How to add picture with original size?
Note: I am working as Developer Evangelist at Aspose
Simply a matter of commenting out the fancy-pants autofitting code:
//AutoFitterOptions options = new AutoFitterOptions { OnlyAuto = true };
//pivotTableSheet.AutoFitRows(options);
Now the image is displayed uniformly at pretty much its actual size (but note the caveat below); a scosh "spilly" at times, but if they complain about that, I'll create a second image, and resize it using this:
// from http://stackoverflow.com/questions/1922040/resize-an-image-c-sharp
public static Bitmap ResizeImage(Image image, int width, int height)
{
var destRect = new Rectangle(0, 0, width, height);
var destImage = new Bitmap(width, height);
destImage.SetResolution(image.HorizontalResolution, image.VerticalResolution);
using (var graphics = Graphics.FromImage(destImage))
{
graphics.CompositingMode = CompositingMode.SourceCopy;
graphics.CompositingQuality = CompositingQuality.HighQuality;
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphics.SmoothingMode = SmoothingMode.HighQuality;
graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
using (var wrapMode = new ImageAttributes())
{
wrapMode.SetWrapMode(WrapMode.TileFlipXY);
graphics.DrawImage(image, destRect, 0, 0, image.Width, image.Height, GraphicsUnit.Pixel, wrapMode);
}
}
return destImage;
}
Caveat emptor: This works well enough that I am grudgingly accepting it, but the images placed on the sheet are not exactly the same size. One is 1.67" X 2.07", the other is 1.63" X 2.07" - close enough for horseshoes, hand-grenades, and images on Excel spreadsheets, I guess.

Zoom in and out : canvas offset

I'm working on a zoom functionnality like this :
public wheelEventHandler(ev) {
var pointer = this.canvas.getPointer(ev.e);
var posx = pointer.x;
var posy = pointer.y;
if (ev.wheelDelta > 0) {
//zoom in
let valeurZoom = this.canvas.getZoom() * 1.1 <= this.maxZoom ? this.canvas.getZoom() * 1.1 : this.maxZoom;
this.canvas.zoomToPoint(new fabric.Point(posx, posy), valeurZoom);
}
else {
//zoom out
let valeurZoom = this.canvas.getZoom() / 1.1 >= 1 ? this.canvas.getZoom() / 1.1 : 1;
this.canvas.zoomToPoint(new fabric.Point(posx, posy), valeurZoom);
}
}
Problem is when i zoom in, and then zoom out, the initial view have an offset, and i don't know what to do, when my zoom is back to 1, i want that canvas shows exactly what it showed before, with image centered and no offset.
How can i do?
this is what i have in the begening and what i want when zoom is back to 1
this is what i have when i zoom back to 1 and i don't want the offset in red
Lempkin,
When you zoom out to initial zoom (to 1) try use this functionality:
var centerOfCanvas = new fabric.Point(canvas.getWidth() / 2, canvas.getHeight() / 2);
canvas.zoomToPoint(centerOfCanvas , 1);
canvas.renderAll();
When you want to zoom out on a center all the time use this logic:
var centerOfCanvas = new fabric.Point(canvas.getWidth() / 2, canvas.getHeight() / 2);
canvas.zoomToPoint(centerOfCanvas , canvas.getZoom() / 1.1);
canvas.renderAll();
If you want to zoom out/zoom in in the mouse position use your logic, but when you zoom is equal to 1 reset to center position of the mouse.
Reset to default:
canvas.viewportTransform = [1,0,0,1,0,0]

Read inner and outer radius of arc - d3.js

I'm working on a project which deals with visual representation of large relational data. We are using pie chart to display the data components(In order). Due to lack of space we are displaying only 10 at a time.
Consider the following example:
Assume that I have 100 data components, out of which I'll display only 10 at a given point of time. The logic i'm using is, I'm setting start and end angle to 0(Zero) for other 90 components. Where in for those 10 components i'm calculation the start and end angle as below-
var angle = 360;
var count = 10;
if(data.length > count) angle = angle/count; //data is array of data component names
else angle = angle/data.length;
//Initially I'll be displaying first ten components
for(var i=0; i<data.length; i++){
var startAngle = i * angle;
var endAngle = startAngle + angle;
var pi = = Math.PI/180;
var arc = d3.svg.arc()
.innerRadius(innerRadius) //dynamic value, calculated based on available space
.outerRadius(outerRadius) //dynamic value, calculated based on available space
.startAngle((startAngle)*pi)
.endAngle((endAngle)*pi);
//Hiding rest of the data components
if(i >= count){
arc.startAngle(0);
arc.endAngle(0);
}
arcGroup.append("path")
.attr("d", arc)
.attr("stroke", "#2E2E2E")
.attr("stroke-width", "1")
.attr("fill","gold");
var text = arcGroup.append("text")
.attr("transform", "translate(" + arc.centroid() + ")")
.attr("text-anchor", "middle")
.attr("font-family","noto_sansregular")
.attr("font-size", 40)
.attr("font-weight","Bold")
.attr("fill", "#000000")
.attr("y",0)
.style("visibility", "visible")
.text(data[i]);
//Hiding text of hidden arcs
if(i >= count) text.style("visibility", "hidden");
}
Then if user wants to see the rest of the components, i'm providing two buttons to rotate (clock or anti-clock) the content.
If current view is -> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
On rotate by one cell clockwise, resulting view should be -> 100, 1, 2, 3, 4, 5, 6, 7, 8, 9
In this case I need to hide component '10' and display component '100', and shift rest of the cells. To achieve this i just need to change the start and end angles of the arcs. I can create new arc object with calculated angles.
The problem here is I don't know how to get the inner and outer radius of the arc, which are dynamically created.
Just like that,
...
arcGroup.append("path")
.filter(function(d) {
// You're Not restricted to the "filter" function
var innerRadius = d.innerRadius()(d);
var outerRadius = d.outerRadius()(d);
})
.attr("d", arc)
...
Technically, it is possible to retrieve the innerRadius and outerRadius from the d attribute of the path elements, but it will require parsing the DSL and will be tedious. These values are not stored nicely on the elements itself by d3.
Hence, it would be better if you recompute the innerRadius and outerRadius while updating the elements:
function showFromIdx(firstIndex) {
argGroup.selectAll('path')
.data( d3.range(data.length)
.map(function (d) {
return (d - firstIndex + data.length) % data.length;
})
)
.attr('d', function (d) {
// You will have to calculate the radii again here.
var innerRadius = foo(d), outerRadius = bar(d);
return d3.svg.arc()
.startAngle(i < count ? i * angle : 0)
.endAngle(i < count ? (i + 1) * angle : 0)
.innerRadius(innerRadius)
.outerRadius(outerRadius)(d);
});
}
Here are several functions that I wrote to get inner and outer radiuses of arcs created using d3. Please tell me if you find mistakes in code.
function getInnerRadiusFromArc(arc) {
var numbersInPattern = _getArcNumbers(arc);
// Possibly, that's sector, so it starts from 0.
// Or maybe that's something else.
if (numbersInPattern.length < 4) {
return 0;
}
// Getting minimum from the array.
var innerRadius = Math.min.apply(null, numbersInPattern);
return innerRadius;
}
function getOuterRadiusFromArc(arc) {
var numbersInPattern = _getArcNumbers(arc);
// Getting maximum from the array.
var outerRadius = Math.max.apply(null, numbersInPattern);
return outerRadius;
}
function _getArcNumbers(arc) {
// Path description parameter, containing necessary data.
var pathDescription = arc.getAttribute("d");
// We need to get all patterns like A<number>,<number>.
// RegExp source:
// http://www.regular-expressions.info/floatingpoint.html
const numberRegExp = /[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?/g;
var arcPattern = new RegExp("A" + numberRegExp.source + "," + numberRegExp.source, "g");
var arcParameters = pathDescription.match(arcPattern);
var numbersInPattern = [];
// We get all the numbers from array ["A<number>,<number>", "A<number>,<number>", ...].
for (let parameterIndex = 0; parameterIndex < arcParameters.length; parameterIndex++) {
let parameter = arcParameters[parameterIndex];
let numbers = parameter.match(numberRegExp);
if (numbers !== null) {
numbersInPattern = numbersInPattern.concat(numbers);
}
}
// Transform strings in our array to numbers.
numbersInPattern = numbersInPattern.map(function (numberString) {
return parseFloat(numberString);
});
return numbersInPattern;
}

How to animate rectangle to fixed width in steps with createjs?

I'm trying to create loading bar for my game. I create basic rectangle and added to the stage and caluclated size acording to the number of files so I get fixed width. Everything works, but for every step (frame) it creates another rectangle, how do I get only one object?
this is my code:
function test(file) {
r_width = 500;
r_height = 20;
ratio = r_width / manifest.length;
if (file == 1) {
new_r_width = 0
// Draw
r = new createjs.Shape();
r_x = (width / 2) - (r_width / 2);
r_y = (height / 2) - (r_height / 2);
new_r_width += ratio;
r.graphics.beginFill("#222").drawRect(r_x, r_y, new_r_width, r_height);
stage.addChild(r);
} else {
stage.clear();
new_r_width += ratio;
r.graphics.beginFill("#" + file * 100).drawRect(r_x, r_y + file * 20, new_r_width, r_height);
stage.addChild(r);
}
stage.update();
}
https://space-clicker-c9-zoranf.c9.io/loading/
If you want to redraw the rectangle, you will have to clear the graphics first, and then ensure the stage is updated. In your code it looks like you are clearing the stage, which is automatically handled by the stage.update() unless you manually turn off updateOnTick.
There are some other approaches too. If you just use a rectangle, you can set the scaleX of the shape. Draw your rectangle at 100% of the size you want it at, and then scale it based on the progress (0-1).
r.scaleX = 0.5; // 50%
A new way that is supported (only in the NEXT version of EaselJS, newer than 0.7.1 in GitHub), you can save off the drawRect command, and modify it.
var r = new createjs.Shape();
r.graphics.beginFill("red");
var rectCommand = r.graphics.drawRect(0,0,100,10).command; // returns the command
// Later
rectCommand.w = 50; // Modify the width of the rectangle
Hope that helps!

Resources