I have a sencha chart with crosszooming and innerPadding like the one in the fiddle. The problem I'm experiencing is that it is not possible to pull the rectangle of the cross zoom completly down to the x-axis and to the right side of the chart. When I remove the innerPadding of the chart everything works fine.
https://fiddle.sencha.com/#fiddle/mh8
Is there a workaround for this problem?
I've forked your fiddle with a fix, here: https://fiddle.sencha.com/#fiddle/mih
NOTE: You question is tagged with Touch2.1 but your fiddle is in 2.4.1
When you define your innerPadding, the innerRegion for the chart is calculated based on your padding.
Excerpt from the source of CartesianChart
shrinkBox.left += innerPadding.left;
shrinkBox.top += innerPadding.top;
shrinkBox.right += innerPadding.right;
shrinkBox.bottom += innerPadding.bottom;
innerWidth = width - innerPadding.left - innerPadding.right;
innerHeight = height - innerPadding.top - innerPadding.bottom;
me.setInnerRegion([shrinkBox.left, shrinkBox.top, innerWidth, innerHeight]);
Now inside the onGesture (protected function) handler of CrossZoom, it actually checks the innerRegion of your chart and if your current x or y is greater than the width or height (you get this from the innerRegion of the chart) of the chart respectively, it's reset to the width/height of the chart (width and height is ). Thus, you are limited inside the padded area.
Is there a workaround for this problem?
You can work around this by overriding this behavior, but it's the expected behavior as far as Sencha is concerned.
Override onGesture function of CrossZoom so that it takes the padding offset into consideration.
//onGesture implementation in CrossZoom
onGesture: function (e) {
var me = this;
if (me.zoomAnimationInProgress) {
return;
}
if (me.getLocks()[me.getGesture()] === me) {
var chart = me.getChart(),
surface = me.getSurface(),
region = chart.getInnerRegion(),
chartWidth = region[2],
chartHeight = region[3],
xy = chart.element.getXY(),
x = e.pageX - xy[0] - region[0],
y = e.pageY - xy[1] - region[1];
if (x < 0) {
x = 0;
} else if (x > chartWidth) {
x = chartWidth; // this is where it limits you in the x-axis
}
if (y < 0) {
y = 0;
} else if (y > chartHeight) {
y = chartHeight; // this is where it limits you in the y-axis
}
me.selectionRect.setAttributes({
width: x - me.startX,
height: y - me.startY
});
if (Math.abs(me.startX - x) < 11 || Math.abs(me.startY - y) < 11) {
me.selectionRect.setAttributes({globalAlpha: 0.5});
} else {
me.selectionRect.setAttributes({globalAlpha: 1});
}
surface.renderFrame();
return false;
}
}
Refer the source code for more details and understanding.
FYI: You may again have a question that you cannot start drawing your CrossZoom overlay outside the padding region. Check onGestureStart, if you are asking that question.
Related
I am looking something like this ( https://jsfiddle.net/xg1o4ekr/378/ ) instead of globe imagine various other shapes of 3D object and marker coming outwards. Since my 3d object is not circle i cannot use the given above code
On clicking a loaded .obj 3D model, there will a pointer rendered on a clicked position(raycaster is used). using three js geometry shapes i have created a pointer. that pointer will render on a clicked position. how to determine pointer’s rotation. (it should dynamically decide the rotation of the pointer)
onMouseClick = (event) => {
event.preventDefault();
// calculate objects intersecting the picking ray
var intersects = this.getIntersects(event.layerX, event.layerY);
if (intersects.length > 0) {
var res = intersects.filter(function (res) {
return res && res.object;
})[0];
if (res && res.object) {
this.selectedObject = res.object;
console.log(res);
const Pointer = this.createPointer();
var g2 = new THREE.Group();
g2.add(Pointer.cone);
g2.add(Pointer.sphere);
g2.position.set(res.point.x, res.point.y, res.point.z);
//g2.rotation.set(res.point.x, res.point.y, res.point.z); //not working fine
g2.rotateX(0.7);
g2.rotateZ(0.9);
g2.rotateY(1);// not working fine
this.scene.add(g2);
}
}
}
getIntersects = (x, y) => {
x = (x / this.width) * 2 - 1;
y = - (y / this.height) * 2 + 1;
this.mouseVector.set(x, y);
this.raycaster.setFromCamera(this.mouseVector, this.camera);
return this.raycaster.intersectObject(this.group, true);
}
Interesting question. It's late here so i wont be able to try code, but maybe this helps?
Does the object you are clicking on have normals?
You can find it in intersets[0].face.normal (or .vertexNormals).
You can align the pointer with that..
var normal = intersects[0].face.normal:
var axis = new THREE.Vector3(0, 1, 0); //(or maybe -1? i'm not sure, play around)
g2.quaternion.setFromUnitVectors(axis, normal);
and if you want to set the pointer at a distance from the surface;
var distance = 4;
g2.position.add( normal.multiplyScalar(distance) );
Also, instead of creating a pointer everytime, why not creating it once and do pointer.clone()?
So the supposed advantage to using Sencha is being able to have 1 code base for multiple platforms. I have a project I need to be on iOS, Android, PC, and Mac. I have found that I can use Sencha Touch to build to mobile devices and those handle finger swipe events automatically. The problem I have encountered is when I am building a desktop app then it doesn't respond to my mousewheel.
I have been on the Sencha forums and this question is unanswered in one place, and in another they promised support for this over 2 years ago. Any 3rd part solutions I have found either are not documented properly or won't work. Elsewhere I have been told that Sencha Touch is for mobile development but Extjs is for desktop, but I really don't want to have to build another codebase just for mousewheel.
There is a JSfiddle here where delta returns 1 when you mousewheel up, and -1 when you mousewheel down.
var doScroll = function (e) {
// cross-browser wheel delta
e = window.event || e;
var delta = Math.max(-1, Math.min(1, (e.wheelDelta || -e.detail)));
// Do something with `delta`
console.log(delta);
e.preventDefault();
};
if (window.addEventListener) {
window.addEventListener("mousewheel", doScroll, false);
window.addEventListener("DOMMouseScroll", doScroll, false);
} else {
window.attachEvent("onmousewheel", doScroll);
}
Put this code into the initialization block for your app. Now this code will get run anywhere in your app no matter which element has focus. I was lucky enough in my app that each of my pages only had 1 element that needed to be scrolled.
replaced console.log(delta); with code that determines which element is active/which element was in need of scrolling, and the code to scroll it.
var scrollMe = Ext.getCmp("componentToScroll");
var currentY = scrollMe.getScrollable().getScroller().position.y;
var pageHeight = document.getElementById("orderList").clientHeight;;
var containerHeight = 722; //the defined height of the scrollMeContainer
var newY = currentY;
if (delta === 1) {
if (currentY >= 30) {
newY = currentY - 30;
}
else {
newY = 0;
}
}
else if (delta === -1) {
if (currentY <= containerHeight - pageHeight - 30) {
newY = currentY + 30;
}
else {
newY = containerHeight - pageHeight;
}
}
scrollMe.getScrollable().getScroller().scrollTo(0, newY);
I need to add some view in iOS 7. And in the same time my project have to work on iOS 6.
How can I do it programmacly? I want to see the same position of "i"-button on 2 versions of app.
Here's a category I put on a ViewController. It might not be the smartest method but it works for my views. All my apps build the UI's programatically. If you set the frame of a view to this after it has been loaded, it will behave the same in iOS 7 as in earlier versions. The code isn't kludgy in that it doesn't rely on the version rather the characteristics of the superview. I'm open to any comments.
#implementation UIViewController (effectiveContentFrame)
// determine frame size and offset to get the max frame we can get for the current view and orientation
// needed this after the introduction of iOS 7 where frames are handled slightly differently
// note: it uses the different heights/widths at the current rotation
/*
iOS 6 portrait
application Frame: = (0.000000,20.000000) 320.000000x460.000000 )
superview Frame = (0.000000,20.000000) 320.000000x460.000000 )
iOS7 portrait
application Frame: = (0.000000,20.000000) 320.000000x460.000000 )
superview Frame = (0.000000,0.000000) 320.000000x480.000000 )
*/
- (CGRect) effectiveContentFrame
{
CGRect rect;
UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation;
CGRect statusBarFrame = [UIApplication sharedApplication].statusBarFrame;
CGFloat statusBarHeight = 0.;
rect = self.view.superview.frame; // the frame will be relative to the superview. Note in iOS6 the root superview frame includes the
if (UIInterfaceOrientationIsPortrait(orientation))
{
rect.size.height += rect.origin.y; // total height
statusBarHeight = statusBarFrame.size.height;
}
else
{
rect.size.height += rect.origin.x; // total height
statusBarHeight = statusBarFrame.size.width;
}
CGFloat extraHeight = 0; // this is going to be how much extra height we have to take off of the total height of the frame,
// which is going to be the status bar+navbar+toolbar heights
CGFloat topHeight = 0; // this is the height of the stuff before the frame, which we are going to use as an offset
if (![UIApplication sharedApplication].statusBarHidden)
extraHeight += statusBarHeight;
if (!self.navigationController.navigationBar.isHidden)
extraHeight += self.navigationController.navigationBar.frame.size.height;
topHeight = extraHeight;
if (!self.navigationController.toolbar.isHidden)
extraHeight += self.navigationController.toolbar.frame.size.height;
rect.origin.y = topHeight - rect.origin.y; // in iOS6 the status bar and navbar is already included in the origin but not in iOS7 .
if (rect.origin.y < 0)
rect.origin.y = 0;
rect.size.height -= extraHeight; // subtract status/nav and toolbar heights from the total height left in the superview
return rect;
}
It seems that type of Top Bar of your main view is Translucent Navigation Bar. Try to change it in IB to Opaque Navigation Bar.
I have had the same problem when I upgraded to the new xCode. I think this is because in older version opaque type was first in the list and now translucent on it's place.
Also, you can try self.edgesForExtendedLayout = UIRectEdgeNone; in your UIViewController
In Xcode 5 IB you can find iOS 6 / 7 deltas. All that you need is just adjust them.
The answer in C#
public static RectangleF GetUsableContentSize(this UIViewController viewController) {
RectangleF rect;
UIInterfaceOrientation orientation = UIApplication.SharedApplication.StatusBarOrientation;
RectangleF statusBarFrame = UIApplication.SharedApplication.StatusBarFrame;
float statusBarHeight = 0.0f;
var view = viewController.View;
if (view.Superview != null)
rect = view.Superview.Frame; // the frame will be relative to the superview. Note in iOS6 the root superview frame includes the
else
rect = view.Frame;
if (orientation == UIInterfaceOrientation.Portrait || orientation == UIInterfaceOrientation.PortraitUpsideDown)
{
rect.Height += rect.Y; // total height
statusBarHeight = statusBarFrame.Height;
}
else
{
rect.Height += rect.X; // total height
statusBarHeight = statusBarFrame.Width;
}
float extraHeight = 0; // this is going to be how much extra height we have to take off of the total height of the frame,
// which is going to be the status bar+navbar+toolbar heights
float topHeight = 0; // this is the height of the stuff before the frame, which we are going to use as an offset
if (!UIApplication.SharedApplication.StatusBarHidden)
extraHeight += statusBarHeight;
if (!viewController.NavigationController.NavigationBar.Hidden)
extraHeight += viewController.NavigationController.NavigationBar.Frame.Height;
topHeight = extraHeight;
if (!viewController.NavigationController.Toolbar.Hidden)
extraHeight += viewController.NavigationController.Toolbar.Frame.Height;
rect.Y = topHeight - rect.Y; // in iOS6 the status bar and navbar is already included in the origin but not in iOS7 .
if (rect.Y < 0)
rect.Y = 0;
rect.Size.Height -= extraHeight; // subtract status/nav and toolbar heights from the total height left in the superview
return rect;
}
It's been 2 hours of struggle against SL grid on WP7. I build my grid using the following code:
public void initUIBoard() {
int x, y;
Button b;
for (x = 0; x < mine.cRows; x++) {
RowDefinition rd = new RowDefinition();
rd.Height = new GridLength(20);
uiBoard.RowDefinitions.Add(rd);
}
for (y = 0; y < mine.cColumns; y++) {
ColumnDefinition cd = new ColumnDefinition();
cd.Width = new GridLength(20);
uiBoard.ColumnDefinitions.Add(cd);
}
for (x = 0; x < mine.cRows; x++)
for (y = 0; y < mine.cColumns; y++)
{
b = new Button();
b.Click += new RoutedEventHandler(this.caseClick);
b.Tag = mine.gameBoard[x][y];
Grid.SetRow(b, x);
Grid.SetColumn(b, y);
uiBoard.Children.Add(b);
}
}
The thing is, my grid is shown empty, am I doing something wrong with these Rows/Columns definition or something ?
Thanks in advance
After some experimentation, it looks like GridLength isn't calculating heights in pixels correctly.
Because the grid cell created isn't large enough the control is not shown.
Try increasing the sizes used for grid length. I did the following and got some output.
rd.Height = new GridLength(40);
Alternatively, consider setting the Heights and Widths to by dynamically sized. e.g.:
rd.Height = new GridLength(1, GridUnitType.Auto);
If you can investigate this height issue some more and also find it to be a height issue bug then please submit it to Microsoft.
Your code seems to work fine (I tried on Silverlight non-Winphone, but should be the same).
My guess is that the cause is somewhere else, for ex. another element covering the uiBoard grid, or the buttons being transparent with no background color/border.
I need to be able to zoom in and out of a Canvas using the mousewheel. I have successfully set up the mouse wheel handlers and am currently using a ScaleTransform to apply the zoom; however, the scaling is not done in an "intuitive" way.
I'm trying to accomplish the same style of "zooming" as you can see in MultiScaleImage, Google Maps/Earth, or Adobe Acrobat Reader--but NOT with an image, with a control. The transition doesn't need to be "smooth" or animated (unless it's an easier approach), but the functionality needs to be the same.
Any thoughts or ideas would be highly appreciated and thanks in advance!
Edit: I've managed to "smooth" the zoom using animation:
<Canvas.Resources>
<Storyboard x:Name="ZoomStoryboard">
<DoubleAnimation x:Name="ZoomAnimationX"
Storyboard.TargetName="Workspace"
Storyboard.TargetProperty="Canvas.RenderTransform.ScaleTransform.ScaleX"
Duration="0:0:0.2"/>
<DoubleAnimation x:Name="ZoomAnimationY"
Storyboard.TargetName="Workspace"
Storyboard.TargetProperty="Canvas.RenderTransform.ScaleTransform.ScaleY"
Duration="0:0:0.2"/>
</Storyboard>
</Canvas.Resources>
with the following code:
_Zoom += (args.Delta / 7);
if (_Zoom < 0.15)
_Zoom = 0.15;
ZoomAnimationX.To = _Zoom;
ZoomAnimationY.To = _Zoom;
ZoomStoryboard.Begin();
ZoomScale.Text = _Zoom.ToString("0.00") + "x";
_PreviousMousePosition = _CurrentMousePosition
However, the issue still arises that it is zooming out of the top-left corner, as opposed to sites like Google Maps where the zoom is "around" the mouse.
You need to use a weighted average as the zoom center based on the mouse position. In other words, keep the latest zoom center (or if you don't have one yet just set it to the current mouse position) and keep the number of times the zoom center was calculated (after the first zoom, that would be 1). Than each time you recalculate the zoom center, increment that var.
Example Code Follows - deltaZoom is how much you're zooming, centerX and centerY are the current zoom center, ZoomSteps is the number of times we've zoomed, and mouseX and mouseY are the current mouse position:
_Zoom += deltaZoom;
if (_Zoom <= 0)
_Zoom = 0.1;
if (deltaZoom >= 0)
{
if (_ZoomSteps == -1)
{
_CenterX = 0;
_CenterY = 0;
_ZoomSteps = 0;
}
else
{
_CenterX = (_CenterX * Math.Abs(_ZoomSteps) + mouseX) / (Math.Abs(_ZoomSteps + 1));
_CenterY = (_CenterY * Math.Abs(_ZoomSteps) + mouseY) / (Math.Abs(_ZoomSteps + 1));
_ZoomSteps++;
}
}
else
{
if (_ZoomSteps == 1)
{
_CenterX = 0;
_CenterY = 0;
_ZoomSteps = 0;
}
else
{
_CenterX = (_CenterX * Math.Abs(_ZoomSteps) - mouseX) / (Math.Abs(_ZoomSteps - 1));
_CenterY = (_CenterY * Math.Abs(_ZoomSteps) - mouseY) / (Math.Abs(_ZoomSteps - 1));
_ZoomSteps--;
}
}
ZoomAnimationX.To = _Zoom;
ZoomAnimationY.To = _Zoom;
CenterAnimationX.To = Math.Abs(_CenterX);
CenterAnimationY.To = Math.Abs(_CenterY);
ZoomStoryboard.Begin();
Edited so that you can drop below 1.0 zoom level but there are still some problems (ZoomStep = -1, 0 or 1 sometimes cause weird shakes).