I want to have the same animation movement on both a Text and a Rect. I put them into a group and apply a tween on the group. However, the x and y props are inherited, width and height are not, which means the Rect's width and height don't have smooth tween. Is there any way to set Rect's width and height to equal to 100% of its Group container's width and height all the time and along with their change?
const { scaleFactor, DynamicData, isPause } = props;
const groupRef = useRef<Konva.Group>(null);
const start = DynamicData.startData;
const end = DynamicData.endData;
useEffect(() => {
if (start && end && groupRef.current) {
const animation = new Tween({
node: groupRef.current,
duration: DynamicData.endTime - DynamicData.startTime,
x: scaleFactor * end.x,
y: scaleFactor * end.y,
width: scaleFactor * end.width,
height: scaleFactor * end.height,
easing: Easings.Linear,
});
if (isPause) {
animation.pause();
} else {
animation.play();
}
}
});
return (
<>
{!_.isUndefined(end) && (
<Group
ref={groupRef}
x={scaleFactor * start.x}
y={scaleFactor * start.y}
width={scaleFactor * start.width}
height={scaleFactor * start.height}
>
<Text
text={start.concept}
/>
<Rect
stroke={start.stroke}
/>
</Group>
)}
</>
);
};
update: for now I add a new Tween on Rect to track the width and height changes:
const sizeAnimation = new Tween({
node: rectRef.current,
duration: DynamicData.endTime - DynamicData.startTime,
width: scaleFactor * end!.width,
height: scaleFactor * end!.height,
easing: Easings.Linear,
});
if (isPause) {
sizeAnimation.pause();
} else {
sizeAnimation.play();
}
width and height properties of Konva.Group do nothing. They don't affect rendering.
You have to add another tween for rectangle.
I have written a custom renderer for iOS to create a chatbubble programmatically. The main chat bubble inherits from ContentView, this is done to allow me to add a Label as it's sole child. For the most part it works well but as soon as there are multiple lines of text it behaves very strangely, namely the text overflows and doesn't respect the parents boundaries(reminds me of when I was a teenager).
When I replace this custom control with a regular frame everything seems to work well. I am calculating the required height by overriding the Draw(CGRect ) call
Code here :
ppublic class ChatBubbleRenderer : VisualElementRenderer<ChatBubbleFrame>
{
public ChatBubbleRenderer()
{
this.ClipsToBounds = false;
}
public override void Draw(CGRect rect1)
{
var rect = Frame;
var currentContext = UIGraphics.GetCurrentContext();
var properRect = AdjustForThickness(rect);
HandleShapeDraw(currentContext, properRect);
}
protected RectangleF AdjustForThickness(CGRect rect)
{
var x = rect.X + Element.Padding.Left;
var y = rect.Y + Element.Padding.Top;
var width = rect.Width - ((Element.Padding.Left + (int)Element.StrokeWidth) * 2);
var height = rect.Height - ((Element.Padding.Top + (int)Element.StrokeWidth) * 2);
return new RectangleF((float)x, (float)y, (float)width, (float)height);
}
protected void HandleShapeDraw(CGContext currentContext, RectangleF rect)
{
var path = new CGPath();
var cr = (float)Element.CornerRadius;
var hl = (float)Element.HandleLength;
var x = rect.Left+hl;
var y = (float)rect.Top;
var startLeft = x;
var startTop = y;
var startRight = rect.Right - hl;
var startBottom = rect.Bottom ;
var centerX = x + cr;
var centerY = y + cr;
var width = (float)rect.Width - hl - hl;
var height = (float)rect.Height ;
if (Element.HandleIsBottomRight)
{
path.AddArc(centerX, centerY, cr, (float)Math.PI, (float)Math.PI * 3f / 2f, false);
x = startRight - cr;
//line to top right arc
path.AddLineToPoint(x, y);
//top right arc
centerX = x;
path.AddArc(centerX, centerY, cr, (float)Math.PI * 3f / 2f, 0, false);
x = x + cr;
//bring y down to top of triangle
y = y + height;
path.AddLineToPoint(x, y);
//chat handle
x = x + hl;
y = y + hl;
path.AddLineToPoint(x, y);
//to bottom left arc
x = startLeft + cr;
path.AddLineToPoint(x, y);
//bottom left arc
centerX = x;
centerY = y - cr;
path.AddArc(centerX, centerY, cr, (float)Math.PI / 2f, (float)Math.PI, false); //false to rotate clockwise
}
else
{
//line to top right arc
path.MoveToPoint(x, y);
x = startRight - cr;
path.AddLineToPoint(x, y);
//top right arc
centerX = x;
path.AddArc(centerX, centerY, cr, (float)Math.PI * 3f / 2f, 0, false);
//line to bottom right arc
x = x + cr;
y = y + height - cr;
path.AddLineToPoint(x, y);
//bottom right arc
centerX = x - cr;
centerY = y;
path.AddArc(centerX, centerY, cr, 0f, (float)Math.PI / 2f, false);
//line to bottom left arc
x = startLeft + cr;
y = y + cr;
path.AddLineToPoint(x, y);
//bottom left arc
centerX = x;
centerY = y - cr;
path.AddArc(centerX, centerY, cr, (float)Math.PI / 2f, (float)Math.PI, false); //false to rotate clockwise
//line to handle
x = startLeft;
y = startTop + hl;
path.AddLineToPoint(x, y);
x = x - hl;
y = startTop;
path.AddLineToPoint(x, y);
}
path.CloseSubpath();
HandleStandardDraw(currentContext, rect, () => currentContext.AddPath(path));
}
/// <summary>
/// A simple method for handling our drawing of the shape. This method is called differently for each type of shape
/// </summary>
/// <param name="currentContext">Current context.</param>
/// <param name="rect">Rect.</param>
/// <param name="createPathForShape">Create path for shape.</param>
/// <param name="lineWidth">Line width.</param>
protected virtual void HandleStandardDraw(CGContext currentContext, RectangleF rect, Action createPathForShape, float? lineWidth = null)
{
currentContext.SetLineWidth(lineWidth ?? Element.StrokeWidth);
currentContext.SetFillColor(Element.InnerColor.ToCGColor());
currentContext.SetStrokeColor(Element.StrokeColor.ToCGColor());
createPathForShape();
currentContext.DrawPath(CoreGraphics.CGPathDrawingMode.FillStroke);
}
}
Chat bubble Code
public class ChatBubbleFrame : ContentView
{
public ChatBubbleFrame()
{
}
public static readonly BindableProperty HandleIsBottomRightProperty = BindableProperty.Create(
propertyName: "HandleIsBottomRight",
returnType: typeof(bool),
declaringType: typeof(ChatBubbleFrame),
defaultValue: true
);
public static readonly BindableProperty InnerColorProperty = BindableProperty.Create(
propertyName: "InnerColor",
returnType: typeof(Color),
declaringType: typeof(ChatBubbleFrame),
defaultValue: Color.Default
);
public static readonly BindableProperty HandleLengthProperty = BindableProperty.Create(
propertyName: "HandleLength",
returnType: typeof(float),
declaringType: typeof(ChatBubbleFrame),
defaultValue: 2f
);
public static readonly BindableProperty StrokeColorProperty = BindableProperty.Create(
propertyName: "StrokeColor",
returnType: typeof(Color),
declaringType: typeof(ChatBubbleFrame),
defaultValue: Color.Default
);
public static readonly BindableProperty StrokeWidthProperty = BindableProperty.Create(
propertyName: "StrokeWidth",
returnType: typeof(float),
declaringType: typeof(ChatBubbleFrame),
defaultValue: 1f
);
public static readonly BindableProperty CornerRadiusProperty = BindableProperty.Create(
propertyName: "CornerRadius",
returnType: typeof(float),
declaringType: typeof(ChatBubbleFrame),
defaultValue: 0f
);
public bool HandleIsBottomRight
{
get { return (bool)GetValue(HandleIsBottomRightProperty); }
set { SetValue(HandleIsBottomRightProperty, value); }
}
public float HandleLength
{
get { return (float)GetValue(HandleLengthProperty); }
set { SetValue(HandleLengthProperty, value); }
}
public Color StrokeColor
{
get { return (Color)GetValue(StrokeColorProperty); }
set { SetValue(StrokeColorProperty, value); }
}
public Color InnerColor
{
get { return (Color)GetValue(InnerColorProperty); }
set { SetValue(InnerColorProperty, value); }
}
public float StrokeWidth
{
get { return (float)GetValue(StrokeWidthProperty); }
set { SetValue(StrokeWidthProperty, value); }
}
public float CornerRadius
{
get
{
return (float)GetValue(CornerRadiusProperty);
}
set
{
SetValue(CornerRadiusProperty, value);
}
}
}
Xaml snippet
<controls:ChatBubbleFrame x:Name="OtherUserBubble"
HandleIsBottomRight="False"
StrokeColor="{StaticResource Color13}"
InnerColor="White"
StrokeWidth="1"
CornerRadius="10"
HandleLength="7"
HorizontalOptions="FillAndExpand"
VerticalOptions="StartAndExpand"
Padding="-1,10,10,10"
Margin="35,0,10,0"
Grid.Column="0">
<StackLayout Margin="17,10,12,18">
<Label Text="{Binding Entity.CommentText }"
Style="{StaticResource Typo23}"
LineBreakMode="WordWrap"
Margin="0,6,10,0" />
</StackLayout>
</controls:ChatBubbleFrame>
Screenshots of a good message bubble and a terrible message bubble
I use this code in Objective-C to generate a random height between 100 and 1000.
My problem is, that new height is often near to the previous one and that is not so nice.
So how to make it so, that there is always some space (50px, for example) between previous and next height?
_randomHeight = arc4random() % (1000-100+1);
You just have to keep generating values until a value meets your requirement:
CGFloat height;
do {
height = arc4random() % (1000-100+1);
} while (fabs(_randomHeight - height) < 50.0f);
_randomHeight = height;
This will Give You correct height
float _randomHight = arc4random() % 900 + 101;
Here is a solution to produce values between 100 and 1000, distant of 50 at least, and using only one call to arc4random to guarantee a fixed execution time:
/// Return a new random height between 100 and 1000, at least 50 space from previous one.
+ (uint32_t)randomHeight {
/// initial value is given equiprobability (1000 - 100 + 50)
static uint32_t _randomHeight = 950;
uint32_t lowValues = MAX(_randomHeight - 50, 0);
uint32_t highValues = MAX(850 - _randomHeight, 0);
uint32_t aRandom = arc4random_uniform(lowValues + highValues + 1);
_randomHeight = aRandom < lowValues ? aRandom : _randomHeight + 50 + aRandom - lowValues;
return _randomHeight + 100;
}
I have a List Items(an Image and text)on BB Screen,
My requirement is to set an image border(So that Image Separation will be done on List Items) to image on BB Screen
Could any one help?
Here My Code:
public void drawListRow(ListField list, Graphics g, int index, int y,
int width) {
String title = (String) listElements.elementAt(index);
Bitmap image = (Bitmap) listImage.elementAt(index);
int LEFT_OFFSET = 2;
int TOP_OFFSET = 8;
int xpos = LEFT_OFFSET;
int ypos = TOP_OFFSET + y;
int w = image.getWidth();
int h = image.getHeight();
g.drawBitmap(xpos, ypos, w, h, image, 4, 6);
xpos = w + 20;
g.setFont(myFont);
g.setColor(Color.BLACK);
g.drawText(title, xpos, ypos);
}
i hope i got your question right and would suggest you drawing a rectangle around the image like that:
g.setColor(Color.RED);
g.drawRect(xpos - 1, ypos - 1, w + 1, h + 1);
This would draw the rectangle around your image without overlapping it. For more details on why you need these adjustments of the position and the size of the rectangle you can check on the documentation of Graphics class here http://www.it.uc3m.es/florina/docencia/j2me/midp/docs/api/javax/microedition/lcdui/Graphics.html
This is what I have for detecting collision.
public static bool IntersectPixels(Rectangle rectangleA, Color[] dataA, Rectangle rectangleB, Color[] dataB)
{
int top = Math.Max(rectangleA.Top, rectangleB.Top);
int bottom = Math.Min(rectangleA.Bottom, rectangleB.Bottom);
int left = Math.Max(rectangleA.Left, rectangleB.Left);
int right = Math.Min(rectangleA.Right, rectangleB.Right);
for (int y = top; y < bottom; y++)
{
for (int x = left; x < right; x++)
{
Color colorA = dataA[(x - rectangleA.Left) + (y - rectangleA.Top) * rectangleA.Width];
Color colorB = dataB[(x - rectangleB.Left) + (y - rectangleB.Top) * rectangleB.Width];
if (colorA.A != 0 && colorB.A != 0)
{
return true;
}
}
}
return false;
}:
It work fine until I want to animate stuff. So I have a texture sprite that have about 12 frame. what I need to do is get the color data array of each frame. This is how I get the color data array:
Color[] playerColorArray = new Color[playerColorArray.X * playerColorArray.Y];
PlayerTexture.GetData(playerColorArray);
CData = playerColorArray;
Now my guess is that i have to update the textureData everytime the frame changes
Is there a way to get the the color data from each frame only?
You can get an array of the complete sprite sheet texture and only use the current frame.
Let's say you have a sprite sheet and stride is the offset of a pixel to the pixel below it. This can be the sprite sheet's width. Furthermore, you have the position x0, y0 of the first pixel of the current frame. Then you just have to modify the index calculation:
int posXInFrame = (x - rectangleA.Left);
int posYInFrame = (y - rectangleA.Top);
Color colorA = dataA[(posXInFrame + x0) + (posYInFrame + y0) * stride];
Probably, you have calculated x0 and y0 somewhere else and can pass those values to the function.